crystal formula loop returns only last record - crystal-reports

using Crystal XI
I have two arrays - one captures a list of timepoints the other captures the times associated with them.
I need to associate the two so that the output looks like
timepoint[1] - time [1] - timepoint[2] - timepoint[2];
timepoint[3] - time[3] - timepoint[4] - timepoint[4];
so i wronte the following code - the arrays are intitialized in the header then loaded with data in the details section and then displayed in the group footer (three formula trick). I can display the data in the two arrays seperatly ok
(as timepoint[1], timepoint[2], etc)
the issue only arrises when trying to combine the two. the code below only prints the last two records in the array for the gorup instead of all of the records.
so if there are 5 timepoints and 5 times the code below displays
timepoint[4]-time[4] - timepoint[5]-time[5]
I will have to eventually perform a calculation between the two associated date times but for now just trying to get the association and display working.
Shared stringVar array Timepoints;
Shared DateTimeVar array Times;
local stringVar combineStr;
local numbervar i;
For i:=1 to UBound(Times)-2 do
(combineStr := Timepoints[i] + ','+ totext(Times[i]) + '-' +
Timepoints[i+1] + totext(Times[i+1]) + ',');
combineStr;
thanks for looking at this

You're overwriting the previous value of the combineStr variable with each iteration. You need to do this:
.
.
.
For i:=1 to UBound(Times)-2 do
(combineStr := combineStr + Timepoints[i] + ','+ totext(Times[i]) + '-' +
Timepoints[i+1] + totext(Times[i+1]) + ',');
combineStr;
A few other things: 1. You'll want to concatenate a newline character, chr(10), instead of a comma between iterations to display like your example in the question. 2. You need to add "step 2" to your for-loop otherwise you'll be printing out timepoints twice.

Related

mask a field with no fixed length in crystal reports 2008

I have a field in crystal reports that displays customer's names. the requirement however is to just display the first 5 characters, which includes spacing as well. whatever comes after the 5th character will be converted into * and the spacing shall be displayed as a space still. as the name field varies, how do i accomplish this?
currently i only have this, which displays the first 5 characters and replaces only the 6th character with an *
Replace({Command.CUST_NAME},MID({Command.CUST_NAME},6),"*")
Unfortunately, it seems Crystal does not suport regex.
So, i would do a function. Try this:
stringvar input := {Command.CUST_NAME};
stringvar output := MID(input, 1, 5);
numbervar i;
for i:=5 to Length (input) step 1 do (
stringvar aChar := MID(input, i, 1);
if aChar <> " " then aChar := "*";
output := output + aChar;
);
output
Maybe you will have to handle if {Command.CUST_NAME} is smaller than 5 chars.

Crystal Reports find the first 3 words of a string

I have a database field with strings like this
oh the sea OToole was right
I like ramen but
Rowing like a Blue but not an artist
They are actual words separated with space
I want to find to extract the first 3 words
The result would be like below
oh the sea
I like ramen
Rowing like a
I tried the following
ExtractString({tbname.field1},""," ") & " " & ExtractString({tbname.field1}," "," ") & ExtractString({tbname.field1}," "," ")
It did work for the the first two fields but not the second
I tried the one below too
split({tbname.field1}, " ")[1] & " " & split({tbname.field1}, " ")[2]
& " " & split({tbname.field1}, " ")[3]
It gives me an error saying the indice must be between 1 and the size of the array
Any insights are more than welcome
if ubound(Split({tbname.field1})) < 3 then
Join(Split({tbname.field1})[1 to ubound(Split({tbname.field1}))]," ")
else Join(Split({tbname.field1})[1 to 3]," ")
** edited to reflect data is contained in a single row, rather than 3 separate rows
Try:
// defined delimiter
Local Stringvar CRLF := Chr(10)+Chr(13);
// split CRLF-delimited string into an array
Local Stringvar Array rows := Split({Command.WORDS}, CRLF);
// the results of all the work
Local Stringvar Array results;
// process each 'row'
Local Numbervar i;
for i := 1 to ubound(rows) do (
// increment the array, then add first 3 words
Redim Preserve results[Ubound(results)+1];
results[ubound(results)]:=Join(Split(rows[i])[1 to 3]," ")
);
// create CRLF-delimited string
Join(results, CRLF);

Crystal Report formula issue :How to split multi line text value in to the array and how to fetch it by forloop in

I have one field in a dataset which has a multi-line textbox value. I want to split that record, store it into an array, and when I fetch the value from the array by a for-loop, I want to prepend a "*" to each line. I have written a formula for that but it's working only for 2 values. After that it's not working and I'm not able to get how to retrieve the value like this.
I want the result to be:
* 123
* 234
* 786
But I'm getting the result:
*123
234
786
my formula is
Local StringVar y;
Local StringVar x;
Local NumberVar i;
y := ""+ chrw(10);
x := y;
Stringvar Array strings := Split({Touche.Concerns}, "\r\n");
Stringvar Array numbers;
For i :=1 To Ubound(strings) Do
(
y := y + chrw(10)+ "$" + strings[i];
);
y;
Instead of a long formula which breaks into arrays and manipulates each line, why not just replace the line breaks with a line break and the asterisk?
"* " & replace(trim({Touche.Concerns}), "\r\n", "\r\n* ");
The leading '*' is to place the char on the first line and the trim function is called to remove any trailing line breaks (so there won't be a line with just the asterisk).
As a side note, use & when concatenating strings and not the + char. Use the + can sometimes cause coercion to where numeric values would be added together. For example "12" + "34" would yield 46 instead of 1234. The & char ensures string concatenation is used.

How to display date on a separate line

Question:
I used the custom date format(e.g., 4/22 11:00), and display these dates on the horizontal axis, however I want to split the date format( 4/22 11:00) into two lines,for instance,
4/22
11:00
Why do I want this
Date( 4/22 ) and time(11:00) are displayed at the distinct lines, which can easily differentiate date from time.
What did I try
I found an item "Wrap" in "Alignment", but it can't work.
Better late than ever, if you're still interested, there's a way.
You need to create a new calculated field, to generate the labels as you wish. If the field you're working if is called Date (for instance), you should do:
STR(DAY([Date])) + '/' + STR(MONTH([Date])) + '/' + STR(YEAR([Date]))
+
'
'
+
IF LEN(STR(DATEPART('hour',[Date]))) == 1
THEN '0' + STR(DATEPART('hour',[Date]))
ELSE STR(DATEPART('hour',[Date]))
END
+
':'
+
IF LEN(STR(DATEPART('minute',[Date]))) == 1
THEN '0' + STR(DATEPART('minute',[Date]))
ELSE STR(DATEPART('minute',[Date]))
END
First line is just to get the date on a d/m/y format. Then the trick is to add + '' separated by blank space (tried \n, but it prints "\n" instead of breaking the line)
The second part is to generate the hh:mm (you can use the same logic to get a dd/mm/yyyy format for the date). Basically it adds a zero if the hour or minute is a one digit number.

crystal reports trimming strings

I’m new on crystal reports and don’t have much knowledge of programming. I’m looking for a formula that will separate the notes (example: To Syd+We miss you+From Bill&Pat) into 3 different field. Any help would be greatly appreciated.
local stringVar subject := 'To Syd+We miss you+From Bill&Pat';
local numberVar location := instr(subject, '+');
if location > 0 then
left(subject, location)
else
subject;
I have hardcoded the string to be modified, but you can replace it with {table.field}
Also, if there will definitely always be + you can simplify things by removing the if.
a note that Lee's answer will get you the leftmost bit of text only.
instr(subject,"+") returns the location of the leftmost presence of +
left(subject,location) pulls out a chunk of subject of 'location' number of characters
if you then wanted to fish out the second and third bit, you could do this:
local stringvar subject := "string1+string2+string3";
local numberVar location1;
local numberVar location2;
location1 := instr(subject, "+");
location2 := instr(location1+1, subject, "+");
/////this instr only starts to look from location1 for the next leftmost + and I'll show below how you can use
( if location1 > 0
then left(subject, location1-1)
/////use Lee's 'left' command to bring up the first bit, I added the minus1 so that the actual + would not show
else "missing first +" )
+chrw(13)+ //I was displaying this on screen so I added a ENTER, you can get rid of this line
( if location2 > 0
/////error checking is sanity-saving sooner or later
then
(
mid(subject, location1+1, location2-1-location1)
/////pulls a chunk from within subject, starting at location1+1 [to get past the + at location1 itself],
/////going rightward to grab 'location2-1-location1' characters
/////(play a few times with the +1/-1 to get hte idea.
/////try it with a two-character seperator, say "To john12Hello12From jane", helped me get my head straight
+ chrw(13)+ //again, this is just for my proofing
right(subject, length(subject)-location2)
/////pulls a chunk from the right of subject, of size 'length of subject' minus location2,
/////so everything from the end until hit that +
)
else "missing second +" )