You've already forked lazarus-ccr
fpspreadsheet: Move rpn stuff from fpspreadsheet.pas to a new unit fpsRPN.pas. Move translatable strings from fpspreadsheet.pas to a new unit fpsStrings.pas. Make sure that all demos still run in the new environment.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3572 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -10,7 +10,7 @@ program excel8write;
|
|||||||
{$mode delphi}{$H+}
|
{$mode delphi}{$H+}
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, fpspreadsheet, xlsbiff8;
|
Classes, SysUtils, fpspreadsheet, fpsRPN, xlsbiff8;
|
||||||
|
|
||||||
const
|
const
|
||||||
Str_First = 'First';
|
Str_First = 'First';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
object FPSChartForm: TFPSChartForm
|
object FPSChartForm: TFPSChartForm
|
||||||
Left = 239
|
Left = 259
|
||||||
Height = 382
|
Height = 382
|
||||||
Top = 154
|
Top = 146
|
||||||
Width = 700
|
Width = 700
|
||||||
Caption = 'FPSpreadsheet Chart Example'
|
Caption = 'FPSpreadsheet Chart Example'
|
||||||
ClientHeight = 382
|
ClientHeight = 382
|
||||||
@ -43,13 +43,14 @@ object FPSChartForm: TFPSChartForm
|
|||||||
FrozenCols = 0
|
FrozenCols = 0
|
||||||
FrozenRows = 0
|
FrozenRows = 0
|
||||||
ReadFormulas = False
|
ReadFormulas = False
|
||||||
|
AutoAdvance = aaDown
|
||||||
ColCount = 27
|
ColCount = 27
|
||||||
ExtendedSelect = False
|
ExtendedSelect = False
|
||||||
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goEditing, goSmoothScroll]
|
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goEditing, goSmoothScroll]
|
||||||
RowCount = 101
|
RowCount = 101
|
||||||
TabOrder = 1
|
TabOrder = 1
|
||||||
ColWidths = (
|
ColWidths = (
|
||||||
42
|
56
|
||||||
64
|
64
|
||||||
64
|
64
|
||||||
64
|
64
|
||||||
@ -88,9 +89,9 @@ object FPSChartForm: TFPSChartForm
|
|||||||
TabOrder = 2
|
TabOrder = 2
|
||||||
end
|
end
|
||||||
object Label1: TLabel
|
object Label1: TLabel
|
||||||
Left = 16
|
Left = 14
|
||||||
Height = 34
|
Height = 42
|
||||||
Top = 8
|
Top = 4
|
||||||
Width = 676
|
Width = 676
|
||||||
AutoSize = False
|
AutoSize = False
|
||||||
Caption = 'Please add data to the grid or load it from a file, then choose the location of the data for the X and Y axises and click on the button "Create Graphic" to generate a chart.'
|
Caption = 'Please add data to the grid or load it from a file, then choose the location of the data for the X and Y axises and click on the button "Create Graphic" to generate a chart.'
|
||||||
@ -99,7 +100,7 @@ object FPSChartForm: TFPSChartForm
|
|||||||
end
|
end
|
||||||
object editSourceFile: TFileNameEdit
|
object editSourceFile: TFileNameEdit
|
||||||
Left = 152
|
Left = 152
|
||||||
Height = 23
|
Height = 28
|
||||||
Top = 48
|
Top = 48
|
||||||
Width = 136
|
Width = 136
|
||||||
DialogOptions = []
|
DialogOptions = []
|
||||||
@ -112,9 +113,9 @@ object FPSChartForm: TFPSChartForm
|
|||||||
end
|
end
|
||||||
object Label2: TLabel
|
object Label2: TLabel
|
||||||
Left = 14
|
Left = 14
|
||||||
Height = 15
|
Height = 20
|
||||||
Top = 51
|
Top = 51
|
||||||
Width = 106
|
Width = 134
|
||||||
Caption = 'Source Spreadsheet:'
|
Caption = 'Source Spreadsheet:'
|
||||||
ParentColor = False
|
ParentColor = False
|
||||||
end
|
end
|
||||||
@ -129,7 +130,7 @@ object FPSChartForm: TFPSChartForm
|
|||||||
end
|
end
|
||||||
object editXAxis: TLabeledEdit
|
object editXAxis: TLabeledEdit
|
||||||
Left = 64
|
Left = 64
|
||||||
Height = 23
|
Height = 28
|
||||||
Top = 80
|
Top = 80
|
||||||
Width = 80
|
Width = 80
|
||||||
EditLabel.AnchorSideTop.Control = editXAxis
|
EditLabel.AnchorSideTop.Control = editXAxis
|
||||||
@ -137,10 +138,10 @@ object FPSChartForm: TFPSChartForm
|
|||||||
EditLabel.AnchorSideRight.Control = editXAxis
|
EditLabel.AnchorSideRight.Control = editXAxis
|
||||||
EditLabel.AnchorSideBottom.Control = editXAxis
|
EditLabel.AnchorSideBottom.Control = editXAxis
|
||||||
EditLabel.AnchorSideBottom.Side = asrBottom
|
EditLabel.AnchorSideBottom.Side = asrBottom
|
||||||
EditLabel.Left = 25
|
EditLabel.Left = 16
|
||||||
EditLabel.Height = 15
|
EditLabel.Height = 20
|
||||||
EditLabel.Top = 84
|
EditLabel.Top = 84
|
||||||
EditLabel.Width = 36
|
EditLabel.Width = 45
|
||||||
EditLabel.Caption = 'X-Axis:'
|
EditLabel.Caption = 'X-Axis:'
|
||||||
EditLabel.ParentColor = False
|
EditLabel.ParentColor = False
|
||||||
LabelPosition = lpLeft
|
LabelPosition = lpLeft
|
||||||
@ -149,7 +150,7 @@ object FPSChartForm: TFPSChartForm
|
|||||||
end
|
end
|
||||||
object EditYAxis: TLabeledEdit
|
object EditYAxis: TLabeledEdit
|
||||||
Left = 208
|
Left = 208
|
||||||
Height = 23
|
Height = 28
|
||||||
Top = 80
|
Top = 80
|
||||||
Width = 80
|
Width = 80
|
||||||
EditLabel.AnchorSideTop.Control = EditYAxis
|
EditLabel.AnchorSideTop.Control = EditYAxis
|
||||||
@ -157,10 +158,10 @@ object FPSChartForm: TFPSChartForm
|
|||||||
EditLabel.AnchorSideRight.Control = EditYAxis
|
EditLabel.AnchorSideRight.Control = EditYAxis
|
||||||
EditLabel.AnchorSideBottom.Control = EditYAxis
|
EditLabel.AnchorSideBottom.Control = EditYAxis
|
||||||
EditLabel.AnchorSideBottom.Side = asrBottom
|
EditLabel.AnchorSideBottom.Side = asrBottom
|
||||||
EditLabel.Left = 169
|
EditLabel.Left = 161
|
||||||
EditLabel.Height = 15
|
EditLabel.Height = 20
|
||||||
EditLabel.Top = 84
|
EditLabel.Top = 84
|
||||||
EditLabel.Width = 36
|
EditLabel.Width = 44
|
||||||
EditLabel.Caption = 'Y-Axis:'
|
EditLabel.Caption = 'Y-Axis:'
|
||||||
EditLabel.ParentColor = False
|
EditLabel.ParentColor = False
|
||||||
LabelPosition = lpLeft
|
LabelPosition = lpLeft
|
||||||
|
@ -11,7 +11,7 @@ program demo_write_formula;
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils,
|
Classes, SysUtils,
|
||||||
fpspreadsheet, xlsbiff5, xlsbiff8, fpsopendocument;
|
fpspreadsheet, xlsbiff5, xlsbiff8, fpsopendocument, fpsRPN;
|
||||||
|
|
||||||
var
|
var
|
||||||
MyWorkbook: TsWorkbook;
|
MyWorkbook: TsWorkbook;
|
||||||
|
@ -52,7 +52,7 @@ unit fpsExprParser;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, contnrs, fpspreadsheet;
|
Classes, SysUtils, contnrs, fpspreadsheet, fpsrpn;
|
||||||
|
|
||||||
type
|
type
|
||||||
{ Tokens }
|
{ Tokens }
|
||||||
|
@ -1138,46 +1138,6 @@ type
|
|||||||
Format: TsSpreadsheetFormat;
|
Format: TsSpreadsheetFormat;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Simple creation an RPNFormula array to be used in fpspreadsheet. }
|
|
||||||
|
|
||||||
{@@ Helper record for simplification of RPN formula creation }
|
|
||||||
PRPNItem = ^TRPNItem;
|
|
||||||
TRPNItem = record
|
|
||||||
FE: TsFormulaElement;
|
|
||||||
Next: PRPNItem;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function CreateRPNFormula(AItem: PRPNItem; AReverse: Boolean = false): TsRPNFormula;
|
|
||||||
procedure DestroyRPNFormula(AItem: PRPNItem);
|
|
||||||
|
|
||||||
function RPNBool(AValue: Boolean;
|
|
||||||
ANext: PRPNItem): PRPNItem;
|
|
||||||
function RPNCellValue(ACellAddress: String;
|
|
||||||
ANext: PRPNItem): PRPNItem; overload;
|
|
||||||
function RPNCellValue(ARow, ACol: Integer; AFlags: TsRelFlags;
|
|
||||||
ANext: PRPNItem): PRPNItem; overload;
|
|
||||||
function RPNCellRef(ACellAddress: String;
|
|
||||||
ANext: PRPNItem): PRPNItem; overload;
|
|
||||||
function RPNCellRef(ARow, ACol: Integer; AFlags: TsRelFlags;
|
|
||||||
ANext: PRPNItem): PRPNItem; overload;
|
|
||||||
function RPNCellRange(ACellRangeAddress: String;
|
|
||||||
ANext: PRPNItem): PRPNItem; overload;
|
|
||||||
function RPNCellRange(ARow, ACol, ARow2, ACol2: Integer; AFlags: TsRelFlags;
|
|
||||||
ANext: PRPNItem): PRPNItem; overload;
|
|
||||||
function RPNCellOffset(ARowOffset, AColOffset: Integer; AFlags: TsRelFlags;
|
|
||||||
ANext: PRPNItem): PRPNItem;
|
|
||||||
function RPNErr(AErrCode: Byte; ANext: PRPNItem): PRPNItem;
|
|
||||||
function RPNInteger(AValue: Word; ANext: PRPNItem): PRPNItem;
|
|
||||||
function RPNMissingArg(ANext: PRPNItem): PRPNItem;
|
|
||||||
function RPNNumber(AValue: Double; ANext: PRPNItem): PRPNItem;
|
|
||||||
function RPNParenthesis(ANext: PRPNItem): PRPNItem;
|
|
||||||
function RPNString(AValue: String; ANext: PRPNItem): PRPNItem;
|
|
||||||
function RPNFunc(AToken: TFEKind; ANext: PRPNItem): PRPNItem; overload;
|
|
||||||
function RPNFunc(AFuncName: String; ANext: PRPNItem): PRPNItem; overload;
|
|
||||||
function RPNFunc(AFuncName: String; ANumParams: Byte; ANext: PRPNItem): PRPNItem; overload;
|
|
||||||
|
|
||||||
// function FixedParamCount(AElementKind: TFEKind): Boolean;
|
|
||||||
|
|
||||||
var
|
var
|
||||||
GsSpreadFormats: array of TsSpreadFormatData;
|
GsSpreadFormats: array of TsSpreadFormatData;
|
||||||
|
|
||||||
@ -1201,47 +1161,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Math, StrUtils, TypInfo, lazutf8,
|
Math, StrUtils, TypInfo, lazutf8,
|
||||||
fpsStreams, fpsUtils, fpsNumFormatParser, fpsExprParser;
|
fpsStrings, fpsStreams, fpsUtils, fpsNumFormatParser, fpsExprParser;
|
||||||
|
|
||||||
{ Translatable strings }
|
|
||||||
resourcestring
|
|
||||||
lpUnsupportedReadFormat = 'Tried to read a spreadsheet using an unsupported format';
|
|
||||||
lpUnsupportedWriteFormat = 'Tried to write a spreadsheet using an unsupported format';
|
|
||||||
lpNoValidSpreadsheetFile = '"%s" is not a valid spreadsheet file';
|
|
||||||
lpInvalidWorksheetName = '"%s" is not a valid worksheet name.';
|
|
||||||
lpUnknownSpreadsheetFormat = 'unknown format';
|
|
||||||
lpMaxRowsExceeded = 'This workbook contains %d rows, but the selected ' +
|
|
||||||
'file format does not support more than %d rows.';
|
|
||||||
lpMaxColsExceeded = 'This workbook contains %d columns, but the selected ' +
|
|
||||||
'file format does not support more than %d columns.';
|
|
||||||
lpTooManyPaletteColors = 'This workbook contains more colors (%d) than ' +
|
|
||||||
'supported by the file format (%d). The additional colors are replaced by '+
|
|
||||||
'the best-matching palette colors.';
|
|
||||||
lpInvalidFontIndex = 'Invalid font index';
|
|
||||||
lpInvalidNumberFormat = 'Trying to use an incompatible number format.';
|
|
||||||
lpInvalidDateTimeFormat = 'Trying to use an incompatible date/time format.';
|
|
||||||
lpNoValidNumberFormatString = 'No valid number format string.';
|
|
||||||
lpNoValidCellAddress = '"%s" is not a valid cell address.';
|
|
||||||
lpNoValidCellRangeAddress = '"%s" is not a valid cell range address.';
|
|
||||||
lpNoValidCellRangeOrCellAddress = '"%s" is not a valid cell or cell range address.';
|
|
||||||
lpSpecifyNumberOfParams = 'Specify number of parameters for function %s';
|
|
||||||
lpIncorrectParamCount = 'Funtion %s requires at least %d and at most %d parameters.';
|
|
||||||
lpCircularReference = 'Circular reference found when calculating worksheet formulas';
|
|
||||||
lpTRUE = 'TRUE';
|
|
||||||
lpFALSE = 'FALSE';
|
|
||||||
lpErrEmptyIntersection = '#NULL!';
|
|
||||||
lpErrDivideByZero = '#DIV/0!';
|
|
||||||
lpErrWrongType = '#VALUE!';
|
|
||||||
lpErrIllegalRef = '#REF!';
|
|
||||||
lpErrWrongName = '#NAME?';
|
|
||||||
lpErrOverflow = '#NUM!';
|
|
||||||
lpErrArgError = '#N/A';
|
|
||||||
lpErrFormulaNotSupported = '<FORMULA?>';
|
|
||||||
lpFileNotFound = 'File "%s" not found.';
|
|
||||||
|
|
||||||
{%H-}lpNoValidDateTimeFormatString = 'No valid date/time format string.';
|
|
||||||
{%H-}lpIllegalNumberFormat = 'Illegal number format.';
|
|
||||||
|
|
||||||
|
|
||||||
const
|
const
|
||||||
{ These are reserved system colors by Microsoft
|
{ These are reserved system colors by Microsoft
|
||||||
@ -1545,7 +1465,7 @@ begin
|
|||||||
sfCSV : Result := 'CSV';
|
sfCSV : Result := 'CSV';
|
||||||
sfWikiTable_Pipes : Result := 'WikiTable Pipes';
|
sfWikiTable_Pipes : Result := 'WikiTable Pipes';
|
||||||
sfWikiTable_WikiMedia : Result := 'WikiTable WikiMedia';
|
sfWikiTable_WikiMedia : Result := 'WikiTable WikiMedia';
|
||||||
else Result := lpUnknownSpreadsheetFormat;
|
else Result := rsUnknownSpreadsheetFormat;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2243,7 +2163,7 @@ begin
|
|||||||
if ParseCellString(AddressStr, r, c) then
|
if ParseCellString(AddressStr, r, c) then
|
||||||
Result := GetCell(r, c)
|
Result := GetCell(r, c)
|
||||||
else
|
else
|
||||||
raise Exception.CreateFmt(lpNoValidCellAddress, [AddressStr]);
|
raise Exception.CreateFmt(rsNoValidCellAddress, [AddressStr]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
@ -2714,17 +2634,17 @@ begin
|
|||||||
cctDateTime:
|
cctDateTime:
|
||||||
Result := DateTimeToStrNoNaN(DateTimeValue, NumberFormat, NumberFormatStr);
|
Result := DateTimeToStrNoNaN(DateTimeValue, NumberFormat, NumberFormatStr);
|
||||||
cctBool:
|
cctBool:
|
||||||
Result := StrUtils.IfThen(BoolValue, lpTRUE, lpFALSE);
|
Result := StrUtils.IfThen(BoolValue, rsTRUE, rsFALSE);
|
||||||
cctError:
|
cctError:
|
||||||
case TsErrorValue(ErrorValue) of
|
case TsErrorValue(ErrorValue) of
|
||||||
errEmptyIntersection : Result := lpErrEmptyIntersection;
|
errEmptyIntersection : Result := rsErrEmptyIntersection;
|
||||||
errDivideByZero : Result := lpErrDivideByZero;
|
errDivideByZero : Result := rsErrDivideByZero;
|
||||||
errWrongType : Result := lpErrWrongType;
|
errWrongType : Result := rsErrWrongType;
|
||||||
errIllegalRef : Result := lpErrIllegalRef;
|
errIllegalRef : Result := rsErrIllegalRef;
|
||||||
errWrongName : Result := lpErrWrongName;
|
errWrongName : Result := rsErrWrongName;
|
||||||
errOverflow : Result := lpErrOverflow;
|
errOverflow : Result := rsErrOverflow;
|
||||||
errArgError : Result := lpErrArgError;
|
errArgError : Result := rsErrArgError;
|
||||||
errFormulaNotSupported: Result := lpErrFormulaNotSupported;
|
errFormulaNotSupported: Result := rsErrFormulaNotSupported;
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
Result := '';
|
Result := '';
|
||||||
@ -3396,7 +3316,7 @@ procedure TsWorksheet.WriteNumber(ACell: PCell; ANumber: Double;
|
|||||||
AFormat: TsNumberFormat; ADecimals: Byte = 2);
|
AFormat: TsNumberFormat; ADecimals: Byte = 2);
|
||||||
begin
|
begin
|
||||||
if IsDateTimeFormat(AFormat) or IsCurrencyFormat(AFormat) then
|
if IsDateTimeFormat(AFormat) or IsCurrencyFormat(AFormat) then
|
||||||
raise Exception.Create(lpInvalidNumberFormat);
|
raise Exception.Create(rsInvalidNumberFormat);
|
||||||
|
|
||||||
if ACell <> nil then begin
|
if ACell <> nil then begin
|
||||||
ACell^.ContentType := cctNumber;
|
ACell^.ContentType := cctNumber;
|
||||||
@ -3457,10 +3377,10 @@ begin
|
|||||||
try
|
try
|
||||||
// Format string ok?
|
// Format string ok?
|
||||||
if parser.Status <> psOK then
|
if parser.Status <> psOK then
|
||||||
raise Exception.Create(lpNoValidNumberFormatString);
|
raise Exception.Create(rsNoValidNumberFormatString);
|
||||||
// Make sure that we do not write a date/time value here
|
// Make sure that we do not write a date/time value here
|
||||||
if parser.IsDateTimeFormat
|
if parser.IsDateTimeFormat
|
||||||
then raise Exception.Create(lpInvalidNumberFormat);
|
then raise Exception.Create(rsInvalidNumberFormat);
|
||||||
// If format string matches a built-in format use its format identifier,
|
// If format string matches a built-in format use its format identifier,
|
||||||
// All this is considered when calling Builtin_NumFormat of the parser.
|
// All this is considered when calling Builtin_NumFormat of the parser.
|
||||||
finally
|
finally
|
||||||
@ -3809,10 +3729,10 @@ begin
|
|||||||
try
|
try
|
||||||
// Format string ok?
|
// Format string ok?
|
||||||
if parser.Status <> psOK then
|
if parser.Status <> psOK then
|
||||||
raise Exception.Create(lpNoValidNumberFormatString);
|
raise Exception.Create(rsNoValidNumberFormatString);
|
||||||
// Make sure that we do not use a number format for date/times values.
|
// Make sure that we do not use a number format for date/times values.
|
||||||
if not parser.IsDateTimeFormat
|
if not parser.IsDateTimeFormat
|
||||||
then raise Exception.Create(lpInvalidDateTimeFormat);
|
then raise Exception.Create(rsInvalidDateTimeFormat);
|
||||||
// Avoid possible duplication of standard formats
|
// Avoid possible duplication of standard formats
|
||||||
if AFormat = nfCustom then
|
if AFormat = nfCustom then
|
||||||
AFormat := parser.NumFormat;
|
AFormat := parser.NumFormat;
|
||||||
@ -4328,7 +4248,7 @@ begin
|
|||||||
|
|
||||||
if (AFontIndex < 0) or (AFontIndex >= Workbook.GetFontCount) or (AFontIndex = 4) then
|
if (AFontIndex < 0) or (AFontIndex >= Workbook.GetFontCount) or (AFontIndex = 4) then
|
||||||
// note: Font index 4 is not defined in BIFF
|
// note: Font index 4 is not defined in BIFF
|
||||||
raise Exception.Create(lpInvalidFontIndex);
|
raise Exception.Create(rsInvalidFontIndex);
|
||||||
|
|
||||||
Include(ACell^.UsedFormattingFields, uffFont);
|
Include(ACell^.UsedFormattingFields, uffFont);
|
||||||
ACell^.FontIndex := AFontIndex;
|
ACell^.FontIndex := AFontIndex;
|
||||||
@ -5668,7 +5588,7 @@ end;
|
|||||||
a different format.
|
a different format.
|
||||||
|
|
||||||
@return An instance of a TsCustomSpreadReader descendent which is able to
|
@return An instance of a TsCustomSpreadReader descendent which is able to
|
||||||
read thi given file format.
|
read the given file format.
|
||||||
}
|
}
|
||||||
function TsWorkbook.CreateSpreadReader(AFormat: TsSpreadsheetFormat): TsCustomSpreadReader;
|
function TsWorkbook.CreateSpreadReader(AFormat: TsSpreadsheetFormat): TsCustomSpreadReader;
|
||||||
var
|
var
|
||||||
@ -5683,7 +5603,7 @@ begin
|
|||||||
Break;
|
Break;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Result = nil then raise Exception.Create(lpUnsupportedReadFormat);
|
if Result = nil then raise Exception.Create(rsUnsupportedReadFormat);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
@ -5708,7 +5628,7 @@ begin
|
|||||||
Break;
|
Break;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Result = nil then raise Exception.Create(lpUnsupportedWriteFormat);
|
if Result = nil then raise Exception.Create(rsUnsupportedWriteFormat);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
@ -5746,7 +5666,7 @@ var
|
|||||||
AReader: TsCustomSpreadReader;
|
AReader: TsCustomSpreadReader;
|
||||||
begin
|
begin
|
||||||
if not FileExists(AFileName) then
|
if not FileExists(AFileName) then
|
||||||
raise Exception.CreateFmt(lpFileNotFound, [AFileName]);
|
raise Exception.CreateFmt(rsFileNotFound, [AFileName]);
|
||||||
|
|
||||||
AReader := CreateSpreadReader(AFormat);
|
AReader := CreateSpreadReader(AFormat);
|
||||||
try
|
try
|
||||||
@ -5774,7 +5694,7 @@ var
|
|||||||
lException: Exception = nil;
|
lException: Exception = nil;
|
||||||
begin
|
begin
|
||||||
if not FileExists(AFileName) then
|
if not FileExists(AFileName) then
|
||||||
raise Exception.CreateFmt(lpFileNotFound, [AFileName]);
|
raise Exception.CreateFmt(rsFileNotFound, [AFileName]);
|
||||||
|
|
||||||
valid := GetFormatFromFileName(AFileName, SheetType);
|
valid := GetFormatFromFileName(AFileName, SheetType);
|
||||||
if valid then
|
if valid then
|
||||||
@ -5805,7 +5725,7 @@ begin
|
|||||||
else
|
else
|
||||||
ReadFromFile(AFileName, SheetType);
|
ReadFromFile(AFileName, SheetType);
|
||||||
end else
|
end else
|
||||||
raise Exception.CreateFmt(lpNoValidSpreadsheetFile, [AFileName]);
|
raise Exception.CreateFmt(rsNoValidSpreadsheetFile, [AFileName]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
@ -5950,7 +5870,7 @@ function TsWorkbook.AddWorksheet(AName: string;
|
|||||||
AcceptEmptyName: Boolean = false): TsWorksheet;
|
AcceptEmptyName: Boolean = false): TsWorksheet;
|
||||||
begin
|
begin
|
||||||
if not ValidWorksheetName(AName, AcceptEmptyName) then
|
if not ValidWorksheetName(AName, AcceptEmptyName) then
|
||||||
raise Exception.CreateFmt(lpInvalidWorksheetName, [AName]);
|
raise Exception.CreateFmt(rsInvalidWorksheetName, [AName]);
|
||||||
|
|
||||||
Result := TsWorksheet.Create;
|
Result := TsWorksheet.Create;
|
||||||
|
|
||||||
@ -7309,7 +7229,7 @@ procedure TsCustomSpreadReader.ReadFromStrings(AStrings: TStrings;
|
|||||||
AData: TsWorkbook);
|
AData: TsWorkbook);
|
||||||
begin
|
begin
|
||||||
Unused(AStrings, AData);
|
Unused(AStrings, AData);
|
||||||
raise Exception.Create(lpUnsupportedReadFormat);
|
raise Exception.Create(rsUnsupportedReadFormat);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TsCustomSpreadWriter }
|
{ TsCustomSpreadWriter }
|
||||||
@ -7500,11 +7420,11 @@ begin
|
|||||||
|
|
||||||
// Check row count
|
// Check row count
|
||||||
if lastRow >= FLimitations.MaxRowCount then
|
if lastRow >= FLimitations.MaxRowCount then
|
||||||
Workbook.AddErrorMsg(lpMaxRowsExceeded, [lastRow+1, FLimitations.MaxRowCount]);
|
Workbook.AddErrorMsg(rsMaxRowsExceeded, [lastRow+1, FLimitations.MaxRowCount]);
|
||||||
|
|
||||||
// Check column count
|
// Check column count
|
||||||
if lastCol >= FLimitations.MaxColCount then
|
if lastCol >= FLimitations.MaxColCount then
|
||||||
Workbook.AddErrorMsg(lpMaxColsExceeded, [lastCol+1, FLimitations.MaxColCount]);
|
Workbook.AddErrorMsg(rsMaxColsExceeded, [lastCol+1, FLimitations.MaxColCount]);
|
||||||
|
|
||||||
// Check color count.
|
// Check color count.
|
||||||
n := Workbook.GetPaletteSize;
|
n := Workbook.GetPaletteSize;
|
||||||
@ -7512,7 +7432,7 @@ begin
|
|||||||
for i:= FLimitations.MaxPaletteSize to n-1 do
|
for i:= FLimitations.MaxPaletteSize to n-1 do
|
||||||
if Workbook.UsesColor(i) then
|
if Workbook.UsesColor(i) then
|
||||||
begin
|
begin
|
||||||
Workbook.AddErrorMsg(lpTooManyPaletteColors, [n, FLimitations.MaxPaletteSize]);
|
Workbook.AddErrorMsg(rsTooManyPaletteColors, [n, FLimitations.MaxPaletteSize]);
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -7731,7 +7651,7 @@ end;
|
|||||||
procedure TsCustomSpreadWriter.WriteToStrings(AStrings: TStrings);
|
procedure TsCustomSpreadWriter.WriteToStrings(AStrings: TStrings);
|
||||||
begin
|
begin
|
||||||
Unused(AStrings);
|
Unused(AStrings);
|
||||||
raise Exception.Create(lpUnsupportedWriteFormat);
|
raise Exception.Create(rsUnsupportedWriteFormat);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
@ -7775,432 +7695,6 @@ end;
|
|||||||
*)
|
*)
|
||||||
|
|
||||||
|
|
||||||
{******************************************************************************}
|
|
||||||
{ Simplified creation of RPN formulas }
|
|
||||||
{******************************************************************************}
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates a pointer to a new RPN item. This represents an element in the array
|
|
||||||
of token of an RPN formula.
|
|
||||||
|
|
||||||
@return Pointer to the RPN item
|
|
||||||
}
|
|
||||||
function NewRPNItem: PRPNItem;
|
|
||||||
begin
|
|
||||||
New(Result);
|
|
||||||
FillChar(Result^.FE, SizeOf(Result^.FE), 0);
|
|
||||||
Result^.FE.StringValue := '';
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Destroys an RPN item
|
|
||||||
}
|
|
||||||
procedure DisposeRPNItem(AItem: PRPNItem);
|
|
||||||
begin
|
|
||||||
if AItem <> nil then
|
|
||||||
Dispose(AItem);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates a boolean value entry in the RPN array.
|
|
||||||
|
|
||||||
@param AValue Boolean value to be stored in the RPN item
|
|
||||||
@next ANext Pointer to the next RPN item in the list
|
|
||||||
}
|
|
||||||
function RPNBool(AValue: Boolean; ANext: PRPNItem): PRPNItem;
|
|
||||||
begin
|
|
||||||
Result := NewRPNItem;
|
|
||||||
Result^.FE.ElementKind := fekBool;
|
|
||||||
if AValue then Result^.FE.DoubleValue := 1.0 else Result^.FE.DoubleValue := 0.0;
|
|
||||||
Result^.Next := ANext;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array for a cell value, specifed by its
|
|
||||||
address, e.g. 'A1'. Takes care of absolute and relative cell addresses.
|
|
||||||
|
|
||||||
@param ACellAddress Adress of the cell given in Excel A1 notation
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
}
|
|
||||||
function RPNCellValue(ACellAddress: String; ANext: PRPNItem): PRPNItem;
|
|
||||||
var
|
|
||||||
r,c: Cardinal;
|
|
||||||
flags: TsRelFlags;
|
|
||||||
begin
|
|
||||||
if not ParseCellString(ACellAddress, r, c, flags) then
|
|
||||||
raise Exception.CreateFmt('"%s" is not a valid cell address.', [ACellAddress]);
|
|
||||||
Result := RPNCellValue(r,c, flags, ANext);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array for a cell value, specifed by its
|
|
||||||
row and column index and a flag containing information on relative addresses.
|
|
||||||
|
|
||||||
@param ARow Row index of the cell
|
|
||||||
@param ACol Column index of the cell
|
|
||||||
@param AFlags Flags specifying absolute or relative cell addresses
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
}
|
|
||||||
function RPNCellValue(ARow, ACol: Integer; AFlags: TsRelFlags;
|
|
||||||
ANext: PRPNItem): PRPNItem;
|
|
||||||
begin
|
|
||||||
Result := NewRPNItem;
|
|
||||||
Result^.FE.ElementKind := fekCell;
|
|
||||||
Result^.FE.Row := ARow;
|
|
||||||
Result^.FE.Col := ACol;
|
|
||||||
Result^.FE.RelFlags := AFlags;
|
|
||||||
Result^.Next := ANext;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array for a cell reference, specifed by its
|
|
||||||
address, e.g. 'A1'. Takes care of absolute and relative cell addresses.
|
|
||||||
"Cell reference" means that all properties of the cell can be handled.
|
|
||||||
Note that most Excel formulas with cells require the cell value only
|
|
||||||
(--> RPNCellValue)
|
|
||||||
|
|
||||||
@param ACellAddress Adress of the cell given in Excel A1 notation
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
}
|
|
||||||
function RPNCellRef(ACellAddress: String; ANext: PRPNItem): PRPNItem;
|
|
||||||
var
|
|
||||||
r,c: Cardinal;
|
|
||||||
flags: TsRelFlags;
|
|
||||||
begin
|
|
||||||
if not ParseCellString(ACellAddress, r, c, flags) then
|
|
||||||
raise Exception.CreateFmt(lpNoValidCellAddress, [ACellAddress]);
|
|
||||||
Result := RPNCellRef(r,c, flags, ANext);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array for a cell reference, specifed by its
|
|
||||||
row and column index and flags containing information on relative addresses.
|
|
||||||
"Cell reference" means that all properties of the cell can be handled.
|
|
||||||
Note that most Excel formulas with cells require the cell value only
|
|
||||||
(--> RPNCellValue)
|
|
||||||
|
|
||||||
@param ARow Row index of the cell
|
|
||||||
@param ACol Column index of the cell
|
|
||||||
@param AFlags Flags specifying absolute or relative cell addresses
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
}
|
|
||||||
function RPNCellRef(ARow, ACol: Integer; AFlags: TsRelFlags;
|
|
||||||
ANext: PRPNItem): PRPNItem;
|
|
||||||
begin
|
|
||||||
Result := NewRPNItem;
|
|
||||||
Result^.FE.ElementKind := fekCellRef;
|
|
||||||
Result^.FE.Row := ARow;
|
|
||||||
Result^.FE.Col := ACol;
|
|
||||||
Result^.FE.RelFlags := AFlags;
|
|
||||||
Result^.Next := ANext;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array for a range of cells, specified by an
|
|
||||||
Excel-style address, e.g. A1:G5. As in Excel, use a $ sign to indicate
|
|
||||||
absolute addresses.
|
|
||||||
|
|
||||||
@param ACellRangeAddress Adress of the cell range given in Excel notation, such as A1:G5
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
}
|
|
||||||
function RPNCellRange(ACellRangeAddress: String; ANext: PRPNItem): PRPNItem;
|
|
||||||
var
|
|
||||||
r1,c1, r2,c2: Cardinal;
|
|
||||||
flags: TsRelFlags;
|
|
||||||
begin
|
|
||||||
if not ParseCellRangeString(ACellRangeAddress, r1,c1, r2,c2, flags) then
|
|
||||||
raise Exception.CreateFmt(lpNoValidCellRangeAddress, [ACellRangeAddress]);
|
|
||||||
Result := RPNCellRange(r1,c1, r2,c2, flags, ANext);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array for a range of cells, specified by the
|
|
||||||
row/column indexes of the top/left and bottom/right corners of the block.
|
|
||||||
The flags indicate relative indexes.
|
|
||||||
|
|
||||||
@param ARow Row index of the top/left cell
|
|
||||||
@param ACol Column index of the top/left cell
|
|
||||||
@param ARow2 Row index of the bottom/right cell
|
|
||||||
@param ACol2 Column index of the bottom/right cell
|
|
||||||
@param AFlags Flags specifying absolute or relative cell addresses
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
}
|
|
||||||
function RPNCellRange(ARow, ACol, ARow2, ACol2: Integer; AFlags: TsRelFlags;
|
|
||||||
ANext: PRPNItem): PRPNItem;
|
|
||||||
begin
|
|
||||||
Result := NewRPNItem;
|
|
||||||
Result^.FE.ElementKind := fekCellRange;
|
|
||||||
Result^.FE.Row := ARow;
|
|
||||||
Result^.FE.Col := ACol;
|
|
||||||
Result^.FE.Row2 := ARow2;
|
|
||||||
Result^.FE.Col2 := ACol2;
|
|
||||||
Result^.FE.RelFlags := AFlags;
|
|
||||||
Result^.Next := ANext;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array for a relative cell reference as used in
|
|
||||||
shared formulas. The given parameters indicate the relativ offset between
|
|
||||||
the current cell coordinates and a reference rell.
|
|
||||||
|
|
||||||
@param ARowOffset Offset between current row and the row of a reference cell
|
|
||||||
@param AColOffset Offset between current column and the column of a reference cell
|
|
||||||
@param AFlags Flags specifying absolute or relative cell addresses
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
}
|
|
||||||
function RPNCellOffset(ARowOffset, AColOffset: Integer; AFlags: TsRelFlags;
|
|
||||||
ANext: PRPNItem): PRPNItem;
|
|
||||||
begin
|
|
||||||
Result := NewRPNItem;
|
|
||||||
Result^.FE.ElementKind := fekCellOffset;
|
|
||||||
Result^.FE.Row := Cardinal(ARowOffset);
|
|
||||||
Result^.FE.Col := Cardinal(AColOffset);
|
|
||||||
Result^.FE.RelFlags := AFlags;
|
|
||||||
Result^.Next := ANext;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array with an error value.
|
|
||||||
|
|
||||||
@param AErrCode Error code to be inserted (see TsErrorValue
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
@see TsErrorValue
|
|
||||||
}
|
|
||||||
function RPNErr(AErrCode: Byte; ANext: PRPNItem): PRPNItem;
|
|
||||||
begin
|
|
||||||
Result := NewRPNItem;
|
|
||||||
Result^.FE.ElementKind := fekErr;
|
|
||||||
Result^.FE.IntValue := AErrCode;
|
|
||||||
Result^.Next := ANext;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array for a 2-byte unsigned integer
|
|
||||||
|
|
||||||
@param AValue Integer value to be inserted into the formula
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
}
|
|
||||||
function RPNInteger(AValue: Word; ANext: PRPNItem): PRPNItem;
|
|
||||||
begin
|
|
||||||
Result := NewRPNItem;
|
|
||||||
Result^.FE.ElementKind := fekInteger;
|
|
||||||
Result^.FE.IntValue := AValue;
|
|
||||||
Result^.Next := ANext;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array for a missing argument in of function call.
|
|
||||||
Use this in a formula to indicate a missing argument
|
|
||||||
|
|
||||||
@param ANext Pointer to the next RPN item in the list.
|
|
||||||
}
|
|
||||||
function RPNMissingArg(ANext: PRPNItem): PRPNItem;
|
|
||||||
begin
|
|
||||||
Result := NewRPNItem;
|
|
||||||
Result^.FE.ElementKind := fekMissingArg;
|
|
||||||
Result^.Next := ANext;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array for a floating point number.
|
|
||||||
|
|
||||||
@param AValue Number value to be inserted into the formula
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
}
|
|
||||||
function RPNNumber(AValue: Double; ANext: PRPNItem): PRPNItem;
|
|
||||||
begin
|
|
||||||
Result := NewRPNItem;
|
|
||||||
Result^.FE.ElementKind := fekNum;
|
|
||||||
Result^.FE.DoubleValue := AValue;
|
|
||||||
Result^.Next := ANext;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array which puts the current operator in parenthesis.
|
|
||||||
For display purposes only, does not affect calculation.
|
|
||||||
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
}
|
|
||||||
function RPNParenthesis(ANext: PRPNItem): PRPNItem;
|
|
||||||
begin
|
|
||||||
Result := NewRPNItem;
|
|
||||||
Result^.FE.ElementKind := fekParen;
|
|
||||||
Result^.Next := ANext;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array for a string.
|
|
||||||
|
|
||||||
@param AValue String to be inserted into the formula
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
}
|
|
||||||
function RPNString(AValue: String; ANext: PRPNItem): PRPNItem;
|
|
||||||
begin
|
|
||||||
Result := NewRPNItem;
|
|
||||||
Result^.FE.ElementKind := fekString;
|
|
||||||
Result^.FE.StringValue := AValue;
|
|
||||||
Result^.Next := ANext;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array for an Excel function or operation
|
|
||||||
specified by its TokenID (--> TFEKind). Note that array elements for all
|
|
||||||
needed parameters must have been created before.
|
|
||||||
|
|
||||||
@param AToken Formula element indicating the function to be executed,
|
|
||||||
see the TFEKind enumeration for possible values.
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
|
|
||||||
@see TFEKind
|
|
||||||
}
|
|
||||||
function RPNFunc(AToken: TFEKind; ANext: PRPNItem): PRPNItem;
|
|
||||||
begin
|
|
||||||
{
|
|
||||||
if FEProps[AToken].MinParams <> FEProps[AToken].MaxParams then
|
|
||||||
raise Exception.CreateFmt(lpSpecifyNumberOfParams, [FEProps[AToken].Symbol]);
|
|
||||||
}
|
|
||||||
Result := NewRPNItem;
|
|
||||||
Result^.FE.ElementKind := AToken;
|
|
||||||
Result^.Fe.FuncName := '';
|
|
||||||
Result^.Next := ANext;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array for an Excel function or operation
|
|
||||||
specified by its TokenID (--> TFEKind). Note that array elements for all
|
|
||||||
needed parameters must have been created before.
|
|
||||||
|
|
||||||
@param AToken Formula element indicating the function to be executed,
|
|
||||||
see the TFEKind enumeration for possible values.
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
|
|
||||||
@see TFEKind
|
|
||||||
}
|
|
||||||
function RPNFunc(AFuncName: String; ANext: PRPNItem): PRPNItem;
|
|
||||||
begin
|
|
||||||
{
|
|
||||||
if FEProps[AToken].MinParams <> FEProps[AToken].MaxParams then
|
|
||||||
raise Exception.CreateFmt(lpSpecifyNumberOfParams, [FEProps[AToken].Symbol]);
|
|
||||||
}
|
|
||||||
Result := RPNFunc(AFuncName, 255, ANext); //FEProps[AToken].MinParams, ANext);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Creates an entry in the RPN array for an Excel function or operation
|
|
||||||
specified by its TokenID (--> TFEKind). Specify the number of parameters used.
|
|
||||||
They must have been created before.
|
|
||||||
|
|
||||||
@param AToken Formula element indicating the function to be executed,
|
|
||||||
see the TFEKind enumeration for possible values.
|
|
||||||
@param ANumParams Number of arguments used in the formula. If -1 then the
|
|
||||||
fixed number of arguments known from the function definiton
|
|
||||||
is used.
|
|
||||||
@param ANext Pointer to the next RPN item in the list
|
|
||||||
|
|
||||||
@see TFEKind
|
|
||||||
}
|
|
||||||
function RPNFunc(AFuncName: String; ANumParams: Byte; ANext: PRPNItem): PRPNItem;
|
|
||||||
begin
|
|
||||||
{
|
|
||||||
if (ANumParams > -1) then
|
|
||||||
if (ANumParams < FEProps[AToken].MinParams) or (ANumParams > FEProps[AToken].MaxParams) then
|
|
||||||
raise Exception.CreateFmt(lpIncorrectParamCount, [
|
|
||||||
FEProps[AToken].Symbol, FEProps[AToken].MinParams, FEProps[AToken].MaxParams
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
Result := NewRPNItem;
|
|
||||||
Result^.FE.ElementKind := fekFunc;
|
|
||||||
Result^.Fe.FuncName := AFuncName;
|
|
||||||
Result^.FE.ParamsNum := ANumParams;
|
|
||||||
Result^.Next := ANext;
|
|
||||||
end;
|
|
||||||
(*
|
|
||||||
{@@
|
|
||||||
Returns if the function defined by the token requires a fixed number of parameter.
|
|
||||||
|
|
||||||
@param AElementKind Identifier of the formula function considered
|
|
||||||
}
|
|
||||||
function FixedParamCount(AElementKind: TFEKind): Boolean;
|
|
||||||
begin
|
|
||||||
Result := (FEProps[AElementKind].MinParams = FEProps[AElementKind].MaxParams)
|
|
||||||
and (FEProps[AElementKind].MinParams >= 0);
|
|
||||||
end;
|
|
||||||
*)
|
|
||||||
{@@
|
|
||||||
Creates an RPN formula by a single call using nested RPN items.
|
|
||||||
|
|
||||||
For each formula element, use one of the RPNxxxx functions implemented here.
|
|
||||||
They are designed to be nested into each other. Terminate the chain by using nil.
|
|
||||||
|
|
||||||
@param AItem Pointer to the first RPN item representing the formula.
|
|
||||||
Each item contains a pointer to the next item in the list.
|
|
||||||
The list is terminated by nil.
|
|
||||||
@param AReverse If true the first rpn item in the chained list becomes the
|
|
||||||
last item in the token array. This feature is needed for
|
|
||||||
reading an xls file.
|
|
||||||
|
|
||||||
@example
|
|
||||||
The RPN formula for the string expression "$A1+2" can be created as follows:
|
|
||||||
<pre>
|
|
||||||
var
|
|
||||||
f: TsRPNFormula;
|
|
||||||
begin
|
|
||||||
f := CreateRPNFormula(
|
|
||||||
RPNCellValue('$A1',
|
|
||||||
RPNNumber(2,
|
|
||||||
RPNFunc(fekAdd,
|
|
||||||
nil))));
|
|
||||||
</pre>
|
|
||||||
}
|
|
||||||
function CreateRPNFormula(AItem: PRPNItem; AReverse: Boolean = false): TsRPNFormula;
|
|
||||||
var
|
|
||||||
item: PRPNItem;
|
|
||||||
nextitem: PRPNItem;
|
|
||||||
n: Integer;
|
|
||||||
begin
|
|
||||||
// Determine count of RPN elements
|
|
||||||
n := 0;
|
|
||||||
item := AItem;
|
|
||||||
while item <> nil do begin
|
|
||||||
inc(n);
|
|
||||||
item := item^.Next;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// Set array length of TsRPNFormula result
|
|
||||||
SetLength(Result, n);
|
|
||||||
|
|
||||||
// Copy FormulaElements to result and free temporary RPNItems
|
|
||||||
item := AItem;
|
|
||||||
if AReverse then n := Length(Result)-1 else n := 0;
|
|
||||||
while item <> nil do begin
|
|
||||||
nextitem := item^.Next;
|
|
||||||
Result[n] := item^.FE;
|
|
||||||
if AReverse then dec(n) else inc(n);
|
|
||||||
DisposeRPNItem(item);
|
|
||||||
item := nextitem;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{@@
|
|
||||||
Destroys the RPN formula starting with the given RPN item.
|
|
||||||
|
|
||||||
@param AItem Pointer to the first RPN items representing the formula.
|
|
||||||
Each item contains a pointer to the next item in the list.
|
|
||||||
The list is terminated by nil.
|
|
||||||
}
|
|
||||||
procedure DestroyRPNFormula(AItem: PRPNItem);
|
|
||||||
var
|
|
||||||
nextitem: PRPNItem;
|
|
||||||
begin
|
|
||||||
while AItem <> nil do begin
|
|
||||||
nextitem := AItem^.Next;
|
|
||||||
DisposeRPNItem(AItem);
|
|
||||||
AItem := nextitem;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
MakeLEPalette(@DEFAULT_PALETTE, Length(DEFAULT_PALETTE));
|
MakeLEPalette(@DEFAULT_PALETTE, Length(DEFAULT_PALETTE));
|
||||||
|
|
||||||
|
@ -499,6 +499,9 @@ function ParseCellString(const AStr: String; out ACellRow, ACellCol: Cardinal;
|
|||||||
end;
|
end;
|
||||||
if AStartPos = 1 then Include(AFlags, rfRelCol);
|
if AStartPos = 1 then Include(AFlags, rfRelCol);
|
||||||
|
|
||||||
|
if i > Length(AStr) then
|
||||||
|
exit;
|
||||||
|
|
||||||
isAbs := (AStr[i] = '$');
|
isAbs := (AStr[i] = '$');
|
||||||
if isAbs then inc(i);
|
if isAbs then inc(i);
|
||||||
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
{ fpsxmlcommon.pas
|
||||||
|
Unit shared by all xml-type reader/writer classes }
|
||||||
|
|
||||||
unit fpsxmlcommon;
|
unit fpsxmlcommon;
|
||||||
|
|
||||||
{$mode objfpc}
|
{$mode objfpc}
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
This package is all you need if you don't want graphical components (like grids and charts)."/>
|
This package is all you need if you don't want graphical components (like grids and charts)."/>
|
||||||
<License Value="LGPL with static linking exception. This is the same license as is used in the LCL (Lazarus Component Library)."/>
|
<License Value="LGPL with static linking exception. This is the same license as is used in the LCL (Lazarus Component Library)."/>
|
||||||
<Version Major="1" Minor="2"/>
|
<Version Major="1" Minor="2"/>
|
||||||
<Files Count="23">
|
<Files Count="25">
|
||||||
<Item1>
|
<Item1>
|
||||||
<Filename Value="fpolestorage.pas"/>
|
<Filename Value="fpolestorage.pas"/>
|
||||||
<UnitName Value="fpolestorage"/>
|
<UnitName Value="fpolestorage"/>
|
||||||
@ -118,6 +118,14 @@ This package is all you need if you don't want graphical components (like grids
|
|||||||
<Filename Value="fpsfunc.pas"/>
|
<Filename Value="fpsfunc.pas"/>
|
||||||
<UnitName Value="fpsfunc"/>
|
<UnitName Value="fpsfunc"/>
|
||||||
</Item23>
|
</Item23>
|
||||||
|
<Item24>
|
||||||
|
<Filename Value="fpsrpn.pas"/>
|
||||||
|
<UnitName Value="fpsrpn"/>
|
||||||
|
</Item24>
|
||||||
|
<Item25>
|
||||||
|
<Filename Value="fpsstrings.pas"/>
|
||||||
|
<UnitName Value="fpsStrings"/>
|
||||||
|
</Item25>
|
||||||
</Files>
|
</Files>
|
||||||
<RequiredPkgs Count="2">
|
<RequiredPkgs Count="2">
|
||||||
<Item1>
|
<Item1>
|
||||||
|
@ -11,7 +11,7 @@ uses
|
|||||||
fpsxmlcommon, xlsbiff2, xlsbiff5, xlsbiff8, xlsxooxml, fpsopendocument,
|
fpsxmlcommon, xlsbiff2, xlsbiff5, xlsbiff8, xlsxooxml, fpsopendocument,
|
||||||
fpsutils, fpszipper, uvirtuallayer_types, uvirtuallayer, uvirtuallayer_ole,
|
fpsutils, fpszipper, uvirtuallayer_types, uvirtuallayer, uvirtuallayer_ole,
|
||||||
uvirtuallayer_ole_helpers, uvirtuallayer_ole_types, uvirtuallayer_stream,
|
uvirtuallayer_ole_helpers, uvirtuallayer_ole_types, uvirtuallayer_stream,
|
||||||
fpolebasic, wikitable, fpsNumFormatParser, fpsfunc;
|
fpolebasic, wikitable, fpsNumFormatParser, fpsfunc, fpsrpn, fpsStrings;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
StrUtils, xlsbiff5;
|
StrUtils, fpsRPN, xlsbiff5;
|
||||||
|
|
||||||
const
|
const
|
||||||
ERROR_SHEET = 'ErrorTest'; //worksheet name
|
ERROR_SHEET = 'ErrorTest'; //worksheet name
|
||||||
|
@ -107,7 +107,7 @@ type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
math, typinfo, lazUTF8, fpsUtils, rpnFormulaUnit;
|
math, typinfo, lazUTF8, fpsUtils, fpsRPN, rpnFormulaUnit;
|
||||||
|
|
||||||
var
|
var
|
||||||
// Array containing the "true" results of the formulas, for comparison
|
// Array containing the "true" results of the formulas, for comparison
|
||||||
|
@ -15,7 +15,7 @@ procedure WriteRPNFormulaSamples(Worksheet: TsWorksheet;
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math, StrUtils;
|
Math, StrUtils, fpsRPN;
|
||||||
|
|
||||||
const
|
const
|
||||||
FALSE_TRUE: array[Boolean] of String = ('FALSE', 'TRUE');
|
FALSE_TRUE: array[Boolean] of String = ('FALSE', 'TRUE');
|
||||||
|
@ -394,7 +394,8 @@ type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
AVL_Tree, Math, Variants, xlsConst, fpsNumFormatParser, fpsExprParser;
|
AVL_Tree, Math, Variants,
|
||||||
|
xlsConst, fpsNumFormatParser, fpsrpn, fpsExprParser;
|
||||||
|
|
||||||
const
|
const
|
||||||
{ Helper table for rpn formulas:
|
{ Helper table for rpn formulas:
|
||||||
@ -431,129 +432,7 @@ const
|
|||||||
INT_EXCEL_TOKEN_TPAREN, {Operator in parenthesis}
|
INT_EXCEL_TOKEN_TPAREN, {Operator in parenthesis}
|
||||||
Word(-1) {fekFunc}
|
Word(-1) {fekFunc}
|
||||||
);
|
);
|
||||||
(*
|
|
||||||
|
|
||||||
// Math functions
|
|
||||||
INT_EXCEL_SHEET_FUNC_ABS, {fekABS}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ACOS, {fekACOS}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ACOSH, {fekACOSH}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ASIN, {fekASIN}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ASINH, {fekASINH}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ATAN, {fekATAN}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ATANH, {fekATANH}
|
|
||||||
INT_EXCEL_SHEET_FUNC_COS, {fekCOS}
|
|
||||||
INT_EXCEL_SHEET_FUNC_COSH, {fekCOSH}
|
|
||||||
INT_EXCEL_SHEET_FUNC_DEGREES, {fekDEGREES}
|
|
||||||
INT_EXCEL_SHEET_FUNC_EXP, {fekEXP}
|
|
||||||
INT_EXCEL_SHEET_FUNC_INT, {fekINT}
|
|
||||||
INT_EXCEL_SHEET_FUNC_LN, {fekLN}
|
|
||||||
INT_EXCEL_SHEET_FUNC_LOG, {fekLOG}
|
|
||||||
INT_EXCEL_SHEET_FUNC_LOG10, {fekLOG10}
|
|
||||||
INT_EXCEL_SHEET_FUNC_PI, {fekPI}
|
|
||||||
INT_EXCEL_SHEET_FUNC_RADIANS, {fekRADIANS}
|
|
||||||
INT_EXCEL_SHEET_FUNC_RAND, {fekRAND}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ROUND, {fekROUND}
|
|
||||||
INT_EXCEL_SHEET_FUNC_SIGN, {fekSIGN}
|
|
||||||
INT_EXCEL_SHEET_FUNC_SIN, {fekSIN}
|
|
||||||
INT_EXCEL_SHEET_FUNC_SINH, {fekSINH}
|
|
||||||
INT_EXCEL_SHEET_FUNC_SQRT, {fekSQRT}
|
|
||||||
INT_EXCEL_SHEET_FUNC_TAN, {fekTAN}
|
|
||||||
INT_EXCEL_SHEET_FUNC_TANH, {fekTANH}
|
|
||||||
|
|
||||||
// Date/time functions
|
|
||||||
INT_EXCEL_SHEET_FUNC_DATE, {fekDATE}
|
|
||||||
INT_EXCEL_SHEET_FUNC_DATEDIF, {fekDATEDIF}
|
|
||||||
INT_EXCEL_SHEET_FUNC_DATEVALUE, {fekDATEVALUE}
|
|
||||||
INT_EXCEL_SHEET_FUNC_DAY, {fekDAY}
|
|
||||||
INT_EXCEL_SHEET_FUNC_HOUR, {fekHOUR}
|
|
||||||
INT_EXCEL_SHEET_FUNC_MINUTE, {fekMINUTE}
|
|
||||||
INT_EXCEL_SHEET_FUNC_MONTH, {fekMONTH}
|
|
||||||
INT_EXCEL_SHEET_FUNC_NOW, {fekNOW}
|
|
||||||
INT_EXCEL_SHEET_FUNC_SECOND, {fekSECOND}
|
|
||||||
INT_EXCEL_SHEET_FUNC_TIME, {fekTIME}
|
|
||||||
INT_EXCEL_SHEET_FUNC_TIMEVALUE, {fekTIMEVALUE}
|
|
||||||
INT_EXCEL_SHEET_FUNC_TODAY, {fekTODAY}
|
|
||||||
INT_EXCEL_SHEET_FUNC_WEEKDAY, {fekWEEKDAY}
|
|
||||||
INT_EXCEL_SHEET_FUNC_YEAR, {fekYEAR}
|
|
||||||
|
|
||||||
// Statistical functions
|
|
||||||
INT_EXCEL_SHEET_FUNC_AVEDEV, {fekAVEDEV}
|
|
||||||
INT_EXCEL_SHEET_FUNC_AVERAGE, {fekAVERAGE}
|
|
||||||
INT_EXCEL_SHEET_FUNC_BETADIST, {fekBETADIST}
|
|
||||||
INT_EXCEL_SHEET_FUNC_BETAINV, {fekBETAINV}
|
|
||||||
INT_EXCEL_SHEET_FUNC_BINOMDIST, {fekBINOMDIST}
|
|
||||||
INT_EXCEL_SHEET_FUNC_CHIDIST, {fekCHIDIST}
|
|
||||||
INT_EXCEL_SHEET_FUNC_CHIINV, {fekCHIINV}
|
|
||||||
INT_EXCEL_SHEET_FUNC_COUNT, {fekCOUNT}
|
|
||||||
INT_EXCEL_SHEET_FUNC_COUNTA, {fekCOUNTA}
|
|
||||||
INT_EXCEL_SHEET_FUNC_COUNTBLANK,{fekCOUNTBLANK}
|
|
||||||
INT_EXCEL_SHEET_FUNC_COUNTIF, {fekCOUNTIF}
|
|
||||||
INT_EXCEL_SHEET_FUNC_MAX, {fekMAX}
|
|
||||||
INT_EXCEL_SHEET_FUNC_MEDIAN, {fekMEDIAN}
|
|
||||||
INT_EXCEL_SHEET_FUNC_MIN, {fekMIN}
|
|
||||||
INT_EXCEL_SHEET_FUNC_PERMUT, {fekPERMUT}
|
|
||||||
INT_EXCEL_SHEET_FUNC_POISSON, {fekPOISSON}
|
|
||||||
INT_EXCEL_SHEET_FUNC_PRODUCT, {fekPRODUCT}
|
|
||||||
INT_EXCEL_SHEET_FUNC_STDEV, {fekSTDEV}
|
|
||||||
INT_EXCEL_SHEET_FUNC_STDEVP, {fekSTDEVP}
|
|
||||||
INT_EXCEL_SHEET_FUNC_SUM, {fekSUM}
|
|
||||||
INT_EXCEL_SHEET_FUNC_SUMIF, {fekSUMIF}
|
|
||||||
INT_EXCEL_SHEET_FUNC_SUMSQ, {fekSUMSQ}
|
|
||||||
INT_EXCEL_SHEET_FUNC_VAR, {fekVAR}
|
|
||||||
INT_EXCEL_SHEET_FUNC_VARP, {fekVARP}
|
|
||||||
|
|
||||||
// Financial functions
|
|
||||||
INT_EXCEL_SHEET_FUNC_FV, {fekFV}
|
|
||||||
INT_EXCEL_SHEET_FUNC_NPER, {fekNPER}
|
|
||||||
INT_EXCEL_SHEET_FUNC_PMT, {fekPMT}
|
|
||||||
INT_EXCEL_SHEET_FUNC_PV, {fekPV}
|
|
||||||
INT_EXCEL_SHEET_FUNC_RATE, {fekRATE}
|
|
||||||
|
|
||||||
// Logical functions
|
|
||||||
INT_EXCEL_SHEET_FUNC_AND, {fekAND}
|
|
||||||
INT_EXCEL_SHEET_FUNC_FALSE, {fekFALSE}
|
|
||||||
INT_EXCEL_SHEET_FUNC_IF, {fekIF}
|
|
||||||
INT_EXCEL_SHEET_FUNC_NOT, {fekNOT}
|
|
||||||
INT_EXCEL_SHEET_FUNC_OR, {fekOR}
|
|
||||||
INT_EXCEL_SHEET_FUNC_TRUE, {fekTRUE}
|
|
||||||
|
|
||||||
// String functions
|
|
||||||
INT_EXCEL_SHEET_FUNC_CHAR, {fekCHAR}
|
|
||||||
INT_EXCEL_SHEET_FUNC_CODE, {fekCODE}
|
|
||||||
INT_EXCEL_SHEET_FUNC_LEFT, {fekLEFT}
|
|
||||||
INT_EXCEL_SHEET_FUNC_LOWER, {fekLOWER}
|
|
||||||
INT_EXCEL_SHEET_FUNC_MID, {fekMID}
|
|
||||||
INT_EXCEL_SHEET_FUNC_PROPER, {fekPROPER}
|
|
||||||
INT_EXCEL_SHEET_FUNC_REPLACE, {fekREPLACE}
|
|
||||||
INT_EXCEL_SHEET_FUNC_RIGHT, {fekRIGHT}
|
|
||||||
INT_EXCEL_SHEET_FUNC_SUBSTITUTE,{fekSUBSTITUTE}
|
|
||||||
INT_EXCEL_SHEET_FUNC_TRIM, {fekTRIM}
|
|
||||||
INT_EXCEL_SHEET_FUNC_UPPER, {fekUPPER}
|
|
||||||
|
|
||||||
// lookup/reference functions
|
|
||||||
INT_EXCEL_SHEET_FUNC_COLUMN, {fekCOLUMN}
|
|
||||||
INT_EXCEL_SHEET_FUNC_COLUMNS, {fekCOLUMNS}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ROW, {fekROW}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ROWS, {fekROWS}
|
|
||||||
|
|
||||||
// Info functions
|
|
||||||
INT_EXCEL_SHEET_FUNC_CELL, {fekCELLINFO}
|
|
||||||
INT_EXCEL_SHEET_FUNC_INFO, {fekINFO}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ISBLANK, {fekIsBLANK}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ISERR, {fekIsERR}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ISERROR, {fekIsERROR}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ISLOGICAL, {fekIsLOGICAL}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ISNA, {fekIsNA}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ISNONTEXT, {fekIsNONTEXT}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ISNUMBER, {fekIsNUMBER}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ISREF, {fekIsREF}
|
|
||||||
INT_EXCEL_SHEET_FUNC_ISTEXT, {fekIsTEXT}
|
|
||||||
INT_EXCEL_SHEET_FUNC_VALUE, {fekValue}
|
|
||||||
|
|
||||||
// Other operations
|
|
||||||
INT_EXCEL_TOKEN_TATTR {fekOpSum}
|
|
||||||
);
|
|
||||||
*)
|
|
||||||
type
|
type
|
||||||
TBIFF58BlankRecord = packed record
|
TBIFF58BlankRecord = packed record
|
||||||
RecordID: Word;
|
RecordID: Word;
|
||||||
@ -572,8 +451,8 @@ type
|
|||||||
Value: Double;
|
Value: Double;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ConvertExcelDateTimeToDateTime(
|
function ConvertExcelDateTimeToDateTime(const AExcelDateNum: Double;
|
||||||
const AExcelDateNum: Double; ADateMode: TDateMode): TDateTime;
|
ADateMode: TDateMode): TDateTime;
|
||||||
begin
|
begin
|
||||||
// Time only:
|
// Time only:
|
||||||
if (AExcelDateNum<1) and (AExcelDateNum>=0) then
|
if (AExcelDateNum<1) and (AExcelDateNum>=0) then
|
||||||
|
Reference in New Issue
Block a user