You've already forked lazarus-ccr
fpspreadsheet: Read/write biff2 column/row formats
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5254 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -52,6 +52,7 @@ type
|
|||||||
procedure AddBuiltinNumFormats; override;
|
procedure AddBuiltinNumFormats; override;
|
||||||
procedure ReadBlank(AStream: TStream); override;
|
procedure ReadBlank(AStream: TStream); override;
|
||||||
procedure ReadBool(AStream: TStream); override;
|
procedure ReadBool(AStream: TStream); override;
|
||||||
|
procedure ReadColumnDefault(AStream: TStream);
|
||||||
procedure ReadColWidth(AStream: TStream);
|
procedure ReadColWidth(AStream: TStream);
|
||||||
procedure ReadDefRowHeight(AStream: TStream);
|
procedure ReadDefRowHeight(AStream: TStream);
|
||||||
procedure ReadFONT(AStream: TStream);
|
procedure ReadFONT(AStream: TStream);
|
||||||
@ -82,36 +83,39 @@ type
|
|||||||
TsSpreadBIFF2Writer = class(TsSpreadBIFFWriter)
|
TsSpreadBIFF2Writer = class(TsSpreadBIFFWriter)
|
||||||
private
|
private
|
||||||
FSheetIndex: Integer; // Index of worksheet to be written
|
FSheetIndex: Integer; // Index of worksheet to be written
|
||||||
procedure GetCellAttributes(ACell: PCell; XFIndex: Word;
|
procedure GetAttributes(AFormatIndex: Integer; XFIndex: Word;
|
||||||
out Attrib1, Attrib2, Attrib3: Byte);
|
out Attrib1, Attrib2, Attrib3: Byte);
|
||||||
procedure GetFormatAndFontIndex(AFormatRecord: PsCellFormat;
|
procedure GetFormatAndFontIndex(AFormatRecord: PsCellFormat;
|
||||||
out AFormatIndex, AFontIndex: Integer);
|
out AFormatIndex, AFontIndex: Integer);
|
||||||
{ Record writing methods }
|
{ Record writing methods }
|
||||||
procedure WriteBOF(AStream: TStream);
|
procedure WriteBOF(AStream: TStream);
|
||||||
procedure WriteCellFormatting(AStream: TStream; ACell: PCell; XFIndex: Word);
|
procedure WriteCellAttributes(AStream: TStream; AFormatIndex: Integer; XFIndex: Word);
|
||||||
procedure WriteColWidth(AStream: TStream; ACol: PCol);
|
procedure WriteColWidth(AStream: TStream; ACol: PCol);
|
||||||
procedure WriteColWidths(AStream: TStream);
|
procedure WriteColWidths(AStream: TStream);
|
||||||
|
// procedure WriteColumnDefault(AStream: TStream; ACol: PCol);
|
||||||
|
procedure WriteColumnDefault(AStream: TStream;
|
||||||
|
AFirstColIndex, ALastColIndex: Word; AFormatIndex: Integer);
|
||||||
|
procedure WriteColumnDefaults(AStream: TStream);
|
||||||
|
procedure WriteDefaultRowHeight(AStream: TStream; AWorksheet: TsWorksheet);
|
||||||
procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
||||||
procedure WriteEOF(AStream: TStream);
|
procedure WriteEOF(AStream: TStream);
|
||||||
procedure WriteFont(AStream: TStream; AFontIndex: Integer);
|
procedure WriteFont(AStream: TStream; AFontIndex: Integer);
|
||||||
procedure WriteFonts(AStream: TStream);
|
procedure WriteFonts(AStream: TStream);
|
||||||
|
procedure WriteFORMATCOUNT(AStream: TStream);
|
||||||
procedure WriteIXFE(AStream: TStream; XFIndex: Word);
|
procedure WriteIXFE(AStream: TStream; XFIndex: Word);
|
||||||
protected
|
protected
|
||||||
procedure AddBuiltinNumFormats; override;
|
procedure AddBuiltinNumFormats; override;
|
||||||
function FunctionSupported(AExcelCode: Integer;
|
function FunctionSupported(AExcelCode: Integer;
|
||||||
const AFuncName: String): Boolean; override;
|
const AFuncName: String): Boolean; override;
|
||||||
// procedure ListAllNumFormats; override;
|
|
||||||
procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal;
|
procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal;
|
||||||
ACell: PCell); override;
|
ACell: PCell); override;
|
||||||
procedure WriteBool(AStream: TStream; const ARow, ACol: Cardinal;
|
procedure WriteBool(AStream: TStream; const ARow, ACol: Cardinal;
|
||||||
const AValue: Boolean; ACell: PCell); override;
|
const AValue: Boolean; ACell: PCell); override;
|
||||||
procedure WriteCodePage(AStream: TStream; ACodePage: String); override;
|
procedure WriteCodePage(AStream: TStream; ACodePage: String); override;
|
||||||
procedure WriteDefaultRowHeight(AStream: TStream; AWorksheet: TsWorksheet);
|
|
||||||
procedure WriteError(AStream: TStream; const ARow, ACol: Cardinal;
|
procedure WriteError(AStream: TStream; const ARow, ACol: Cardinal;
|
||||||
const AValue: TsErrorValue; ACell: PCell); override;
|
const AValue: TsErrorValue; ACell: PCell); override;
|
||||||
procedure WriteFORMAT(AStream: TStream; ANumFormatStr: String;
|
procedure WriteFORMAT(AStream: TStream; ANumFormatStr: String;
|
||||||
AFormatIndex: Integer); override;
|
AFormatIndex: Integer); override;
|
||||||
procedure WriteFORMATCOUNT(AStream: TStream);
|
|
||||||
procedure WriteLabel(AStream: TStream; const ARow, ACol: Cardinal;
|
procedure WriteLabel(AStream: TStream; const ARow, ACol: Cardinal;
|
||||||
const AValue: string; ACell: PCell); override;
|
const AValue: string; ACell: PCell); override;
|
||||||
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal;
|
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal;
|
||||||
@ -179,6 +183,7 @@ const
|
|||||||
{%H-}INT_EXCEL_ID_INDEX = $000B;
|
{%H-}INT_EXCEL_ID_INDEX = $000B;
|
||||||
INT_EXCEL_ID_FORMAT = $001E;
|
INT_EXCEL_ID_FORMAT = $001E;
|
||||||
INT_EXCEL_ID_FORMATCOUNT = $001F;
|
INT_EXCEL_ID_FORMATCOUNT = $001F;
|
||||||
|
INT_EXCEL_ID_COLUMNDEFAULT = $0020;
|
||||||
INT_EXCEL_ID_COLWIDTH = $0024;
|
INT_EXCEL_ID_COLWIDTH = $0024;
|
||||||
INT_EXCEL_ID_DEFROWHEIGHT = $0025;
|
INT_EXCEL_ID_DEFROWHEIGHT = $0025;
|
||||||
INT_EXCEL_ID_WINDOW2 = $003E;
|
INT_EXCEL_ID_WINDOW2 = $003E;
|
||||||
@ -362,6 +367,102 @@ begin
|
|||||||
Workbook.OnReadCellData(Workbook, r, c, cell);
|
Workbook.OnReadCellData(Workbook, r, c, cell);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsSpreadBIFF2Reader.ReadColumnDefault(AStream: TStream);
|
||||||
|
var
|
||||||
|
c, col1, col2: Word;
|
||||||
|
attr1, attr2, attr3: Byte;
|
||||||
|
fmt: TsCellFormat;
|
||||||
|
fmtIndex: Integer;
|
||||||
|
fontIndex: Integer;
|
||||||
|
fnt: TsFont;
|
||||||
|
nf: TsNumFormatParams;
|
||||||
|
nfs: String;
|
||||||
|
b: Byte;
|
||||||
|
begin
|
||||||
|
{ Index of first column }
|
||||||
|
col1 := WordLEToN(AStream.ReadWord);
|
||||||
|
|
||||||
|
{ Index of last column - note: the file value is incremented by 1 }
|
||||||
|
col2 := WordLEToN(AStream.ReadWord) - 1;
|
||||||
|
|
||||||
|
{ Attributes }
|
||||||
|
attr1 := AStream.ReadByte;
|
||||||
|
attr2 := AStream.ReadByte;
|
||||||
|
attr3 := AStream.ReadByte;
|
||||||
|
|
||||||
|
InitFormatRecord(fmt);
|
||||||
|
fmt.ID := FCellFormatList.Count;
|
||||||
|
|
||||||
|
// Font index
|
||||||
|
fontIndex := (attr2 and $C0) shr 6;
|
||||||
|
if fontIndex > 4 then dec(fontIndex); // Watch out for the nasty missing font #4...
|
||||||
|
fnt := TsFont(FFontList[fontIndex]);
|
||||||
|
fmt.FontIndex := Workbook.FindFont(fnt.FontName, fnt.Size, fnt.Style, fnt.Color);
|
||||||
|
if fmt.FontIndex = -1 then
|
||||||
|
fmt.FontIndex := Workbook.AddFont(fnt.FontName, fnt.Size, fnt.Style, fnt.Color);
|
||||||
|
if fmt.FontIndex > 0 then
|
||||||
|
Include(fmt.UsedFormattingFields, uffFont);
|
||||||
|
|
||||||
|
// Number format index
|
||||||
|
b := attr2 and $3F;
|
||||||
|
nfs := NumFormatList[b];
|
||||||
|
if nfs <> '' then begin
|
||||||
|
fmt.NumberFormatIndex := Workbook.AddNumberFormat(nfs);
|
||||||
|
nf := Workbook.GetNumberFormat(fmt.NumberFormatIndex);
|
||||||
|
fmt.NumberFormat := nf.NumFormat;
|
||||||
|
fmt.NumberFormatStr := nf.NumFormatStr;
|
||||||
|
if fmt.NumberFormat <> nfGeneral then
|
||||||
|
Include(fmt.UsedFormattingfields, uffNumberFormat);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Horizontal alignment
|
||||||
|
b := attr3 and MASK_XF_HOR_ALIGN;
|
||||||
|
if (b <= ord(High(TsHorAlignment))) then
|
||||||
|
begin
|
||||||
|
fmt.HorAlignment := TsHorAlignment(b);
|
||||||
|
if fmt.HorAlignment <> haDefault then
|
||||||
|
Include(fmt.UsedFormattingFields, uffHorAlign);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Vertical alignment - not used in BIFF2
|
||||||
|
fmt.VertAlignment := vaDefault;
|
||||||
|
|
||||||
|
// Word wrap - not used in BIFF2
|
||||||
|
// -- nothing to do here
|
||||||
|
|
||||||
|
// Text rotation - not used in BIFF2
|
||||||
|
// -- nothing to do here
|
||||||
|
|
||||||
|
// Borders
|
||||||
|
fmt.Border := [];
|
||||||
|
if attr3 and $08 <> 0 then
|
||||||
|
Include(fmt.Border, cbWest);
|
||||||
|
if attr3 and $10 <> 0 then
|
||||||
|
Include(fmt.Border, cbEast);
|
||||||
|
if attr3 and $20 <> 0 then
|
||||||
|
Include(fmt.Border, cbNorth);
|
||||||
|
if attr3 and $40 <> 0 then
|
||||||
|
Include(fmt.Border, cbSouth);
|
||||||
|
if fmt.Border <> [] then
|
||||||
|
Include(fmt.UsedFormattingFields, uffBorder);
|
||||||
|
|
||||||
|
// Background color not supported, only shaded background
|
||||||
|
if attr3 and $80 <> 0 then
|
||||||
|
begin
|
||||||
|
fmt.Background.Style := fsGray50;
|
||||||
|
fmt.Background.FgColor := scBlack;
|
||||||
|
fmt.Background.BgColor := scTransparent;
|
||||||
|
Include(fmt.UsedFormattingFields, uffBackground);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Add the decoded data to the format list
|
||||||
|
FCellFormatList.Add(fmt);
|
||||||
|
fmtIndex := FWorkbook.AddCellFormat(fmt);
|
||||||
|
|
||||||
|
for c := col1 to col2 do
|
||||||
|
FWorksheet.WriteColFormatIndex(c, fmtIndex);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsSpreadBIFF2Reader.ReadColWidth(AStream: TStream);
|
procedure TsSpreadBIFF2Reader.ReadColWidth(AStream: TStream);
|
||||||
const
|
const
|
||||||
EPS = 1E-3;
|
EPS = 1E-3;
|
||||||
@ -386,9 +487,11 @@ end;
|
|||||||
procedure TsSpreadBIFF2Reader.ReadDefRowHeight(AStream: TStream);
|
procedure TsSpreadBIFF2Reader.ReadDefRowHeight(AStream: TStream);
|
||||||
var
|
var
|
||||||
hw: word;
|
hw: word;
|
||||||
|
h: Single;
|
||||||
begin
|
begin
|
||||||
hw := WordLEToN(AStream.ReadWord);
|
hw := WordLEToN(AStream.ReadWord);
|
||||||
FWorksheet.WriteDefaultRowHeight(TwipsToPts(hw and $8000), suPoints);
|
h := TwipsToPts(hw and $7FFF);
|
||||||
|
FWorksheet.WriteDefaultRowHeight(h, suPoints);
|
||||||
{
|
{
|
||||||
h := TwipsToPts(hw and $8000) / FWorkbook.GetDefaultFontSize;
|
h := TwipsToPts(hw and $8000) / FWorkbook.GetDefaultFontSize;
|
||||||
if h > ROW_HEIGHT_CORRECTION then
|
if h > ROW_HEIGHT_CORRECTION then
|
||||||
@ -493,6 +596,7 @@ begin
|
|||||||
INT_EXCEL_ID_BOOLERROR : ReadBool(AStream);
|
INT_EXCEL_ID_BOOLERROR : ReadBool(AStream);
|
||||||
INT_EXCEL_ID_BOTTOMMARGIN : ReadMargin(AStream, 3);
|
INT_EXCEL_ID_BOTTOMMARGIN : ReadMargin(AStream, 3);
|
||||||
INT_EXCEL_ID_CODEPAGE : ReadCodePage(AStream);
|
INT_EXCEL_ID_CODEPAGE : ReadCodePage(AStream);
|
||||||
|
INT_EXCEL_ID_COLUMNDEFAULT : ReadColumnDefault(AStream);
|
||||||
INT_EXCEL_ID_COLWIDTH : ReadColWidth(AStream);
|
INT_EXCEL_ID_COLWIDTH : ReadColWidth(AStream);
|
||||||
INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
|
INT_EXCEL_ID_DEFCOLWIDTH : ReadDefColWidth(AStream);
|
||||||
INT_EXCEL_ID_EOF : BIFF2EOF := True;
|
INT_EXCEL_ID_EOF : BIFF2EOF := True;
|
||||||
@ -780,6 +884,13 @@ type
|
|||||||
Col1: Word;
|
Col1: Word;
|
||||||
Col2: Word;
|
Col2: Word;
|
||||||
Height: Word;
|
Height: Word;
|
||||||
|
NotUsed: Word;
|
||||||
|
ContainsXF: Byte;
|
||||||
|
OffsetToCell: Word;
|
||||||
|
Attributes1: Byte;
|
||||||
|
Attributes2: Byte;
|
||||||
|
Attributes3: Byte;
|
||||||
|
XFIndex: Word;
|
||||||
end;
|
end;
|
||||||
var
|
var
|
||||||
rowrec: TRowRecord;
|
rowrec: TRowRecord;
|
||||||
@ -788,6 +899,8 @@ var
|
|||||||
auto: Boolean;
|
auto: Boolean;
|
||||||
rowheight: Single;
|
rowheight: Single;
|
||||||
defRowHeight: Single;
|
defRowHeight: Single;
|
||||||
|
containsXF: Boolean;
|
||||||
|
xf: Word;
|
||||||
begin
|
begin
|
||||||
rowRec.RowIndex := 0; // to silence the compiler...
|
rowRec.RowIndex := 0; // to silence the compiler...
|
||||||
AStream.ReadBuffer(rowrec, SizeOf(TRowRecord));
|
AStream.ReadBuffer(rowrec, SizeOf(TRowRecord));
|
||||||
@ -795,9 +908,12 @@ begin
|
|||||||
auto := h and $8000 <> 0;
|
auto := h and $8000 <> 0;
|
||||||
rowheight := FWorkbook.ConvertUnits(TwipsToPts(h and $7FFF), suPoints, FWorkbook.Units);
|
rowheight := FWorkbook.ConvertUnits(TwipsToPts(h and $7FFF), suPoints, FWorkbook.Units);
|
||||||
defRowHeight := FWorksheet.ReadDefaultRowHeight(FWorkbook.Units);
|
defRowHeight := FWorksheet.ReadDefaultRowHeight(FWorkbook.Units);
|
||||||
|
containsXF := rowRec.ContainsXF = 1;
|
||||||
|
xf := WordLEToN(rowRec.XFIndex);
|
||||||
|
|
||||||
// No row record if rowheight in file is the same as the default rowheight
|
// No row record if rowheight in file is the same as the default rowheight and
|
||||||
if SameValue(rowheight, defRowHeight, ROWHEIGHT_EPS) then
|
// if there is no formatting record.
|
||||||
|
if SameValue(rowheight, defRowHeight, ROWHEIGHT_EPS) and (not containsXF) then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
// Otherwise: create a row record
|
// Otherwise: create a row record
|
||||||
@ -806,6 +922,7 @@ begin
|
|||||||
if auto then
|
if auto then
|
||||||
lRow^.RowHeightType := rhtAuto else
|
lRow^.RowHeightType := rhtAuto else
|
||||||
lRow^.RowHeightType := rhtCustom;
|
lRow^.RowHeightType := rhtCustom;
|
||||||
|
lRow^.FormatIndex := XFToFormatIndex(xf);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
@ -1032,7 +1149,62 @@ begin
|
|||||||
Result := inherited and (AExcelCode < 200);
|
Result := inherited and (AExcelCode < 200);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Determines the formatting attributes of a cell, row or column. This is needed,
|
||||||
|
for example, for writing a cell content record, such as WriteLabel,
|
||||||
|
WriteNumber, etc.
|
||||||
|
|
||||||
|
The attributes contain, in bit masks, xf record index, font index,
|
||||||
|
borders, etc.
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsSpreadBIFF2Writer.GetAttributes(AFormatIndex: Integer;
|
||||||
|
XFIndex: Word; out Attrib1, Attrib2, Attrib3: Byte);
|
||||||
|
var
|
||||||
|
fmt: PsCellFormat;
|
||||||
|
fontIdx, formatIdx: Integer;
|
||||||
|
begin
|
||||||
|
fmt := Workbook.GetPointerToCellFormat(AFormatIndex);
|
||||||
|
|
||||||
|
if fmt^.UsedFormattingFields = [] then begin
|
||||||
|
Attrib1 := 15;
|
||||||
|
Attrib2 := 0;
|
||||||
|
Attrib3 := 0;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// 1st byte:
|
||||||
|
// Mask $3F: Index to XF record
|
||||||
|
// Mask $40: 1 = Cell is locked
|
||||||
|
// Mask $80: 1 = Formula is hidden
|
||||||
|
Attrib1 := Min(XFIndex, $3F) and $3F;
|
||||||
|
|
||||||
|
// 2nd byte:
|
||||||
|
// Mask $3F: Index to FORMAT record ("FORMAT" = number format!)
|
||||||
|
// Mask $C0: Index to FONT record
|
||||||
|
GetFormatAndFontIndex(fmt, formatIdx, fontIdx);
|
||||||
|
Attrib2 := formatIdx + fontIdx shr 6;
|
||||||
|
// Attrib2 := fmt^.FontIndex shr 6;
|
||||||
|
|
||||||
|
// 3rd byte
|
||||||
|
// Mask $07: horizontal alignment
|
||||||
|
// Mask $08: Cell has left border
|
||||||
|
// Mask $10: Cell has right border
|
||||||
|
// Mask $20: Cell has top border
|
||||||
|
// Mask $40: Cell has bottom border
|
||||||
|
// Mask $80: Cell has shaded background
|
||||||
|
Attrib3 := 0;
|
||||||
|
if uffHorAlign in fmt^.UsedFormattingFields then
|
||||||
|
Attrib3 := ord (fmt^.HorAlignment);
|
||||||
|
if uffBorder in fmt^.UsedFormattingFields then begin
|
||||||
|
if cbNorth in fmt^.Border then Attrib3 := Attrib3 or $20;
|
||||||
|
if cbWest in fmt^.Border then Attrib3 := Attrib3 or $08;
|
||||||
|
if cbEast in fmt^.Border then Attrib3 := Attrib3 or $10;
|
||||||
|
if cbSouth in fmt^.Border then Attrib3 := Attrib3 or $40;
|
||||||
|
end;
|
||||||
|
if (uffBackground in fmt^.UsedFormattingFields) then
|
||||||
|
Attrib3 := Attrib3 or $80;
|
||||||
|
end;
|
||||||
|
(*
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Determines the cell attributes needed for writing a cell content record, such
|
Determines the cell attributes needed for writing a cell content record, such
|
||||||
as WriteLabel, WriteNumber, etc.
|
as WriteLabel, WriteNumber, etc.
|
||||||
@ -1041,9 +1213,6 @@ end;
|
|||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsSpreadBIFF2Writer.GetCellAttributes(ACell: PCell; XFIndex: Word;
|
procedure TsSpreadBIFF2Writer.GetCellAttributes(ACell: PCell; XFIndex: Word;
|
||||||
out Attrib1, Attrib2, Attrib3: Byte);
|
out Attrib1, Attrib2, Attrib3: Byte);
|
||||||
var
|
|
||||||
fmt: PsCellFormat;
|
|
||||||
fontIdx, formatIdx: Integer;
|
|
||||||
begin
|
begin
|
||||||
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
|
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
|
||||||
|
|
||||||
@ -1086,7 +1255,7 @@ begin
|
|||||||
if (uffBackground in fmt^.UsedFormattingFields) then
|
if (uffBackground in fmt^.UsedFormattingFields) then
|
||||||
Attrib3 := Attrib3 or $80;
|
Attrib3 := Attrib3 or $80;
|
||||||
end;
|
end;
|
||||||
|
*)
|
||||||
procedure TsSpreadBIFF2Writer.GetFormatAndFontIndex(AFormatRecord: PsCellFormat;
|
procedure TsSpreadBIFF2Writer.GetFormatAndFontIndex(AFormatRecord: PsCellFormat;
|
||||||
out AFormatIndex, AFontIndex: Integer);
|
out AFormatIndex, AFontIndex: Integer);
|
||||||
var
|
var
|
||||||
@ -1126,10 +1295,13 @@ end;
|
|||||||
*)
|
*)
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Attaches cell formatting data for the given cell to the current record.
|
Attaches cell formatting data for the given cell to the current record.
|
||||||
Is called from all writing methods of cell contents.
|
Is called from all writing methods of cell contents and rows
|
||||||
|
|
||||||
|
@param AFormatIndex Index into the workbook's FCellFormatList
|
||||||
|
@param XFIndex Index of the XF record used here
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsSpreadBIFF2Writer.WriteCellFormatting(AStream: TStream; ACell: PCell;
|
procedure TsSpreadBIFF2Writer.WriteCellAttributes(AStream: TStream;
|
||||||
XFIndex: Word);
|
AFormatIndex: Integer; XFIndex: Word);
|
||||||
type
|
type
|
||||||
TCellFmtRecord = packed record
|
TCellFmtRecord = packed record
|
||||||
XFIndex_Locked_Hidden: Byte;
|
XFIndex_Locked_Hidden: Byte;
|
||||||
@ -1141,7 +1313,7 @@ var
|
|||||||
fmt: PsCellFormat;
|
fmt: PsCellFormat;
|
||||||
w: Word;
|
w: Word;
|
||||||
begin
|
begin
|
||||||
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
|
fmt := Workbook.GetPointerToCellFormat(AFormatIndex);
|
||||||
rec.XFIndex_Locked_Hidden := 0; // to silence the compiler...
|
rec.XFIndex_Locked_Hidden := 0; // to silence the compiler...
|
||||||
FillChar(rec, SizeOf(rec), 0);
|
FillChar(rec, SizeOf(rec), 0);
|
||||||
|
|
||||||
@ -1210,6 +1382,71 @@ begin
|
|||||||
inherited; *)
|
inherited; *)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Writes an Excel 2 COLUMNDEFAULT record containing default column formatting of
|
||||||
|
specified columns
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsSpreadBIFF2Writer.WriteColumnDefault(AStream: TStream;
|
||||||
|
AFirstColIndex, ALastColIndex: Word; AFormatIndex: Integer);
|
||||||
|
//ACol: PCol);
|
||||||
|
var
|
||||||
|
attr1, attr2, attr3: Byte;
|
||||||
|
xf: Word;
|
||||||
|
begin
|
||||||
|
{ BIFF record header }
|
||||||
|
WriteBIFFHeader(AStream, INT_EXCEL_ID_COLUMNDEFAULT, 2+2+3+2);
|
||||||
|
|
||||||
|
{ Index to first column }
|
||||||
|
AStream.WriteWord(WordToLE(AFirstColIndex));
|
||||||
|
|
||||||
|
{ Index to last column }
|
||||||
|
AStream.WriteWord(WordToLE(ALastColIndex + 1));
|
||||||
|
// Unlike specified in the excelfileformat.pdf, Excel 2 wants to have the
|
||||||
|
// last column index incremented by 1!
|
||||||
|
|
||||||
|
{ Attributes }
|
||||||
|
xf := FindXFIndex(AFormatIndex);
|
||||||
|
GetAttributes(AFormatIndex, xf, attr1, attr2, attr3);
|
||||||
|
AStream.WriteByte(attr1);
|
||||||
|
AStream.WriteByte(attr2);
|
||||||
|
AStream.WriteByte(attr3);
|
||||||
|
|
||||||
|
{ Not used }
|
||||||
|
AStream.WriteWord(0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsSpreadBIFF2Writer.WriteColumnDefaults(AStream: TStream);
|
||||||
|
var
|
||||||
|
j, j1: Integer;
|
||||||
|
sheet: TsWorksheet;
|
||||||
|
lCol, lCol1: PCol;
|
||||||
|
lastcol: Integer;
|
||||||
|
begin
|
||||||
|
sheet := Workbook.GetFirstWorksheet;
|
||||||
|
j := 0;
|
||||||
|
while (j < sheet.Cols.Count) do begin
|
||||||
|
lCol := PCol(sheet.Cols[j]);
|
||||||
|
j1 := j;
|
||||||
|
lastcol := lCol^.Col;
|
||||||
|
while (j1 < sheet.Cols.Count) do begin
|
||||||
|
lCol1 := PCol(sheet.Cols[j1]);
|
||||||
|
if lCol1^.FormatIndex <> lCol^.FormatIndex then
|
||||||
|
break;
|
||||||
|
lastCol := lCol1^.Col;
|
||||||
|
inc(j1);
|
||||||
|
end;
|
||||||
|
WriteColumnDefault(AStream, lCol^.Col, lastCol, lCol^.FormatIndex);
|
||||||
|
j := j1;
|
||||||
|
end;
|
||||||
|
{
|
||||||
|
for j := 0 to sheet.Cols.Count-1 do begin
|
||||||
|
lCol := PCol(sheet.Cols[j]);
|
||||||
|
if lCol^.FormatIndex > 0 then
|
||||||
|
WriteColumnDefault(AStream, lCol);
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Writes an Excel 2 COLWIDTH record
|
Writes an Excel 2 COLWIDTH record
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
@ -1224,12 +1461,11 @@ type
|
|||||||
end;
|
end;
|
||||||
var
|
var
|
||||||
rec: TColRecord;
|
rec: TColRecord;
|
||||||
w: Integer;
|
w: Single;
|
||||||
begin
|
begin
|
||||||
if Assigned(ACol) then begin
|
|
||||||
{ BIFF record header }
|
{ BIFF record header }
|
||||||
rec.RecordID := WordToLE(INT_EXCEL_ID_COLWIDTH);
|
rec.RecordID := WordToLE(INT_EXCEL_ID_COLWIDTH);
|
||||||
rec.RecordSize := WordToLE(4);
|
rec.RecordSize := WordToLE(SizeOf(TColRecord) - 4);
|
||||||
|
|
||||||
{ Start and end column }
|
{ Start and end column }
|
||||||
rec.StartCol := ACol^.Col;
|
rec.StartCol := ACol^.Col;
|
||||||
@ -1237,13 +1473,15 @@ begin
|
|||||||
|
|
||||||
{ Column width }
|
{ Column width }
|
||||||
{ calculate width to be in units of 1/256 of pixel width of character "0" }
|
{ calculate width to be in units of 1/256 of pixel width of character "0" }
|
||||||
w := round(FWorkbook.ConvertUnits(ACol^.Width, FWorkbook.Units, suChars)*256);
|
if ACol^.ColWidthType = cwtDefault then
|
||||||
rec.ColWidth := WordToLE(w);
|
w := FWorksheet.ReadDefaultColWidth(suChars)
|
||||||
|
else
|
||||||
|
w := FWorkbook.ConvertUnits(ACol^.Width, FWorkbook.Units, suChars);
|
||||||
|
rec.ColWidth := WordToLE(round(w*256));
|
||||||
|
|
||||||
{ Write out }
|
{ Write out }
|
||||||
AStream.WriteBuffer(rec, SizeOf(rec));
|
AStream.WriteBuffer(rec, SizeOf(rec));
|
||||||
end;
|
end;
|
||||||
end;
|
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Write COLWIDTH records for all columns
|
Write COLWIDTH records for all columns
|
||||||
@ -1335,18 +1573,16 @@ begin
|
|||||||
WriteFormatCount(AStream);
|
WriteFormatCount(AStream);
|
||||||
WriteNumFormats(AStream);
|
WriteNumFormats(AStream);
|
||||||
WriteXFRecords(AStream);
|
WriteXFRecords(AStream);
|
||||||
|
|
||||||
WriteDefaultColWidth(AStream, FWorksheet);
|
WriteDefaultColWidth(AStream, FWorksheet);
|
||||||
WriteColWidths(AStream);
|
WriteColWidths(AStream);
|
||||||
WriteDimensions(AStream, FWorksheet);
|
WriteDimensions(AStream, FWorksheet);
|
||||||
|
WriteColumnDefaults(AStream);
|
||||||
WriteRows(AStream, FWorksheet);
|
WriteRows(AStream, FWorksheet);
|
||||||
|
|
||||||
if (boVirtualMode in Workbook.Options) then
|
if (boVirtualMode in Workbook.Options) then
|
||||||
WriteVirtualCells(AStream, FWorksheet)
|
WriteVirtualCells(AStream, FWorksheet)
|
||||||
else begin
|
else
|
||||||
// WriteRows(AStream, FWorksheet);
|
|
||||||
WriteCellsToStream(AStream, FWorksheet.Cells);
|
WriteCellsToStream(AStream, FWorksheet.Cells);
|
||||||
end;
|
|
||||||
|
|
||||||
WriteWindow1(AStream);
|
WriteWindow1(AStream);
|
||||||
// { -- currently not working
|
// { -- currently not working
|
||||||
@ -1673,7 +1909,7 @@ begin
|
|||||||
AStream.WriteWord(WordToLE(ACol));
|
AStream.WriteWord(WordToLE(ACol));
|
||||||
|
|
||||||
{ BIFF2 Attributes }
|
{ BIFF2 Attributes }
|
||||||
WriteCellFormatting(AStream, ACell, xf);
|
WriteCellAttributes(AStream, ACell^.FormatIndex, xf);
|
||||||
|
|
||||||
{ Encoded result of RPN formula }
|
{ Encoded result of RPN formula }
|
||||||
WriteRPNResult(AStream, ACell);
|
WriteRPNResult(AStream, ACell);
|
||||||
@ -1764,7 +2000,7 @@ begin
|
|||||||
rec.Col := WordToLE(ACol);
|
rec.Col := WordToLE(ACol);
|
||||||
|
|
||||||
{ BIFF2 attributes }
|
{ BIFF2 attributes }
|
||||||
GetCellAttributes(ACell, xf, rec.Attrib1, rec.Attrib2, rec.Attrib3);
|
GetAttributes(ACell^.FormatIndex, xf, rec.Attrib1, rec.Attrib2, rec.Attrib3);
|
||||||
|
|
||||||
{ Cell value }
|
{ Cell value }
|
||||||
rec.BoolErrValue := ord(AValue);
|
rec.BoolErrValue := ord(AValue);
|
||||||
@ -1820,7 +2056,7 @@ begin
|
|||||||
rec.Col := WordToLE(ACol);
|
rec.Col := WordToLE(ACol);
|
||||||
|
|
||||||
{ BIFF2 attributes }
|
{ BIFF2 attributes }
|
||||||
GetCellAttributes(ACell, xf, rec.Attrib1, rec.Attrib2, rec.Attrib3);
|
GetAttributes(ACell^.FormatIndex, xf, rec.Attrib1, rec.Attrib2, rec.Attrib3);
|
||||||
|
|
||||||
{ Cell value }
|
{ Cell value }
|
||||||
rec.BoolErrValue := ConvertToExcelError(AValue);
|
rec.BoolErrValue := ConvertToExcelError(AValue);
|
||||||
@ -1864,7 +2100,7 @@ begin
|
|||||||
rec.Col := WordToLE(ACol);
|
rec.Col := WordToLE(ACol);
|
||||||
|
|
||||||
{ BIFF2 attributes }
|
{ BIFF2 attributes }
|
||||||
GetCellAttributes(ACell, xf, rec.Attrib1, rec.Attrib2, rec.Attrib3);
|
GetAttributes(ACell^.FormatIndex, xf, rec.Attrib1, rec.Attrib2, rec.Attrib3);
|
||||||
|
|
||||||
{ Write out }
|
{ Write out }
|
||||||
AStream.WriteBuffer(rec, Sizeof(rec));
|
AStream.WriteBuffer(rec, Sizeof(rec));
|
||||||
@ -1919,7 +2155,7 @@ begin
|
|||||||
rec.Col := WordToLE(ACol);
|
rec.Col := WordToLE(ACol);
|
||||||
|
|
||||||
{ BIFF2 attributes }
|
{ BIFF2 attributes }
|
||||||
GetCellAttributes(ACell, xf, rec.Attrib1, rec.Attrib2, rec.Attrib3);
|
GetAttributes(ACell^.FormatIndex, xf, rec.Attrib1, rec.Attrib2, rec.Attrib3);
|
||||||
|
|
||||||
{ Text length: 8 bit }
|
{ Text length: 8 bit }
|
||||||
rec.TextLen := L;
|
rec.TextLen := L;
|
||||||
@ -1959,7 +2195,7 @@ begin
|
|||||||
rec.Col := WordToLE(ACol);
|
rec.Col := WordToLE(ACol);
|
||||||
|
|
||||||
{ BIFF2 attributes }
|
{ BIFF2 attributes }
|
||||||
GetCellAttributes(ACell, xf, rec.Attrib1, rec.Attrib2, rec.Attrib3);
|
GetAttributes(ACell^.FormatIndex, xf, rec.Attrib1, rec.Attrib2, rec.Attrib3);
|
||||||
|
|
||||||
{ Number value }
|
{ Number value }
|
||||||
rec.Value := AValue;
|
rec.Value := AValue;
|
||||||
@ -1975,15 +2211,15 @@ var
|
|||||||
rowheight: Word;
|
rowheight: Word;
|
||||||
auto: Boolean;
|
auto: Boolean;
|
||||||
w: Word;
|
w: Word;
|
||||||
|
xf: Word;
|
||||||
begin
|
begin
|
||||||
if (ARowIndex >= FLimitations.MaxRowCount) or (AFirstColIndex >= FLimitations.MaxColCount)
|
if (ARowIndex >= FLimitations.MaxRowCount) or
|
||||||
or (ALastColIndex >= FLimitations.MaxColCount)
|
(AFirstColIndex >= FLimitations.MaxColCount) or
|
||||||
|
(ALastColIndex >= FLimitations.MaxColCount)
|
||||||
then
|
then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
Unused(ASheet);
|
containsXF := (ARow <> nil) and (ARow^.FormatIndex > 0);
|
||||||
|
|
||||||
containsXF := false;
|
|
||||||
|
|
||||||
{ BIFF record header }
|
{ BIFF record header }
|
||||||
WriteBiffHeader(AStream, INT_EXCEL_ID_ROW, IfThen(containsXF, 18, 13));
|
WriteBiffHeader(AStream, INT_EXCEL_ID_ROW, IfThen(containsXF, 18, 13));
|
||||||
@ -2016,20 +2252,20 @@ begin
|
|||||||
{ not used }
|
{ not used }
|
||||||
AStream.WriteWord(0);
|
AStream.WriteWord(0);
|
||||||
|
|
||||||
{ Contains row attribute field and XF index }
|
{ Does the record contain row attribute field and XF index? }
|
||||||
AStream.WriteByte(ord(containsXF));
|
AStream.WriteByte(ord(containsXF));
|
||||||
|
|
||||||
{ Relative offset to calculate stream position of the first cell record for this row }
|
{ Relative offset to calculate stream position of the first cell record for this row }
|
||||||
AStream.WriteWord(0);
|
AStream.WriteWord(0);
|
||||||
|
|
||||||
if containsXF then begin
|
if containsXF then begin
|
||||||
|
xf := FindXFIndex(ARow^.FormatIndex);
|
||||||
|
|
||||||
{ Default row attributes }
|
{ Default row attributes }
|
||||||
AStream.WriteByte(0);
|
WriteCellAttributes(AStream, ARow^.FormatIndex, xf);
|
||||||
AStream.WriteByte(0);
|
|
||||||
AStream.WriteByte(0);
|
|
||||||
|
|
||||||
{ Index to XF record }
|
{ Index to XF record }
|
||||||
AStream.WriteWord(WordToLE(15));
|
AStream.WriteWord(WordToLE(xf));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -386,6 +386,7 @@ type
|
|||||||
|
|
||||||
procedure AddBuiltinNumFormats; override;
|
procedure AddBuiltinNumFormats; override;
|
||||||
procedure ApplyCellFormatting(ACell: PCell; XFIndex: Word); virtual;
|
procedure ApplyCellFormatting(ACell: PCell; XFIndex: Word); virtual;
|
||||||
|
function XFToFormatIndex(XFIndex: Word): Integer;
|
||||||
|
|
||||||
(*
|
(*
|
||||||
procedure ApplyRichTextFormattingRuns(ACell: PCell;
|
procedure ApplyRichTextFormattingRuns(ACell: PCell;
|
||||||
@ -988,19 +989,22 @@ end;
|
|||||||
Applies the XF formatting referred to by XFIndex to the specified cell
|
Applies the XF formatting referred to by XFIndex to the specified cell
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsSpreadBIFFReader.ApplyCellFormatting(ACell: PCell; XFIndex: Word);
|
procedure TsSpreadBIFFReader.ApplyCellFormatting(ACell: PCell; XFIndex: Word);
|
||||||
|
begin
|
||||||
|
if Assigned(ACell) then
|
||||||
|
ACell^.FormatIndex := XFToFormatIndex(XFIndex);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TsSpreadBIFFReader.XFToFormatIndex(XFIndex: Word): Integer;
|
||||||
var
|
var
|
||||||
fmt: PsCellFormat;
|
fmt: PsCellFormat;
|
||||||
i: Integer;
|
idx: Integer;
|
||||||
begin
|
begin
|
||||||
if Assigned(ACell) then begin
|
idx := FCellFormatList.FindIndexOfID(XFIndex);
|
||||||
i := FCellFormatList.FindIndexOfID(XFIndex);
|
if idx > -1 then begin
|
||||||
if i > -1 then
|
fmt := FCellFormatList.Items[idx];
|
||||||
begin
|
result := FWorkbook.AddCellFormat(fmt^); // Adds a copy of fmt to workbook
|
||||||
fmt := FCellFormatList.Items[i];
|
|
||||||
ACell^.FormatIndex := FWorkbook.AddCellFormat(fmt^); // Adds a copy of fmt to workbook
|
|
||||||
end else
|
end else
|
||||||
ACell^.FormatIndex := 0;
|
Result := 0;
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
(*
|
(*
|
||||||
@ -2143,14 +2147,9 @@ begin
|
|||||||
xf := (flags and $0FFF0000) shr 16;
|
xf := (flags and $0FFF0000) shr 16;
|
||||||
if xf = 15 then hasFormat := false;
|
if xf = 15 then hasFormat := false;
|
||||||
end;
|
end;
|
||||||
if hasFormat then begin
|
if hasFormat then
|
||||||
// Find the format with ID xf
|
// Find the format with ID xf
|
||||||
idx := FCellFormatList.FindIndexOfID(xf);
|
lRow.FormatIndex := XFToFormatIndex(xf);
|
||||||
if idx > -1 then begin
|
|
||||||
fmt := FCellFormatList.Items[idx];
|
|
||||||
lRow.FormatIndex := FWorkbook.AddCellFormat(fmt^);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// We only create a row record for fpspreadsheet if the row has a
|
// We only create a row record for fpspreadsheet if the row has a
|
||||||
// non-standard height (i.e. different from default row height) or format.
|
// non-standard height (i.e. different from default row height) or format.
|
||||||
|
Reference in New Issue
Block a user