diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas index 9742e94e6..d8b4af859 100755 --- a/components/fpspreadsheet/fpspreadsheet.pas +++ b/components/fpspreadsheet/fpspreadsheet.pas @@ -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; diff --git a/components/fpspreadsheet/xlsxooxml.pas b/components/fpspreadsheet/xlsxooxml.pas index 6d526f351..772e2be41 100755 --- a/components/fpspreadsheet/xlsxooxml.pas +++ b/components/fpspreadsheet/xlsxooxml.pas @@ -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;