You've already forked lazarus-ccr
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:
@ -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
|
||||
|
@ -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
|
||||
|
@ -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")');
|
||||
|
Reference in New Issue
Block a user