You've already forked lazarus-ccr
fpspreadsheet: Fix ods formula issues, seems to be ok now.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3513 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -3956,86 +3956,117 @@ var
|
||||
cell: PCell;
|
||||
begin
|
||||
Result := 0;
|
||||
if Arg.ResultType = rtInteger then
|
||||
result := Arg.ResInteger
|
||||
else
|
||||
if Arg.ResultType = rtFloat then
|
||||
result := trunc(Arg.ResFloat)
|
||||
else
|
||||
if Arg.ResultType = rtDateTime then
|
||||
result := trunc(Arg.ResDateTime)
|
||||
else
|
||||
if (Arg.ResultType = rtCell) then
|
||||
begin
|
||||
cell := ArgToCell(Arg);
|
||||
if Assigned(cell) and (cell^.ContentType = cctNumber) then
|
||||
result := trunc(cell^.NumberValue);
|
||||
case Arg.ResultType of
|
||||
rtInteger : result := Arg.ResInteger;
|
||||
rtFloat : result := trunc(Arg.ResFloat);
|
||||
rtDateTime : result := trunc(Arg.ResDateTime);
|
||||
rtBoolean : if Arg.ResBoolean then Result := 1 else Result := 0;
|
||||
rtString : if not TryStrToInt(Arg.ResString, Result) then Result := 0;
|
||||
rtCell : begin
|
||||
cell := ArgToCell(Arg);
|
||||
if Assigned(cell) then
|
||||
case cell^.ContentType of
|
||||
cctNumber : result := trunc(cell^.NumberValue);
|
||||
cctDateTime : result := trunc(cell^.DateTimeValue);
|
||||
cctBool : if cell^.BoolValue then result := 1;
|
||||
cctUTF8String: if not TryStrToInt(cell^.UTF8StringValue, result)
|
||||
then Result := 0;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ArgToFloat(Arg: TsExpressionResult): TsExprFloat;
|
||||
// Utility function for the built-in math functions. Accepts also integers
|
||||
// in place of the floating point arguments. To be called in builtins or
|
||||
// user-defined callbacks having float results.
|
||||
// Utility function for the built-in math functions. Accepts also integers and
|
||||
// other data types in place of floating point arguments. To be called in
|
||||
// builtins or user-defined callbacks having float results or arguments.
|
||||
var
|
||||
cell: PCell;
|
||||
s: String;
|
||||
fs: TFormatSettings;
|
||||
begin
|
||||
Result := 0.0;
|
||||
if Arg.ResultType = rtInteger then
|
||||
result := Arg.ResInteger
|
||||
else
|
||||
if Arg.ResultType = rtDateTime then
|
||||
result := Arg.ResDateTime
|
||||
else
|
||||
if Arg.ResultType = rtFloat then
|
||||
result := Arg.ResFloat
|
||||
else
|
||||
if (Arg.ResultType = rtCell) then
|
||||
begin
|
||||
cell := ArgToCell(Arg);
|
||||
if Assigned(cell) then
|
||||
case cell^.ContentType of
|
||||
cctNumber : Result := cell^.NumberValue;
|
||||
cctDateTime : Result := cell^.DateTimeValue;
|
||||
end;
|
||||
case Arg.ResultType of
|
||||
rtInteger : result := Arg.ResInteger;
|
||||
rtDateTime : result := Arg.ResDateTime;
|
||||
rtFloat : result := Arg.ResFloat;
|
||||
rtBoolean : if Arg.ResBoolean then Result := 1.0 else Result := 0.0;
|
||||
rtString : if not TryStrToFloat(Arg.ResString, Result) then Result := 0.0;
|
||||
rtCell : begin
|
||||
cell := ArgToCell(Arg);
|
||||
if Assigned(cell) then
|
||||
case cell^.ContentType of
|
||||
cctNumber : Result := cell^.NumberValue;
|
||||
cctDateTime : Result := cell^.DateTimeValue;
|
||||
cctBool : if cell^.BoolValue then result := 1.0;
|
||||
cctUTF8String: begin
|
||||
fs := Arg.Worksheet.Workbook.FormatSettings;
|
||||
s := cell^.UTF8StringValue;
|
||||
if not TryStrToFloat(s, result, fs) then
|
||||
result := 0.0;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ArgToDateTime(Arg: TsExpressionResult): TDateTime;
|
||||
var
|
||||
cell: PCell;
|
||||
fs: TFormatSettings;
|
||||
begin
|
||||
Result := 0.0;
|
||||
if Arg.ResultType = rtDateTime then
|
||||
result := Arg.ResDateTime
|
||||
else
|
||||
if Arg.ResultType = rtInteger then
|
||||
Result := Arg.ResInteger
|
||||
else
|
||||
if Arg.ResultType = rtFloat then
|
||||
Result := Arg.ResFloat
|
||||
else
|
||||
if (Arg.ResultType = rtCell) then
|
||||
begin
|
||||
cell := ArgToCell(Arg);
|
||||
if Assigned(cell) and (cell^.ContentType = cctDateTime) then
|
||||
Result := cell^.DateTimeValue;
|
||||
case Arg.ResultType of
|
||||
rtDateTime : result := Arg.ResDateTime;
|
||||
rtInteger : Result := Arg.ResInteger;
|
||||
rtFloat : Result := Arg.ResFloat;
|
||||
rtBoolean : if Arg.ResBoolean then Result := 1.0;
|
||||
rtString : begin
|
||||
fs := Arg.Worksheet.Workbook.FormatSettings;
|
||||
if not TryStrToDateTime(Arg.ResString, Result) then
|
||||
Result := 1.0;
|
||||
end;
|
||||
rtCell : begin
|
||||
cell := ArgToCell(Arg);
|
||||
if Assigned(cell) then
|
||||
if (cell^.ContentType = cctDateTime) then
|
||||
Result := cell^.DateTimeValue;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ArgToString(Arg: TsExpressionResult): String;
|
||||
// The Office applications are very fuzzy about data types...
|
||||
var
|
||||
cell: PCell;
|
||||
fs: TFormatSettings;
|
||||
dt: TDateTime;
|
||||
begin
|
||||
Result := '';
|
||||
case Arg.ResultType of
|
||||
rtString : result := Arg.ResString;
|
||||
rtInteger : Result := IntToStr(Arg.ResInteger);
|
||||
rtFloat : Result := FloatToStr(Arg.ResFloat);
|
||||
rtBoolean : if Arg.ResBoolean then Result := '1' else Result := '0';
|
||||
rtCell : begin
|
||||
cell := ArgToCell(Arg);
|
||||
if Assigned(cell) and (cell^.ContentType = cctUTF8String) then
|
||||
Result := cell^.UTF8Stringvalue;
|
||||
if Assigned(cell) then
|
||||
case cell^.ContentType of
|
||||
cctUTF8String : Result := cell^.UTF8Stringvalue;
|
||||
cctNumber : Result := Format('%g', [cell^.NumberValue]);
|
||||
cctBool : if cell^.BoolValue then Result := '1' else Result := '0';
|
||||
cctDateTime : begin
|
||||
fs := Arg.Worksheet.Workbook.FormatSettings;
|
||||
dt := cell^.DateTimeValue;
|
||||
if frac(dt) = 0.0 then
|
||||
Result := FormatDateTime(fs.LongTimeFormat, dt, fs)
|
||||
else
|
||||
if trunc(dt) = 0 then
|
||||
Result := FormatDateTime(fs.ShortDateFormat, dt, fs)
|
||||
else
|
||||
Result := FormatDateTime('cc', dt, fs);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -4070,7 +4101,7 @@ begin
|
||||
end;
|
||||
end
|
||||
else
|
||||
if (arg.ResultType in [rtInteger, rtFloat, rtDateTime, rtCell]) then
|
||||
if (arg.ResultType in [rtInteger, rtFloat, rtDateTime, rtCell, rtBoolean]) then
|
||||
begin
|
||||
AData[n] := ArgToFloat(arg);
|
||||
inc(n);
|
||||
|
@ -1230,9 +1230,12 @@ begin
|
||||
end;
|
||||
|
||||
// Read formula results
|
||||
// ... number value
|
||||
valueType := GetAttrValue(ACellNode, 'office:value-type');
|
||||
valueStr := GetAttrValue(ACellNode, 'office:value');
|
||||
// ODS wants a 0 in the NumberValue field in case of an error. If there is
|
||||
// no error, this value will be corrected below.
|
||||
cell^.NumberValue := 0.0;
|
||||
// (a) number value
|
||||
if (valueType = 'float') then begin
|
||||
if UpperCase(valueStr) = '1.#INF' then
|
||||
FWorksheet.WriteNumber(cell, 1.0/0.0)
|
||||
@ -1253,12 +1256,12 @@ begin
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
// Date/time value
|
||||
// (b) Date/time value
|
||||
if (valueType = 'date') or (valueType = 'time') then begin
|
||||
floatValue := ExtractDateTimeFromNode(ACellNode, cell^.NumberFormat, cell^.NumberFormatStr);
|
||||
FWorkSheet.WriteDateTime(cell, floatValue);
|
||||
end else
|
||||
// text
|
||||
// (c) text
|
||||
if (valueType = 'string') then begin
|
||||
node := ACellNode.FindNode('text:p');
|
||||
if (node <> nil) and (node.FirstChild <> nil) then begin
|
||||
@ -1266,7 +1269,7 @@ begin
|
||||
FWorksheet.WriteUTF8Text(cell, valueStr);
|
||||
end;
|
||||
end else
|
||||
// Text
|
||||
// (e) Text
|
||||
FWorksheet.WriteUTF8Text(cell, valueStr);
|
||||
|
||||
if FIsVirtualMode then
|
||||
@ -3604,6 +3607,7 @@ var
|
||||
formula: String;
|
||||
valuetype: String;
|
||||
value: string;
|
||||
valueStr: String;
|
||||
begin
|
||||
Unused(AStream, ARow, ACol);
|
||||
|
||||
@ -3623,6 +3627,7 @@ begin
|
||||
parser.Free;
|
||||
end;
|
||||
|
||||
valueStr := '';
|
||||
case ACell^.ContentType of
|
||||
cctNumber:
|
||||
begin
|
||||
@ -3647,6 +3652,7 @@ begin
|
||||
begin
|
||||
valuetype := 'string';
|
||||
value := 'office:string-value="' + ACell^.UTF8StringValue +'"';
|
||||
valueStr := '<text:p>' + ACell^.UTF8StringValue + '</text:p>';
|
||||
end;
|
||||
cctBool:
|
||||
begin
|
||||
@ -3655,8 +3661,10 @@ begin
|
||||
end;
|
||||
cctError:
|
||||
begin
|
||||
valuetype := 'error';
|
||||
value := 'office:value="' + GetErrorValueStr(ACell^.ErrorValue) + '"';
|
||||
// Strange: but in case of an error, Open/LibreOffice always writes a
|
||||
// float value 0 to the cell
|
||||
valuetype := 'float';
|
||||
value := 'office:value="0"';
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -3668,10 +3676,9 @@ begin
|
||||
if ACell^.CalcState=csCalculated then
|
||||
AppendToStream(AStream, Format(
|
||||
'<table:table-cell table:formula="=%s" office:value-type="%s" %s %s>' +
|
||||
// '<text:p>%s</text:p>'+
|
||||
valueStr +
|
||||
'</table:table-cell>', [
|
||||
formula, valuetype, value, lStyle
|
||||
//value
|
||||
]))
|
||||
else
|
||||
AppendToStream(AStream, Format(
|
||||
|
@ -48,10 +48,12 @@
|
||||
<Unit1>
|
||||
<Filename Value="datetests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="datetests"/>
|
||||
</Unit1>
|
||||
<Unit2>
|
||||
<Filename Value="stringtests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="stringtests"/>
|
||||
</Unit2>
|
||||
<Unit3>
|
||||
<Filename Value="numberstests.pas"/>
|
||||
@ -61,7 +63,6 @@
|
||||
<Unit4>
|
||||
<Filename Value="manualtests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="manualtests"/>
|
||||
</Unit4>
|
||||
<Unit5>
|
||||
<Filename Value="testsutility.pas"/>
|
||||
@ -71,6 +72,7 @@
|
||||
<Unit6>
|
||||
<Filename Value="internaltests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="internaltests"/>
|
||||
</Unit6>
|
||||
<Unit7>
|
||||
<Filename Value="formattests.pas"/>
|
||||
@ -80,6 +82,7 @@
|
||||
<Unit8>
|
||||
<Filename Value="colortests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="colortests"/>
|
||||
</Unit8>
|
||||
<Unit9>
|
||||
<Filename Value="fonttests.pas"/>
|
||||
@ -96,7 +99,6 @@
|
||||
<Unit12>
|
||||
<Filename Value="rpnformulaunit.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="rpnFormulaUnit"/>
|
||||
</Unit12>
|
||||
<Unit13>
|
||||
<Filename Value="formulatests.pas"/>
|
||||
@ -110,10 +112,12 @@
|
||||
<Unit15>
|
||||
<Filename Value="errortests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="errortests"/>
|
||||
</Unit15>
|
||||
<Unit16>
|
||||
<Filename Value="virtualmodetests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="virtualmodetests"/>
|
||||
</Unit16>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
|
@ -220,7 +220,10 @@
|
||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||
MyWorksheet.WriteErrorValue(Row, 2, errDivideByZero);
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := ErrorResult(errDivideByZero);
|
||||
if AFormat = sfOpenDocument then
|
||||
sollValues[Row] := FloatResult(0)
|
||||
else
|
||||
sollValues[Row] := ErrorResult(errDivideByZero);
|
||||
|
||||
// Division of cell values
|
||||
inc(Row);
|
||||
@ -956,9 +959,12 @@
|
||||
RPNFunc('ACOS', nil))))
|
||||
else
|
||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||
MyWorksheet.WriteErrorValue(Row, 2, errOverflow);;
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := ErrorResult(errOverFlow);
|
||||
MyWorksheet.WriteErrorValue(Row, 2, errOverflow);
|
||||
if AFormat = sfOpenDocument then
|
||||
sollValues[Row] := FloatResult(0)
|
||||
else
|
||||
sollValues[Row] := ErrorResult(errOverFlow);
|
||||
|
||||
// ARCCOSH - valid result
|
||||
inc(Row);
|
||||
@ -985,9 +991,12 @@
|
||||
RPNFunc('ACOSH', nil))))
|
||||
else
|
||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := ErrorResult(errOverFlow);
|
||||
MyWorksheet.WriteErrorValue(Row, 2, errOverflow);
|
||||
SetLength(sollValues, Row+1);
|
||||
if AFormat = sfOpenDocument then
|
||||
sollValues[Row] := FloatResult(0)
|
||||
else
|
||||
sollValues[Row] := ErrorResult(errOverFlow);
|
||||
|
||||
// ASIN
|
||||
inc(Row);
|
||||
@ -1014,9 +1023,12 @@
|
||||
RPNFunc('ASIN', nil))))
|
||||
else
|
||||
Myworksheet.WriteFormula(Row, 1, formula);
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := ErrorResult(errOverFlow);
|
||||
MyWorksheet.WriteErrorValue(Row, 2, errOverflow);
|
||||
SetLength(sollValues, Row+1);
|
||||
if AFormat = sfOpenDocument then
|
||||
sollValues[Row] := FloatResult(0)
|
||||
else
|
||||
sollValues[Row] := ErrorResult(errOverFlow);
|
||||
|
||||
// ARCSINH
|
||||
inc(Row);
|
||||
@ -1073,9 +1085,12 @@
|
||||
RPNFunc('ATANH', nil))))
|
||||
else
|
||||
myWorksheet.WriteFormula(Row, 1, formula);
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := ErrorResult(errOverFlow);
|
||||
MyWorksheet.WriteErrorValue(Row, 2, errOverFlow);
|
||||
SetLength(sollValues, Row+1);
|
||||
if AFormat = sfOpenDocument then
|
||||
sollValues[Row] := FloatResult(0)
|
||||
else
|
||||
sollValues[Row] := ErrorResult(errOverFlow);
|
||||
|
||||
// CEILING
|
||||
if AFormat <> sfExcel2 then begin
|
||||
@ -1262,7 +1277,10 @@
|
||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||
myWorksheet.WriteUTF8Text(Row, 2, GetErrorValueStr(errOverflow));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
if AFormat = sfOpenDocument then
|
||||
sollValues[Row] := FloatResult(0)
|
||||
else
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
|
||||
// LN - error due to argument < 0
|
||||
inc(Row);
|
||||
@ -1276,7 +1294,10 @@
|
||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||
MyWorksheet.WriteUTF8Text(Row, 2, GetErrorValueStr(errOverflow));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
if AFormat = sfOpenDocument then
|
||||
sollValues[Row] := FloatResult(0)
|
||||
else
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
|
||||
// LOG10 - valid result
|
||||
inc(Row);
|
||||
@ -1305,7 +1326,10 @@
|
||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||
myWorksheet.WriteUTF8Text(Row, 2, GetErrorValueStr(errOverflow));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
if AFormat = sfOpenDocument then
|
||||
sollValues[Row] := FloatResult(0)
|
||||
else
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
|
||||
// LOG10 - error due to argument < 0
|
||||
inc(Row);
|
||||
@ -1319,7 +1343,10 @@
|
||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||
MyWorksheet.WriteUTF8Text(Row, 2, GetErrorValueStr(errOverFlow));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
if AFormat = sfOpenDocument then
|
||||
sollValues[Row] := FloatResult(0)
|
||||
else
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
|
||||
// LOG - valid result (2 arguments)
|
||||
inc(Row);
|
||||
@ -1352,7 +1379,10 @@
|
||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||
MyWorksheet.WriteUTF8Text(Row, 2, GetErrorValueStr(errOverflow));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
if AFormat = sfOpenDocument then
|
||||
sollValues[Row] := FloatResult(0)
|
||||
else
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
}
|
||||
|
||||
// LOG - valid result (1 argument)
|
||||
@ -1383,7 +1413,10 @@
|
||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||
MyWorksheet.WriteUTF8Text(Row, 2, GetErrorValueStr(errOverflow));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
if AFormat = sfOpenDocument then
|
||||
sollValues[Row] := FloatResult(0)
|
||||
else
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
|
||||
// LOG - negative value
|
||||
inc(Row);
|
||||
@ -1398,7 +1431,10 @@
|
||||
MyWorksheet.WriteFormula(Row, 1, formula);
|
||||
MyWorksheet.WriteUTF8Text(Row, 2, GetErrorValueStr(errOverflow));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
if AFormat = sfOpenDocument then
|
||||
sollValues[Row] := FloatResult(0)
|
||||
else
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
|
||||
// LOG of cell
|
||||
inc(Row);
|
||||
@ -1623,7 +1659,10 @@
|
||||
myWorksheet.WriteFormula(Row, 1, formula);
|
||||
MyWorksheet.WriteUTF8Text(Row, 2, GetErrorValueStr(errOverflow));
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
if AFormat = sfOpenDocument then
|
||||
sollValues[Row] := FloatResult(0)
|
||||
else
|
||||
sollValues[Row] := ErrorResult(errOverflow);
|
||||
|
||||
// SQRT of cell value
|
||||
inc(Row);
|
||||
|
Reference in New Issue
Block a user