Formatting Formulas by Code? - crystal-reports

I have the following formula as the grouping for a Cross Tab Report:
{Command.Year} & ' ' & {Command.RF Period}
Year is a SmallInt and Period is a TinyInt.
The problem is that it shows on the report as:
2,009.00 9.00
The database values are actually:
2009 9
I can't remove the decimal places via formatting because they are in the formula together.
Ultimately I'd like it to be:
2009 09
Edit:
I found this link: http://www.kenhamady.com/form15.shtml
Now my code looks like this for period:
WhileReadingRecords;
StringVar text := Totext ( {Command.RF Period} , 6 , "" ) ; //put your numeric field in this line
NumberVar end := length ( text ) ;
NumberVar clip :=
(if Val ( text [ end - 6 to end ] ) = 0 then 1 else 0 ) +
(if Val ( text [ end - 5 to end ] ) = 0 then 1 else 0 ) +
(if Val ( text [ end - 4 to end ] ) = 0 then 1 else 0 ) +
(if Val ( text [ end - 3 to end ] ) = 0 then 1 else 0 ) +
(if Val ( text [ end - 2 to end ] ) = 0 then 1 else 0 ) +
(if Val ( text [ end - 1 to end ] ) = 0 then 1 else 0 ) +
(if Val ( text [ end - 0 to end ] ) = 0 then 1 else 0 ) ;
text [ 1 to Length ( text ) - clip ]
However, I don't use Crystal Language, I use VB. How do I append a 0 in front of the period if it does not begin with a 1?
The problem now is that September (9) shows up after October, Nov, and Dec because aphabetically 9 comes after 1.
Anybody?

The ToText function is very useful for this kind of thing, no loops required. In Crystal's VB Syntax :
Formula = ToText({Command.Year}, 0, "") & " " & ToText({Command.RF Period}, "00")
This should work if {Command.Year} and {Command.RF Period} are integers as you describe.

Related

Transform matrix to one-line representation for copy&paste

Suppose I have an output which is a large array, say 500x4.
I would like to transform this array into code form to create the same array.
An example:
output_array = randn(2,3)
output_array =
-0.2408 -0.9390 1.1794
-0.9064 0.1178 -0.4643
I would like to obtain:
input_array = [-0.2408 -0.9390 1.1794; -0.9064 0.1178 -0.4643]
For low dimensions, manual work is easy, but I would to be able to obtain the input code for arbitrary matrices.
Thanks.
This is one way:
a = randi(2,3)
linespec = [repmat('%d ',1,size(a,2)) '; ']
spec = strrep(['[ ' repmat(linespec,1,size(a,1)) ' ]'],'; ','')
b = sprintf(spec,a(:) )
a =
2 2 1
1 1 1
1 2 2
linespec =
%d %d %d ;
spec =
[ %d %d %d ; %d %d %d ; %d %d %d ]
b =
[ 2 1 1 ; 2 1 2 ; 1 1 2 ]
Be aware, that the number of spaces defined in ' ... ' snippets do matter!
use:
spec = ['b = ' strrep(['[ ' repmat(linespec,1,size(a,1)) ' ]'],'; ','') ]
to get:
b =
b = [ 1 2 2 ; 1 2 2 ; 1 2 1 ]
It could be interesting to wrap everything into a function:
function [ out ] = Matrix2String( a )
varname = inputname(1);
linespec = [repmat('%d ',1,size(a,2)) '; '];
spec = [varname ' = ' strrep(['[ ' repmat(linespec,1,size(a,1)) ' ]'],'; ','') ];
out = sprintf(spec,a(:) );
end
a call like:
a = randi(2,3)
Matrix2String(a)
would then return:
ans =
a = [ 2 1 1 ; 2 1 2 ; 1 1 1 ]

How to Remove special characters from name-value pairs in the Webspeed URL?

I need to remove carriage return and linefeed characters that are present in Webspeed URL containing name-value pairs..How can that be done? any ideas please!
To replace characters you can use the REPLACE function
REPLACE function
Returns a string with specified substring replacements.
Syntax
REPLACE ( source-string , from-string , to-string )
Example:
DEFINE VARIABLE cTxt AS CHARACTER NO-UNDO FORMAT "x(20)".
DEFINE VARIABLE cNewTxt AS CHARACTER NO-UNDO FORMAT "x(20)".
cTxt = "abc123abc123abc123".
cNewTxt = REPLACE(cTxt, "a", "-").
DISPLAY cNewTxt .
You could target new lines using the control code ~n
REPLACE(cString, "~n", "replacing character").
Or target the individual %0d (decimal ascii code 13) and %0a's (decimal ascii code 10).
REPLACE(cString, CHR(13), "replacing character").
REPLACE(cString, CHR(10), "replacing character").
I have recently had a need to do something like this and found the following to be quite handy. This might be a bit drastic -- it removes all control codes and anything higher than ascii 126. But you can adjust those limits easily enough. (My usage is to populate text fields -- so all of that stuff is illegal input for me.)
define variable hd as character no-undo initial "0123456789ABCDEF".
function hex2char returns character ( h as character ):
define variable i as integer no-undo.
if length( h ) <> 2 or index( hd, substring( h, 1, 1 )) < 0 or index( hd, substring( h, 2, 1 )) < 0 then
return "".
i = ((( index( hd, substring( h, 1, 1 )) - 1 ) * 16 ) +
index( hd, substring( h, 2, 1 )) - 1
).
if i < 32 or i >= 127 then
return "".
else
return chr( i ).
end.
function url-decode returns character ( input url as character ):
define variable xurl as character no-undo.
define variable zurl as character no-undo.
define variable pct as integer no-undo.
/* fix known trouble makers
*/
assign
xurl = replace( url, "+", " " )
xurl = replace( xurl, "%0A%0D", "~n" ) /* <LF><CR> */
xurl = replace( xurl, "%0D%0A", "~n" ) /* <CR><LF> */
xurl = replace( xurl, "%0D", "~n" ) /* <CR> */
.
pct = index( xurl, "%" ).
do while pct > 0 and xurl > "":
assign
zurl = zurl + substring( xurl, 1, pct - 1 ) + hex2char( substring( xurl, pct + 1, 2 ))
xurl = substring( xurl, pct + 3 )
pct = index( xurl, "%" )
.
end.
return zurl + xurl.
end.
display url-decode( sampleUrl ) view-as editor size 60 by 25.

FileMaker Divide by Zero Error

I have a Calculation field in my Results table that will calculate the coursework_percent based on a student's submission of classwork, homework, quiz, project and participation. The code for the Calculation field is this:
Sum ( Coursework_Results_Classwork::mark ) / If ( Sum ( Coursework_CR_Classwork::max_mark ) ≠ 0 ; Sum ( Coursework_CR_Classwork::max_mark ) - Sum ( Coursework_Results_Classwork::reduce_max ) ; 1 ) * Coursework_Weighting::classwork_w
+
Sum ( Coursework_Results_Homework::mark ) / If ( Sum ( Coursework_CR_Homework::max_mark ) ≠ 0 ; Sum ( Coursework_CR_Homework::max_mark ) - Sum ( Coursework_Results_Homework::reduce_max ) ; 1 ) * Coursework_Weighting::homework_w
+
Sum ( Coursework_Results_Quiz::mark ) / If ( Sum ( Coursework_CR_Quiz::max_mark ) ≠ 0 ; Sum ( Coursework_CR_Quiz::max_mark ) - Sum ( Coursework_Results_Quiz::reduce_max ) ; 1 ) * Coursework_Weighting::quiz_w
+
Sum ( Coursework_Results_Project::mark ) / If ( Sum ( Coursework_CR_Project::max_mark ) ≠ 0 ; Sum ( Coursework_CR_Project::max_mark ) - Sum ( Coursework_Results_Project::reduce_max ) ; 1 ) * Coursework_Weighting::project_w
+
Sum ( Coursework_Results_Participation::mark ) / If ( Sum ( Coursework_CR_Participation::max_mark ) ≠ 0 ; Sum ( Coursework_CR_Participation::max_mark ) - Sum ( Coursework_Results_Participation::reduce_max ) ) * Coursework_Weighting::participation_w
The idea behind the code is this:
If a student did not submit a coursework due to valid reason, he should not be penalised. Hence, his maximum mark should be adjusted accordingly. I used reduce_max to reduce his otherwise maximum possible score.
My bug is this:
If a particular category (e.g. homework) has only 1 assignment and the student did not submit with valid reason(hence an empty field), the calculated field will have a division by zero error. I cannot use a zero because zero is used for non-submission without valid reason. I suspect that the bug lies in my If condition testing for ≠ 0. An empty field is not considered a zero.
Can someone help me out? Thanks.
I amended pft's answer to solve my problem. The bug was not really due to empty field. Instead, it occurs when I use reduce_max such that the maximum of the coursework becomes zero. My solution is this:
Let ([
sumOfClasswork = Sum ( Coursework_Results_Classwork::mark );
sumOfHomework = Sum ( Coursework_Results_Homework::mark );
sumOfQuiz = Sum ( Coursework_Results_Quiz::mark );
sumOfProject = Sum ( Coursework_Results_Project::mark );
sumOfParticipation = Sum ( Coursework_Results_Participation::mark );
classworkMax = Sum ( Coursework_CR_Classwork::max_mark );
homeworkMax = Sum ( Coursework_CR_Homework::max_mark );
quizMax = Sum ( Coursework_CR_Quiz::max_mark );
projectMax = Sum ( Coursework_CR_Project::max_mark );
participationMax = Sum ( Coursework_CR_Participation::max_mark );
classworkReductions = Sum ( Coursework_Results_Classwork::reduce_max );
homeworkReductions = Sum ( Coursework_Results_Homework::reduce_max );
quizReductions = Sum ( Coursework_Results_Quiz::reduce_max );
projectReductions = Sum ( Coursework_Results_Project::reduce_max );
participationReductions = Sum ( Coursework_Results_Participation::reduce_max );
// if coursework maximum after reduction is zero, 1 is returned to avoid a division by zero error
classworkRedMax = If ( classworkMax - classworkReductions <> 0 ; classworkMax - classworkReductions ; 1 );
homeworkRedMax = If ( homeworkMax - homeworkReductions <> 0 ; homeworkMax - homeworkReductions ; 1 );
quizRedMax = If ( quizMax - quizReductions <> 0 ; quizMax - quizReductions ; 1 );
projectRedMax = If ( projectMax - projectReductions <> 0 ; projectMax - projectReductions ; 1 );
participationRedMax = If ( participationMax - participationReductions <> 0 ; participationMax - participationReductions ; 1 );
classworkWeight = Coursework_Weighting::classwork_w;
homeworkWeight = Coursework_Weighting::homework_w;
quizWeight = Coursework_Weighting::quiz_w;
projectWeight = Coursework_Weighting::project_w;
participationWeight = Coursework_Weighting::participation_w
];
// finally the computation of coursework ;)
sumOfClasswork / classworkRedMax * classworkWeight
+
sumOfHomework / homeworkRedMax * homeworkWeight
+
sumOfQuiz / quizRedMax * quizWeight
+
sumOfProject / projectRedMax * projectWeight
+
sumOfParticipation / participationRedMax * participationWeight
)
I believe the IsEmpty function should help you out here. If I understand your intention correctly, you could use this code segment:
Let ([
sumOfMarks = Sum ( Coursework_Results_Classwork::mark );
sumOfMaxs = Sum ( Coursework_CR_Classwork::max_mark );
sumOfReductions = Sum ( Coursework_Results_Classwork::reduce_max );
firstMax = Coursework_CR_Classwork::max_mark;
theWeight = Coursework_Weighting::classwork_w
];
Case (
// The case where the student has at least one valid,
// positively-scored assignment
sumOfMaxs > 0 ; sumOfMarks / (sumOfMaxs - sumOfReductions) ;
// The case where there is only one related record for max_mark
// and it is empty
IsEmpty ( firstMax ) ; 1
) * theWeight
)

How to find occurances of a string in crystal report?

I am trying to count the total number of (First column closed) Closed records. But I Get the result like 1.00 and 0.00 .
Desired results:
Code:
Local NumberVar str := 0;
Local NumberVar strLen := count({#Status});
Local NumberVar i;
For i := 1 To strLen Do (
If instr(i, {#Status}, "Closed") <> 0 Then
str := str + 1;
);
If(str > 0 ) Then str
You have two obvious options:
1) Running total with a evaluation expression: instr({#Status}, "Closed") <> 0 set to count
2) Create a new formula if instr({#Status}, "Closed") <> 0 then 1 else 0 then you can summarize that (either in a formula or using a "summary")
Your formula should be:
// formula's result might not always be 'Closed'
IIf( InStr({#Status}, "Closed") > 0, 1, 0 )
or
// formula's result is clean
IIf( {#Status}="Closed", 1, 0 )
** edit **
Insert a summary field that references this formula. By the way, this formula doesn't need to be added to the canvas to function correctly.

Crystal Reports Date Format

how can I format the day from a date field to print like 1st 2nd 3rd and so on? Thanks
I found a solution for this.
NumberVar DayIn := Day (PrintDate);
Totext (DayIn , 0 )
& (if DayIn in 4 to 20 then 'th' else
if remainder (DayIn , 10) = 1 then 'st' else
if remainder (DayIn , 10) = 2 then 'nd' else
if remainder (DayIn , 10) = 3 then 'rd' else 'th')
from http://www.kenhamady.com/news0910.shtml