fpspreadsheet: Read non-contiguous shared formulas correctly from OOXLM (BIFF8 still faulty)

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3588 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-09-22 10:51:33 +00:00
parent ccb7862c6b
commit 094bb314fc
2 changed files with 62 additions and 8 deletions

View File

@ -5113,7 +5113,7 @@ var
cellnode: TAVLTreeNode;
col: PCol;
i: Integer;
r, c, ic: Cardinal;
r, c, cc: Cardinal;
r1, c1, r2, c2: Cardinal;
rLast, cLast: Cardinal;
cell, nextcell, gapcell, oldbase, newbase: PCell;
@ -5160,7 +5160,38 @@ begin
gapcell := GetCell(r, ACol);
gapcell^.Mergebase := cell^.MergeBase;
end;
end
else
// A shared formula block is found immediately to the left of the
// inserted column. If it extends to the right we have to create a new
// shared formula base in the upper left cell. Note: Excel does not
// extend the shared formula to the inserted column.
if cell^.SharedFormulaBase <> nil then begin
oldbase := cell^.SharedFormulaBase;
// Does it extend to the right of the new column?
nextcell := FindCell(r, ACol+1);
if Assigned(nextcell) and (nextcell^.SharedFormulaBase = oldbase) then
begin
// Yes.
// It next cell is in the top row of the block we make it a shared formula base
if r = oldbase^.Row then
begin
newbase := nextcell;
nextcell^.SharedFormulaBase := nextcell;
nextcell^.FormulaValue := InsertColToFormula(ACol, oldbase); // ??
// Note: the references are not correct here - we fix that later!
end;
// Use the new shared formulabase in all cells of the old block at the right
for cc := ACol+1 to cLast do
begin
cell := FindCell(r, cc);
if (cell = nil) or (cell^.SharedFormulaBase <> oldbase) then
break;
cell^.SharedFormulaBase := newbase;
end;
end;
end;
(*
else
// A shared formula block is found immediately before the inserted column
@ -5198,6 +5229,8 @@ begin
*)
end;
// Fix shared formulas:
// A shared formula block may break into two pieces if cell references Cell references to the left and to the right of
// Seek along the column immediately to the left of the inserted column
c := ACol - 1;
for r := 0 to rLast do
@ -5228,9 +5261,9 @@ begin
end;
// Now link all cells to the right of the new column (which still
// use the old base) to the new base
for ic := ACol+1 to cLast do
for cc := ACol+1 to cLast do
begin
cell := FindCell(r, ic);
cell := FindCell(r, cc);
if (cell = nil) or (cell^.SharedFormulaBase <> oldbase) then
break;
cell^.SharedFormulaBase := newbase;

View File

@ -65,6 +65,7 @@ type
FFillList: TFPList;
FBorderList: TFPList;
FThemeColors: array of TsColorValue;
FSharedFormulas: TStringList;
FWrittenByFPS: Boolean;
procedure ReadBorders(ANode: TDOMNode);
procedure ReadCell(ANode: TDOMNode; AWorksheet: TsWorksheet);
@ -395,6 +396,8 @@ begin
// Set up the default palette in order to have the default color names correct.
Workbook.UseDefaultPalette;
FSharedFormulas := TStringList.Create;
FSharedStrings := TStringList.Create;
FFillList := TFPList.Create;
FBorderList := TFPList.Create;
@ -418,6 +421,7 @@ begin
FBorderList.Free;
FSharedStrings.Free;
FSharedFormulas.Free;
inherited Destroy;
end;
@ -610,7 +614,7 @@ end;
procedure TsSpreadOOXMLReader.ReadCell(ANode: TDOMNode; AWorksheet: TsWorksheet);
var
s: String;
addr, s: String;
rowIndex, colIndex: Cardinal;
cell: PCell;
datanode: TDOMNode;
@ -623,8 +627,8 @@ begin
exit;
// get row and column address
s := GetAttrValue(ANode, 'r'); // cell address, like 'A1'
ParseCellString(s, rowIndex, colIndex);
addr := GetAttrValue(ANode, 'r'); // cell address, like 'A1'
ParseCellString(addr, rowIndex, colIndex);
// create cell
if FIsVirtualMode then
@ -656,11 +660,28 @@ begin
s := GetAttrValue(datanode, 't');
if s = 'shared' then
begin
// Shared formula
s := GetAttrValue(datanode, 'ref');
if (s <> '') then
AWorksheet.WriteSharedFormula(s, formulaStr);
if (s <> '') then // This is the shared formula base
begin
s := GetAttrValue(datanode, 'si');
if s <> '' then
FSharedFormulas.AddObject(addr, Pointer(PtrInt(StrToInt(s))));
FWorksheet.WriteFormula(cell, formulaStr);
cell^.SharedFormulaBase := cell;
//AWorksheet.WriteSharedFormula(s, formulaStr);
end else
begin
s := GetAttrValue(datanode, 'si');
if s <> '' then
begin
s := FSharedFormulas[FSharedFormulas.IndexOfObject(Pointer(PtrInt(StrToInt(s))))];
cell^.SharedFormulaBase := FWorksheet.FindCell(s);
end;
end;
end
else
// "Normal" formula
AWorksheet.WriteFormula(cell, formulaStr);
end;
datanode := datanode.NextSibling;