I have a dataset and I need to loop through the records and print a crystal reports label based on how many pallets I'll have.
So in this instance I need the first record set to print 9 times the second to print 5 times, the next to print 4 then 12 for the last.
Option 1: At least one of the 3rd-party desktop Crystal reports schedulers (ses list [here][1]) provides an option to print copies governed by a Crystal formula.
Option 2: if you can create a "REPEATER" table with a single column (How_Many) containing a row for each value: 1, 2, 3, 4, 5, 6...
In your report, add the REPEATER table and add a join condition of
Pallets_Quantity >= Repeater.How_Many
If the ">=" join option is not available, remove the join to the REPEATER table and create this condition in the Record Selection formula:
{Pallets_Quantity} >= {Repeater.How_Many}
This would cause each order to be duplicated as many times as the value of {Order.quantity}.
Option 3: if the quantity is fairly small, you could create cloned sections as Detail b, Detail c, etc. and control which ones are suppressed based on the quantity.
[1]: https://%20at:%20https://kenhamady.com/productlinks/default.html#desktopsched)
Related
I am trying to set up a Crystal Report to generate pallet labels which include a "Pallet N of M" line on each page.
The order in the database only has one entry, which contains all of the other information for the label(s). My issue is that the number of pallets isn't known until print time, and each label needs the same order information as well as a pallet ID. What I am looking for is for the user to enter a parameter for the total number of pallets, then have Crystal generate the correct number of unique labels.
For example, if the order has 4 pallets then Crystal should generate 4 copies of the label, the only difference on each copy being the last line which should read 'Pallet 1 of 4', 'Pallet 2 of 4', 'Pallet 3 of 4', and 'Pallet 4 of 4' respectively.
The only solution I can think of would be to create a number of sections equal to the maximum number of pallets, all containing my real data as a sub-report, then suppress any which are greater than the entered parameter. I am trying to avoid this because we may have greater than 50 pallets on a given order, so that would be tedious to create and is just not a very clean solution.
-= EDIT =-
Big thanks to Aliqux for the solution. In the end I needed to change the syntax to be Oracle compatible and also include the LINKVALUE field in the report, but the answer was 99% there especially considering I had not mentioned that my datasource was Oracle. The Command syntax I ended up using (with my parameter called TotalPallets) was:
SELECT
-1 AS "LINKVALUE"
FROM table
WHERE rownum <= {?TotalPallets}
You will need to Add a command to your tables.
1) Under database Expert in the Database you used select Add Command.
2) Click create to Create a Parameter.
3) Create the requested values, you can leave the Default Value blank if you want, and change the Value Type to Number. (I will be calling my parameter Counter)
4) Put the following in the SQL query where table is the main table you are using
SELECT TOP {?Counter}
-1 AS LINKVALUE
FROM table
5) Click okay and enter a value if prompted
6) In links link a number field, that will never go into negative numbers as we are using -1 for a base, to the LINKVALUE in the Command Table.
7)Link Options are as followed
Join Type: Inner Join, Enforce Join: Not Enforced, Link Type: !=
8) In your report create a formula with a shared numbervalue the starts from one.
shared numbervar counters;
if counters = {?Counter} then counters := 0;
counters := counters + 1
9) You can use that formula and the Counter Parameter for your labels
totext({#Counts},0,"")+" of "+totext({?Counter},0,"")
Credit reference: https://blogs.sap.com/2014/01/24/duplicating-data-details-records-n-times-eg-repeating-labels-n-times/
I've got data as picture below, i'm using crystal report to display statistic report from that data.
i want to count MRN which got 2 until 5 rows of episode number only.
currently im doing
1) group MRN in crystal report and count(episode number).
2) create 1 formula like :
if count(episode number) >=2 and count(episode number)<=5 then count(episode number)"
3) put the formula to report and try to insert summary to count that formula, but no selection summary appear for that formula.
Can you give me an idea how to count MRN with 2 until 5 episode only? refer to picture for clear explanation
In Crystal you can use two condition types to sort which records are being showed:
Record selection formula
Group selection formula
Both are located in the menu Report > Selection formulas
In your case you can define a group on field MRN and create a Count field inside that group. To show only groups where the count is between 2 and 5, use the Selection Formula > Group condition in the Report menu.
Count ({EpisodeNo},{MRN}) <=5 and Count ({EpisodeNo},{MRN})>=2
I have a report that is only one record, however, the user specifies how many times it needs printed, let's say 10. Each time it prints it prints 4 of the same report. Like this, Page 1 x 4, Page 2 x 4, Page 3 x 4, etc. With 10 copes their will be 40 pages altogether.
Update:
I was able to get all the pages I needed based on the values the user inputs. So if there are 10 pallets I have 40 pages of labels, which is correct. Now the control number part that needs to be displayed. It is kind of like a page number but every 4 pages the number needs to increment by 1. I assume I can use WhilePrinterRecords and some how increment, but I am still new to Crystal and unfamiliar with it.
Example:
Page 1: Control number 1
Page 2: Control number 1
Page 3: Control number 1
Page 4: Control number 1
Page 5: Control number 2
Page 6: Control number 2
Page 7: Control number 2
Page 8: Control number 2
This would continue until there is no more pages to print.
if you want 4 copies for each label, what you could do is create 4 sections on the report with the same info. Make sure that you assign the label size to each page(e.g. 4x6). e.g. if you have that info on your header, create PHa, PHb, PHc and PHd, same for details or PF.
don't know if this could work for you, but at least is a recommendation. You can create suppressed sections with the same info(e.g. 10 sections) and create a parameter that control that suppress condition defaulted in 4. If the user what to print 5, it will enable section 5th, same if want to print 3 it will suppress the 4th.
Upadte: how to get the increment:
place a formula on your page footer like below one. It will return value when gets an integer and suppress it when is equal to 0(right click on it, number tab, customize, suppress if 0).
if pagenumber = Ceiling(pageNumber,4) then numbervar page := page +1
then place another formula on your PF as well like below one and suppress it when pagenumber = Ceiling(pageNumber,4) so it won't show when the other has value and put one overlapping the other to get the value in the same place.
if {1st formula} <> 0 then numbervar page1 := {1st formula};
page1 + 1
2nd Update:
Because is a label and your details are acting as a new page do this:
create a new detail section, so you will have details a and b and place your formulas on details b
I have used additional tables for such tricks; these tables must be linked to report to multiply main query results. Some care has to be taken to not allow multiple users printouts to mix.
Example, assuming your report query has some unique id to link and your user/session has also some unique id:
you create table cr_special(reportid int, userid int, ctlnumber int)
you design report, linked to this table by reportid and filtered by userid; changing ctlnumber field is taken from your special table
before printing, you delete all records with reportid/userid combo and insert new ones
you print report, giving userid as parameter
Say you want to print 10 reports with increasing numbers - then you insert 10 records into your special table with ctlnumber increasing from 1 to 10.
Variation of this solution is to use some other non-related table, like our all-dates-containing dates table :)
Both of these solutions are ugly, but they usually work.
Another approach is to use some stored procedure to return these sequential numbers as records and link your report to such procedure; Crystal Reports and stored procedures do not behave always well however.
I'm using Crystal Reports XI (R2) and have a cross-tab which displays information about flights. There is the 'Total' column' as well as the Arrivals and Departures columns which are created automatically thanks to the grouping condition. What I'm trying to do is to have the 'flight directions' parameter, where the user can select 'All, departures only or arrivals only' values and according to this selection the cross-tab would have one or two columns. How can this be achieved? I tried using the following formula(and have the suppress empty columns option enabled) :
if {?Pm-#flight_direction_description} = "Departures Only"
then
if ({Command_1.IsArrival} = 1)
then 0
else {Command_1.IsArrival}
which indeed works (only one column is displayed) but then under the Departures column it lists all the flights (so the departures column is the same as the Total column) whereas it should only display information about departing flights.
I've had similar situations come up; while certainly not ideal, and if no one has any better suggestions, you could create Detail A, Detail B and Detail C sections, all of them suppressed. From there...
You could put your "All" crosstab in Detail A
Create a second crosstab for Destinations only, and put that in Detail B
Create a third crosstab for Arrivals only, and put that in Detail C
Then, in your Detail A, B and C sections, you can condtionally unsuppress the section you want based on the parameter passed in.
I want to create multiple groups in ireport, and the data should display in a group-wise manner.For Eg:
First the Group1 data should be printed completely, then,
Group1:
Module Data
After this i want to print the Group2 data completely
Group2:
Category data
I am using the Result Set datasource.
Can Someone help me in this?
Jasper reports will work exactly in this manner as long as your query results are ordered properly.
For example, let's say you are grouping by a field called "MY_GROUP" and it has values "GROUP A" and "GROUP B". In your report you will create a group for field "MY_GROUP". In your query, make sure you have MY_GROUP as the first field in your ORDER BY clause. You can also accomplish this in iReports by adding the "MY_GROUP" field as your the first field in the Sort Options section of the Report query.
Now that you have added your group and are ordering properly your results will come out like this:
Header - GROUP A
Detail - GROUP A
Footer - GROUP A
Header - GROUP B
Detail - GROUP B
Footer - GROUP B
Exactly as you wish. My guess is that you were not properly ordering your query results. This could result in having multiple groupings for GROUP A, GROUP B, etc. all interspersed.
If groups in iReport don't keep all the data together, use subreports. When Jasper gets to a subreport, it runs the whole subreport and puts the whole thing into the report. You could have something like:
Subreport 1 - Group 1
Group 1 first record
Group 1 second record
Group 1 third record
...
Group 1 last record
Subreport 2 - Group 2
Group 2 first record
Group 2 second record
Group 2 third record
...
Group 2 third record
It's exactly as Tom said. Jasper Reports Groups do not order the data retrieved from the query, they just take it in the order it comes.
In order to display the information in a group-wise manner, you have to add an ORDER BY to the query so the rows the report receives are already ordered.
So there is an issue that happens when you use multiple group headers. The first header behaves like expected ordered by Column Value A only on unique values. The 2nd header using Column Value B will print on every row despite being non-unique values.
In theory you should be able to use ORDER BY:
ORDER BY ValueA, ValueB
to properly display the report assuming you are using sql, plsql, etc... However, in my case that did not happen, though for others it seems to work.
Use subreports to attach the minor differences via unique reports. You create a root report with empty details. Then you create Unique reports to serve as sub reprots. Finally, you use the subreport element to link the values into the root report. Though that is a good bit of work and may cause repeat code.
A hacky way I used was: A mixture of "Print When Expressions" with logical boolean expressions with 2 group headers and a column header.
Boolean Expressions:
$F{QUERY}.equals(Query1) && ($P{P_Typequery}.equalsIgnoreCase("QueryA") && $P{P_parameter} == null)
and
$F{QUERY}.equals(Query1) && ($P{P_Typequery}.equalsIgnoreCase("P_QueryA") && $P{P_parameter} != null)
with two group headers and a column header. The column header will not repeat for every row so you assign one of the booleans expressions to it's "print when" so it does not always print. The first group header will not repeat for every row and works. The 2nd group header is used for the times you DO want it to repeat for every unique value since it always prints for every row, and you use the other boolean on it's "print when". Hope it helps