I have spent too many hours today trying to get a report to work. I'm using CR9. Hopefully this post will help someone along the way save a few or more hours. The problem that had me stuck had to do with a global array variable but I believe my points apply to use of any global variable. Specifically, any global variable that is set in one formula and then used in another formula, which you'd think shouldn't be so hard.
Suggestion 1: If you have never the read the help text (via F1 in CR) on WhileReadingRecords and WhilePrintingRecords, please stop reading this and do so now. It's worth the read.
Suggestion 2: If you have never read the help text on global variables (search the Index in Help for global variables and double click the first match which should be global variables) please have a look.
In the help text near the end of the entry for global variables, there's an eye-opener. I've copied it here and hopefully CD won't mind. I've added the bold because this was ultimately the answer to my problem:
[ul]Here is an example...
Rem Formula C
Global x as Number
x = 10
formula = x
Rem Formula D
'call the function WhileReadingRecords
WhileReadingRecords
Global x as Number
x = x + 1
formula = x
If Formula C is placed in the Report Header and then Formula D is placed in a detail section, Formula C will be evaluated before Formula D. Formula C will be evaluated once and then Formula D will be evaluated for each record appearing in the detail section. Formula C returns 10. For the first detail record, Formula D returns 11. This is because the value 10 of x is retained from when it was set by Formula C. Formula D then adds 1 to this value, setting x to 11 and then returns 11. For the second detail record, formula D return 12, adding 1 to the previously retained value of x which was 11. This process continues for the remaining detail records.
The call to WhileReadingRecords tells Crystal Reports to re-evaluate Formula D as it reads in each record of the report. Otherwise, since the formula does not contain any database fields, the program will evaluate it only once before reading the records from the database. The formula will then return the value 11 instead of 11, 12, 13, ... as the successive records are processed.
[/ul]
From the points made above, I have learned:
Rule 1:Global variables must be declared in any formula in which they are used. This is goofy to me but I'm sure there's a good reason for it. The example above shows how to do it. In my case, I had:
[ul]
[li]FormulaA displayed in detail section (initializes and sets values in the array then displays the first value):
Global StringVar Array Customers =
Customer[1] = "12345";
.
.
Customer[5] = "98765";
WhileReadingRecords; //Without this you will get "" which goes against what the help text tells you. A bug in CR9?
Customer[1];
[/li]
[li]FormulaB displayed in detail section (displays second value of the Customer array):
Global StringVar Array Customers;
WhileReadingRecords;
Customers[2];
[/li]
[li]FormulaC displayed in detail section (displays third value of the Customer array):
Global StringVar Array Customers;
WhileReadingRecords;
Customers[3];
[/li]
[/ul]
Rule 2: If you have a global variable that is being set in one formula and used in another formula that does not reference database fields, use WhileReadingRecords if the formula is used in the detail section. (But this doesn't seem to be consistent with the help text. I had to place WhileReadingRecords in the formula shown above in FormulaA). If the formula is used in a group section use WhilePrintingRecords.
If anyone has any more to add to this or any corrections, please help yourself.
Suggestion 1: If you have never the read the help text (via F1 in CR) on WhileReadingRecords and WhilePrintingRecords, please stop reading this and do so now. It's worth the read.
Suggestion 2: If you have never read the help text on global variables (search the Index in Help for global variables and double click the first match which should be global variables) please have a look.
In the help text near the end of the entry for global variables, there's an eye-opener. I've copied it here and hopefully CD won't mind. I've added the bold because this was ultimately the answer to my problem:
[ul]Here is an example...
Rem Formula C
Global x as Number
x = 10
formula = x
Rem Formula D
'call the function WhileReadingRecords
WhileReadingRecords
Global x as Number
x = x + 1
formula = x
If Formula C is placed in the Report Header and then Formula D is placed in a detail section, Formula C will be evaluated before Formula D. Formula C will be evaluated once and then Formula D will be evaluated for each record appearing in the detail section. Formula C returns 10. For the first detail record, Formula D returns 11. This is because the value 10 of x is retained from when it was set by Formula C. Formula D then adds 1 to this value, setting x to 11 and then returns 11. For the second detail record, formula D return 12, adding 1 to the previously retained value of x which was 11. This process continues for the remaining detail records.
The call to WhileReadingRecords tells Crystal Reports to re-evaluate Formula D as it reads in each record of the report. Otherwise, since the formula does not contain any database fields, the program will evaluate it only once before reading the records from the database. The formula will then return the value 11 instead of 11, 12, 13, ... as the successive records are processed.
[/ul]
From the points made above, I have learned:
Rule 1:Global variables must be declared in any formula in which they are used. This is goofy to me but I'm sure there's a good reason for it. The example above shows how to do it. In my case, I had:
[ul]
[li]FormulaA displayed in detail section (initializes and sets values in the array then displays the first value):
Global StringVar Array Customers =
Code:
["","","","",""];
.
.
Customer[5] = "98765";
WhileReadingRecords; //Without this you will get "" which goes against what the help text tells you. A bug in CR9?
Customer[1];
[/li]
[li]FormulaB displayed in detail section (displays second value of the Customer array):
Global StringVar Array Customers;
WhileReadingRecords;
Customers[2];
[/li]
[li]FormulaC displayed in detail section (displays third value of the Customer array):
Global StringVar Array Customers;
WhileReadingRecords;
Customers[3];
[/li]
[/ul]
Rule 2: If you have a global variable that is being set in one formula and used in another formula that does not reference database fields, use WhileReadingRecords if the formula is used in the detail section. (But this doesn't seem to be consistent with the help text. I had to place WhileReadingRecords in the formula shown above in FormulaA). If the formula is used in a group section use WhilePrintingRecords.
If anyone has any more to add to this or any corrections, please help yourself.