diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas index 2e7e515ba..d5efc670e 100755 --- a/components/fpspreadsheet/fpspreadsheet.pas +++ b/components/fpspreadsheet/fpspreadsheet.pas @@ -2044,9 +2044,16 @@ end; (e.g., during reading into empty worksheets). -------------------------------------------------------------------------------} function TsWorksheet.AddCell(ARow, ACol: Cardinal): PCell; +var + fmtIndex: Integer; begin 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 FFirstColIndex := GetFirstColIndex(true) else FFirstColIndex := Min(FFirstColIndex, ACol); @@ -6366,8 +6373,8 @@ end; pointer to the TCol record, or nil if not found @param ACol Index of the column looked for - @return Pointer to the column record with this column index, or - nil if not found + @return Pointer to the column record with this column index, or nil + if not found -------------------------------------------------------------------------------} function TsWorksheet.FindCol(ACol: Cardinal): PCol; var @@ -6490,14 +6497,14 @@ end; -------------------------------------------------------------------------------} function TsWorksheet.GetColFormatIndex(ACol: Cardinal): Integer; var - col: PCol; + lCol: PCol; begin Result := 0; // Default format has index 0 if ACol <> UNASSIGNED_ROW_COL_INDEX then begin - col := FindCol(ACol); - if col <> nil then - Result := col^.FormatIndex + lCol := FindCol(ACol); + if lCol <> nil then + Result := lCol^.FormatIndex end; end; @@ -6959,7 +6966,7 @@ end; {@@ ---------------------------------------------------------------------------- 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. -------------------------------------------------------------------------------} @@ -7125,6 +7132,7 @@ begin exit; lCol := GetCol(ACol); lCol^.Width := FWorkbook.ConvertUnits(AWidth, AUnits, FWorkbook.FUnits); + lCol^.ColWidthType := cwtCustom; end; {@@ ---------------------------------------------------------------------------- diff --git a/components/fpspreadsheet/fpsreaderwriter.pas b/components/fpspreadsheet/fpsreaderwriter.pas index 575f0833d..b9d89f6b0 100644 --- a/components/fpspreadsheet/fpsreaderwriter.pas +++ b/components/fpspreadsheet/fpsreaderwriter.pas @@ -325,20 +325,28 @@ const var c: Cardinal; w: Single; + lCol: PCol; begin if AWorksheet.Cols.Count < 2 then exit; // Check whether all columns have the same column width w := PCol(AWorksheet.Cols[0])^.Width; - for c := 1 to AWorksheet.Cols.Count-1 do - if not SameValue(PCol(AWorksheet.Cols[c])^.Width, w, EPS) then + for c := 1 to AWorksheet.Cols.Count-1 do begin + lCol := PCol(AWorksheet.Cols[c]); + if not SameValue(lCol^.Width, w, EPS) then exit; + end; // 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.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; {@@ ---------------------------------------------------------------------------- @@ -352,20 +360,28 @@ const var r: Cardinal; h: Single; + lRow: PRow; begin if AWorksheet.Rows.Count <= 1 then exit; // Check whether all rows have the same height h := PRow(AWorksheet.Rows[0])^.Height; - for r := 1 to AWorksheet.Rows.Count-1 do - if not SameValue(PRow(AWorksheet.Rows[r])^.Height, h, EPS) then + for r := 1 to AWorksheet.Rows.Count-1 do begin + lRow := PRow(AWorksheet.Rows[r]); + if not SameValue(lRow^.Height, h, EPS) then exit; + end; // 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.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; {@@ ---------------------------------------------------------------------------- diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas index 2f293d79d..4d70b7ebf 100755 --- a/components/fpspreadsheet/xlsbiff2.pas +++ b/components/fpspreadsheet/xlsbiff2.pas @@ -1659,7 +1659,7 @@ begin RPNLength := 0; - xf := FindXFIndex(ACell); + xf := FindXFIndex(ACell^.FormatIndex); if xf >= 63 then WriteIXFE(AStream, xf); @@ -1751,7 +1751,7 @@ begin if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then exit; - xf := FindXFIndex(ACell); + xf := FindXFIndex(ACell^.FormatIndex); if xf >= 63 then WriteIXFE(AStream, xf); @@ -1807,7 +1807,7 @@ begin if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then exit; - xf := FindXFIndex(ACell); + xf := FindXFIndex(ACell^.FormatIndex); if xf >= 63 then WriteIXFE(AStream, xf); @@ -1851,7 +1851,7 @@ begin if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then exit; - xf := FindXFIndex(ACell); + xf := FindXFIndex(ACell^.FormatIndex); if xf >= 63 then WriteIXFE(AStream, xf); @@ -1906,7 +1906,7 @@ begin end; L := Length(AnsiText); - xf := FindXFIndex(ACell); + xf := FindXFIndex(ACell^.FormatIndex); if xf >= 63 then WriteIXFE(AStream, xf); @@ -1946,7 +1946,7 @@ begin if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then exit; - xf := FindXFIndex(ACell); + xf := FindXFIndex(ACell^.FormatIndex); if xf >= 63 then WriteIXFE(AStream, xf); diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas index 6b6079fed..54469fc3c 100755 --- a/components/fpspreadsheet/xlsbiff5.pas +++ b/components/fpspreadsheet/xlsbiff5.pas @@ -1706,7 +1706,7 @@ begin rec.Col := WordToLE(ACol); { Index to XF record } - rec.XFIndex := WordToLE(FindXFIndex(ACell)); + rec.XFIndex := WordToLE(FindXFIndex(ACell^.FormatIndex)); { String length, 16 bit } rec.TextLen := WordToLE(L); diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas index df739ee44..63388dc9b 100755 --- a/components/fpspreadsheet/xlsbiff8.pas +++ b/components/fpspreadsheet/xlsbiff8.pas @@ -3037,7 +3037,7 @@ begin rec.Col := WordToLE(ACol); { Index to XF record, according to formatting } - rec.XFIndex := WordToLE(FindXFIndex(ACell)); + rec.XFIndex := WordToLE(FindXFIndex(ACell^.FormatIndex)); { Byte String with 16-bit length } rec.TextLen := WordToLE(L); diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas index 2b310065a..4fd4c0a7d 100644 --- a/components/fpspreadsheet/xlscommon.pas +++ b/components/fpspreadsheet/xlscommon.pas @@ -503,7 +503,7 @@ type FPalette: TsPalette; procedure AddBuiltinNumFormats; override; - function FindXFIndex(ACell: PCell): Integer; virtual; + function FindXFIndex(AFormatIndex: Integer): Integer; virtual; function FixLineEnding(const AText: String): String; function FormulaSupported(ARPNFormula: TsRPNFormula; out AUnsupported: String): Boolean; 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 - 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 - Result := LAST_BUILTIN_XF + ACell^.FormatIndex; + Result := LAST_BUILTIN_XF + AFormatIndex; end; {@@ ---------------------------------------------------------------------------- @@ -3144,7 +3145,7 @@ begin rec.Col := WordToLE(ACol); { Index to XF record, according to formatting } - rec.XFIndex := WordToLE(FindXFIndex(ACell)); + rec.XFIndex := WordToLE(FindXFIndex(ACell^.FormatIndex)); { Write out } AStream.WriteBuffer(rec, SizeOf(rec)); @@ -3171,7 +3172,7 @@ begin rec.Col := WordToLE(ACol); { Index to XF record, according to formatting } - rec.XFIndex := WordToLE(FindXFIndex(ACell)); + rec.XFIndex := WordToLE(FindXFIndex(ACell^.FormatIndex)); { Cell value } rec.BoolErrValue := ord(AValue); @@ -3258,8 +3259,8 @@ begin w := round(FWorkbook.ConvertUnits(ACol^.Width, FWorkbook.Units, suChars)*256); rec.ColWidth := WordToLE(w); - rec.XFIndex := WordToLE(15); // Index of XF record, not used - rec.OptionFlags := 0; // not used + rec.XFIndex := WordToLE(FindXFIndex(ACol^.FormatIndex));// Index of XF record + rec.OptionFlags := 0; // hidden, outline, collapsed flags are not used rec.NotUsed := 0; { Write out } @@ -3470,7 +3471,7 @@ begin rec.Col := WordToLE(ACol); { Index to XF record, according to formatting } - rec.XFIndex := WordToLE(FindXFIndex(ACell)); + rec.XFIndex := WordToLE(FindXFIndex(ACell^.FormatIndex)); { Cell value } rec.BoolErrValue := ConvertToExcelError(AValue); @@ -3692,7 +3693,7 @@ begin rec.Col := WordToLE(ACol); { Index to XF record } - rec.XFIndex := FindXFIndex(ACell); + rec.XFIndex := FindXFIndex(ACell^.FormatIndex); { IEE 754 floating-point value } rec.Value := AValue; @@ -4023,7 +4024,7 @@ begin AStream.WriteWord(WordToLE(ACol)); { Index to XF record, according to formatting } - AStream.WriteWord(FindXFIndex(ACell)); + AStream.WriteWord(FindXFIndex(ACell^.FormatIndex)); { Encoded result of RPN formula } WriteRPNResult(AStream, ACell); @@ -4388,6 +4389,10 @@ begin if spacebelow then dw := dw or $20000000; if (ARow <> nil) and (ARow^.RowHeightType = rhtCustom) then // Custom row height 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 } AStream.WriteDWord(DWordToLE(dw));