I have two kinds of parameters in a specific Crystal Report I am making -- two dates that I use directly in the SQL query, and a parameter that will filter the report based on sales reps within the query.
I defined the two dates (date1 and date2, if you will) when I created the command, and those work fine. However, when adding the dynamic parameter to choose which values I want for the 'sales rep' field, only a text box appears, meaning the parameter list hasn't been generated dynamically like advertised.
I know the reason for this -- the query hasn't run yet, so there aren't any dynamic values to pull. The date range is a necessary evil as well, since the report takes five minutes to run if a date range isn't set due to so many older records (which need to stick around do to history purposes).
Is it possible to generate this list dynamically at all, or am I stuck having to update a list with static values?
Thanks.
To get the dynamic parameter to work, you'll have to add whatever table to the report that contains the 'sales rep' field. You can pull the table in next to the SQL Command that you're creating, and just link them however you want with an outer join so as not to limit your records (You could even not link them at all, but Crystal will complain about having "Multiple starting points" or whatever.
Now you can pull the sales reps into the dynamic parameter and use it in either the SQL Command itself as a parameter, or you can just use it in the record selection formula to filter results from the SQL Command. In both cases, CR will query the database twice; the first time to simply get the entire list of reps and the second time to run the SQL Command.
The main takeaway here is that the table, not a command, needs to be in the report in order to be a candidate to populate dynamic parameters... even if you won't use that table again in the report. Hopefully that helps, even if it is 7 months late.
Finally figured this out:
Using SQL create the stored procedure that gathers your report data. This stored procedure CAN NOT have parameters. It must generate all your report data upon execution
Example 1: Exec MyReportStoredProcedure
Create another stored procedure to gather your parameter list values. Again no parameters used in the stored procedure.
Example 2: Exec MyCrystalParameterList
In Crystal Reports under Database -> Database Expert add both stored procedures (Called tables) to the "Selected Tables" section. Click "OK". Crystal will then try to make links between the two tables. Click "Remove All Links". Click "OK" on all link warnings that follow.
Now build your report using the columns from MyReportStoredProcedure
Run you report. You will NOT get prompts to enter parameters. All possible data will be displayed in the report.
* Now time to link the parameter to the data. *
Crystal reports will execute both stored procedures as soon as you open the report.
Crystal reports does not pull data based on the parameter like reporting services (SSRS).
Crystal filters the data based on the parameter value you selected after all data is gathered.
Running MyReportStoredProcedure returns the following:
1 Stop XX 7A [columns5] [columns6] [columns7] [columns8]
1 Gone CC 88 [columns5] [columns6] [columns7] [columns8]
1 Gone CC 88 [columns5] [columns6] [columns7] [columns8]
2 Nice XX C3 [columns5] [columns6] [columns7] [columns8]
3 Loop EE C3 [columns5] [columns6] [columns7] [columns8]
3 Loop DD C3 [columns5] [columns6] [columns7] [columns8]
3 Loop DD C3 [columns5] [columns6] [columns7] [columns8]
...
... 700,000,000 Additional records
...
Running MyCrystalParameterList returns the following:
1 Stop XX 7A
1 Gone CC 88
2 Nice XX C3
3 Loop EE C3
3 Loop DD C3
>> A distinct list of values only 5 rows <<
* Link the parameter data column to the corresponding report column *
Now link the parameter Column1 to the report column1. This link ties the main report values (MyReportStoredProcedure) to the parameter values (MyCrystalParameterList).
In Crystal Reports under Database -> Database Expert Click the tab called Links.
In this section you link the tables/columns together. You could have done this in the steps above but for better understanding I want you to do it here after showing the data returned for both stored procedures (tables).
* Create your cascading parameter *
In Crystal Reports find the Field Explorer panel. Usually its on the right side of the screen.
Now Right click [Parameter Fields] and select [New]
Name the parameter
leave the type as [String]
set "List of Values" to [Dynamic]
set "Choose a Data Source" radial button to [New]
In the table below the radial button, click in the first row under the word "Value"
A drop down showing both tables will be displayed ([MyReportStoredProcedure and MyCrystalParameterList])
Select the columns for your first parameter from your MyCrystalParameterList stored procedure (table).
Your column is now listed in the first row.
Now click the next row and select your next column from your parameter stored procedure (table).
repeat until all of your desired parameters are displayed in the table rows.
On the right side of this table you will see a column called "Parameters" there is text in this column for each row.
Click each field in the "Parameters" column and a parameter is created in Crystal report that corresponds to your parameter stored procedure (table) column.
Click "Okay" to close the "Create New Parameter" dialog box.
If you run your report, you will be prompted to select values for your parameters and the parameters will list available values.
ALL OF THE DATA WILL BE RETURNED IN THE REPORT!!! We are not done.
* Last step (Finally!) *
Tell Crystal reports to filter the report data based on the parameter value.
In crystal reports, click on Report -> Select Expert -> Record
A "Chose field" dialog box will display
Fields panel Look for the report stored procedure and expand it so the columns are showing
Select one of the columns that linked to the parameter stored procedure (table).
You will now see a formula dialog box with a default value of "is any value".
change this value to "is equal to"
A drop down box will appear to the right.
The drop down box will show your parameters!!!!!!
Select the parameter that corresponds to the report field you select.
repeat for all of your parameters.
Now run your report. The data is now filer by your parameter value!!
You are done!!!! Thank GOD!
Note:
You can make a single stored procedure for each parameter. Just add them to the report using Database Expert.
In my example I made one stored procedure that pulls all possible parameter combinations.
DO NOT ADJUST YOUR REGISTREY SETTING AND MAKE CRYSTAL REPORTS READ MORE THAN 1000 RECORDS!!!
Your report stored procedure can return 1 Billion records but your list of parameters should not be more than 1000 unique values.
You cannot build your parameter list from the report stored procedure because crystal reports will only look at the first 1000 records.
Your parameter list must be a separate stored procedure that pull distinct values.
* You have the foundation, Now build the rest. Good luck. *
Related
Need some help on crystal reports:
We are currently using crystal reports at work to generate confirmation papers to internal counterparties.
These confirmations are automatically triggered by our system when we set the interest rate on a specific deal.
The parameters that are sent from our external system are "deal number" and "action number". This information is passed on from the "events" database table, containing following columns:
The confirmation generated by performing the rate set contains specific information regarding interest payments we expect from counterparties.
So this confirmation generated has unique parameters, being the rateset "action number" and "deal number" from events table (see attached).
Now in this confirmation, we also want to make a reference to the "Next RateSet" date.
We tried to solve this by inserting an SQL statement to:
select top (1) effective date from events table where the
comments=rate set and where the action no = 0
This logic however does not hold up when we have to generate backdated confirmations.
So in theory, I would like to perform a select statement where I select the first record where the "event no" is larger than the "event no" from the current generated confirmation.
I'm not sure how to perform this though, as I've read it's not possible to use a crystal parameter in the SQL selection.
Any suggestions?
One option is to add the table a 2nd time to the report.
Crystal would assign an Alias to the 2nd instance by adding a number to the table name.
To make things more intuitive, change that alias to something like 'NextRateSet'.
Join the Events table to its alias on:
Events.Dealno = NextRateSet.Dealno AND
Events.EffectiveDate < NextRateSet.EffectiveDate
Add record selection criteria of:
NextRateSet.ActionNo = 0
Group the report on Events.DealNo and Sort it Descending by NextRateSet.EffectiveDate.
Suppress the detail section and move everything to the Group Footer.
Since the Group footer shows the last record in the group, it would show the earliest NextRateSet.EffectiveDate. And since that alias is restricted to EffectiveDates following the Events.EffectiveDate, you get the correct date.
I am trying to convert an old Microsoft Access report into Crystal reports. I have everything working perfectly except for this last small detail. The Access report uses a DSUM function within an if statement for one of the fields on the report.
After much searching, I've determined that CR doesn't have anything similar.
Here's basically what I'm dealing with.
I have a proposal report. In the details of the report I print the qty, description, and a couple of price fields.
The data looks like something this:
Proposalnum Partitem RolltoItem Unitprice
18611.............1.......... NULL........0.00
18611.............2......... NULL.......17225.92
18611............3............ 2............156.90
18611............4............. 2............482.05
What I need to do is when I print a specific part, I need to query through the rest of the records to find the parts that have a matching number in the rolltoitem field and add the unitprice to the part I'm printing.
So in this example when I print partitem #2, I need to add the 156.90 and the 482.05 from parts 3 and 4 to the 17225.92 so I print a total of 17864.87.
Is there any way to do this?
As far as i know, there is no such function.
But I would try this.
The general idea is: group the data by ProposalNum and use a subreport to select the "children rows" and sum the "children prices".
Details:
Create an empty group section by PartItem.
If you want to show only items where RoolToItem is null, use a suppress function for this case.
In the details section, put a subreport. The data source of the subreport would be the same of the main report.
Change subreport links to select data in subreport based on fields: PartItem in the main report = RolltoItem in the subreport.
Pass other fields to the subreport without select data: ProposalNum, PartItem, UnitPrice. I think you need to create parameters in the subreports before doing that - example: ParentProposalNum, ParentPartItem, ParentUnitPrice.
Create a new formula: ParentUnitPrice + Sum ({YourDataSource.UnitPrice})
Put the formula in the subreport footer a long with the other fields. Maybe: ParentProposalNum, ParentPartItem, formula.
It is a theoretical solution. I hope it points out to the right direction.
If you are trying to sum the Unitprice column for all items that have the same value in Rolltoitem, you could do this with a SQL Expression Field. The code would look something like this. My Where clause may need tweaked though since I'm not sure what your database structure looks like.
(
Select Sum("YourDataBaseTableName"."Unitprice")
From YourDataBaseTableName
Where "YourDataBaseTableName"."Rolltoitem" = *currentRolltoitemValue*
)
Syntax can also vary for SQL Expression Fields based upon what type of database you are using. The syntax I provided is fairly general, but should work on SQL Server.
EDIT: Adding example with explanation of how it works.
Here is one of my SQL Expression Fields from a crystal report that prints a Bill of Lading for shipped goods.
(
Select Sum("SHIPMENTS"."PALLET_COUNT")
From SHIPMENTS
Where "SHIPMENTS"."BOL_ID" = "BOL"."ID"
)
In my database the BOL table is the starting point. A single BOL can contain 1 or more SHIPMENTS, and a single SHIPMENTS can contain one or more PRODUCTS.
Top level grouping is on BOL.ID. The PALLET_COUNT is found once and only once on each SHIPMENTS. I also had a sorting requirement for the data in the details section that prevented me from using a Running Total Field.
This allows a BOL with 2 SHIPMENTS that contains a total of 3 products to look like this:
BOL.ID SHIPMENTS.ID SHIPMENTS.BOL_ID PALLET_COUNT PRODUCT.ID
1 10 1 2 XXX
1 9 1 1 YYY
1 10 1 2 ZZZ
The correct PALLET_COUNT for this BOL should be 3, since PRODUCTS XXX and ZZZ are in the same SHIPMENTS and the PALLET_COUNT is duplicated because of its relationship to the PRODUCTS.
Not sure what's going on here. I'm creating a report using two tables. I do an inner join on both tables to obtain the rows I need. I'm sure the proper rows exist because I have taken the DB query that Crystal Reports generates for you and ran it on sql developer and it returns the appropriate rows. Not sure why my report would return empty if it's grabbing the proper rows and the DB has been verified using Crystal Report's "Verify Database" tool.
Check and Double check each section of your report, you might have left some Suppression formula. Secondly check and double check Record Selection filters in the report.
Sometimes what we don't see the first time, miraculously appears the second time.
I need to design a crystal report with 3 columns. Column 1 is a text box in the report, and column 2 and column 3 are datafields from a particular table.
Is it possible for me to use column1 as a parameter that would help me to fetch the other columns from the database??
col1 col2 col3
TextBox value1 value2
so when a user changes the value in TextBox, col2 and col3 value should reflect based on textbox value.
Or is there any other way in which i can achieve this??
There is no way to interact with a report the way you want via text boxes after the report has run. Since you can't select records on the fly, you'll have to create a report parameter of the same type as your primary keys (column A) and then set it to "Allow multiple values". You'll be able to select only the records you're looking for at run time by adding {table.colA} in {?Parameter1} into your Record Selection formula.
Drop {table.colA} and {table.ColB} into the Details section of the report. Now when you run it you can just add your 15 items as the parameter and you'll get what you're looking for.
Alternatively, if its important for the user to interact with the report after it's presented, you could accomplish this using (1) sections/grouping and Crystal's Hide option or (2) an on-demand subreport.
For example, you could group by column1, and then print a detail section for all the values. Mark the detail section Hide. Then, when you click on the value, that section will expand.
Or instead of marking it Hide, mark the group footer (for column1) New Page After Section. Then you can use the document tree along the left side to navigate to the page containing the values you're interested in seeing.
Say I have this column returned in a command for Crystal:
deposit_no
123
130
125
124
126
127
128
129
and I need to have this in the report title:
Includes deposits between 123 - 130
I've tried a running formula for minimum and maximum and they aren't returning the correct values no matter how I manipulate them. I've tried evaluate for every record, on change of the deposit_no field, etc. I have no grouping on this report.
Edited to add:
While I preferred to handle this on the CR side of things, I changed my command to include what mson wrote below. So technically, mson had the correct answer.
create a stored procedure or view that has the information you want. access the stored procedure or view through crystal reports.
crystal reports is a hindrance to properly coding anything.
the unexpected result you are getting may be because the column is not numeric. often, number values are stored as varchar/nvarchar. this is done especially for fields like zipcode/phone number/etc. where the value may be numeric, but you would never do math on them.
in any event, here are the snippets you can use to build in sql server (and then call from crystal)
select min(coalesce(cast(deposit_no as int),0)) as min_deposit from tableA
select max(coalesce(cast(deposit_no as int),0)) as max_deposit from tableA
Came across this while searching for the same thing, and would like to add to SqlACID's answer which does work.
You can do this in your formula editor.
'XX'+totext(Minimum ({YY.Num}), 0, '') + '-XX'+totext(Maximum ({YY.Num}), 0, '')
Create a formula field using summary functions for minimum and maximum of the deposit_no field, then drag the formula field to the page header