fpspreadsheet: Some more rpn functions calculated (info, lookup/reference category)

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3277 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-07-04 09:03:49 +00:00
parent fb2b3159ea
commit 0b6819fe83
3 changed files with 343 additions and 70 deletions

View File

@ -41,22 +41,21 @@ type
function PopString(out AValue: String; out AErrArg: TsArgument): Boolean;
function PopStringValues(ANumArgs: Integer; ARangeAllowed:Boolean;
out AValues: TsArgStringArray; out AErrArg: TsArgument): Boolean;
procedure Push(AValue: TsArgument);
procedure PushBool(AValue: Boolean);
procedure Push(AValue: TsArgument; AWorksheet: TsWorksheet);
procedure PushBool(AValue: Boolean; AWorksheet: TsWorksheet);
procedure PushCell(AValue: PCell; AWorksheet: TsWorksheet);
procedure PushCellRange(AFirstRow, AFirstCol, ALastRow, ALastCol: Cardinal;
AWorksheet: TsWorksheet);
procedure PushMissing;
procedure PushNumber(AValue: Double);
procedure PushString(AValue: String);
procedure PushMissing(AWorksheet: TsWorksheet);
procedure PushNumber(AValue: Double; AWorksheet: TsWorksheet);
procedure PushString(AValue: String; AWorksheet: TsWorksheet);
procedure Clear;
procedure Delete(AIndex: Integer);
end;
function CreateBool(AValue: Boolean): TsArgument;
function CreateCell(AValue: PCell; AWorksheet: TsWorksheet): TsArgument;
function CreateCellRange(AFirstRow, AFirstCol, ALastRow, ALastCol: Cardinal;
AWorksheet: TsWorksheet): TsArgument;
function CreateCell(AValue: PCell): TsArgument;
function CreateCellRange(AFirstRow, AFirstCol, ALastRow, ALastCol: Cardinal): TsArgument;
function CreateNumber(AValue: Double): TsArgument;
function CreateString(AValue: String): TsArgument;
function CreateError(AError: TsErrorValue): TsArgument;
@ -156,14 +155,22 @@ 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;
{ lookup / reference }
function fpsCOLUMN (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsCOLUMNS (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsROW (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsROWS (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
{ info functions }
function fpsCELLINFO (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsINFO (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsISBLANK (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsISERR (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsISERROR (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsISLOGICAL (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsISNA (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsISNONTEXT (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsISNUMBER (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsISREF (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsISTEXT (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
function fpsVALUE (Args: TsArgumentStack; NumArgs: Integer): TsArgument;
@ -188,16 +195,14 @@ begin
Result.Boolvalue := AValue;
end;
function CreateCell(AValue: PCell; AWorksheet: TsWorksheet): TsArgument;
function CreateCell(AValue: PCell): TsArgument;
begin
Result := CreateArgument;
Result.ArgumentType := atCell;
Result.Cell := AValue;
Result.Worksheet := AWorksheet;
end;
function CreateCellRange(AFirstRow, AFirstCol, ALastRow, ALastCol: Cardinal;
AWorksheet: TsWorksheet): TsArgument;
function CreateCellRange(AFirstRow, AFirstCol, ALastRow, ALastCol: Cardinal): TsArgument;
begin
Result := CreateArgument;
Result.ArgumentType := atCellRange;
@ -205,7 +210,6 @@ begin
Result.FirstCol := AFirstCol;
Result.LastRow := ALastRow;
Result.LastCol := ALastCol;
Result.Worksheet := AWorksheet;
end;
function CreateNumber(AValue: Double): TsArgument;
@ -289,7 +293,7 @@ begin
Result := TsArgumentStack.Create;
for counter := 1 to ACount do begin
arg := Pop;
Result.Push(arg);
Result.Push(arg, arg.Worksheet);
end;
end;
@ -588,7 +592,7 @@ begin
end;
end;
procedure TsArgumentStack.Push(AValue: TsArgument);
procedure TsArgumentStack.Push(AValue: TsArgument; AWorksheet: TsWorksheet);
var
arg: PsArgument;
begin
@ -596,42 +600,43 @@ begin
arg^ := AValue;
arg^.StringValue := AValue.StringValue;
arg^.Cell := AValue.Cell;
arg^.Worksheet := AWorksheet;
Add(arg);
end;
procedure TsArgumentStack.PushBool(AValue: Boolean);
procedure TsArgumentStack.PushBool(AValue: Boolean; AWorksheet: TsWorksheet);
begin
Push(CreateBool(AValue));
Push(CreateBool(AValue), AWorksheet);
end;
procedure TsArgumentStack.PushCell(AValue: PCell; AWorksheet: TsWorksheet);
begin
Push(CreateCell(AValue, AWorksheet));
Push(CreateCell(AValue), AWorksheet);
end;
procedure TsArgumentStack.PushCellRange(AFirstRow, AFirstCol, ALastRow, ALastCol: Cardinal;
AWorksheet: TsWorksheet);
begin
Push(CreateCellRange(AFirstRow, AFirstCol, ALastRow, ALastCol, AWorksheet));
Push(CreateCellRange(AFirstRow, AFirstCol, ALastRow, ALastCol), AWorksheet);
end;
procedure TsArgumentStack.PushMissing;
procedure TsArgumentStack.PushMissing(AWorksheet: TsWorksheet);
var
arg: TsArgument;
begin
arg := CreateArgument;
arg.IsMissing := true;
Push(arg);
Push(arg, AWorksheet);
end;
procedure TsArgumentStack.PushNumber(AValue: Double);
procedure TsArgumentStack.PushNumber(AValue: Double; AWorksheet: TsWorksheet);
begin
Push(CreateNumber(AValue));
Push(CreateNumber(AValue), AWorksheet);
end;
procedure TsArgumentStack.PushString(AValue: String);
procedure TsArgumentStack.PushString(AValue: String; AWorksheet: TsWorksheet);
begin
Push(CreateString(AValue));
Push(CreateString(AValue), AWorksheet);
end;
@ -1811,6 +1816,80 @@ begin
end;
{ Lookup / refernence functions }
function fpsCOLUMN(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
{ COLUMN( [reference] )
Returns the column number of a cell reference (starting at 1).
"reference" is a reference to a cell or range of cells.
If omitted, it is assumed that the reference is the cell address in which the
COLUMN function has been entered in. }
var
arg: TsArgument;
begin
if NumArgs = 0 then
Result := CreateError(errArgError);
// We don't know here which cell contains the formula.
arg := Args.Pop;
case arg.ArgumentType of
atCell : Result := CreateNumber(arg.Cell^.Col + 1);
atCellRange: Result := CreateNumber(arg.FirstCol + 1);
else Result := CreateError(errWrongType);
end;
end;
function fpsCOLUMNS(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
{ COLUMNS( [reference] )
returns the number of column in a cell reference. }
var
arg: TsArgument;
begin
arg := Args.Pop;
case arg.ArgumentType of
atCell : Result := CreateNumber(1);
atCellRange: Result := CreateNumber(arg.LastCol - arg.FirstCol + 1);
else Result := CreateError(errWrongType);
end;
end;
function fpsROW(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
{ ROW( [reference] )
Returns the row number of a cell reference (starting at 1!)
"reference" is a reference to a cell or range of cells.
If omitted, it is assumed that the reference is the cell address in which the
ROW function has been entered in. }
var
arg: TsArgument;
begin
if NumArgs = 0 then
Result := CreateError(errArgError);
// We don't know here which cell contains the formula.
arg := Args.Pop;
case arg.ArgumentType of
atCell : Result := CreateNumber(arg.Cell^.Row + 1);
atCellRange: Result := CreateNumber(arg.FirstRow + 1);
else Result := CreateError(errWrongType);
end;
end;
function fpsROWS(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
{ ROWS( [reference] )
returns the number of rows in a cell reference. }
var
arg: TsArgument;
begin
arg := Args.Pop;
case arg.ArgumentType of
atCell : Result := CreateNumber(1);
atCellRange: Result := CreateNumber(arg.LastRow - arg.FirstRow + 1);
else Result := CreateError(errWrongType);
end;
end;
{ Info functions }
function fpsCELLINFO(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
@ -1978,6 +2057,51 @@ begin
end;
end;
function fpsINFO(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
{ INFO( type )
returns information about the operating environment.
type can be one of the following values:
+ "directory" Path of the current directory.
+ "numfile" Number of active worksheets.
- "origin" The cell that is in the top, left-most cell visible in the current Excel spreadsheet.
- "osversion" Operating system version.
- "recalc" Returns the recalculation mode - either Automatic or Manual.
- "release" Version of Excel that you are running.
- "system" Name of the operating environment.
ONLY THOSE MARKED BY "+" ARE SUPPORTED! }
var
arg: TsArgument;
workbook: TsWorkbook;
s: String;
begin
arg := Args.Pop;
if arg.ArgumentType <> atString then
Result := CreateError(errWrongType)
else begin
s := Lowercase(arg.StringValue);
workbook := arg.Worksheet.Workbook;
if s = 'directory' then
Result := CreateString(ExtractFilePath(workbook.FileName))
else
if s = 'numfile' then
Result := CreateNumber(workbook.GetWorksheetCount)
else
Result := CreateError(errFormulaNotSupported);
end;
end;
function fpsISBLANK(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// ISBLANK( value )
// Checks for blank cell
var
arg: TsArgument;
begin
arg := Args.Pop;
Result := CreateBool((arg.ArgumentType = atCell) and
((arg.Cell = nil) or (arg.Cell^.ContentType = cctEmpty))
);
end;
function fpsISERR(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// ISERR( value )
// If value is an error value (except #N/A), this function will return TRUE.
@ -2038,6 +2162,15 @@ begin
Result := CreateBool(arg.ArgumentType = atNumber);
end;
function fpsISREF(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// ISREF( value )
var
arg: TsArgument;
begin
arg := Args.Pop;
Result := CreateBool(arg.ArgumentType in [atCell, atCellRange]);
end;
function fpsISTEXT(Args: TsArgumentStack; NumArgs: Integer): TsArgument;
// ISTEXT( value )
var

View File

@ -697,6 +697,7 @@ type
FReadFormulas: Boolean;
FDefaultColWidth: Single; // in "characters". Excel uses the width of char "0" in 1st font
FDefaultRowHeight: Single; // in "character heights", i.e. line count
FFileName: String;
{ Internal methods }
procedure PrepareBeforeSaving;
@ -768,6 +769,8 @@ type
{@@ This property is only used for formats which don't support unicode
and support a single encoding for the whole document, like Excel 2 to 5 }
property Encoding: TsEncoding read FEncoding write FEncoding;
{@@ Filename of the saved workbook }
property FileName: String read FFileName;
{@@ Identifies the file format which was detected when reading the file }
property FileFormat: TsSpreadsheetFormat read FFormat;
{@@ This property allows to turn off reading of rpn formulas; this is a
@ -1211,11 +1214,11 @@ var
(Symbol:'VAR'; MinParams:1; MaxParams:30; Func:fpsVAR), // fekVAR
(Symbol:'VARP'; MinParams:1; MaxParams:30; Func:fpsVARP), // fekVARP
{ financial }
(Symbol:'FV'; MinParams:3; MaxParams:5; Func:nil), // fekFV
(Symbol:'NPER'; MinParams:3; MaxParams:5; Func:nil), // fekNPER
(Symbol:'PMT'; MinParams:3; MaxParams:5; Func:nil), // fekPMT
(Symbol:'PV'; MinParams:3; MaxParams:5; Func:nil), // fekPV
(Symbol:'RATE'; MinParams:3; MaxParams:6; Func:nil), // fekRATE
(Symbol:'FV'; MinParams:3; MaxParams:5; Func:nil), // fekFV
(Symbol:'NPER'; MinParams:3; MaxParams:5; Func:nil), // fekNPER
(Symbol:'PMT'; MinParams:3; MaxParams:5; Func:nil), // fekPMT
(Symbol:'PV'; MinParams:3; MaxParams:5; Func:nil), // fekPV
(Symbol:'RATE'; MinParams:3; MaxParams:6; Func:nil), // fekRATE
{ logical }
(Symbol:'AND'; MinParams:0; MaxParams:30; Func:fpsAND), // fekAND
(Symbol:'FALSE'; MinParams:0; MaxParams:0; Func:fpsFALSE), // fekFALSE
@ -1224,37 +1227,37 @@ var
(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: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:fpsMID), // fekMID
(Symbol:'PROPER'; MinParams:1; MaxParams:1; Func:nil), // 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
(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:fpsMID), // fekMID
(Symbol:'PROPER'; MinParams:1; MaxParams:1; Func:nil), // 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 }
(Symbol:'COLUMN'; MinParams:0; MaxParams:1; Func:nil), // fekCOLUMN
(Symbol:'COLUMNS'; MinParams:1; MaxParams:1; Func:nil), // fekCOLUMNS
(Symbol:'ROW'; MinParams:0; MaxParams:1; Func:nil), // fekROW
(Symbol:'ROWS'; MinParams:1; MaxParams:1; Func:nil), // fekROWS
(Symbol:'COLUMN'; MinParams:0; MaxParams:1; Func:fpsCOLUMN), // fekCOLUMN
(Symbol:'COLUMNS'; MinParams:1; MaxParams:1; Func:fpsCOLUMNS), // fekCOLUMNS
(Symbol:'ROW'; MinParams:0; MaxParams:1; Func:fpsROW), // fekROW
(Symbol:'ROWS'; MinParams:1; MaxParams:1; Func:fpsROWS), // fekROWS
{ info }
(Symbol:'CELL'; MinParams:1; MaxParams:2; Func:fpsCELLINFO), // fekCELLINFO
(Symbol:'INFO'; MinParams:1; MaxParams:1; Func:nil), // fekINFO
(Symbol:'ISBLANK'; MinParams:1; MaxParams:1; Func:nil), // fekIsBLANK
(Symbol:'ISERR'; MinParams:1; MaxParams:1; Func:fpsISERR), // fekIsERR
(Symbol:'ISERROR'; MinParams:1; MaxParams:1; Func:fpsISERROR), // fekIsERROR
(Symbol:'ISLOGICAL'; MinParams:1; MaxParams:1; Func:fpsISLOGICAL), // fekIsLOGICAL
(Symbol:'ISNA'; MinParams:1; MaxParams:1; Func:fpsISNA), // fekIsNA
(Symbol:'ISNONTEXT'; MinParams:1; MaxParams:1; Func:fpsISNONTEXT), // fekIsNONTEXT
(Symbol:'ISNUMBER'; MinParams:1; MaxParams:1; Func:fpsISNUMBER), // fekIsNUMBER
(Symbol:'ISREF'; MinParams:1; MaxParams:1; Func:nil), // fekIsRef
(Symbol:'ISTEXT'; MinParams:1; MaxParams:1; Func:fpsISTEXT), // fekIsTEXT
(Symbol:'VALUE'; MinParams:1; MaxParams:1; Func:fpsVALUE), // fekValue
(Symbol:'CELL'; MinParams:1; MaxParams:2; Func:fpsCELLINFO), // fekCELLINFO (*)
(Symbol:'INFO'; MinParams:1; MaxParams:1; Func:fpsINFO), // fekINFO (*)
(Symbol:'ISBLANK'; MinParams:1; MaxParams:1; Func:fpsISBLANK), // fekIsBLANK
(Symbol:'ISERR'; MinParams:1; MaxParams:1; Func:fpsISERR), // fekIsERR
(Symbol:'ISERROR'; MinParams:1; MaxParams:1; Func:fpsISERROR), // fekIsERROR
(Symbol:'ISLOGICAL'; MinParams:1; MaxParams:1; Func:fpsISLOGICAL), // fekIsLOGICAL
(Symbol:'ISNA'; MinParams:1; MaxParams:1; Func:fpsISNA), // fekIsNA
(Symbol:'ISNONTEXT'; MinParams:1; MaxParams:1; Func:fpsISNONTEXT), // fekIsNONTEXT
(Symbol:'ISNUMBER'; MinParams:1; MaxParams:1; Func:fpsISNUMBER), // fekIsNUMBER
(Symbol:'ISREF'; MinParams:1; MaxParams:1; Func:fpsISREF), // fekIsRef
(Symbol:'ISTEXT'; MinParams:1; MaxParams:1; Func:fpsISTEXT), // fekIsTEXT
(Symbol:'VALUE'; MinParams:1; MaxParams:1; Func:fpsVALUE), // fekValue
{ Other operations }
(Symbol:'SUM'; MinParams:1; MaxParams:1; Func:nil) // fekOpSUM (Unary sum operation). Note: CANNOT be used for summing sell contents; use fekSUM}
(Symbol:'SUM'; MinParams:1; MaxParams:1; Func:nil) // fekOpSUM (Unary sum operation). Note: CANNOT be used for summing sell contents; use fekSUM}
);
{@@
@ -1510,15 +1513,16 @@ begin
args := TsArgumentStack.Create;
try
for i := 0 to Length(ACell^.RPNFormulaValue) - 1 do begin
fe := ACell^.RPNFormulaValue[i]; // fe = "formula element"
fe := ACell^.RPNFormulaValue[i]; // "fe" means "formula element"
case fe.ElementKind of
fekCell, fekCellRef:
begin
cell := FindCell(fe.Row, fe.Col);
case cell^.CalcState of
csNotCalculated: CalcRPNFormula(cell);
csCalculating : raise Exception.Create(lpCircularReference);
end;
if cell <> nil then
case cell^.CalcState of
csNotCalculated: CalcRPNFormula(cell);
csCalculating : raise Exception.Create(lpCircularReference);
end;
args.PushCell(cell, self);
end;
fekCellRange:
@ -1535,15 +1539,15 @@ begin
args.PushCellRange(fe.Row, fe.Col, fe.Row2, fe.Col2, self);
end;
fekNum:
args.PushNumber(fe.DoubleValue);
args.PushNumber(fe.DoubleValue, self);
fekInteger:
args.PushNumber(1.0*fe.IntValue);
args.PushNumber(1.0*fe.IntValue, self);
fekString:
args.PushString(fe.StringValue);
args.PushString(fe.StringValue, self);
fekBool:
args.PushBool(fe.DoubleValue <> 0.0);
args.PushBool(fe.DoubleValue <> 0.0, self);
fekMissingArg:
args.PushMissing;
args.PushMissing(self);
fekParen: ; // visual effect only
fekErr:
exit;
@ -1562,7 +1566,7 @@ begin
// Result of function
val := func(args, fe.ParamsNum);
// Push result on stack for usage by next function or as final result
args.Push(val);
args.Push(val, self);
end; // case
end; // for
@ -3958,6 +3962,7 @@ var
begin
AReader := CreateSpreadReader(AFormat);
try
FFileName := AFileName;
AReader.ReadFromFile(AFileName, Self);
FFormat := AFormat;
finally
@ -4067,6 +4072,7 @@ var
begin
AWriter := CreateSpreadWriter(AFormat);
try
FFileName := AFileName;
PrepareBeforeSaving;
AWriter.WriteToFile(AFileName, AOverwriteExisting);
finally

View File

@ -1662,11 +1662,76 @@
sollValues[Row] := CreateString(UTF8UpperCase('Viele Grüße'));
{------------------------------------------------------------------------------}
{ Lookup / referece functions }
{------------------------------------------------------------------------------}
// COLUMN
MyWorksheet.WriteUTF8Text(Row, 0, '=COLUMN(A1)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNCellRef('A1',
RPNFunc(fekCOLUMN, 1, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateNumber(1);
MyWorksheet.WriteUTF8Text(Row, 0, '=COLUMN(C1:D3)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNCellRange('C1:D3',
RPNFunc(fekCOLUMN, 1, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateNumber(3);
// COLUMNS
MyWorksheet.WriteUTF8Text(Row, 0, '=COLUMNS(A1)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNCellRef('A1',
RPNFunc(fekCOLUMNS, 1, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateNumber(1);
MyWorksheet.WriteUTF8Text(Row, 0, '=COLUMNS(C1:D3)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNCellRange('C1:D3',
RPNFunc(fekCOLUMNS, 1, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateNumber(2);
// ROW
MyWorksheet.WriteUTF8Text(Row, 0, '=ROW(A1)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNCellRef('A1',
RPNFunc(fekROW, 1, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateNumber(1);
MyWorksheet.WriteUTF8Text(Row, 0, '=ROW(C2:D3)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNCellRange('C2:D3',
RPNFunc(fekROW, 1, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateNumber(2);
// ROWS
MyWorksheet.WriteUTF8Text(Row, 0, '=ROWS(A1)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNCellRef('A1',
RPNFunc(fekROWS, 1, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateNumber(1);
MyWorksheet.WriteUTF8Text(Row, 0, '=ROWS(C2:D3)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNCellRange('C2:D3',
RPNFunc(fekROWS, 1, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateNumber(2);
{------------------------------------------------------------------------------}
{ Information functions }
{------------------------------------------------------------------------------}
// INFO
// CELL
MyWorksheet.WriteUTF8Text(Row, 0, '=CELL("address", A1)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('address',
@ -1723,6 +1788,47 @@
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString('v');
// INFO
MyWorksheet.WriteUTF8Text(Row, 0, '=INFO("directory", A1)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('directory',
RPNFunc(fekINFO, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateString(ExtractFilePath(TempFile));
MyWorksheet.WriteUTF8Text(Row, 0, '=INFO("numfile")');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNString('numfile',
RPNFunc(fekINFO, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateNumber(MyWorkbook.GetWorksheetCount);
// IsBlank
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=ISBLANK(A1)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNCellRef('A1',
RPNFunc(fekISBLANK, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateBool(false); // cell contains text --> not blank
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=ISBLANK(G1)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNCellRef('G1',
RPNFunc(fekISBLANK, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateBool(true); // the cell does not exist --> blank
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=ISBLANK(H1)');
MyWorksheet.WriteBlank(0, 7); // A11 is an empty cell
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNCellRef('H1',
RPNFunc(fekISBLANK, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateBool(true); // the cell exists, but it is empty
// IsError
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=ISERROR(1/0)');
@ -1745,6 +1851,34 @@
SetLength(sollValues, Row+1);
sollValues[Row] := CreateBool(false);
// IsRef
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=ISREF(1)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNNumber(1,
RPNFunc(fekISREF, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateBool(false);
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=ISREF(A1)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNCellRef('A1',
RPNFunc(fekISREF, nil))));
SetLength(sollValues, Row+1);
sollValues[Row] := CreateBool(true);
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=ISREF(A1)');
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
RPNCellValue('A1', // we use a cell value here !
RPNFunc(fekISREF, nil))));
SetLength(sollValues, Row+1);
// The correct result would be "false" because a cell value is not the same as
// a cell reference. But Excel seems to ignore this difference here and
// accepts only a "true".
sollValues[Row] := CreateBool(true);
// VALUE
inc(Row);
MyWorksheet.WriteUTF8Text(Row, 0, '=VALUE("100")');