diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas index 4e7990068..0380e188e 100755 --- a/components/fpspreadsheet/fpspreadsheet.pas +++ b/components/fpspreadsheet/fpspreadsheet.pas @@ -230,6 +230,7 @@ type function CreateSpreadWriter(AFormat: TsSpreadsheetFormat): TsCustomSpreadWriter; procedure ReadFromFile(AFileName: string; AFormat: TsSpreadsheetFormat); overload; procedure ReadFromFile(AFileName: string); overload; + procedure ReadFromFileIgnoringExtension(AFileName: string); procedure ReadFromStream(AStream: TStream; AFormat: TsSpreadsheetFormat); procedure WriteToFile(const AFileName: string; const AFormat: TsSpreadsheetFormat; @@ -903,6 +904,25 @@ begin end; end; +procedure TsWorkbook.ReadFromFileIgnoringExtension(AFileName: string); +var + SheetType: TsSpreadsheetFormat; + lException: Exception; +begin + while (SheetType in [sfExcel2..sfExcel8]) and (lException <> nil) do + begin + try + Dec(SheetType); + ReadFromFile(AFileName, SheetType); + lException := nil; + except + on E: Exception do + { do nothing } ; + end; + if lException = nil then Break; + end; +end; + {@@ Reads the document from a seekable stream. } diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas index 7a13957a1..b59fee4d9 100755 --- a/components/fpspreadsheet/xlsbiff5.pas +++ b/components/fpspreadsheet/xlsbiff5.pas @@ -75,7 +75,7 @@ type { TsSpreadBIFF5Reader } - TsSpreadBIFF5Reader = class(TsCustomSpreadReader) + TsSpreadBIFF5Reader = class(TsSpreadBIFFReader) private RecordSize: Word; FWorksheet: TsWorksheet; @@ -117,7 +117,7 @@ type { Record writing methods } procedure WriteBOF(AStream: TStream; ADataType: Word); function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64; - procedure WriteCodepage(AStream: TStream; AEncoding: TsEncoding); + //procedure WriteCodepage(AStream: TStream; AEncoding: TsEncoding); this is in xlscommon procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet); procedure WriteEOF(AStream: TStream); procedure WriteFont(AStream: TStream; AFont: TFPCustomFont); @@ -151,7 +151,7 @@ const INT_EXCEL_ID_RSTRING = $00D6; INT_EXCEL_ID_RK = $027E; INT_EXCEL_ID_MULRK = $00BD; - INT_EXCEL_ID_CODEPAGE = $0042; + INT_EXCEL_ID_CODEPAGE = xlscommon.INT_EXCEL_ID_CODEPAGE; { Cell Addresses constants } MASK_EXCEL_ROW = $3FFF; @@ -169,21 +169,6 @@ const INT_BOF_BUILD_ID = $1FD2; INT_BOF_BUILD_YEAR = $07CD; - { CODEPAGE record constants } - - WORD_ASCII = 367; - WORD_UTF_16 = 1200; // BIFF 8 - WORD_CP_1250_Latin2 = 1250; - WORD_CP_1251_Cyrillic = 1251; - WORD_CP_1252_Latin1 = 1252; // BIFF4-BIFF5 - WORD_CP_1253_Greek = 1253; - WORD_CP_1254_Turkish = 1254; - WORD_CP_1255_Hebrew = 1255; - WORD_CP_1256_Arabic = 1256; - WORD_CP_1257_Baltic = 1257; - WORD_CP_1258_Vietnamese = 1258; - WORD_CP_1258_Latin1_BIFF2_3 = 32769; // BIFF2-BIFF3 - { FONT record constants } INT_FONT_WEIGHT_NORMAL = $0190; @@ -531,29 +516,6 @@ begin AStream.WriteBuffer(LatinSheetName[1], Len); end; -procedure TsSpreadBIFF5Writer.WriteCodepage(AStream: TStream; AEncoding: TsEncoding); -var - lCodepage: Word; -begin - { BIFF Record header } - AStream.WriteWord(WordToLE(INT_EXCEL_ID_CODEPAGE)); - AStream.WriteWord(WordToLE(2)); - - { Codepage } - case AEncoding of - seLatin2: lCodepage := WORD_CP_1250_Latin2; - seCyrillic: lCodepage := WORD_CP_1251_Cyrillic; - seGreek: lCodepage := WORD_CP_1253_Greek; - seTurkish: lCodepage := WORD_CP_1254_Turkish; - seHebrew: lCodepage := WORD_CP_1255_Hebrew; - seArabic: lCodepage := WORD_CP_1256_Arabic; - else - // Default is Latin1 - lCodepage := WORD_CP_1252_Latin1; - end; - AStream.WriteWord(WordToLE(lCodepage)); -end; - { Writes an Excel 5 DIMENSIONS record diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas index 408fb44e4..247abc6c4 100755 --- a/components/fpspreadsheet/xlsbiff8.pas +++ b/components/fpspreadsheet/xlsbiff8.pas @@ -87,6 +87,9 @@ type procedure ReadRichString(const AStream: TStream); procedure ReadSST(const AStream: TStream); procedure ReadLabelSST(const AStream: TStream); + + // Workbook Globals records + // procedure ReadCodepage in xlscommon procedure ReadFont(const AStream: TStream); public { General reading methods } @@ -118,6 +121,7 @@ type { Record writing methods } procedure WriteBOF(AStream: TStream; ADataType: Word); function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64; + // procedure WriteCodepage in xlscommon procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet); procedure WriteEOF(AStream: TStream); procedure WriteFont(AStream: TStream; AFont: TFPCustomFont); @@ -1378,7 +1382,7 @@ begin end; Result:=WideStringLEToN(Result); end else begin - //String is 1 byte per char, this is UTF-16 with the high word ommited because it is zero + //String is 1 byte per char, this is UTF-16 with the high byte ommited because it is zero // so decompress and then convert if ALength > PendingRecordSize then lLen := PendingRecordSize else lLen := ALength; diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas index d7486d72a..561667f03 100644 --- a/components/fpspreadsheet/xlscommon.pas +++ b/components/fpspreadsheet/xlscommon.pas @@ -12,6 +12,9 @@ uses fpsutils, lconvencoding; const + { RECORD IDs which didn't change across versions 2-8 } + INT_EXCEL_ID_CODEPAGE = $0042; + { Formula constants TokenID values } { Binary Operator Tokens } @@ -79,6 +82,21 @@ const EXTRA_COLOR_PALETTE_GREY10PCT = $18; // E6E6E6H EXTRA_COLOR_PALETTE_GREY20PCT = $19; // E6E6E6H + { CODEPAGE record constants } + + WORD_ASCII = 367; + WORD_UTF_16 = 1200; // BIFF 8 + WORD_CP_1250_Latin2 = 1250; + WORD_CP_1251_Cyrillic = 1251; + WORD_CP_1252_Latin1 = 1252; // BIFF4-BIFF5 + WORD_CP_1253_Greek = 1253; + WORD_CP_1254_Turkish = 1254; + WORD_CP_1255_Hebrew = 1255; + WORD_CP_1256_Arabic = 1256; + WORD_CP_1257_Baltic = 1257; + WORD_CP_1258_Vietnamese = 1258; + WORD_CP_1258_Latin1_BIFF2_3 = 32769; // BIFF2-BIFF3 + type { TsSpreadBIFFReader } @@ -86,6 +104,8 @@ type TsSpreadBIFFReader = class(TsCustomSpreadReader) protected FCodepage: string; + // Here we can add reading of records which didn't change across BIFF2-8 versions + // Workbook Globals records procedure ReadCodePage(AStream: TStream); end; @@ -101,12 +121,16 @@ type procedure GetLastColCallback(ACell: PCell; AStream: TStream); function GetLastColIndex(AWorksheet: TsWorksheet): Word; function FormulaElementKindToExcelTokenID(AElementKind: TFEKind): Byte; + // Other records which didn't change + // Workbook Globals records + procedure WriteCodepage(AStream: TStream; AEncoding: TsEncoding); end; implementation { TsSpreadBIFFReader } +// In BIFF 8 it seams to always use the UTF-16 codepage procedure TsSpreadBIFFReader.ReadCodePage(AStream: TStream); var lCodePage: Word; @@ -229,5 +253,29 @@ begin end; end; +procedure TsSpreadBIFFWriter.WriteCodepage(AStream: TStream; + AEncoding: TsEncoding); +var + lCodepage: Word; +begin + { BIFF Record header } + AStream.WriteWord(WordToLE(INT_EXCEL_ID_CODEPAGE)); + AStream.WriteWord(WordToLE(2)); + + { Codepage } + case AEncoding of + seLatin2: lCodepage := WORD_CP_1250_Latin2; + seCyrillic: lCodepage := WORD_CP_1251_Cyrillic; + seGreek: lCodepage := WORD_CP_1253_Greek; + seTurkish: lCodepage := WORD_CP_1254_Turkish; + seHebrew: lCodepage := WORD_CP_1255_Hebrew; + seArabic: lCodepage := WORD_CP_1256_Arabic; + else + // Default is Latin1 + lCodepage := WORD_CP_1252_Latin1; + end; + AStream.WriteWord(WordToLE(lCodepage)); +end; + end.