I've been having trouble pushing down queries to a SQL server when using Crystal Reports (I'm currently working with Crystal Reports 2013).
If I enter the following as a record selection formula, Crystal uses a WHERE clause to select the records:
{LINKAGE.ENTITY_ID_1} = 1 and
{LINKAGE.ENTITY_TABLE_1} = "ENT" and
{LINKAGE.ENTITY_TABLE_2} in ["DOC","PHO"]
-Gives-
SELECT "LINKAGE"."ENTITY_ID_1", "LINKAGE"."ENTITY_TABLE_1", "LINKAGE"."ENTITY_TABLE_2"
FROM "TESTING_DB"."dbo"."LINKAGE" "LINKAGE"
WHERE "LINKAGE"."ENTITY_ID_1"=1 AND "LINKAGE"."ENTITY_TABLE_1"='ENT' AND ("LINKAGE"."ENTITY_TABLE_2"='DOC' OR "LINKAGE"."ENTITY_TABLE_2"='PHO')
If I change the 'hard coded' values to instead use variables, Crystal no longer includes a WHERE clause when selecting records:
numbervar valueNumber := 1;
stringvar valueString := "ENT";
stringvar array valueArray := ["DOC","PHO"];
{LINKAGE.ENTITY_ID_1} = valueNumber and
{LINKAGE.ENTITY_TABLE_1} = valueString and
{LINKAGE.ENTITY_TABLE_2} in valueArray
-Gives-
SELECT "LINKAGE"."ENTITY_ID_1", "LINKAGE"."ENTITY_TABLE_1", "LINKAGE"."ENTITY_TABLE_2"
FROM "TESTING_DB"."dbo"."LINKAGE" "LINKAGE"
From reading the documentation it sounds as though there shouldn't be an issue pushing these down, so I'm not too sure what I might be missing. Any insight would be greatly appreciated!
I seem to have found the answer in the Crystal Reports User Guide. There it's mentioned that only a constant or parameter value can be pushed down but not a variable:
https://help.sap.com/doc/dfc124becfa845ffa91b1e717b20e3ec/2016%20SP3/en-US/4770d0cd6e041014910aba7db0e91070.html#loio4770d0cd6e041014910aba7db0e91070
Related
I am working with Crystal Reports 11.5.10.1263 [CR Developer Type: Full].
I am familiar with Programming and SQL syntax in general and have worked with expressions in SSRS & MS Access but never in Crystal Reports.
Problem:
I modified the SQL in the Crystal report and it has had the desired effect - except in the last part of the report output - where the changes I made to the SQL do not have the desired effect.
The 'desired effect' is that when a field named 'FundNumber' has the values '2595', '2597' Then the field named 'Organization' should be assigned the value '41600'.
The Detail Record in the Report has the following three rows as part of its 'Formula':
+ IIf({Data.Payments} > 0, "+01W ", "-01W ")
+ Left({Data.FundNumber}+ SPACE(6),6)
+ Left({Data.Organization}+ SPACE(6),6)
I want to change the Data.Organization row to an IIF Statement that says [pseucode]:
IIf Data.FundNumber IN ["2595", "2597"] Then "41600" Else Data.Organization
I believe the Left() function is saying 'return the left 6 characters of [Data.Organization + 6 Spaces] ?? and that it has to do with the way the data is presented in the output.
I would appreciate help with creating the IIF statement for this.
I included the 'IIf({Data.Payments} ...' row in case that helps - as my google searches have turned up examples that use IF instead of IIF.
Thanks!
The syntax most of the time is the same as VB. Try
IIF({Data.FundNumber} = "2595" or {Data.FundNumber} = "2597", "41600", {Data.Organization})
Say I'm working on a report, on a column called someTable.someColumn. What I need is to have all of the values in the ReportHeader. I know I cound create a subreport, pass them this column and iterate it in the details, but I would like to know if it's possible to do it without a subreport.
If I use the following, I get the right result, which in my case is 9:
COUNT(someTable.someColumn)
I also tried the following, but it doesn't work - it only takes one of the 9 values randomly.
Local NumberVar i := 0;
Local StringVar Array items := {someTable.someColumn};
Local StringVar output := "";
while (i < count(items)) do (
i := i+1;
output := output + items[i];
);
output;
Is it possible to iterate over a column in order to get the values?
You can't do this in the report header. You have to use the detail section to read each value.
The only solution which springs to mind is using a subreport. Although you wouldn't pass them this column and iterate it in the details. Because it would only pass the first value from the column. You would pass it the report parameters which it could use to obtain the column values from the database the same way your main report does.
I haven't found a way to do this in the report header, but you could put it in your report footer with the following formula:
global StringVar output;
output := output + {someTable.someColumn} + ",";
This will execute each time someTable.someColumn changes over the course of report generation, and append it to the global variable. Unfortunately, it doesn't keep all instances of it up to date - for example, if you include it in the report details somewhere, you'll be able to see the evolution of output over the course of the report. In the header, it'll only display the first value.
Note: You won't want to set output := "" in this formula, as that'll reset the value each time. It seems, though, that Crystal automatically initializes the variable for you when it's created, and I didn't run into any errors with only the above formula (i.e, I didn't need to create a second formula to initialize output). I've also included a delimeter (+ ","), to help separate each of the values, but you can easily just remove that.
I have the following problem with iReport / JasperReports server.
I'm using a main reports with two subreports returning a calculated price, the type of the subreport variable and the local variable is BigDecimal.
If the return value from a subreport is null (no rows found) then the assigned local variable in the main report is always null. But I want to have "0.00" because I want to calculate a sum.
The construct (return_variable == null ? new BigDecimal(0) : return_variable) doesn't help as well as to set the local variable to a default value new BigDecimal(0). I always get null instead of the wanted value "0.00" ;-(
I've tested with version 3.7.6 until 4.4. of iReport, nothing helps.
Does anybody have a hint for me? Thank you in advance.
I've had the same problem, except I tried to use the return value of the subreport as a parameter of another subreport. I succeeded in getting the result I wanted by using a scriptlet in the second subreport.
I proceeded this way :
-in subreport 2, I have my parameter p (Float), its value being the return value of subreport 1
-in subreport 2, I have a variable v (Float), initialized with p
-in my scriptlet (in the method beforeDetailEval(), I test my variable v : if it is null, I assign the value new Float("0.0")
I works ok.
The limitation with this is if you want to use the return value of your subreport directly in your main report. I tried doing that, but never succeeded.
Hope this will help someone some day.
Cecilka
Yahoo! By the Grace of GOD, I found a great answer to my own question. Posting it as it may help someone in future.
1) I changed my Simple SQL Query with a MySQL stored procedure as.
My Stored Procedure as
BEGIN
SET #p = 0;
SET #n = 0;
SET #m = '00';
SELECT x.*, y.* FROM
(select #n:=#n+1 as "ID", #m:=acc as "Account" from tbl_reports) x
right JOIN
(SELECT if(#m='00',0,#p:=#p+1) as "IDU") y
ON y.IDU = x.ID;
END
In IReport, I declared my variable as
$F{IDU}>0?$F{Amount}:0
In this way, it now shows 0.00 instead of null.
In Crystal Reports v 11, is it possible to display the 'Parameter Description' value on the report, as opposed to only the parameter value? Whenever I drag the parameter onto the report to display it, only the value is displayed, and I want to print the description.
Note: I'm working in Crystal 11 (XI), not the .NET Crystal Report plug-in.
I agree with Ryan--there isn't a native mechanism to grab these values. A user-function library (UFL) might be an approach worth investigating.
In lieu of that, I handle this a number of ways:
a formula with a case statement to convert the value to a description.
a custom function that does the same a #1; custom functions can be shared w/ other reports via the BOE repository
use a subreport to query a table that can covert the value to a description. store the values in an array in the Detail section (suppressed), then Join() the array in the report footer. if you embed the subreport in its own section, it will expand as needed to accommodate an expansive list
you might be able to adapt #3 to use a list of values exposed by BO's query as a web service (QAAWS), but I haven't experimented with this. If it doesn't have an associated schema document, CR won't be able to use the XML webservice as a data source.
First, Concatenate the parameter value and the description together and delimit the two values using a pipe '|' or other lesser used character
Example:
CustomerID, CustomerName -> 12345|ABC Company
Second Use a Crystal function with an array to display the description side on your report i.e everything after your delimiting character
Numbervar i;
Numbervar j;
StringVar Array z := "";
Local StringVar Array x := split(Join({?My Parameter},";"),";");
j := count(x);
redim preserve z[j];
for i := 1 to j do(
z[i] := right(x[i],Length(x[i])-instr(x[i],"|"))
);
join(z,",")
Third. Create a second function like the one above to return the Parameter value to the left of the delimiter to use as part of the report's Selection Formula**
I don't believe there is a way to directly get at the description (several other posts scattered around the interwebs seem to agree). If you have a small(-ish) number of parameter options, you can just create a formula or function that contains a case-statement that will translate the value to its description.
I got over the shock that Crystal Reports somehow is able to retrieve the description of a parameter but it doesn't expose it to be used in formulas. Being forced to duplicate the definition of parameters and description seems to me bad form, simply because one is not supposed to duplicate things when programming. An alternative hack (besides all the ones listed) would be to make your Values and Descriptions as values of a SQL data source (hardcode them in SQL). Then you can populate your parameter from said data source and you will have the Descriptions available as a field. That way you only have "one version of the truth" that maps your values to your descriptions, although more moving pieces.
See: 1678487 - How to display parameter descriptions instead of parameter values in the Crystal Reports at: https://apps.support.sap.com/sap/support/knowledge/public/en/1678487
There is a new function that can actually be used for displaying the descriptions of a parameter on a report.
Source : https://launchpad.support.sap.com/#/notes/2037542
I will paste the entire document for those users who don't have to access to this page.
A new function GetValueDescriptions() is added in Crystal Reports 2016, to allow user create formula that could operate / display descriptions of selected value for a parameter.
GetValueDescriptions() supports all kinds of parameters (single and multiple, discrete and range). Below is an formula example where {?customerMultiDiscreteAndRange} is a multiple range parameter:
local stringVar range array im := GetValueDescriptions ({?customerMultiDiscreteAndRange});
local numberVar i := 1;
local stringVar out := "";
while i <= count(im) do
(
if (IncludesLowerBound ({?customerMultiDiscreteAndRange}[i])) then
( out := out + "["; )
else
( out := out + "("; );
if (HasLowerBound ({?customerMultiDiscreteAndRange}[i])) then
( out := out + GetLowerBound(im[i]) );
out := out + "..";
if (HasUpperBound ({?customerMultiDiscreteAndRange}[i])) then
( out := out + GetUpperBound(im[i]) );
if (IncludesUpperBound ({?customerMultiDiscreteAndRange}[i])) then
( out := out + "]"; )
else
( out := out + ")"; );
if (i < count(im)) then
out := out + ", ";
i:= i + 1;
);
out;
Also note two new functions - GetLowerBound() and GetUpperBound(), they can be used to get correct lower / upper bound descriptions. These two are especially useful if Maximum() and Minimum() returns swapped descriptions.
Above formula example can be adjusted easily, e.g. to show both the value and descrition, or to satisfy more reporting needs.
To use these functions, upgrade your Crystal Reports to a release where the enhancement has been made.
See the SP Patch Level section for details and available patches.
For SAP Crystal Reports, version for Eclipse:
These functions are supported for runtime only since SP22, with following limitations:
Static multi-range parameters are not supported in SAP Crystal Reports, version for Eclipse runtime, which is the same as before. Dynamic multi-range parameters are supported.
"Value Options" to show description is not supported in the embedded designer in SAP Crystal Reports, version for Eclipse. If you have an existing report designed in SAP Crystal Reports 2016 with parameters' "Value Options" to show description, any modification resaved in the embedded designer will overwrite the "Value Options" to show value. Instead, reports created in SAP Crystal Reports 2016 with the "Value Options" to show description is supported in SAP Crystal Reports, version for Eclipse runtime.
To download the latest Support Packages of SAP Crystal Reports, version for Eclipse:
https://wiki.scn.sap.com/wiki/display/BOBJ/SAP+Crystal+Reports+version+for+Eclipse+-+Downloads
I'm creating a invoice crystal report for sage mas 500 AR module. In it, I'm attempting to add the tarinvoice.balance field with the following formula:
if {tarPrintInvcHdrWrk.Posted} = 1 then
ToText({tarInvoice.Balance})
I'm assuming that when the {tarPrintInvcHdrWrk.Posted} = 1 conditional statement holds FALSE, it doesn't attempt to pull the invoice field because when I remove the formula from the report, the form displays correctly without it.
When the conditional statement renders true in the report, the balance fields behaves correctly. However, with the formula renders FALSE in the CR form, the entire crystal report bombs and displays blank. Any ideas why or what I'm doing wrong?
Just tried setting everything to zero and the report still bombs. I'm starting to think its more of a query error in the report. I wish there was a way to exclude the field in the query when posted = 0.
With tarinvoice.balance removed when the posted = 0, the report works fine.
With tarinvoice.balance included and posted = 1, report works fine.
With tarinvoice.balance included and posted =0, report bombs.
I believe the conditional statement fails immediately if you encounter a NULL, so your formula needs to test IsNull({tarPrintInvcHdrWrk.Posted}) before it tests equality with "1".
You can change the way Crystal handles a null value for a value in a formula. At the top of the Formula Workshop there is a drop down box that usually says "Exceptions For Nulls".
Change this to the other option "Default Values For Nulls" and your formula should no longer bomb out. You used to be able to specify the what the default values applied were, but more recent versions of Crystal have these hard coded.
Search the help for "Null Treatment" for a table showing them.
I modified the formula to this:
if isnull({tarPrintInvcHdrWrk.Posted}) = FALSE then
if {tarPrintInvcHdrWrk.Posted} = 1 then
if isnull({tarInvoice.Balance}) = FALSE then
ToText({tarInvoice.Balance})
else
"0.00"
else
"0.0"
else
"0"
The crystal report still bombs.. Nevertheless, it does show "0" in the appropriate space.
I saw a suggestion on Exp.Exch to try putting the field into a variable before converting it to text.
e.g.
NumberVar InvoiceBalance;
If isnull({tarInvoice.Balance}) then
InvoiceBalance := 0
Else
InvoiceBalance := {tarInvoice.Balance};
If {tarPrintInvcHdrWrk.Posted} = 1 then
ToText(InvoiceBalance);
I also tried to recreate your problem, since I have see similar things before.
No luck though trying with CR 8.5 & XI R2. Perhpas it has to do with linked tables as well, since I only tried on a simple single table.
I have also seen similar behaviour when using a formula within a Running Total - they do not like nulls at all!
If you put {tarInvoice.Balance} directly on report (into details "debug" section - often needed, don't forget supress it in production :)), what values it displays or does report become empty?
Maybe you have Suppress If Blank section on your report. Try to put: Else " "
if isnull({tarPrintInvcHdrWrk.Posted}) or {tarPrintInvcHdrWrk.Posted}=0 then
" "
else
if {tarPrintInvcHdrWrk.Posted} = 1 then
ToText({tarInvoice.Balance})
else
" "
I have trouble with this kind of field when making reports to export to excel. A field with no data in will pull all columns to the right of it over to "fill the gap".