So I have a series of orders that come in everyday. We add them to a database and then use Crystal Reports make packing sheets of these orders. We have two tables one for order information(name, address, order number, etc) and one for the items. In Crystal Report we use the order for the report and then do a subreport with all the item associated with order number. Now I have been given the requirement that we need to all the orders sorted by the first item's item number. How do I sort a report by a field in a subreport?
First of all, you can accomplish this report w/o a subreport. The report would be grouped by order # w/ the order fields in the group header. The Details section would contain the order-items.
In any case (my approach or yours), if you just need to sort the order-items by item number, simply reference that field in the Record Sort Expert.
If you need to sort the orders by each order's order-items[0] (the first item in the list), you'll need to create a SQL Expression that returns the item #. If you add a group on the SQL Expression field, then make that the top-level group (G1), the report will group first by the SQL Expression, then by the Order #. The SQL Expression should resemble:
(
//this will select the numerically-smallest item# for a given order#
SELECT min(item #)
FROM order-items
//correlate to 'main' query
WHERE order#=order.order#
)
If you need more complex rules for 'first item #' (whatever that means), you need to include it in the SQL Expression.
Related
I am attempting to group by order #, and display this as one row.However since the same order #, the 'Total' should only add 47.66 once.
I've attempted to use the group expert to no avail. I can do this in SQL but can't design it Crystal reports.
Create a new group by Order # and move all items from the detail section to the header of the Order # group. This should do the trick of displaying it as a single row.
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.
I am using iReport 4.1.3. I have created invoice report and I want to have 3 copies of same invoice report. The first invoice should have label as "ORIGINAL", second should have "DUPLICATE" and the third should have label as "TRIPLICATE" on it.
Thank you.
If you would like to show all three copies every time you open the report, here is a creative if not elegant solution.
Add a cross join to the FROM clause of your query returning the three different copies. In MySQL it looks like this:
CROSS JOIN
(
Select 'ORIGINAL' as copy, 1 as sequence
UNION
SELECT 'DUPLICATE' as copy, 2 as sequence
UNION
SELECT 'TRIPLICATE' as copy, 3 as sequence
) x
Then add the "copy" field to your select statement. This will cause your query to return 3 records for each record it was previously returning. One record with "ORIGINAL" in the copy field, one with "DUPLICATE" and one with "TRIPLICATE". Add "sequence" to your ORDER BY clause.
Then in the report, group by the "copy" field. Force a new page for each group and you should be all set. Any variables you are totaling at the report level you will need to change to the group level ("copy" group). And if you have any controls in the Summary section, move them to the new group footer section. Also create a text field to display the "copy" field in the page or group header.
It's not necessarily pretty, but it should work.
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
Ok, this might be a weird request, but is it possible to essentially flatten my dataset inside a crystal report?
I have a datatable in C# that was created with a join, so when it hits the report its 2 records. Most of the columns have identical data, with the last few displaying a different address.
Instead of printing the detail section multiple times with mostly similar data, I need to display 1 'record' with the common data printed once, and each records address arranged next it. As in, all the common fields displayed in one area, and then next to that the address fields from the record where 'AddressType = 1', then next to that the address fields where 'AddressType = 2'
Is this a subreport thing? Because even with subreports I can't get it to only print 1 detail section with the data from just the first record.
Is this even possible with crystal? For long drawn out reasons, I can't flatten the data before it gets to the report.
Ok, someone here in the office showed me the way, so I'll put this out there.
Given data with cols A,B,C all common and D,E different across multiple rows, this is how I 'flattened' the dataset in crystal:
Create a group based on col A, and put A,B,C inside that group header - get rid of the details section entirely
Create a subreport in the group header for each row of data, in my case 2 subreports
Inside each subreport, put fields D,E. Important: There are NO links for these subreports!
For each subreport go into the Select Expert and create a condition that shows only 1 particular row of data. This conditional will have the same field for each subreport, but different values. In my case it was AddressType='A', and AddressType='B'
This will produce 1 report, with A,B,C listed once, and D,E listed once for each subreport(once for each row of data)
This was confusing, time consuming, and I hate crystal reports now more than ever.
It would be pretty ugly, but you could add a group for each common field in Group Expert and then display the data for the common fields in the last group header. So if your common fields are field1 through field5, you would create five groups and put all five fields in the group header of field5. Then you would put the unique address fields (call them field field6 through field8) in the details section.
Now the trick is getting everything to line up correctly. You can set "underlay following sections" on the group header for field5; this will cause field1 through field5 to "fall down" into the details section. You just need to make sure that field6 through field8 are all to the right of field1 through field5 so the text does not overlap.
Now, if you want the two address records to print horizontally, I think you will need a subreport with multiple columns for that. But the same principle applies -- just make sure the subreport is to the right of field1 through field5 so the data doesn't overlap.
Have you tried the suppress if duplicated option on each non-address field?
Otherwise, you could group by the common id, put the common fields in that header, and then display the multiple addresses in the details section.
Or, you could remove the addresses from the datasource and use a subreport to fetch this data for each record. This would bypass the join and be the slowest option performance wise, due to having to select the addresses for each record.
Ok, firstly let's see if I understand this right :
You want a report that would be in the format
MainDetails Address(type1)
MainDetails Address(type2)
to instead be in the format
MainDetails Address(type1) Address(type2)
?
Assuming there are only two address types, you can do the following :
1) Group by Main details (whatever the unique entry is
2) Put the address details in the group header next to them, on the right
3) Also put the address details in the details section, but positioned as if they were in the Address(type2) column positions, so it looks like :
GH MainDetails Address
D.......................................Address
4) Next, add a sort to the report on the AddressType field, so that AddressType=1 shows first.
5) Add a conditional suppression formula to the Details section saying {AddressType=1}
6) Using the Section Expert, in the Group Header tick the 'underlay following sections' box
This should work as long as the number of addresses is either 1 or 2.