diff --git a/components/fpspreadsheet/examples/excel2demo/excel2write.lpi b/components/fpspreadsheet/examples/excel2demo/excel2write.lpi
index b796af7d9..5d80f62c2 100644
--- a/components/fpspreadsheet/examples/excel2demo/excel2write.lpi
+++ b/components/fpspreadsheet/examples/excel2demo/excel2write.lpi
@@ -54,5 +54,10 @@
+
+
+
+
+
diff --git a/components/fpspreadsheet/fpsopendocument.pas b/components/fpspreadsheet/fpsopendocument.pas
index 0eb47c027..e3ac875f6 100755
--- a/components/fpspreadsheet/fpsopendocument.pas
+++ b/components/fpspreadsheet/fpsopendocument.pas
@@ -2995,11 +2995,10 @@ begin
Format('table:number-columns-repeated="%d"', [colsRepeated]));
AppendToStream(AStream, Format(
- '', [styleName, rowsRepeatedStr]));
- AppendToStream(AStream, Format(
- '', [colsRepeatedStr]));
- AppendToStream(AStream,
- '');
+ '' +
+ '' +
+ '',
+ [styleName, rowsRepeatedStr, colsRepeatedStr]));
r := rr;
continue;
@@ -3476,8 +3475,8 @@ begin
// The row should already be the correct one
AppendToStream(AStream,
- '',
- '' + UTF8TextToXMLText(AValue) + '',
+ '' +
+ '' + UTF8TextToXMLText(AValue) + '' +
'');
end;
@@ -3514,8 +3513,8 @@ begin
end;
AppendToStream(AStream,
- '',
- '' + DisplayStr + '',
+ '' +
+ '' + DisplayStr + '' +
'');
end;
diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas
index a590191ef..c8788a8cd 100755
--- a/components/fpspreadsheet/xlsbiff2.pas
+++ b/components/fpspreadsheet/xlsbiff2.pas
@@ -87,6 +87,8 @@ type
TsSpreadBIFF2Writer = class(TsSpreadBIFFWriter)
private
function FindXFIndex(ACell: PCell): Word;
+ procedure GetCellAttributes(ACell: PCell; XFIndex: Word;
+ out Attrib1, Attrib2, Attrib3: Byte);
{ Record writing methods }
procedure WriteBOF(AStream: TStream);
procedure WriteCellFormatting(AStream: TStream; ACell: PCell; XFIndex: Word);
@@ -850,6 +852,50 @@ begin
end;
end;
+{ Determines the cell attributes needed for writing a cell content record, such
+ as WriteLabel, WriteNumber, etc.
+ The cell attributes contain, in bit masks, xf record index, font index, borders, etc.}
+procedure TsSpreadBIFF2Writer.GetCellAttributes(ACell: PCell; XFIndex: Word;
+ out Attrib1, Attrib2, Attrib3: Byte);
+begin
+ if ACell^.UsedFormattingFields = [] then begin
+ Attrib1 := 15;
+ Attrib2 := 0;
+ Attrib3 := 0;
+ exit;
+ end;
+
+ // 1st byte:
+ // Mask $3F: Index to XF record
+ // Mask $40: 1 = Cell is locked
+ // Mask $80: 1 = Formula is hidden
+ Attrib1 := Min(XFIndex, $3F) and $3F;
+
+ // 2nd byte:
+ // Mask $3F: Index to FORMAT record
+ // Mask $C0: Index to FONT record
+ Attrib2 := ACell^.FontIndex shr 6;
+
+ // 3rd byte
+ // Mask $07: horizontal alignment
+ // Mask $08: Cell has left border
+ // Mask $10: Cell has right border
+ // Mask $20: Cell has top border
+ // Mask $40: Cell has bottom border
+ // Mask $80: Cell has shaded background
+ Attrib3 := 0;
+ if uffHorAlign in ACell^.UsedFormattingFields then
+ Attrib3 := ord (ACell^.HorAlignment);
+ if uffBorder in ACell^.UsedFormattingFields then begin
+ if cbNorth in ACell^.Border then Attrib3 := Attrib3 or $20;
+ if cbWest in ACell^.Border then Attrib3 := Attrib3 or $08;
+ if cbEast in ACell^.Border then Attrib3 := Attrib3 or $10;
+ if cbSouth in ACell^.Border then Attrib3 := Attrib3 or $40;
+ end;
+ if uffBackgroundColor in ACell^.UsedFormattingFields then
+ Attrib3 := Attrib3 or $80;
+end;
+
{ Builds up the list of number formats to be written to the biff2 file.
Unlike biff5+ no formats are added here because biff2 supports only 21
standard formats; these formats have been added by the NumFormatList's
@@ -888,7 +934,7 @@ begin
// 2nd byte:
// Mask $3F: Index to FORMAT record
// Mask $C0: Index to FONT record
- w := ACell.FontIndex shl 6;
+ w := ACell.FontIndex shr 6; // was shl --> MUST BE shr!
b := Lo(w);
//b := ACell.FontIndex shl 6;
AStream.WriteByte(b);
@@ -918,10 +964,36 @@ end;
Writes an Excel 2 COLWIDTH record
}
procedure TsSpreadBIFF2Writer.WriteColWidth(AStream: TStream; ACol: PCol);
+type
+ TColRecord = packed record
+ RecordID: Word;
+ RecordSize: Word;
+ StartCol: Byte;
+ EndCol: Byte;
+ ColWidth: Word;
+ end;
var
+ rec: TColRecord;
w: Integer;
begin
if Assigned(ACol) then begin
+ { BIFF record header }
+ rec.RecordID := WordToLE(INT_EXCEL_ID_COLWIDTH);
+ rec.RecordSize := WordToLE(4);
+
+ { Start and end column }
+ rec.StartCol := ACol^.Col;
+ rec.EndCol := ACol^.Col;
+
+ { Column width }
+ { calculate width to be in units of 1/256 of pixel width of character "0" }
+ w := round(ACol^.Width * 256);
+ rec.ColWidth := WordToLE(w);
+
+ { Write out }
+ AStream.WriteBuffer(rec, SizeOf(rec));
+
+ (*
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_COLWIDTH)); // BIFF record header
AStream.WriteWord(WordToLE(4)); // Record size
@@ -930,6 +1002,7 @@ begin
{ calculate width to be in units of 1/256 of pixel width of character "0" }
w := round(ACol^.Width * 256);
AStream.WriteWord(WordToLE(w)); // write width
+ *)
end;
end;
@@ -1257,15 +1330,42 @@ end;
procedure TsSpreadBiff2Writer.WriteFormat(AStream: TStream;
AFormatData: TsNumFormatData; AListIndex: Integer);
+type
+ TNumFormatRecord = packed record
+ RecordID: Word;
+ RecordSize: Word;
+ FormatLen: Byte;
+ end;
var
len: Integer;
s: ansistring;
+ rec: TNumFormatRecord;
+ buf: array of byte;
begin
Unused(AFormatData);
s := NumFormatList.FormatStringForWriting(AListIndex);
len := Length(s);
+ { BIFF record header }
+ rec.RecordID := WordToLE(INT_EXCEL_ID_FORMAT);
+ rec.RecordSize := WordToLE(1 + len);
+
+ { Length byte of format string }
+ rec.FormatLen := len;
+
+ { 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));
+
+ { Write out }
+ AStream.WriteBuffer(buf[0], SizeOf(Rec) + SizeOf(ansiChar)*len);
+
+ { Clean up }
+ SetLength(buf, 0);
+
+ (*
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_FORMAT));
AStream.WriteWord(WordToLE(1 + len));
@@ -1273,6 +1373,7 @@ begin
{ Format string }
AStream.WriteByte(len); // AnsiString, char count in 1 byte
AStream.WriteBuffer(s[1], len); // String data
+ *)
end;
procedure TsSpreadBIFF2Writer.WriteFormatCount(AStream: TStream);
@@ -1401,13 +1502,38 @@ end;
*******************************************************************}
procedure TsSpreadBIFF2Writer.WriteBlank(AStream: TStream;
const ARow, ACol: Cardinal; ACell: PCell);
+type
+ TBlankRecord = packed record
+ RecordID: Word;
+ RecordSize: Word;
+ Row: Word;
+ Col: Word;
+ Attrib1, Attrib2, Attrib3: Byte;
+ end;
+
var
xf: Word;
+ rec: TBlankRecord;
begin
xf := FindXFIndex(ACell);
if xf >= 63 then
WriteIXFE(AStream, xf);
+ { BIFF record header }
+ rec.RecordID := WordToLE(INT_EXCEL_ID_BLANK);
+ rec.RecordSize := WordToLE(7);
+
+ { BIFF record data }
+ rec.Row := WordToLE(ARow);
+ rec.Col := WordToLE(ACol);
+
+ { BIFF2 attributes }
+ GetCellAttributes(ACell, xf, rec.Attrib1, rec.Attrib2, rec.Attrib3);
+
+ { Write out }
+ AStream.WriteBuffer(rec, Sizeof(rec));
+
+ (*
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_BLANK));
AStream.WriteWord(WordToLE(7));
@@ -1418,6 +1544,7 @@ begin
{ BIFF2 Attributes }
WriteCellFormatting(AStream, ACell, xf);
+ *)
end;
{*******************************************************************
@@ -1433,12 +1560,25 @@ end;
*******************************************************************}
procedure TsSpreadBIFF2Writer.WriteLabel(AStream: TStream; const ARow,
ACol: Cardinal; const AValue: string; ACell: PCell);
+type
+ TLabelRecord = packed record
+ RecordID: Word;
+ RecordSize: Word;
+ Row: Word;
+ Col: Word;
+ Attrib1: Byte;
+ Attrib2: Byte;
+ Attrib3: Byte;
+ TextLen: Byte;
+ end;
const
- MaxBytes=255; //limit for this format
+ MAXBYTES = 255; //limit for this format
var
L: Byte;
AnsiText: ansistring;
TextTooLong: boolean=false;
+ rec: TLabelRecord;
+ buf: array of byte;
var
xf: Word;
begin
@@ -1446,14 +1586,13 @@ begin
AnsiText := UTF8ToISO_8859_1(AValue);
- if Length(AnsiText)>MaxBytes then
- begin
+ if Length(AnsiText) > MAXBYTES then begin
// BIFF 5 does not support labels/text bigger than 255 chars,
// so BIFF2 won't either
// Rather than lose data when reading it, let the application programmer deal
// with the problem or purposefully ignore it.
TextTooLong:=true;
- AnsiText := Copy(AnsiText,1,MaxBytes);
+ AnsiText := Copy(AnsiText, 1, MAXBYTES);
end;
L := Length(AnsiText);
@@ -1461,6 +1600,30 @@ begin
if xf >= 63 then
WriteIXFE(AStream, xf);
+ { BIFF record header }
+ rec.RecordID := WordToLE(INT_EXCEL_ID_LABEL);
+ rec.RecordSize := WordToLE(8 + L);
+
+ { BIFF record data }
+ rec.Row := WordToLE(ARow);
+ rec.Col := WordToLE(ACol);
+
+ { BIFF2 attributes }
+ GetCellAttributes(ACell, xf, rec.Attrib1, rec.Attrib2, rec.Attrib3);
+
+ { Text length: 8 bit }
+ rec.TextLen := L;
+
+ { Copy the text characters into a buffer immediately after rec }
+ SetLength(buf, SizeOf(rec) + SizeOf(ansiChar)*L);
+ Move(rec, buf[0], SizeOf(rec));
+ Move(AnsiText[1], buf[SizeOf(rec)], L*SizeOf(ansiChar));
+
+ { Write out }
+ AStream.WriteBuffer(buf[0], SizeOf(Rec) + SizeOf(ansiChar)*L);
+
+
+ (*
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_LABEL));
AStream.WriteWord(WordToLE(8 + L));
@@ -1475,6 +1638,7 @@ begin
{ String with 8-bit size }
AStream.WriteByte(L);
AStream.WriteBuffer(AnsiText[1], L);
+ *)
{
//todo: keep a log of errors and show with an exception after writing file or something.
@@ -1495,13 +1659,25 @@ end;
*******************************************************************}
procedure TsSpreadBIFF2Writer.WriteNumber(AStream: TStream; const ARow,
ACol: Cardinal; const AValue: double; ACell: PCell);
+type
+ TNumberRecord = packed record
+ RecordID: Word;
+ RecordSize: Word;
+ Row: Word;
+ Col: Word;
+ Attrib1: Byte;
+ Attrib2: Byte;
+ Attrib3: Byte;
+ Value: Double;
+ end;
var
xf: Word;
+ rec: TNumberRecord;
begin
xf := FindXFIndex(ACell);
if xf >= 63 then
WriteIXFE(AStream, xf);
-
+ (*
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_NUMBER));
AStream.WriteWord(WordToLE(15));
@@ -1515,6 +1691,24 @@ begin
{ IEE 754 floating-point value }
AStream.WriteBuffer(AValue, 8);
+ *)
+
+ { BIFF record header }
+ rec.RecordID := WordToLE(INT_EXCEL_ID_NUMBER);
+ rec.RecordSize := WordToLE(15);
+
+ { BIFF record data }
+ rec.Row := WordToLE(ARow);
+ rec.Col := WordToLE(ACol);
+
+ { BIFF2 attributes }
+ GetCellAttributes(ACell, xf, rec.Attrib1, rec.Attrib2, rec.Attrib3);
+
+ { Number value }
+ rec.Value := AValue;
+
+ { Write out }
+ AStream.WriteBuffer(rec, SizeOf(Rec));
end;
procedure TsSpreadBIFF2Writer.WriteRow(AStream: TStream; ASheet: TsWorksheet;
diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas
index 20f6450f0..14069d8d7 100755
--- a/components/fpspreadsheet/xlsbiff5.pas
+++ b/components/fpspreadsheet/xlsbiff5.pas
@@ -667,9 +667,18 @@ end;
*******************************************************************}
procedure TsSpreadBiff5Writer.WriteFormat(AStream: TStream;
AFormatData: TsNumFormatData; AListIndex: Integer);
+type
+ TNumFormatRecord = packed record
+ RecordID: Word;
+ RecordSize: Word;
+ FormatIndex: Word;
+ FormatStringLen: Byte;
+ end;
var
len: Integer;
s: ansistring;
+ rec: TNumFormatRecord;
+ buf: array of byte;
begin
if (AFormatData = nil) or (AFormatData.FormatString = '') then
exit;
@@ -677,6 +686,28 @@ begin
s := NumFormatList.FormatStringForWriting(AListIndex);
len := Length(s);
+ { BIFF record header }
+ rec.RecordID := WordToLE(INT_EXCEL_ID_FORMAT);
+ rec.RecordSize := WordToLE(2 + 1 + len * SizeOf(AnsiChar));
+
+ { Format index }
+ rec.FormatIndex := WordToLE(AFormatData.Index);
+
+ { Format string }
+ { Length in 1 byte }
+ rec.FormatStringLen := len;
+ { 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));
+
+ { Write out }
+ AStream.WriteBuffer(buf[0], SizeOf(Rec) + SizeOf(ansiChar)*len);
+
+ { Clean up }
+ SetLength(buf, 0);
+
+(*
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_FORMAT));
AStream.WriteWord(WordToLE(2 + 1 + len * SizeOf(AnsiChar)));
@@ -687,7 +718,9 @@ begin
{ Format string }
AStream.WriteByte(len); // AnsiString, char count in 1 byte
AStream.WriteBuffer(s[1], len * SizeOf(AnsiChar)); // String data
+ *)
end;
+
(*
{*******************************************************************
* TsSpreadBIFF5Writer.WriteRPNFormula ()
@@ -893,44 +926,79 @@ end;
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteLabel(AStream: TStream; const ARow,
ACol: Cardinal; const AValue: string; ACell: PCell);
+type
+ TLabelRecord = packed record
+ RecordID: Word;
+ RecordSize: Word;
+ Row: Word;
+ Col: Word;
+ XFIndex: Word;
+ TextLen: Word;
+ end;
const
- MaxBytes=255; //limit for this format
+ MAXBYTES = 255; //limit for this format
var
L: Word;
AnsiValue: ansistring;
TextTooLong: boolean=false;
+ rec: TLabelRecord;
+ buf: array of byte;
begin
case WorkBookEncoding of
- seLatin2: AnsiValue := UTF8ToCP1250(AValue);
- seCyrillic: AnsiValue := UTF8ToCP1251(AValue);
- seGreek: AnsiValue := UTF8ToCP1253(AValue);
- seTurkish: AnsiValue := UTF8ToCP1254(AValue);
- seHebrew: AnsiValue := UTF8ToCP1255(AValue);
- seArabic: AnsiValue := UTF8ToCP1256(AValue);
+ seLatin2: AnsiValue := UTF8ToCP1250(AValue);
+ seCyrillic: AnsiValue := UTF8ToCP1251(AValue);
+ seGreek: AnsiValue := UTF8ToCP1253(AValue);
+ seTurkish: AnsiValue := UTF8ToCP1254(AValue);
+ seHebrew: AnsiValue := UTF8ToCP1255(AValue);
+ seArabic: AnsiValue := UTF8ToCP1256(AValue);
else
// Latin 1 is the default
AnsiValue := UTF8ToCP1252(AValue);
end;
- if AnsiValue = '' then
- begin
+ if AnsiValue = '' then begin
// Bad formatted UTF8String (maybe ANSI?)
- if Length(AValue)<>0 then begin
+ if Length(AValue) <> 0 then begin
//It was an ANSI string written as UTF8 quite sure, so raise exception.
Raise Exception.CreateFmt('Expected UTF8 text but probably ANSI text found in cell [%d,%d]',[ARow,ACol]);
end;
Exit;
end;
- if Length(AnsiValue)>MaxBytes then
- begin
+ if Length(AnsiValue) > MAXBYTES then begin
// Rather than lose data when reading it, let the application programmer deal
// with the problem or purposefully ignore it.
TextTooLong := true;
- AnsiValue := Copy(AnsiValue,1,MaxBytes);
+ AnsiValue := Copy(AnsiValue, 1, MAXBYTES);
end;
L := Length(AnsiValue);
+ { BIFF record header }
+ rec.RecordID := WordToLE(INT_EXCEL_ID_LABEL);
+ rec.RecordSize := WordToLE(8 + L);
+
+ { BIFF record data }
+ rec.Row := WordToLE(ARow);
+ rec.Col := WordToLE(ACol);
+
+ { Index to XF record }
+ rec.XFIndex := WordToLE(FindXFIndex(ACell));
+
+ { String length, 16 bit }
+ rec.TextLen := WordToLE(L);
+
+ { Copy the text characters into a buffer immediately after rec }
+ SetLength(buf, SizeOf(rec) + SizeOf(ansiChar)*L);
+ Move(rec, buf[0], SizeOf(rec));
+ Move(AnsiValue[1], buf[SizeOf(rec)], L*SizeOf(ansiChar));
+
+ { Write out }
+ AStream.WriteBuffer(buf[0], SizeOf(Rec) + SizeOf(ansiChar)*L);
+
+ { Clean up }
+ SetLength(buf, 0);
+
+ (*
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_LABEL));
AStream.WriteWord(WordToLE(8 + L));
@@ -945,7 +1013,7 @@ begin
{ Byte String with 16-bit size }
AStream.WriteWord(WordToLE(L));
AStream.WriteBuffer(AnsiValue[1], L);
-
+ *)
{
//todo: keep a log of errors and show with an exception after writing file or something.
We can't just do the following
diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas
index 2540ca7a9..bbf02277f 100755
--- a/components/fpspreadsheet/xlsbiff8.pas
+++ b/components/fpspreadsheet/xlsbiff8.pas
@@ -687,9 +687,19 @@ end;
procedure TsSpreadBiff8Writer.WriteFormat(AStream: TStream;
AFormatData: TsNumFormatData; AListIndex: Integer);
+type
+ TNumFormatRecord = packed record
+ RecordID: Word;
+ RecordSize: Word;
+ FormatIndex: Word;
+ FormatStringLen: Word;
+ FormatStringFlags: Byte;
+ end;
var
len: Integer;
s: widestring;
+ rec: TNumFormatRecord;
+ buf: array of byte;
begin
if (AFormatData = nil) or (AFormatData.FormatString = '') then
exit;
@@ -697,6 +707,30 @@ begin
s := NumFormatList.FormatStringForWriting(AListIndex);
len := Length(s);
+ { BIFF record header }
+ rec.RecordID := WordToLE(INT_EXCEL_ID_FORMAT);
+ rec.RecordSize := WordToLE(2 + 2 + 1 + len * SizeOf(WideChar));
+
+ { Format index }
+ rec.FormatIndex := WordToLE(AFormatData.Index);
+
+ { Format string }
+ { - length of string = 16 bits }
+ rec.FormatStringLen := WordToLE(len);
+ { - Widestring flags, 1 = regular unicode LE string }
+ rec.FormatStringFlags := 1;
+ { - Copy the text characters into a buffer immediately after rec }
+ SetLength(buf, SizeOf(rec) + SizeOf(WideChar)*len);
+ Move(rec, buf[0], SizeOf(rec));
+ Move(s[1], buf[SizeOf(rec)], len*SizeOf(WideChar));
+
+ { Write out }
+ AStream.WriteBuffer(buf[0], SizeOf(rec) + SizeOf(WideChar)*len);
+
+ { Clean up }
+ SetLength(buf, 0);
+
+(*
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_FORMAT));
AStream.WriteWord(WordToLE(2 + 2 + 1 + len * SizeOf(WideChar)));
@@ -711,6 +745,7 @@ begin
AStream.WriteByte(1);
{ - String data }
AStream.WriteBuffer(WideStringToLE(s)[1], len * Sizeof(WideChar));
+ *)
end;
{*******************************************************************
diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas
index 181e8aefa..5c51ff4ae 100644
--- a/components/fpspreadsheet/xlscommon.pas
+++ b/components/fpspreadsheet/xlscommon.pas
@@ -1730,7 +1730,31 @@ end;
different record structure. }
procedure TsSpreadBIFFWriter.WriteBlank(AStream: TStream;
const ARow, ACol: Cardinal; ACell: PCell);
+type
+ TBlankRecord = packed record
+ RecordID: Word;
+ RecordSize: Word;
+ Row: Word;
+ Col: Word;
+ XFIndex: Word;
+ end;
+var
+ rec: TBlankRecord;
begin
+ { BIFF record header }
+ rec.RecordID := WordToLE(INT_EXCEL_ID_BLANK);
+ rec.RecordSize := WordToLE(6);
+
+ { Row and column index }
+ rec.Row := WordToLE(ARow);
+ rec.Col := WordToLE(ACol);
+
+ { Index to XF record, according to formatting }
+ rec.XFIndex := WordToLE(FindXFIndex(ACell));
+
+ { Write out }
+ AStream.WriteBuffer(rec, SizeOf(rec));
+ (*
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_BLANK));
AStream.WriteWord(WordToLE(6));
@@ -1741,6 +1765,7 @@ begin
{ Index to XF record, according to formatting }
WriteXFIndex(AStream, ACell);
+ *)
end;
procedure TsSpreadBIFFWriter.WriteCodepage(AStream: TStream;
@@ -1770,10 +1795,42 @@ end;
{ Writes column info for the given column. Currently only the colum width is used.
Valid for BIFF5 and BIFF8 (BIFF2 uses a different record. }
procedure TsSpreadBIFFWriter.WriteColInfo(AStream: TStream; ACol: PCol);
+type
+ TColRecord = packed record
+ RecordID: Word;
+ RecordSize: Word;
+ StartCol: Word;
+ EndCol: Word;
+ ColWidth: Word;
+ XFIndex: Word;
+ OptionFlags: Word;
+ NotUsed: Word;
+ end;
var
+ rec: TColRecord;
w: Integer;
begin
if Assigned(ACol) then begin
+ { BIFF record header }
+ rec.RecordID := WordToLE(INT_EXCEL_ID_COLINFO);
+ rec.RecordSize := WordToLE(12);
+
+ { Start and end column }
+ rec.StartCol := WordToLE(ACol^.Col);
+ rec.EndCol := WordToLE(ACol^.Col);
+
+ { calculate width to be in units of 1/256 of pixel width of character "0" }
+ w := round(ACol^.Width * 256);
+
+ rec.ColWidth := WordToLE(w);
+ rec.XFIndex := WordToLE(15); // Index of XF record, not used
+ rec.OptionFlags := 0; // not used
+ rec.NotUsed := 0;
+
+ { Write out }
+ AStream.WriteBuffer(rec, SizeOf(rec));
+
+ (*
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_COLINFO)); // BIFF record header
AStream.WriteWord(WordToLE(12)); // Record size
@@ -1785,6 +1842,7 @@ begin
AStream.WriteWord(15); // XF record, ignored
AStream.WriteWord(0); // option flags, ignored
AStream.WriteWord(0); // "not used"
+ *)
end;
end;
diff --git a/components/fpspreadsheet/xlsxooxml.pas b/components/fpspreadsheet/xlsxooxml.pas
index c6b63a934..a39fc91e6 100755
--- a/components/fpspreadsheet/xlsxooxml.pas
+++ b/components/fpspreadsheet/xlsxooxml.pas
@@ -1189,7 +1189,7 @@ end;
procedure TsSpreadOOXMLWriter.WriteLabel(AStream: TStream; const ARow,
ACol: Cardinal; const AValue: string; ACell: PCell);
const
- MaxBytes=32767; //limit for this format
+ MAXBYTES = 32767; //limit for this format
var
CellPosText: string;
lStyleIndex: Cardinal;
@@ -1201,18 +1201,17 @@ begin
Unused(ARow, ACol, ACell);
// Office 2007-2010 (at least) support no more characters in a cell;
- if Length(AValue)>MaxBytes then
- begin
- TextTooLong:=true;
- ResultingValue:=Copy(AValue,1,MaxBytes); //may chop off multicodepoint UTF8 characters but well...
+ if Length(AValue) > MAXBYTES then begin
+ TextTooLong := true;
+ ResultingValue := Copy(AValue, 1, MAXBYTES); //may chop off multicodepoint UTF8 characters but well...
end
else
ResultingValue:=AValue;
AppendToStream(FSSharedStrings,
- '', Format(
- '%s', [UTF8TextToXMLText(ResultingValue)]),
- '' );
+ '' +
+ '' + UTF8TextToXMLText(ResultingValue) + '' +
+ '');
CellPosText := TsWorksheet.CellPosToText(ARow, ACol);
lStyleIndex := GetStyleIndex(ACell);