You've already forked lazarus-ccr
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:
@@ -5113,7 +5113,7 @@ var
|
|||||||
cellnode: TAVLTreeNode;
|
cellnode: TAVLTreeNode;
|
||||||
col: PCol;
|
col: PCol;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
r, c, ic: Cardinal;
|
r, c, cc: Cardinal;
|
||||||
r1, c1, r2, c2: Cardinal;
|
r1, c1, r2, c2: Cardinal;
|
||||||
rLast, cLast: Cardinal;
|
rLast, cLast: Cardinal;
|
||||||
cell, nextcell, gapcell, oldbase, newbase: PCell;
|
cell, nextcell, gapcell, oldbase, newbase: PCell;
|
||||||
@@ -5160,7 +5160,38 @@ begin
|
|||||||
gapcell := GetCell(r, ACol);
|
gapcell := GetCell(r, ACol);
|
||||||
gapcell^.Mergebase := cell^.MergeBase;
|
gapcell^.Mergebase := cell^.MergeBase;
|
||||||
end;
|
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;
|
end;
|
||||||
|
|
||||||
(*
|
(*
|
||||||
else
|
else
|
||||||
// A shared formula block is found immediately before the inserted column
|
// A shared formula block is found immediately before the inserted column
|
||||||
@@ -5198,6 +5229,8 @@ begin
|
|||||||
*)
|
*)
|
||||||
end;
|
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
|
// Seek along the column immediately to the left of the inserted column
|
||||||
c := ACol - 1;
|
c := ACol - 1;
|
||||||
for r := 0 to rLast do
|
for r := 0 to rLast do
|
||||||
@@ -5228,9 +5261,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
// Now link all cells to the right of the new column (which still
|
// Now link all cells to the right of the new column (which still
|
||||||
// use the old base) to the new base
|
// use the old base) to the new base
|
||||||
for ic := ACol+1 to cLast do
|
for cc := ACol+1 to cLast do
|
||||||
begin
|
begin
|
||||||
cell := FindCell(r, ic);
|
cell := FindCell(r, cc);
|
||||||
if (cell = nil) or (cell^.SharedFormulaBase <> oldbase) then
|
if (cell = nil) or (cell^.SharedFormulaBase <> oldbase) then
|
||||||
break;
|
break;
|
||||||
cell^.SharedFormulaBase := newbase;
|
cell^.SharedFormulaBase := newbase;
|
||||||
|
@@ -65,6 +65,7 @@ type
|
|||||||
FFillList: TFPList;
|
FFillList: TFPList;
|
||||||
FBorderList: TFPList;
|
FBorderList: TFPList;
|
||||||
FThemeColors: array of TsColorValue;
|
FThemeColors: array of TsColorValue;
|
||||||
|
FSharedFormulas: TStringList;
|
||||||
FWrittenByFPS: Boolean;
|
FWrittenByFPS: Boolean;
|
||||||
procedure ReadBorders(ANode: TDOMNode);
|
procedure ReadBorders(ANode: TDOMNode);
|
||||||
procedure ReadCell(ANode: TDOMNode; AWorksheet: TsWorksheet);
|
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.
|
// Set up the default palette in order to have the default color names correct.
|
||||||
Workbook.UseDefaultPalette;
|
Workbook.UseDefaultPalette;
|
||||||
|
|
||||||
|
FSharedFormulas := TStringList.Create;
|
||||||
|
|
||||||
FSharedStrings := TStringList.Create;
|
FSharedStrings := TStringList.Create;
|
||||||
FFillList := TFPList.Create;
|
FFillList := TFPList.Create;
|
||||||
FBorderList := TFPList.Create;
|
FBorderList := TFPList.Create;
|
||||||
@@ -418,6 +421,7 @@ begin
|
|||||||
FBorderList.Free;
|
FBorderList.Free;
|
||||||
|
|
||||||
FSharedStrings.Free;
|
FSharedStrings.Free;
|
||||||
|
FSharedFormulas.Free;
|
||||||
|
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
@@ -610,7 +614,7 @@ end;
|
|||||||
|
|
||||||
procedure TsSpreadOOXMLReader.ReadCell(ANode: TDOMNode; AWorksheet: TsWorksheet);
|
procedure TsSpreadOOXMLReader.ReadCell(ANode: TDOMNode; AWorksheet: TsWorksheet);
|
||||||
var
|
var
|
||||||
s: String;
|
addr, s: String;
|
||||||
rowIndex, colIndex: Cardinal;
|
rowIndex, colIndex: Cardinal;
|
||||||
cell: PCell;
|
cell: PCell;
|
||||||
datanode: TDOMNode;
|
datanode: TDOMNode;
|
||||||
@@ -623,8 +627,8 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
|
|
||||||
// get row and column address
|
// get row and column address
|
||||||
s := GetAttrValue(ANode, 'r'); // cell address, like 'A1'
|
addr := GetAttrValue(ANode, 'r'); // cell address, like 'A1'
|
||||||
ParseCellString(s, rowIndex, colIndex);
|
ParseCellString(addr, rowIndex, colIndex);
|
||||||
|
|
||||||
// create cell
|
// create cell
|
||||||
if FIsVirtualMode then
|
if FIsVirtualMode then
|
||||||
@@ -656,11 +660,28 @@ begin
|
|||||||
s := GetAttrValue(datanode, 't');
|
s := GetAttrValue(datanode, 't');
|
||||||
if s = 'shared' then
|
if s = 'shared' then
|
||||||
begin
|
begin
|
||||||
|
// Shared formula
|
||||||
s := GetAttrValue(datanode, 'ref');
|
s := GetAttrValue(datanode, 'ref');
|
||||||
if (s <> '') then
|
if (s <> '') then // This is the shared formula base
|
||||||
AWorksheet.WriteSharedFormula(s, formulaStr);
|
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
|
end
|
||||||
else
|
else
|
||||||
|
// "Normal" formula
|
||||||
AWorksheet.WriteFormula(cell, formulaStr);
|
AWorksheet.WriteFormula(cell, formulaStr);
|
||||||
end;
|
end;
|
||||||
datanode := datanode.NextSibling;
|
datanode := datanode.NextSibling;
|
||||||
|
Reference in New Issue
Block a user