You've already forked lazarus-ccr
fpspreadsheet: Improve codepage handling for biff2 and biff2 files.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3924 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -321,7 +321,7 @@ begin
|
||||
7: WorkbookSource.FileFormat := sfOpenDocument; // Open/LibreOffice
|
||||
8: WorkbookSource.FileFormat := sfCSV; // Text files
|
||||
end;
|
||||
WorkbookSource.FileName := AcFileOpen.Dialog.FileName; // this loads the file
|
||||
WorkbookSource.FileName := UTF8ToAnsi(AcFileOpen.Dialog.FileName); // this loads the file
|
||||
UpdateCaption;
|
||||
end;
|
||||
|
||||
@ -341,7 +341,7 @@ begin
|
||||
6: fmt := sfCSV;
|
||||
7: fmt := sfWikiTable_WikiMedia;
|
||||
end;
|
||||
WorkbookSource.SaveToSpreadsheetFile(AcFileSaveAs.Dialog.FileName, fmt);
|
||||
WorkbookSource.SaveToSpreadsheetFile(UTF8ToAnsi(AcFileSaveAs.Dialog.FileName), fmt);
|
||||
UpdateCaption;
|
||||
finally
|
||||
Screen.Cursor := crDefault;
|
||||
@ -401,7 +401,7 @@ begin
|
||||
Caption := 'demo_ctrls'
|
||||
else
|
||||
Caption := Format('demo_ctrls - "%s" [%s]', [
|
||||
WorkbookSource.Filename,
|
||||
AnsiToUTF8(WorkbookSource.Filename),
|
||||
GetFileFormatName(WorkbookSource.Workbook.FileFormat)
|
||||
]);
|
||||
end;
|
||||
|
@ -120,6 +120,8 @@ implementation
|
||||
{ TForm1 }
|
||||
|
||||
procedure TForm1.BtnLoadClick(Sender: TObject);
|
||||
var
|
||||
fn: ansistring;
|
||||
begin
|
||||
if OpenDialog.Execute then begin
|
||||
WorkbookSource.AutodetectFormat := false;
|
||||
@ -136,16 +138,17 @@ begin
|
||||
end;
|
||||
|
||||
// There are 3 possibilities to open a file:
|
||||
fn := UTF8ToAnsi(OpenDialog.Filename);
|
||||
case CbLoader.ItemIndex of
|
||||
0: if WorkbookSource.AutodetectFormat then
|
||||
WorkbookSource.Workbook.ReadFromFile(OpenDialog.FileName)
|
||||
WorkbookSource.Workbook.ReadFromFile(fn)
|
||||
else
|
||||
WorkbookSource.Workbook.ReadFromFile(OpenDialog.Filename, WorkbookSource.FileFormat);
|
||||
1: WorkbookSource.FileName := OpenDialog.FileName; // this loads the file
|
||||
WorkbookSource.Workbook.ReadFromFile(fn, WorkbookSource.FileFormat);
|
||||
1: WorkbookSource.FileName := fn; // this loads the file
|
||||
2: if WorkbookSource.AutodetectFormat then
|
||||
WorksheetGrid.LoadFromSpreadsheetFile(OpenDialog.FileName)
|
||||
WorksheetGrid.LoadFromSpreadsheetFile(fn)
|
||||
else
|
||||
WorksheetGrid.LoadFromSpreadsheetFile(OpenDialog.FileName, WorkbookSource.FileFormat);
|
||||
WorksheetGrid.LoadFromSpreadsheetFile(fn, WorkbookSource.FileFormat);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
@ -115,21 +115,22 @@ end;
|
||||
// Saves sheet in grid to file, overwriting existing file
|
||||
procedure TForm1.BtnSaveClick(Sender: TObject);
|
||||
var
|
||||
err: String;
|
||||
err, fn: String;
|
||||
begin
|
||||
if WorksheetGrid.Workbook = nil then
|
||||
exit;
|
||||
|
||||
if WorksheetGrid.Workbook.Filename <>'' then begin
|
||||
SaveDialog.InitialDir := ExtractFileDir(WorksheetGrid.Workbook.FileName);
|
||||
SaveDialog.FileName := ChangeFileExt(ExtractFileName(WorksheetGrid.Workbook.FileName), '');
|
||||
fn := AnsiToUTF8(WorksheetGrid.Workbook.Filename);
|
||||
SaveDialog.InitialDir := ExtractFileDir(fn);
|
||||
SaveDialog.FileName := ChangeFileExt(ExtractFileName(fn), '');
|
||||
end;
|
||||
|
||||
if SaveDialog.Execute then
|
||||
begin
|
||||
Screen.Cursor := crHourglass;
|
||||
try
|
||||
WorksheetGrid.SaveToSpreadsheetFile(SaveDialog.FileName);
|
||||
WorksheetGrid.SaveToSpreadsheetFile(UTF8ToAnsi(SaveDialog.FileName));
|
||||
finally
|
||||
Screen.Cursor := crDefault;
|
||||
// Show a message in case of error(s)
|
||||
|
@ -7,7 +7,7 @@ uses
|
||||
cthreads,
|
||||
{$ENDIF}{$ENDIF}
|
||||
Interfaces, // this includes the LCL widgetset
|
||||
Forms, mainfrm, fpsHelpers
|
||||
Forms, mainfrm, fpsCell
|
||||
{ you can add units after this };
|
||||
|
||||
{$R *.res}
|
||||
|
@ -92,21 +92,23 @@ end;
|
||||
procedure TForm1.BtnSaveClick(Sender: TObject);
|
||||
var
|
||||
err: String;
|
||||
fn: String;
|
||||
begin
|
||||
if Grid.Workbook = nil then
|
||||
exit;
|
||||
|
||||
if Grid.Workbook.Filename <>'' then
|
||||
begin
|
||||
SaveDialog.InitialDir := ExtractFileDir(Grid.Workbook.FileName);
|
||||
SaveDialog.FileName := ChangeFileExt(ExtractFileName(Grid.Workbook.FileName), '');
|
||||
fn := AnsiToUtf8(Grid.Workbook.Filename);
|
||||
SaveDialog.InitialDir := ExtractFileDir(fn);
|
||||
SaveDialog.FileName := ChangeFileExt(ExtractFileName(fn), '');
|
||||
end;
|
||||
|
||||
if SaveDialog.Execute then
|
||||
begin
|
||||
Screen.Cursor := crHourglass;
|
||||
try
|
||||
Grid.SaveToSpreadsheetFile(SaveDialog.FileName);
|
||||
Grid.SaveToSpreadsheetFile(UTF8ToAnsi(SaveDialog.FileName));
|
||||
finally
|
||||
Screen.Cursor := crDefault;
|
||||
// Show a message in case of error(s)
|
||||
|
@ -498,7 +498,7 @@ object MainFrm: TMainFrm
|
||||
BorderStyle = bsNone
|
||||
ColCount = 27
|
||||
MouseWheelOption = mwGrid
|
||||
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goRowSizing, goColSizing, goThumbTracking, goDblClickAutoSize, goHeaderHotTracking, goHeaderPushedLook, goFixedColSizing]
|
||||
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goRowSizing, goColSizing, goThumbTracking, goDblClickAutoSize, goHeaderHotTracking, goHeaderPushedLook, goFixedColSizing, goCellHints]
|
||||
RowCount = 101
|
||||
TabOrder = 1
|
||||
TitleStyle = tsNative
|
||||
|
@ -324,6 +324,7 @@ type
|
||||
procedure WorksheetGridHeaderClick(Sender: TObject; IsColumn: Boolean;
|
||||
Index: Integer);
|
||||
procedure WorksheetGridSelection(Sender: TObject; aCol, aRow: Integer);
|
||||
|
||||
private
|
||||
FCopiedFormat: TCell;
|
||||
procedure LoadFile(const AFileName: String);
|
||||
@ -759,7 +760,7 @@ begin
|
||||
7: fmt := sfWikiTable_wikimedia;
|
||||
end;
|
||||
try
|
||||
WorksheetGrid.SaveToSpreadsheetFile(SaveDialog.FileName, fmt);
|
||||
WorksheetGrid.SaveToSpreadsheetFile(Utf8ToAnsi(SaveDialog.FileName), fmt);
|
||||
finally
|
||||
Screen.Cursor := crDefault;
|
||||
err := WorksheetGrid.Workbook.ErrorMsg;
|
||||
@ -1006,7 +1007,7 @@ begin
|
||||
end;
|
||||
|
||||
procedure TMainFrm.LoadFile(const AFileName: String);
|
||||
// Loads first worksheet from file into grid
|
||||
// Loads first worksheet from file into grid. File name is UTF8.
|
||||
var
|
||||
err: String;
|
||||
begin
|
||||
@ -1014,7 +1015,7 @@ begin
|
||||
Screen.Cursor := crHourglass;
|
||||
try
|
||||
try
|
||||
WorksheetGrid.LoadFromSpreadsheetFile(UTF8ToSys(AFileName));
|
||||
WorksheetGrid.LoadFromSpreadsheetFile(utf8ToAnsi(AFileName));
|
||||
except
|
||||
on E: Exception do begin
|
||||
// In an error occurs show at least an empty valid worksheet
|
||||
|
@ -1248,9 +1248,9 @@ procedure TsCellCommentAction.ExecuteTarget(Target: TObject);
|
||||
var
|
||||
txt: String;
|
||||
cellStr: String;
|
||||
x, y: Integer;
|
||||
R: TRect;
|
||||
begin
|
||||
Unused(Target);
|
||||
|
||||
if Worksheet = nil then
|
||||
exit;
|
||||
|
||||
@ -1275,6 +1275,8 @@ end;
|
||||
|
||||
procedure TsCellCommentAction.UpdateTarget(Target: TObject);
|
||||
begin
|
||||
Unused(Target);
|
||||
|
||||
case FMode of
|
||||
ccmNew : Enabled := (Worksheet <> nil) and (Length(GetSelection) > 0);
|
||||
ccmEdit,
|
||||
|
@ -65,7 +65,7 @@ type
|
||||
LineEnding: TsCSVLineEnding; // W: Specification for line ending to be written
|
||||
Delimiter: Char; // RW: Column delimiter
|
||||
QuoteChar: Char; // RW: Character for quoting texts
|
||||
Encoding: String; // RW: Encoding of file
|
||||
Encoding: String; // RW: Encoding of file (code page, such as "utf8", "cp1252" etc)
|
||||
DetectContentType: Boolean; // R: try to convert strings to content types
|
||||
NumberFormat: String; // W: if empty write numbers like in sheet, otherwise use this format
|
||||
AutoDetectNumberFormat: Boolean; // R: automatically detects decimal/thousand separator used in numbers
|
||||
@ -202,8 +202,6 @@ end;
|
||||
constructor TsCSVReader.Create(AWorkbook: TsWorkbook);
|
||||
begin
|
||||
inherited Create(AWorkbook);
|
||||
FFormatSettings := CSVParams.FormatSettings;
|
||||
ReplaceFormatSettings(FFormatSettings, AWorkbook.FormatSettings);
|
||||
FWorksheetName := 'Sheet1'; // will be replaced by filename
|
||||
end;
|
||||
|
||||
@ -455,6 +453,9 @@ begin
|
||||
FWorkbook := AData;
|
||||
FWorksheet := AData.AddWorksheet(FWorksheetName, true);
|
||||
|
||||
FFormatSettings := CSVParams.FormatSettings;
|
||||
ReplaceFormatSettings(FFormatSettings, FWorkbook.FormatSettings);
|
||||
|
||||
// Create csv parser, read file and store in worksheet
|
||||
Parser := TCSVParser.Create;
|
||||
try
|
||||
|
@ -59,9 +59,9 @@ type
|
||||
MergeBase: PCell; // Upper left cell of a merged range
|
||||
Comment: String; // Comment attached to the cell
|
||||
{ Cell content }
|
||||
UTF8StringValue: String; // strings cannot be part of a variant record
|
||||
UTF8StringValue: String; // Strings cannot be part of a variant record
|
||||
FormulaValue: String;
|
||||
case ContentType: TCellContentType of // must be at the end of the declaration
|
||||
case ContentType: TCellContentType of // variant part must be at the end
|
||||
cctEmpty : (); // has no data at all
|
||||
cctFormula : (); // FormulaValue is outside the variant record
|
||||
cctNumber : (Numbervalue: Double);
|
||||
@ -187,9 +187,9 @@ type
|
||||
procedure UpdateCaches;
|
||||
|
||||
{ Reading of values }
|
||||
function ReadAsUTF8Text(ARow, ACol: Cardinal): ansistring; overload;
|
||||
function ReadAsUTF8Text(ACell: PCell): ansistring; overload;
|
||||
function ReadAsUTF8Text(ACell: PCell; AFormatSettings: TFormatSettings): ansistring; overload;
|
||||
function ReadAsUTF8Text(ARow, ACol: Cardinal): string; overload; //ansistring; overload;
|
||||
function ReadAsUTF8Text(ACell: PCell): string; overload; //ansistring; overload;
|
||||
function ReadAsUTF8Text(ACell: PCell; AFormatSettings: TFormatSettings): string; overload; //ansistring; overload;
|
||||
function ReadAsNumber(ARow, ACol: Cardinal): Double; overload;
|
||||
function ReadAsNumber(ACell: PCell): Double; overload;
|
||||
function ReadAsDateTime(ARow, ACol: Cardinal; out AResult: TDateTime): Boolean; overload;
|
||||
@ -555,7 +555,8 @@ type
|
||||
private
|
||||
{ Internal data }
|
||||
FWorksheets: TFPList;
|
||||
FEncoding: TsEncoding;
|
||||
FCodePage: String;
|
||||
// FEncoding: TsEncoding;
|
||||
FFormat: TsSpreadsheetFormat;
|
||||
FBuiltinFontCount: Integer;
|
||||
FPalette: array of TsColorValue;
|
||||
@ -694,7 +695,8 @@ type
|
||||
property ActiveWorksheet: TsWorksheet read FActiveWorksheet;
|
||||
{@@ This property is only used for formats which don't support unicode
|
||||
and support a single encoding for the whole document, like Excel 2 to 5 }
|
||||
property Encoding: TsEncoding read FEncoding write FEncoding;
|
||||
property CodePage: String read FCodePage write FCodepage;
|
||||
// property Encoding: TsEncoding read FEncoding write FEncoding;
|
||||
{@@ Retrieves error messages collected during reading/writing }
|
||||
property ErrorMsg: String read GetErrorMsg;
|
||||
{@@ Filename of the saved workbook }
|
||||
@ -2446,13 +2448,13 @@ end;
|
||||
Reads the contents of a cell and returns an user readable text
|
||||
representing the contents of the cell.
|
||||
|
||||
The resulting ansistring is UTF-8 encoded.
|
||||
The resulting string is UTF-8 encoded.
|
||||
|
||||
@param ARow The row of the cell
|
||||
@param ACol The column of the cell
|
||||
@return The text representation of the cell
|
||||
-------------------------------------------------------------------------------}
|
||||
function TsWorksheet.ReadAsUTF8Text(ARow, ACol: Cardinal): ansistring;
|
||||
function TsWorksheet.ReadAsUTF8Text(ARow, ACol: Cardinal): string; //ansistring;
|
||||
begin
|
||||
Result := ReadAsUTF8Text(GetCell(ARow, ACol));
|
||||
end;
|
||||
@ -2461,21 +2463,21 @@ end;
|
||||
Reads the contents of a cell and returns an user readable text
|
||||
representing the contents of the cell.
|
||||
|
||||
The resulting ansistring is UTF-8 encoded.
|
||||
The resulting string is UTF-8 encoded.
|
||||
|
||||
@param ACell Pointer to the cell
|
||||
@return The text representation of the cell
|
||||
-------------------------------------------------------------------------------}
|
||||
function TsWorksheet.ReadAsUTF8Text(ACell: PCell): ansistring;
|
||||
function TsWorksheet.ReadAsUTF8Text(ACell: PCell): string; //ansistring;
|
||||
begin
|
||||
Result := ReadAsUTF8Text(ACell, FWorkbook.FormatSettings);
|
||||
end;
|
||||
|
||||
function TsWorksheet.ReadAsUTF8Text(ACell: PCell;
|
||||
AFormatSettings: TFormatSettings): ansistring;
|
||||
AFormatSettings: TFormatSettings): string; //ansistring;
|
||||
|
||||
function FloatToStrNoNaN(const AValue: Double;
|
||||
ANumberFormat: TsNumberFormat; ANumberFormatStr: string): ansistring;
|
||||
ANumberFormat: TsNumberFormat; ANumberFormatStr: string): string; //ansistring;
|
||||
begin
|
||||
if IsNan(AValue) then
|
||||
Result := ''
|
||||
@ -2493,7 +2495,7 @@ function TsWorksheet.ReadAsUTF8Text(ACell: PCell;
|
||||
end;
|
||||
|
||||
function DateTimeToStrNoNaN(const Value: Double;
|
||||
ANumberFormat: TsNumberFormat; ANumberFormatStr: String): ansistring;
|
||||
ANumberFormat: TsNumberFormat; ANumberFormatStr: String): string; //ansistring;
|
||||
var
|
||||
fmtp, fmtn, fmt0: String;
|
||||
begin
|
||||
@ -6424,11 +6426,14 @@ end;
|
||||
constructor TsWorkbook.Create;
|
||||
var
|
||||
fmt: TsCellFormat;
|
||||
cp: String;
|
||||
begin
|
||||
inherited Create;
|
||||
FWorksheets := TFPList.Create;
|
||||
FLog := TStringList.Create;
|
||||
FFormat := sfExcel8;
|
||||
FCodePage := GetDefaultTextEncoding;
|
||||
// FEncoding := seLatin1;
|
||||
|
||||
FormatSettings := UTF8FormatSettings;
|
||||
FormatSettings.ShortDateFormat := MakeShortDateFormat(FormatSettings.ShortDateFormat);
|
||||
@ -8736,6 +8741,7 @@ end;
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsCustomSpreadWriter.WriteComment(AStream: TStream; ACell: PCell);
|
||||
begin
|
||||
Unused(AStream, ACell);
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
|
@ -1845,7 +1845,6 @@ var
|
||||
lCell: PCell;
|
||||
justif: Byte;
|
||||
fmt: PsCellFormat;
|
||||
savedBrushColor: TColor;
|
||||
begin
|
||||
if (Worksheet = nil) then
|
||||
exit;
|
||||
|
@ -10,7 +10,7 @@
|
||||
unit fpsRPN;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}{$H+}
|
||||
{$mode objfpc}{$H+}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
@ -436,6 +436,7 @@ begin
|
||||
while item <> nil do begin
|
||||
nextitem := item^.Next;
|
||||
Result[n] := item^.FE;
|
||||
Result[n].StringValue := item^.FE.StringValue;
|
||||
if AReverse then dec(n) else inc(n);
|
||||
DisposeRPNItem(item);
|
||||
item := nextitem;
|
||||
|
@ -52,6 +52,7 @@ resourcestring
|
||||
'text found in cell %s.';
|
||||
rsIndexInSSTOutOfRange = 'Index %d in SST out of range (0-%d).';
|
||||
rsAmbiguousDecThouSeparator = 'Assuming usage of decimal separator in "%s".';
|
||||
rsCodePageNotSupported = 'Code page "%s" is not supported. Using "cp1252" (Latin 1) instead.';
|
||||
|
||||
|
||||
rsTRUE = 'TRUE'; // wp: Do we really want to translate these strings?
|
||||
|
@ -48,7 +48,7 @@ const
|
||||
|
||||
|
||||
type
|
||||
|
||||
(*
|
||||
{@@ Possible encodings for a non-unicode encoded text }
|
||||
TsEncoding = (
|
||||
seLatin1,
|
||||
@ -57,8 +57,9 @@ type
|
||||
seGreek,
|
||||
seTurkish,
|
||||
seHebrew,
|
||||
seArabic
|
||||
);
|
||||
seArabic,
|
||||
seUTF16
|
||||
); *)
|
||||
|
||||
{@@ Tokens to identify the <b>elements in an expanded formula</b>.
|
||||
|
||||
@ -110,7 +111,7 @@ type
|
||||
ElementKind: TFEKind;
|
||||
Row, Row2: Cardinal; // zero-based
|
||||
Col, Col2: Cardinal; // zero-based
|
||||
Param1, Param2: Word; // Extra parameters
|
||||
// Param1, Param2: Word; // Extra parameters
|
||||
DoubleValue: double;
|
||||
IntValue: Word;
|
||||
StringValue: String;
|
||||
@ -228,7 +229,7 @@ type
|
||||
|
||||
Due to limitations of the text mode the characters are not rotated here.
|
||||
There is, however, also a "stacked" variant which looks exactly like
|
||||
the former case.
|
||||
the 90-degrees-clockwise case.
|
||||
}
|
||||
TsTextRotation = (trHorizontal, rt90DegreeClockwiseRotation,
|
||||
rt90DegreeCounterClockwiseRotation, rtStacked);
|
||||
|
@ -228,7 +228,7 @@ begin
|
||||
SetLength(sa, ls);
|
||||
ANumbytes := ls*SizeOf(AnsiChar) + ALenBytes + 1;
|
||||
Move(FBuffer[ABufIndex + ALenBytes + 1], sa[1], ls*SizeOf(AnsiChar));
|
||||
AString := sa;
|
||||
AString := AnsiToUTF8(sa);
|
||||
end else begin
|
||||
SetLength(sw, ls);
|
||||
ANumBytes := ls*SizeOf(WideChar) + ALenBytes + 1;
|
||||
|
@ -381,7 +381,9 @@ var
|
||||
ActualDateTime: TDateTime;
|
||||
Row: Cardinal;
|
||||
TempFile: string; //write xls/xml to this file and read back from it
|
||||
ErrorMargin: TDateTime;
|
||||
begin
|
||||
ErrorMargin := 1.0/(24*60*60*1000*100); // 0.01 ms
|
||||
TempFile:=NewTempFile;
|
||||
{// Not needed: use workbook.writetofile with overwrite=true
|
||||
if fileexists(TempFile) then
|
||||
@ -397,7 +399,8 @@ begin
|
||||
// Some checks inside worksheet itself
|
||||
if not(MyWorkSheet.ReadAsDateTime(Row,0,ActualDateTime)) then
|
||||
Fail('Failed writing date time for cell '+CellNotation(MyWorkSheet,Row));
|
||||
CheckEquals(SollDates[Row],ActualDateTime,'Test date/time value mismatch cell '+CellNotation(MyWorksheet,Row));
|
||||
CheckEquals(SollDates[Row], ActualDateTime,
|
||||
'Test date/time value mismatch cell '+CellNotation(MyWorksheet,Row));
|
||||
end;
|
||||
MyWorkBook.WriteToFile(TempFile, AFormat, true);
|
||||
finally
|
||||
@ -420,7 +423,8 @@ begin
|
||||
begin
|
||||
if not(MyWorkSheet.ReadAsDateTime(Row,0,ActualDateTime)) then
|
||||
Fail('Could not read date time for cell '+CellNotation(MyWorkSheet,Row));
|
||||
CheckEquals(SollDates[Row],ActualDateTime,'Test date/time value mismatch cell '+CellNotation(MyWorkSheet,Row));
|
||||
CheckEquals(SollDates[Row], ActualDateTime, ErrorMargin,
|
||||
'Test date/time value mismatch cell '+CellNotation(MyWorkSheet,Row));
|
||||
end;
|
||||
finally
|
||||
MyWorkbook.Free;
|
||||
|
@ -48,6 +48,7 @@
|
||||
<Unit1>
|
||||
<Filename Value="datetests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="datetests"/>
|
||||
</Unit1>
|
||||
<Unit2>
|
||||
<Filename Value="stringtests.pas"/>
|
||||
@ -60,7 +61,6 @@
|
||||
<Unit4>
|
||||
<Filename Value="manualtests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="manualtests"/>
|
||||
</Unit4>
|
||||
<Unit5>
|
||||
<Filename Value="testsutility.pas"/>
|
||||
@ -69,21 +69,19 @@
|
||||
<Unit6>
|
||||
<Filename Value="internaltests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="internaltests"/>
|
||||
</Unit6>
|
||||
<Unit7>
|
||||
<Filename Value="formattests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="formattests"/>
|
||||
</Unit7>
|
||||
<Unit8>
|
||||
<Filename Value="colortests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="colortests"/>
|
||||
</Unit8>
|
||||
<Unit9>
|
||||
<Filename Value="fonttests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="fonttests"/>
|
||||
</Unit9>
|
||||
<Unit10>
|
||||
<Filename Value="optiontests.pas"/>
|
||||
@ -96,15 +94,16 @@
|
||||
<Unit12>
|
||||
<Filename Value="rpnformulaunit.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="rpnFormulaUnit"/>
|
||||
</Unit12>
|
||||
<Unit13>
|
||||
<Filename Value="formulatests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="formulatests"/>
|
||||
</Unit13>
|
||||
<Unit14>
|
||||
<Filename Value="emptycelltests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emptycelltests"/>
|
||||
</Unit14>
|
||||
<Unit15>
|
||||
<Filename Value="errortests.pas"/>
|
||||
@ -121,7 +120,6 @@
|
||||
<Unit18>
|
||||
<Filename Value="celltypetests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="celltypetests"/>
|
||||
</Unit18>
|
||||
<Unit19>
|
||||
<Filename Value="sortingtests.pas"/>
|
||||
@ -130,7 +128,6 @@
|
||||
<Unit20>
|
||||
<Filename Value="copytests.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="copytests"/>
|
||||
</Unit20>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
|
@ -52,7 +52,7 @@
|
||||
{!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! DO NOT CHANGE THIS FORMULA - ITS RESULT (-9) IS HARD-CODED IN OTHER TESTS !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
|
||||
|
||||
(*
|
||||
// Add cell values - relative addresses
|
||||
inc(Row);
|
||||
formula := 'B1+B2';
|
||||
@ -3001,7 +3001,7 @@
|
||||
SetLength(sollValues, Row+1);
|
||||
sollValues[Row] := StringResult('Ha');
|
||||
Myworksheet.WriteUTF8Text(Row, 2, sollValues[Row].ResString);
|
||||
|
||||
*)
|
||||
// LEFT (2 parameters, utf8)
|
||||
inc(Row);
|
||||
formula := 'LEFT("Ändern",3)';
|
||||
|
@ -57,7 +57,7 @@ type
|
||||
|
||||
TsSpreadBIFF2Reader = class(TsSpreadBIFFReader)
|
||||
private
|
||||
WorkBookEncoding: TsEncoding;
|
||||
// WorkBookEncoding: TsEncoding;
|
||||
FFont: TsFont;
|
||||
protected
|
||||
procedure CreateNumFormatList; override;
|
||||
@ -110,6 +110,8 @@ type
|
||||
ACell: PCell); override;
|
||||
procedure WriteBool(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: Boolean; ACell: PCell); override;
|
||||
// procedure WriteCodePage(AStream: TStream; AEncoding: TsEncoding); override;
|
||||
procedure WriteCodePage(AStream: TStream; ACodePage: String); override;
|
||||
procedure WriteError(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: TsErrorValue; ACell: PCell); override;
|
||||
procedure WriteLabel(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
@ -512,7 +514,7 @@ begin
|
||||
FWorkbook.RemoveAllFonts;
|
||||
|
||||
{ Store some data about the workbook that other routines need }
|
||||
WorkBookEncoding := AData.Encoding;
|
||||
//WorkBookEncoding := AData.Encoding;
|
||||
|
||||
BIFF2EOF := False;
|
||||
|
||||
@ -531,6 +533,7 @@ begin
|
||||
case RecordType of
|
||||
INT_EXCEL_ID_BLANK : ReadBlank(AStream);
|
||||
INT_EXCEL_ID_BOOLERROR : ReadBool(AStream);
|
||||
INT_EXCEL_ID_CODEPAGE : ReadCodePage(AStream);
|
||||
INT_EXCEL_ID_NOTE : ReadComment(AStream);
|
||||
INT_EXCEL_ID_FONT : ReadFont(AStream);
|
||||
INT_EXCEL_ID_FONTCOLOR : ReadFontColor(AStream);
|
||||
@ -648,8 +651,8 @@ var
|
||||
L: Byte;
|
||||
ARow, ACol: Cardinal;
|
||||
XF: Word;
|
||||
AValue: ansistring;
|
||||
AStrValue: UTF8String;
|
||||
ansiStr: ansistring;
|
||||
valueStr: UTF8String;
|
||||
cell: PCell;
|
||||
begin
|
||||
{ Read entire record, starting at Row, except for string data }
|
||||
@ -661,10 +664,12 @@ begin
|
||||
|
||||
{ String with 8-bit size }
|
||||
L := rec.TextLen;
|
||||
SetLength(AValue, L);
|
||||
AStream.ReadBuffer(AValue[1], L);
|
||||
SetLength(ansiStr, L);
|
||||
AStream.ReadBuffer(ansiStr[1], L);
|
||||
|
||||
{ Save the data }
|
||||
valueStr := ConvertEncoding(ansiStr, FCodePage, encodingUTF8);
|
||||
{
|
||||
case WorkBookEncoding of
|
||||
seLatin2: AStrValue := CP1250ToUTF8(AValue);
|
||||
seCyrillic: AStrValue := CP1251ToUTF8(AValue);
|
||||
@ -676,6 +681,7 @@ begin
|
||||
// Latin 1 is the default
|
||||
AStrValue := CP1252ToUTF8(AValue);
|
||||
end;
|
||||
}
|
||||
|
||||
{ Create cell }
|
||||
if FIsVirtualMode then begin
|
||||
@ -683,7 +689,7 @@ begin
|
||||
cell := @FVirtualCell;
|
||||
end else
|
||||
cell := FWorksheet.GetCell(ARow, ACol);
|
||||
FWorksheet.WriteUTF8Text(cell, AStrValue);
|
||||
FWorksheet.WriteUTF8Text(cell, valueStr);
|
||||
|
||||
{ Apply formatting to cell }
|
||||
ApplyCellFormatting(cell, XF);
|
||||
@ -870,7 +876,8 @@ begin
|
||||
begin
|
||||
// The "IncompleteCell" has been identified in the sheet when reading
|
||||
// the FORMULA record which precedes the String record.
|
||||
FIncompleteCell^.UTF8StringValue := AnsiToUTF8(s);
|
||||
// FIncompleteCell^.UTF8StringValue := AnsiToUTF8(s);
|
||||
FIncompleteCell^.UTF8StringValue := ConvertEncoding(s, FCodePage, encodingUTF8);
|
||||
FIncompleteCell^.ContentType := cctUTF8String;
|
||||
if FIsVirtualMode then
|
||||
Workbook.OnReadCellData(Workbook, FIncompleteCell^.Row, FIncompleteCell^.Col, FIncompleteCell);
|
||||
@ -1141,6 +1148,32 @@ begin
|
||||
AStream.WriteBuffer(rec, SizeOf(rec));
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Writes an Excel 2 CODEPAGE record
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsSpreadBIFF2Writer.WriteCodePage(AStream: TStream; ACodePage: String);
|
||||
// AEncoding: TsEncoding);
|
||||
begin
|
||||
if ACodePage = 'cp1251' then begin
|
||||
AStream.WriteWord(WordToLE(INT_EXCEL_ID_CODEPAGE));
|
||||
AStream.WriteWord(WordToLE(2));
|
||||
AStream.WriteWord(WordToLE(WORD_CP_1258_Latin1_BIFF2_3));
|
||||
FCodePage := ACodePage;
|
||||
end else
|
||||
inherited;
|
||||
(*
|
||||
if AEncoding = seLatin1 then begin
|
||||
cp := WORD_CP_1258_Latin1_BIFF2_3;
|
||||
FCodePage := 'cp1252';
|
||||
|
||||
{ BIFF Record header }
|
||||
AStream.WriteWord(WordToLE(INT_EXCEL_ID_CODEPAGE));
|
||||
AStream.WriteWord(WordToLE(2));
|
||||
AStream.WriteWord(WordToLE(cp));
|
||||
end else
|
||||
inherited; *)
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Writes an Excel 2 COLWIDTH record
|
||||
-------------------------------------------------------------------------------}
|
||||
@ -1245,6 +1278,7 @@ begin
|
||||
|
||||
WriteBOF(AStream);
|
||||
WriteFonts(AStream);
|
||||
WriteCodePage(AStream, Workbook.CodePage); //Encoding);
|
||||
WriteFormatCount(AStream);
|
||||
WriteNumFormats(AStream);
|
||||
WriteXFRecords(AStream);
|
||||
@ -1531,7 +1565,7 @@ var
|
||||
begin
|
||||
Unused(ANumFormatData);
|
||||
|
||||
s := NumFormatList.FormatStringForWriting(AListIndex);
|
||||
s := ConvertEncoding(NumFormatList.FormatStringForWriting(AListIndex), encodingUTF8, FCodePage);
|
||||
len := Length(s);
|
||||
|
||||
{ BIFF record header }
|
||||
|
@ -34,19 +34,15 @@ EOF
|
||||
The row and column numbering in BIFF files is zero-based.
|
||||
|
||||
Excel file format specification obtained from:
|
||||
|
||||
http://sc.openoffice.org/excelfileformat.pdf
|
||||
http://sc.openoffice.org/excelfileformat.pdf
|
||||
|
||||
Records Needed to Make a BIFF5 File Microsoft Excel Can Use obtained from:
|
||||
|
||||
http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q147732&ID=KB;EN-US;Q147732&LN=EN-US&rnk=2&SD=msdn&FR=0&qry=BIFF&src=DHCS_MSPSS_msdn_SRCH&SPR=MSALL&
|
||||
http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q147732&ID=KB;EN-US;Q147732&LN=EN-US&rnk=2&SD=msdn&FR=0&qry=BIFF&src=DHCS_MSPSS_msdn_SRCH&SPR=MSALL&
|
||||
|
||||
Microsoft BIFF 5 writer example:
|
||||
http://support.microsoft.com/kb/150447/en-us
|
||||
|
||||
http://support.microsoft.com/kb/150447/en-us
|
||||
|
||||
Encoding information: ISO_8859_1 is used, to have support to
|
||||
other characters, please use a format which support unicode
|
||||
Encoding information: as specified fy the Encoding property of the workbook.
|
||||
|
||||
AUTHORS: Felipe Monteiro de Carvalho
|
||||
}
|
||||
@ -101,8 +97,6 @@ type
|
||||
{ TsSpreadBIFF5Writer }
|
||||
|
||||
TsSpreadBIFF5Writer = class(TsSpreadBIFFWriter)
|
||||
private
|
||||
WorkBookEncoding: TsEncoding;
|
||||
protected
|
||||
{ Record writing methods }
|
||||
procedure WriteBOF(AStream: TStream; ADataType: Word);
|
||||
@ -353,6 +347,7 @@ begin
|
||||
case RecordType of
|
||||
INT_EXCEL_ID_BOF : ;
|
||||
INT_EXCEL_ID_BOUNDSHEET : ReadBoundSheet(AStream);
|
||||
INT_EXCEL_ID_CODEPAGE : ReadCodePage(AStream);
|
||||
INT_EXCEL_ID_FONT : ReadFont(AStream);
|
||||
INT_EXCEL_ID_FORMAT : ReadFormat(AStream);
|
||||
INT_EXCEL_ID_XF : ReadXF(AStream);
|
||||
@ -481,7 +476,8 @@ begin
|
||||
|
||||
SetLength(s, Len);
|
||||
AStream.ReadBuffer(s[1], Len*SizeOf(AnsiChar));
|
||||
sheetName := AnsiToUTF8(s);
|
||||
// sheetName := AnsiToUTF8(s);
|
||||
sheetName := ConvertEncoding(s, FCodePage, EncodingUTF8);
|
||||
FWorksheetNames.Add(sheetName);
|
||||
end;
|
||||
|
||||
@ -550,7 +546,8 @@ begin
|
||||
SetLength(s, Len);
|
||||
AStream.ReadBuffer(s[1], len);
|
||||
if (FIncompleteCell <> nil) and (s <> '') then begin
|
||||
FIncompleteCell^.UTF8StringValue := AnsiToUTF8(s);
|
||||
// FIncompleteCell^.UTF8StringValue := AnsiToUTF8(s);
|
||||
FIncompletecell^.UTF8StringValue := ConvertEncoding(s, FCodePage, encodingUTF8);
|
||||
FIncompleteCell^.ContentType := cctUTF8String;
|
||||
if FIsVirtualMode then
|
||||
Workbook.OnReadCellData(Workbook, FIncompleteCell^.Row, FIncompleteCell^.Col, FIncompleteCell);
|
||||
@ -720,7 +717,6 @@ end;
|
||||
procedure TsSpreadBIFF5Reader.ReadFromStream(AStream: TStream; AData: TsWorkbook);
|
||||
var
|
||||
BIFF5EOF: Boolean;
|
||||
p,s: Int64;
|
||||
begin
|
||||
{ Initializations }
|
||||
|
||||
@ -743,8 +739,6 @@ begin
|
||||
ReadWorksheet(AStream, AData);
|
||||
|
||||
// Check for the end of the file
|
||||
p := AStream.Position;
|
||||
s := AStream.Size;
|
||||
if AStream.Position >= AStream.Size then BIFF5EOF := True;
|
||||
|
||||
// Final preparations
|
||||
@ -818,7 +812,7 @@ begin
|
||||
Len := AStream.ReadByte();
|
||||
SetLength(fontname, Len);
|
||||
AStream.ReadBuffer(fontname[1], Len);
|
||||
font.FontName := fontname;
|
||||
font.FontName := ConvertEncoding(fontname, FCodePage, encodingUTF8);
|
||||
|
||||
{ Add font to workbook's font list }
|
||||
FWorkbook.AddFont(font);
|
||||
@ -846,7 +840,8 @@ begin
|
||||
AStream.ReadBuffer(fmtString[1], len);
|
||||
|
||||
// Add to the list
|
||||
NumFormatList.AnalyzeAndAdd(fmtIndex, AnsiToUTF8(fmtString));
|
||||
// NumFormatList.AnalyzeAndAdd(fmtIndex, AnsiToUTF8(fmtString));
|
||||
NumFormatList.AnalyzeAndAdd(fmtIndex, ConvertEncoding(fmtString, FCodePage, encodingUTF8));
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF5Reader.ReadLabel(AStream: TStream);
|
||||
@ -856,7 +851,8 @@ var
|
||||
ARow, ACol: Cardinal;
|
||||
XF: WORD;
|
||||
cell: PCell;
|
||||
AValue: ansistring;
|
||||
ansistr: ansistring;
|
||||
valuestr: String;
|
||||
begin
|
||||
rec.Row := 0; // to silence the compiler...
|
||||
|
||||
@ -868,8 +864,8 @@ begin
|
||||
|
||||
{ Byte String with 16-bit size }
|
||||
L := WordLEToN(rec.TextLen);
|
||||
SetLength(AValue, L);
|
||||
AStream.ReadBuffer(AValue[1], L);
|
||||
SetLength(ansistr, L);
|
||||
AStream.ReadBuffer(ansistr[1], L);
|
||||
|
||||
{ Create cell }
|
||||
if FIsVirtualMode then begin
|
||||
@ -879,7 +875,8 @@ begin
|
||||
cell := FWorksheet.GetCell(ARow, ACol);
|
||||
|
||||
{ Save the data }
|
||||
FWorksheet.WriteUTF8Text(cell, ISO_8859_1ToUTF8(AValue));
|
||||
valueStr := ConvertEncoding(ansistr, FCodePage, encodingUTF8);
|
||||
FWorksheet.WriteUTF8Text(cell, valueStr); //ISO_8859_1ToUTF8(ansistr));
|
||||
|
||||
{ Add attributes }
|
||||
ApplyCellFormatting(cell, XF);
|
||||
@ -939,14 +936,11 @@ var
|
||||
i, len: Integer;
|
||||
pane: Byte;
|
||||
begin
|
||||
{ Store some data about the workbook that other routines need }
|
||||
WorkBookEncoding := Workbook.Encoding;
|
||||
|
||||
{ Write workbook globals }
|
||||
|
||||
WriteBOF(AStream, INT_BOF_WORKBOOK_GLOBALS);
|
||||
|
||||
WriteCodepage(AStream, WorkBookEncoding);
|
||||
WriteCodepage(AStream, Workbook.CodePage); //WorkBook.Encoding);
|
||||
WriteWindow1(AStream);
|
||||
WriteFonts(AStream);
|
||||
WriteNumFormats(AStream);
|
||||
@ -1042,11 +1036,14 @@ end;
|
||||
function TsSpreadBIFF5Writer.WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
|
||||
var
|
||||
Len: Byte;
|
||||
LatinSheetName: string;
|
||||
xlsSheetName: ansistring;
|
||||
begin
|
||||
xlsSheetName := ConvertEncoding(ASheetName, encodingUTF8, FCodePage);
|
||||
Len := Length(xlsSheetName);
|
||||
{
|
||||
LatinSheetName := UTF8ToISO_8859_1(ASheetName);
|
||||
Len := Length(LatinSheetName);
|
||||
|
||||
}
|
||||
{ BIFF Record header }
|
||||
AStream.WriteWord(WordToLE(INT_EXCEL_ID_BOUNDSHEET));
|
||||
AStream.WriteWord(WordToLE(6 + 1 + Len));
|
||||
@ -1064,7 +1061,8 @@ begin
|
||||
|
||||
{ Sheet name: Byte string, 8-bit length }
|
||||
AStream.WriteByte(Len);
|
||||
AStream.WriteBuffer(LatinSheetName[1], Len);
|
||||
// AStream.WriteBuffer(LatinSheetName[1], Len);
|
||||
AStream.WriteBuffer(xlsSheetName[1], Len);
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
@ -1204,15 +1202,18 @@ type
|
||||
end;
|
||||
var
|
||||
len: Integer;
|
||||
s: ansistring;
|
||||
fmtStr: String;
|
||||
ansiFmtStr: ansiString;
|
||||
rec: TNumFormatRecord;
|
||||
buf: array of byte;
|
||||
begin
|
||||
if (ANumFormatData = nil) or (ANumFormatData.FormatString = '') then
|
||||
exit;
|
||||
|
||||
s := UTF8ToAnsi(NumFormatList.FormatStringForWriting(AListIndex));
|
||||
len := Length(s);
|
||||
// s := UTF8ToAnsi(NumFormatList.FormatStringForWriting(AListIndex));
|
||||
fmtStr := NumFormatList.FormatStringForWriting(AListIndex);
|
||||
ansiFmtStr := ConvertEncoding(fmtStr, encodingUTF8, FCodePage);
|
||||
len := Length(ansiFmtStr);
|
||||
|
||||
{ BIFF record header }
|
||||
rec.RecordID := WordToLE(INT_EXCEL_ID_FORMAT);
|
||||
@ -1227,7 +1228,7 @@ begin
|
||||
{ Copy the format string characters into a buffer immediately after rec }
|
||||
SetLength(buf, SizeOf(rec) + SizeOf(ansiChar)*len);
|
||||
Move(rec, buf[0], SizeOf(rec));
|
||||
Move(s[1], buf[SizeOf(rec)], len*SizeOf(ansiChar));
|
||||
Move(ansiFmtStr[1], buf[SizeOf(rec)], len*SizeOf(ansiChar));
|
||||
|
||||
{ Write out }
|
||||
AStream.WriteBuffer(buf[0], SizeOf(Rec) + SizeOf(ansiChar)*len);
|
||||
@ -1284,6 +1285,8 @@ begin
|
||||
if (ARow >= FLimitations.MaxRowCount) or (ACol >= FLimitations.MaxColCount) then
|
||||
exit;
|
||||
|
||||
ansiValue := ConvertEncoding(AValue, encodingUTF8, FCodePage);
|
||||
{
|
||||
case WorkBookEncoding of
|
||||
seLatin2: AnsiValue := UTF8ToCP1250(AValue);
|
||||
seCyrillic: AnsiValue := UTF8ToCP1251(AValue);
|
||||
@ -1295,6 +1298,7 @@ begin
|
||||
// Latin 1 is the default
|
||||
AnsiValue := UTF8ToCP1252(AValue);
|
||||
end;
|
||||
}
|
||||
|
||||
if AnsiValue = '' then begin
|
||||
// Bad formatted UTF8String (maybe ANSI?)
|
||||
@ -1354,7 +1358,8 @@ var
|
||||
s: ansistring;
|
||||
len: Integer;
|
||||
begin
|
||||
s := UTF8ToAnsi(AString);
|
||||
// s := UTF8ToAnsi(AString);
|
||||
s := ConvertEncoding(AString, encodingUTF8, FCodePage);
|
||||
len := Length(s);
|
||||
|
||||
{ BIFF Record header }
|
||||
|
@ -78,7 +78,7 @@ type
|
||||
procedure ReadWorkbookGlobals(AStream: TStream; AData: TsWorkbook);
|
||||
procedure ReadWorksheet(AStream: TStream; AData: TsWorkbook);
|
||||
procedure ReadBoundsheet(AStream: TStream);
|
||||
function ReadString(const AStream: TStream; const ALength: WORD): UTF8String;
|
||||
function ReadString(const AStream: TStream; const ALength: WORD): String;
|
||||
protected
|
||||
procedure ReadFont(const AStream: TStream);
|
||||
procedure ReadFormat(AStream: TStream); override;
|
||||
@ -219,7 +219,7 @@ var
|
||||
implementation
|
||||
|
||||
uses
|
||||
Math, fpsStrings, fpsStreams, fpsExprParser;
|
||||
Math, lconvencoding, fpsStrings, fpsStreams, fpsExprParser;
|
||||
|
||||
const
|
||||
{ Excel record IDs }
|
||||
@ -349,81 +349,80 @@ var
|
||||
lLen: SizeInt;
|
||||
RecordType: WORD;
|
||||
RecordSize: WORD;
|
||||
C: char;
|
||||
C: WideChar;
|
||||
begin
|
||||
StringFlags:=AStream.ReadByte;
|
||||
Dec(PendingRecordSize);
|
||||
if StringFlags and 4 = 4 then begin
|
||||
//Asian phonetics
|
||||
//Read Asian phonetics Length (not used)
|
||||
AsianPhoneticBytes:=DWordLEtoN(AStream.ReadDWord);
|
||||
AsianPhoneticBytes := DWordLEtoN(AStream.ReadDWord);
|
||||
end;
|
||||
if StringFlags and 8 = 8 then begin
|
||||
//Rich string
|
||||
RunsCounter:=WordLEtoN(AStream.ReadWord);
|
||||
RunsCounter := WordLEtoN(AStream.ReadWord);
|
||||
dec(PendingRecordSize,2);
|
||||
end;
|
||||
if StringFlags and 1 = 1 Then begin
|
||||
//String is WideStringLE
|
||||
if (ALength*SizeOf(WideChar)) > PendingRecordSize then begin
|
||||
SetLength(Result,PendingRecordSize div 2);
|
||||
AStream.ReadBuffer(Result[1],PendingRecordSize);
|
||||
Dec(PendingRecordSize,PendingRecordSize);
|
||||
SetLength(Result, PendingRecordSize div 2);
|
||||
AStream.ReadBuffer(Result[1], PendingRecordSize);
|
||||
Dec(PendingRecordSize, PendingRecordSize);
|
||||
end else begin
|
||||
SetLength(Result, ALength);
|
||||
AStream.ReadBuffer(Result[1],ALength * SizeOf(WideChar));
|
||||
Dec(PendingRecordSize,ALength * SizeOf(WideChar));
|
||||
AStream.ReadBuffer(Result[1], ALength * SizeOf(WideChar));
|
||||
Dec(PendingRecordSize, ALength * SizeOf(WideChar));
|
||||
end;
|
||||
Result := WideStringLEToN(Result);
|
||||
end else begin
|
||||
//String is 1 byte per char, this is UTF-16 with the high byte ommited because it is zero
|
||||
//so decompress and then convert
|
||||
lLen:=ALength;
|
||||
// String is 1 byte per char, this is UTF-16 with the high byte ommited
|
||||
// because it is zero, so decompress and then convert
|
||||
lLen := ALength;
|
||||
SetLength(DecomprStrValue, lLen);
|
||||
for i := 1 to lLen do
|
||||
begin
|
||||
C:=WideChar(AStream.ReadByte());
|
||||
C := WideChar(AStream.ReadByte); // Read 1 byte, but put it into a 2-byte char
|
||||
DecomprStrValue[i] := C;
|
||||
Dec(PendingRecordSize);
|
||||
if (PendingRecordSize<=0) and (i<lLen) then begin
|
||||
//A CONTINUE may happend here
|
||||
if (PendingRecordSize <= 0) and (i < lLen) then begin
|
||||
//A CONTINUE may have happened here
|
||||
RecordType := WordLEToN(AStream.ReadWord);
|
||||
RecordSize := WordLEToN(AStream.ReadWord);
|
||||
if RecordType<>INT_EXCEL_ID_CONTINUE then begin
|
||||
if RecordType <> INT_EXCEL_ID_CONTINUE then begin
|
||||
Raise Exception.Create('[TsSpreadBIFF8Reader.ReadWideString] Expected CONTINUE record not found.');
|
||||
end else begin
|
||||
PendingRecordSize:=RecordSize;
|
||||
DecomprStrValue:=copy(DecomprStrValue,1,i)+ReadWideString(AStream,ALength-i);
|
||||
PendingRecordSize := RecordSize;
|
||||
DecomprStrValue := copy(DecomprStrValue,1,i) + ReadWideString(AStream, ALength-i);
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Result := DecomprStrValue;
|
||||
end;
|
||||
if StringFlags and 8 = 8 then begin
|
||||
//Rich string (This only happened in BIFF8)
|
||||
for j := 1 to RunsCounter do begin
|
||||
if (PendingRecordSize<=0) then begin
|
||||
if (PendingRecordSize <= 0) then begin
|
||||
//A CONTINUE may happend here
|
||||
RecordType := WordLEToN(AStream.ReadWord);
|
||||
RecordSize := WordLEToN(AStream.ReadWord);
|
||||
if RecordType<>INT_EXCEL_ID_CONTINUE then begin
|
||||
if RecordType <> INT_EXCEL_ID_CONTINUE then begin
|
||||
Raise Exception.Create('[TsSpreadBIFF8Reader.ReadWideString] Expected CONTINUE record not found.');
|
||||
end else begin
|
||||
PendingRecordSize:=RecordSize;
|
||||
PendingRecordSize := RecordSize;
|
||||
end;
|
||||
end;
|
||||
AStream.ReadWord;
|
||||
AStream.ReadWord;
|
||||
dec(PendingRecordSize,2*2);
|
||||
dec(PendingRecordSize, 2*2);
|
||||
end;
|
||||
end;
|
||||
if StringFlags and 4 = 4 then begin
|
||||
//Asian phonetics
|
||||
//Read Asian phonetics, discarded as not used.
|
||||
SetLength(AnsiStrValue,AsianPhoneticBytes);
|
||||
AStream.ReadBuffer(AnsiStrValue[1],AsianPhoneticBytes);
|
||||
SetLength(AnsiStrValue, AsianPhoneticBytes);
|
||||
AStream.ReadBuffer(AnsiStrValue[1], AsianPhoneticBytes);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -572,7 +571,7 @@ begin
|
||||
end;
|
||||
|
||||
function TsSpreadBIFF8Reader.ReadString(const AStream: TStream;
|
||||
const ALength: WORD): UTF8String;
|
||||
const ALength: WORD): String;
|
||||
begin
|
||||
Result := UTF16ToUTF8(ReadWideString(AStream, ALength));
|
||||
end;
|
||||
@ -618,18 +617,16 @@ begin
|
||||
BIFF8EOF := False;
|
||||
|
||||
{ Read workbook globals }
|
||||
|
||||
ReadWorkbookGlobals(AStream, AData);
|
||||
|
||||
// Check for the end of the file
|
||||
if AStream.Position >= AStream.Size then BIFF8EOF := True;
|
||||
|
||||
{ Now read all worksheets }
|
||||
|
||||
while (not BIFF8EOF) do
|
||||
begin
|
||||
//Safe to not read beyond assigned worksheet names.
|
||||
if FCurrentWorksheet>FWorksheetNames.Count-1 then break;
|
||||
if FCurrentWorksheet > FWorksheetNames.Count-1 then break;
|
||||
|
||||
ReadWorksheet(AStream, AData);
|
||||
|
||||
@ -647,9 +644,7 @@ begin
|
||||
FWorkbook.UsePalette(@PALETTE_BIFF8, Length(PALETTE_BIFF8));
|
||||
|
||||
{ Finalizations }
|
||||
|
||||
FWorksheetNames.Free;
|
||||
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF8Reader.ReadLabel(AStream: TStream);
|
||||
@ -956,20 +951,22 @@ end;
|
||||
|
||||
{ Helper function for reading a string with 8-bit length. }
|
||||
function TsSpreadBIFF8Reader.ReadString_8bitLen(AStream: TStream): String;
|
||||
const
|
||||
HAS_8BITLEN = true;
|
||||
var
|
||||
s: widestring;
|
||||
wideStr: widestring;
|
||||
begin
|
||||
s := ReadWideString(AStream, true);
|
||||
Result := UTF8Encode(s);
|
||||
wideStr := ReadWideString(AStream, HAS_8BITLEN);
|
||||
Result := UTF8Encode(wideStr);
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF8Reader.ReadStringRecord(AStream: TStream);
|
||||
var
|
||||
s: String;
|
||||
wideStr: WideString;
|
||||
begin
|
||||
s := ReadWideString(AStream, false);
|
||||
if (FIncompleteCell <> nil) and (s <> '') then begin
|
||||
FIncompleteCell^.UTF8StringValue := UTF8Encode(s);
|
||||
wideStr := ReadWideString(AStream, false);
|
||||
if (FIncompleteCell <> nil) and (wideStr <> '') then begin
|
||||
FIncompleteCell^.UTF8StringValue := UTF8Encode(wideStr);
|
||||
FIncompleteCell^.ContentType := cctUTF8String;
|
||||
if FIsVirtualMode then
|
||||
Workbook.OnReadCellData(Workbook, FIncompleteCell^.Row, FIncompleteCell^.Col, FIncompleteCell);
|
||||
@ -984,14 +981,12 @@ procedure TsSpreadBIFF8Reader.ReadXF(const AStream: TStream);
|
||||
begin
|
||||
case dw of
|
||||
$01..$07: result := TsLineStyle(dw-1);
|
||||
// $07: Result := lsDotted;
|
||||
else Result := lsDashed;
|
||||
end;
|
||||
end;
|
||||
var
|
||||
rec: TBIFF8_XFRecord;
|
||||
fmt: TsCellFormat;
|
||||
// xf: TXFRecord;
|
||||
b: Byte;
|
||||
dw: DWord;
|
||||
fill: Integer;
|
||||
@ -1271,9 +1266,8 @@ var
|
||||
pane: Byte;
|
||||
begin
|
||||
{ Write workbook globals }
|
||||
|
||||
WriteBOF(AStream, INT_BOF_WORKBOOK_GLOBALS);
|
||||
|
||||
WriteCodePage(AStream, 'ucs2le'); //seUTF16);
|
||||
WriteWindow1(AStream);
|
||||
WriteFonts(AStream);
|
||||
WriteNumFormats(AStream);
|
||||
@ -1293,7 +1287,6 @@ begin
|
||||
WriteEOF(AStream);
|
||||
|
||||
{ Write each worksheet }
|
||||
|
||||
for i := 0 to Workbook.GetWorksheetCount - 1 do
|
||||
begin
|
||||
FWorksheet := Workbook.GetWorksheetByIndex(i);
|
||||
@ -1483,7 +1476,7 @@ begin
|
||||
if AFont.Size <= 0.0 then
|
||||
raise Exception.Create('Font size not specified.');
|
||||
|
||||
WideFontName := AFont.FontName;
|
||||
WideFontName := UTF8Decode(AFont.FontName);
|
||||
Len := Length(WideFontName);
|
||||
|
||||
{ BIFF Record header }
|
||||
|
@ -4,20 +4,13 @@ unit xlscommon;
|
||||
OpenOffice Microsoft Excel File Format document }
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}{$H+}
|
||||
{$mode objfpc}{$H+}
|
||||
{$endif}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, DateUtils,
|
||||
(*
|
||||
{$ifdef USE_NEW_OLE}
|
||||
fpolebasic,
|
||||
{$else}
|
||||
fpolestorage,
|
||||
{$endif}
|
||||
*)
|
||||
fpstypes, fpspreadsheet, fpsutils, lconvencoding;
|
||||
|
||||
const
|
||||
@ -73,6 +66,11 @@ const
|
||||
|
||||
{ CODEPAGE record constants }
|
||||
WORD_ASCII = 367;
|
||||
WORD_CP_437_DOS_US = 437;
|
||||
WORD_CP_850_DOS_Latin1 = 850;
|
||||
WORD_CP_852_DOS_Latin2 = 852;
|
||||
WORD_CP_866_DOS_Cyrillic = 866;
|
||||
WORD_CP_874_Thai = 874;
|
||||
WORD_UTF_16 = 1200; // BIFF 8
|
||||
WORD_CP_1250_Latin2 = 1250;
|
||||
WORD_CP_1251_Cyrillic = 1251;
|
||||
@ -304,6 +302,7 @@ type
|
||||
FDateMode: TDateMode;
|
||||
FLastRow: Cardinal;
|
||||
FLastCol: Cardinal;
|
||||
FCodePage: String; // in a format prepared for lconvencoding.ConvertEncoding
|
||||
procedure CreateNumFormatList; override;
|
||||
function FindXFIndex(ACell: PCell): Integer; virtual;
|
||||
function FixColor(AColor: TsColor): TsColor; override;
|
||||
@ -321,7 +320,7 @@ type
|
||||
procedure WriteBool(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: Boolean; ACell: PCell); override;
|
||||
// Writes out used codepage for character encoding
|
||||
procedure WriteCodepage(AStream: TStream; AEncoding: TsEncoding);
|
||||
procedure WriteCodePage(AStream: TStream; ACodePage: String); virtual;
|
||||
// Writes out column info(s)
|
||||
procedure WriteColInfo(AStream: TStream; ACol: PCol);
|
||||
procedure WriteColInfos(AStream: TStream; ASheet: TsWorksheet);
|
||||
@ -403,7 +402,7 @@ implementation
|
||||
|
||||
uses
|
||||
AVL_Tree, Math, Variants,
|
||||
{%H-}fpspatches, xlsConst, fpsNumFormatParser, fpsrpn, fpsExprParser;
|
||||
{%H-}fpspatches, fpsStrings, xlsConst, fpsNumFormatParser, fpsrpn, fpsExprParser;
|
||||
|
||||
const
|
||||
{ Helper table for rpn formulas:
|
||||
@ -827,49 +826,41 @@ begin
|
||||
lCodePage := WordLEToN(AStream.ReadWord());
|
||||
|
||||
case lCodePage of
|
||||
// 016FH = 367 = ASCII
|
||||
// 01B5H = 437 = IBM PC CP-437 (US)
|
||||
//02D0H = 720 = IBM PC CP-720 (OEM Arabic)
|
||||
//02E1H = 737 = IBM PC CP-737 (Greek)
|
||||
//0307H = 775 = IBM PC CP-775 (Baltic)
|
||||
//0352H = 850 = IBM PC CP-850 (Latin I)
|
||||
$0352: FCodepage := 'cp850';
|
||||
//0354H = 852 = IBM PC CP-852 (Latin II (Central European))
|
||||
$0354: FCodepage := 'cp852';
|
||||
//0357H = 855 = IBM PC CP-855 (Cyrillic)
|
||||
$0357: FCodepage := 'cp855';
|
||||
//0359H = 857 = IBM PC CP-857 (Turkish)
|
||||
$0359: FCodepage := 'cp857';
|
||||
//035AH = 858 = IBM PC CP-858 (Multilingual Latin I with Euro)
|
||||
//035CH = 860 = IBM PC CP-860 (Portuguese)
|
||||
//035DH = 861 = IBM PC CP-861 (Icelandic)
|
||||
//035EH = 862 = IBM PC CP-862 (Hebrew)
|
||||
//035FH = 863 = IBM PC CP-863 (Canadian (French))
|
||||
//0360H = 864 = IBM PC CP-864 (Arabic)
|
||||
//0361H = 865 = IBM PC CP-865 (Nordic)
|
||||
//0362H = 866 = IBM PC CP-866 (Cyrillic (Russian))
|
||||
//0365H = 869 = IBM PC CP-869 (Greek (Modern))
|
||||
//036AH = 874 = Windows CP-874 (Thai)
|
||||
//03A4H = 932 = Windows CP-932 (Japanese Shift-JIS)
|
||||
//03A8H = 936 = Windows CP-936 (Chinese Simplified GBK)
|
||||
//03B5H = 949 = Windows CP-949 (Korean (Wansung))
|
||||
//03B6H = 950 = Windows CP-950 (Chinese Traditional BIG5)
|
||||
//04B0H = 1200 = UTF-16 (BIFF8)
|
||||
$04B0: FCodepage := 'utf-16';
|
||||
//04E2H = 1250 = Windows CP-1250 (Latin II) (Central European)
|
||||
//04E3H = 1251 = Windows CP-1251 (Cyrillic)
|
||||
//04E4H = 1252 = Windows CP-1252 (Latin I) (BIFF4-BIFF5)
|
||||
//04E5H = 1253 = Windows CP-1253 (Greek)
|
||||
//04E6H = 1254 = Windows CP-1254 (Turkish)
|
||||
$04E6: FCodepage := 'cp1254';
|
||||
//04E7H = 1255 = Windows CP-1255 (Hebrew)
|
||||
//04E8H = 1256 = Windows CP-1256 (Arabic)
|
||||
//04E9H = 1257 = Windows CP-1257 (Baltic)
|
||||
//04EAH = 1258 = Windows CP-1258 (Vietnamese)
|
||||
//0551H = 1361 = Windows CP-1361 (Korean (Johab))
|
||||
//2710H = 10000 = Apple Roman
|
||||
//8000H = 32768 = Apple Roman
|
||||
//8001H = 32769 = Windows CP-1252 (Latin I) (BIFF2-BIFF3)
|
||||
// 016FH = 367 = ASCII
|
||||
WORD_CP_437_DOS_US: FCodePage := 'cp437'; // IBM PC CP-437 (US)
|
||||
//02D0H = 720 = IBM PC CP-720 (OEM Arabic)
|
||||
//02E1H = 737 = IBM PC CP-737 (Greek)
|
||||
//0307H = 775 = IBM PC CP-775 (Baltic)
|
||||
WORD_CP_850_DOS_Latin1: FCodepage := 'cp850'; // IBM PC CP-850 (Latin I)
|
||||
WORD_CP_852_DOS_Latin2: FCodepage := 'cp852'; // IBM PC CP-852 (Latin II (Central European))
|
||||
//035AH = 858 = IBM PC CP-858 (Multilingual Latin I with Euro)
|
||||
//035CH = 860 = IBM PC CP-860 (Portuguese)
|
||||
//035DH = 861 = IBM PC CP-861 (Icelandic)
|
||||
//035EH = 862 = IBM PC CP-862 (Hebrew)
|
||||
//035FH = 863 = IBM PC CP-863 (Canadian (French))
|
||||
//0360H = 864 = IBM PC CP-864 (Arabic)
|
||||
//0361H = 865 = IBM PC CP-865 (Nordic)
|
||||
WORD_CP_866_DOS_Cyrillic: FCodePage := 'cp866'; // IBM PC CP-866 (Cyrillic Russian)
|
||||
//0365H = 869 = IBM PC CP-869 (Greek (Modern))
|
||||
WORD_CP_874_Thai: FCodePage := 'cp874'; // 874 = Windows CP-874 (Thai)
|
||||
//03A4H = 932 = Windows CP-932 (Japanese Shift-JIS)
|
||||
//03A8H = 936 = Windows CP-936 (Chinese Simplified GBK)
|
||||
//03B5H = 949 = Windows CP-949 (Korean (Wansung))
|
||||
//03B6H = 950 = Windows CP-950 (Chinese Traditional BIG5)
|
||||
WORD_UTF_16 : FCodePage := 'ucs2le'; // UTF-16 (BIFF8)
|
||||
WORD_CP_1250_Latin2: FCodepage := 'cp1250'; // Windows CP-1250 (Latin II) (Central European)
|
||||
WORD_CP_1251_Cyrillic: FCodePage := 'cp1251'; // Windows CP-1251 (Cyrillic)
|
||||
WORD_CP_1252_Latin1: FCodePage := 'cp1252'; // Windows CP-1252 (Latin I) (BIFF4-BIFF5)
|
||||
WORD_CP_1253_Greek: FCodePage := 'cp1253'; // Windows CP-1253 (Greek)
|
||||
WORD_CP_1254_Turkish: FCodepage := 'cp1254'; // Windows CP-1254 (Turkish)
|
||||
WORD_CP_1255_Hebrew: FCodePage := 'cp1255'; // Windows CP-1255 (Hebrew)
|
||||
WORD_CP_1256_Arabic: FCodePage := 'cp1256'; // Windows CP-1256 (Arabic)
|
||||
WORD_CP_1257_Baltic: FCodePage := 'cp1257'; // Windows CP-1257 (Baltic)
|
||||
WORD_CP_1258_Vietnamese: FCodePage := 'cp1258'; // Windows CP-1258 (Vietnamese)
|
||||
//0551H = 1361 = Windows CP-1361 (Korean (Johab))
|
||||
//2710H = 10000 = Apple Roman
|
||||
//8000H = 32768 = Apple Roman
|
||||
WORD_CP_1258_Latin1_BIFF2_3: FCodePage := 'cp1252'; // Windows CP-1252 (Latin I) (BIFF2-BIFF3)
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -1711,7 +1702,8 @@ begin
|
||||
len := AStream.ReadByte;
|
||||
SetLength(s, len);
|
||||
AStream.ReadBuffer(s[1], len);
|
||||
Result := ansiToUTF8(s);
|
||||
Result := ConvertEncoding(s, FCodePage, encodingUTF8);
|
||||
// Result := ansiToUTF8(s);
|
||||
end;
|
||||
|
||||
{ Reads a STRING record. It immediately precedes a FORMULA record which has a
|
||||
@ -1806,7 +1798,7 @@ end;
|
||||
function TsSpreadBIFFWriter.GetLastRowIndex(AWorksheet: TsWorksheet): Integer;
|
||||
begin
|
||||
FLastRow := 0;
|
||||
IterateThroughCells(nil, AWorksheet.Cells, GetLastRowCallback);
|
||||
IterateThroughCells(nil, AWorksheet.Cells, @GetLastRowCallback);
|
||||
Result := FLastRow;
|
||||
end;
|
||||
|
||||
@ -1819,7 +1811,7 @@ end;
|
||||
function TsSpreadBIFFWriter.GetLastColIndex(AWorksheet: TsWorksheet): Word;
|
||||
begin
|
||||
FLastCol := 0;
|
||||
IterateThroughCells(nil, AWorksheet.Cells, GetLastColCallback);
|
||||
IterateThroughCells(nil, AWorksheet.Cells, @GetLastColCallback);
|
||||
Result := FLastCol;
|
||||
end;
|
||||
|
||||
@ -1878,28 +1870,44 @@ begin
|
||||
AStream.WriteBuffer(rec, SizeOf(rec));
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFFWriter.WriteCodepage(AStream: TStream;
|
||||
AEncoding: TsEncoding);
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Writes the code page identifier defined by the workbook to the stream.
|
||||
BIFF2 has to be overridden because is uses cp1252, but has a different
|
||||
number code.
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsSpreadBIFFWriter.WriteCodepage(AStream: TStream; ACodePage: String);
|
||||
// AEncoding: TsEncoding);
|
||||
var
|
||||
lCodepage: Word;
|
||||
cp: 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;
|
||||
FCodePage := lowercase(ACodePage);
|
||||
case FCodePage of
|
||||
'ucs2le': cp := WORD_UTF_16; // Biff 7
|
||||
'cp437' : cp := WORD_CP_437_DOS_US;
|
||||
'cp850' : cp := WORD_CP_850_DOS_Latin1;
|
||||
'cp852' : cp := WORD_CP_852_DOS_Latin2;
|
||||
'cp866' : cp := WORD_CP_866_DOS_Cyrillic;
|
||||
'cp874' : cp := WORD_CP_874_Thai;
|
||||
'cp1250': cp := WORD_CP_1250_Latin2;
|
||||
'cp1251': cp := WORD_CP_1251_Cyrillic;
|
||||
'cp1252': cp := WORD_CP_1252_Latin1;
|
||||
'cp1253': cp := WORD_CP_1253_Greek;
|
||||
'cp1254': cp := WORD_CP_1254_Turkish;
|
||||
'cp1255': cp := WORD_CP_1255_Hebrew;
|
||||
'cp1256': cp := WORD_CP_1256_Arabic;
|
||||
'cp1257': cp := WORD_CP_1257_Baltic;
|
||||
'cp1258': cp := WORD_CP_1258_Vietnamese;
|
||||
else
|
||||
// Default is Latin1
|
||||
lCodepage := WORD_CP_1252_Latin1;
|
||||
Workbook.AddErrorMsg(rsCodePageNotSupported, [FCodePage]);
|
||||
FCodePage := 'cp1252';
|
||||
cp := WORD_CP_1252_Latin1;
|
||||
end;
|
||||
AStream.WriteWord(WordToLE(lCodepage));
|
||||
AStream.WriteWord(WordToLE(cp));
|
||||
end;
|
||||
|
||||
{ Writes column info for the given column. Currently only the colum width is used.
|
||||
@ -1958,7 +1966,8 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Writes a NOTE record which describes a comment attached to a cell }
|
||||
{ Writes a NOTE record which describes a comment attached to a cell
|
||||
Valid für Biff2 and BIFF5}
|
||||
procedure TsSpreadBIFFWriter.WriteComment(AStream: TStream; ACell: PCell);
|
||||
const
|
||||
CHUNK_SIZE = 2048;
|
||||
@ -1977,7 +1986,7 @@ begin
|
||||
|
||||
List := TStringList.Create;
|
||||
try
|
||||
List.Text := UTF8ToAnsi(ACell^.Comment);
|
||||
List.Text := ConvertEncoding(ACell^.Comment, encodingUTF8, FCodePage);
|
||||
comment := List[0];
|
||||
for p := 1 to List.Count-1 do
|
||||
comment := comment + #$0A + List[p];
|
||||
@ -2402,8 +2411,8 @@ begin
|
||||
shared formula RECORD here. The shared formula RECORD must follow the
|
||||
first FORMULA record referring to the shared formula}
|
||||
if (ACell^.SharedFormulaBase <> nil) and
|
||||
(ARow = ACell^.SharedFormulaBase.Row) and
|
||||
(ACol = ACell^.SharedFormulaBase.Col)
|
||||
(ARow = ACell^.SharedFormulaBase^.Row) and
|
||||
(ACol = ACell^.SharedFormulaBase^.Col)
|
||||
then
|
||||
WriteSharedFormula(AStream, ACell^.SharedFormulaBase);
|
||||
|
||||
@ -2484,8 +2493,8 @@ var
|
||||
begin
|
||||
rec.FormulaSize := WordToLE(5);
|
||||
rec.Token := INT_EXCEL_TOKEN_TEXP; // Marks the cell for using a shared formula
|
||||
rec.Row := WordToLE(ACell^.SharedFormulaBase.Row);
|
||||
rec.Col := WordToLE(ACell^.SharedFormulaBase.Col);
|
||||
rec.Row := WordToLE(ACell^.SharedFormulaBase^.Row);
|
||||
rec.Col := WordToLE(ACell^.SharedFormulaBase^.Col);
|
||||
AStream.WriteBuffer(rec, SizeOf(rec));
|
||||
RPNLength := SizeOf(rec);
|
||||
end;
|
||||
@ -2929,7 +2938,7 @@ var
|
||||
len: Byte;
|
||||
s: ansistring;
|
||||
begin
|
||||
s := UTF8ToAnsi(AString);
|
||||
s := ConvertEncoding(AString, encodingUTF8, FCodePage);
|
||||
len := Length(s);
|
||||
AStream.WriteByte(len);
|
||||
AStream.WriteBuffer(s[1], len);
|
||||
|
@ -2395,6 +2395,8 @@ end;
|
||||
|
||||
procedure TsSpreadOOXMLWriter.WriteWorksheetRels(AWorksheet: TsWorksheet);
|
||||
begin
|
||||
Unused(AWorksheet);
|
||||
|
||||
// Create stream
|
||||
SetLength(FSSheetRels, FCurSheetNum + 1);
|
||||
if (boBufStream in Workbook.Options) then
|
||||
|
Reference in New Issue
Block a user