You've already forked lazarus-ccr
fpspreadsheet: Read print ranges and repeated print rows and columns from BIFF5 and BIFF8 files (xls - BIFF2 does not support them).
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4512 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -51,6 +51,10 @@ function RPNCellRange(ARow, ACol, ARow2, ACol2: Integer; AFlags: TsRelFlags;
|
||||
ANext: PRPNItem): PRPNItem; overload;
|
||||
function RPNCellOffset(ARowOffset, AColOffset: Integer; AFlags: TsRelFlags;
|
||||
ANext: PRPNItem): PRPNItem;
|
||||
function RPNCellRef3D(ASheet, ARow, ACol: Integer; AFlags: TsRelFlags;
|
||||
ANext: PRPNItem): PRPNItem;
|
||||
function RPNCellRange3D(ASheet1, ARow1, ACol1, ASheet2, ARow2, ACol2: Integer;
|
||||
AFlags: TsRelFlags; ANext: PRPNItem): PRPNItem;
|
||||
function RPNErr(AErrCode: TsErrorValue; ANext: PRPNItem): PRPNItem;
|
||||
function RPNInteger(AValue: Word; ANext: PRPNItem): PRPNItem;
|
||||
function RPNMissingArg(ANext: PRPNItem): PRPNItem;
|
||||
@ -82,6 +86,7 @@ begin
|
||||
New(Result);
|
||||
FillChar(Result^.FE, SizeOf(Result^.FE), 0);
|
||||
Result^.FE.StringValue := '';
|
||||
Result^.FE.SheetNames := '';
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
@ -254,6 +259,30 @@ begin
|
||||
Result^.Next := ANext;
|
||||
end;
|
||||
|
||||
function RPNCellRef3D(ASheet, ARow, ACol: Integer; AFlags: TsRelFlags;
|
||||
ANext: PRPNItem): PRPNItem;
|
||||
begin
|
||||
Result := NewRPNItem;
|
||||
Result^.FE.ElementKind := fekCellRef3d;
|
||||
Result^.FE.Sheet := ASheet;
|
||||
Result^.FE.Row := ARow;
|
||||
Result^.FE.Col := ACol;
|
||||
Result^.FE.RelFlags := AFlags;
|
||||
Result^.Next := ANext;
|
||||
end;
|
||||
|
||||
function RPNCellRange3D(ASheet1, ARow1, ACol1, ASheet2, ARow2, ACol2: Integer;
|
||||
AFlags: TsRelFlags; ANext: PRPNItem): PRPNItem;
|
||||
begin
|
||||
Result := RPNCellRef3d(ASheet1, ARow1, ACol1, AFlags, ANext);
|
||||
Result^.FE.ElementKind := fekCellRange3D;
|
||||
Result^.FE.Sheet2 := ASheet2;
|
||||
Result^.FE.Row2 := ARow2;
|
||||
Result^.FE.Col2 := ACol2;
|
||||
Result^.FE.RelFlags := AFlags;
|
||||
end;
|
||||
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Creates an entry in the RPN array with an error value.
|
||||
|
||||
@ -437,6 +466,7 @@ begin
|
||||
nextitem := item^.Next;
|
||||
Result[n] := item^.FE;
|
||||
Result[n].StringValue := item^.FE.StringValue;
|
||||
Result[n].Sheetnames := item^.FE.SheetNames;
|
||||
if AReverse then dec(n) else inc(n);
|
||||
DisposeRPNItem(item);
|
||||
item := nextitem;
|
||||
|
@ -104,13 +104,15 @@ type
|
||||
}
|
||||
TFEKind = (
|
||||
{ Basic operands }
|
||||
fekCell, fekCellRef, fekCellRange, fekCellOffset, fekNum, fekInteger,
|
||||
fekString, fekBool, fekErr, fekMissingArg,
|
||||
fekCell, fekCellRef, fekCellRange, fekCellOffset,
|
||||
fekCellRef3d, fekCellRange3d,
|
||||
fekNum, fekInteger, fekString, fekBool, fekErr, fekMissingArg,
|
||||
{ Basic operations }
|
||||
fekAdd, fekSub, fekMul, fekDiv, fekPercent, fekPower, fekUMinus, fekUPlus,
|
||||
fekConcat, // string concatenation
|
||||
fekEqual, fekGreater, fekGreaterEqual, fekLess, fekLessEqual, fekNotEqual,
|
||||
fekParen, // show parenthesis around expression node
|
||||
fekList, // List operator
|
||||
fekParen, // show parenthesis around expression node -- don't add anything after fekParen!
|
||||
{ Functions - they are identified by their name }
|
||||
fekFunc
|
||||
);
|
||||
@ -139,16 +141,17 @@ const
|
||||
|
||||
type
|
||||
{@@ Elements of an expanded formula.
|
||||
Note: If ElementKind is fekCellOffset, "Row" and "Col" have to be cast
|
||||
to signed integers! }
|
||||
Note: If ElementKind is fekCellOffset, "Row" and "Col" have to be cast to signed integers! }
|
||||
TsFormulaElement = record
|
||||
ElementKind: TFEKind;
|
||||
Row, Row2: Cardinal; // zero-based
|
||||
Col, Col2: Cardinal; // zero-based
|
||||
Row, Row2: Cardinal; // zero-based
|
||||
Col, Col2: Cardinal; // zero-based
|
||||
Sheet, Sheet2: Integer; // zero-based
|
||||
SheetNames: String; // both sheet names separated by a TAB character (intermediate use only)
|
||||
DoubleValue: double;
|
||||
IntValue: Word;
|
||||
StringValue: String;
|
||||
RelFlags: TsRelFlags; // store info on relative/absolute addresses
|
||||
RelFlags: TsRelFlags; // info on relative/absolute addresses
|
||||
FuncName: String;
|
||||
ParamsNum: Byte;
|
||||
end;
|
||||
@ -569,6 +572,15 @@ type
|
||||
{@@ Array with cell ranges }
|
||||
TsCellRangeArray = array of TsCellRange;
|
||||
|
||||
{@@ Record combining sheet index and row/column corner indexes of a cell range }
|
||||
TsCellRange3d = record
|
||||
Row1, Col1, Row2, Col2: Cardinal;
|
||||
Sheet1, Sheet2: Integer;
|
||||
end;
|
||||
|
||||
{@@ Array of 3d cell ranges }
|
||||
TsCellRange3dArray = array of TsCellRange3d;
|
||||
|
||||
{@@ Record containing limiting indexes of column or row range }
|
||||
TsRowColRange = record
|
||||
FirstIndex, LastIndex: Cardinal;
|
||||
|
@ -115,6 +115,25 @@ type
|
||||
procedure TestWriteRead_BIFF5_HeaderFooterFontColor_2sheets;
|
||||
procedure TestWriteRead_BIFF5_HeaderFooterFontColor_3sheets;
|
||||
|
||||
procedure TestWriteRead_BIFF5_PrintRanges_1sheet_1Range_NoSpace;
|
||||
procedure TestWriteRead_BIFF5_PrintRanges_1sheet_2Ranges_NoSpace;
|
||||
procedure TestWriteRead_BIFF5_PrintRanges_2sheet_1Range_NoSpace;
|
||||
procedure TestWriteRead_BIFF5_PrintRanges_2sheet_2Ranges_NoSpace;
|
||||
|
||||
procedure TestWriteRead_BIFF5_PrintRanges_1sheet_1Range_Space;
|
||||
procedure TestWriteRead_BIFF5_PrintRanges_1sheet_2Ranges_Space;
|
||||
procedure TestWriteRead_BIFF5_PrintRanges_2sheet_1Range_Space;
|
||||
procedure TestWriteRead_BIFF5_PrintRanges_2sheet_2Ranges_Space;
|
||||
|
||||
procedure TestWriteRead_BIFF5_RepeatedRow_0;
|
||||
procedure TestWriteRead_BIFF5_RepeatedRows_0_1;
|
||||
procedure TestWriteRead_BIFF5_RepeatedRows_1_3;
|
||||
procedure TestWriteRead_BIFF5_RepeatedCol_0;
|
||||
procedure TestWriteRead_BIFF5_RepeatedCols_0_1;
|
||||
procedure TestWriteRead_BIFF5_RepeatedCols_1_3;
|
||||
procedure TestWriteRead_BIFF5_RepeatedCol_0_Row_0;
|
||||
procedure TestWriteRead_BIFF5_RepeatedCols_0_1_Rows_0_1;
|
||||
|
||||
{ BIFF8 page layout tests }
|
||||
procedure TestWriteRead_BIFF8_PageMargins_1sheet_0;
|
||||
procedure TestWriteRead_BIFF8_PageMargins_1sheet_1;
|
||||
@ -169,6 +188,25 @@ type
|
||||
procedure TestWriteRead_BIFF8_HeaderFooterFontColor_2sheets;
|
||||
procedure TestWriteRead_BIFF8_HeaderFooterFontColor_3sheets;
|
||||
|
||||
procedure TestWriteRead_BIFF8_PrintRanges_1sheet_1Range_NoSpace;
|
||||
procedure TestWriteRead_BIFF8_PrintRanges_1sheet_2Ranges_NoSpace;
|
||||
procedure TestWriteRead_BIFF8_PrintRanges_2sheet_1Range_NoSpace;
|
||||
procedure TestWriteRead_BIFF8_PrintRanges_2sheet_2Ranges_NoSpace;
|
||||
|
||||
procedure TestWriteRead_BIFF8_PrintRanges_1sheet_1Range_Space;
|
||||
procedure TestWriteRead_BIFF8_PrintRanges_1sheet_2Ranges_Space;
|
||||
procedure TestWriteRead_BIFF8_PrintRanges_2sheet_1Range_Space;
|
||||
procedure TestWriteRead_BIFF8_PrintRanges_2sheet_2Ranges_Space;
|
||||
|
||||
procedure TestWriteRead_BIFF8_RepeatedRow_0;
|
||||
procedure TestWriteRead_BIFF8_RepeatedRows_0_1;
|
||||
procedure TestWriteRead_BIFF8_RepeatedRows_1_3;
|
||||
procedure TestWriteRead_BIFF8_RepeatedCol_0;
|
||||
procedure TestWriteRead_BIFF8_RepeatedCols_0_1;
|
||||
procedure TestWriteRead_BIFF8_RepeatedCols_1_3;
|
||||
procedure TestWriteRead_BIFF8_RepeatedCol_0_Row_0;
|
||||
procedure TestWriteRead_BIFF8_RepeatedCols_0_1_Rows_0_1;
|
||||
|
||||
{ OOXML page layout tests }
|
||||
procedure TestWriteRead_OOXML_PageMargins_1sheet_0;
|
||||
procedure TestWriteRead_OOXML_PageMargins_1sheet_1;
|
||||
@ -1138,6 +1176,87 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_PrintRanges_1sheet_1Range_NoSpace;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel5, 1, 1, false);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_PrintRanges_1sheet_2Ranges_NoSpace;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel5, 1, 2, false);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_PrintRanges_2sheet_1Range_NoSpace;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel5, 2, 1, false);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_PrintRanges_2sheet_2Ranges_NoSpace;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel5, 2, 2, false);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_PrintRanges_1sheet_1Range_Space;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel5, 1, 1, true);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_PrintRanges_1sheet_2Ranges_Space;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel5, 1, 2, true);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_PrintRanges_2sheet_1Range_Space;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel5, 2, 1, true);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_PrintRanges_2sheet_2Ranges_Space;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel5, 2, 2, true);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_RepeatedRow_0;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel5, -1, -1, 0, 0);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_RepeatedRows_0_1;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel5, -1, -1, 0, 1);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_RepeatedRows_1_3;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel5, -1, -1, 1, 3);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_RepeatedCol_0;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel5, 0, 0, -1, -1);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_RepeatedCols_0_1;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel5, 0, 1, -1, -1);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_RepeatedCols_1_3;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel5, 1, 3, -1, -1);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_RepeatedCol_0_Row_0;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel5, 0, 0, 0, 0);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF5_RepeatedCols_0_1_Rows_0_1;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel5, 0, 1, 0, 1);
|
||||
end;
|
||||
|
||||
|
||||
{ Tests for BIFF8 file format }
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_PageMargins_1sheet_0;
|
||||
@ -1363,6 +1482,87 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_PrintRanges_1sheet_1Range_NoSpace;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel8, 1, 1, false);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_PrintRanges_1sheet_2Ranges_NoSpace;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel8, 1, 2, false);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_PrintRanges_2sheet_1Range_NoSpace;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel8, 2, 1, false);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_PrintRanges_2sheet_2Ranges_NoSpace;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel8, 2, 2, false);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_PrintRanges_1sheet_1Range_Space;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel8, 1, 1, true);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_PrintRanges_1sheet_2Ranges_Space;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel8, 1, 2, true);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_PrintRanges_2sheet_1Range_Space;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel8, 2, 1, true);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_PrintRanges_2sheet_2Ranges_Space;
|
||||
begin
|
||||
TestWriteRead_PrintRanges(sfExcel8, 2, 2, true);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_RepeatedRow_0;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel8, -1, -1, 0, 0);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_RepeatedRows_0_1;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel8, -1, -1, 0, 1);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_RepeatedRows_1_3;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel8, -1, -1, 1, 3);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_RepeatedCol_0;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel8, 0, 0, -1, -1);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_RepeatedCols_0_1;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel8, 0, 1, -1, -1);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_RepeatedCols_1_3;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel8, 1, 3, -1, -1);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_RepeatedCol_0_Row_0;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel8, 0, 0, 0, 0);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_BIFF8_RepeatedCols_0_1_Rows_0_1;
|
||||
begin
|
||||
TestWriteRead_RepeatedColRows(sfExcel8, 0, 1, 0, 1);
|
||||
end;
|
||||
|
||||
|
||||
{ Tests for OOXML file format }
|
||||
|
||||
procedure TSpreadWriteReadPageLayoutTests.TestWriteRead_OOXML_PageMargins_1sheet_0;
|
||||
|
@ -59,7 +59,7 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, fpcanvas, lconvencoding,
|
||||
fpsTypes, fpspreadsheet,
|
||||
fpsTypes, fpspreadsheet, fpsrpn,
|
||||
xlscommon,
|
||||
{$ifdef USE_NEW_OLE}
|
||||
fpolebasic,
|
||||
@ -69,7 +69,6 @@ uses
|
||||
fpsUtils;
|
||||
|
||||
type
|
||||
|
||||
{ TsSpreadBIFF5Reader }
|
||||
|
||||
TsSpreadBIFF5Reader = class(TsSpreadBIFFReader)
|
||||
@ -77,9 +76,11 @@ type
|
||||
procedure PopulatePalette; override;
|
||||
{ Record writing methods }
|
||||
procedure ReadBoundsheet(AStream: TStream);
|
||||
procedure ReadDEFINEDNAME(AStream: TStream);
|
||||
procedure ReadFONT(const AStream: TStream);
|
||||
procedure ReadFORMAT(AStream: TStream); override;
|
||||
procedure ReadLABEL(AStream: TStream); override;
|
||||
function ReadRPNCellRange3D(AStream: TStream; var ARPNItem: PRPNItem): Boolean; override;
|
||||
procedure ReadRSTRING(AStream: TStream);
|
||||
procedure ReadStandardWidth(AStream: TStream; ASheet: TsWorksheet);
|
||||
procedure ReadStringRecord(AStream: TStream); override;
|
||||
@ -88,7 +89,6 @@ type
|
||||
procedure ReadXF(AStream: TStream);
|
||||
public
|
||||
{ General reading methods }
|
||||
// procedure ReadFromFile(AFileName: string); override;
|
||||
procedure ReadFromStream(AStream: TStream; AParams: TsStreamParams = []); override;
|
||||
end;
|
||||
|
||||
@ -346,7 +346,9 @@ type
|
||||
end;
|
||||
|
||||
|
||||
{ TsSpreadBIFF5Reader }
|
||||
{------------------------------------------------------------------------------}
|
||||
{ TsSpreadBIFF5Reader }
|
||||
{------------------------------------------------------------------------------}
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Populates the reader's default palette using the BIFF5 default colors.
|
||||
@ -357,6 +359,96 @@ begin
|
||||
FPalette.UseColors(PALETTE_BIFF5);
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Reads a BOUNDSHEET record containing a worksheet name
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsSpreadBIFF5Reader.ReadBoundsheet(AStream: TStream);
|
||||
var
|
||||
Len: Byte;
|
||||
s: AnsiString;
|
||||
sheetName: String;
|
||||
begin
|
||||
{ Absolute stream position of the BOF record of the sheet represented
|
||||
by this record }
|
||||
// Just assume that they are in order
|
||||
AStream.ReadDWord();
|
||||
|
||||
{ Visibility }
|
||||
AStream.ReadByte();
|
||||
|
||||
{ Sheet type }
|
||||
AStream.ReadByte();
|
||||
|
||||
{ Sheet name: Byte string, 8-bit length }
|
||||
Len := AStream.ReadByte();
|
||||
|
||||
SetLength(s, Len);
|
||||
AStream.ReadBuffer(s[1], Len*SizeOf(AnsiChar));
|
||||
sheetName := ConvertEncoding(s, FCodePage, EncodingUTF8);
|
||||
FWorksheetNames.Add(sheetName);
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Reads a DEFINEDNAME record. Currently only extracts print ranges and titles.
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsSpreadBIFF5Reader.ReadDEFINEDNAME(AStream: TStream);
|
||||
var
|
||||
options: Word;
|
||||
len: byte;
|
||||
formulaSize: Word;
|
||||
ansistr: ansiString;
|
||||
defName: String;
|
||||
rpnformula: TsRPNFormula;
|
||||
extsheetIndex: Integer;
|
||||
sheetIndex: Integer;
|
||||
begin
|
||||
// Options
|
||||
options := WordLEToN(AStream.ReadWord);
|
||||
if options and $0020 = 0 then // only support built-in names at the moment!
|
||||
exit;
|
||||
|
||||
// Keyboard shortcut --> ignore
|
||||
AStream.ReadByte;
|
||||
|
||||
// Length of name (character count)
|
||||
len := AStream.ReadByte;
|
||||
|
||||
// Size of formula data
|
||||
formulasize := WordLEToN(AStream.ReadWord);
|
||||
|
||||
// EXTERNSHEET index (1-base), or 0 if global name
|
||||
extsheetIndex := SmallInt(WordLEToN(AStream.ReadWord)) - 1; // now 0-based!
|
||||
|
||||
// Sheet index (1-based) on which the name is valid (0 = global)
|
||||
sheetIndex := SmallInt(WordLEToN(AStream.ReadWord)) - 1; // now 0-based!
|
||||
|
||||
// Length of Menu text (ignore)
|
||||
AStream.ReadByte;
|
||||
|
||||
// Length of description text(ignore)
|
||||
AStream.ReadByte;
|
||||
|
||||
// Length of help topic text (ignore)
|
||||
AStream.ReadByte;
|
||||
|
||||
// Length of status bar text (ignore)
|
||||
AStream.ReadByte;
|
||||
|
||||
// Name
|
||||
SetLength(ansistr, len);
|
||||
AStream.ReadBuffer(ansistr[1], len);
|
||||
defName := ConvertEncoding(ansistr, FCodepage, encodingUTF8);
|
||||
|
||||
// Formula
|
||||
if not ReadRPNTokenArray(AStream, formulaSize, rpnFormula) then
|
||||
exit;
|
||||
// Store defined name in internal list
|
||||
FDefinedNames.Add(TsBIFFDefinedName.Create(defName, rpnFormula, sheetIndex));
|
||||
|
||||
// Skip rest...
|
||||
end;
|
||||
|
||||
|
||||
procedure TsSpreadBIFF5Reader.ReadWorkbookGlobals(AStream: TStream);
|
||||
var
|
||||
SectionEOF: Boolean = False;
|
||||
@ -372,14 +464,16 @@ begin
|
||||
CurStreamPos := AStream.Position;
|
||||
|
||||
case RecordType of
|
||||
INT_EXCEL_ID_BOF : ;
|
||||
INT_EXCEL_ID_BOUNDSHEET : ReadBoundSheet(AStream);
|
||||
INT_EXCEL_ID_CODEPAGE : ReadCodePage(AStream);
|
||||
INT_EXCEL_ID_FONT : ReadFont(AStream);
|
||||
INT_EXCEL_ID_FORMAT : ReadFormat(AStream);
|
||||
INT_EXCEL_ID_XF : ReadXF(AStream);
|
||||
INT_EXCEL_ID_PALETTE : ReadPalette(AStream);
|
||||
INT_EXCEL_ID_EOF : SectionEOF := True;
|
||||
INT_EXCEL_ID_BOF : ;
|
||||
INT_EXCEL_ID_BOUNDSHEET : ReadBoundSheet(AStream);
|
||||
INT_EXCEL_ID_CODEPAGE : ReadCodePage(AStream);
|
||||
INT_EXCEL_ID_DEFINEDNAME : ReadDefinedName(AStream);
|
||||
INT_EXCEL_ID_EXTERNSHEET : ReadExternSheet(AStream);
|
||||
INT_EXCEL_ID_FONT : ReadFont(AStream);
|
||||
INT_EXCEL_ID_FORMAT : ReadFormat(AStream);
|
||||
INT_EXCEL_ID_XF : ReadXF(AStream);
|
||||
INT_EXCEL_ID_PALETTE : ReadPalette(AStream);
|
||||
INT_EXCEL_ID_EOF : SectionEOF := True;
|
||||
else
|
||||
// nothing
|
||||
end;
|
||||
@ -401,7 +495,7 @@ var
|
||||
RecordType: Word;
|
||||
CurStreamPos: Int64;
|
||||
begin
|
||||
FWorksheet := FWorkbook.AddWorksheet(FWorksheetNames[FCurrentWorksheet], true);
|
||||
FWorksheet := FWorkbook.AddWorksheet(FWorksheetNames[FCurSheetIndex], true);
|
||||
|
||||
while (not SectionEOF) do
|
||||
begin
|
||||
@ -497,30 +591,36 @@ begin
|
||||
FixRows(FWorksheet);
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF5Reader.ReadBoundsheet(AStream: TStream);
|
||||
function TsSpreadBIFF5Reader.ReadRPNCellRange3D(AStream: TStream;
|
||||
var ARPNItem: PRPNItem): Boolean;
|
||||
var
|
||||
Len: Byte;
|
||||
s: AnsiString;
|
||||
sheetName: String;
|
||||
sheetIndex: SmallInt;
|
||||
sheetIndex1, sheetIndex2: Word;
|
||||
r1, c1, r2, c2: Cardinal;
|
||||
flags: TsRelFlags;
|
||||
begin
|
||||
{ Absolute stream position of the BOF record of the sheet represented
|
||||
by this record }
|
||||
// Just assume that they are in order
|
||||
AStream.ReadDWord();
|
||||
Result := true;
|
||||
|
||||
{ Visibility }
|
||||
AStream.ReadByte();
|
||||
// 1-based index to EXTERNSHEET record containing name of first referenced worksheet
|
||||
// negative for 3D reference, positive for external reference
|
||||
sheetIndex := WordLEToN(AStream.ReadWord);
|
||||
if sheetIndex > 0 then
|
||||
exit(false); // we support only internal references here!
|
||||
sheetIndex := abs(sheetindex) - 1; // make it a usable 0-based index although we don't need it any more...
|
||||
|
||||
{ Sheet type }
|
||||
AStream.ReadByte();
|
||||
// Next 8 bytes not used.
|
||||
AStream.ReadDWord;
|
||||
AStream.ReadDWord;
|
||||
|
||||
{ Sheet name: Byte string, 8-bit length }
|
||||
Len := AStream.ReadByte();
|
||||
// Zero-based index to first and last referenced sheet (in case of internal ref)
|
||||
sheetIndex1 := WordLEToN(AStream.ReadWord);
|
||||
sheetIndex2 := WordLEToN(AStream.ReadWord);
|
||||
|
||||
SetLength(s, Len);
|
||||
AStream.ReadBuffer(s[1], Len*SizeOf(AnsiChar));
|
||||
sheetName := ConvertEncoding(s, FCodePage, EncodingUTF8);
|
||||
FWorksheetNames.Add(sheetName);
|
||||
// Cell range coordinates
|
||||
ReadRPNCellRangeAddress(AStream, r1, c1, r2, c2, flags);
|
||||
if r2 = $FFFF then r2 := Cardinal(-1);
|
||||
if c2 = $FF then c2 := Cardinal(-1);
|
||||
ARPNItem := RPNCellRange3D(sheetIndex1, r1, c1, sheetIndex2, r2, c2, flags, ARPNItem);
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF5Reader.ReadRSTRING(AStream: TStream);
|
||||
|
@ -56,7 +56,7 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, fpcanvas, DateUtils, contnrs, lazutf8,
|
||||
fpstypes, fpspreadsheet, xlscommon,
|
||||
fpstypes, fpspreadsheet, fpsrpn, xlscommon,
|
||||
{$ifdef USE_NEW_OLE}
|
||||
fpolebasic,
|
||||
{$else}
|
||||
@ -66,6 +66,12 @@ uses
|
||||
|
||||
type
|
||||
|
||||
TBIFF8ExternSheet = packed record
|
||||
ExternBookIndex: Word;
|
||||
FirstSheetIndex: Word;
|
||||
LastSheetIndex: Word;
|
||||
end;
|
||||
|
||||
{ TsSpreadBIFF8Reader }
|
||||
TsSpreadBIFF8Reader = class(TsSpreadBIFFReader)
|
||||
private
|
||||
@ -75,22 +81,26 @@ type
|
||||
FCommentPending: Boolean;
|
||||
FCommentID: Integer;
|
||||
FCommentLen: Integer;
|
||||
procedure ReadBoundsheet(AStream: TStream);
|
||||
FBiff8ExternSheets: array of TBiff8ExternSheet;
|
||||
function ReadString(const AStream: TStream; const ALength: Word;
|
||||
out ARichTextParams: TsRichTextParams): String;
|
||||
function ReadUnformattedWideString(const AStream: TStream;
|
||||
const ALength: Word): WideString;
|
||||
function ReadWideString(const AStream: TStream; const ALength: Word;
|
||||
out ARichTextParams: TsRichTextParams): WideString; overload;
|
||||
function ReadWideString(const AStream: TStream; const AUse8BitLength: Boolean): WideString; overload;
|
||||
function ReadWideString(const AStream: TStream;
|
||||
const AUse8BitLength: Boolean): WideString; overload;
|
||||
protected
|
||||
procedure PopulatePalette; override;
|
||||
procedure ReadBOUNDSHEET(AStream: TStream);
|
||||
procedure ReadCONTINUE(const AStream: TStream);
|
||||
procedure ReadDEFINEDNAME(const AStream: TStream);
|
||||
procedure ReadEXTERNSHEET(const AStream: TStream);
|
||||
procedure ReadFONT(const AStream: TStream);
|
||||
procedure ReadFORMAT(AStream: TStream); override;
|
||||
procedure ReadHeaderFooter(AStream: TStream; AIsHeader: Boolean); override;
|
||||
procedure ReadHyperLink(AStream: TStream);
|
||||
procedure ReadHyperlinkToolTip(AStream: TStream);
|
||||
procedure ReadHyperLink(const AStream: TStream);
|
||||
procedure ReadHyperlinkToolTip(const AStream: TStream);
|
||||
procedure ReadLABEL(AStream: TStream); override;
|
||||
procedure ReadLabelSST(const AStream: TStream);
|
||||
procedure ReadMergedCells(const AStream: TStream);
|
||||
@ -103,6 +113,7 @@ type
|
||||
out ARowOffset, AColOffset: Integer; out AFlags: TsRelFlags); override;
|
||||
procedure ReadRPNCellRangeAddress(AStream: TStream;
|
||||
out ARow1, ACol1, ARow2, ACol2: Cardinal; out AFlags: TsRelFlags); override;
|
||||
function ReadRPNCellRange3D(AStream: TStream; var ARPNItem: PRPNItem): Boolean; override;
|
||||
procedure ReadRPNCellRangeOffset(AStream: TStream;
|
||||
out ARow1Offset, ACol1Offset, ARow2Offset, ACol2Offset: Integer;
|
||||
out AFlags: TsRelFlags); override;
|
||||
@ -443,13 +454,14 @@ type
|
||||
Text: String;
|
||||
end;
|
||||
|
||||
|
||||
{ TsSpreadBIFF8Reader }
|
||||
|
||||
destructor TsSpreadBIFF8Reader.Destroy;
|
||||
var
|
||||
j: Integer;
|
||||
begin
|
||||
SetLength(FBiff8ExternSheets, 0);
|
||||
|
||||
if Assigned(FSharedStringTable) then
|
||||
begin
|
||||
for j := FSharedStringTable.Count-1 downto 0 do
|
||||
@ -777,16 +789,18 @@ begin
|
||||
|
||||
if RecordType <> INT_EXCEL_ID_CONTINUE then begin
|
||||
case RecordType of
|
||||
INT_EXCEL_ID_BOF : ;
|
||||
INT_EXCEL_ID_BOUNDSHEET: ReadBoundSheet(AStream);
|
||||
INT_EXCEL_ID_EOF : SectionEOF := True;
|
||||
INT_EXCEL_ID_SST : ReadSST(AStream);
|
||||
INT_EXCEL_ID_CODEPAGE : ReadCodepage(AStream);
|
||||
INT_EXCEL_ID_FONT : ReadFont(AStream);
|
||||
INT_EXCEL_ID_FORMAT : ReadFormat(AStream);
|
||||
INT_EXCEL_ID_XF : ReadXF(AStream);
|
||||
INT_EXCEL_ID_DATEMODE : ReadDateMode(AStream);
|
||||
INT_EXCEL_ID_PALETTE : ReadPalette(AStream);
|
||||
INT_EXCEL_ID_BOF : ;
|
||||
INT_EXCEL_ID_BOUNDSHEET : ReadBoundSheet(AStream);
|
||||
INT_EXCEL_ID_DEFINEDNAME : ReadDEFINEDNAME(AStream);
|
||||
INT_EXCEL_ID_EOF : SectionEOF := True;
|
||||
INT_EXCEL_ID_EXTERNSHEET : ReadEXTERNSHEET(AStream);
|
||||
INT_EXCEL_ID_SST : ReadSST(AStream);
|
||||
INT_EXCEL_ID_CODEPAGE : ReadCodepage(AStream);
|
||||
INT_EXCEL_ID_FONT : ReadFont(AStream);
|
||||
INT_EXCEL_ID_FORMAT : ReadFormat(AStream);
|
||||
INT_EXCEL_ID_XF : ReadXF(AStream);
|
||||
INT_EXCEL_ID_DATEMODE : ReadDateMode(AStream);
|
||||
INT_EXCEL_ID_PALETTE : ReadPalette(AStream);
|
||||
else
|
||||
// nothing
|
||||
end;
|
||||
@ -809,7 +823,7 @@ var
|
||||
RecordType: Word;
|
||||
CurStreamPos: Int64;
|
||||
begin
|
||||
FWorksheet := FWorkbook.AddWorksheet(FWorksheetNames[FCurrentWorksheet], true);
|
||||
FWorksheet := FWorkbook.AddWorksheet(FWorksheetNames[FCurSheetIndex], true);
|
||||
|
||||
while (not SectionEOF) do
|
||||
begin
|
||||
@ -829,6 +843,7 @@ begin
|
||||
INT_EXCEL_ID_COLINFO : ReadColInfo(AStream);
|
||||
INT_EXCEL_ID_CONTINUE : ReadCONTINUE(AStream);
|
||||
INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
|
||||
INT_EXCEL_ID_DEFINEDNAME : ReadDefinedName(AStream);
|
||||
INT_EXCEL_ID_EOF : SectionEOF := True;
|
||||
INT_EXCEL_ID_FOOTER : ReadHeaderFooter(AStream, false);
|
||||
INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
|
||||
@ -944,7 +959,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
(*
|
||||
const AStrea
|
||||
procedure TsSpreadBIFF8Reader.ReadFromStream(AStream: TStream);
|
||||
var
|
||||
BIFF8EOF: Boolean;
|
||||
@ -1179,6 +1193,26 @@ begin
|
||||
if (c2 and MASK_EXCEL_RELATIVE_ROW <> 0) then Include(AFlags, rfRelRow2);
|
||||
end;
|
||||
|
||||
function TsSpreadBIFF8Reader.ReadRPNCellRange3D(AStream: TStream;
|
||||
var ARPNItem: PRPNItem): Boolean;
|
||||
var
|
||||
sheetIndex: Integer;
|
||||
r1, c1, r2, c2: Cardinal;
|
||||
flags: TsRelFlags;
|
||||
begin
|
||||
Result := true;
|
||||
sheetIndex := WordLEToN(AStream.ReadWord);
|
||||
if FBiff8ExternSheets[sheetIndex].ExternBookIndex <> 0 then
|
||||
exit(false);
|
||||
ReadRPNCellRangeAddress(AStream, r1, c1, r2, c2, flags);
|
||||
if r2 = $FFFF then r2 := Cardinal(-1);
|
||||
if c2 = $FF then c2 := Cardinal(-1);
|
||||
ARPNItem := RPNCellRange3D(
|
||||
FBiff8ExternSheets[sheetIndex].FirstSheetIndex, r1, c1,
|
||||
FBiff8ExternSheets[sheetIndex].LastSheetIndex, r2, c2,
|
||||
flags, ARPNItem);
|
||||
end;
|
||||
|
||||
{ Reads the difference between row and column corner indexes of a cell range
|
||||
and a reference cell.
|
||||
Overriding the implementation in xlscommon. }
|
||||
@ -1628,6 +1662,84 @@ begin
|
||||
FCellFormatList.Add(fmt);
|
||||
end;
|
||||
|
||||
{ Reads a DEFINEDNAME record. Currently only extract print ranges and titles. }
|
||||
procedure TsSpreadBIFF8Reader.ReadDEFINEDNAME(const AStream: TStream);
|
||||
var
|
||||
options: Word;
|
||||
len: byte;
|
||||
formulaSize: Word;
|
||||
widestr: WideString;
|
||||
defName: String;
|
||||
rpnformula: TsRPNFormula;
|
||||
rtf: TsRichTextParams;
|
||||
validOnSheet: Integer;
|
||||
begin
|
||||
// Options
|
||||
options := WordLEToN(AStream.ReadWord);
|
||||
if options and $0020 = 0 then // only support built-in names at the moment!
|
||||
exit;
|
||||
|
||||
// Keyboard shortcut --> ignore
|
||||
AStream.ReadByte;
|
||||
|
||||
// Length of name (character count)
|
||||
len := AStream.ReadByte;
|
||||
|
||||
// Size of formula data
|
||||
formulasize := WordLEToN(AStream.ReadWord);
|
||||
|
||||
// not used
|
||||
AStream.ReadWord;
|
||||
|
||||
// Sheet index (1-based) on which the name is valid (0 = global)
|
||||
validOnSheet := SmallInt(WordLEToN(AStream.ReadWord)) - 1; // now 0-based!
|
||||
|
||||
// Length of Menu text (ignore)
|
||||
AStream.ReadByte;
|
||||
|
||||
// Length of description text(ignore)
|
||||
AStream.ReadByte;
|
||||
|
||||
// Length of help topic text (ignore)
|
||||
AStream.ReadByte;
|
||||
|
||||
// Length of status bar text (ignore)
|
||||
AStream.ReadByte;
|
||||
|
||||
// Name
|
||||
wideStr := ReadWideString(AStream, len, rtf);
|
||||
defName := UTF8Encode(widestr);
|
||||
|
||||
// Formula
|
||||
if not ReadRPNTokenArray(AStream, formulaSize, rpnFormula) then
|
||||
exit;
|
||||
// Store defined name in internal list
|
||||
FDefinedNames.Add(TsBIFFDefinedName.Create(defName, rpnFormula, validOnSheet));
|
||||
|
||||
// Skip rest...
|
||||
end;
|
||||
|
||||
{ Reads an EXTERNSHEET record. Needed for named cells and print ranges. }
|
||||
procedure TsSpreadBIFF8Reader.ReadEXTERNSHEET(const AStream: TStream);
|
||||
var
|
||||
numItems: Word;
|
||||
i: Integer;
|
||||
begin
|
||||
numItems := WordLEToN(AStream.ReadWord);
|
||||
SetLength(FBiff8ExternSheets, numItems);
|
||||
|
||||
for i := 0 to numItems-1 do begin
|
||||
AStream.ReadBuffer(FBiff8ExternSheets[i], Sizeof(FBiff8ExternSheets[i]));
|
||||
with FBiff8ExternSheets[i] do
|
||||
begin
|
||||
ExternBookIndex := WordLEToN(ExternBookIndex);
|
||||
FirstSheetIndex := WordLEToN(FirstSheetIndex);
|
||||
LastSheetIndex := WordLEToN(LastSheetIndex);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ Reads a FONT record. The retrieved font is stored in the workbook's FontList. }
|
||||
procedure TsSpreadBIFF8Reader.ReadFONT(const AStream: TStream);
|
||||
var
|
||||
@ -1761,7 +1873,7 @@ end;
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Reads a HYPERLINK record
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsSpreadBIFF8Reader.ReadHyperlink(AStream: TStream);
|
||||
procedure TsSpreadBIFF8Reader.ReadHyperlink(const AStream: TStream);
|
||||
var
|
||||
row, col, row1, col1, row2, col2: word;
|
||||
guid: TGUID;
|
||||
@ -1902,7 +2014,7 @@ end;
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Reads a HYPERLINK TOOLTIP record
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsSpreadBIFF8Reader.ReadHyperlinkToolTip(AStream: TStream);
|
||||
procedure TsSpreadBIFF8Reader.ReadHyperlinkToolTip(const AStream: TStream);
|
||||
var
|
||||
txt: String;
|
||||
widestr: widestring;
|
||||
|
@ -12,7 +12,7 @@ interface
|
||||
uses
|
||||
Classes, SysUtils, DateUtils, lconvencoding,
|
||||
fpsTypes, fpSpreadsheet, fpsUtils, fpsNumFormatParser, fpsPalette,
|
||||
fpsReaderWriter;
|
||||
fpsReaderWriter, fpsrpn;
|
||||
|
||||
const
|
||||
{ RECORD IDs which didn't change across versions 2-8 }
|
||||
@ -349,6 +349,21 @@ type
|
||||
RecordSize: Word;
|
||||
end;
|
||||
|
||||
{TsBIFFDefinedName }
|
||||
TsBIFFDefinedName = class
|
||||
private
|
||||
FName: String;
|
||||
FFormula: TsRPNFormula;
|
||||
FValidOnSheet: Integer;
|
||||
function GetRanges: TsCellRange3dArray;
|
||||
public
|
||||
constructor Create(AName: String; AFormula: TsRPNFormula; AValidOnSheet: Integer);
|
||||
procedure UpdateSheetIndex(ASheetName: String; ASheetIndex: Integer);
|
||||
property Name: String read FName;
|
||||
property Ranges: TsCellRange3dArray read GetRanges;
|
||||
property ValidOnSheet: Integer read FValidOnSheet;
|
||||
end;
|
||||
|
||||
{ TsSpreadBIFFReader }
|
||||
TsSpreadBIFFReader = class(TsCustomSpreadReader)
|
||||
protected
|
||||
@ -360,9 +375,11 @@ type
|
||||
FIncompleteNoteLength: Word;
|
||||
FFirstNumFormatIndexInFile: Integer;
|
||||
FPalette: TsPalette;
|
||||
FDefinedNames: TFPList;
|
||||
FWorksheetNames: TStrings;
|
||||
FCurrentWorksheet: Integer;
|
||||
FCurSheetIndex: Integer;
|
||||
FActivePane: Integer;
|
||||
FExternSheets: TStrings;
|
||||
|
||||
procedure AddBuiltinNumFormats; override;
|
||||
procedure ApplyCellFormatting(ACell: PCell; XFIndex: Word); virtual;
|
||||
@ -375,7 +392,11 @@ type
|
||||
// Returns the numberformat for a given XF record
|
||||
procedure ExtractNumberFormat(AXFIndex: WORD;
|
||||
out ANumberFormat: TsNumberFormat; out ANumberFormatStr: String); virtual;
|
||||
procedure ExtractPrintRanges(AWorksheet: TsWorksheet);
|
||||
procedure ExtractPrintTitles(AWorksheet: TsWorksheet);
|
||||
function FindDefinedName(AWorksheet: TsWorksheet; const AName: String): TsBiffDefinedName;
|
||||
procedure FixColors;
|
||||
procedure FixDefinedNames(AWorksheet: TsWorksheet);
|
||||
function FixFontIndex(AFontIndex: Integer): Integer;
|
||||
// Tries to find if a number cell is actually a date/datetime/time cell and retrieves the value
|
||||
function IsDateTime(Number: Double; ANumberFormat: TsNumberFormat;
|
||||
@ -397,6 +418,8 @@ type
|
||||
procedure ReadDefColWidth(AStream: TStream);
|
||||
// Read the default row height
|
||||
procedure ReadDefRowHeight(AStream: TStream);
|
||||
// Read an EXTERNSHEET record (defined names)
|
||||
procedure ReadExternSheet(AStream: TStream);
|
||||
// Read FORMAT record (cell formatting)
|
||||
procedure ReadFormat(AStream: TStream); virtual;
|
||||
// Read FORMULA record
|
||||
@ -431,13 +454,17 @@ type
|
||||
out ARowOffset, AColOffset: Integer; out AFlags: TsRelFlags); virtual;
|
||||
procedure ReadRPNCellRangeAddress(AStream: TStream;
|
||||
out ARow1, ACol1, ARow2, ACol2: Cardinal; out AFlags: TsRelFlags); virtual;
|
||||
function ReadRPNCellRange3D(AStream: TStream; var ARPNItem: PRPNItem): Boolean; virtual;
|
||||
procedure ReadRPNCellRangeOffset(AStream: TStream;
|
||||
out ARow1Offset, ACol1Offset, ARow2Offset, ACol2Offset: Integer;
|
||||
out AFlags: TsRelFlags); virtual;
|
||||
function ReadRPNFunc(AStream: TStream): Word; virtual;
|
||||
procedure ReadRPNSharedFormulaBase(AStream: TStream; out ARow, ACol: Cardinal); virtual;
|
||||
function ReadRPNTokenArray(AStream: TStream; ACell: PCell;
|
||||
ASharedFormulaBase: PCell = nil): Boolean;
|
||||
ASharedFormulaBase: PCell = nil): Boolean; overload;
|
||||
function ReadRPNTokenArray(AStream: TStream; ARpnTokenArraySize: Word;
|
||||
out ARpnFormula: TsRPNFormula; ACell: PCell = nil;
|
||||
ASharedFormulaBase: PCell = nil): Boolean; overload;
|
||||
function ReadRPNTokenArraySize(AStream: TStream): word; virtual;
|
||||
procedure ReadSELECTION(AStream: TStream);
|
||||
procedure ReadSharedFormula(AStream: TStream);
|
||||
@ -599,7 +626,8 @@ implementation
|
||||
uses
|
||||
AVL_Tree, Math, Variants,
|
||||
{%H-}fpspatches, fpsStrings, fpsClasses, fpsNumFormat, xlsConst,
|
||||
fpsrpn, fpsExprParser;
|
||||
//fpsrpn,
|
||||
fpsExprParser;
|
||||
|
||||
const
|
||||
{ Helper table for rpn formulas:
|
||||
@ -610,6 +638,8 @@ const
|
||||
INT_EXCEL_TOKEN_TREFR, {fekCellRef}
|
||||
INT_EXCEL_TOKEN_TAREA_R, {fekCellRange}
|
||||
INT_EXCEL_TOKEN_TREFN_V, {fekCellOffset}
|
||||
INT_EXCEL_TOKEN_TREF3D_R, {fekCellRef3d }
|
||||
INT_EXCEL_TOKEN_TAREA3D_R, {fekCellRange3d }
|
||||
INT_EXCEL_TOKEN_TNUM, {fekNum}
|
||||
INT_EXCEL_TOKEN_TINT, {fekInteger}
|
||||
INT_EXCEL_TOKEN_TSTR, {fekString}
|
||||
@ -633,6 +663,7 @@ const
|
||||
INT_EXCEL_TOKEN_TLT, {fekLess <}
|
||||
INT_EXCEL_TOKEN_TLE, {fekLessEqual, <=}
|
||||
INT_EXCEL_TOKEN_TNE, {fekNotEqual, <>}
|
||||
INT_EXCEL_TOKEN_TLIST, {List operator (",")}
|
||||
INT_EXCEL_TOKEN_TPAREN, {Operator in parenthesis}
|
||||
Word(-1) {fekFunc}
|
||||
);
|
||||
@ -820,6 +851,76 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ TsBIFFDefinedName }
|
||||
{------------------------------------------------------------------------------}
|
||||
constructor TsBIFFDefinedName.Create(AName: String; AFormula: TsRPNFormula;
|
||||
AValidOnSheet: Integer);
|
||||
begin
|
||||
FName := AName;
|
||||
FFormula := AFormula;
|
||||
FValidOnSheet := AValidOnSheet;
|
||||
end;
|
||||
|
||||
function TsBIFFDefinedName.GetRanges: TsCellRange3dArray;
|
||||
var
|
||||
i, n: Integer;
|
||||
elem: TsFormulaElement;
|
||||
begin
|
||||
SetLength(Result, 0);
|
||||
for i:=0 to Length(FFormula)-1 do begin
|
||||
n := Length(Result);
|
||||
elem := FFormula[i];
|
||||
case elem.ElementKind of
|
||||
fekCellRef3D:
|
||||
begin
|
||||
SetLength(Result, n+1);
|
||||
Result[n].Sheet1 := elem.Sheet;
|
||||
Result[n].Row1 := elem.Row;
|
||||
Result[n].Col1 := elem.Col;
|
||||
Result[n].Sheet2 := -1;
|
||||
Result[n].Row2 := Cardinal(-1);
|
||||
Result[n].Col2 := Cardinal(-1);
|
||||
end;
|
||||
fekCellRange3d:
|
||||
begin
|
||||
SetLength(Result, n+1);
|
||||
Result[n].Sheet1 := elem.Sheet;
|
||||
Result[n].Row1 := elem.Row;
|
||||
Result[n].Col1 := elem.Col;
|
||||
Result[n].Sheet2 := elem.Sheet2;
|
||||
Result[n].Row2 := elem.Row2;
|
||||
Result[n].Col2 := elem.Col2;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsBIFFDefinedName.UpdateSheetIndex(ASheetName: String; ASheetIndex: Integer);
|
||||
var
|
||||
elem: TsFormulaElement;
|
||||
i, p: Integer;
|
||||
s: String;
|
||||
begin
|
||||
for i:=0 to Length(FFormula)-1 do begin
|
||||
elem := FFormula[i];
|
||||
if (elem.ElementKind in [fekCellRef3d, fekCellRange3d]) then begin
|
||||
if elem.SheetNames = '' then
|
||||
Continue;
|
||||
p := pos(#9, elem.SheetNames);
|
||||
if p > 0 then begin
|
||||
if ASheetName = Copy(elem.SheetNames, 1, p-1) then
|
||||
elem.Sheet := ASheetIndex;
|
||||
if ASheetName = Copy(elem.SheetNames, p+1, MaxInt) then
|
||||
elem.Sheet2 := ASheetIndex;
|
||||
end else
|
||||
if ASheetName = elem.SheetNames then
|
||||
elem.Sheet := ASheetIndex;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ TsSpreadBIFFReader }
|
||||
{------------------------------------------------------------------------------}
|
||||
@ -834,6 +935,9 @@ begin
|
||||
FCellFormatList := TsCellFormatList.Create(true);
|
||||
// true = allow duplicates! XF indexes get out of sync if not all format records are in list
|
||||
|
||||
FExternSheets := TStringList.Create;
|
||||
FDefinedNames := TFPList.Create;
|
||||
|
||||
// Initial base date in case it won't be read from file
|
||||
FDateMode := dm1900;
|
||||
|
||||
@ -850,8 +954,15 @@ end;
|
||||
Destructor of the reader class
|
||||
-------------------------------------------------------------------------------}
|
||||
destructor TsSpreadBIFFReader.Destroy;
|
||||
var
|
||||
j: Integer;
|
||||
begin
|
||||
for j:=0 to FDefinedNames.Count-1 do TObject(FDefinedNames[j]).Free;
|
||||
FDefinedNames.Free;
|
||||
|
||||
FExternSheets.Free;
|
||||
FPalette.Free;
|
||||
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
@ -982,6 +1093,64 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsSpreadBiffReader.ExtractPrintRanges(AWorksheet: TsWorksheet);
|
||||
var
|
||||
defName: TsBiffDefinedName;
|
||||
rng: TsCellRange3DArray;
|
||||
i: Integer;
|
||||
begin
|
||||
// #6 is the symbol for "Print_Area"
|
||||
defName := FindDefinedName(AWorksheet, #6);
|
||||
if defName <> nil then
|
||||
begin
|
||||
rng := defName.Ranges;
|
||||
for i := 0 to High(rng) do
|
||||
AWorksheet.AddPrintRange(rng[i].Row1, rng[i].Col1, rng[i].Row2, rng[i].Col2);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsSpreadBiffReader.ExtractPrintTitles(AWorksheet: TsWorksheet);
|
||||
var
|
||||
defName: TsBiffDefinedName;
|
||||
rng: TsCellRange3dArray;
|
||||
i: Integer;
|
||||
begin
|
||||
// #7 is the symbol for "Print_Titles"
|
||||
defName := FindDefinedName(AWorksheet, #7);
|
||||
if defName <> nil then
|
||||
begin
|
||||
rng := defName.Ranges;
|
||||
for i := 0 to High(rng) do
|
||||
begin
|
||||
if (rng[i].Col2 <> Cardinal(-1)) then
|
||||
AWorksheet.SetRepeatedPrintCols(rng[i].Col1, rng[i].Col2)
|
||||
else
|
||||
if (rng[i].Row2 <> Cardinal(-1)) then
|
||||
AWorksheet.SetRepeatedPrintRows(rng[i].Row1, rng[i].Row2);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsSpreadBIffReader.FindDefinedName(AWorksheet: TsWorksheet;
|
||||
const AName: String): TsBiffDefinedName;
|
||||
var
|
||||
i: integer;
|
||||
wi: Integer;
|
||||
defName: TsBiffDefinedName;
|
||||
begin
|
||||
wi := FWorkbook.GetWorksheetIndex(AWorksheet);
|
||||
for i := 0 to FDefinedNames.Count-1 do
|
||||
begin
|
||||
defName := TsBiffDefinedName(FDefinedNames[i]);
|
||||
if (defName.ValidOnSheet = wi) and (defName.Name = AName) then
|
||||
begin
|
||||
Result := TsBiffDefinedName(FDefinedNames[i]);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
It is a problem of the biff file structure that the font is loaded before the
|
||||
palette. Therefore, when reading the font, we cannot determine its rgb color.
|
||||
@ -1029,6 +1198,21 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFFReader.FixDefinedNames(AWorksheet: TsWorksheet);
|
||||
var
|
||||
sheetName1, sheetName2: String;
|
||||
i: Integer;
|
||||
defname: TsBiffDefinedName;
|
||||
sheetIndex: Integer;
|
||||
begin
|
||||
sheetIndex := FWorkbook.GetWorksheetIndex(AWorksheet);
|
||||
for i:=0 to FDefinedNames.Count-1 do begin
|
||||
defname := TsBiffDefinedName(FDefinedNames.Items[i]);
|
||||
defname.UpdateSheetIndex(AWorksheet.Name, sheetIndex);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Converts the index of a font in the reader fontlist to the index of this font
|
||||
in the workbook's fontlist. If the font is not yet contained in the workbook
|
||||
@ -1349,6 +1533,30 @@ begin
|
||||
FWorksheet.DefaultRowHeight := h - ROW_HEIGHT_CORRECTION;
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
In the file format versions up to BIFF5 (incl) this record stores the name of
|
||||
an external document and a sheet name inside of this document.
|
||||
|
||||
NOTE: A character #03 is prepended to the sheet name if the EXTERNSHEET stores
|
||||
a reference to one of the own sheets.
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsSpreadBIFFReader.ReadExternSheet(AStream: TStream);
|
||||
var
|
||||
len, b: Byte;
|
||||
ansistr: AnsiString;
|
||||
s: String;
|
||||
begin
|
||||
len := AStream.ReadByte;
|
||||
b := AStream.ReadByte;
|
||||
if b = 3 then
|
||||
inc(len);
|
||||
SetLength(ansistr, len);
|
||||
AStream.ReadBuffer(ansistr[2], len-1);
|
||||
ansistr[1] := char(b);
|
||||
s := ConvertEncoding(ansistr, FCodePage, encodingUTF8);
|
||||
FExternSheets.Add(s);
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Reads the (number) FORMAT record for formatting numerical data
|
||||
To be overridden by descendants.
|
||||
@ -1957,6 +2165,13 @@ begin
|
||||
if (r2 and MASK_EXCEL_RELATIVE_ROW <> 0) then Include(AFlags, rfRelRow2);
|
||||
end;
|
||||
|
||||
function TsSpreadBIFFReader.ReadRPNCellRange3D(AStream: TStream;
|
||||
var ARPNItem: PRPNItem): Boolean;
|
||||
begin
|
||||
Result := false; // "false" means: "not supported"
|
||||
// must be overridden
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Reads the difference between row and column corner indexes of a cell range
|
||||
and a reference cell.
|
||||
@ -2024,6 +2239,7 @@ end;
|
||||
Reads the array of rpn tokens from the current stream position, creates an
|
||||
rpn formula, converts it to a string formula and stores it in the cell.
|
||||
-------------------------------------------------------------------------------}
|
||||
(*
|
||||
function TsSpreadBIFFReader.ReadRPNTokenArray(AStream: TStream;
|
||||
ACell: PCell; ASharedFormulaBase: PCell = nil): Boolean;
|
||||
var
|
||||
@ -2179,6 +2395,174 @@ begin
|
||||
Result := true;
|
||||
end;
|
||||
end;
|
||||
*)
|
||||
|
||||
function TsSpreadBIFFReader.ReadRPNTokenArray(AStream: TStream;
|
||||
ACell: PCell; ASharedFormulaBase: PCell = nil): Boolean;
|
||||
var
|
||||
n: Word;
|
||||
rpnFormula: TsRPNformula;
|
||||
strFormula: String;
|
||||
begin
|
||||
n := ReadRPNTokenArraySize(AStream);
|
||||
Result := ReadRPNTokenArray(AStream, n, rpnFormula, ACell, ASharedFormulaBase);
|
||||
if Result then begin
|
||||
strFormula := FWorksheet.ConvertRPNFormulaToStringFormula(rpnFormula);
|
||||
if strFormula <> '' then
|
||||
ACell^.FormulaValue := strFormula;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsSpreadBIFFReader.ReadRPNTokenArray(AStream: TStream;
|
||||
ARpnTokenArraySize: Word; out ARpnFormula: TsRPNFormula; ACell: PCell = nil;
|
||||
ASharedFormulaBase: PCell = nil): Boolean;
|
||||
var
|
||||
n: Word;
|
||||
p0: Int64;
|
||||
token: Byte;
|
||||
rpnItem: PRPNItem;
|
||||
supported: boolean;
|
||||
dblVal: Double = 0.0; // IEEE 8 byte floating point number
|
||||
flags: TsRelFlags;
|
||||
r, c, r2, c2: Cardinal;
|
||||
dr, dc, dr2, dc2: Integer;
|
||||
sheetIndex: Integer;
|
||||
fek: TFEKind;
|
||||
exprDef: TsBuiltInExprIdentifierDef;
|
||||
funcCode: Word;
|
||||
b: Byte;
|
||||
found: Boolean;
|
||||
begin
|
||||
rpnItem := nil;
|
||||
p0 := AStream.Position;
|
||||
supported := true;
|
||||
while (AStream.Position < p0 + ARPNTokenArraySize) and supported do begin
|
||||
token := AStream.ReadByte;
|
||||
case token of
|
||||
INT_EXCEL_TOKEN_TREFV:
|
||||
begin
|
||||
ReadRPNCellAddress(AStream, r, c, flags);
|
||||
rpnItem := RPNCellValue(r, c, flags, rpnItem);
|
||||
end;
|
||||
INT_EXCEL_TOKEN_TREFR:
|
||||
begin
|
||||
ReadRPNCellAddress(AStream, r, c, flags);
|
||||
rpnItem := RPNCellRef(r, c, flags, rpnItem);
|
||||
end;
|
||||
INT_EXCEL_TOKEN_TAREA_R, INT_EXCEL_TOKEN_TAREA_V:
|
||||
begin
|
||||
ReadRPNCellRangeAddress(AStream, r, c, r2, c2, flags);
|
||||
rpnItem := RPNCellRange(r, c, r2, c2, flags, rpnItem);
|
||||
end;
|
||||
INT_EXCEL_TOKEN_TREFN_R, INT_EXCEL_TOKEN_TREFN_V:
|
||||
begin
|
||||
ReadRPNCellAddressOffset(AStream, dr, dc, flags);
|
||||
// For compatibility with other formats, convert offsets back to regular indexes.
|
||||
if (rfRelRow in flags)
|
||||
then r := LongInt(ACell^.Row) + dr
|
||||
else r := dr;
|
||||
if (rfRelCol in flags)
|
||||
then c := LongInt(ACell^.Col) + dc
|
||||
else c := dc;
|
||||
case token of
|
||||
INT_EXCEL_TOKEN_TREFN_V: rpnItem := RPNCellValue(r, c, flags, rpnItem);
|
||||
INT_EXCEL_TOKEN_TREFN_R: rpnItem := RPNCellRef(r, c, flags, rpnItem);
|
||||
end;
|
||||
end;
|
||||
INT_EXCEL_TOKEN_TAREA3D_R:
|
||||
begin
|
||||
if not ReadRPNCellRange3D(AStream, rpnItem) then supported := false;
|
||||
end;
|
||||
INT_EXCEL_TOKEN_TREFN_A:
|
||||
begin
|
||||
ReadRPNCellRangeOffset(AStream, dr, dc, dr2, dc2, flags);
|
||||
// For compatibility with other formats, convert offsets back to regular indexes.
|
||||
if (rfRelRow in flags)
|
||||
then r := LongInt(ACell^.Row) + dr
|
||||
else r := LongInt(ASharedFormulaBase^.Row) + dr;
|
||||
if (rfRelRow2 in flags)
|
||||
then r2 := LongInt(ACell^.Row) + dr2
|
||||
else r2 := LongInt(ASharedFormulaBase^.Row) + dr2;
|
||||
if (rfRelCol in flags)
|
||||
then c := LongInt(ACell^.Col) + dc
|
||||
else c := LongInt(ASharedFormulaBase^.Col) + dc;
|
||||
if (rfRelCol2 in flags)
|
||||
then c2 := LongInt(ACell^.Col) + dc2
|
||||
else c2 := LongInt(ASharedFormulaBase^.Col) + dc2;
|
||||
rpnItem := RPNCellRange(r, c, r2, c2, flags, rpnItem);
|
||||
end;
|
||||
INT_EXCEL_TOKEN_TMISSARG:
|
||||
rpnItem := RPNMissingArg(rpnItem);
|
||||
INT_EXCEL_TOKEN_TSTR:
|
||||
rpnItem := RPNString(ReadString_8BitLen(AStream), rpnItem);
|
||||
INT_EXCEL_TOKEN_TERR:
|
||||
rpnItem := RPNErr(ConvertFromExcelError(AStream.ReadByte), rpnItem);
|
||||
INT_EXCEL_TOKEN_TBOOL:
|
||||
rpnItem := RPNBool(AStream.ReadByte=1, rpnItem);
|
||||
INT_EXCEL_TOKEN_TINT:
|
||||
rpnItem := RPNInteger(WordLEToN(AStream.ReadWord), rpnItem);
|
||||
INT_EXCEL_TOKEN_TNUM:
|
||||
begin
|
||||
AStream.ReadBuffer(dblVal, 8);
|
||||
rpnItem := RPNNumber(dblVal, rpnItem);
|
||||
end;
|
||||
INT_EXCEL_TOKEN_TPAREN:
|
||||
rpnItem := RPNParenthesis(rpnItem);
|
||||
|
||||
INT_EXCEL_TOKEN_FUNC_R,
|
||||
INT_EXCEL_TOKEN_FUNC_V,
|
||||
INT_EXCEL_TOKEN_FUNC_A:
|
||||
// functions with fixed argument count
|
||||
begin
|
||||
funcCode := ReadRPNFunc(AStream);
|
||||
exprDef := BuiltInIdentifiers.IdentifierByExcelCode(funcCode);
|
||||
if exprDef <> nil then
|
||||
rpnItem := RPNFunc(exprDef.Name, rpnItem)
|
||||
else
|
||||
supported := false;
|
||||
end;
|
||||
|
||||
INT_EXCEL_TOKEN_FUNCVAR_R,
|
||||
INT_EXCEL_TOKEN_FUNCVAR_V,
|
||||
INT_EXCEL_TOKEN_FUNCVAR_A:
|
||||
// functions with variable argument count
|
||||
begin
|
||||
b := AStream.ReadByte;
|
||||
funcCode := ReadRPNFunc(AStream);
|
||||
exprDef := BuiltinIdentifiers.IdentifierByExcelCode(funcCode);
|
||||
if exprDef <> nil then
|
||||
rpnItem := RPNFunc(exprDef.Name, b, rpnItem)
|
||||
else
|
||||
supported := false;
|
||||
end;
|
||||
|
||||
INT_EXCEL_TOKEN_TEXP:
|
||||
// Indicates that cell belongs to a shared or array formula.
|
||||
// This information is not needed any more.
|
||||
ReadRPNSharedFormulaBase(AStream, r, c);
|
||||
|
||||
else
|
||||
found := false;
|
||||
for fek in TBasicOperationTokens do
|
||||
if (TokenIDs[fek] = token) then begin
|
||||
rpnItem := RPNFunc(fek, rpnItem);
|
||||
found := true;
|
||||
break;
|
||||
end;
|
||||
if not found then
|
||||
supported := false;
|
||||
end;
|
||||
end;
|
||||
if not supported then begin
|
||||
DestroyRPNFormula(rpnItem);
|
||||
ARPNFormula := nil;
|
||||
Result := false;
|
||||
end
|
||||
else begin
|
||||
ARPNFormula := CreateRPNFormula(rpnItem, true); // true --> we have to flip the order of items!
|
||||
Result := true;
|
||||
end;
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Helper function for reading of the size of the token array of an RPN formula.
|
||||
@ -2385,19 +2769,9 @@ end;
|
||||
procedure TsSpreadBIFFReader.InternalReadFromStream(AStream: TStream);
|
||||
var
|
||||
BIFFEOF: Boolean;
|
||||
i: Integer;
|
||||
sheet: TsWorksheet;
|
||||
begin
|
||||
{ OLEStream := TMemoryStream.Create;
|
||||
try
|
||||
OLEStorage := TOLEStorage.Create;
|
||||
try
|
||||
// Only one stream is necessary for any number of worksheets
|
||||
OLEDocument.Stream := AStream; //OLEStream;
|
||||
OLEStorage.ReadOLEStream(AStream, OLEDocument, AStreamName);
|
||||
finally
|
||||
OLEStorage.Free;
|
||||
end;
|
||||
}
|
||||
|
||||
// Check if the operation succeeded
|
||||
if AStream.Size = 0 then
|
||||
raise Exception.Create('[TsSpreadBIFFReader.InternalReadFromStream] Reading of OLE document failed');
|
||||
@ -2408,7 +2782,7 @@ begin
|
||||
{Initializations }
|
||||
FWorksheetNames := TStringList.Create;
|
||||
try
|
||||
FCurrentWorksheet := 0;
|
||||
FCurSheetIndex := 0;
|
||||
BIFFEOF := false;
|
||||
|
||||
{ Read workbook globals }
|
||||
@ -2428,12 +2802,21 @@ begin
|
||||
BIFFEOF := true;
|
||||
|
||||
// Final preparations
|
||||
inc(FCurrentWorksheet);
|
||||
inc(FCurSheetIndex);
|
||||
// It can happen in files written by Office97 that the OLE directory is
|
||||
// at the end of the file.
|
||||
if FCurrentWorksheet = FWorksheetNames.Count then
|
||||
if FCurSheetIndex = FWorksheetNames.Count then
|
||||
BIFFEOF := true;
|
||||
end;
|
||||
|
||||
{ Extract print ranges, repeated rows/cols }
|
||||
for i:=0 to FWorkbook.GetWorksheetCount-1 do begin
|
||||
sheet := FWorkbook.GetWorksheetByIndex(i);
|
||||
FixDefinedNames(sheet);
|
||||
ExtractPrintRanges(sheet);
|
||||
ExtractPrintTitles(sheet);
|
||||
end;
|
||||
|
||||
finally
|
||||
{ Finalization }
|
||||
FreeAndNil(FWorksheetNames);
|
||||
|
@ -55,6 +55,12 @@ const
|
||||
INT_EXCEL_TOKEN_TAREAN_R = $2D;
|
||||
INT_EXCEL_TOKEN_TAREAN_V = $4D;
|
||||
INT_EXCEL_TOKEN_TAREAN_A = $6D;
|
||||
INT_EXCEL_TOKEN_TREF3d_R = $3A;
|
||||
INT_EXCEL_TOKEN_TREF3d_V = $5A;
|
||||
INT_EXCEL_TOKEN_TREF3d_A = $7A;
|
||||
INT_EXCEL_TOKEN_TAREA3d_R = $3B;
|
||||
INT_EXCEL_TOKEN_TAREA3d_V = $5B;
|
||||
INT_EXCEL_TOKEN_TAREA3d_A = $7B;
|
||||
|
||||
{ Function Tokens }
|
||||
// _R: reference; _V: value; _A: array
|
||||
|
Reference in New Issue
Block a user