You've already forked lazarus-ccr
fpspreadsheet: Read default column width and row height from biff and ooxml files
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3532 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -251,7 +251,7 @@ const
|
||||
|
||||
FALSE_TRUE: Array[boolean] of String = ('false', 'true');
|
||||
|
||||
COLWIDTH_EPS = 1e-2; // for mm
|
||||
COLWIDTH_EPS = 1e-2; // for mm
|
||||
ROWHEIGHT_EPS = 1e-2; // for lines
|
||||
|
||||
type
|
||||
|
@ -1066,11 +1066,13 @@ type
|
||||
FVirtualCell: TCell;
|
||||
{@@ Stores if the reader is in virtual mode }
|
||||
FIsVirtualMode: Boolean;
|
||||
|
||||
{ Helper methods }
|
||||
{@@ Removes column records if all of them have the same column width }
|
||||
procedure FixCols(AWorksheet: TsWorksheet);
|
||||
{@@ Removes row records if all of them have the same row height }
|
||||
procedure FixRows(AWorksheet: TsWorksheet);
|
||||
|
||||
{ Record reading methods }
|
||||
{@@ Abstract method for reading a blank cell. Must be overridden by descendent classes. }
|
||||
procedure ReadBlank(AStream: TStream); virtual; abstract;
|
||||
@ -6583,9 +6585,9 @@ end;
|
||||
|
||||
{@@
|
||||
Deletes unnecessary column records as they are written by Office applications
|
||||
when converting a file to another format.
|
||||
when they convert a file to another format.
|
||||
|
||||
@param AWorksheet The columns in this worksheet are processed.
|
||||
@param AWorksheet The columns in this worksheet are processed.
|
||||
}
|
||||
procedure TsCustomSpreadReader.FixCols(AWorkSheet: TsWorksheet);
|
||||
const
|
||||
@ -6593,20 +6595,10 @@ const
|
||||
var
|
||||
c: Cardinal;
|
||||
w: Single;
|
||||
cLast: Cardinal;
|
||||
begin
|
||||
if AWorksheet.Cols.Count = 0 then
|
||||
if AWorksheet.Cols.Count <= 1 then
|
||||
exit;
|
||||
|
||||
(* Better to avoid this...
|
||||
|
||||
// Delete all column records after the last column containing an existing cell.
|
||||
cLast := AWorksheet.GetLastOccupiedColIndex;
|
||||
for c := AWorksheet.Cols.Count-1 downto 0 do
|
||||
if PCol(AWorksheet.Cols[c])^.Col > cLast then
|
||||
AWorksheet.RemoveCol(c);
|
||||
*)
|
||||
|
||||
// Check whether all columns have the same column width
|
||||
w := PCol(AWorksheet.Cols[0])^.Width;
|
||||
for c := 1 to AWorksheet.Cols.Count-1 do
|
||||
@ -6617,11 +6609,6 @@ begin
|
||||
// to the DefaultColWidth and delete all column records.
|
||||
AWorksheet.DefaultColWidth := w;
|
||||
AWorksheet.RemoveAllCols;
|
||||
|
||||
// To do:
|
||||
// There's probably more to be done here, such as:
|
||||
// - if all columns have the same width except for a few use their width as
|
||||
// DefaultColWidth and delete these records.
|
||||
end;
|
||||
|
||||
{@@
|
||||
@ -6637,18 +6624,9 @@ var
|
||||
rLast: Cardinal;
|
||||
h: Single;
|
||||
begin
|
||||
if AWorksheet.Rows.Count = 0 then
|
||||
if AWorksheet.Rows.Count <= 1 then
|
||||
exit;
|
||||
|
||||
(* Better to avoid this...
|
||||
|
||||
// Delete all row records after the last row containing an existing cell.
|
||||
rLast := AWorksheet.GetLastOccupiedRowIndex;
|
||||
for r := AWorksheet.Rows.Count-1 downto 0 do
|
||||
if PRow(AWorksheet.Rows[r])^.Row > rLast then
|
||||
AWorksheet.RemoveRow(r);
|
||||
*)
|
||||
|
||||
// Check whether all rows have the same height
|
||||
h := PRow(AWorksheet.Rows[0])^.Height;
|
||||
for r := 1 to AWorksheet.Rows.Count-1 do
|
||||
@ -6659,11 +6637,6 @@ begin
|
||||
// to the DefaultRowHeight and delete all row records.
|
||||
AWorksheet.DefaultRowHeight := h;
|
||||
AWorksheet.RemoveAllRows;
|
||||
|
||||
// To do:
|
||||
// There's probably more to be done here, such as:
|
||||
// - if all rows have the same height except for a few use their height as
|
||||
// DefaultRowHeight and delete these records.
|
||||
end;
|
||||
|
||||
{@@
|
||||
|
@ -957,7 +957,8 @@ begin
|
||||
|
||||
numBytes := 2;
|
||||
Move(FBuffer[FBufferIndex], w, numbytes);
|
||||
ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)),
|
||||
w := WordLEToN(w);
|
||||
ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('%d (%f characters)', [w, w/256]),
|
||||
'Width of the columns in 1/256 of the width of the zero character, using default font (first FONT record in the file)');
|
||||
|
||||
numBytes := 2;
|
||||
|
@ -66,6 +66,7 @@ type
|
||||
out ANumberFormat: TsNumberFormat; out ANumberFormatStr: String); override;
|
||||
procedure ReadBlank(AStream: TStream); override;
|
||||
procedure ReadColWidth(AStream: TStream);
|
||||
procedure ReadDefRowHeight(AStream: TStream);
|
||||
procedure ReadFont(AStream: TStream);
|
||||
procedure ReadFontColor(AStream: TStream);
|
||||
procedure ReadFormat(AStream: TStream); override;
|
||||
@ -161,25 +162,26 @@ uses
|
||||
|
||||
const
|
||||
{ Excel record IDs }
|
||||
INT_EXCEL_ID_DIMENSIONS = $0000;
|
||||
INT_EXCEL_ID_BLANK = $0001;
|
||||
INT_EXCEL_ID_INTEGER = $0002;
|
||||
INT_EXCEL_ID_NUMBER = $0003;
|
||||
INT_EXCEL_ID_LABEL = $0004;
|
||||
INT_EXCEL_ID_ROW = $0008;
|
||||
INT_EXCEL_ID_BOF = $0009;
|
||||
{%H-}INT_EXCEL_ID_INDEX = $000B;
|
||||
INT_EXCEL_ID_FORMAT = $001E;
|
||||
INT_EXCEL_ID_FORMATCOUNT= $001F;
|
||||
INT_EXCEL_ID_COLWIDTH = $0024;
|
||||
INT_EXCEL_ID_WINDOW2 = $003E;
|
||||
INT_EXCEL_ID_XF = $0043;
|
||||
INT_EXCEL_ID_IXFE = $0044;
|
||||
INT_EXCEL_ID_FONTCOLOR = $0045;
|
||||
INT_EXCEL_ID_DIMENSIONS = $0000;
|
||||
INT_EXCEL_ID_BLANK = $0001;
|
||||
INT_EXCEL_ID_INTEGER = $0002;
|
||||
INT_EXCEL_ID_NUMBER = $0003;
|
||||
INT_EXCEL_ID_LABEL = $0004;
|
||||
INT_EXCEL_ID_ROW = $0008;
|
||||
INT_EXCEL_ID_BOF = $0009;
|
||||
{%H-}INT_EXCEL_ID_INDEX = $000B;
|
||||
INT_EXCEL_ID_FORMAT = $001E;
|
||||
INT_EXCEL_ID_FORMATCOUNT = $001F;
|
||||
INT_EXCEL_ID_COLWIDTH = $0024;
|
||||
INT_EXCEL_ID_DEFROWHEIGHT = 00025;
|
||||
INT_EXCEL_ID_WINDOW2 = $003E;
|
||||
INT_EXCEL_ID_XF = $0043;
|
||||
INT_EXCEL_ID_IXFE = $0044;
|
||||
INT_EXCEL_ID_FONTCOLOR = $0045;
|
||||
|
||||
{ BOF record constants }
|
||||
INT_EXCEL_SHEET = $0010;
|
||||
{%H-}INT_EXCEL_CHART = $0020;
|
||||
INT_EXCEL_SHEET = $0010;
|
||||
{%H-}INT_EXCEL_CHART = $0020;
|
||||
{%H-}INT_EXCEL_MACRO_SHEET = $0040;
|
||||
|
||||
type
|
||||
@ -423,9 +425,7 @@ var
|
||||
c, c1, c2: Cardinal;
|
||||
w: Word;
|
||||
col: TCol;
|
||||
sheet: TsWorksheet;
|
||||
begin
|
||||
sheet := Workbook.GetFirstWorksheet;
|
||||
// read column start and end index of column range
|
||||
c1 := AStream.ReadByte;
|
||||
c2 := AStream.ReadByte;
|
||||
@ -433,9 +433,21 @@ begin
|
||||
w := WordLEToN(AStream.ReadWord);
|
||||
// calculate width in units of "characters"
|
||||
col.Width := w / 256;
|
||||
// assign width to columns
|
||||
for c := c1 to c2 do
|
||||
sheet.WriteColInfo(c, col);
|
||||
// assign width to columns, but only if different from default column width.
|
||||
if not SameValue(col.Width, FWorksheet.DefaultColWidth) then
|
||||
for c := c1 to c2 do
|
||||
FWorksheet.WriteColInfo(c, col);
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF2Reader.ReadDefRowHeight(AStream: TStream);
|
||||
var
|
||||
hw: word;
|
||||
h : Single;
|
||||
begin
|
||||
hw := WordLEToN(AStream.ReadWord);
|
||||
h := TwipsToPts(hw and $8000) / FWorkbook.GetDefaultFontSize;
|
||||
if h > ROW_HEIGHT_CORRECTION then
|
||||
FWorksheet.DefaultRowHeight := h - ROW_HEIGHT_CORRECTION;
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF2Reader.ReadFont(AStream: TStream);
|
||||
@ -509,22 +521,24 @@ begin
|
||||
CurStreamPos := AStream.Position;
|
||||
|
||||
case RecordType of
|
||||
INT_EXCEL_ID_BLANK : ReadBlank(AStream);
|
||||
INT_EXCEL_ID_FONT : ReadFont(AStream);
|
||||
INT_EXCEL_ID_FONTCOLOR : ReadFontColor(AStream);
|
||||
INT_EXCEL_ID_FORMAT : ReadFormat(AStream);
|
||||
INT_EXCEL_ID_INTEGER : ReadInteger(AStream);
|
||||
INT_EXCEL_ID_NUMBER : ReadNumber(AStream);
|
||||
INT_EXCEL_ID_LABEL : ReadLabel(AStream);
|
||||
INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
|
||||
INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
|
||||
INT_EXCEL_ID_COLWIDTH : ReadColWidth(AStream);
|
||||
INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
|
||||
INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
|
||||
INT_EXCEL_ID_PANE : ReadPane(AStream);
|
||||
INT_EXCEL_ID_XF : ReadXF(AStream);
|
||||
INT_EXCEL_ID_BOF : ;
|
||||
INT_EXCEL_ID_EOF : BIFF2EOF := True;
|
||||
INT_EXCEL_ID_BLANK : ReadBlank(AStream);
|
||||
INT_EXCEL_ID_FONT : ReadFont(AStream);
|
||||
INT_EXCEL_ID_FONTCOLOR : ReadFontColor(AStream);
|
||||
INT_EXCEL_ID_FORMAT : ReadFormat(AStream);
|
||||
INT_EXCEL_ID_INTEGER : ReadInteger(AStream);
|
||||
INT_EXCEL_ID_NUMBER : ReadNumber(AStream);
|
||||
INT_EXCEL_ID_LABEL : ReadLabel(AStream);
|
||||
INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
|
||||
INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
|
||||
INT_EXCEL_ID_COLWIDTH : ReadColWidth(AStream);
|
||||
INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
|
||||
INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
|
||||
INT_EXCEL_ID_DEFROWHEIGHT: ReadDefRowHeight(AStream);
|
||||
INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
|
||||
INT_EXCEL_ID_PANE : ReadPane(AStream);
|
||||
INT_EXCEL_ID_XF : ReadXF(AStream);
|
||||
INT_EXCEL_ID_BOF : ;
|
||||
INT_EXCEL_ID_EOF : BIFF2EOF := True;
|
||||
else
|
||||
// nothing
|
||||
end;
|
||||
|
@ -82,13 +82,14 @@ type
|
||||
FCurrentWorksheet: Integer;
|
||||
protected
|
||||
{ Record writing methods }
|
||||
procedure ReadBoundsheet(AStream: TStream);
|
||||
procedure ReadFont(const AStream: TStream);
|
||||
procedure ReadFormat(AStream: TStream); override;
|
||||
procedure ReadLabel(AStream: TStream); override;
|
||||
procedure ReadWorkbookGlobals(AStream: TStream; AData: TsWorkbook);
|
||||
procedure ReadWorksheet(AStream: TStream; AData: TsWorkbook);
|
||||
procedure ReadBoundsheet(AStream: TStream);
|
||||
procedure ReadRichString(AStream: TStream);
|
||||
procedure ReadStandardWidth(AStream: TStream; ASheet: TsWorksheet);
|
||||
procedure ReadStringRecord(AStream: TStream); override;
|
||||
procedure ReadXF(AStream: TStream);
|
||||
public
|
||||
@ -221,38 +222,39 @@ const
|
||||
// see: in xlscommon
|
||||
|
||||
{ BOF record constants }
|
||||
INT_BOF_BIFF5_VER = $0500;
|
||||
INT_BOF_WORKBOOK_GLOBALS= $0005;
|
||||
{%H-}INT_BOF_VB_MODULE = $0006;
|
||||
INT_BOF_SHEET = $0010;
|
||||
{%H-}INT_BOF_CHART = $0020;
|
||||
{%H-}INT_BOF_MACRO_SHEET = $0040;
|
||||
{%H-}INT_BOF_WORKSPACE = $0100;
|
||||
INT_BOF_BUILD_ID = $1FD2;
|
||||
INT_BOF_BUILD_YEAR = $07CD;
|
||||
INT_BOF_BIFF5_VER = $0500;
|
||||
INT_BOF_WORKBOOK_GLOBALS = $0005;
|
||||
{%H-}INT_BOF_VB_MODULE = $0006;
|
||||
INT_BOF_SHEET = $0010;
|
||||
{%H-}INT_BOF_CHART = $0020;
|
||||
{%H-}INT_BOF_MACRO_SHEET = $0040;
|
||||
{%H-}INT_BOF_WORKSPACE = $0100;
|
||||
INT_BOF_BUILD_ID = $1FD2;
|
||||
INT_BOF_BUILD_YEAR = $07CD;
|
||||
|
||||
{ Record IDs }
|
||||
INT_EXCEL_ID_STANDARDWIDTH = $0099;
|
||||
|
||||
{ FONT record constants }
|
||||
INT_FONT_WEIGHT_NORMAL = $0190;
|
||||
|
||||
{%H-}BYTE_ANSILatin1 = $00;
|
||||
{%H-}BYTE_SYSTEM_DEFAULT = $01;
|
||||
{%H-}BYTE_SYMBOL = $02;
|
||||
{%H-}BYTE_Apple_Roman = $4D;
|
||||
{%H-}BYTE_ANSILatin1 = $00;
|
||||
{%H-}BYTE_SYSTEM_DEFAULT = $01;
|
||||
{%H-}BYTE_SYMBOL = $02;
|
||||
{%H-}BYTE_Apple_Roman = $4D;
|
||||
{%H-}BYTE_ANSI_Japanese_Shift_JIS = $80;
|
||||
{%H-}BYTE_ANSI_Korean_Hangul = $81;
|
||||
{%H-}BYTE_ANSI_Korean_Johab = $81;
|
||||
{%H-}BYTE_ANSI_Korean_Hangul = $81;
|
||||
{%H-}BYTE_ANSI_Korean_Johab = $81;
|
||||
{%H-}BYTE_ANSI_Chinese_Simplified_GBK = $86;
|
||||
{%H-}BYTE_ANSI_Chinese_Traditional_BIG5 = $88;
|
||||
{%H-}BYTE_ANSI_Greek = $A1;
|
||||
{%H-}BYTE_ANSI_Turkish = $A2;
|
||||
{%H-}BYTE_ANSI_Vietnamese = $A3;
|
||||
{%H-}BYTE_ANSI_Hebrew = $B1;
|
||||
{%H-}BYTE_ANSI_Arabic = $B2;
|
||||
{%H-}BYTE_ANSI_Baltic = $BA;
|
||||
{%H-}BYTE_ANSI_Cyrillic = $CC;
|
||||
{%H-}BYTE_ANSI_Thai = $DE;
|
||||
{%H-}BYTE_ANSI_Latin2 = $EE;
|
||||
{%H-}BYTE_OEM_Latin1 = $FF;
|
||||
{%H-}BYTE_ANSI_Greek = $A1;
|
||||
{%H-}BYTE_ANSI_Turkish = $A2;
|
||||
{%H-}BYTE_ANSI_Vietnamese = $A3;
|
||||
{%H-}BYTE_ANSI_Hebrew = $B1;
|
||||
{%H-}BYTE_ANSI_Arabic = $B2;
|
||||
{%H-}BYTE_ANSI_Baltic = $BA;
|
||||
{%H-}BYTE_ANSI_Cyrillic = $CC;
|
||||
{%H-}BYTE_ANSI_Thai = $DE;
|
||||
{%H-}BYTE_ANSI_Latin2 = $EE;
|
||||
{%H-}BYTE_OEM_Latin1 = $FF;
|
||||
|
||||
{ FORMULA record constants }
|
||||
{%H-}MASK_FORMULA_RECALCULATE_ALWAYS = $0001;
|
||||
@ -1160,22 +1162,24 @@ begin
|
||||
|
||||
case RecordType of
|
||||
|
||||
INT_EXCEL_ID_BLANK : ReadBlank(AStream);
|
||||
INT_EXCEL_ID_MULBLANK : ReadMulBlank(AStream);
|
||||
INT_EXCEL_ID_NUMBER : ReadNumber(AStream);
|
||||
INT_EXCEL_ID_LABEL : ReadLabel(AStream);
|
||||
INT_EXCEL_ID_RSTRING : ReadRichString(AStream); //(RSTRING) This record stores a formatted text cell (Rich-Text). In BIFF8 it is usually replaced by the LABELSST record. Excel still uses this record, if it copies formatted text cells to the clipboard.
|
||||
INT_EXCEL_ID_RK : ReadRKValue(AStream); //(RK) This record represents a cell that contains an RK value (encoded integer or floating-point value). If a floating-point value cannot be encoded to an RK value, a NUMBER record will be written. This record replaces the record INTEGER written in BIFF2.
|
||||
INT_EXCEL_ID_MULRK : ReadMulRKValues(AStream);
|
||||
INT_EXCEL_ID_COLINFO : ReadColInfo(AStream);
|
||||
INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
|
||||
INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
|
||||
INT_EXCEL_ID_SHAREDFMLA: ReadSharedFormula(AStream);
|
||||
INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
|
||||
INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
|
||||
INT_EXCEL_ID_PANE : ReadPane(AStream);
|
||||
INT_EXCEL_ID_BOF : ;
|
||||
INT_EXCEL_ID_EOF : SectionEOF := True;
|
||||
INT_EXCEL_ID_BLANK : ReadBlank(AStream);
|
||||
INT_EXCEL_ID_MULBLANK : ReadMulBlank(AStream);
|
||||
INT_EXCEL_ID_NUMBER : ReadNumber(AStream);
|
||||
INT_EXCEL_ID_LABEL : ReadLabel(AStream);
|
||||
INT_EXCEL_ID_RSTRING : ReadRichString(AStream); //(RSTRING) This record stores a formatted text cell (Rich-Text). In BIFF8 it is usually replaced by the LABELSST record. Excel still uses this record, if it copies formatted text cells to the clipboard.
|
||||
INT_EXCEL_ID_RK : ReadRKValue(AStream); //(RK) This record represents a cell that contains an RK value (encoded integer or floating-point value). If a floating-point value cannot be encoded to an RK value, a NUMBER record will be written. This record replaces the record INTEGER written in BIFF2.
|
||||
INT_EXCEL_ID_MULRK : ReadMulRKValues(AStream);
|
||||
INT_EXCEL_ID_COLINFO : ReadColInfo(AStream);
|
||||
INT_EXCEL_ID_STANDARDWIDTH : ReadStandardWidth(AStream, FWorksheet);
|
||||
INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
|
||||
INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
|
||||
INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
|
||||
INT_EXCEL_ID_SHAREDFMLA : ReadSharedFormula(AStream);
|
||||
INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
|
||||
INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
|
||||
INT_EXCEL_ID_PANE : ReadPane(AStream);
|
||||
INT_EXCEL_ID_BOF : ;
|
||||
INT_EXCEL_ID_EOF : SectionEOF := True;
|
||||
|
||||
{$IFDEF FPSPREADDEBUG} // Only write out if debugging
|
||||
else
|
||||
@ -1291,6 +1295,20 @@ begin
|
||||
Workbook.OnReadCellData(Workbook, ARow, ACol, cell);
|
||||
end;
|
||||
|
||||
{ Reads the default column width that is used when a bit in the GCW bit structure
|
||||
is set for the corresponding column. The GCW is ignored here. The column
|
||||
width read from the STANDARDWIDTH record overrides the one from the
|
||||
DEFCOLWIDTH record. }
|
||||
procedure TsSpreadBIFF5Reader.ReadStandardWidth(AStream: TStream; ASheet: TsWorksheet);
|
||||
var
|
||||
w: Word;
|
||||
begin
|
||||
// read width in 1/256 of the width of "0" character
|
||||
w := WordLEToN(AStream.ReadWord);
|
||||
// calculate width in units of "characters" and use it as DefaultColWidth
|
||||
ASheet.DefaultColWidth := w / 256;
|
||||
end;
|
||||
|
||||
{ Reads a STRING record which contains the result of string formula. }
|
||||
procedure TsSpreadBIFF5Reader.ReadStringRecord(AStream: TStream);
|
||||
var
|
||||
|
@ -1430,30 +1430,31 @@ begin
|
||||
|
||||
case RecordType of
|
||||
|
||||
INT_EXCEL_ID_BLANK : ReadBlank(AStream);
|
||||
INT_EXCEL_ID_MULBLANK : ReadMulBlank(AStream);
|
||||
INT_EXCEL_ID_NUMBER : ReadNumber(AStream);
|
||||
INT_EXCEL_ID_LABEL : ReadLabel(AStream);
|
||||
INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
|
||||
INT_EXCEL_ID_SHAREDFMLA: ReadSharedFormula(AStream);
|
||||
INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
|
||||
INT_EXCEL_ID_BLANK : ReadBlank(AStream);
|
||||
INT_EXCEL_ID_MULBLANK : ReadMulBlank(AStream);
|
||||
INT_EXCEL_ID_NUMBER : ReadNumber(AStream);
|
||||
INT_EXCEL_ID_LABEL : ReadLabel(AStream);
|
||||
INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
|
||||
INT_EXCEL_ID_SHAREDFMLA : ReadSharedFormula(AStream);
|
||||
INT_EXCEL_ID_STRING : ReadStringRecord(AStream);
|
||||
//(RSTRING) This record stores a formatted text cell (Rich-Text).
|
||||
// In BIFF8 it is usually replaced by the LABELSST record. Excel still
|
||||
// uses this record, if it copies formatted text cells to the clipboard.
|
||||
INT_EXCEL_ID_RSTRING : ReadRichString(AStream);
|
||||
INT_EXCEL_ID_RSTRING : ReadRichString(AStream);
|
||||
// (RK) This record represents a cell that contains an RK value
|
||||
// (encoded integer or floating-point value). If a floating-point
|
||||
// value cannot be encoded to an RK value, a NUMBER record will be written.
|
||||
// This record replaces the record INTEGER written in BIFF2.
|
||||
INT_EXCEL_ID_RK : ReadRKValue(AStream);
|
||||
INT_EXCEL_ID_MULRK : ReadMulRKValues(AStream);
|
||||
INT_EXCEL_ID_LABELSST : ReadLabelSST(AStream); //BIFF8 only
|
||||
INT_EXCEL_ID_COLINFO : ReadColInfo(AStream);
|
||||
INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
|
||||
INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
|
||||
INT_EXCEL_ID_PANE : ReadPane(AStream);
|
||||
INT_EXCEL_ID_BOF : ;
|
||||
INT_EXCEL_ID_EOF : SectionEOF := True;
|
||||
INT_EXCEL_ID_RK : ReadRKValue(AStream);
|
||||
INT_EXCEL_ID_MULRK : ReadMulRKValues(AStream);
|
||||
INT_EXCEL_ID_LABELSST : ReadLabelSST(AStream); //BIFF8 only
|
||||
INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
|
||||
INT_EXCEL_ID_COLINFO : ReadColInfo(AStream);
|
||||
INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
|
||||
INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
|
||||
INT_EXCEL_ID_PANE : ReadPane(AStream);
|
||||
INT_EXCEL_ID_BOF : ;
|
||||
INT_EXCEL_ID_EOF : SectionEOF := True;
|
||||
else
|
||||
// nothing
|
||||
end;
|
||||
|
@ -22,50 +22,52 @@ uses
|
||||
|
||||
const
|
||||
{ RECORD IDs which didn't change across versions 2-8 }
|
||||
INT_EXCEL_ID_EOF = $000A;
|
||||
INT_EXCEL_ID_SELECTION = $001D;
|
||||
INT_EXCEL_ID_CONTINUE = $003C;
|
||||
INT_EXCEL_ID_PANE = $0041;
|
||||
INT_EXCEL_ID_CODEPAGE = $0042;
|
||||
INT_EXCEL_ID_DATEMODE = $0022;
|
||||
INT_EXCEL_ID_WINDOW1 = $003D;
|
||||
INT_EXCEL_ID_EOF = $000A;
|
||||
INT_EXCEL_ID_SELECTION = $001D;
|
||||
INT_EXCEL_ID_CONTINUE = $003C;
|
||||
INT_EXCEL_ID_DATEMODE = $0022;
|
||||
INT_EXCEL_ID_WINDOW1 = $003D;
|
||||
INT_EXCEL_ID_PANE = $0041;
|
||||
INT_EXCEL_ID_CODEPAGE = $0042;
|
||||
INT_EXCEL_ID_DEFCOLWIDTH = $0055;
|
||||
|
||||
{ RECORD IDs which did not change across versions 2, 5, 8}
|
||||
INT_EXCEL_ID_FORMULA = $0006; // BIFF3: $0206, BIFF4: $0406
|
||||
INT_EXCEL_ID_FONT = $0031; // BIFF3-4: $0231
|
||||
INT_EXCEL_ID_FORMULA = $0006; // BIFF3: $0206, BIFF4: $0406
|
||||
INT_EXCEL_ID_FONT = $0031; // BIFF3-4: $0231
|
||||
|
||||
{ RECORD IDs which did not change across version 3-8}
|
||||
INT_EXCEL_ID_COLINFO = $007D; // does not exist in BIFF2
|
||||
INT_EXCEL_ID_SHEETPR = $0081; // does not exist in BIFF2
|
||||
INT_EXCEL_ID_COUNTRY = $008C; // does not exist in BIFF2
|
||||
INT_EXCEL_ID_PALETTE = $0092; // does not exist in BIFF2
|
||||
INT_EXCEL_ID_DIMENSIONS = $0200; // BIFF2: $0000
|
||||
INT_EXCEL_ID_BLANK = $0201; // BIFF2: $0001
|
||||
INT_EXCEL_ID_NUMBER = $0203; // BIFF2: $0003
|
||||
INT_EXCEL_ID_LABEL = $0204; // BIFF2: $0004
|
||||
INT_EXCEL_ID_STRING = $0207; // BIFF2: $0007
|
||||
INT_EXCEL_ID_ROW = $0208; // BIFF2: $0008
|
||||
INT_EXCEL_ID_INDEX = $020B; // BIFF2: $000B
|
||||
INT_EXCEL_ID_WINDOW2 = $023E; // BIFF2: $003E
|
||||
INT_EXCEL_ID_RK = $027E; // does not exist in BIFF2
|
||||
INT_EXCEL_ID_STYLE = $0293; // does not exist in BIFF2
|
||||
INT_EXCEL_ID_COLINFO = $007D; // does not exist in BIFF2
|
||||
INT_EXCEL_ID_SHEETPR = $0081; // does not exist in BIFF2
|
||||
INT_EXCEL_ID_COUNTRY = $008C; // does not exist in BIFF2
|
||||
INT_EXCEL_ID_PALETTE = $0092; // does not exist in BIFF2
|
||||
INT_EXCEL_ID_DIMENSIONS = $0200; // BIFF2: $0000
|
||||
INT_EXCEL_ID_BLANK = $0201; // BIFF2: $0001
|
||||
INT_EXCEL_ID_NUMBER = $0203; // BIFF2: $0003
|
||||
INT_EXCEL_ID_LABEL = $0204; // BIFF2: $0004
|
||||
INT_EXCEL_ID_STRING = $0207; // BIFF2: $0007
|
||||
INT_EXCEL_ID_ROW = $0208; // BIFF2: $0008
|
||||
INT_EXCEL_ID_INDEX = $020B; // BIFF2: $000B
|
||||
INT_EXCEL_ID_DEFROWHEIGHT= $0225; // BIFF2: $0025
|
||||
INT_EXCEL_ID_WINDOW2 = $023E; // BIFF2: $003E
|
||||
INT_EXCEL_ID_RK = $027E; // does not exist in BIFF2
|
||||
INT_EXCEL_ID_STYLE = $0293; // does not exist in BIFF2
|
||||
|
||||
{ RECORD IDs which did not change across version 4-8 }
|
||||
INT_EXCEL_ID_PAGESETUP = $00A1; // does not exist before BIFF4
|
||||
INT_EXCEL_ID_FORMAT = $041E; // BIFF2-3: $001E
|
||||
INT_EXCEL_ID_PAGESETUP = $00A1; // does not exist before BIFF4
|
||||
INT_EXCEL_ID_FORMAT = $041E; // BIFF2-3: $001E
|
||||
|
||||
{ RECORD IDs which did not change across versions 5-8 }
|
||||
INT_EXCEL_ID_BOUNDSHEET = $0085; // Renamed to SHEET in the latest OpenOffice docs, does not exist before 5
|
||||
INT_EXCEL_ID_MULRK = $00BD; // does not exist before BIFF5
|
||||
INT_EXCEL_ID_MULBLANK = $00BE; // does not exist before BIFF5
|
||||
INT_EXCEL_ID_XF = $00E0; // BIFF2:$0043, BIFF3:$0243, BIFF4:$0443
|
||||
INT_EXCEL_ID_RSTRING = $00D6; // does not exist before BIFF5
|
||||
INT_EXCEL_ID_SHAREDFMLA = $04BC; // does not exist before BIFF5
|
||||
INT_EXCEL_ID_BOF = $0809; // BIFF2:$0009, BIFF3:$0209; BIFF4:$0409
|
||||
INT_EXCEL_ID_BOUNDSHEET = $0085; // Renamed to SHEET in the latest OpenOffice docs, does not exist before 5
|
||||
INT_EXCEL_ID_MULRK = $00BD; // does not exist before BIFF5
|
||||
INT_EXCEL_ID_MULBLANK = $00BE; // does not exist before BIFF5
|
||||
INT_EXCEL_ID_XF = $00E0; // BIFF2:$0043, BIFF3:$0243, BIFF4:$0443
|
||||
INT_EXCEL_ID_RSTRING = $00D6; // does not exist before BIFF5
|
||||
INT_EXCEL_ID_SHAREDFMLA = $04BC; // does not exist before BIFF5
|
||||
INT_EXCEL_ID_BOF = $0809; // BIFF2:$0009, BIFF3:$0209; BIFF4:$0409
|
||||
|
||||
{ FONT record constants }
|
||||
INT_FONT_WEIGHT_NORMAL = $0190;
|
||||
INT_FONT_WEIGHT_BOLD = $02BC;
|
||||
INT_FONT_WEIGHT_NORMAL = $0190;
|
||||
INT_FONT_WEIGHT_BOLD = $02BC;
|
||||
|
||||
{ CODEPAGE record constants }
|
||||
WORD_ASCII = 367;
|
||||
@ -82,8 +84,8 @@ const
|
||||
WORD_CP_1258_Latin1_BIFF2_3 = 32769; // BIFF2-BIFF3
|
||||
|
||||
{ DATEMODE record, 5.28 }
|
||||
DATEMODE_1900_BASE=1; //1/1/1900 minus 1 day in FPC TDateTime
|
||||
DATEMODE_1904_BASE=1462; //1/1/1904 in FPC TDateTime
|
||||
DATEMODE_1900_BASE = 1; //1/1/1900 minus 1 day in FPC TDateTime
|
||||
DATEMODE_1904_BASE = 1462; //1/1/1904 in FPC TDateTime
|
||||
|
||||
{ WINDOW1 record constants - BIFF5-BIFF8 }
|
||||
MASK_WINDOW1_OPTION_WINDOW_HIDDEN = $0001;
|
||||
@ -245,6 +247,10 @@ type
|
||||
procedure ReadColInfo(const AStream: TStream);
|
||||
// Figures out what the base year for dates is for this file
|
||||
procedure ReadDateMode(AStream: TStream);
|
||||
// Reads the default column width
|
||||
procedure ReadDefColWidth(AStream: TStream);
|
||||
// Reas the default row height
|
||||
procedure ReadDefRowHeight(AStream: TStream);
|
||||
// Read FORMAT record (cell formatting)
|
||||
procedure ReadFormat(AStream: TStream); virtual;
|
||||
// Read FORMULA record
|
||||
@ -963,6 +969,8 @@ end;
|
||||
Valid for BIFF3-BIFF8.
|
||||
For BIFF2 use the records COLWIDTH and COLUMNDEFAULT. }
|
||||
procedure TsSpreadBiffReader.ReadColInfo(const AStream: TStream);
|
||||
const
|
||||
EPS = 1E-2; // allow for large epsilon because col width calculation is not very well-defined...
|
||||
var
|
||||
c, c1, c2: Cardinal;
|
||||
w: Word;
|
||||
@ -975,9 +983,10 @@ begin
|
||||
w := WordLEToN(AStream.ReadWord);
|
||||
// calculate width in units of "characters"
|
||||
col.Width := w / 256;
|
||||
// assign width to columns
|
||||
for c := c1 to c2 do
|
||||
FWorksheet.WriteColInfo(c, col);
|
||||
// assign width to columns, but only if different from default column width
|
||||
if not SameValue(col.Width, FWorksheet.DefaultColWidth, EPS) then
|
||||
for c := c1 to c2 do
|
||||
FWorksheet.WriteColInfo(c, col);
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFFReader.ReadDateMode(AStream: TStream);
|
||||
@ -1002,6 +1011,30 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
// Reads the default column width
|
||||
procedure TsSpreadBIFFReader.ReadDefColWidth(AStream: TStream);
|
||||
begin
|
||||
// The file contains the column width in characters
|
||||
FWorksheet.DefaultColWidth := WordLEToN(AStream.ReadWord);
|
||||
end;
|
||||
|
||||
// Reads the default row height
|
||||
// Valid for BIFF3 - BIFF8 (override for BIFF2)
|
||||
procedure TsSpreadBIFFReader.ReadDefRowHeight(AStream: TStream);
|
||||
var
|
||||
options, hw: Word;
|
||||
h: Single;
|
||||
begin
|
||||
// Options
|
||||
AStream.ReadWord;
|
||||
|
||||
// Height, in Twips (1/20 pt).
|
||||
hw := WordLEToN(AStream.ReadWord);
|
||||
h := TwipsToPts(hw) / FWorkbook.GetDefaultFontSize;
|
||||
if h > ROW_HEIGHT_CORRECTION then
|
||||
FWorksheet.DefaultRowHeight := h - ROW_HEIGHT_CORRECTION;
|
||||
end;
|
||||
|
||||
// Read the FORMAT record for formatting numerical data
|
||||
procedure TsSpreadBIFFReader.ReadFormat(AStream: TStream);
|
||||
begin
|
||||
|
@ -80,6 +80,7 @@ type
|
||||
procedure ReadPalette(ANode: TDOMNode);
|
||||
procedure ReadRowHeight(ANode: TDOMNode; AWorksheet: TsWorksheet);
|
||||
procedure ReadSharedStrings(ANode: TDOMNode);
|
||||
procedure ReadSheetFormatPr(ANode: TDOMNode; AWorksheet: TsWorksheet);
|
||||
procedure ReadSheetList(ANode: TDOMNode; AList: TStrings);
|
||||
procedure ReadSheetViews(ANode: TDOMNode; AWorksheet: TsWorksheet);
|
||||
procedure ReadThemeElements(ANode: TDOMNode);
|
||||
@ -866,6 +867,8 @@ begin
|
||||
end;
|
||||
|
||||
procedure TsSpreadOOXMLReader.ReadCols(ANode: TDOMNode; AWorksheet: TsWorksheet);
|
||||
const
|
||||
EPS = 1e-2;
|
||||
var
|
||||
colNode: TDOMNode;
|
||||
col, col1, col2: Cardinal;
|
||||
@ -884,11 +887,10 @@ begin
|
||||
s := GetAttrValue(colNode, 'max');
|
||||
if s <> '' then col2 := StrToInt(s)-1 else col2 := col1;
|
||||
s := GetAttrValue(colNode, 'width');
|
||||
if s <> '' then begin
|
||||
w := StrToFloat(s, FPointSeparatorSettings);
|
||||
for col := col1 to col2 do
|
||||
AWorksheet.WriteColWidth(col, w);
|
||||
end;
|
||||
if (s <> '') and TryStrToFloat(s, w, FPointSeparatorSettings) then
|
||||
if not SameValue(w, AWorksheet.DefaultColWidth, EPS) then
|
||||
for col := col1 to col2 do
|
||||
AWorksheet.WriteColWidth(col, w);
|
||||
end;
|
||||
colNode := colNode.NextSibling;
|
||||
end;
|
||||
@ -1189,6 +1191,29 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsSpreadOOXMLReader.ReadSheetFormatPr(ANode: TDOMNode;
|
||||
AWorksheet: TsWorksheet);
|
||||
var
|
||||
w, h: Single;
|
||||
s: String;
|
||||
begin
|
||||
if ANode = nil then
|
||||
exit;
|
||||
|
||||
s := GetAttrValue(ANode, 'defaultColWidth'); // is in characters
|
||||
if (s <> '') and TryStrToFloat(s, w, FPointSeparatorSettings) then
|
||||
AWorksheet.DefaultColWidth := w;
|
||||
|
||||
s := GetAttrValue(ANode, 'defaultRowHeight'); // in in points
|
||||
if (s <> '') and TryStrToFloat(s, h, FPointSeparatorSettings) then begin
|
||||
h := h / Workbook.GetDefaultFontSize;
|
||||
if h > ROW_HEIGHT_CORRECTION then begin
|
||||
h := h - ROW_HEIGHT_CORRECTION;
|
||||
AWorksheet.DefaultRowHeight := h;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsSpreadOOXMLReader.ReadSheetList(ANode: TDOMNode; AList: TStrings);
|
||||
var
|
||||
node: TDOMNode;
|
||||
@ -1340,8 +1365,8 @@ begin
|
||||
end;
|
||||
rownode := rownode.NextSibling;
|
||||
end;
|
||||
FixRows(AWorksheet);
|
||||
FixCols(AWorksheet);
|
||||
FixRows(AWorksheet);
|
||||
end;
|
||||
|
||||
procedure TsSpreadOOXMLReader.ReadFromFile(AFileName: string; AData: TsWorkbook);
|
||||
@ -1440,6 +1465,7 @@ begin
|
||||
FWorksheet := AData.AddWorksheet(SheetList[i]);
|
||||
|
||||
ReadSheetViews(Doc.DocumentElement.FindNode('sheetViews'), FWorksheet);
|
||||
ReadSheetFormatPr(Doc.DocumentElement.FindNode('sheetFormatPr'), FWorksheet);
|
||||
ReadCols(Doc.DocumentElement.FindNode('cols'), FWorksheet);
|
||||
ReadWorksheet(Doc.DocumentElement.FindNode('sheetData'), FWorksheet);
|
||||
|
||||
|
Reference in New Issue
Block a user