From 92a0c02e8f95bf5342b7b0fb9ec2d1b13b842b75 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Wed, 13 May 2020 05:42:33 +0000 Subject: [PATCH] fpspreadsheet: Add error log entry when reading xlsx files with non-numeric data in numeric cells, instead of aborting the program. Issue #37055, modified patch by Tulurdes. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7452 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../fpspreadsheet/source/common/xlsxooxml.pas | 53 ++++++++++++------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/components/fpspreadsheet/source/common/xlsxooxml.pas b/components/fpspreadsheet/source/common/xlsxooxml.pas index b733df144..023285614 100644 --- a/components/fpspreadsheet/source/common/xlsxooxml.pas +++ b/components/fpspreadsheet/source/common/xlsxooxml.pas @@ -736,6 +736,7 @@ begin tnode := tnode.NextSibling; end; end; + if (boReadFormulas in book.Options) and ((nodeName = 'f') or (nodeName = 'x:f'))then begin // Formula to cell @@ -800,32 +801,44 @@ begin else if (s = '') or (s = 'n') then begin // Number or date/time, depending on format - number := StrToFloat(dataStr, FPointSeparatorSettings); - if IsDateTimeFormat(numFmt) then + if TryStrToFloat(dataStr, number, FPointSeparatorSettings) 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); + 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 + workbook.AddErrorMsg( + 'Error reading cell %s: Failure to convert "%s" to number.', [ + GetCellString(rowindex, colindex), dataStr + ]); 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 + if TryStrToInt(dataStr, sstIndex) 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; + 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 + workbook.AddErrorMsg( + 'Error readind cell %s: Failure to extract SST index from value "%s"', [ + GetCellString(rowindex, colindex), dataStr + ]); end else if (s = 'str') or (s = 'inlineStr') then begin // literal string