fpspreadsheet: Write column and row formats to biff5/biff8

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5252 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2016-10-08 17:57:29 +00:00
parent 33f7d1b3af
commit 547331def4
6 changed files with 63 additions and 34 deletions

View File

@ -2044,9 +2044,16 @@ end;
(e.g., during reading into empty worksheets). (e.g., during reading into empty worksheets).
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
function TsWorksheet.AddCell(ARow, ACol: Cardinal): PCell; function TsWorksheet.AddCell(ARow, ACol: Cardinal): PCell;
var
fmtIndex: Integer;
begin begin
Result := Cells.AddCell(ARow, ACol); Result := Cells.AddCell(ARow, ACol);
fmtIndex := GetRowFormatIndex(ARow);
if fmtIndex = 0 then
fmtIndex := GetColFormatIndex(ACol);
Result^.FormatIndex := fmtIndex;
if FFirstColIndex = UNASSIGNED_ROW_COL_INDEX then if FFirstColIndex = UNASSIGNED_ROW_COL_INDEX then
FFirstColIndex := GetFirstColIndex(true) else FFirstColIndex := GetFirstColIndex(true) else
FFirstColIndex := Min(FFirstColIndex, ACol); FFirstColIndex := Min(FFirstColIndex, ACol);
@ -6366,8 +6373,8 @@ end;
pointer to the TCol record, or nil if not found pointer to the TCol record, or nil if not found
@param ACol Index of the column looked for @param ACol Index of the column looked for
@return Pointer to the column record with this column index, or @return Pointer to the column record with this column index, or nil
nil if not found if not found
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
function TsWorksheet.FindCol(ACol: Cardinal): PCol; function TsWorksheet.FindCol(ACol: Cardinal): PCol;
var var
@ -6490,14 +6497,14 @@ end;
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
function TsWorksheet.GetColFormatIndex(ACol: Cardinal): Integer; function TsWorksheet.GetColFormatIndex(ACol: Cardinal): Integer;
var var
col: PCol; lCol: PCol;
begin begin
Result := 0; // Default format has index 0 Result := 0; // Default format has index 0
if ACol <> UNASSIGNED_ROW_COL_INDEX then if ACol <> UNASSIGNED_ROW_COL_INDEX then
begin begin
col := FindCol(ACol); lCol := FindCol(ACol);
if col <> nil then if lCol <> nil then
Result := col^.FormatIndex Result := lCol^.FormatIndex
end; end;
end; end;
@ -6959,7 +6966,7 @@ end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Removes a specified column record from the worksheet and frees the occupied Removes a specified column record from the worksheet and frees the occupied
memory. This resets its column width to default. memory. This resets its column width and format to default.
Note: Cells in that column are retained. Note: Cells in that column are retained.
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
@ -7125,6 +7132,7 @@ begin
exit; exit;
lCol := GetCol(ACol); lCol := GetCol(ACol);
lCol^.Width := FWorkbook.ConvertUnits(AWidth, AUnits, FWorkbook.FUnits); lCol^.Width := FWorkbook.ConvertUnits(AWidth, AUnits, FWorkbook.FUnits);
lCol^.ColWidthType := cwtCustom;
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------

View File

@ -325,20 +325,28 @@ const
var var
c: Cardinal; c: Cardinal;
w: Single; w: Single;
lCol: PCol;
begin begin
if AWorksheet.Cols.Count < 2 then if AWorksheet.Cols.Count < 2 then
exit; exit;
// Check whether all columns have the same column width // Check whether all columns have the same column width
w := PCol(AWorksheet.Cols[0])^.Width; w := PCol(AWorksheet.Cols[0])^.Width;
for c := 1 to AWorksheet.Cols.Count-1 do for c := 1 to AWorksheet.Cols.Count-1 do begin
if not SameValue(PCol(AWorksheet.Cols[c])^.Width, w, EPS) then lCol := PCol(AWorksheet.Cols[c]);
if not SameValue(lCol^.Width, w, EPS) then
exit; exit;
end;
// At this point we know that all columns have the same width. We pass this // At this point we know that all columns have the same width. We pass this
// to the DefaultColWidth and delete all column records. // to the DefaultColWidth ...
AWorksheet.WriteDefaultColWidth(w, FWorkbook.Units); AWorksheet.WriteDefaultColWidth(w, FWorkbook.Units);
AWorksheet.RemoveAllCols;
// ...and delete all column records with non-default format
for c := AWorksheet.Cols.Count-1 downto 0 do begin
lCol := PCol(AWorksheet.Cols[c]);
if lCol^.FormatIndex = 0 then AWorksheet.RemoveCol(c);
end;
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
@ -352,20 +360,28 @@ const
var var
r: Cardinal; r: Cardinal;
h: Single; h: Single;
lRow: PRow;
begin begin
if AWorksheet.Rows.Count <= 1 then if AWorksheet.Rows.Count <= 1 then
exit; exit;
// Check whether all rows have the same height // Check whether all rows have the same height
h := PRow(AWorksheet.Rows[0])^.Height; h := PRow(AWorksheet.Rows[0])^.Height;
for r := 1 to AWorksheet.Rows.Count-1 do for r := 1 to AWorksheet.Rows.Count-1 do begin
if not SameValue(PRow(AWorksheet.Rows[r])^.Height, h, EPS) then lRow := PRow(AWorksheet.Rows[r]);
if not SameValue(lRow^.Height, h, EPS) then
exit; exit;
end;
// At this point we know that all rows have the same height. We pass this // At this point we know that all rows have the same height. We pass this
// to the DefaultRowHeight and delete all row records. // to the DefaultRowHeight ...
AWorksheet.WriteDefaultRowHeight(h, FWorkbook.Units); AWorksheet.WriteDefaultRowHeight(h, FWorkbook.Units);
AWorksheet.RemoveAllRows;
// ... and delete all row records with non-default format.
for r := AWorksheet.Rows.Count-1 downto 0 do begin
lRow := PRow(AWorksheet.Rows[r]);
if lRow^.FormatIndex = 0 then AWorksheet.RemoveRow(r);
end;
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------

View File

@ -1659,7 +1659,7 @@ begin
RPNLength := 0; RPNLength := 0;
xf := FindXFIndex(ACell); xf := FindXFIndex(ACell^.FormatIndex);
if xf >= 63 then if xf >= 63 then
WriteIXFE(AStream, xf); WriteIXFE(AStream, xf);
@ -1751,7 +1751,7 @@ begin
if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then
exit; exit;
xf := FindXFIndex(ACell); xf := FindXFIndex(ACell^.FormatIndex);
if xf >= 63 then if xf >= 63 then
WriteIXFE(AStream, xf); WriteIXFE(AStream, xf);
@ -1807,7 +1807,7 @@ begin
if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then
exit; exit;
xf := FindXFIndex(ACell); xf := FindXFIndex(ACell^.FormatIndex);
if xf >= 63 then if xf >= 63 then
WriteIXFE(AStream, xf); WriteIXFE(AStream, xf);
@ -1851,7 +1851,7 @@ begin
if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then
exit; exit;
xf := FindXFIndex(ACell); xf := FindXFIndex(ACell^.FormatIndex);
if xf >= 63 then if xf >= 63 then
WriteIXFE(AStream, xf); WriteIXFE(AStream, xf);
@ -1906,7 +1906,7 @@ begin
end; end;
L := Length(AnsiText); L := Length(AnsiText);
xf := FindXFIndex(ACell); xf := FindXFIndex(ACell^.FormatIndex);
if xf >= 63 then if xf >= 63 then
WriteIXFE(AStream, xf); WriteIXFE(AStream, xf);
@ -1946,7 +1946,7 @@ begin
if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then
exit; exit;
xf := FindXFIndex(ACell); xf := FindXFIndex(ACell^.FormatIndex);
if xf >= 63 then if xf >= 63 then
WriteIXFE(AStream, xf); WriteIXFE(AStream, xf);

View File

@ -1706,7 +1706,7 @@ begin
rec.Col := WordToLE(ACol); rec.Col := WordToLE(ACol);
{ Index to XF record } { Index to XF record }
rec.XFIndex := WordToLE(FindXFIndex(ACell)); rec.XFIndex := WordToLE(FindXFIndex(ACell^.FormatIndex));
{ String length, 16 bit } { String length, 16 bit }
rec.TextLen := WordToLE(L); rec.TextLen := WordToLE(L);

View File

@ -3037,7 +3037,7 @@ begin
rec.Col := WordToLE(ACol); rec.Col := WordToLE(ACol);
{ Index to XF record, according to formatting } { Index to XF record, according to formatting }
rec.XFIndex := WordToLE(FindXFIndex(ACell)); rec.XFIndex := WordToLE(FindXFIndex(ACell^.FormatIndex));
{ Byte String with 16-bit length } { Byte String with 16-bit length }
rec.TextLen := WordToLE(L); rec.TextLen := WordToLE(L);

View File

@ -503,7 +503,7 @@ type
FPalette: TsPalette; FPalette: TsPalette;
procedure AddBuiltinNumFormats; override; procedure AddBuiltinNumFormats; override;
function FindXFIndex(ACell: PCell): Integer; virtual; function FindXFIndex(AFormatIndex: Integer): Integer; virtual;
function FixLineEnding(const AText: String): String; function FixLineEnding(const AText: String): String;
function FormulaSupported(ARPNFormula: TsRPNFormula; out AUnsupported: String): Boolean; function FormulaSupported(ARPNFormula: TsRPNFormula; out AUnsupported: String): Boolean;
function FunctionSupported(AExcelCode: Integer; const AFuncName: String): Boolean; virtual; function FunctionSupported(AExcelCode: Integer; const AFuncName: String): Boolean; virtual;
@ -2980,11 +2980,12 @@ end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Determines the index of the XF record, according to formatting of the Determines the index of the XF record, according to formatting of the
given cell given format index; this format index is taken from a cell, row, or column
record.
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
function TsSpreadBIFFWriter.FindXFIndex(ACell: PCell): Integer; function TsSpreadBIFFWriter.FindXFIndex(AFormatIndex: Integer): Integer;
begin begin
Result := LAST_BUILTIN_XF + ACell^.FormatIndex; Result := LAST_BUILTIN_XF + AFormatIndex;
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
@ -3144,7 +3145,7 @@ begin
rec.Col := WordToLE(ACol); rec.Col := WordToLE(ACol);
{ Index to XF record, according to formatting } { Index to XF record, according to formatting }
rec.XFIndex := WordToLE(FindXFIndex(ACell)); rec.XFIndex := WordToLE(FindXFIndex(ACell^.FormatIndex));
{ Write out } { Write out }
AStream.WriteBuffer(rec, SizeOf(rec)); AStream.WriteBuffer(rec, SizeOf(rec));
@ -3171,7 +3172,7 @@ begin
rec.Col := WordToLE(ACol); rec.Col := WordToLE(ACol);
{ Index to XF record, according to formatting } { Index to XF record, according to formatting }
rec.XFIndex := WordToLE(FindXFIndex(ACell)); rec.XFIndex := WordToLE(FindXFIndex(ACell^.FormatIndex));
{ Cell value } { Cell value }
rec.BoolErrValue := ord(AValue); rec.BoolErrValue := ord(AValue);
@ -3258,8 +3259,8 @@ begin
w := round(FWorkbook.ConvertUnits(ACol^.Width, FWorkbook.Units, suChars)*256); w := round(FWorkbook.ConvertUnits(ACol^.Width, FWorkbook.Units, suChars)*256);
rec.ColWidth := WordToLE(w); rec.ColWidth := WordToLE(w);
rec.XFIndex := WordToLE(15); // Index of XF record, not used rec.XFIndex := WordToLE(FindXFIndex(ACol^.FormatIndex));// Index of XF record
rec.OptionFlags := 0; // not used rec.OptionFlags := 0; // hidden, outline, collapsed flags are not used
rec.NotUsed := 0; rec.NotUsed := 0;
{ Write out } { Write out }
@ -3470,7 +3471,7 @@ begin
rec.Col := WordToLE(ACol); rec.Col := WordToLE(ACol);
{ Index to XF record, according to formatting } { Index to XF record, according to formatting }
rec.XFIndex := WordToLE(FindXFIndex(ACell)); rec.XFIndex := WordToLE(FindXFIndex(ACell^.FormatIndex));
{ Cell value } { Cell value }
rec.BoolErrValue := ConvertToExcelError(AValue); rec.BoolErrValue := ConvertToExcelError(AValue);
@ -3692,7 +3693,7 @@ begin
rec.Col := WordToLE(ACol); rec.Col := WordToLE(ACol);
{ Index to XF record } { Index to XF record }
rec.XFIndex := FindXFIndex(ACell); rec.XFIndex := FindXFIndex(ACell^.FormatIndex);
{ IEE 754 floating-point value } { IEE 754 floating-point value }
rec.Value := AValue; rec.Value := AValue;
@ -4023,7 +4024,7 @@ begin
AStream.WriteWord(WordToLE(ACol)); AStream.WriteWord(WordToLE(ACol));
{ Index to XF record, according to formatting } { Index to XF record, according to formatting }
AStream.WriteWord(FindXFIndex(ACell)); AStream.WriteWord(FindXFIndex(ACell^.FormatIndex));
{ Encoded result of RPN formula } { Encoded result of RPN formula }
WriteRPNResult(AStream, ACell); WriteRPNResult(AStream, ACell);
@ -4388,6 +4389,10 @@ begin
if spacebelow then dw := dw or $20000000; if spacebelow then dw := dw or $20000000;
if (ARow <> nil) and (ARow^.RowHeightType = rhtCustom) then // Custom row height if (ARow <> nil) and (ARow^.RowHeightType = rhtCustom) then // Custom row height
dw := dw or $00000040; // Row height and font height do not match dw := dw or $00000040; // Row height and font height do not match
if ARow^.FormatIndex > 0 then begin
dw := dw or $00000080; // Row has custom format
dw := dw or (FindXFIndex(ARow^.FormatIndex) shl 16); // xf index
end;
{ Write out } { Write out }
AStream.WriteDWord(DWordToLE(dw)); AStream.WriteDWord(DWordToLE(dw));