fpspreadsheet: (Almost) complete calculation of built-in rpn string function of fpspreadsheet (PROPER and SUBSTITUTE missing)

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3257 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-06-30 22:30:23 +00:00
parent 57036aa680
commit 734c816bd1
6 changed files with 419 additions and 24 deletions

View File

@ -107,14 +107,22 @@ function fpsNOT (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsOR (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsTRUE (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
{ String functions }
function fpsCHAR (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsCODE (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsLEFT (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsLOWER (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsMID (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsPROPER (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsREPLACE (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsRIGHT (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsSUBSTITUTE (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsTRIM (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsUPPER (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
implementation
uses
Math;
Math, lazutf8, StrUtils, fpsUtils;
type
TBoolArray = array of boolean;
@ -736,6 +744,7 @@ begin
end;
function fpsLOG(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// LOG( number, [base] )
var
arg_base, arg_number: TsArgument;
data: TFloatArray;
@ -869,6 +878,7 @@ end;
function fpsAVEDEV(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// Average value of absolute deviations of data from their mean.
// AVEDEV( argument1, [argument2, ... argument_n] )
var
data: TFloatArray;
m: Double;
@ -884,6 +894,7 @@ begin
end;
function fpsAVERAGE(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// AVERAGE( argument1, [argument2, ... argument_n] )
var
data: TFloatArray;
begin
@ -892,7 +903,9 @@ begin
end;
function fpsCOUNT(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
{ Count non-missing arguments }
{ Count non-missing arguments
COUNT( argument1, [argument2, ... argument_n] )
}
var
n, i: Integer;
begin
@ -903,6 +916,7 @@ begin
end;
function fpsMAX(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// MAX( number1, number2, ... number_n )
var
data: TFloatArray;
begin
@ -911,6 +925,7 @@ begin
end;
function fpsMIN(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// MIN( number1, number2, ... number_n )
var
data: TFloatArray;
begin
@ -919,6 +934,7 @@ begin
end;
function fpsPRODUCT(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// PRODUCT( number1, number2, ... number_n )
var
data: TFloatArray;
i: Integer;
@ -933,6 +949,7 @@ begin
end;
function fpsSTDEV(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// STDEV( number1, [number2, ... number_n] )
var
data: TFloatArray;
begin
@ -941,6 +958,7 @@ begin
end;
function fpsSTDEVP(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// STDEVP( number1, [number2, ... number_n] )
var
data: TFloatArray;
begin
@ -949,6 +967,7 @@ begin
end;
function fpsSUM(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// SUM( value1, [value2, ... value_n] )
var
data: TFloatArray;
begin
@ -957,6 +976,7 @@ begin
end;
function fpsSUMSQ(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// SUMSQ( value1, [value2, ... value_n] )
var
data: TFloatArray;
begin
@ -965,6 +985,7 @@ begin
end;
function fpsVAR(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// VAR( number1, number2, ... number_n )
var
data: TFloatArray;
begin
@ -973,6 +994,7 @@ begin
end;
function fpsVARP(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// VARP( number1, number2, ... number_n )
var
data: TFloatArray;
begin
@ -984,6 +1006,7 @@ end;
{ Logical functions }
function fpsAND(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// AND( condition1, [condition2], ... )
var
data: TBoolArray;
i: Integer;
@ -1002,11 +1025,13 @@ begin
end;
function fpsFALSE(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// FALSE( )
begin
Result := CreateBool(false);
end;
function fpsIF(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// IF( condition, [value_if_true], [value_if_false] )
var
condition: TsArgument;
case1, case2: TsArgument;
@ -1026,6 +1051,7 @@ begin
end;
function fpsNOT(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// NOT( logical_value )
var
data: TBoolArray;
begin
@ -1034,6 +1060,7 @@ begin
end;
function fpsOR(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// OR( condition1, [condition2], ... )
var
data: TBoolArray;
i: Integer;
@ -1052,6 +1079,7 @@ begin
end;
function fpsTRUE(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// TRUE ( )
begin
Result := CreateBool(true);
end;
@ -1059,28 +1087,191 @@ end;
{ String functions }
function fpsCHAR(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// CHAR( ascii_value )
var
data: TFloatArray;
begin
if PopFloatValues(Args, 1, data, Result) then begin
if (data[0] >= 0) and (data[0] <= 255) then
Result := CreateString(AnsiToUTF8(Char(Round(data[0]))));
end;
end;
function fpsCODE(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// CODE( text )
var
data: TStrArray;
begin
if PopStringValues(Args, 1, data, Result) then begin
if Length(data) > 0 then
Result := CreateNumber(Ord(UTF8ToAnsi(data[0])[1]))
else
Result := CreateEmpty;
end;
end;
function fpsLEFT(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// LEFT( text, [number_of_characters] )
var
arg1, arg2: TsArgument;
count: Integer;
s: String;
begin
count := 1;
if NumArgs = 2 then begin
arg2 := Args.Pop;
if not arg2.IsMissing then begin
if arg2.ArgumentType <> atNumber then begin
Result := createError(errWrongType);
exit;
end;
count := Round(arg2.NumberValue);
end;
end;
arg1 := Args.Pop;
if arg1.ArgumentType <> atString then begin
Result := CreateError(errWrongType);
exit;
end;
s := arg1.StringValue;
Result := CreateString(UTF8LeftStr(s, count));
end;
function fpsLOWER(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// LOWER( text )
var
data: TStrArray;
begin
if PopStringValues(Args, NumArgs, data, Result) then
Result := CreateString(lowercase(data[0]));
Result := CreateString(UTF8LowerCase(data[0]));
end;
function fpsMID(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// MID( text, start_position, number_of_characters )
var
fdata: TFloatArray;
sdata: TStrArray;
begin
if PopFloatValues(Args, 2, fdata, Result) then
if PopStringValues(Args, 1, sdata, Result) then
Result := CreateString(UTF8Copy(sdata[0], Round(fData[0]), Round(fdata[1])));
end;
function fpsPROPER(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// PROPER( text )
var
data: TStrArray;
begin
if PopStringValues(Args, 1, data, Result) then
Result := CreateString(UTF8ProperCase(data[0]));
end;
function fpsREPLACE(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// REPLACE( old_text, start, number_of_chars, new_text )
var
arg_new, arg_old, arg_start, arg_count: TsArgument;
s, s1, s2, snew: String;
p, count: Integer;
begin
arg_new := Args.Pop;
if arg_new.ArgumentType <> atString then begin
Result := CreateError(errWrongType);
exit;
end;
arg_count := Args.Pop;
if arg_count.ArgumentType <> atNumber then begin
Result := CreateError(errWrongType);
exit;
end;
arg_start := Args.Pop;
if arg_start.ArgumentType <> atNumber then begin
Result := CreateError(errWrongType);
exit;
end;
arg_old := Args.Pop;
if arg_old.ArgumentType <> atString then begin
Result := CreateError(errWrongType);
exit;
end;
s := arg_old.StringValue;
snew := arg_new.StringValue;
p := round(arg_start.NumberValue);
count := round(arg_count.NumberValue);
s1 := UTF8Copy(s, 1, p-1);
s2 := UTF8Copy(s, p+count, UTF8Length(s));
Result := CreateString(s1 + snew + s2);
end;
function fpsRIGHT(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// RIGHT( text, [number_of_characters] )
var
arg1, arg2: TsArgument;
count: Integer;
s: String;
begin
count := 1;
if NumArgs = 2 then begin
arg2 := Args.Pop;
if not arg2.IsMissing then begin
if arg2.ArgumentType <> atNumber then begin
Result := createError(errWrongType);
exit;
end;
count := round(arg2.NumberValue);
end;
end;
arg1 := Args.Pop;
if arg1.ArgumentType <> atString then begin
Result := CreateError(errWrongType);
exit;
end;
s := arg1.StringValue;
Result := CreateString(UTF8RightStr(s, count));
end;
function fpsSUBSTITUTE(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// SUBSTITUTE( text, old_text, new_text, [nth_appearance] )
var
data: TStrArray;
arg_n: TsArgument;
n: Integer;
begin
n := -1;
if NumArgs = 4 then begin
arg_n := Args.Pop;
if arg_n.ArgumentType <> atNumber then begin
Result := CreateError(errWrongType);
exit;
end;
n := round(arg_n.Numbervalue);
end;
if PopStringValues(Args, 3, data, Result) then begin
if n = -1 then
Result := CreateString(UTF8StringReplace(data[0], data[1], data[2], [rfReplaceall]))
else
raise Exception.Create('not implemented');
end;
end;
function fpsTRIM(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// TRIM( text )
var
data: TStrArray;
begin
if PopStringValues(Args, NumArgs, data, Result) then
Result := CreateString(trim(data[0]));
Result := CreateString(UTF8Trim(data[0]));
end;
function fpsUPPER(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// UPPER( text )
var
data: TStrArray;
begin
if PopStringValues(Args, NumArgs, data, Result) then
Result := CreateString(uppercase(data[0]));
Result := CreateString(UTF8UpperCase(data[0]));
end;
end.

View File

@ -1202,15 +1202,15 @@ const
(Symbol:'OR'; MinParams:1; MaxParams:30; Func:fpsOR), // fekOR
(Symbol:'TRUE'; MinParams:0; MaxParams:0; Func:fpsTRUE), // fekTRUE
{ string }
(Symbol:'CHAR'; MinParams:1; MaxParams:1; Func:nil), // fekCHAR
(Symbol:'CODE'; MinParams:1; MaxParams:1; Func:nil), // fekCODE
(Symbol:'LEFT'; MinParams:1; MaxParams:2; Func:nil), // fekLEFT
(Symbol:'CHAR'; MinParams:1; MaxParams:1; Func:fpsCHAR), // fekCHAR
(Symbol:'CODE'; MinParams:1; MaxParams:1; Func:fpsCODE), // fekCODE
(Symbol:'LEFT'; MinParams:1; MaxParams:2; Func:fpsLEFT), // fekLEFT
(Symbol:'LOWER'; MinParams:1; MaxParams:1; Func:fpsLOWER), // fekLOWER
(Symbol:'MID'; MinParams:3; MaxParams:3; Func:nil), // fekMID
(Symbol:'PROPER'; MinParams:1; MaxParams:1; Func:nil), // fekPROPER
(Symbol:'REPLACE'; MinParams:4; MaxParams:4; Func:nil), // fekREPLACE
(Symbol:'RIGHT'; MinParams:1; MaxParams:2; Func:nil), // fekRIGHT
(Symbol:'SUBSTITUTE';MinParams:3; MaxParams:4; Func:nil), // fekSUBSTITUTE
(Symbol:'MID'; MinParams:3; MaxParams:3; Func:fpsMID), // fekMID
(Symbol:'PROPER'; MinParams:1; MaxParams:1; Func:fpsPROPER), // fekPROPER
(Symbol:'REPLACE'; MinParams:4; MaxParams:4; Func:fpsREPLACE), // fekREPLACE
(Symbol:'RIGHT'; MinParams:1; MaxParams:2; Func:fpsRIGHT), // fekRIGHT
(Symbol:'SUBSTITUTE';MinParams:3; MaxParams:4; Func:fpsSUBSTITUTE), // fekSUBSTITUTE
(Symbol:'TRIM'; MinParams:1; MaxParams:1; Func:fpsTRIM), // fekTRIM
(Symbol:'UPPER'; MinParams:1; MaxParams:1; Func:fpsUPPER), // fekUPPER
{ lookup/reference }

View File

@ -77,6 +77,7 @@ function GetCellRangeString(ARow1, ACol1, ARow2, ACol2: Cardinal; AFlags: TsRelF
function GetErrorValueStr(AErrorValue: TsErrorValue): String;
function UTF8ProperCase(AText: String): String;
function UTF8TextToXMLText(AText: ansistring): ansistring;
function IfThen(ACondition: Boolean; AValue1,AValue2: TsNumberFormat): TsNumberFormat; overload;
@ -139,7 +140,7 @@ var
implementation
uses
Math;
Math, lazutf8;
{******************************************************************************}
{ Endianess helper functions }
@ -662,6 +663,42 @@ begin
end;
end;
{@@
Converts a string to "proper case", i.e. 1st character of each word is
upper-case, other characters are lowercase.
@param S String to be converted
@return String in proper case }
function UTF8ProperCase(AText: String): String;
begin
result := '';
end;
(*
const
Delims: TSysCharSet = ['0'..'9', ' ', '.', ',', ';', ':', '-', '_',
'<', '>', '|', '''', '#', '*', '+', '~', '!', '"', '§', '$', '%', '&', '/', '(', ')', '=',
'?', '\', '}', ']', '[', '{', '@'];
var
ch: String;
len, i, j: Integer;
res: string;
w: String;
p: Integer;
words: Array of String;
begin
AText := UTF8Lowercase(AText);
i := 0;
w := 'dummy';
Result := '';
while w <> '' do begin
w := ExtractWordPos(i, AText, Delims, p);
Result := UTF8Copy(AText, 1, p-1) + UTF8Uppercase(UTF8Copy(w, 1, 1)) +
UTF8Copy(w, 2, Length(w)-1);
inc(i);
end;
end;
*)
{@@
Converts a string encoded in UTF8 to a string usable in XML. For this purpose,
some characters must be translated.

View File

@ -49,7 +49,7 @@ type
implementation
uses
math, typinfo, fpsUtils, rpnFormulaUnit;
math, typinfo, lazUTF8, fpsUtils, rpnFormulaUnit;
{ TSpreadWriteReadFormatTests }

View File

@ -47,9 +47,6 @@
<UseExternalDbgSyms Value="True"/>
</Debugging>
</Linking>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
</Item2>
</BuildModes>
@ -129,7 +126,6 @@
<Unit12>
<Filename Value="rpnformulaunit.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="rpnFormulaUnit"/>
</Unit12>
<Unit13>
<Filename Value="formulatests.pas"/>
@ -139,7 +135,6 @@
<Unit14>
<Filename Value="emptycelltests.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="emptycelltests"/>
</Unit14>
</Units>
</ProjectOptions>
@ -159,9 +154,6 @@
<OptimizationLevel Value="0"/>
</Optimizations>
</CodeGeneration>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
<Debugging>
<Exceptions Count="6">

View File

@ -1045,6 +1045,63 @@
{ String functions }
{------------------------------------------------------------------------------}
// CHAR
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=CHAR(72)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNNumber(72,
RPNFunc(fekCHAR, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString(char(72));
// CODE
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=CODE("Hallo word")');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('Hallo world',
RPNFunc(fekCODE, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateNumber(ord('H'));
// LEFT (2 parameters)
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=LEFT("Hallo word", 2)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('Hallo world',
RPNNumber(2,
RPNFunc(fekLEFT, 2, nil)))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString('Ha');
// LEFT (2 parameters, utf8)
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=LEFT("Ändern", 3)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('Ändern',
RPNNumber(3,
RPNFunc(fekLEFT, 2, nil)))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString('Änd');
// LEFT (2 parameters, 1 of them missing)
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=LEFT("Hallo word", )');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('Hallo world',
RPNMissingArg(
RPNFunc(fekLEFT, 2, nil)))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString('H');
// LEFT (1 parameter)
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=LEFT("Hallo word")');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('Hallo world',
RPNFunc(fekLEFT, 1, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString('H');
// Lower case
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=LOWER("Hallo word")');
@ -1054,6 +1111,115 @@
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString(LowerCase('Hallo world'));
// Lower case / utf8
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=LOWER("Viele Grüße")');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('Viele Grüße',
RPNFunc(fekLOWER, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString(UTF8LowerCase('Viele Grüße'));
// MID
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=MID("Hallo word", 3, 2)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('Hallo world',
RPNNumber(3,
RPNNumber(2,
RPNFunc(fekMID, nil))))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString('ll');
// REPLACE
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=REPLACE("weather", 2, 2, "he")');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('weather',
RPNNumber(2,
RPNNumber(2,
RPNString('he',
RPNFunc(fekREPLACE, nil)))))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString('whether');
// REPLACE / utf8
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=REPLACE("würde", 2, 1, "u")');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('würde',
RPNNumber(2,
RPNNumber(1,
RPNString('u',
RPNFunc(fekREPLACE, nil)))))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString('wurde');
// RIGHT (2 parameters)
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=RIGHT("Hallo word", 2)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('Hallo world',
RPNNumber(2,
RPNFunc(fekRIGHT, 2, nil)))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString('ld');
// RIGHT (2 parameters, one of them missing)
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=RIGHT("Hallo word", )');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('Hallo world',
RPNMissingArg(
RPNFunc(fekRIGHT, 2, nil)))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString('d');
// RIGHT (1 parameter)
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=RIGHT("Hallo word")');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('Hallo world',
RPNFunc(fekRIGHT, 1, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString('d');
// SUBSTITUTE
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=SUBSTITUTE("lazarus", "s", "s.exe")');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('lazarus',
RPNString('s',
RPNString('s.exe',
RPNFunc(fekSUBSTITUTE, 3, nil))))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString('lazarus.exe');
// SUBSTITUTE
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=SUBSTITUTE("lAzArus", "A", "a")');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('lAzArus',
RPNString('A',
RPNString('a',
RPNFunc(fekSUBSTITUTE, 3, nil))))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString('lazarus');
// SUBSTITUTE / utf8
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=SUBSTITUTE("lÄzÄrus", "Ä", "a")');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('lÄzÄrus',
RPNString('Ä',
RPNString('a',
RPNFunc(fekSUBSTITUTE, 3, nil))))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString('lazarus');
// SUBSTITUTE / 4 parameters
// to do...
// Trim
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=TRIM(" Hallo word ")');
@ -1061,7 +1227,7 @@
RPNString(' Hallo world ',
RPNFunc(fekTRIM, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString(Trim(' Hallo world '));
sollValues[Row] := CreateString(UTF8Trim(' Hallo world '));
// Upper case
inc(Row);
@ -1072,3 +1238,12 @@
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString(UpperCase('Hallo world'));
// Upper case / utf8
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=UPPER("Viele Grüße")');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('Viele Grüße',
RPNFunc(fekUPPER, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString(UTF8UpperCase('Viele Grüße'));