diff --git a/components/fpspreadsheet/fpsopendocument.pas b/components/fpspreadsheet/fpsopendocument.pas
index 99d4245f2..29e9fdb96 100755
--- a/components/fpspreadsheet/fpsopendocument.pas
+++ b/components/fpspreadsheet/fpsopendocument.pas
@@ -1275,6 +1275,7 @@ begin
ApplyStyleToCell(cell, stylename);
fmt := Workbook.GetPointerToCellFormat(cell^.FormatIndex);
+ formula := '';
if (boReadFormulas in FWorkbook.Options) then
begin
// Read formula, trim it, ...
@@ -1352,6 +1353,7 @@ begin
FWorksheet.WriteBoolValue(cell, boolValue);
end else
// (e) Text
+ if (valueStr <> '') then
FWorksheet.WriteUTF8Text(cell, valueStr);
if FIsVirtualMode then
@@ -4219,11 +4221,6 @@ begin
hyperlink := FWorksheet.FindHyperlink(ACell);
SplitHyperlink(hyperlink^.Target, target, bookmark);
- {
- if (target = '') and (bookmark <> '') then
- target := '#' + bookmark
- else
- }
if (target <> '') and (pos('file:', target) = 0) then
begin
u := ParseURI(target);
@@ -4237,33 +4234,11 @@ begin
if (bookmark <> '') then
target := target + '#' + bookmark;
- {
- u := ParseURI(hyperlink^.Target);
- if u.Protocol = '' then // relative file name, or internal link
- begin
- if target <> '' then target := '../' + target;
- if bookmark <> '' then target := target + '#' + bookmark;
- end else
- target := hyperlink^.Target;
- }
- //ValidXMLText(target);
- {
- target := hyperlink^.Target;
- if target[1] <> '#' then
- begin
- u := ParseURI(target);
- if u.Protocol = '' then begin
- //UriToFileName(hyperlink^.Target, target);
- target := 'file:///' + ExpandFileName(target);
- ValidXMLText(target);
-// if not IsAbsoluteURI(target) then target := '..\' + target;
- end;
- end;
- }
textp := Format(
''+
'%s'+
'', [target, txt]);
+
end else
textp := '' + txt + '';
diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas
index 5c554645a..a62dd2f26 100755
--- a/components/fpspreadsheet/fpspreadsheet.pas
+++ b/components/fpspreadsheet/fpspreadsheet.pas
@@ -1249,7 +1249,6 @@ end;
-------------------------------------------------------------------------------}
procedure TsWorksheet.CalcFormulas;
var
- node: TAVLTreeNode;
cell: PCell;
begin
// prevent infinite loop due to triggering of formula calculation whenever
@@ -1257,23 +1256,15 @@ begin
inc(FWorkbook.FCalculationLock);
try
// Step 1 - mark all formula cells as "not calculated"
- node := FCells.FindLowest;
- while Assigned(node) do begin
- cell := PCell(node.Data);
+ for cell in FCells do
if HasFormula(cell) then
SetCalcState(cell, csNotCalculated);
- node := FCells.FindSuccessor(node);
- end;
// Step 2 - calculate cells. If a not-yet-calculated cell is found it is
// calculated and then marked as such.
- node := FCells.FindLowest;
- while Assigned(node) do begin
- cell := PCell(node.Data);
- if (cell^.ContentType <> cctError) and HasFormula(cell) then
+ for cell in FCells do
+ if HasFormula(cell) and (cell^.ContentType <> cctError) then
CalcFormula(cell);
- node := FCells.FindSuccessor(node);
- end;
finally
dec(FWorkbook.FCalculationLock);
diff --git a/components/fpspreadsheet/tests/insertdeletetests.pas b/components/fpspreadsheet/tests/insertdeletetests.pas
index 0ce17954b..30b11f424 100644
--- a/components/fpspreadsheet/tests/insertdeletetests.pas
+++ b/components/fpspreadsheet/tests/insertdeletetests.pas
@@ -24,12 +24,14 @@ type
DeleteRow: Integer;
Formula: String;
SollFormula: String;
+ {
SharedFormulaRowCount: Integer; // Size of shared formula block before insert/delete
SharedFormulaColCount: Integer;
SharedFormulaBaseCol_After: Integer; // Position of shared formula base after insert/delete
SharedFormulaBaseRow_After: Integer;
SharedFormulaRowCount_After: Integer; // Size of shared formula block after insert/delete
SharedFormulaColCount_After: Integer;
+ }
MergedColCount: Integer; // size of merged block before insert/delete
MergedRowCount: Integer;
MergedColCount_After: Integer; // size of merged block after insert/delete
@@ -237,12 +239,14 @@ begin
DeleteRow := -1;
Formula := '';
SollFormula := '';
+ {
SharedFormulaColCount := 0;
SharedFormulaRowCount := 0;
SharedFormulaBaseCol_After := -1;
SharedFormulaBaseRow_After := -1;
SharedFormulaColCount_After := 0;
SharedFormulaRowCount_After := 0;
+ }
MergedColCount := 0;
MergedRowCount := 0;
end;
@@ -931,16 +935,17 @@ var
r1,c1,r2,c2: Cardinal;
MyCell: PCell;
TempFile: string; //write xls/xml to this file and read back from it
- L, LL: TStringList;
+ L: TStringList;
s: String;
expected: String;
actual: String;
- expectedFormulas: array of array of String;
+// expectedFormulas: array of array of String;
begin
TempFile := GetTempFileName;
L := TStringList.Create;
try
+ {
// Extract soll formulas into a 2D array in case of shared formulas
if (InsDelTestData[ATestIndex].SharedFormulaRowCount_After > 0) or
(InsDelTestData[ATestIndex].SharedFormulaColCount_After > 0) then
@@ -963,7 +968,7 @@ begin
LL.Free;
end;
end;
-
+ }
L.Delimiter := '|';
L.StrictDelimiter := true;
L.DelimitedText := InsDelTestData[ATestIndex].Layout;
@@ -1047,6 +1052,7 @@ begin
end;
if HasFormula(MyCell) then
begin
+ {
if (InsDelTestData[ATestIndex].SharedFormulaRowCount_After > 0) or
(InsDelTestData[ATestIndex].SharedFormulaColCount_After > 0)
then
@@ -1057,6 +1063,7 @@ begin
'Shared formula mismatch, cell ' + CellNotation(MyWorksheet, Row, Col)
)
else
+ }
CheckEquals(
InsDelTestData[ATestIndex].SollFormula,
MyWorksheet.ReadFormulaAsString(MyCell),
diff --git a/components/fpspreadsheet/xlsxooxml.pas b/components/fpspreadsheet/xlsxooxml.pas
index bbd4f3eb1..344f752a2 100755
--- a/components/fpspreadsheet/xlsxooxml.pas
+++ b/components/fpspreadsheet/xlsxooxml.pas
@@ -66,6 +66,7 @@ type
FFillList: TFPList;
FBorderList: TFPList;
FHyperlinkList: TFPList;
+ FSharedFormulaBaseList: TFPList;
FThemeColors: array of TsColorValue;
FWrittenByFPS: Boolean;
procedure ApplyCellFormatting(ACell: PCell; XfIndex: Integer);
@@ -468,6 +469,7 @@ begin
FHyperlinkList := TFPList.Create;
FCellFormatList := TsCellFormatList.Create(true);
// Allow duplicates because xf indexes used in cell records cannot be found any more.
+ FSharedFormulaBaseList := TFPList.Create;
FPointSeparatorSettings := DefaultFormatSettings;
FPointSeparatorSettings.DecimalSeparator := '.';
@@ -487,6 +489,7 @@ begin
FHyperlinkList.Free;
FSharedStrings.Free;
+ FSharedFormulaBaseList.Free; // Don't free items, they are worksheet cells
// FCellFormatList and FFontList are destroyed by ancestor
@@ -664,7 +667,7 @@ procedure TsSpreadOOXMLReader.ReadCell(ANode: TDOMNode; AWorksheet: TsWorksheet)
var
addr, s: String;
rowIndex, colIndex: Cardinal;
- cell: PCell;
+ cell, sharedformulabase: PCell;
datanode: TDOMNode;
dataStr: String;
formulaStr: String;
@@ -716,13 +719,21 @@ begin
begin
// Shared formula
s := GetAttrValue(datanode, 'ref');
- if (s <> '') then // This is the shared formula range
+ if (s <> '') then // This defines the shared formula range
begin
- // Split shared formula into single-cell formulas
- ParseCellRangeString(s, rng);
- for r := rng.Row1 to rng.Row2 do
- for c := rng.Col1 to rng.Col2 do
- FWorksheet.CopyFormula(cell, r, c);
+ AWorksheet.WriteFormula(cell, FormulaStr);
+ // We store the shared formula base in the SharedFormulaBaseList.
+ // The list index is identical with the 'si' attribute of the node.
+ FSharedFormulaBaseList.Add(cell);
+ end else
+ begin
+ // Get index into the SharedFormulaBaseList
+ s := GetAttrValue(datanode, 'si');
+ if s <> '' then
+ begin
+ sharedformulabase := PCell(FSharedFormulaBaseList[StrToInt(s)]);
+ FWorksheet.CopyFormula(sharedformulabase, rowindex, colindex);
+ end;
end;
end
else
@@ -735,8 +746,10 @@ begin
// get data type
s := GetAttrValue(ANode, 't'); // "t" = data type
if (s = '') and (dataStr = '') then
- AWorksheet.WriteBlank(cell)
- else
+ begin
+ AWorksheet.WriteBlank(cell); // this erases the formula!!!
+ if formulaStr <> '' then cell^.FormulaValue := formulaStr;
+ end else
if (s = '') or (s = 'n') then begin
// Number or date/time, depending on format
number := StrToFloat(dataStr, FPointSeparatorSettings);