fpspreadsheet: Finishes the basic support for date reading

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@2263 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
sekelsenmat
2012-01-23 13:48:39 +00:00
parent 37d06a3d25
commit 09153c582d
3 changed files with 50 additions and 8 deletions

View File

@ -603,6 +603,7 @@ begin
//cctFormula
cctNumber: Result := FloatToStr(ACell^.NumberValue);
cctUTF8String: Result := ACell^.UTF8StringValue;
cctDateTime: Result := SysUtils.DateToStr(ACell^.DateTimeValue);
else
Result := '';
end;

View File

@ -52,7 +52,7 @@ unit xlsbiff8;
interface
uses
Classes, SysUtils, fpcanvas,
Classes, SysUtils, fpcanvas, DateUtils,
fpspreadsheet, xlscommon,
{$ifdef USE_NEW_OLE}
fpolebasic,
@ -104,7 +104,7 @@ type
procedure ReadXF(const AStream: TStream);
procedure ReadFormat(const AStream: TStream);
function FindFormatRecordForCell(const AFXIndex: Integer): TFormatRecordData;
class function ConvertExcelDateToTDateTime(const AExcelDateNum: Integer): TDateTime;
class function ConvertExcelDateToTDateTime(const AExcelDateNum: Double; ABaseDate: TDateTime): TDateTime;
// Workbook Globals records
// procedure ReadCodepage in xlscommon
@ -1472,6 +1472,7 @@ begin
INT_EXCEL_ID_FONT: ReadFont(AStream);
INT_EXCEL_ID_XF: ReadXF(AStream);
INT_EXCEL_ID_FORMAT: ReadFormat(AStream);
INT_EXCEL_ID_DATEMODE: ReadDateMode(AStream);
else
// nothing
end;
@ -1557,6 +1558,7 @@ var
ARow, ACol, XF: WORD;
Number: Double;
lFormatData: TFormatRecordData;
lDateTime: TDateTime;
begin
ReadRowColXF(AStream,ARow,ACol,XF);
@ -1570,14 +1572,17 @@ begin
// See: http://www.gaia-gis.it/FreeXL/freexl-1.0.0a-doxy-doc/Format.html
// Unfornately Excel doesnt give us a direct way to find this,
// we need to guess by the FORMAT field
{ lFormatData := FindFormatRecordForCell(XF);
lFormatData := FindFormatRecordForCell(XF);
if lFormatData <> nil then
begin
// Dates have /
if Pos('/', lFormatData.FormatString) > 0 then
begin
lDateTime := ConvertExcelDateToTDateTime(Number, FBaseDate);
FWorksheet.WriteDateTime(ARow,ACol,lDateTime);
Exit;
end;
end;
end;}
FWorksheet.WriteNumber(ARow,ACol,Number);
end;
@ -1963,9 +1968,9 @@ begin
end;
class function TsSpreadBIFF8Reader.ConvertExcelDateToTDateTime(
const AExcelDateNum: Integer): TDateTime;
const AExcelDateNum: Double; ABaseDate: TDateTime): TDateTime;
begin
Result := IncDay(ABaseDate, Round(AExcelDateNum));
end;
procedure TsSpreadBIFF8Reader.ReadFont(const AStream: TStream);

View File

@ -7,13 +7,14 @@ unit xlscommon;
interface
uses
Classes, SysUtils,
Classes, SysUtils, DateUtils,
fpspreadsheet,
fpsutils, lconvencoding;
const
{ RECORD IDs which didn't change across versions 2-8 }
INT_EXCEL_ID_CODEPAGE = $0042;
INT_EXCEL_ID_DATEMODE = $0022;
{ Formula constants TokenID values }
@ -104,9 +105,12 @@ type
TsSpreadBIFFReader = class(TsCustomSpreadReader)
protected
FCodepage: string;
FBaseDate: TDateTime;
constructor Create; override;
// Here we can add reading of records which didn't change across BIFF2-8 versions
// Workbook Globals records
procedure ReadCodePage(AStream: TStream);
procedure ReadDateMode(AStream: TStream);
end;
{ TsSpreadBIFFWriter }
@ -130,6 +134,14 @@ implementation
{ TsSpreadBIFFReader }
constructor TsSpreadBIFFReader.Create;
begin
inherited Create;
// Initial base date in case it wont be informed
FBaseDate := DateUtils.EncodeDateDay(1900, 1);
FBaseDate := DateUtils.IncDay(FBaseDate, -1);
end;
// In BIFF 8 it seams to always use the UTF-16 codepage
procedure TsSpreadBIFFReader.ReadCodePage(AStream: TStream);
var
@ -181,6 +193,30 @@ begin
end;
end;
procedure TsSpreadBIFFReader.ReadDateMode(AStream: TStream);
var
lBaseMode: Word;
begin
//5.28 DATEMODE
//BIFF2 BIFF3 BIFF4 BIFF5 BIFF8
//0022H 0022H 0022H 0022H 0022H
//This record specifies the base date for displaying date values. All dates are stored as count of days past this base date. In
//BIFF2-BIFF4 this record is part of the Calculation Settings Block (➜4.3). In BIFF5-BIFF8 it is stored in the Workbook
//Globals Substream.
//Record DATEMODE, BIFF2-BIFF8:
//Offset Size Contents
//0 2 0 = Base date is 1899-Dec-31 (the cell value 1 represents 1900-Jan-01)
// 1 = Base date is 1904-Jan-01 (the cell value 1 represents 1904-Jan-02)
lBaseMode := WordLEtoN(AStream.ReadWord);
if lBaseMode = 0 then
begin
FBaseDate := DateUtils.EncodeDateDay(1900, 1);
FBaseDate := DateUtils.IncDay(FBaseDate, -1);
end
else
FBaseDate := DateUtils.EncodeDateDay(1904, 1);
end;
function TsSpreadBIFFWriter.FPSColorToEXCELPallete(AColor: TsColor): Word;
begin
case AColor of