fpspreadsheet: Add formula ROUNDUP, fix ROUNDDOWN and ROUND. Patch by veb86 (https://forum.lazarus.freepascal.org/index.php/topic,67428.msg518782.html)

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9353 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz 2024-05-28 15:12:51 +00:00
parent 744fe8c3a3
commit c335a9e65a
2 changed files with 51 additions and 5 deletions

View File

@ -21,6 +21,8 @@ uses
xlsconst, {%H-}fpsPatches, fpsUtils,
fpsnumformat, fpspreadsheet, fpsexprparser;
const
EPS = 1E-12;
{------------------------------------------------------------------------------}
{ Builtin math functions }
@ -438,13 +440,19 @@ end;
function MyRoundDown(const AValue: Double; const Digits: TRoundToRange): Double;
var
RV: Double;
RV, uValue, tmp, integral: Double;
begin
uValue := abs(AValue);
RV := IntPower(10, Digits);
Result := Trunc(AValue / RV) * RV;
tmp := uValue * RV;
integral := Int(tmp);
if (1-Frac(tmp))/RV < EPS then
tmp := integral +1
else
tmp := integral;
Result := abs(tmp/RV)*sign(AValue);
end;
{ The Excel ROUNDDOWN function returns a number rounded down to a given number
of decimal places. Unlike standard rounding, where only numbers less than 5
are rounded down, ROUNDDOWN rounds all numbers down. }
@ -462,7 +470,43 @@ begin
if IsNaN(x) then
Result := ErrorResult(errWrongType)
else
Result := FloatResult(MyRoundDown(x, -n));
Result := FloatResult(MyRoundDown(x, n));
end;
end;
function MyRoundUp(const AValue: Double; const Digits: TRoundToRange): Double;
var
RV, uValue, tmp, integral: Double;
begin
uValue := abs(AValue);
RV := IntPower(10, Digits);
tmp := uValue * RV;
integral := Int(tmp);
if ((Frac(tmp)/RV) < EPS) then
tmp := integral
else
tmp := integral +1;
Result := abs(tmp/RV) * sign(AValue);
end;
{ The Excel ROUNDUP function returns a number rounded UP to a given number
of decimal places. Unlike standard rounding, where only numbers less than 5
are rounded UP, ROUNDUP rounds all numbers up. }
procedure fpsROUNDUP(var Result: TsExpressionResult; const Args: TsExprParameterArray);
var
x: TsExprFloat;
n: Integer;
begin
x := ArgToFloat(Args[1]);
if IsNaN(x) then
Result := ErrorResult(errWrongType)
else begin
n := Round(x);
x := ArgToFloat(Args[0]);
if IsNaN(x) then
Result := ErrorResult(errWrongType)
else
Result := FloatResult(MyRoundUp(x, n));
end;
end;
@ -2446,7 +2490,8 @@ begin
AddFunction(cat, 'RADIANS', 'F', 'F', INT_EXCEL_SHEET_FUNC_RADIANS, @fpsRADIANS);
AddFunction(cat, 'RAND', 'F', '', INT_EXCEL_SHEET_FUNC_RAND, @fpsRAND);
AddFunction(cat, 'ROUND', 'F', 'FF', INT_EXCEL_SHEET_FUNC_ROUND, @fpsROUND);
AddFunction(cat, 'ROUNDDOWN', 'F', 'F', INT_EXCEL_SHEET_FUNC_ROUNDDOWN, @fpsROUNDDOWN);
AddFunction(cat, 'ROUNDDOWN', 'F', 'FF', INT_EXCEL_SHEET_FUNC_ROUNDDOWN, @fpsROUNDDOWN);
AddFunction(cat, 'ROUNDUP', 'F', 'FF', INT_EXCEL_SHEET_FUNC_ROUNDUP, @fpsROUNDUP);
AddFunction(cat, 'SIGN', 'F', 'F', INT_EXCEL_SHEET_FUNC_SIGN, @fpsSIGN);
AddFunction(cat, 'SIN', 'F', 'F', INT_EXCEL_SHEET_FUNC_SIN, @fpsSIN);
AddFunction(cat, 'SINH', 'F', 'F', INT_EXCEL_SHEET_FUNC_SINH, @fpsSINH);

View File

@ -236,6 +236,7 @@ const
// No BIFF2 after 199
INT_EXCEL_SHEET_FUNC_ROUNDUP = 212; // not available in BIFF2
INT_EXCEL_SHEET_FUNC_ROUNDDOWN = 213; // not available in BIFF2
INT_EXCEL_SHEET_FUNC_ADDRESS = 219; // not available in BIFF2
INT_EXCEL_SHEET_FUNC_TODAY = 221; // not available in BIFF2