We have a growing number of non-data-driven SSRS 2008 subscriptions and the default list in SSRS does not provide any way to indicate what each subscription is all about. Yes, there is a description but it is auto-generated and not very helpful. We need it to say "Company ABC Quarterly to Managers", for instance.
I looked at using the ReportingService2010 web service and managed to not only read each report's description but modify it. However, as soon as someone edits the subscription from SSRS, which will be required sometimes, the description reverts to the auto-generated one.
Although I have never worked with data-driven reports, I wonder whether these will provide the functionality that I need. It just seems like a lot of work to set up, given that I don't really need the subscriptions to be data-driven.
Am I missing something simple here? Is this simple functionality something that comes with upgrading to a newer SSRS version?
Thanks!
Am I missing something simple here? Is this simple functionality
something that comes with upgrading to a newer SSRS version?
It does not appear that standard subscriptions in SSRS 2012 allow descriptions to be entered either (I couldn't find a screenshot of the UI though).
Although I have never worked with data-driven reports, I wonder
whether these will provide the functionality that I need. It just
seems like a lot of work to set up, given that I don't really need the
subscriptions to be data-driven.
I would argue against the need for data-driven subscriptions if standard subscriptions are fulfilling the business need. Would this be worth your time and effort? If it is, the obvious advantage is that subscription descriptions are editable in the UI, and do not appear to be overwritten when modifying the subscription.
If you're still interested in using standard subscriptions...
One way to "hack" SSRS such that the subscriptions will not overwrite the description (which isn't editable in the UI anyway) would be to modify the stored procedure ReportServer.dbo.UpdateSubscription.
DISCLAIMER: Use the following advice at your own risk. This involves modifying a standard sproc that Reporting Services relies on.
You can alter the update statement such that the description value would only be modified if the subscription is not a data-driven subscription (we do not want to break data-driven subscription descriptions, which are editable in the UI). In the stored procedure, you can distinguish data-driven subscriptions from standard subscriptions by looking at the value of #DataSettings. If it IS NULL, then it is a plain old subscription. If it IS NOT NULL, then we're looking at a data-driven subscription.
The following line in the Update statement:
[Description] = #Description,
Can be changed to:
[Description] = CASE WHEN #DataSettings IS NULL THEN [Description]
ELSE #Description
END,
This would keep all standard subscription descriptions the same when they are modified in SSRS, but allow data-driven subscription descriptions to be modified.
Per Mat's Mug, I am noting the solution that I eventually used:
Since all of our subscriptions involve emailing the report, we could get away with re-purposing the email subject field as the description. This way it was possible to produce a listing of all subscriptions and show an arbitrary description for each one.
Here's an expansion on the hack from dev_etter. I was able to use the Stored Procedure #parameter input along with a new Report Parameter (pReportParameterName) to create a dynamic, user controllable description that's unique to the report.
Add a new hidden text parameter to the report (pReportParameterName)
Add the Code Block 1 below in Stored Procedure UpdateSubscription above the UPDATE statement.
Change the 'Description = ' line of the UPDATE statement to something like Code Block 2 below.
With that set up, create or edit a Timed Subscription and enter the desired text into the Description parameter. After saving you should see the entered description in the Description column of the Subscriptions screen.
/*** Code Block 1 ***/
DECLARE #Param as XML = CAST(#Parameters as XML)
DECLARE #MY_Description as varchar(512)
SELECT #MY_Description = e.f.value('(.)[1]', 'varchar (100)')
FROM (select 1 id, #Param xCol) tx
CROSS APPLY tx.xCol.nodes('./ParameterValues/ParameterValue') AS a(b)
CROSS APPLY a.b.nodes('./Name') AS c(d)
CROSS APPLY a.b.nodes('./Value') AS e(f)
WHERE c.d.value('(.)[1]', 'varchar (100)') LIKE 'pReportParameterName'
/*** Code Block 2 ***/
[Description] = --#Description
CASE
WHEN #DataSettings IS NULL
AND #MY_Description IS NOT NULL
THEN #MY_Description
ELSE #Description
END,
Cheers,
Sj
Related
I have a pbix file that takes an Azure Storage account as a parameter and reads data from there accordingly. The next step is to be able to embed this powerbi dashboard on a webpage and let the end user specify the storage account. I see a lot of questions and answers surrounding passing in filter query parameters--this is different, we're trying to read from a completely different data source and not filtering on a static data source.
Another way to ask this question is: is there a way to embed powerbi template files, if not, is there a feature request somewhere we can upvote?
The short answer is no.
There is a reason to use filters in this case instead of parameters. Parameters are something that is part of the report itself. Each users that looks at your reports will get the same parameter values as the others. If one of them changes some parameter, this will affect all other users. Filters on the other hand, is something local for your session. You can filter the report the way you like, and this will not affect other users experience in any way.
You can't embed templates, because template is simply a state of the report on the disk. When you open it, it's not a template anymore, but becomes a report.
You can either combine the data from all of your data sources in a single report, adding one more column to indicate from where this data comes from, and then filter on this new column. Or create/modify ETL process (for example dataflows can be used for this) to combine these data sources into a single one.
We have some tables in our database that all have the same attributes but the table is named differently for each. I'm not sure of the Architect's original intent in creating them in this way, but this is what I have to work with.
My question for all the expert Oracle APEX developers: is there away to create a reusable page that I can pass the table name to and that table name would be used in the reporting region and DML processing of that page?
I've read up on templates and plugins and don't see a path forward with those options. Of course, I'm new to webdevelopment, so forgive my ignorance.
We are using version 18.2.
Thanks,
Brian
For reporting purposes, you could use a source which is a function that returns a query (i.e. a SELECT statement). Doing so, you'd dynamically decide which table to select from.
However, DML isn't that simple. Instead of default row processing, you should write your own process(es) so that you'd insert/update/delete rows in the right table. I've never done that, but I'd say that it is possible. Basically, you'd keep all logic in the database (for example, a package) and call those procedures from your Apex application.
You could have multiple regions on one page; one region per table. Then use dynamic actions to show/hide the regions and run the select query based on a table name selected by the user.
Select table name from a dropdown or list
Show the region that matches the table name (dynamic action)
Hide the any other regions that are visible (dynamic action)
Refresh the selected region so the data loads (dynamic action)
If that idea works let me know and I can provide a bit more guidance.
I never tried it with reports, but would it work to put all three reports in a single page, and set them via an Item to have Server-Side Conditions that decide what gets shown in the page? You'd likely need separate items with a determined value for the page to recognize and display.
I know I did that to set buttons such as Delete, Save and Create dynamically, rather than creating two or more separate pages for handling editing of certain information. In this case it regarded which buttons to shown based on a reports' primary key being sent to said "Edit" page. If the value was empty, it meant you wanted to create a new record (also because the create button/link sent no PK). If said PK was sent (via a edit button/link), then you'd have the page recognize it and hide the create button and rather show the edit button.
I'm currently building a staffing CRM in Oracle Apex for my company and we have a lead generation form that allows recruiters to add any sales leads.
Once a recruiter adds a lead the page sends an email to the assigned sales person.
Now here's my issue, I need to get APEX.MAIL to ignore any null email address fields on the form page since management wants to be able to assign up to 3 sales people to receive that lead, though they may only assign 1 or 2.
How can I make APEX.MAIL ignore the page item for the sales email if the field is null.
Right now the "To" line is p_to=> :P3_SALESMAN
How I want it to look is p_to=> :P3_SALESMAN, :P3_SALESMAN2, :P3_SALESMAN,3,
But if :P3_SALESMAN2 or :P3_SALESMAN3 are null, I want APEX.MAIL to ignore them.
Or would that even cause a problem is the field is null?
You don't indicate how you are calling APEX.MAIL...
Since APEX.MAIL is a PLSQL pkg, one suggestion is to write a wrapper PLSQL pkg that will look at the parameters you pass in (P3_SALESMAN1.2,3...) and use If Else logic to evaluate the fields as null or not and then determine whether to call the APEX.MAIL pkg.
Writing in-line PLSQL in APEX quickly becomes a maintenance and reusability headache, so you should think about always using a PLSQL stored Proc/Func to encapsulate your logic and call it from the page.
Like Joe mentioned, using stored procedure is better than writing in-line pl/sql, which I learnt the hard way.
About building the list of email addresses, I can't think of another way, but to use if-else condition, and adding email addresses to a string, if they exist and passing the final string to p_to in APEX_MAIL.
I have a tabular form which is updated throughout the year and i wanted to prevent users from editing certain rows. Currently the 'row type' is hard coded however I want the application admin to control which 'row types' are readable / write at certain times. My answered question, click here.
Currently a dynamic action is fired which prevents the rows that contain the type 'manager figure' and 'sales_target' being edited.
I have created a table with the three row types against each customer. Each status is set by a number: 0 to 3 (These i will decode into something meaningful for users).
0 - Row with that row type is read only.
1 - Users can enter into the row with that row type.
2 - row is read only with that row type.
3 - row is complete and set to read only.
I have created a new form (new tab) for the admin user to maintain each status.
Currently for Customer 'Big Toy Store' rows should be set as follows:
Manager Figure row should be read only (since set to 2)
Sales should be readable (since set to 0)
Sales target should be writable (since set to 1)
Please can i be pointed in the right direction, ive looked into jquery but struggling to work out how to pass the output of an sql query to it, so it can be used to determine which rows should be read only.
Link:apex.oracle.com
workspace: apps2
user: developer.user
password: DynamicAction
application name: Application 71656 Read only Rows for Tabular Form
I'm not sure that a tabular form is a good format to work out this idea. As you can see, you require quite a bit of javascript to produce the results you want. Not only that, but this is all client side too, and thus there are some security risks to take into account. After all, I could just run some Firebug and disable or revert all things you did, and even change the numbers. Especially with sales figures, which is something you most definitely do want altered by everybody and is also the nature of your question, security is important.
There are more elegant ways here for you to control this, and not in the least to reduce the amount of highly customized javascript code. For example, you could do away with the tabular form, and instead implement a modal popup from an interactive report. Since the modal popup would be an iframe and thus a different page, you can create a form page. On a form page you have a lot more control over what happens to certain elements. You can specify conditions, read-only conditions, or use authorization schemes. All things you can not evidently use in a tabular form.
I'd think you'd do yourself a service by thinking this over again, and explore a different option. How much of a dealbreaker is using a tabular form actually?
You need the user. You need to know what group he belongs to, and then this has to be checked against the different statusses and rows have to be en/disabled. Do you really want this to happen on the client side?
I'm not saying it can't be done in a tabular form and javascript. It can, I'm just really doubting this is the correct approach!
I am having a problem in QTP with selection of a web list box and I have exhausted what I know to do to resolve it. I am hoping someone can help.
There are 5 controls in a container, 2 webedit controls and 3 weblist controls. Together, they allow entry of accounts associated with a customer, and there can be 16 accounts for any customer. There are only ever five controls active at any time, whether editing or entering information for an account. When the information for an account is entered and accepted, it changes to a read-only table row and a new set of controls appears below it for entry of the next account.
The information entered in these controls is the account number, type, description, designation, and status. The status value is contingent on the designation, and the items in the list change dynamically depending on what the user specifies for the designation. The status list is not enabled until the designation is specified.
After some experimenting with timing, I was able to get past an issue where the status list for the first account was seen by QTP as disabled even though it was clearly enabled. I was then able to advance to entry of the second account.
I change the designation on the second account and try to select an appropriate item (specified in a data table) in the status list. My specification from the data table is never found. I figured it was a problem with verbiage differences and also that I should probably anticipate that and address it now, so I wrote a function to accept three parameters, the list and up to two search items. My function searches the listbox passed to it and looks for a match (full or partial) on the search items it receives. Here is where I encountered a significant problem.
The list of the control my function received was from the previous iteration of the test, corresponding to the designation of that account. This is why my function was not finding the selection item. The list on the screen shows the appropriate items, which suggests that I am looking at the wrong object. I also get the ‘object is disabled’ message when I put my data table value directly into the list with the select statement.
The active controls are displayed below the readonly presentation of the previously entered accounts. I am very new to QTP, but I also read documentation. My only theory at this point is that ATP is not passing the right list to my function… that perhaps that how it was learned included the position, which will change each time. However, the spy identifies the screen control as the same item I processed for the preceding account, which makes my theory suspect. In addition, the other four controls, which are not dynamically changing, do not present the same problem. I can put the information in them consistently.
I apologize for the length of this question, but I wanted to be as thorough and clear as possible. Can anyone help me get past this obstacle.
There are many possiblities why it is exposing this behaviour, so let's start with something simple:
Did you try a myWebList.Refresh call before you do something with the listbox? Refresh re-identifies the object.
Have you put a break point (red dot) inside the custom function. Just see what is happening there. With the debug viewer you can enter a realtime command in the scope of that function like msgbox myWebList.exist(0) or myWebList.Highlight
Can you see how the disabled property is propagated to the webpage? If you can 'Object Spy' it as TO property, you can add it in the GUI Map description.
A more sophisticated aproach is to create a Description with the weblist properties. If you can read the disabled property as an RO property from the 'Object Spy', you can use it as an identifier like "attribute/customDisabledProperty:=false".
If you cannot correctly read the disabled property, you can create a description object and do a count on the amount of items that match that description on that page with numberOfLists = Browser("my browser").Page("my page").ChildObjects(myDescription).Count and get the last list with Set lastList = Browser("my browser").Page("my page").ChildObjects(myDescription)(numberOfLists-1)
Keep us informed. Depending on how this works out, we can work into a direction for a solution.
I figured this out early this morning. There are 4 different list boxes used, each made visible or enabled dependent on the selection of the previous list. This is why the spy found the one listed when I was using it and also why the items in the list were not appropriate to what I had selected and also why it appeared disabled to QTP but enabled to me.
I was selecting the same designation when trying to spy it. It was intuitive that the controls were all the same. I am also a windows programmer and I would have populated the same list each time with the appropriate list items, and I presumed that was what the web developer was doing. It was not and it took some time to figure that out. Now that I figured it out, everything is working fine, and I came back to report that. This was a significant, time-intensive lesson.
Thank you very much for your input. It is still useful because I am very new to QTP and every thing I learn is of value.