I'm using Crystal 2020 and I have two tables, osEntity and osCommunication, that can be joined on osCommunication.fkosEntity=osEntity.PK. osCommunication contains phone numbers for customers in osEntity and each customer can have multiple phone numbers, so naturally this means that some records look like this:
Name Phone
John Smith 555-555-5555
John Smith 555-555-3333
but I would like it to look like this in my report:
Name Phone
John Smith 555-555-5555, 555-555-3333
I tried accomplishing this by creating a sub-report and linking osEntity.PK in the outer report to osCommunication.fkosEntity in the sub-report and then creating a formula that loops through osCommunication.information, the field that contains the phone numbers, to concatenate them like so,
stringvar array numbers := {osCommunication.Information};
numbervar cnt := count(numbers);
stringvar out := "";
numbervar i;
for i := 1 to cnt - 1 step 1 do (
out := out + numbers[i] + ", ";
);
out := out + numbers[cnt];
out
The problem is that Crystal is only giving me access to one row at a time, so this formula produces something more like 5, 5, 5, -, 5, 5, 5, -, 5, 5, 5, 5 rather than 555-555-5555, 555-555-3333. Is there a way that I can get access to all rows returned by the query to osCommunication at once rather than one row at a time? I've done something like this with parameters from user input before but I'm struggling to do the same with the result of a query. Any help would be greatly appreciated, thank you.
UPDATE: I was able to work out the following solution thanks to @MilletSoftware
Admittedly, I don't fully understand why, but I wasn't able to get the list of concatenated phone numbers to print in the group footer of each group until I changed all of my global variables to shared variables. I also ended up using a string array to make filtering out duplicates a little easier. None the less, I'll include my completed solution here for the sake of those who may be looking to do something similar.
Group Header Section:
Shared StringVar Array Phones; //Array containing all phone numbers related to the current group.
Redim Phones[1]; //Reset the Array at the start of each group.
Shared NumberVar reCount; //Current record count for the current group.
Shared StringVar currentEntity; //The entity ID of the current group.
//Check if starting a new group. If so, update the current group's EntityID and resent the record count.
If currentEntity = "" or currentEntity <> {osEntity.EntityID} Then
(
currentEntity := {osEntity.EntityID};
reCount := 1
);
Details Section:
Shared StringVar Array Phones;
Shared NumberVar reCount;
//Only add phone number to array if it is unique
If Not({osCommunication.Information} In Phones) Then
(
ReDim Preserve Phones[reCount];
Phones[reCount] := {osCommunication.Information};
reCount := reCount + 1;
);
Group Footer Section:
Shared StringVar Array Phones;
//Join all phone numbers in the array into a comma separated list
Join(Phones,', ');
Group by Customer. In the Group Header, use a formula to reset a global string variable.
Global Stringvar Phones := "";
In the detail section, concatenate the phone number to the global variable:
Global StringVar Phones := Phones + {Customer.Phone} + ", " ;
In the Group Footer, use a formula to get rid of the last comma, and display the phone numbers:
Global StringVar Phones;
IF Len(Phones) > 2 Then Phones := LEFT(Phones, Len(Phones) - 2);
Phones;