diff --git a/components/fpspreadsheet/source/common/fpspreadsheet.pas b/components/fpspreadsheet/source/common/fpspreadsheet.pas index 34f273619..63e620231 100644 --- a/components/fpspreadsheet/source/common/fpspreadsheet.pas +++ b/components/fpspreadsheet/source/common/fpspreadsheet.pas @@ -660,6 +660,8 @@ type FBuiltinFontCount: Integer; FReadWriteFlag: TsReadWriteFlag; FCalculationLock: Integer; + FDeleteFormulaLock: Integer; + FNotificationLock: Integer; FRebuildFormulaLock: Integer; FActiveWorksheet: TsWorksheet; FOnOpenWorkbook: TNotifyEvent; @@ -670,7 +672,6 @@ type FOnRemovingWorksheet: TsWorksheetEvent; FOnSelectWorksheet: TsWorksheetEvent; FOnReadCellData: TsWorkbookReadCellDataEvent; - FLockCount: Integer; FSearchEngine: TObject; FCryptoInfo: TsCryptoInfo; {FrevisionsCrypto: TsCryptoInfo;} // Commented out because it needs revision handling @@ -797,6 +798,8 @@ type function FixFormulas(ACorrection: TsFormulaCorrection; AData: Pointer; AParam: PtrInt): boolean; procedure RebuildFormulas; + procedure LockFormulas; + procedure UnlockFormulas; { Clipboard } procedure CopyToClipboardStream(AStream: TStream; AFormat: TsSpreadsheetFormat; @@ -1252,41 +1255,46 @@ begin // Find or create the formula cell lCell := GetCell(AFormula^.Row, AFormula^.Col); - // Assign formula result - case res.ResultType of - rtEmpty : WriteBlank(lCell, true); - rtError : WriteErrorValue(lCell, res.ResError); - rtInteger : WriteNumber(lCell, res.ResInteger); - rtFloat : WriteNumber(lCell, res.ResFloat); - rtDateTime : WriteDateTime(lCell, res.ResDateTime); - rtString : WriteText(lCell, res.ResString); - rtHyperlink : begin - link := ArgToString(res); - p := pos(HYPERLINK_SEPARATOR, link); - if p > 0 then - begin - txt := Copy(link, p+Length(HYPERLINK_SEPARATOR), Length(link)); - link := Copy(link, 1, p-1); - end else - txt := link; - WriteHyperlink(lCell, link); - WriteText(lCell, txt); - end; - rtBoolean : WriteBoolValue(lCell, res.ResBoolean); - rtCell : begin - lCellRef := (res.Worksheet as TsWorksheet).FindCell(res.ResRow, res.ResCol); - if lCellRef <> nil then - case lCellRef^.ContentType of - cctNumber : WriteNumber(lCell, lCellRef^.NumberValue); - cctDateTime : WriteDateTime(lCell, lCellRef^.DateTimeValue); - cctUTF8String: WriteText(lCell, lCellRef^.UTF8StringValue); - cctBool : WriteBoolValue(lCell, lCellRef^.Boolvalue); - cctError : WriteErrorValue(lCell, lCellRef^.ErrorValue); - cctEmpty : WriteBlank(lCell, true); - end - else - WriteBlank(lCell, true); - end; + FWorkbook.LockFormulas; + try + // Assign formula result + case res.ResultType of + rtEmpty : WriteBlank(lCell, true); + rtError : WriteErrorValue(lCell, res.ResError); + rtInteger : WriteNumber(lCell, res.ResInteger); + rtFloat : WriteNumber(lCell, res.ResFloat); + rtDateTime : WriteDateTime(lCell, res.ResDateTime); + rtString : WriteText(lCell, res.ResString); + rtHyperlink : begin + link := ArgToString(res); + p := pos(HYPERLINK_SEPARATOR, link); + if p > 0 then + begin + txt := Copy(link, p+Length(HYPERLINK_SEPARATOR), Length(link)); + link := Copy(link, 1, p-1); + end else + txt := link; + WriteHyperlink(lCell, link); + WriteText(lCell, txt); + end; + rtBoolean : WriteBoolValue(lCell, res.ResBoolean); + rtCell : begin + lCellRef := (res.Worksheet as TsWorksheet).FindCell(res.ResRow, res.ResCol); + if lCellRef <> nil then + case lCellRef^.ContentType of + cctNumber : WriteNumber(lCell, lCellRef^.NumberValue); + cctDateTime : WriteDateTime(lCell, lCellRef^.DateTimeValue); + cctUTF8String: WriteText(lCell, lCellRef^.UTF8StringValue); + cctBool : WriteBoolValue(lCell, lCellRef^.Boolvalue); + cctError : WriteErrorValue(lCell, lCellRef^.ErrorValue); + cctEmpty : WriteBlank(lCell, true); + end + else + WriteBlank(lCell, true); + end; + end; + finally + FWorkbook.UnlockFormulas; end; // Restore the formula. Could have been erased by WriteBlank or WriteText('') @@ -3641,7 +3649,7 @@ end; -------------------------------------------------------------------------------} procedure TsWorksheet.DeleteFormula(ACell: PCell); begin - if HasFormula(ACell) then begin + if HasFormula(ACell) and (FWorkbook.FDeleteFormulaLock = 0) then begin FFormulas.DeleteFormula(ACell); ACell^.Flags := ACell^.Flags - [cfHasFormula, cf3dFormula]; end; @@ -4090,7 +4098,7 @@ begin FName := AName; if FWorkbook.FReadWriteFlag = rwfNormal then begin FWorkbook.RebuildFormulas; - if (FWorkbook.FLockCount = 0) and Assigned(FWorkbook.FOnRenameWorksheet) then + if (FWorkbook.FNotificationLock = 0) and Assigned(FWorkbook.FOnRenameWorksheet) then FWorkbook.FOnRenameWorksheet(FWorkbook, self); end; end; @@ -4595,6 +4603,9 @@ begin end; end; + // Delete any pre-existing formula + DeleteFormula(ACell); + ACell^.UTF8StringValue := AText; if (AText = '') then begin @@ -4718,6 +4729,9 @@ end; procedure TsWorksheet.WriteNumber(ACell: PCell; ANumber: Double); begin if ACell <> nil then begin + // Delete any pre-existing formula + DeleteFormula(ACell); + // Write number to cell ACell^.ContentType := cctNumber; ACell^.NumberValue := ANumber; ChangedCell(ACell^.Row, ACell^.Col); @@ -4768,6 +4782,10 @@ begin raise EFPSpreadsheet.Create(rsInvalidNumberFormat); if ACell <> nil then begin + // Delete any pre-existing formula + DeleteFormula(ACell); + + // Write value to cell ACell^.ContentType := cctNumber; ACell^.NumberValue := ANumber; @@ -4830,6 +4848,13 @@ var fmt: TsCellFormat; begin if ACell <> nil then begin + // Delete any pre-existing formula + DeleteFormula(ACell); + + // Write value to cell + ACell^.ContentType := cctNumber; + ACell^.NumberValue := ANumber; + parser := TsNumFormatParser.Create(ANumFormatString, FWorkbook.FormatSettings); try // Format string ok? @@ -4844,9 +4869,6 @@ begin parser.Free; end; - ACell^.ContentType := cctNumber; - ACell^.NumberValue := ANumber; - fmt := Workbook.GetCellFormat(ACell^.FormatIndex); if ANumFormat <> nfGeneral then begin fmt.NumberFormatIndex := Workbook.AddNumberFormat(ANumFormatString); @@ -4930,6 +4952,9 @@ end; procedure TsWorksheet.WriteBoolValue(ACell: PCell; AValue: Boolean); begin if ACell <> nil then begin + // Delete any pre-existing formula + DeleteFormula(ACell); + // Write value to cell ACell^.ContentType := cctBool; ACell^.BoolValue := AValue; ChangedCell(ACell^.Row, ACell^.Col); @@ -5031,8 +5056,7 @@ begin if ACell = nil then exit; - if HasFormula(ACell) then - DeleteFormula(ACell); + DeleteFormula(ACell); if AValue = '' then begin @@ -5258,6 +5282,10 @@ begin raise EFPSpreadsheet.Create('[TsWorksheet.WriteCurrency] ANumFormat can only be nfCurrency or nfCurrencyRed'); if (ACell <> nil) then begin + // Delete any pre-existing formula + DeleteFormula(ACell); + + // Write value to cell ACell^.ContentType := cctNumber; ACell^.NumberValue := AValue; @@ -5293,6 +5321,9 @@ end; procedure TsWorksheet.WriteDateTime(ACell: PCell; AValue: TDateTime); begin if ACell <> nil then begin + // Delete pre-existing formula + DeleteFormula(ACell); + // Write date to cell ACell^.ContentType := cctDateTime; ACell^.DateTimeValue := AValue; ChangedCell(ACell^.Row, ACell^.Col); @@ -5341,6 +5372,10 @@ var fmt: TsCellFormat; begin if ACell <> nil then begin + // Delete any pre-existing formula + DeleteFormula(ACell); + + // Write date to cell ACell^.ContentType := cctDateTime; ACell^.DateTimeValue := AValue; @@ -5588,6 +5623,9 @@ end; procedure TsWorksheet.WriteErrorValue(ACell: PCell; AValue: TsErrorValue); begin if ACell <> nil then begin + // Delete any pre-existing formula + DeleteFormula(ACell); + // Write value to cell ACell^.ContentType := cctError; ACell^.ErrorValue := AValue; ChangedCell(ACell^.Row, ACell^.Col); @@ -8120,7 +8158,7 @@ end; -------------------------------------------------------------------------------} procedure TsWorkbook.DisableNotifications; begin - inc(FLockCount); + inc(FNotificationLock); end; {@@ ---------------------------------------------------------------------------- @@ -8128,7 +8166,7 @@ end; -------------------------------------------------------------------------------} procedure TsWorkbook.EnableNotifications; begin - dec(FLockCount); + dec(FNotificationLock); end; {@@ ---------------------------------------------------------------------------- @@ -8136,7 +8174,7 @@ end; -------------------------------------------------------------------------------} function TsWorkbook.NotificationsEnabled: Boolean; begin - Result := (FLockCount = 0); + Result := (FNotificationLock = 0); end; {@@ ---------------------------------------------------------------------------- @@ -8399,7 +8437,7 @@ begin PrepareBeforeReading; ok := false; FReadWriteFlag := rwfRead; - inc(FLockCount); // This locks various notifications from being sent + inc(FNotificationLock); // This locks various notifications from being sent try AReader.ReadFromFile(AFileName, APassword, AParams); ok := true; @@ -8410,7 +8448,7 @@ begin FFormatID := AFormatID; finally FReadWriteFlag := rwfNormal; - dec(FLockCount); + dec(FNotificationLock); if ok and Assigned(FOnOpenWorkbook) then // ok is true if file has been read successfully FOnOpenWorkbook(self); // send common notification end; @@ -8535,7 +8573,7 @@ begin PrepareBeforeReading; FReadWriteFlag := rwfRead; ok := false; - inc(FLockCount); + inc(FNotificationLock); try AStream.Position := 0; AReader.ReadFromStream(AStream, APassword, AParams); @@ -8547,7 +8585,7 @@ begin FFormatID := AFormatID; finally FReadWriteFlag := rwfNormal; - dec(FLockCount); + dec(FNotificationLock); if ok and Assigned(FOnOpenWorkbook) then // ok is true if stream has been read successfully FOnOpenWorkbook(self); // send common notification end; @@ -8720,18 +8758,18 @@ begin // Set the name of the new worksheet. // For this we turn off notification of listeners. This is not necessary here // because it will be repeated at end when OnAddWorksheet is executed below. - inc(FLockCount); + inc(FNotificationLock); inc(FRebuildFormulaLock); try Result.Name := AName; finally - dec(FLockCount); + dec(FNotificationLock); dec(FRebuildFormulaLock); end; // Send notification for new worksheet to listeners. They get the worksheet // name here as well. - if (FLockCount = 0) and Assigned(FOnAddWorksheet) then + if (FNotificationLock = 0) and Assigned(FOnAddWorksheet) then FOnAddWorksheet(self, Result); // Make sure that there is an "active" worksheet @@ -8766,7 +8804,7 @@ begin exit; Result := AddWorksheet(AWorksheet.Name, ReplaceDuplicateName); - inc(FLockCount); + inc(FNotificationLock); try for cell in AWorksheet.Cells do begin @@ -8787,7 +8825,7 @@ begin Result.CopyRow(r, r, AWorksheet); end; finally - dec(FLockCount); + dec(FNotificationLock); end; Result.ChangedCell(r, c); @@ -8971,7 +9009,7 @@ begin FActiveWorksheet := nil; FWorksheets.ForEachCall(RemoveWorksheetsCallback, nil); FWorksheets.Clear; - if (FLockCount = 0) and Assigned(FOnRemoveWorksheet) then + if (FNotificationLock = 0) and Assigned(FOnRemoveWorksheet) then FOnRemoveWorksheet(self, -1); end; @@ -9750,6 +9788,16 @@ begin FWorksheets.ForEachCall(RebuildFormulasCallback, nil); end; +procedure TsWorkbook.LockFormulas; +begin + inc(FDeleteFormulaLock); +end; + +procedure TsWorkbook.UnlockFormulas; +begin + dec(FDeleteFormulaLock); +end; + { AData points to the deleted worksheet } procedure FixWorksheetDeletedCallback(ANode: TsExprNode; AData1, AData2: Pointer; diff --git a/components/fpspreadsheet/source/common/xlscommon.pas b/components/fpspreadsheet/source/common/xlscommon.pas index 2b00da924..d9be2fb1f 100644 --- a/components/fpspreadsheet/source/common/xlscommon.pas +++ b/components/fpspreadsheet/source/common/xlscommon.pas @@ -1913,7 +1913,7 @@ begin if IsDateTime(ResultFormula, nf, nfs, dt) then sheet.WriteDateTime(cell, dt) //, nf, nfs) else - sheet.WriteNumber(cell, ResultFormula); //, nf, nfs); + sheet.WriteNumber(cell, ResultFormula); end; { Formula token array } diff --git a/components/fpspreadsheet/source/common/xlsxooxml.pas b/components/fpspreadsheet/source/common/xlsxooxml.pas index e86a14510..ff8e2ffe8 100644 --- a/components/fpspreadsheet/source/common/xlsxooxml.pas +++ b/components/fpspreadsheet/source/common/xlsxooxml.pas @@ -640,6 +640,7 @@ var dataStr: String; formulaStr: String; formula: PsFormula; + isSharedFormula: Boolean; nodeName: String; sstIndex: Integer; number: Double; @@ -699,7 +700,7 @@ begin dataStr := dataStr + GetNodeValue(tnode); tnode := tnode.NextSibling; end; - end else + end; if (boReadFormulas in book.Options) and (nodeName = 'f') then begin // Formula to cell @@ -755,77 +756,83 @@ begin datanode := datanode.NextSibling; end; - // get data type - s := GetAttrValue(ANode, 't'); // "t" = data type - if (s = '') and (dataStr = '') then - sheet.WriteBlank(cell, true) // true --> do not erase the formula!!! - else - if (s = '') or (s = 'n') then begin - // Number or date/time, depending on format - number := StrToFloat(dataStr, FPointSeparatorSettings); - if IsDateTimeFormat(numFmt) then - begin - if not IsTimeIntervalFormat(numFmt) then // no correction of time origin for "time interval" format - number := ConvertExcelDateTimeToDateTime(number, FDateMode); - sheet.WriteDateTime(cell, number); + book.LockFormulas; // Protect formulas from being deleted by the WriteXXXX calls + try + // get data type + s := GetAttrValue(ANode, 't'); // "t" = data type + if (s = '') and (dataStr = '') then + sheet.WriteBlank(cell, true) // true --> do not erase the formula!!! + else + if (s = '') or (s = 'n') then begin + // Number or date/time, depending on format + number := StrToFloat(dataStr, FPointSeparatorSettings); + if IsDateTimeFormat(numFmt) then + begin + if not IsTimeIntervalFormat(numFmt) then // no correction of time origin for "time interval" format + number := ConvertExcelDateTimeToDateTime(number, FDateMode); + sheet.WriteDateTime(cell, number); + end + else if IsTextFormat(numFmt) then + sheet.WriteText(cell, dataStr) + else + sheet.WriteNumber(cell, number); end - else if IsTextFormat(numFmt) then - sheet.WriteText(cell, dataStr) else - sheet.WriteNumber(cell, number); - end - else - if s = 's' then begin - // String from shared strings table - sstIndex := StrToInt(dataStr); - sheet.WriteText(cell, FSharedStrings[sstIndex]); - // Read rich-text parameters from the stream stored in the Objects of the stringlist - if FSharedStrings.Objects[sstIndex] <> nil then - begin - ms := TMemoryStream(FSharedStrings.Objects[sstIndex]); - ms.Position := 0; - n := ms.ReadWord; // Count of array elements - SetLength(cell^.RichTextParams, n); - ms.ReadBuffer(cell^.RichTextParams[0], n*SizeOf(TsRichTextParam)); - end; - end else - if (s = 'str') or (s = 'inlineStr') then begin - // literal string -// formulaStr := cell^.FormulaValue; - sheet.WriteText(cell, datastr); -// cell^.FormulaValue := formulaStr; - end else - if s = 'b' then - // boolean - sheet.WriteBoolValue(cell, dataStr='1') - else - if s = 'e' then begin - // error value - if dataStr = '#NULL!' then - sheet.WriteErrorValue(cell, errEmptyIntersection) - else if dataStr = '#DIV/0!' then - sheet.WriteErrorValue(cell, errDivideByZero) - else if dataStr = '#VALUE!' then - sheet.WriteErrorValue(cell, errWrongType) - else if dataStr = '#REF!' then - sheet.WriteErrorValue(cell, errIllegalRef) - else if dataStr = '#NAME?' then - sheet.WriteErrorValue(cell, errWrongName) - else if dataStr = '#NUM!' then - sheet.WriteErrorValue(cell, errOverflow) - else if dataStr = '#N/A' then - sheet.WriteErrorValue(cell, errArgError) - else if dataStr = '' then - // rare case... - // see http://forum.lazarus.freepascal.org/index.php/topic,38726.0.html - sheet.WriteBlank(cell) + if s = 's' then begin + // String from shared strings table + sstIndex := StrToInt(dataStr); + sheet.WriteText(cell, FSharedStrings[sstIndex]); + // Read rich-text parameters from the stream stored in the Objects of the stringlist + if FSharedStrings.Objects[sstIndex] <> nil then + begin + ms := TMemoryStream(FSharedStrings.Objects[sstIndex]); + ms.Position := 0; + n := ms.ReadWord; // Count of array elements + SetLength(cell^.RichTextParams, n); + ms.ReadBuffer(cell^.RichTextParams[0], n*SizeOf(TsRichTextParam)); + end; + end else + if (s = 'str') or (s = 'inlineStr') then begin + // literal string + sheet.WriteText(cell, datastr); + end else + if s = 'b' then + // boolean + sheet.WriteBoolValue(cell, dataStr='1') else - raise EFPSpreadsheetReader.Create(rsUnknownErrorType); - end else - raise EFPSpreadsheetReader.Create(rsUnknownDataType); + if s = 'e' then begin + // error value + if dataStr = '#NULL!' then + sheet.WriteErrorValue(cell, errEmptyIntersection) + else if dataStr = '#DIV/0!' then + sheet.WriteErrorValue(cell, errDivideByZero) + else if dataStr = '#VALUE!' then + sheet.WriteErrorValue(cell, errWrongType) + else if dataStr = '#REF!' then + sheet.WriteErrorValue(cell, errIllegalRef) + else if dataStr = '#NAME?' then + sheet.WriteErrorValue(cell, errWrongName) + else if dataStr = '#NUM!' then + sheet.WriteErrorValue(cell, errOverflow) + else if dataStr = '#N/A' then + sheet.WriteErrorValue(cell, errArgError) + else if dataStr = '' then + // rare case... + // see http://forum.lazarus.freepascal.org/index.php/topic,38726.0.html + sheet.WriteBlank(cell) + else + raise EFPSpreadsheetReader.Create(rsUnknownErrorType); - if FIsVirtualMode then - book.OnReadCellData(book, rowIndex, colIndex, cell); + + end else + raise EFPSpreadsheetReader.Create(rsUnknownDataType); + + if FIsVirtualMode then + book.OnReadCellData(book, rowIndex, colIndex, cell); + + finally + book.UnlockFormulas; + end; end; procedure TsSpreadOOXMLReader.ReadCellXfs(ANode: TDOMNode); diff --git a/components/fpspreadsheet/tests/formulatests.pas b/components/fpspreadsheet/tests/formulatests.pas index 674e52d56..e792484b1 100644 --- a/components/fpspreadsheet/tests/formulatests.pas +++ b/components/fpspreadsheet/tests/formulatests.pas @@ -38,6 +38,7 @@ type procedure Test_Write_Read_CalcFormulas(AFormat: TsSpreadsheetformat; UseRPNFormula: Boolean); procedure Test_Write_Read_Calc3DFormulas(AFormat: TsSpreadsheetFormat); + procedure Test_OverwriteFormulaTest(ATest: Integer; AFormat: TsSpreadsheetFormat); published // Writes out formulas & reads them back. @@ -83,7 +84,30 @@ type procedure Test_Write_Read_Calc3DFormula_OOXML; procedure Test_Write_Read_Calc3DFormula_ODS; + { Overwrite formula with other content } + procedure Test_OverwriteFormula_Number_BIFF2; + procedure Test_OverwriteFormula_Number_BIFF5; + procedure Test_OverwriteFormula_Number_BIFF8; + procedure Test_OverwriteFormula_Number_OOXML; + procedure Test_OverwriteFormula_Number_ODS; + procedure Test_OverwriteFormula_Text_BIFF2; + procedure Test_OverwriteFormula_Text_BIFF5; + procedure Test_OverwriteFormula_Text_BIFF8; + procedure Test_OverwriteFormula_Text_OOXML; + procedure Test_OverwriteFormula_Text_ODS; + + procedure Test_OverwriteFormula_Bool_BIFF2; + procedure Test_OverwriteFormula_Bool_BIFF5; + procedure Test_OverwriteFormula_Bool_BIFF8; + procedure Test_OverwriteFormula_Bool_OOXML; + procedure Test_OverwriteFormula_Bool_ODS; + + procedure Test_OverwriteFormula_Error_BIFF2; + procedure Test_OverwriteFormula_Error_BIFF5; + procedure Test_OverwriteFormula_Error_BIFF8; + procedure Test_OverwriteFormula_Error_OOXML; + procedure Test_OverwriteFormula_Error_ODS; end; implementation @@ -842,6 +866,208 @@ begin end; +{------------------------------------------------------------------------------} + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormulaTest(ATest: Integer; + AFormat: TsSpreadsheetFormat); +type + TSollValues = record + NumberValue: Integer; + TextValue: String; + BoolValue: Boolean; + ErrorValue: TsErrorValue; + end; +const + SollValue: TSollValues = ( + NumberValue: 100; + TextValue: 'abc'; + BoolValue: false; + ErrorValue: errIllegalRef + ); +var + tempfile: String; + book: TsWorkbook; + sheet: TsWorksheet; + x: Float; + s: String; + b: Boolean; + err: TsErrorValue; + cell: PCell; +begin + tempFile := GetTempFileName; + + book := TsWorkbook.Create; + try + book.Options := book.Options + [boAutoCalc]; + sheet := book.AddWorksheet('Test'); + sheet.WriteFormula(0, 0, '=1+1'); + case ATest of + 0: sheet.WriteNumber(0, 0, sollValue.NumberValue); + 1: sheet.WriteText(0, 0, sollValue.TextValue); + 2: sheet.WriteBoolValue(0, 0, sollValue.BoolValue); + 3: sheet.WriteErrorValue(0, 0, sollValue.ErrorValue); + end; + cell := sheet.FindCell(0, 0); + CheckEquals(true, cell <> nil, 'Cell A1 not found before saving'); + case ATest of + 0: begin + x := sheet.ReadAsNumber(0, 0); + CheckEquals(sollValue.NumberValue, x, 'Cell number content mismatch before saving'); + end; + 1: begin + s := sheet.ReadAsText(0, 0); + CheckEquals(sollValue.TextValue, s, 'Cell string content mismatch before saving'); + end; + 2: begin + b := cell^.BoolValue; + CheckEquals(sollValue.BoolValue, b, 'Cell boolean content mismatch before saving'); + end; + 3: begin + err := cell^.ErrorValue; + CheckEquals(ord(sollValue.ErrorValue), ord(err), 'Cell error ontent mismatch before saving'); + end; + end; + book.WriteToFile(tempFile, AFormat, true); + finally + book.Free; + end; + + book := TsWorkbook.Create; + try + book.Options := book.Options + [boReadFormulas, boAutoCalc]; + book.ReadFromFile(tempFile, AFormat); + sheet := book.GetWorksheetByIndex(0); + cell := sheet.FindCell(0, 0); + CheckEquals(true, cell <> nil, 'Cell A1 not found after reading'); + case ATest of + 0: begin + x := sheet.ReadAsNumber(Cell); + CheckEquals(sollValue.NumberValue, x, 'Cell number content mismatch before saving'); + end; + 1: begin + s := sheet.ReadAsText(cell); + CheckEquals(sollValue.TextValue, s, 'Cell string content mismatch before saving'); + end; + 2: begin + b := cell^.BoolValue; + CheckEquals(sollValue.BoolValue, b, 'Cell boolean content mismatch before saving'); + end; + 3: begin + err := cell^.ErrorValue; + CheckEquals(ord(sollValue.ErrorValue), ord(err), 'Cell error ontent mismatch before saving'); + end; + end; + finally + book.Free; + deleteFile(tempFile); + end; +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Number_BIFF2; +begin + Test_OverwriteFormulaTest(0, sfExcel2); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Number_BIFF5; +begin + Test_OverwriteFormulaTest(0, sfExcel5); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Number_BIFF8; +begin + Test_OverwriteFormulaTest(0, sfExcel8); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Number_OOXML; +begin + Test_OverwriteFormulaTest(0, sfOOXML); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Number_ODS; +begin + Test_OverwriteFormulaTest(0, sfOpenDocument); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Text_BIFF2; +begin + Test_OverwriteFormulaTest(1, sfExcel2); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Text_BIFF5; +begin + Test_OverwriteFormulaTest(1, sfExcel5); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Text_BIFF8; +begin + Test_OverwriteFormulaTest(1, sfExcel8); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Text_OOXML; +begin + Test_OverwriteFormulaTest(1, sfOOXML); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Text_ODS; +begin + Test_OverwriteFormulaTest(1, sfOpenDocument); +end; + + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Bool_BIFF2; +begin + Test_OverwriteFormulaTest(2, sfExcel2); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Bool_BIFF5; +begin + Test_OverwriteFormulaTest(2, sfExcel5); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Bool_BIFF8; +begin + Test_OverwriteFormulaTest(2, sfExcel8); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Bool_OOXML; +begin + Test_OverwriteFormulaTest(2, sfOOXML); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Bool_ODS; +begin + Test_OverwriteFormulaTest(2, sfOpenDocument); +end; + + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Error_BIFF2; +begin + Test_OverwriteFormulaTest(3, sfExcel2); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Error_BIFF5; +begin + Test_OverwriteFormulaTest(3, sfExcel5); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Error_BIFF8; +begin + Test_OverwriteFormulaTest(3, sfExcel8); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Error_OOXML; +begin + Test_OverwriteFormulaTest(3, sfOOXML); +end; + +procedure TSpreadWriteReadFormulaTests.Test_OverwriteFormula_Error_ODS; +begin + Test_OverwriteFormulaTest(3, sfOpenDocument); +end; + + + + initialization // Register so these tests are included in a full run RegisterTest(TSpreadWriteReadFormulaTests);