fpspreadsheet: Initial commit with row and column formats. Display in grid seems to work. Reading implemented for biff8 and biff5.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5249 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2016-10-07 13:52:08 +00:00
parent baaf12ebfa
commit e47b907659
4 changed files with 333 additions and 115 deletions

View File

@ -41,32 +41,6 @@ type
TsWorksheet = class;
TsWorkbook = class;
{@@ The record TRow contains information about a spreadsheet row:
@param Row The index of the row (beginning with 0)
@param Height The height of the row (expressed in the units defined by
the workbook)
@param RowHeightType Specifies default, automatic or custom row height }
TRow = record
Row: Cardinal;
Height: Single;
RowHeightType: TsRowHeightType;
end;
{@@ Pointer to a TRow record }
PRow = ^TRow;
{@@ The record TCol contains information about a spreadsheet column:
@param Col The index of the column (beginning with 0)
@param Width The width of the column (expressed in the units defined in the workbook)
Only columns with non-default widths have a column record. }
TCol = record
Col: Cardinal;
Width: Single;
end;
{@@ Pointer to a TCol record }
PCol = ^TCol;
{@@ Worksheet user interface options:
@param soShowGridLines Show or hide the grid lines in the spreadsheet
@param soShowHeaders Show or hide the column or row headers of the spreadsheet
@ -200,6 +174,10 @@ type
function GetNumberFormatAttributes(ACell: PCell; out ADecimals: Byte;
out ACurrencySymbol: String): Boolean;
function GetEffectiveCellFormatIndex(ACell: PCell): Integer;
function GetPointerToEffectiveCellFormat(ARow, ACol: Cardinal): PsCellFormat; overload;
function GetPointerToEffectiveCellFormat(ACell: PCell): PsCellFormat; overload;
function ReadUsedFormatting(ACell: PCell): TsUsedFormattingFields;
function ReadBackground(ACell: PCell): TsFillPattern;
function ReadBackgroundColor(ACell: PCell): TsColor;
@ -438,10 +416,12 @@ type
function GetCellCountInRow(ARow: Cardinal): Cardinal;
function GetCellCountInCol(ACol: Cardinal): Cardinal;
function GetRow(ARow: Cardinal): PRow;
function GetRowFormatIndex(ARow: Cardinal): Integer;
function GetRowHeight(ARow: Cardinal; AUnits: TsSizeUnits): Single; overload;
function GetRowHeight(ARow: Cardinal): Single; overload; deprecated 'Use version with parameter AUnits.';
function GetRowHeightType(ARow: Cardinal): TsRowHeightType;
function GetCol(ACol: Cardinal): PCol;
function GetColFormatIndex(ACol: Cardinal): Integer;
function GetColWidth(ACol: Cardinal; AUnits: TsSizeUnits): Single; overload;
function GetColWidth(ACol: Cardinal): Single; overload; deprecated 'Use version with parameter AUnits.';
procedure DeleteCol(ACol: Cardinal);
@ -457,11 +437,13 @@ type
procedure WriteDefaultColWidth(AValue: Single; AUnits: TsSizeUnits);
procedure WriteDefaultRowHeight(AValue: Single; AUnits: TsSizeUnits);
procedure WriteRowInfo(ARow: Cardinal; AData: TRow);
procedure WriteRowFormatIndex(ARow: Cardinal; AFormatIndex: Integer);
procedure WriteRowHeight(ARow: Cardinal; AHeight: Single; AUnits: TsSizeUnits;
ARowHeightType: TsRowHeightType = rhtCustom); overload;
procedure WriteRowHeight(ARow: Cardinal; AHeight: Single;
ARowHeightType: TsRowHeightType = rhtCustom); overload; deprecated 'Use version with parameter AUnits';
procedure WriteColInfo(ACol: Cardinal; AData: TCol);
procedure WriteColFormatIndex(ACol: Cardinal; AFormatIndex: Integer);
procedure WriteColWidth(ACol: Cardinal; AWidth: Single; AUnits: TsSizeUnits); overload;
procedure WriteColWidth(ACol: Cardinal; AWidth: Single); overload; deprecated 'Use version with parameter AUnits';
@ -2873,6 +2855,70 @@ begin
end;
end;
{@@ ----------------------------------------------------------------------------
Returns the index of the effective cell format to be used at the specified
cell.
"Effective" cell format means: At first, look for the cell format.
If it is default, look for the row format. If it is default, look for
the column format. (see "excelfileformat", p. 89)
-------------------------------------------------------------------------------}
function TsWorksheet.GetEffectiveCellFormatIndex(ACell: PCell): Integer;
begin
Result := 0;
if ACell <> nil then
Result := ACell^.FormatIndex;
if Result = 0 then
Result := GetRowFormatIndex(ACell^.Row);
if Result = 0 then
Result := GetColFormatIndex(ACell^.Col);
end;
{@@ ----------------------------------------------------------------------------
Returns a pointer to the effective cell format to be used at the cell in
ARow and ACol.
"Effective" cell format means: At first, look for the cell format.
If it is default, look for the row format. If it is default, look for
the column format. (see "excelfileformat", p. 89)
-------------------------------------------------------------------------------}
function TsWorksheet.GetPointerToEffectiveCellFormat(ARow, ACol: Cardinal): PsCellFormat;
var
cell: PCell;
fmtIndex: Integer;
begin
cell := FindCell(ARow, ACol);
if (cell <> nil) and (cell^.FormatIndex > 0) then
fmtIndex := cell^.FormatIndex
else begin
fmtIndex := GetRowFormatIndex(ARow);
if fmtIndex = 0 then
fmtIndex := GetColFormatIndex(ACol);
end;
Result := FWorkbook.GetPointerToCellFormat(fmtIndex);
end;
{@@ ----------------------------------------------------------------------------
Mainly like GetPointerToEffectiveCellFormat(ARow, ACol), but avoids looking
for the cell if ACell <> nil
-------------------------------------------------------------------------------}
function TsWorksheet.GetPointerToEffectiveCellFormat(ACell: PCell): PsCellFormat;
var
fmtIndex: Integer;
begin
fmtIndex := 0;
if (ACell <> nil) then begin
if (ACell^.FormatIndex > 0) then
fmtIndex := ACell^.FormatIndex
else begin
fmtIndex := GetRowFormatIndex(ACell^.Row);
if fmtIndex = 0 then
fmtIndex := GetColFormatIndex(ACell^.Col);
end;
end;
Result := FWorkbook.GetPointerToCellFormat(fmtIndex);
end;
{@@ ----------------------------------------------------------------------------
Reads the set of used formatting fields of a cell.
@ -4545,6 +4591,7 @@ var
isMixed: Boolean;
rtParams: TsRichTextParams;
plain: String;
fmtIndex: Integer;
begin
if ACell = nil then
exit;
@ -4564,8 +4611,10 @@ begin
WriteNumberFormat(ACell, nfText);
end;
fmt := Workbook.GetCellFormat(ACell^.FormatIndex);
fmtIndex := GetEffectiveCellFormatIndex(ACell);
fmt := Workbook.GetCellFormat(fmtIndex);
numFmtParams := Workbook.GetNumberFormat(fmt.NumberFormatIndex);
ACell^.FormatIndex := fmtIndex;
isPercent := Pos('%', AValue) = Length(AValue);
if isPercent then Delete(AValue, Length(AValue), 1);
@ -6430,6 +6479,28 @@ begin
end;
end;
{@@ ----------------------------------------------------------------------------
Returns the index to the cell format to be used for a given column.
If there is no column record then the default format (index 0) is used.
@param ACol Index of the column considered
@return Index of the format into the workbook's FCellFormatList. This format
will be used for formatting a cell if itself does not have a
non-zero format index, and if there is no row format either.
-------------------------------------------------------------------------------}
function TsWorksheet.GetColFormatIndex(ACol: Cardinal): Integer;
var
col: 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
end;
end;
{@@ ----------------------------------------------------------------------------
Returns the width of the given column. If there is no column record then
the default column width is returned.
@ -6460,6 +6531,28 @@ begin
Result := GetColWidth(ACol, suChars);
end;
{@@ ----------------------------------------------------------------------------
Returns the index to the cell format to be used for a given row.
If there is no row record then the default format (index 0) is returned.
@param ARow Index of the row considered
@return Index of the format into the workbook's FCellFormatList. This format
will be used for formatting a cell if itself does not have a
non-zero format index.
-------------------------------------------------------------------------------}
function TsWorksheet.GetRowFormatIndex(ARow: Cardinal): Integer;
var
row: PRow;
begin
Result := 0; // Default format has index 0
if ARow <> UNASSIGNED_ROW_COL_INDEX then
begin
row := FindRow(ARow);
if row <> nil then
Result := row^.FormatIndex
end;
end;
{@@ ----------------------------------------------------------------------------
Returns the height of the given row. If there is no row record then the
default row height is returned
@ -6905,24 +6998,40 @@ end;
{@@ ----------------------------------------------------------------------------
Writes a row record for the row at a given index to the spreadsheet.
Currently the row record contains only the row height (and the row index,
of course).
The row record contains info on the row height and the row format index.
Creates a new row record if it does not yet exist.
@param ARow Index of the row record which will be created or modified
@param AData Data to be written. Expected to be already in the units
defined for the workbook
Note that the row height value can be negative to indicate
that this is an auto-calculated value (i.e. the value can
change for example when the font size changes).
@param AData Data to be written. Row height expected to be already in the
units defined for the workbook.
-------------------------------------------------------------------------------}
procedure TsWorksheet.WriteRowInfo(ARow: Cardinal; AData: TRow);
var
AElement: PRow;
lRow: PRow;
begin
AElement := GetRow(ARow);
AElement^.Height := AData.Height;
lRow := GetRow(ARow);
lRow^.Height := AData.Height;
lRow^.RowHeightType := AData.RowHeightType;
lRow^.FormatIndex := AData.FormatIndex;
end;
{@@ ----------------------------------------------------------------------------
Sets the cell format index for a specific row.
Creates a new row record if it does not yet exist.
@param ARow Index of the row to be considered
@param AFormatIndex Index into the workbook's FCellFormatList. This format
will be used if a cell has default format index (0).
-------------------------------------------------------------------------------}
procedure TsWorksheet.WriteRowFormatIndex(ARow: Cardinal; AFormatIndex:Integer);
var
lRow: PRow;
begin
if ARow = UNASSIGNED_ROW_COL_INDEX then
exit;
lRow := GetRow(ARow);
lRow^.FormatIndex := AFormatIndex;
end;
{@@ ----------------------------------------------------------------------------
@ -6938,13 +7047,13 @@ end;
procedure TsWorksheet.WriteRowHeight(ARow: Cardinal; AHeight: Single;
AUnits: TsSizeUnits; ARowHeightType: TsRowHeightType = rhtCustom);
var
AElement: PRow;
lRow: PRow;
begin
if ARow = UNASSIGNED_ROW_COL_INDEX then
exit;
AElement := GetRow(ARow);
AElement^.Height := FWorkbook.ConvertUnits(AHeight, AUnits, FWorkbook.FUnits);
AElement^.RowHeightType := ARowHeightType;
lRow := GetRow(ARow);
lRow^.Height := FWorkbook.ConvertUnits(AHeight, AUnits, FWorkbook.FUnits);
lRow^.RowHeightType := ARowHeightType;
end;
{@@ ----------------------------------------------------------------------------
@ -6961,22 +7070,42 @@ begin
end;
{@@ ----------------------------------------------------------------------------
Writes a column record for the column at a given index to the spreadsheet.
Currently the column record contains only the column width (and the column
index, of course).
Writes a column record for the column at a specific index to the spreadsheet.
The column record contains info on the column width and the format index.
Creates a new column record if it does not yet exist.
@param ACol Index of the column record which will be created or modified
@param AData Data to be written (essentially column width). The column
width is already in the units defined for the workbook.
@param AData Data to be written. The column width must already be in
the units defined for the workbook.
-------------------------------------------------------------------------------}
procedure TsWorksheet.WriteColInfo(ACol: Cardinal; AData: TCol);
var
AElement: PCol;
lCol: PCol;
begin
AElement := GetCol(ACol);
AElement^.Width := AData.Width;
lCol := GetCol(ACol);
lCol^.Width := AData.Width;
lCol^.ColWidthType := AData.ColWidthType;
lCol^.FormatIndex := AData.FormatIndex;
end;
{@@ ----------------------------------------------------------------------------
Sets the cell format index for a specific column.
Creates a new column record if it does not yet exist.
@param ACol Index of the column to be considered
@param AFormatIndex Index into the workbook's FCellFormatList. This format
will be used if a cell has default format index (0) and
if there is no specific default row format.
-------------------------------------------------------------------------------}
procedure TsWorksheet.WriteColFormatIndex(ACol: Cardinal; AFormatIndex:Integer);
var
lCol: PCol;
begin
if ACol = UNASSIGNED_ROW_COL_INDEX then
exit;
lCol := GetCol(ACol);
lCol^.FormatIndex := AFormatIndex;
end;
{@@ ----------------------------------------------------------------------------
@ -6990,12 +7119,12 @@ end;
procedure TsWorksheet.WriteColWidth(ACol: Cardinal; AWidth: Single;
AUnits: TsSizeUnits);
var
AElement: PCol;
lCol: PCol;
begin
if ACol = UNASSIGNED_ROW_COL_INDEX then
exit;
AElement := GetCol(ACol);
AElement^.Width := FWorkbook.ConvertUnits(AWidth, AUnits, FWorkbook.FUnits);
lCol := GetCol(ACol);
lCol^.Width := FWorkbook.ConvertUnits(AWidth, AUnits, FWorkbook.FUnits);
end;
{@@ ----------------------------------------------------------------------------

View File

@ -498,7 +498,7 @@ type
TsWorksheetGrid = class(TsCustomWorksheetGrid)
published
// inherited from TsCustomWorksheetGrid
{@@ Automatically recalculates the worksheet if a cell value changes. }
{@@ Automatically recalculates the worksheet formulas if a cell value changes. }
property AutoCalc;
{@@ Automatically expand grid dimensions }
property AutoExpand default [aeData, aeNavigation];
@ -1307,8 +1307,8 @@ begin
if (cell = nil) or not (cell^.ContentType in [cctUTF8String]) then // ... non-label cells
exit;
fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
// fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
fmt := Worksheet.GetPointerToEffectiveCellFormat(cell);
if (uffWordWrap in fmt^.UsedFormattingFields) then // ... word-wrap
exit;
if (uffTextRotation in fmt^.UsedFormattingFields) and // ... vertical text
@ -1717,10 +1717,13 @@ begin
r := ARow - FHeaderCount;
c := ACol - FHeaderCount;
fmt := Worksheet.GetPointerToEffectiveCellFormat(r, c);
lCell := Worksheet.FindCell(r, c);
if lCell <> nil then
begin
fmt := Workbook.GetPointerToCellFormat(lCell^.FormatIndex);
//if lCell <> nil then
//begin
// fmt := Workbook.GetPointerToCellFormat(lCell^.FormatIndex);
// numFmt := Workbook.GetNumberFormat(fmt^.NumberFormatIndex);
// Background color
@ -1760,7 +1763,7 @@ begin
end;
// Font
if Worksheet.HasHyperlink(lCell) then
if (lcell <> nil) and Worksheet.HasHyperlink(lCell) then
fnt := Workbook.GetHyperlinkFont
else
fnt := Workbook.GetDefaultFont;
@ -1771,7 +1774,7 @@ begin
Canvas.Font.Height := Round(ZoomFactor * Canvas.Font.Height);
// Wordwrap, text alignment and text rotation are handled by "DrawTextInCell".
end;
//end;
end;
if IsSelected then
@ -1997,7 +2000,8 @@ begin
DrawBorderLine(ARect.Bottom-1, ARect, drawHor, bs);
if ACell <> nil then begin
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
fmt := Worksheet.GetPointerToEffectiveCellFormat(ACell);
// fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
{
if Worksheet.IsMergeBase(ACell) then
begin
@ -2212,7 +2216,8 @@ begin
then
Continue;
// Overflow possible from non-merged, non-right-aligned, horizontal label cells
fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
// fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
fmt := Worksheet.GetPointerToEffectiveCellFormat(cell);
if (not Worksheet.IsMerged(cell)) and
(cell^.ContentType = cctUTF8String) and
not (uffTextRotation in fmt^.UsedFormattingFields) and
@ -2239,7 +2244,8 @@ begin
then
continue;
// Overflow possible from non-merged, horizontal, non-left-aligned label cells
fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
// fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
fmt := Worksheet.GetPointerToEffectiveCellFormat(cell);
if (not Worksheet.IsMerged(cell)) and
(cell^.ContentType = cctUTF8String) and
not (uffTextRotation in fmt^.UsedFormattingFields) and
@ -2496,15 +2502,7 @@ begin
ts.Layout := tlCenter;
ts.Opaque := false;
Canvas.TextStyle := ts;
{
writeLn('HEADER');
writeln(Format('1 - col=%d, row=%d, font size=%d', [acol, arow, canvas.font.size]));
}
inherited DrawCellText(aCol, aRow, aRect, aState, GetCellText(ACol,ARow));
{
writeln(GetCellText(ACol, ARow));
writeln(Format('2 - col=%d, row=%d, font size=%d', [acol, arow, canvas.font.size]));
}
exit;
end;
@ -2516,7 +2514,8 @@ begin
if txt = '' then
exit;
fmt := Workbook.GetPointerToCellFormat(lCell^.FormatIndex);
// fmt := Workbook.GetPointerToCellFormat(lCell^.FormatIndex);
fmt := Worksheet.GetPointerToEffectiveCellFormat(lCell);
wrapped := (uffWordWrap in fmt^.UsedFormattingFields) or (fmt^.TextRotation = rtStacked);
RTL := IsRightToLeft;
if (uffBiDi in fmt^.UsedFormattingFields) then
@ -2702,9 +2701,10 @@ begin
if (Worksheet = nil) or (ACell = nil) then
exit;
fmt := Worksheet.GetPointerToEffectiveCellFormat(ACell);
with ACell^ do
begin
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
// fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
if Col > 0 then
SetNeighborBorder(Row, Col-1, cbEast, fmt^.BorderStyles[cbWest], cbWest in fmt^.Border);
SetNeighborBorder(Row, Col+1, cbWest, fmt^.BorderStyles[cbEast], cbEast in fmt^.Border);
@ -3121,7 +3121,8 @@ begin
DoPrepareCanvas(ACol, ARow, []);
fmt := Workbook.GetPointerToCellFormat(lCell^.FormatIndex);
// fmt := Workbook.GetPointerToCellFormat(lCell^.FormatIndex);
fmt := Worksheet.GetPointerToEffectiveCellFormat(lCell);
if (uffFont in fmt^.UsedFormattingFields) then
fntIndex := fmt^.FontIndex else fntIndex := DEFAULT_FONTINDEX;
if (uffTextRotation in fmt^.UsedFormattingFields) then
@ -4670,7 +4671,8 @@ begin
if (Result = '') or ((ACell <> nil) and (ACell^.ContentType = cctUTF8String)) then
exit;
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
// fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
fmt := Worksheet.GetPointerToEffectiveCellFormat(ACell^.Row, ACell^.Col);
isRotated := (fmt^.TextRotation <> trHorizontal);
isStacked := (fmt^.TextRotation = rtStacked);
numFmt := Workbook.GetNumberFormat(fmt^.NumberFormatIndex);
@ -5646,8 +5648,10 @@ begin
// If it is a date/time format write a date/time cell...
if cell <> nil then
begin
fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
if fmt <> nil then nfp := Workbook.GetNumberFormat(fmt^.NumberFormatIndex);
// fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
fmt := Worksheet.GetPointerToEffectiveCellFormat(cell);
if fmt <> nil then
nfp := Workbook.GetNumberFormat(fmt^.NumberFormatIndex);
if (fmt <> nil) and IsDateTimeFormat(nfp) then
Worksheet.WriteDateTime(r, c, VarToDateTime(AValue)) else
Worksheet.WriteNumber(r, c, AValue);

View File

@ -674,7 +674,7 @@ type
Worksheet: Pointer; // Must be cast to TsWorksheet when used (avoids circular unit reference)
{ Status flags }
Flags: TsCellFlags;
{ Index of format record in the workbook's FCellFormatList }
{ Index of format record in the workbook's CellFormatList }
FormatIndex: Integer;
{ Cell content }
UTF8StringValue: String; // Strings cannot be part of a variant record
@ -693,6 +693,57 @@ type
{@@ Pointer to a TCell record }
PCell = ^TCell;
{@@ Types of row heights
rhtDefault - default row height
rhtAuto - automatically determined row height, depends on font size,
text rotation, rich-text parameters, word-wrap
rhtCustom - user-determined row height (dragging the row header borders in
the grid, or changed by code) }
TsRowHeightType = (rhtDefault, rhtCustom, rhtAuto);
{@@ Types of column widths
cwtDefault - default column width
cwtCustom - userdefined column width (dragging the column header border
in the grid, or by changed by code) }
TsColWidthtype = (cwtDefault, cwtCustom);
{@@ The record TRow contains information about a spreadsheet row:
@param Row The index of the row (beginning with 0)
@param Height The height of the row (expressed in the units defined
by the workbook)
@param RowHeightType Specifies whether the row has default, custom, or
automatic height
@param FormatIndex Row default format, index into the workbook's
FCellFormatList
Only rows with non-default height or non-default format have a row record. }
TRow = record
Row: Cardinal;
Height: Single;
RowHeightType: TsRowHeightType;
FormatIndex: Integer;
end;
{@@ Pointer to a TRow record }
PRow = ^TRow;
{@@ The record TCol contains information about a spreadsheet column:
@param Col The index of the column (beginning with 0)
@param Width The width of the column (expressed in the units defined
in the workbook)
@param ColWidthType Specifies whether the column has default or custom width
@param FormatIndex Column default format, index into the workbook's
FCellFormatlist
Only columns with non-default width or non-default format have a column record. }
TCol = record
Col: Cardinal;
Width: Single;
ColWidthType: TsColWidthType;
FormatIndex: Integer;
end;
{@@ Pointer to a TCol record }
PCol = ^TCol;
{@@ Embedded image }
TsImage = record
Row, Col: Cardinal; // cell for top/left edge of the image (anchor)
@ -725,15 +776,6 @@ type
{@@ Array with all possible images in a header or a footer }
TsHeaderFooterImages = array[TsHeaderFooterSectionIndex] of TsHeaderFooterImage;
const
{@@ Indexes to be used for the various headers and footers }
HEADER_FOOTER_INDEX_FIRST = 0;
HEADER_FOOTER_INDEX_ODD = 1;
HEADER_FOOTER_INDEX_EVEN = 2;
HEADER_FOOTER_INDEX_ALL = 1;
type
{@@ Search option }
TsSearchOption = (soCompareEntireCell, soMatchCase, soRegularExpr, soAlongRows,
soBackward, soWrapDocument, soEntireDocument);
@ -770,18 +812,18 @@ type
TsStreamParam = (spClipboard, spWindowsClipboardHTML);
TsStreamParams = set of TsStreamParam;
{@@ Types of row heights
rhtDefault - default row height
rhtAuto - automatically determined row height, depends on font size,
text rotation, rich-text parameters, word-wrap
rhtCustom - user-determined row height (dragging the row header borders in
the grid }
TsRowHeightType = (rhtDefault, rhtAuto, rhtCustom);
const
RowHeightTypeNames: array[TsRowHeightType] of string = (
'Default', 'Auto', 'Custom');
ColWidthTypeNames: array[TsColWidthType] of string = (
'Default', 'Custom');
{@@ Indexes to be used for the various headers and footers }
HEADER_FOOTER_INDEX_FIRST = 0;
HEADER_FOOTER_INDEX_ODD = 1;
HEADER_FOOTER_INDEX_EVEN = 2;
HEADER_FOOTER_INDEX_ALL = 1;
implementation

View File

@ -386,6 +386,7 @@ type
procedure AddBuiltinNumFormats; override;
procedure ApplyCellFormatting(ACell: PCell; XFIndex: Word); virtual;
(*
procedure ApplyRichTextFormattingRuns(ACell: PCell;
ARuns: TsRichTextFormattingRuns);
@ -1001,6 +1002,7 @@ begin
ACell^.FormatIndex := 0;
end;
end;
(*
{@@ ----------------------------------------------------------------------------
Converts the rich-text formatting run data as read from the file to the
@ -1401,19 +1403,37 @@ const
var
c, c1, c2: Cardinal;
w: Word;
colwidth: Double;
xf: Word;
lCol: TCol;
idx: Integer;
fmt: PsCellFormat;
begin
// read column start and end index of column range
{ Read column start and end index of column range }
c1 := WordLEToN(AStream.ReadWord);
c2 := WordLEToN(AStream.ReadWord);
// read col width in 1/256 of the width of "0" character
{ Read col width in 1/256 of the width of "0" character }
w := WordLEToN(AStream.ReadWord);
// calculate width in workbook units
colwidth := FWorkbook.ConvertUnits(w / 256, suChars, FWorkbook.Units);
// assign width to columns, but only if different from default column width
if not SameValue(colwidth, FWorksheet.ReadDefaultColWidth(FWorkbook.Units), EPS) then
{ Calculate width in workbook units }
lCol.Width := FWorkbook.ConvertUnits(w / 256, suChars, FWorkbook.Units);
if SameValue(lCol.Width, FWorksheet.ReadDefaultColWidth(FWorkbook.Units), EPS) then
lCol.ColWidthType := cwtDefault else
lCol.ColWidthType := cwtCustom;
{ Read xf record index }
xf := WordLEToN(AStream.ReadWord);
idx := FCellFormatList.FindIndexOfID(xf);
if idx > -1 then begin
fmt := FCellFormatList.Items[idx];
lCol.FormatIndex := FWorkbook.AddCellFormat(fmt^);
end else
lCol.FormatIndex := 0;
{ Assign width and format to columns, but only if different from defaults }
if (lCol.FormatIndex > 0) or (lCol.ColWidthType = cwtCustom) then
for c := c1 to c2 do
FWorksheet.WriteColWidth(c, colwidth, FWorkbook.Units);
FWorksheet.WriteColInfo(c, lCol);
end;
{@@ ----------------------------------------------------------------------------
@ -2086,33 +2106,56 @@ type
end;
var
rowrec: TRowRecord;
lRow: PRow;
lRow: TRow;
h: word;
hpts: Single;
hdef: Single;
isNonDefaultHeight: Boolean;
isAutoSizeHeight: Boolean;
hasFormat: Boolean;
flags: DWord;
xf: Word;
idx: Integer;
fmt: PsCellFormat;
begin
rowrec.RowIndex := 0; // to silence the compiler...
AStream.ReadBuffer(rowrec, SizeOf(TRowRecord));
rowrec.RowIndex := WordLEToN(rowrec.RowIndex);
flags := DWordLEToN(rowrec.Flags);
{ Row height }
h := WordLEToN(rowrec.Height) and $7FFF; // mask off "custom" bit
hpts := FWorkbook.ConvertUnits(TwipsToPts(h), suPoints, FWorkbook.Units);
hdef := FWorksheet.ReadDefaultRowHeight(FWorkbook.Units);
isNonDefaultHeight := not SameValue(hpts, hdef, ROWHEIGHT_EPS);
isAutoSizeHeight := WordLEToN(rowrec.Flags) and $00000040 = 0;
// If this bis is set then font size and row height do NOT match, i.e. NO autosize
isAutoSizeHeight := flags and $00000040 = 0;
// If this bit is set then font size and row height do NOT match, i.e. NO autosize
if isAutoSizeHeight then
lRow.RowHeightType := rhtAuto else
lRow.RowHeightType := rhtCustom;
lRow.Height := hpts;
{ Row format }
lRow.FormatIndex := 0;
hasFormat := flags and $00000080 <> 0;
// If this bit is set then the record contains an xf index.
if hasFormat then begin
xf := (flags and $0FFF0000) shr 16;
if xf = 15 then hasFormat := false;
end;
if hasFormat then begin
// Find the format with ID xf
idx := FCellFormatList.FindIndexOfID(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
// non-standard height (i.e. different from default row height).
if isNonDefaultHeight then begin
lRow := FWorksheet.GetRow(WordLEToN(rowrec.RowIndex));
if isAutoSizeHeight then
lRow^.RowHeightType := rhtAuto else
lRow^.RowHeightType := rhtCustom;
lRow^.Height := hpts;
end;
// non-standard height (i.e. different from default row height) or format.
if isNonDefaultHeight or hasFormat then
FWorksheet.WriteRowInfo(rowrec.RowIndex, lRow);
end;
{@@ ----------------------------------------------------------------------------