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);