fpspreadsheet: Extend INDEX formula to return columns and rows. Add unit test for it.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9361 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
parent
a14eab917f
commit
af4a35901d
@ -855,6 +855,8 @@ function ArgToString(Arg: TsExpressionResult): String;
|
||||
procedure ArgsToFloatArray(const Args: TsExprParameterArray;
|
||||
out AData: TsExprFloatArray; out AError: TsErrorValue);
|
||||
function BooleanResult(AValue: Boolean): TsExpressionResult;
|
||||
function CellRangeResult(AWorksheet: TsBasicWorksheet; ASheet1Index, ASheet2Index: Integer;
|
||||
ARow1, ACol1, ARow2, ACol2: Cardinal): TsExpressionResult; overload;
|
||||
function CellResult(AValue: String): TsExpressionResult; overload;
|
||||
function CellResult(ACellRow, ACellCol: Cardinal): TsExpressionResult; overload;
|
||||
function DateTimeResult(AValue: TDateTime): TsExpressionResult;
|
||||
@ -4085,7 +4087,7 @@ end;
|
||||
|
||||
procedure TsFunctionCallBackExprNode.GetNodeValue(out AResult: TsExpressionResult);
|
||||
begin
|
||||
AResult.ResultType := NodeType; // was at end!
|
||||
AResult.ResultType := NodeType;
|
||||
if Length(FArgumentParams) > 0 then
|
||||
CalcParams;
|
||||
FCallBack(AResult, FArgumentParams);
|
||||
@ -4103,7 +4105,7 @@ end;
|
||||
|
||||
procedure TFPFunctionEventHandlerExprNode.GetNodeValue(out Result: TsExpressionResult);
|
||||
begin
|
||||
Result.ResultType := NodeType; // was at end
|
||||
Result.ResultType := NodeType;
|
||||
if Length(FArgumentParams) > 0 then
|
||||
CalcParams;
|
||||
FCallBack(Result, FArgumentParams);
|
||||
@ -4360,8 +4362,8 @@ begin
|
||||
FError := errOK;
|
||||
book := TsWorkbook(GetWorkbook);
|
||||
|
||||
F3dRange := ((ASheet1 <> '') and (ASheet2 <> '') { and (ASheet1 <> ASheet2)}) or
|
||||
((ASheet1 <> '') and (ASheet2 = ''));
|
||||
F3dRange := ((ASheet1 <> '') and (ASheet2 <> '')) or
|
||||
((ASheet1 <> '') and (ASheet2 = ''));
|
||||
|
||||
FSheetIndex[1] := book.GetWorksheetIndex(ASheet1);
|
||||
if (FSheetIndex[1] = -1) and (ASheet1 <> '') then
|
||||
@ -4858,6 +4860,20 @@ begin
|
||||
Result.ResBoolean := AValue;
|
||||
end;
|
||||
|
||||
function CellRangeResult(AWorksheet: TsBasicWorksheet;
|
||||
ASheet1Index, ASheet2Index: Integer;
|
||||
ARow1, ACol1, ARow2, ACol2: Cardinal): TsExpressionResult;
|
||||
begin
|
||||
Result.ResultType := rtCellRange;
|
||||
Result.Worksheet := AWorksheet; // Worksheet in which the formula sits
|
||||
Result.ResCellRange.Sheet1 := ASheet1Index;
|
||||
Result.ResCellRange.Sheet2 := ASheet2Index;
|
||||
Result.ResCellRange.Row1 := ARow1;
|
||||
Result.ResCellRange.Col1 := ACol1;
|
||||
Result.ResCellRange.Row2 := ARow2;
|
||||
Result.ResCellRange.Col2 := ACol2;
|
||||
end;
|
||||
|
||||
function CellResult(AValue: String): TsExpressionResult;
|
||||
var
|
||||
p: Integer;
|
||||
@ -4882,6 +4898,7 @@ begin
|
||||
Result.ResultType := rtCell;
|
||||
Result.ResRow := ACellRow;
|
||||
Result.ResCol := ACellCol;
|
||||
Result.Worksheet := nil;
|
||||
end;
|
||||
|
||||
function DateTimeResult(AValue: TDateTime): TsExpressionResult;
|
||||
@ -4934,6 +4951,8 @@ begin
|
||||
Result := (cell = nil) or (cell^.ContentType = cctEmpty) or
|
||||
((cell^.ContentType = cctUTF8String) and (cell^.UTF8StringValue = ''));
|
||||
end;
|
||||
rtCellRange:
|
||||
Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -4960,6 +4979,7 @@ begin
|
||||
Result := TryStrToInt64(cell^.UTF8StringValue, i);
|
||||
end;
|
||||
end;
|
||||
rtCellRange: Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -4974,6 +4994,7 @@ begin
|
||||
cell := (AValue.Worksheet as TsWorksheet).FindCell(AValue.ResRow, AValue.ResCol);
|
||||
Result := (cell <> nil) and (cell^.ContentType = cctUTF8String);
|
||||
end;
|
||||
rtCellRange: Result := false;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -2283,8 +2283,8 @@ end;
|
||||
Searches for a value in an array based on its coordinates.
|
||||
When the last parameter, col_no, is omitted, the input range must be a
|
||||
1-d vector, either a row or a column.
|
||||
The case of row_no or col_no equal to zero (returning the entire row or column)
|
||||
is not supported as FPSpreadsheet cannot return a cell range, so far. }
|
||||
Specification of row_no or col_no as zero returns the entire column or row
|
||||
within the range. }
|
||||
procedure fpsINDEX(var Result: TsExpressionResult; const Args: TsExprParameterArray);
|
||||
var
|
||||
rng: TsCellRange3d;
|
||||
@ -2319,6 +2319,22 @@ begin
|
||||
exit;
|
||||
row := ArgToInt(Args[1]) + rng.Row1 - 1; // The Args are relative to the range
|
||||
col := ArgToInt(Args[2]) + rng.Col1 - 1;
|
||||
if ArgToInt(Args[1]) = 0 then // entire column within range
|
||||
begin
|
||||
if (col >= rng.Col1) and (col <= rng.Col2) then
|
||||
Result := CellRangeResult(Args[0].Worksheet, rng.Sheet1, rng.Sheet2, rng.Row1, col, rng.Row2, col)
|
||||
else
|
||||
Result := ErrorResult(errIllegalRef);
|
||||
exit;
|
||||
end;
|
||||
if ArgToInt(Args[2]) = 0 then // entire row within range
|
||||
begin
|
||||
if (row >= rng.Row1) and (row <= rng.Row2) then
|
||||
Result := CellRangeResult(Args[0].Worksheet, rng.Sheet1, rng.Sheet2, row, rng.Col1, row, rng.Col2)
|
||||
else
|
||||
Result := ErrorResult(errIllegalRef);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
// Check whether col/row indices are inside the range
|
||||
@ -2330,6 +2346,7 @@ begin
|
||||
|
||||
book := TsWorksheet(Args[0].Worksheet).Workbook;
|
||||
Result := CellResult(row, col);
|
||||
Result.Worksheet := Args[0].Worksheet;
|
||||
Result.ResSheetIndex := rng.Sheet1;
|
||||
Result.ResSheetName := book.GetWorksheetByIndex(rng.Sheet1).Name;
|
||||
end;
|
||||
@ -2344,10 +2361,12 @@ procedure fpsINDIRECT(var Result: TsExpressionResult;
|
||||
interpreted as an R1C1-style reference.
|
||||
|
||||
NOTE: ref_style and mixing of A1 and R1C1 notation is not supported. }
|
||||
{
|
||||
var
|
||||
sheet: TsWorksheet;
|
||||
book: TsWorkbook;
|
||||
addr: String;
|
||||
}
|
||||
begin
|
||||
Result := ErrorResult(errArgError);
|
||||
if Length(Args) > 0 then
|
||||
|
@ -3482,6 +3482,20 @@
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := ErrorResult(errIllegalRef);
|
||||
|
||||
inc(Row);
|
||||
formula := 'SUM(INDEX(M1:O2,0,2))'; // Sum of numbers in 2nd column of M1:O2
|
||||
MyWorksheet.WriteText(Row, 0, formula);
|
||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := IntegerResult(2);
|
||||
|
||||
inc(Row);
|
||||
formula := 'SUM(INDEX(M1:O2,2,0))'; // Sum of numbers in 2nd row of M1:O2
|
||||
MyWorksheet.WriteText(Row, 0, formula);
|
||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := IntegerResult(6);
|
||||
|
||||
// INDIRECT
|
||||
inc(Row);
|
||||
formula := 'INDIRECT(P1)';
|
||||
|
Loading…
Reference in New Issue
Block a user