fpspreadsheet: Remove fix for Excel's Year-1900 problem because it creates new issues... (issue #38742).

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8033 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2021-05-15 21:38:39 +00:00
parent 1efc3bc6f2
commit e66195efeb
3 changed files with 25 additions and 28 deletions

View File

@ -821,29 +821,17 @@ begin
if (AExcelDateNum < 1) and (AExcelDateNum >= 0) then if (AExcelDateNum < 1) and (AExcelDateNum >= 0) then
begin begin
Result := AExcelDateNum; Result := AExcelDateNum;
end end else
else
begin begin
case ADateMode of case ADateMode of
dm1900: dm1900:
begin begin
Result := AExcelDateNum + DATEMODE_1900_BASE - 1.0; Result := AExcelDateNum + DATEMODE_1900_BASE - 1.0;
// Excel and Lotus 1-2-3 incorrectly assume that 1900 was a leap year { Excel and Lotus 1-2-3 incorrectly assume that 1900 was a leap year
// Therefore all dates before March 01 are off by 1. Therefore all dates before March 01 are off by 1.
// The old fps implementation corrected only Feb 29, but all days are Unlike earlier fps versions we no longer attempt to fix this issue
// wrong! because it leads to other issues (when dates are in order then
if AExcelDateNum < 61 then the weekdays are off by 1!) }
Result := Result + 1.0;
(*
// Check for Lotus 1-2-3 bug with 1900 leap year
if AExcelDateNum=61.0 then
// 29 feb does not exist, change to 28
// Spell out that we remove a day for ehm "clarity".
result := 61.0 - 1.0 + DATEMODE_1900_BASE - 1.0
else
result := AExcelDateNum + DATEMODE_1900_BASE - 1.0;
*)
end; end;
dm1904: dm1904:
result := AExcelDateNum + DATEMODE_1904_BASE; result := AExcelDateNum + DATEMODE_1904_BASE;
@ -857,17 +845,21 @@ function ConvertDateTimeToExcelDateTime(const ADateTime: TDateTime;
ADateMode: TDateMode): Double; ADateMode: TDateMode): Double;
begin begin
// Time only // Time only
if (ADateTime<1) and (ADateTime>=0) then if (ADateTime < 1) and (ADateTime >= 0) then
begin begin
Result:=ADateTime; Result := ADateTime;
end end
else else
begin begin
case ADateMode of case ADateMode of
dm1900: dm1900:
begin begin
{ Excel and Lotus 1-2-3 incorrectly assume that 1900 was a leap year
Therefore all dates before March 01 are off by 1.
Unlike earlier fps versions we no longer attempt to fix this issue
because it leads to other issues (when dates are in order then
the weekdays are off by 1!) }
Result := ADateTime - DATEMODE_1900_BASE + 1.0; Result := ADateTime - DATEMODE_1900_BASE + 1.0;
if Result < 61 then Result := Result - 1.0;
end; end;
dm1904: dm1904:
Result := ADateTime - DATEMODE_1904_BASE; Result := ADateTime - DATEMODE_1904_BASE;
@ -1507,7 +1499,9 @@ begin
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Converts the number to a date/time and return that if it is Converts the number to a date/time and returns that if it is
Like LibreOffice Calc, we do not attempt to fix the Year-1900 issue of Excel
files because it leads to even more confusion...
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
function TsSpreadBIFFReader.IsDateTime(Number: Double; function TsSpreadBIFFReader.IsDateTime(Number: Double;
ANumberFormat: TsNumberFormat; ANumberFormatStr: String; ANumberFormat: TsNumberFormat; ANumberFormatStr: String;
@ -2250,7 +2244,7 @@ begin
end else end else
cell := sheet.AddCell(ARow, ACol); // "real" cell cell := sheet.AddCell(ARow, ACol); // "real" cell
if IsDateTime(value, nf, nfs, dt) then // Year-1900 correction occurs here! if IsDateTime(value, nf, nfs, dt) then // DateMode correction occurs here!
sheet.WriteDateTime(cell, dt, nf, nfs) sheet.WriteDateTime(cell, dt, nf, nfs)
else if nf = nfText then else if nf = nfText then
sheet.WriteText(cell, GeneralFormatFloat(value, FWorkbook.FormatSettings)) sheet.WriteText(cell, GeneralFormatFloat(value, FWorkbook.FormatSettings))
@ -4189,11 +4183,11 @@ var
cf: TsCellFormat; cf: TsCellFormat;
nfp: TsNumFormatParams; nfp: TsNumFormatParams;
begin begin
// We must correct the bug of Lotus 1-2-3 which had ignored that year 1900 was // We must convert the date value to the Excel date basis (DateMode),
// a leap year, but only for "normal" date format, not for time-interval formats // but not for time-interval formats.
cf := TsWorksheet(FWorksheet).ReadCellFormat(ACell); cf := TsWorksheet(FWorksheet).ReadCellFormat(ACell);
nfp := TsWorkbook(FWorkbook).GetNumberFormat(cf.NumberFormatIndex); nfp := TsWorkbook(FWorkbook).GetNumberFormat(cf.NumberFormatIndex);
if IsTimeIntervalFormat(nfp) then //or IsTimeFormat(nfp) then if IsTimeIntervalFormat(nfp) then
ExcelDateSerial := AValue ExcelDateSerial := AValue
else else
ExcelDateSerial := ConvertDateTimeToExcelDateTime(AValue, FDateMode); ExcelDateSerial := ConvertDateTimeToExcelDateTime(AValue, FDateMode);

View File

@ -2745,6 +2745,7 @@ var
fmt: PsCellFormat; fmt: PsCellFormat;
begin begin
Unused(ARow, ACol); Unused(ARow, ACol);
(*
fmt := (FWorkbook as TsWorkbook).GetPointerToCellFormat(ACell^.FormatIndex); fmt := (FWorkbook as TsWorkbook).GetPointerToCellFormat(ACell^.FormatIndex);
if (fmt <> nil) and (uffNumberFormat in fmt^.UsedFormattingFields) then if (fmt <> nil) and (uffNumberFormat in fmt^.UsedFormattingFields) then
begin begin
@ -2764,9 +2765,10 @@ begin
end; end;
if valueStr = '' then if valueStr = '' then
begin begin
*)
ExcelDate := ConvertDateTimeToExcelDateTime(AValue, FDateMode); ExcelDate := ConvertDateTimeToExcelDateTime(AValue, FDateMode);
valueStr := FormatDateTime('yyyy-mm-dd"T"hh:nn:ss.zzz', ExcelDate); valueStr := FormatDateTime('yyyy-mm-dd"T"hh:nn:ss.zzz', ExcelDate);
end; //end;
AppendToStream(AStream, Format(CELL_INDENT + AppendToStream(AStream, Format(CELL_INDENT +
'<Cell%s%s%s%s%s>' + LF + VALUE_INDENT + // colIndex, style, formula, hyperlink, merge '<Cell%s%s%s%s%s>' + LF + VALUE_INDENT + // colIndex, style, formula, hyperlink, merge

View File

@ -1043,7 +1043,8 @@ begin
begin begin
if IsDateTimeFormat(numFmt) then if IsDateTimeFormat(numFmt) then
begin begin
if not IsTimeIntervalFormat(numFmt) then // no correction of time origin for "time interval" format if not IsTimeIntervalFormat(numFmt) then
// no correction of time origin for "time" or "time interval" format
number := ConvertExcelDateTimeToDateTime(number, FDateMode); number := ConvertExcelDateTimeToDateTime(number, FDateMode);
sheet.WriteDateTime(cell, number); sheet.WriteDateTime(cell, number);
end end