Add a note to fpopendocument on difficulties when reading empty formatted cells. 
Add function "CopyCell" to TsWorksheet.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3705 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-11-06 15:19:20 +00:00
parent 1b86c7e3dd
commit ad1bdb294a
3 changed files with 62 additions and 25 deletions

View File

@ -6,7 +6,7 @@ interface
uses uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
ButtonPanel, Grids, ExtCtrls, Buttons, StdCtrls, ComboEx, ButtonPanel, Grids, ExtCtrls, Buttons, StdCtrls,
fpspreadsheet, fpspreadsheetgrid; fpspreadsheet, fpspreadsheetgrid;
type type

View File

@ -83,8 +83,10 @@ type
// Applies internally stored column widths to current worksheet // Applies internally stored column widths to current worksheet
procedure ApplyColWidths; procedure ApplyColWidths;
// Applies a style to a cell // Applies a style to a cell
procedure ApplyStyleToCell(ARow, ACol: Cardinal; AStyleName: String); overload; function ApplyStyleToCell(ARow, ACol: Cardinal;
procedure ApplyStyleToCell(ACell: PCell; AStyleName: String); overload; AStyleName: String): Boolean; overload;
function ApplyStyleToCell(ACell: PCell;
AStyleName: String): Boolean; overload;
// Extracts a boolean value from the xml node // Extracts a boolean value from the xml node
function ExtractBoolFromNode(ANode: TDOMNode): Boolean; function ExtractBoolFromNode(ANode: TDOMNode): Boolean;
// Extracts the date/time value from the xml node // Extracts the date/time value from the xml node
@ -778,24 +780,26 @@ begin
end; end;
end; end;
{ Applies the style data referred to by the style name to the specified cell } { Applies the style data referred to by the style name to the specified cell
procedure TsSpreadOpenDocReader.ApplyStyleToCell(ARow, ACol: Cardinal; The function result is false if a style with the given name could not be found }
AStyleName: String); function TsSpreadOpenDocReader.ApplyStyleToCell(ARow, ACol: Cardinal;
AStyleName: String): Boolean;
var var
cell: PCell; cell: PCell;
begin begin
cell := FWorksheet.GetCell(ARow, ACol); cell := FWorksheet.GetCell(ARow, ACol);
if Assigned(cell) then Result := ApplyStyleToCell(cell, AStyleName)
ApplyStyleToCell(cell, AStyleName);
end; end;
procedure TsSpreadOpenDocReader.ApplyStyleToCell(ACell: PCell; AStyleName: String); function TsSpreadOpenDocReader.ApplyStyleToCell(ACell: PCell; AStyleName: String): Boolean;
var var
styleData: TCellStyleData; styleData: TCellStyleData;
styleIndex: Integer; styleIndex: Integer;
numFmtData: TsNumFormatData; numFmtData: TsNumFormatData;
i: Integer; i: Integer;
begin begin
Result := false;
// Is there a style attached to the cell? // Is there a style attached to the cell?
styleIndex := -1; styleIndex := -1;
if AStyleName <> '' then if AStyleName <> '' then
@ -876,6 +880,8 @@ begin
ACell^.NumberFormatStr := numFmtData.FormatString; ACell^.NumberFormatStr := numFmtData.FormatString;
end; end;
end; end;
Result := true;
end; end;
{ Creates the correct version of the number format list { Creates the correct version of the number format list
@ -1028,7 +1034,17 @@ procedure TsSpreadOpenDocReader.ReadBlank(ARow, ACol: Word; ACellNode: TDOMNode)
var var
styleName: String; styleName: String;
cell: PCell; cell: PCell;
lCell: TCell;
begin begin
// a temporary cell record to store the formatting if there is any
InitCell(ARow, ACol, lCell);
lCell.ContentType := cctEmpty;
styleName := GetAttrValue(ACellNode, 'table:style-name');
if not ApplyStyleToCell(@lCell, stylename) then
exit;
// No need to store a record for an empty, unformatted cell
if FIsVirtualMode then if FIsVirtualMode then
begin begin
InitCell(ARow, ACol, FVirtualCell); InitCell(ARow, ACol, FVirtualCell);
@ -1036,10 +1052,12 @@ begin
end else end else
cell := FWorksheet.GetCell(ARow, ACol); cell := FWorksheet.GetCell(ARow, ACol);
FWorkSheet.WriteBlank(cell); FWorkSheet.WriteBlank(cell);
FWorksheet.CopyFormat(@lCell, cell);
{
styleName := GetAttrValue(ACellNode, 'table:style-name'); styleName := GetAttrValue(ACellNode, 'table:style-name');
ApplyStyleToCell(cell, stylename); ApplyStyleToCell(cell, stylename);
}
if FIsVirtualMode then if FIsVirtualMode then
Workbook.OnReadCellData(Workbook, ARow, ACol, cell); Workbook.OnReadCellData(Workbook, ARow, ACol, cell);
end; end;
@ -1983,15 +2001,6 @@ begin
while Assigned(cellNode) do while Assigned(cellNode) do
begin begin
nodeName := cellNode.NodeName; nodeName := cellNode.NodeName;
// These nodes occur due to indentation spaces which are not skipped
// automatically any more due to PreserveWhiteSpace option applied
// to ReadXMLFile
{
if nodeName <> 'table:table-cell' then begin //= '#text' then begin
cellNode := cellNode.NextSibling;
Continue;
end;
}
if nodeName = 'table:table-cell' then if nodeName = 'table:table-cell' then
begin begin
// select this cell value's type // select this cell value's type
@ -2010,11 +2019,17 @@ begin
ReadDateTime(row, col, cellNode) ReadDateTime(row, col, cellNode)
else if (paramValueType = 'boolean') then else if (paramValueType = 'boolean') then
ReadBoolean(row, col, cellNode) ReadBoolean(row, col, cellNode)
else if (paramValueType = '') then //and (tableStyleName <> '') then else if (paramValueType = '') and (tableStyleName <> '') then
ReadBlank(row, col, cellNode); ReadBlank(row, col, cellNode);
{$Warning TODO: Check if the removal of "tableStyleName" here does not { NOTE: Empty cells having no cell format, but a column format only,
create unnecessary empty cells. The ReadBlank should only be executed are skipped here. --> Currently the reader does not detect the format
if the cell contains formatting! } of empty cells correctly.
It would work if the "(tableStyleName <> '')" would be omitted, but
then the reader would create a record for all 1E9 cells prepared by
the Excel2007 export --> crash!
The column format is available in the FColumnList, but since the usage
of colsSpanned in the row it is possible to miss the correct column format.
Pretty nasty situation! }
if ParamFormula <> '' then if ParamFormula <> '' then
ReadFormula(row, col, cellNode); ReadFormula(row, col, cellNode);

View File

@ -745,7 +745,9 @@ type
function UseSharedFormula(ARow, ACol: Cardinal; ASharedFormulaBase: PCell): PCell; function UseSharedFormula(ARow, ACol: Cardinal; ASharedFormulaBase: PCell): PCell;
{ Data manipulation methods - For Cells } { Data manipulation methods - For Cells }
procedure CopyCell(AFromRow, AFromCol, AToRow, AToCol: Cardinal; AFromWorksheet: TsWorksheet); procedure CopyCell(AFromRow, AFromCol, AToRow, AToCol: Cardinal;
AFromWorksheet: TsWorksheet); overload;
procedure CopyCell(AFromCell, AToCell: PCell); overload;
procedure CopyFormat(AFormat: PCell; AToRow, AToCol: Cardinal); overload; procedure CopyFormat(AFormat: PCell; AToRow, AToCol: Cardinal); overload;
procedure CopyFormat(AFromCell, AToCell: PCell); overload; procedure CopyFormat(AFromCell, AToCell: PCell); overload;
procedure ExchangeCells(ARow1, ACol1, ARow2, ACol2: Cardinal); procedure ExchangeCells(ARow1, ACol1, ARow2, ACol2: Cardinal);
@ -1830,7 +1832,7 @@ end;
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
procedure TsWorksheet.ChangedFont(ARow, ACol: Cardinal); procedure TsWorksheet.ChangedFont(ARow, ACol: Cardinal);
begin begin
if Assigned(FonChangeFont) then FOnChangeFont(Self, ARow, ACol); if Assigned(FOnChangeFont) then FOnChangeFont(Self, ARow, ACol);
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
@ -1849,6 +1851,9 @@ var
lSrcCell, lDestCell: PCell; lSrcCell, lDestCell: PCell;
begin begin
lSrcCell := AFromWorksheet.FindCell(AFromRow, AFromCol); lSrcCell := AFromWorksheet.FindCell(AFromRow, AFromCol);
if lSrcCell = nil then
exit;
lDestCell := GetCell(AToRow, AToCol); lDestCell := GetCell(AToRow, AToCol);
lDestCell^ := lSrcCell^; lDestCell^ := lSrcCell^;
lDestCell^.Row := AToRow; lDestCell^.Row := AToRow;
@ -1857,6 +1862,23 @@ begin
ChangedFont(AToRow, AToCol); ChangedFont(AToRow, AToCol);
end; end;
{@@ ----------------------------------------------------------------------------
Copies a cell
@param FromCell Pointer to the source cell which will be copied
@param ToCell Pointer to the destination cell
-------------------------------------------------------------------------------}
procedure TsWorksheet.CopyCell(AFromCell, AToCell: PCell);
begin
if (AFromCell = nil) or (AToCell = nil) then
exit;
AToCell^ := AFromCell^;
AToCell^.Row := AFromCell^.Row;
AToCell^.Col := AFromCell^.Col;
ChangedCell(AToCell^.Row, AToCell^.Col);
ChangedFont(AToCell^.Row, AToCell^.Col);
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Copies all format parameters from the format cell to another cell. Copies all format parameters from the format cell to another cell.