I need to create a field to put on group footer #1 that shows the latest price by customer type. The grouping is item_ID (see below). So for example if there were transactions over time with varying prices to Factories and to Retail stores, it would only show the price for the last time that item was sold for a factory(I have a separate field for retail stores). I have tried a few things but nothing is working. For example:
On the detail level:
if {TRANSACTIONS.TRANDATE} = Maximum ({#FactoryTranDate}, {TRANSACTION_LINES.ITEM_ID}) then
{TRANSACTIONS_LINES.PRICE}
FactoryTranDate is basically: if customer type = factory then trandate. Then I created a max of this on group footer #1.
This appears correctly on the transaction line but if the last transaction for that item wasn't to a factory, it will be 0 on the summary line. I tried to do a Max of that detail level field but it doesn't come up for my summary fields, I am assuming cause it gets confused upon doing a summary of a summary?
Sounds like the problem you are running into is the column of data you are trying to print in the footer has multiple rows and you can't predict where the value you want might be within those rows. So by the time you get to the footer, it only has the value held by the last row that printed.
To get around this you would want to use a few formula fields to create variables that can be used to store the value you want from the correct row when it is printed.
I would plan to use 3 formula fields. One to initialize your variable and set it to a default value of zero. Place this formula field in the header that corresponds to your footer and this will ensure the variable exists and is reset to a default value for each grouped value in this header. The formula will look something like this:
WhilePrintingRecords;
Shared NumberVar price:=0.00;
The second formula will declare the same variable again, and it will also include some logic to know when to set the value of the variable. This formula field should be placed within the section that prints the detail records for the grouping. The formula would look something like this:
WhilePrintingRecords;
If <condition to evaluate> Then
Shared NumberVar price:={TRANSACTIONS_LINES.PRICE}
I'm not entirely sure what condition you will want to evaluate here though based on the information you've provided, but I suspect it will be along the lines of if customer type = factory. However, it should be a condition that is only true when you want to capture the price of the detail record within the grouping. If you have multiple cases where it might be true, then you will want to sort them in such a way that the one you wish to capture is printed last within the group. Since you stated that it should be the last factory price, then I would sort by Transaction Date and the variable will change its value with each record that has a true condition and will only keep the price from the one with the latest Transaction Date.
The third formula field is simply for printing the value of your variable in the footer. This field will be placed in the footer section and will display the value of the variable on your report. The formula for this field will look something like this:
WhilePrintingRecords;
Shared NumberVar price;
The formula fields used in the header and details sections can be suppressed if you don't want them to print on your report, but I would recommend waiting until you have the final value printed in the footer verified before suppressing them. This will allow you to see how the value of your variable changes as the report is generated if you are not familiar already with using variable in this manner. You may also want to read up on the scope of variables in crystal reports if this is a new topic for you. My suggestions here all use the SHARED scope, but there are also LOCAL and GLOBAL scopes. GLOBAL might work better in your case, but I tend to favor SHARED in examples such as these because they have the most broad scope. LOCAL definitely will not work for you here though.
Related
I have a Crystal Report of "SALES"
All are GROUPED AND SUMMED Daily,Weekly,and Monthly
I also have a Sub-report of "EXPENSES"
What I want to have is to have a Total SALES and EXPENSES for each GROUP FOOTER on the Main Report which would look like this
I think a Shared variable will do the trick here. When creating variables in Crystal Report you can have a scope of Local, Global, or Shared. Local variables are in scope within a single formula or expression. Global variables are in scope within different sections of a report. Shared variables are in scope throughout the different sections of the report and any sub-reports as well.
Begin by creating a Formula Field in your Expenses sub-report. This formula field will need to create the variable and populate it with a value it reads from a field on your sub-report. Since I don't know the names of your fields, I will make one up called {Table.ExpenseTotal}. Now we can write the code for the formula field as follows:
WhilePrintingRecords;
Shared NumberVar expense := {Table.ExpenseTotal};
The next step is to place this formula field into the sub-report. It should be placed somewhere in the same section of the sub-report that contains the {Table.ExpenseTotal} field. This formula field will also display its value on the sub-report, so you will probably want to set its Suppress property to hide this field.
Now you will need to create a new formula field in your main report. The code for this formula field will be as follows:
WhilePrintingRecords;
Shared NumberVar expense;
The next step is to place this formula field into the main report. It must be placed in a section that follows the section containing the sub-report. At this time the formula field should be displaying the value of the expense variable that was created and populated in your sub-report.
To apply this to your report you will want to substitute the field that contains the Sum of expenses for the example field name I used.
There are some limitations to consider when using variables like this. These variables do not exist until the report is being printed, which is why the "WhilePrintingRecords" declaration is used. This means these formula fields may not be used in Summary Fields, Running Total Fields, or Record Selection because all of these are parsed before the report begins printing. You should also be mindful of which sections you place the Formula Fields within. The code for each variable is very simple usually, but the placement within sections and how Crystal Reports moves from section to section while printing is what determines the looping structure for how the values of your variable are updated.
If a row has the same ID as the last one, I want to combine them - summing up the cubicFt and Savings. $perFt divides the savings by the cubicFt, so it wouldn't be summed, simply dividing the new results. I also want the Descriptions to be concatenated, like this:
Make a Group based on ID (or whatever the leftmost column is). Then suppress the Details section and the Group Header. Instead, you'll be putting all the fields you want to display in the Group Footer. From there it's simple:
Create a Summary or Running Total for both cubicFt and Savings.
Reconfigure your $PerFt to use the summary/running total fields you made in step 1.
Combine the Descriptions by creating a shared string variable Descriptions. Whenever the group changes, reset it with Descriptions = "". Whenever the group doesn't change, add the description string to your variable. Something like:
Descriptions = Descriptions & " ; " & {yourtable.Description}
Then create a final formula ShowDescription in the Group Footer to display the results with RIGHT(Descriptions, LEN(Descriptions)-2)
You need to do grouping, either by modifying the SELECT statement or the stored query that generates the data, or within Crystal Reports. I'm literally 20 years out of date on Crystal Reports, although I have used similar software, so this will have to be tweaked.
For the first solution, all you need is a concatenation aggregation function for the string field. Your DB may or may not have one built in, so you may need to add it.
SELECT Building, ID,
SUM(cubicFt), SUM(savings),
SUM(savings)/SUM(cubicFt) AS [$perft],
LEFT(STRING_AGG(description, ';'), -1) -- drop extra ; at end
GROUP BY Building, ID;
However, you should be able to do the same within Crystal by setting this up as a subtotal group (not sure if you have to do user definitions for the string aggregation), and then hiding the detail section.
I have a report where the fields come from data pulled from a SQL server. I have a total field that i have added to the report...however i have an interesting conundrum--i was hoping someone had a formula i could use.
Three of my columns do NOT need summation...however my project requirements are telling me instead to just pull the last number from the last row in the report and putting that in the total row. To better clarify:
1999 0.1% 0.2% 0.3%
2001 -2% 0.3% 3.4%
Basically, in the total field, i'd be pulling the values from 2001 since it is the last report row. In my total row, i want to have -2%, 0.3% and 3.4% showing (since those are the last row's values). SO basically, i just want to pull the last report row's data (NOT total it).
Anybody have a formula i can use for this?
If I read this correctly, I typically would just put the fields themselves in the footer, without any formulas. The report should display the values from the last record in the group.
Well, I have two formulas you can use... I think the only way to do this is with a variable to capture the final value in the details section, and then display it in the group footer. So, in details, create formula field like this:
shared CurrencyVar lastValue;
if (OnLastRecord) then
lastValue := {my_table.field_name}
Add this to your details section and suppress it (so it doesn't display). Then add another formula like this:
shared CurrencyVar lastValue;
lastValue;
Add this to your group section where the total would normally go.
You will need another set for formulas for each field you need to handle this way. Note that you could handle all the fields in the first formula if you use basic syntax (so you can have multiple statements under the 'if').
I would like to share my example.
I should keep last modified value in details and represent in group.
In details I have:
shared NumberVar X1;
if {Q.SklID}={#InSkl8} AND ({Q.Poredak}=1 OR {Q.Poredak}=2) then X8:={Q.MCena};
and in group I have following formula:
shared NumberVar X8;
X8;
This way, I escape situation to have NULL in group formula because I don't have else clause in details formula.
I have a Crystal report that needs to display the data from the first record regardless of the number of records (usually 1 to 13 records). This field is placed at the bottom of the report and without any control it will always display the last record. This field indicates the container number being used for blood transport and the first record will always be the most current record.
welcome to SO.
What is your data source? (Access database, SQL Server, etc.)
The ideal solution would be to modify the database query to:
Sort the records in some meaningful fashion.
Bring back only one result to your Crystal report.
Performing the work in this way may not make much of a difference for this particular report, but if you run several of the reports will start to become important.
Best regards,
Put a formula in your Report header that contains: shared numbervar myVar := {MyTable.Field};. Duplicate that line for each field you want to display (with the appropriate data type). In the Report footer, for each field, create a formula containing shared numbervar myVar;
I have a Jasper report that displays a list of bill line items. These items are grouped by billing period, and then by whether the item is a charge or credit. For billing periods in which there are charges but no credits, I would like to display a static text field stating "No credits" in the Credit group for that period. How can this be done?
Edited to add: This is assuming that I am using an SQL query for the data source, as opposed to customizing one. If I customize my data source, I can handle this in pre-processing before I reach the report, but I was hoping to discover a way to get around Jasper's behavior of skipping groups with no rows meeting the group criteria.
If you were able to, in your data source, have a count of total # of credits for each group, then you could use the 'print when expression' property on the static text. e.g:
new Boolean ($F{total_credits}.equals(0));
The static text would need to go in the group header or footer as it wouldn't work in the group detail section (it would print out multiple times).
You may need to create a variable instead of use $F{total_credits} directly - I'm not certain how JasperReports deals with accessing fields in group footers. You may also find that in the group header it picks up the correct total_credits while in the group footer it doesn't.
The other way would be to have a variable that counts the total # of credits in the group. You would need to set the 'reset type' for the variable to 'group', then set the reset group. The Variable expression would be something like:
$V{myvariable} +
($F{credit_or_debit}.equals("credit") ? new Integer(1) : new Integer(0))
and the initial value expression would be new Integer(0)
Then in the group footer you could use the 'print when expression' on the static text to look at the variable.