You've already forked lazarus-ccr
fpspreadsheet: Reactivate the expression parser test cases which were commented (and forgotten) some time ago. Activate missing argument tests. Add some "exotic" formulas. All passed.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4186 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -1259,14 +1259,6 @@ begin
|
|||||||
ParserError(SErrUnexpectedEndOfExpression);
|
ParserError(SErrUnexpectedEndOfExpression);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ If the result types differ, they are converted to a common type if possible. }
|
|
||||||
{
|
|
||||||
procedure TsExpressionParser.CheckNodes(var ALeft, ARight: TsExprNode);
|
|
||||||
begin
|
|
||||||
ALeft := MatchNodes(ALeft, ARight);
|
|
||||||
ARight := MatchNodes(ARight, ALeft);
|
|
||||||
end;
|
|
||||||
}
|
|
||||||
procedure TsExpressionParser.CheckResultType(const Res: TsExpressionResult;
|
procedure TsExpressionParser.CheckResultType(const Res: TsExpressionResult;
|
||||||
AType: TsResultType); inline;
|
AType: TsResultType); inline;
|
||||||
begin
|
begin
|
||||||
@ -1280,24 +1272,7 @@ begin
|
|||||||
FHashList.Clear;
|
FHashList.Clear;
|
||||||
FreeAndNil(FExprNode);
|
FreeAndNil(FExprNode);
|
||||||
end;
|
end;
|
||||||
(*
|
|
||||||
function TsExpressionParser.ConvertNode(ToDo: TsExprNode;
|
|
||||||
ToType: TsResultType): TsExprNode;
|
|
||||||
begin
|
|
||||||
Result := ToDo;
|
|
||||||
case ToDo.NodeType of
|
|
||||||
rtInteger :
|
|
||||||
case ToType of
|
|
||||||
rtFloat : Result := TsIntToFloatExprNode.Create(self, Result);
|
|
||||||
rtDateTime : Result := TsIntToDateTimeExprNode.Create(self, Result);
|
|
||||||
end;
|
|
||||||
rtFloat :
|
|
||||||
case ToType of
|
|
||||||
rtDateTime : Result := TsFloatToDateTimeExprNode.Create(self, Result);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
*)
|
|
||||||
{ Prepares copy mode: The formula is contained in ASourceCell and will be
|
{ Prepares copy mode: The formula is contained in ASourceCell and will be
|
||||||
modified such as seen from ADestCell. }
|
modified such as seen from ADestCell. }
|
||||||
procedure TsExpressionParser.PrepareCopyMode(ASourceCell, ADestCell: PCell);
|
procedure TsExpressionParser.PrepareCopyMode(ASourceCell, ADestCell: PCell);
|
||||||
@ -1487,7 +1462,6 @@ begin
|
|||||||
GetToken;
|
GetToken;
|
||||||
CheckEOF;
|
CheckEOF;
|
||||||
Right := Level3;
|
Right := Level3;
|
||||||
//CheckNodes(Result, right);
|
|
||||||
case tt of
|
case tt of
|
||||||
ttLessthan : C := TsLessExprNode;
|
ttLessthan : C := TsLessExprNode;
|
||||||
ttLessthanEqual : C := TsLessEqualExprNode;
|
ttLessthanEqual : C := TsLessEqualExprNode;
|
||||||
@ -1519,7 +1493,6 @@ begin
|
|||||||
GetToken;
|
GetToken;
|
||||||
CheckEOF;
|
CheckEOF;
|
||||||
right := Level4;
|
right := Level4;
|
||||||
//CheckNodes(Result, right);
|
|
||||||
case tt of
|
case tt of
|
||||||
ttPlus : Result := TsAddExprNode.Create(self, Result, right);
|
ttPlus : Result := TsAddExprNode.Create(self, Result, right);
|
||||||
ttMinus : Result := TsSubtractExprNode.Create(self, Result, right);
|
ttMinus : Result := TsSubtractExprNode.Create(self, Result, right);
|
||||||
@ -1545,7 +1518,6 @@ begin
|
|||||||
tt := TokenType;
|
tt := TokenType;
|
||||||
GetToken;
|
GetToken;
|
||||||
right := Level5;
|
right := Level5;
|
||||||
//CheckNodes(Result, right);
|
|
||||||
case tt of
|
case tt of
|
||||||
ttMul : Result := TsMultiplyExprNode.Create(self, Result, right);
|
ttMul : Result := TsMultiplyExprNode.Create(self, Result, right);
|
||||||
ttDiv : Result := TsDivideExprNode.Create(self, Result, right);
|
ttDiv : Result := TsDivideExprNode.Create(self, Result, right);
|
||||||
@ -1570,7 +1542,6 @@ begin
|
|||||||
tt := TokenType;
|
tt := TokenType;
|
||||||
GetToken;
|
GetToken;
|
||||||
right := Level6;
|
right := Level6;
|
||||||
//CheckNodes(Result, right);
|
|
||||||
Result := TsPowerExprNode.Create(self, Result, right);
|
Result := TsPowerExprNode.Create(self, Result, right);
|
||||||
end;
|
end;
|
||||||
except
|
except
|
||||||
@ -1581,13 +1552,10 @@ end;
|
|||||||
|
|
||||||
function TsExpressionParser.Level6: TsExprNode;
|
function TsExpressionParser.Level6: TsExprNode;
|
||||||
var
|
var
|
||||||
//isPlus, isMinus: Boolean;
|
|
||||||
signs: String;
|
signs: String;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
{$ifdef debugexpr} Writeln('Level 6 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
|
{$ifdef debugexpr} Writeln('Level 6 ',TokenName(TokenType),': ',CurrentToken);{$endif debugexpr}
|
||||||
// isPlus := false;
|
|
||||||
// isMinus := false;
|
|
||||||
signs := '';
|
signs := '';
|
||||||
while (TokenType in [ttPlus, ttMinus]) do
|
while (TokenType in [ttPlus, ttMinus]) do
|
||||||
begin
|
begin
|
||||||
@ -1595,10 +1563,6 @@ begin
|
|||||||
ttPlus : signs := signs + '+';
|
ttPlus : signs := signs + '+';
|
||||||
ttMinus : signs := signs + '-';
|
ttMinus : signs := signs + '-';
|
||||||
end;
|
end;
|
||||||
{
|
|
||||||
isPlus := (TokenType = ttPlus);
|
|
||||||
isMinus := (TokenType = ttMinus);
|
|
||||||
}
|
|
||||||
GetToken;
|
GetToken;
|
||||||
end;
|
end;
|
||||||
Result := Level7;
|
Result := Level7;
|
||||||
@ -1610,23 +1574,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
dec(i);
|
dec(i);
|
||||||
end;
|
end;
|
||||||
{
|
|
||||||
if isPlus then
|
|
||||||
Result := TsUPlusExprNode.Create(self, Result);
|
|
||||||
if isMinus then
|
|
||||||
Result := TsUMinusExprNode.Create(self, Result);
|
|
||||||
}
|
|
||||||
|
|
||||||
while TokenType = ttPercent do begin
|
while TokenType = ttPercent do begin
|
||||||
Result := TsPercentExprNode.Create(self, Result);
|
Result := TsPercentExprNode.Create(self, Result);
|
||||||
GetToken;
|
GetToken;
|
||||||
end;
|
end;
|
||||||
{
|
|
||||||
if TokenType = ttPercent then begin
|
|
||||||
Result := TsPercentExprNode.Create(self, Result);
|
|
||||||
GetToken;
|
|
||||||
end;
|
|
||||||
}
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsExpressionParser.Level7: TsExprNode;
|
function TsExpressionParser.Level7: TsExprNode;
|
||||||
@ -1653,53 +1605,7 @@ begin
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
Result := Primitive;
|
Result := Primitive;
|
||||||
{
|
|
||||||
if TokenType = ttPower then
|
|
||||||
begin
|
|
||||||
try
|
|
||||||
CheckEOF;
|
|
||||||
GetToken;
|
|
||||||
Right := Level1; //Primitive;
|
|
||||||
CheckNodes(Result, right);
|
|
||||||
Result := TsPowerExprNode.Create(self, Result, Right);
|
|
||||||
//GetToken;
|
|
||||||
except
|
|
||||||
Result.Free;
|
|
||||||
raise;
|
|
||||||
end;
|
|
||||||
end; }
|
|
||||||
{
|
|
||||||
if TokenType = ttPercent then begin
|
|
||||||
Result := TsPercentExprNode.Create(self, Result);
|
|
||||||
GetToken;
|
|
||||||
end;
|
|
||||||
}
|
|
||||||
end;
|
end;
|
||||||
(*
|
|
||||||
{ Checks types of todo and match. If ToDO can be converted to it matches
|
|
||||||
the type of match, then a node is inserted.
|
|
||||||
For binary operations, this function is called for both operands. }
|
|
||||||
function TsExpressionParser.MatchNodes(ToDo, Match: TsExprNode): TsExprNode;
|
|
||||||
var
|
|
||||||
TT, MT : TsResultType;
|
|
||||||
begin
|
|
||||||
Result := ToDo;
|
|
||||||
TT := ToDo.NodeType;
|
|
||||||
MT := Match.NodeType;
|
|
||||||
if TT <> MT then
|
|
||||||
begin
|
|
||||||
if TT = rtInteger then
|
|
||||||
begin
|
|
||||||
if (MT in [rtFloat, rtDateTime]) then
|
|
||||||
Result := ConvertNode(ToDo, MT);
|
|
||||||
end
|
|
||||||
else if (TT = rtFloat) then
|
|
||||||
begin
|
|
||||||
if (MT = rtDateTime) then
|
|
||||||
Result := ConvertNode(ToDo, rtDateTime);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end; *)
|
|
||||||
|
|
||||||
procedure TsExpressionParser.ParserError(Msg: String);
|
procedure TsExpressionParser.ParserError(Msg: String);
|
||||||
begin
|
begin
|
||||||
@ -2057,14 +1963,7 @@ begin
|
|||||||
CreateNodeFromRPN(FExprNode, index);
|
CreateNodeFromRPN(FExprNode, index);
|
||||||
if Assigned(FExprNode) then FExprNode.Check;
|
if Assigned(FExprNode) then FExprNode.Check;
|
||||||
end;
|
end;
|
||||||
(*
|
|
||||||
{ Signals that the parser is in SharedFormulaMode, i.e. there is an active cell
|
|
||||||
to which all relative addresses have to be adapted. }
|
|
||||||
function TsExpressionParser.SharedFormulaMode: Boolean;
|
|
||||||
begin
|
|
||||||
Result := (ActiveCell <> nil) and (ActiveCell^.SharedFormulaBase <> nil);
|
|
||||||
end;
|
|
||||||
*)
|
|
||||||
function TsExpressionParser.TokenType: TsTokenType;
|
function TsExpressionParser.TokenType: TsTokenType;
|
||||||
begin
|
begin
|
||||||
Result := FScanner.TokenType;
|
Result := FScanner.TokenType;
|
||||||
@ -2236,10 +2135,6 @@ begin
|
|||||||
if ID.ExcelCode = AExcelCode then exit;
|
if ID.ExcelCode = AExcelCode then exit;
|
||||||
dec(Result);
|
dec(Result);
|
||||||
end;
|
end;
|
||||||
{
|
|
||||||
while (Result >= 0) and (GetI(Result).ExcelCode = AExcelCode) do
|
|
||||||
dec(Result);
|
|
||||||
}
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsExprIdentifierDefs.SetI(AIndex: Integer;
|
procedure TsExprIdentifierDefs.SetI(AIndex: Integer;
|
||||||
@ -2816,16 +2711,7 @@ function TsUPlusExprNode.AsString: String;
|
|||||||
begin
|
begin
|
||||||
Result := '+' + TrimLeft(Operand.AsString);
|
Result := '+' + TrimLeft(Operand.AsString);
|
||||||
end;
|
end;
|
||||||
{
|
|
||||||
procedure TsUPlusExprNode.Check;
|
|
||||||
const
|
|
||||||
AllowedTokens = [rtInteger, rtFloat, rtCell, rtEmpty, rtError];
|
|
||||||
begin
|
|
||||||
inherited;
|
|
||||||
if not (Operand.NodeType in AllowedTokens) then
|
|
||||||
RaiseParserError(SErrNoUPlus, [ResultTypeName(Operand.NodeType), Operand.AsString])
|
|
||||||
end;
|
|
||||||
}
|
|
||||||
procedure TsUPlusExprNode.GetNodeValue(out Result: TsExpressionResult);
|
procedure TsUPlusExprNode.GetNodeValue(out Result: TsExpressionResult);
|
||||||
var
|
var
|
||||||
cell: PCell;
|
cell: PCell;
|
||||||
@ -2875,16 +2761,7 @@ function TsUMinusExprNode.AsString: String;
|
|||||||
begin
|
begin
|
||||||
Result := '-' + TrimLeft(Operand.AsString);
|
Result := '-' + TrimLeft(Operand.AsString);
|
||||||
end;
|
end;
|
||||||
{
|
|
||||||
procedure TsUMinusExprNode.Check;
|
|
||||||
const
|
|
||||||
AllowedTokens = [rtInteger, rtFloat, rtCell, rtEmpty, rtError];
|
|
||||||
begin
|
|
||||||
inherited;
|
|
||||||
if not (Operand.NodeType in AllowedTokens) then
|
|
||||||
RaiseParserError(SErrNoNegation, [ResultTypeName(Operand.NodeType), Operand.AsString])
|
|
||||||
end;
|
|
||||||
}
|
|
||||||
procedure TsUMinusExprNode.GetNodeValue(out Result: TsExpressionResult);
|
procedure TsUMinusExprNode.GetNodeValue(out Result: TsExpressionResult);
|
||||||
var
|
var
|
||||||
cell: PCell;
|
cell: PCell;
|
||||||
|
@ -212,7 +212,13 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Length(Args) = 2 then begin
|
if (Length(Args) = 2) then
|
||||||
|
begin
|
||||||
|
if (Args[1].ResultType = rtMissingArg) then
|
||||||
|
begin
|
||||||
|
Result := ErrorResult(errOverflow); // #NUM! as tested by Excel
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
base := ArgToFloat(Args[1]);
|
base := ArgToFloat(Args[1]);
|
||||||
if base < 0 then begin
|
if base < 0 then begin
|
||||||
Result := ErrorResult(errOverflow); // #NUM!
|
Result := ErrorResult(errOverflow); // #NUM!
|
||||||
@ -698,19 +704,19 @@ var
|
|||||||
begin
|
begin
|
||||||
s := ArgToString(Args[0]);
|
s := ArgToString(Args[0]);
|
||||||
if s = '' then
|
if s = '' then
|
||||||
Result.ResultType := rtEmpty
|
Result := EmptyResult
|
||||||
|
else
|
||||||
|
if Length(Args) > 2 then
|
||||||
|
Result := ErrorResult(errArgError)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
if Length(Args) = 1 then
|
if Length(Args) = 1 then
|
||||||
count := 1
|
count := 1
|
||||||
else
|
else
|
||||||
if Args[1].ResultType in [rtInteger, rtFloat] then
|
if Args[1].ResultType = rtMissingArg then
|
||||||
count := ArgToInt(Args[1])
|
count := 1
|
||||||
else
|
else
|
||||||
begin
|
count := ArgToInt(Args[1]);
|
||||||
Result := ErrorResult(errWrongType);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
Result := StringResult(UTF8LeftStr(s, count));
|
Result := StringResult(UTF8LeftStr(s, count));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -780,18 +786,19 @@ var
|
|||||||
begin
|
begin
|
||||||
s := ArgToString(Args[0]);
|
s := ArgToString(Args[0]);
|
||||||
if s = '' then
|
if s = '' then
|
||||||
Result.ResultType := rtEmpty
|
Result := EmptyResult
|
||||||
else begin
|
else
|
||||||
|
if Length(Args) > 2 then
|
||||||
|
Result := ErrorResult(errArgError)
|
||||||
|
else
|
||||||
|
begin
|
||||||
if Length(Args) = 1 then
|
if Length(Args) = 1 then
|
||||||
count := 1
|
count := 1
|
||||||
else
|
else
|
||||||
if Args[1].ResultType in [rtInteger, rtFloat] then
|
if Args[1].ResultType = rtMissingArg then
|
||||||
count := ArgToInt(Args[1])
|
count := 1
|
||||||
else
|
else
|
||||||
begin
|
count := ArgToInt(Args[1]);
|
||||||
Result := ErrorResult(errWrongType);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
Result := StringResult(UTF8RightStr(s, count));
|
Result := StringResult(UTF8RightStr(s, count));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -4347,25 +4347,25 @@ begin
|
|||||||
if FWorksheet.IsMergeBase(ACell) then
|
if FWorksheet.IsMergeBase(ACell) then
|
||||||
begin
|
begin
|
||||||
FWorksheet.FindMergedRange(ACell, r1, c1, r2, c2);
|
FWorksheet.FindMergedRange(ACell, r1, c1, r2, c2);
|
||||||
rowsSpannedStr := Format('table:number-rows-spanned="%d"', [r2 - r1 + 1]);
|
rowsSpannedStr := Format(' table:number-rows-spanned="%d"', [r2 - r1 + 1]);
|
||||||
colsSpannedStr := Format('table:number-columns-spanned="%d"', [c2 - c1 + 1]);
|
colsSpannedStr := Format(' table:number-columns-spanned="%d"', [c2 - c1 + 1]);
|
||||||
spannedStr := colsSpannedStr + ' ' + rowsSpannedStr;
|
spannedStr := colsSpannedStr + rowsSpannedStr;
|
||||||
end else
|
end else
|
||||||
spannedStr := '';
|
spannedStr := '';
|
||||||
|
|
||||||
fmt := FWorkbook.GetCellFormat(ACell^.FormatIndex);
|
fmt := FWorkbook.GetCellFormat(ACell^.FormatIndex);
|
||||||
if fmt.UsedFormattingFields <> [] then
|
if fmt.UsedFormattingFields <> [] then
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'<table:table-cell table:style-name="ce%d" %s>', [ACell^.FormatIndex, spannedStr]),
|
'<table:table-cell table:style-name="ce%d"%s>', [ACell^.FormatIndex, spannedStr]),
|
||||||
comment,
|
comment,
|
||||||
'</table:table-cell>')
|
'</table:table-cell>')
|
||||||
else
|
else
|
||||||
if comment <> '' then
|
if comment <> '' then
|
||||||
AppendToStream(AStream,
|
AppendToStream(AStream,
|
||||||
'<table:table-cell ' + spannedStr + '>' + comment + '</table:table-cell>')
|
'<table:table-cell' + spannedStr + '>' + comment + '</table:table-cell>')
|
||||||
else
|
else
|
||||||
AppendToStream(AStream,
|
AppendToStream(AStream,
|
||||||
'<table:table-cell ' + spannedStr + '/>');
|
'<table:table-cell' + spannedStr + '/>');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
@ -5086,9 +5086,9 @@ begin
|
|||||||
if FWorksheet.IsMergeBase(ACell) then
|
if FWorksheet.IsMergeBase(ACell) then
|
||||||
begin
|
begin
|
||||||
FWorksheet.FindMergedRange(ACell, r1, c1, r2, c2);
|
FWorksheet.FindMergedRange(ACell, r1, c1, r2, c2);
|
||||||
rowsSpannedStr := Format('table:number-rows-spanned="%d"', [r2 - r1 + 1]);
|
rowsSpannedStr := Format(' table:number-rows-spanned="%d"', [r2 - r1 + 1]);
|
||||||
colsSpannedStr := Format('table:number-columns-spanned="%d"', [c2 - c1 + 1]);
|
colsSpannedStr := Format(' table:number-columns-spanned="%d"', [c2 - c1 + 1]);
|
||||||
spannedStr := colsSpannedStr + ' ' + rowsSpannedStr;
|
spannedStr := colsSpannedStr + rowsSpannedStr;
|
||||||
end else
|
end else
|
||||||
spannedStr := '';
|
spannedStr := '';
|
||||||
|
|
||||||
@ -5111,39 +5111,39 @@ begin
|
|||||||
cctNumber:
|
cctNumber:
|
||||||
begin
|
begin
|
||||||
valuetype := 'float';
|
valuetype := 'float';
|
||||||
value := 'office:value="' + Format('%g', [ACell^.NumberValue], FPointSeparatorSettings) + '"';
|
value := ' office:value="' + Format('%g', [ACell^.NumberValue], FPointSeparatorSettings) + '"';
|
||||||
end;
|
end;
|
||||||
cctDateTime:
|
cctDateTime:
|
||||||
if trunc(ACell^.DateTimeValue) = 0 then
|
if trunc(ACell^.DateTimeValue) = 0 then
|
||||||
begin
|
begin
|
||||||
valuetype := 'time';
|
valuetype := 'time';
|
||||||
value := 'office:time-value="' + FormatDateTime(ISO8601FormatTimeOnly, ACell^.DateTimeValue) + '"';
|
value := ' office:time-value="' + FormatDateTime(ISO8601FormatTimeOnly, ACell^.DateTimeValue) + '"';
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
valuetype := 'date';
|
valuetype := 'date';
|
||||||
if frac(ACell^.DateTimeValue) = 0.0 then
|
if frac(ACell^.DateTimeValue) = 0.0 then
|
||||||
value := 'office:date-value="' + FormatDateTime(ISO8601FormatDateOnly, ACell^.DateTimeValue) + '"'
|
value := ' office:date-value="' + FormatDateTime(ISO8601FormatDateOnly, ACell^.DateTimeValue) + '"'
|
||||||
else
|
else
|
||||||
value := 'office:date-value="' + FormatDateTime(ISO8601FormatExtended, ACell^.DateTimeValue) + '"';
|
value := ' office:date-value="' + FormatDateTime(ISO8601FormatExtended, ACell^.DateTimeValue) + '"';
|
||||||
end;
|
end;
|
||||||
cctUTF8String:
|
cctUTF8String:
|
||||||
begin
|
begin
|
||||||
valuetype := 'string';
|
valuetype := 'string';
|
||||||
value := 'office:string-value="' + ACell^.UTF8StringValue +'"';
|
value := ' office:string-value="' + ACell^.UTF8StringValue +'"';
|
||||||
valueStr := '<text:p>' + ACell^.UTF8StringValue + '</text:p>';
|
valueStr := '<text:p>' + ACell^.UTF8StringValue + '</text:p>';
|
||||||
end;
|
end;
|
||||||
cctBool:
|
cctBool:
|
||||||
begin
|
begin
|
||||||
valuetype := 'boolean';
|
valuetype := 'boolean';
|
||||||
value := 'office:boolean-value="' + BoolToStr(ACell^.BoolValue, 'true', 'false') + '"';
|
value := ' office:boolean-value="' + BoolToStr(ACell^.BoolValue, 'true', 'false') + '"';
|
||||||
end;
|
end;
|
||||||
cctError:
|
cctError:
|
||||||
begin
|
begin
|
||||||
// Strange: but in case of an error, Open/LibreOffice always writes a
|
// Strange: but in case of an error, Open/LibreOffice always writes a
|
||||||
// float value 0 to the cell
|
// float value 0 to the cell
|
||||||
valuetype := 'float';
|
valuetype := 'float';
|
||||||
value := 'office:value="0"';
|
value := ' office:value="0"';
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -5154,7 +5154,7 @@ begin
|
|||||||
data type. Seems to work... }
|
data type. Seems to work... }
|
||||||
if FWorksheet.GetCalcState(ACell) = csCalculated then
|
if FWorksheet.GetCalcState(ACell) = csCalculated then
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'<table:table-cell table:formula="=%s" office:value-type="%s" %s %s %s>' +
|
'<table:table-cell table:formula="=%s" office:value-type="%s"%s%s%s>' +
|
||||||
comment +
|
comment +
|
||||||
valueStr +
|
valueStr +
|
||||||
'</table:table-cell>', [
|
'</table:table-cell>', [
|
||||||
@ -5163,7 +5163,7 @@ begin
|
|||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'<table:table-cell table:formula="=%s" %s %s', [
|
'<table:table-cell table:formula="=%s"%s%s', [
|
||||||
formula, lStyle, spannedStr]));
|
formula, lStyle, spannedStr]));
|
||||||
if comment <> '' then
|
if comment <> '' then
|
||||||
AppendToStream(AStream, '>' + comment + '</table:table-cell>')
|
AppendToStream(AStream, '>' + comment + '</table:table-cell>')
|
||||||
@ -5198,7 +5198,7 @@ begin
|
|||||||
// Style
|
// Style
|
||||||
fmt := FWorkbook.GetCellFormat(ACell^.FormatIndex);
|
fmt := FWorkbook.GetCellFormat(ACell^.FormatIndex);
|
||||||
if fmt.UsedFormattingFields <> [] then
|
if fmt.UsedFormattingFields <> [] then
|
||||||
lStyle := ' table:style-name="ce' + IntToStr(ACell^.FormatIndex) + '" '
|
lStyle := ' table:style-name="ce' + IntToStr(ACell^.FormatIndex) + '"'
|
||||||
else
|
else
|
||||||
lStyle := '';
|
lStyle := '';
|
||||||
|
|
||||||
@ -5209,9 +5209,9 @@ begin
|
|||||||
if FWorksheet.IsMergeBase(ACell) then
|
if FWorksheet.IsMergeBase(ACell) then
|
||||||
begin
|
begin
|
||||||
FWorksheet.FindMergedRange(ACell, r1, c1, r2, c2);
|
FWorksheet.FindMergedRange(ACell, r1, c1, r2, c2);
|
||||||
rowsSpannedStr := Format('table:number-rows-spanned="%d"', [r2 - r1 + 1]);
|
rowsSpannedStr := Format(' table:number-rows-spanned="%d"', [r2 - r1 + 1]);
|
||||||
colsSpannedStr := Format('table:number-columns-spanned="%d"', [c2 - c1 + 1]);
|
colsSpannedStr := Format(' table:number-columns-spanned="%d"', [c2 - c1 + 1]);
|
||||||
spannedStr := colsSpannedStr + ' ' + rowsSpannedStr;
|
spannedStr := colsSpannedStr + rowsSpannedStr;
|
||||||
end else
|
end else
|
||||||
spannedStr := '';
|
spannedStr := '';
|
||||||
|
|
||||||
@ -5253,7 +5253,7 @@ begin
|
|||||||
|
|
||||||
// Write it ...
|
// Write it ...
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'<table:table-cell office:value-type="string" %s %s>' +
|
'<table:table-cell office:value-type="string"%s%s>' +
|
||||||
comment +
|
comment +
|
||||||
textp +
|
textp +
|
||||||
'</table:table-cell>', [
|
'</table:table-cell>', [
|
||||||
@ -5298,7 +5298,7 @@ begin
|
|||||||
if (nfkCurrency in nfSection.Kind) then
|
if (nfkCurrency in nfSection.Kind) then
|
||||||
valtype := 'currency'
|
valtype := 'currency'
|
||||||
end;
|
end;
|
||||||
lStyle := ' table:style-name="ce' + IntToStr(ACell^.FormatIndex) + '" ';
|
lStyle := ' table:style-name="ce' + IntToStr(ACell^.FormatIndex) + '"';
|
||||||
end else
|
end else
|
||||||
lStyle := '';
|
lStyle := '';
|
||||||
|
|
||||||
@ -5309,9 +5309,9 @@ begin
|
|||||||
if FWorksheet.IsMergeBase(ACell) then
|
if FWorksheet.IsMergeBase(ACell) then
|
||||||
begin
|
begin
|
||||||
FWorksheet.FindMergedRange(ACell, r1, c1, r2, c2);
|
FWorksheet.FindMergedRange(ACell, r1, c1, r2, c2);
|
||||||
rowsSpannedStr := Format('table:number-rows-spanned="%d"', [r2 - r1 + 1]);
|
rowsSpannedStr := Format(' table:number-rows-spanned="%d"', [r2 - r1 + 1]);
|
||||||
colsSpannedStr := Format('table:number-columns-spanned="%d"', [c2 - c1 + 1]);
|
colsSpannedStr := Format(' table:number-columns-spanned="%d"', [c2 - c1 + 1]);
|
||||||
spannedStr := colsSpannedStr + ' ' + rowsSpannedStr;
|
spannedStr := colsSpannedStr + rowsSpannedStr;
|
||||||
end else
|
end else
|
||||||
spannedStr := '';
|
spannedStr := '';
|
||||||
|
|
||||||
@ -5330,7 +5330,7 @@ begin
|
|||||||
FWorkbook.AddErrorMsg(rsODSHyperlinksOfTextCellsOnly, [GetCellString(ARow, ACol)]);
|
FWorkbook.AddErrorMsg(rsODSHyperlinksOfTextCellsOnly, [GetCellString(ARow, ACol)]);
|
||||||
|
|
||||||
AppendToStream(AStream, Format(
|
AppendToStream(AStream, Format(
|
||||||
'<table:table-cell office:value-type="%s" office:value="%s" %s %s >' +
|
'<table:table-cell office:value-type="%s" office:value="%s"%s%s >' +
|
||||||
comment +
|
comment +
|
||||||
'<text:p>%s</text:p>' +
|
'<text:p>%s</text:p>' +
|
||||||
'</table:table-cell>', [
|
'</table:table-cell>', [
|
||||||
|
@ -1518,7 +1518,9 @@ begin
|
|||||||
(Pos('<', AppoSt) = 1) or
|
(Pos('<', AppoSt) = 1) or
|
||||||
(Pos('>', AppoSt) = 1) or
|
(Pos('>', AppoSt) = 1) or
|
||||||
(Pos('"', AppoSt) = 1) or
|
(Pos('"', AppoSt) = 1) or
|
||||||
(Pos(''', AppoSt) = 1) then begin
|
(Pos(''', AppoSt) = 1) or
|
||||||
|
(Pos('%', AppoSt) = 1) // %
|
||||||
|
then begin
|
||||||
//'&' is the first char of a special chat, it must not be converted
|
//'&' is the first char of a special chat, it must not be converted
|
||||||
WrkStr:=WrkStr + AText[Idx];
|
WrkStr:=WrkStr + AText[Idx];
|
||||||
end else begin
|
end else begin
|
||||||
@ -1529,6 +1531,7 @@ begin
|
|||||||
'>': WrkStr:=WrkStr + '>';
|
'>': WrkStr:=WrkStr + '>';
|
||||||
'"': WrkStr:=WrkStr + '"';
|
'"': WrkStr:=WrkStr + '"';
|
||||||
'''':WrkStr:=WrkStr + ''';
|
'''':WrkStr:=WrkStr + ''';
|
||||||
|
'%': WrkStr:=WrkStr + '%';
|
||||||
{
|
{
|
||||||
#10: WrkStr := WrkStr + ' ';
|
#10: WrkStr := WrkStr + ' ';
|
||||||
#13: WrkStr := WrkStr + ' ';
|
#13: WrkStr := WrkStr + ' ';
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
MyWorksheet.WriteNumber (1, 12, 1); // M2
|
MyWorksheet.WriteNumber (1, 12, 1); // M2
|
||||||
MyWorksheet.WriteNumber (1, 13, 2); // N2
|
MyWorksheet.WriteNumber (1, 13, 2); // N2
|
||||||
|
|
||||||
|
// Create an error in H2
|
||||||
|
MyWorksheet.WriteFormula (1, 7, '1/0');
|
||||||
{------------------------------------------------------------------------------}
|
{------------------------------------------------------------------------------}
|
||||||
{ Basic operations }
|
{ Basic operations }
|
||||||
{------------------------------------------------------------------------------}
|
{------------------------------------------------------------------------------}
|
||||||
@ -52,7 +54,7 @@
|
|||||||
{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
!! DO NOT CHANGE THIS FORMULA - ITS RESULT (-9) IS HARD-CODED IN OTHER TESTS !!
|
!! DO NOT CHANGE THIS FORMULA - ITS RESULT (-9) IS HARD-CODED IN OTHER TESTS !!
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
|
||||||
(*
|
|
||||||
// Add cell values - relative addresses
|
// Add cell values - relative addresses
|
||||||
inc(Row);
|
inc(Row);
|
||||||
formula := 'B1+B2';
|
formula := 'B1+B2';
|
||||||
@ -317,6 +319,23 @@
|
|||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
sollValues[Row] := FloatResult(4 * power(2, 0.5));
|
sollValues[Row] := FloatResult(4 * power(2, 0.5));
|
||||||
|
|
||||||
|
// Exotic sample from OpenOffice test files
|
||||||
|
inc(Row);
|
||||||
|
formula := '50%^200%';
|
||||||
|
MyWorksheet.WriteUTF8Text(Row, 0, formula);
|
||||||
|
if UseRPNFormula then
|
||||||
|
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||||
|
RPNNumber(50.0,
|
||||||
|
RPNFunc(fekPercent,
|
||||||
|
RPNNumber(200.0,
|
||||||
|
RPNFunc(fekPercent,
|
||||||
|
RPNFunc(fekPower, nil)))))))
|
||||||
|
else
|
||||||
|
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||||
|
MyWorksheet.WriteNumber(Row, 2, power(0.5, 2));
|
||||||
|
SetLength(sollValues, Row+1);
|
||||||
|
sollValues[Row] := FloatResult(power(0.5, 2));
|
||||||
|
|
||||||
// Power function
|
// Power function
|
||||||
if AFormat <> sfExcel2 then begin
|
if AFormat <> sfExcel2 then begin
|
||||||
// Power of constant
|
// Power of constant
|
||||||
@ -428,6 +447,21 @@
|
|||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
sollValues[Row] := FloatResult(+cellB2);
|
sollValues[Row] := FloatResult(+cellB2);
|
||||||
|
|
||||||
|
// Exotic case from OpenOffice test files
|
||||||
|
inc(Row);
|
||||||
|
formula := '+-B2';
|
||||||
|
MyWorksheet.WriteUTF8Text(Row, 0, formula);
|
||||||
|
if UseRPNFormula then
|
||||||
|
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||||
|
RPNCellvalue('B2',
|
||||||
|
RPNFunc(fekUMinus,
|
||||||
|
RPNFunc(fekUPlus, nil)))))
|
||||||
|
else
|
||||||
|
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||||
|
MyWorksheet.WriteNumber(Row, 2, -cellB2);
|
||||||
|
SetLength(sollValues, Row+1);
|
||||||
|
sollValues[Row] := FloatResult(-cellB2);
|
||||||
|
|
||||||
// String result
|
// String result
|
||||||
inc(Row);
|
inc(Row);
|
||||||
formula := '"Hallo"';
|
formula := '"Hallo"';
|
||||||
@ -1364,11 +1398,9 @@
|
|||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
sollValues[Row] := FloatResult(logn(2, number));
|
sollValues[Row] := FloatResult(logn(2, number));
|
||||||
|
|
||||||
{ removed until new formula system supports missing arguments...
|
// LOG - error result (2 arguments, base missing)
|
||||||
|
|
||||||
// LOG - valid result (2 arguments, base missing)
|
|
||||||
inc(Row);
|
inc(Row);
|
||||||
formula := 'LOG(0.1, )';
|
formula := 'LOG(0.1,)';
|
||||||
MyWorksheet.WriteUTF8Text(Row, 0, formula);
|
MyWorksheet.WriteUTF8Text(Row, 0, formula);
|
||||||
if UseRPNFormula then
|
if UseRPNFormula then
|
||||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||||
@ -1383,7 +1415,6 @@
|
|||||||
sollValues[Row] := FloatResult(0)
|
sollValues[Row] := FloatResult(0)
|
||||||
else
|
else
|
||||||
sollValues[Row] := ErrorResult(errOverflow);
|
sollValues[Row] := ErrorResult(errOverflow);
|
||||||
}
|
|
||||||
|
|
||||||
// LOG - valid result (1 argument)
|
// LOG - valid result (1 argument)
|
||||||
inc(Row);
|
inc(Row);
|
||||||
@ -3001,7 +3032,7 @@
|
|||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
sollValues[Row] := StringResult('Ha');
|
sollValues[Row] := StringResult('Ha');
|
||||||
Myworksheet.WriteUTF8Text(Row, 2, sollValues[Row].ResString);
|
Myworksheet.WriteUTF8Text(Row, 2, sollValues[Row].ResString);
|
||||||
*)
|
|
||||||
// LEFT (2 parameters, utf8)
|
// LEFT (2 parameters, utf8)
|
||||||
inc(Row);
|
inc(Row);
|
||||||
formula := 'LEFT("Ändern",3)';
|
formula := 'LEFT("Ändern",3)';
|
||||||
@ -3017,7 +3048,6 @@
|
|||||||
sollValues[Row] := StringResult('Änd');
|
sollValues[Row] := StringResult('Änd');
|
||||||
Myworksheet.WriteUTF8Text(Row, 2, sollValues[Row].ResString);
|
Myworksheet.WriteUTF8Text(Row, 2, sollValues[Row].ResString);
|
||||||
|
|
||||||
{ -- at the momement no missing arguments support
|
|
||||||
// LEFT (2 parameters, 1 of them missing)
|
// LEFT (2 parameters, 1 of them missing)
|
||||||
inc(Row);
|
inc(Row);
|
||||||
formula := 'LEFT("Hallo world",)';
|
formula := 'LEFT("Hallo world",)';
|
||||||
@ -3032,7 +3062,7 @@
|
|||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
sollValues[Row] := StringResult('H');
|
sollValues[Row] := StringResult('H');
|
||||||
Myworksheet.WriteUTF8Text(Row, 2, sollValues[Row].ResString);
|
Myworksheet.WriteUTF8Text(Row, 2, sollValues[Row].ResString);
|
||||||
}
|
|
||||||
// LEFT (1 parameter)
|
// LEFT (1 parameter)
|
||||||
inc(Row);
|
inc(Row);
|
||||||
formula := 'LEFT("Hallo world")';
|
formula := 'LEFT("Hallo world")';
|
||||||
@ -3169,10 +3199,9 @@
|
|||||||
sollValues[Row] := StringResult('ld');
|
sollValues[Row] := StringResult('ld');
|
||||||
Myworksheet.WriteUTF8Text(Row, 2, sollValues[Row].ResString);
|
Myworksheet.WriteUTF8Text(Row, 2, sollValues[Row].ResString);
|
||||||
|
|
||||||
{ --- no missing parameter support now
|
|
||||||
// RIGHT (2 parameters, one of them missing)
|
// RIGHT (2 parameters, one of them missing)
|
||||||
inc(Row);
|
inc(Row);
|
||||||
formula := 'RIGHT("Hallo world", )';
|
formula := 'RIGHT("Hallo world",)';
|
||||||
MyWorksheet.WriteUTF8Text(Row, 0, formula);
|
MyWorksheet.WriteUTF8Text(Row, 0, formula);
|
||||||
if UseRPNFormula then
|
if UseRPNFormula then
|
||||||
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||||
@ -3184,7 +3213,6 @@
|
|||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
sollValues[Row] := StringResult('d');
|
sollValues[Row] := StringResult('d');
|
||||||
Myworksheet.WriteUTF8Text(Row, 2, sollValues[Row].ResString);
|
Myworksheet.WriteUTF8Text(Row, 2, sollValues[Row].ResString);
|
||||||
}
|
|
||||||
|
|
||||||
// RIGHT (1 parameter)
|
// RIGHT (1 parameter)
|
||||||
inc(Row);
|
inc(Row);
|
||||||
@ -3444,8 +3472,37 @@
|
|||||||
SetLength(sollValues, Row+1);
|
SetLength(sollValues, Row+1);
|
||||||
sollValues[Row] := CreateNumberArg(MyWorkbook.GetWorksheetCount);
|
sollValues[Row] := CreateNumberArg(MyWorkbook.GetWorksheetCount);
|
||||||
*)
|
*)
|
||||||
// IsBlank
|
|
||||||
|
|
||||||
|
// ERROR.TYPE
|
||||||
|
(* ---- fails for ODS ---> to be checked
|
||||||
|
inc(Row);
|
||||||
|
formula := 'ERROR.TYPE(A1)';
|
||||||
|
MyWorksheet.WriteUTF8Text(Row, 0, formula);
|
||||||
|
if UseRPNFormula then
|
||||||
|
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||||
|
RPNCellRef('A1',
|
||||||
|
RPNFUNC('ERROR.TYPE', nil))))
|
||||||
|
else
|
||||||
|
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||||
|
SetLength(sollvalues, Row+1);
|
||||||
|
sollValues[Row] := ErrorResult(errArgError);
|
||||||
|
MyWorksheet.WriteUTF8Text(Row, 2, '#N/A');
|
||||||
|
|
||||||
|
inc(Row);
|
||||||
|
formula := 'ERROR.TYPE(H2)'; // this cells contains "1/0" --> #DIV/0!
|
||||||
|
MyWorksheet.WriteUTF8Text(Row, 0, formula);
|
||||||
|
if UseRPNFormula then
|
||||||
|
MyWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||||
|
RPNCellRef('H2',
|
||||||
|
RPNFUNC('ERROR.TYPE', nil))))
|
||||||
|
else
|
||||||
|
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||||
|
SetLength(sollvalues, Row+1);
|
||||||
|
sollValues[Row] := IntegerResult(ord(errDivideByZero));
|
||||||
|
MyWorksheet.WriteUTF8Text(Row, 2, IntToStr(ord(errDivideByZero)));
|
||||||
|
*)
|
||||||
|
|
||||||
|
// IsBlank
|
||||||
inc(Row);
|
inc(Row);
|
||||||
formula := 'ISBLANK(A1)';
|
formula := 'ISBLANK(A1)';
|
||||||
MyWorksheet.WriteUTF8Text(Row, 0, formula);
|
MyWorksheet.WriteUTF8Text(Row, 0, formula);
|
||||||
@ -3489,7 +3546,6 @@
|
|||||||
// IsErr
|
// IsErr
|
||||||
inc(Row);
|
inc(Row);
|
||||||
formula := 'ISERR(H2)';
|
formula := 'ISERR(H2)';
|
||||||
MyWorksheet.WriteFormula(1, 7, '1/0'); // Create an error in H2
|
|
||||||
MyWorksheet.WriteUTF8Text(Row, 0, formula);
|
MyWorksheet.WriteUTF8Text(Row, 0, formula);
|
||||||
if UseRPNFormula then
|
if UseRPNFormula then
|
||||||
myWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
myWorksheet.WriteRPNFormula(Row, 1, CreateRPNFormula(
|
||||||
|
Reference in New Issue
Block a user