Technical Questions
 Crystal Reports Forum : Crystal Reports 9 through 2022 : Technical Questions
Message Icon Topic: How many appear once, versus how many appear more. Post Reply Post New Topic
Page  of 2 Next >>
Author Message
MDRussell
Newbie
Newbie


Joined: 20 May 2008
Location: Canada
Online Status: Offline
Posts: 9
Quote MDRussell Replybullet Topic: How many appear once, versus how many appear more.
     Posted: 20 May 2008 at 11:57am
Hi everyone,

I have a report where I need to display two values in the report footer.

One value: How many people only appear once in the report
2nd value: How many people appear more than once in the report

The report is grouped by program. So a person may appear in only one program, or may appear in several programs.

I can't figure out how to gather this data.. I've been playing with formula and running total fields all morning.

Can anyone give me advice on the crystal syntax that will do this for me?




Edited by MDRussell - 20 May 2008 at 12:01pm
IP IP Logged
hilfy
Admin Group
Admin Group
Avatar

Joined: 20 Nov 2006
Online Status: Offline
Posts: 3702
Quote hilfy Replybullet Posted: 20 May 2008 at 4:22pm

You'll probably have to do this in a subreport because you need to count in a different order than your report.  Set up the same table structure as the main report (or just the main data tables if you have lookup tables), group by person instead of by program.  Then try using a couple of formulas - something like this:

{@Only One}
if PreviousIsNull({table.person_id}) or previous({table.person_id}) <> {table.person_id} then
  if NextIsNull({table.person_id}) or next({table.person_id}) <> {table.person_id} then 1 else 0
else 0
{@More than One}
if previous({table.person_id}) = {table.person_id} and
  (NextIsNull({table.person_id}) or next({table.person_id}) <> {table.person_id}) then 0 else 1
 
You then put grand total sums of these two formulas in the subreport's report footer.
 
-Dell
IP IP Logged
MDRussell
Newbie
Newbie


Joined: 20 May 2008
Location: Canada
Online Status: Offline
Posts: 9
Quote MDRussell Replybullet Posted: 20 May 2008 at 7:42pm
ok, so it's getting there, but not quite..

I made the sub report with the group by person, so when I preview the sub report it has a row for each program they're in. if someone's in the report 4 times, it comes up like:

program 1 - 1.00
program 2 - 1.00
program 3 - 1.00
program 4 - 0.00

I'm not too sure what that's about.. and I also can't figure out how to get the summed value into the footer.. when I try and SUM(@only_one), it says that field can't be summarized.

Am I missing something?

Also, the main report is being filtered with a record selection formula - will that carry into the sub report? or is there something I need to do there?
IP IP Logged
Lugh
Senior Member
Senior Member
Avatar

Joined: 14 Nov 2007
Online Status: Offline
Posts: 377
Quote Lugh Replybullet Posted: 21 May 2008 at 5:22am
You could also do it with a pair of arrays and a bit of jiggling.

In the Report Header, initialize the arrays like so:

WhileReadingRecords

Global StringVar Array TotName;
Global StringVar Array MultName;

ReDim TotName[1];
ReDim MultName[1];

TotName will end up holding all the names in the report.  MultName will end up holding all the names that appear more than once.  Note that if you have a lot of names, you may run into memory issues, and may need to try an alternate approach.

In the Details section, update the arrays like so:

WhileReadingRecords

Global StringVar Array TotName;
Global StringVar Array MultName;

IF {MyReport.MyName} in TotName THEN
    (IF Not({MyReport.MyName} in MultName) THEN
         (MultName[UBound(MultName)] = {MyReport.MyName};
         ReDim Preserve MultName[UBound(MultName)+1];))
ELSE
    (TotName[UBound(TotName)] = {MyReport.MyName};
    ReDim Preserve TotName[UBound(TotName)+1];)

This will look at the name of the record.  If it is already in the list of names, then it will look in the list of names listed multiple times.  If it is in both, it ignores it.  If it is in neither, it adds it to the total list.  If it is in the total list, but not the multiple list, it adds it to the multiple list.  Once it adds a name to a list, it also increases the size of that list by 1 to account for the next record to come in.

In the Report Footer, your "Only Once" formula will look like:

WhileReadingRecords

Global StringVar Array TotName;
Global StringVar Array MultName;

Count(TotName) - Count(MultName);


Your "More than Once" formula will look like:

WhileReadingRecords

Global StringVar Array TotName;
Global StringVar Array MultName;

Count(MultName);



Does that make sense?

IP IP Logged
MDRussell
Newbie
Newbie


Joined: 20 May 2008
Location: Canada
Online Status: Offline
Posts: 9
Quote MDRussell Replybullet Posted: 21 May 2008 at 7:13am
Lugh:

I think it makes sense.. but I'm not really sure where to put the array in the header.. do I put create a formula field in the header? or is it accessed through the section expert?

same with the details section I guess - where do I put the update array code?
IP IP Logged
Lugh
Senior Member
Senior Member
Avatar

Joined: 14 Nov 2007
Online Status: Offline
Posts: 377
Quote Lugh Replybullet Posted: 21 May 2008 at 11:06am
Yeah, you just create a formula field and put it in the section.  It doesn't return a value, so nothing will display.  Of course, you could just put it in a formatting formula somewhere, but that gets needlessly complicated and obscure.


IP IP Logged
MDRussell
Newbie
Newbie


Joined: 20 May 2008
Location: Canada
Online Status: Offline
Posts: 9
Quote MDRussell Replybullet Posted: 21 May 2008 at 11:19am
Lugh:

Ok, I created the header formula field and am getting an error when I try and save it. First, I had to add a ; at the end of "whilereadingrecords", because it was saying the rest wasn't part of the formula. Now, it's saying "the result of a formula cannot be an array"

here's the header formula with the added ";".

WhileReadingRecords;

Global StringVar Array TotName;
Global StringVar Array MultName;

ReDim TotName[1];
ReDim MultName[1];
IP IP Logged
MDRussell
Newbie
Newbie


Joined: 20 May 2008
Location: Canada
Online Status: Offline
Posts: 9
Quote MDRussell Replybullet Posted: 21 May 2008 at 2:03pm
nevermind, just found an article that says you have to state a "0;" at the end of a formula like that. Back I go! I'll report back soon :)
IP IP Logged
MDRussell
Newbie
Newbie


Joined: 20 May 2008
Location: Canada
Online Status: Offline
Posts: 9
Quote MDRussell Replybullet Posted: 21 May 2008 at 10:04pm
OK, Lugh, I got all the formulas in, but the result of both OnlyOnce and MoreThanOnce are both coming back as "1" - any thoughts?

I had to change the formula that went into the details section a bit because it was throwing errors.. maybe that's the problem?

Here it is..

WhileReadingRecords;

Global StringVar Array TotName;
Global StringVar Array MultName;

IF {ai_vew_report_aiaba.full_name} in TotName THEN
    (IF Not({ai_vew_report_aiaba.full_name} in MultName) THEN
         MultName[UBound(MultName)] = {ai_vew_report_aiaba.full_name};
          ReDim Preserve MultName[UBound(MultName)+1];)
ELSE
    (TotName[UBound(TotName)] = {ai_vew_report_aiaba.full_name};
    ReDim Preserve TotName[UBound(TotName)+1];);

0;

IP IP Logged
Lugh
Senior Member
Senior Member
Avatar

Joined: 14 Nov 2007
Online Status: Offline
Posts: 377
Quote Lugh Replybullet Posted: 22 May 2008 at 5:30am
Sorry about the buggy code.  Glad you figured it out.

My thought would be to test the condition structure.  Have it return a different integer based on which condition got fulfilled.  Like so:

WhileReadingRecords;

Global StringVar Array TotName;
Global StringVar Array MultName;

IF {ai_vew_report_aiaba.full_name} in TotName THEN
    (IF Not({ai_vew_report_aiaba.full_name} in MultName) THEN
         (MultName[UBound(MultName)] = {ai_vew_report_aiaba.full_name};
          ReDim Preserve MultName[UBound(MultName)+1];
            2;)
    ELSE 3;)
ELSE
    (TotName[UBound(TotName)] = {ai_vew_report_aiaba.full_name};
    ReDim Preserve TotName[UBound(TotName)+1];
    1;);


This should return 1 if this is the first time the name has come up, 2 if it's the second, and 3 if it's the third or more.  Make it visible on the report, and run a sanity check on it.

If this formula looks like it's working properly, then check the array in the footer.  Add a bit that looks like:

Local StringVar ArrayPrint := "";
Local NumberVar i;
For i := 1 to UBound(TotName) Do
    ArrayPrint = ArrayPrint + ";" + TotName;
ArrayPrint;

And do it again for MultName.  See if you are getting the names populated in there.  If you, say, only have the last name in there, then the ReDim process may not be working properly.  If you have no names in there, try changing it to WhilePrintingRecords, to see if it is perhaps trying to process the information too early.


IP IP Logged
Page  of 2 Next >>
Printable version Printable version

Forum Jump
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot delete your posts in this forum
You cannot edit your posts in this forum
You cannot create polls in this forum
You cannot vote in polls in this forum