diff --git a/components/fpspreadsheet/examples/excel8demo/excel8write.lpr b/components/fpspreadsheet/examples/excel8demo/excel8write.lpr
index a651b2de6..2f30a19f3 100644
--- a/components/fpspreadsheet/examples/excel8demo/excel8write.lpr
+++ b/components/fpspreadsheet/examples/excel8demo/excel8write.lpr
@@ -52,6 +52,10 @@ begin
lCell^.BackgroundColor := scPURPLE;
lCell^.UsedFormattingFields := [uffBackgroundColor];
+ // Word-wrapped long text
+ MyWorksheet.WriteUTF8Text(6, 3, 'This is a very, very, very, very long text.');
+ MyWorksheet.WriteUsedFormatting(6, 3, [uffWordwrap]);
+
{ Uncomment this to test large XLS files
for i := 2 to 20 do
begin
@@ -61,7 +65,6 @@ begin
MyWorksheet.WriteAnsiText(i, 3, ParamStr(0));
end;
}
-
// Write the formula E1 = A1 + B1
SetLength(MyRPNFormula, 3);
MyRPNFormula[0].ElementKind := fekCell;
diff --git a/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi b/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi
index e40b049ad..a53fadb58 100644
--- a/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi
+++ b/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi
@@ -38,15 +38,17 @@
-
+
+
-
-
+
+
+
@@ -55,35 +57,35 @@
-
+
-
-
-
+
+
+
-
+
-
-
-
-
-
-
+
+
+
-
+
-
-
-
+
+
+
+
+
+
@@ -92,7 +94,7 @@
-
+
@@ -100,7 +102,7 @@
-
+
@@ -108,7 +110,7 @@
-
+
@@ -116,167 +118,266 @@
-
+
-
+
-
-
-
+
-
+
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -303,6 +404,11 @@
+
+
+
+
+
diff --git a/components/fpspreadsheet/fpspreadsheetgrid.pas b/components/fpspreadsheet/fpspreadsheetgrid.pas
index 5e6aa13a0..35cf90eb4 100644
--- a/components/fpspreadsheet/fpspreadsheetgrid.pas
+++ b/components/fpspreadsheet/fpspreadsheetgrid.pas
@@ -217,6 +217,11 @@ begin
// Default alignment of number is right-justify
if lCell^.ContentType = cctNumber then
ts.Alignment := taRightJustify;
+ // Word wrap?
+ if (uffWordWrap in lCell^.UsedFormattingFields) then begin
+ ts.Wordbreak := true;
+ ts.SingleLine := false;
+ end;
end;
end;
Canvas.TextStyle := ts;
diff --git a/components/fpspreadsheet/tests/formattests.pas b/components/fpspreadsheet/tests/formattests.pas
index ada997335..ad5564a50 100644
--- a/components/fpspreadsheet/tests/formattests.pas
+++ b/components/fpspreadsheet/tests/formattests.pas
@@ -49,6 +49,8 @@ type
procedure TestWriteReadDateTimeFormats;
// Test column width
procedure TestWriteReadColWidths;
+ // Test word wrapping
+ procedure TestWriteReadWordWrap;
end;
implementation
@@ -274,6 +276,58 @@ begin
DeleteFile(TempFile);
end;
+procedure TSpreadWriteReadFormatTests.TestWriteReadWordWrap;
+const
+ LONGTEXT = 'This is a very, very, very, very long text.';
+var
+ MyWorksheet: TsWorksheet;
+ MyWorkbook: TsWorkbook;
+ MyCell: PCell;
+ TempFile: string; //write xls/xml to this file and read back from it
+begin
+ TempFile:=GetTempFileName;
+ {// Not needed: use workbook.writetofile with overwrite=true
+ if fileexists(TempFile) then
+ DeleteFile(TempFile);
+ }
+ // Write out all test values:
+ // Cell A1 is word-wrapped, Cell B1 is NOT word-wrapped
+ MyWorkbook := TsWorkbook.Create;
+ MyWorkSheet:= MyWorkBook.AddWorksheet(FmtNumbersSheet);
+ MyWorksheet.WriteUTF8Text(0, 0, LONGTEXT);
+ MyWorksheet.WriteUsedFormatting(0, 0, [uffWordwrap]);
+ MyCell := MyWorksheet.FindCell(0, 0);
+ if MyCell = nil then
+ fail('Error in test code. Failed to get word-wrapped cell.');
+ CheckEquals((uffWordWrap in MyCell^.UsedFormattingFields), true, 'Test unsaved word wrap mismatch cell ' + CellNotation(MyWorksheet,0,0));
+ MyWorksheet.WriteUTF8Text(1, 0, LONGTEXT);
+ MyWorksheet.WriteUsedFormatting(1, 0, []);
+ MyCell := MyWorksheet.FindCell(1, 0);
+ if MyCell = nil then
+ fail('Error in test code. Failed to get word-wrapped cell.');
+ CheckEquals((uffWordWrap in MyCell^.UsedFormattingFields), false, 'Test unsaved non-wrapped cell mismatch, cell ' + CellNotation(MyWorksheet,0,0));
+ MyWorkBook.WriteToFile(TempFile,sfExcel8,true);
+ MyWorkbook.Free;
+
+ // Open the spreadsheet, as biff8
+ MyWorkbook := TsWorkbook.Create;
+ MyWorkbook.ReadFromFile(TempFile, sfExcel8);
+ MyWorksheet:=GetWorksheetByName(MyWorkBook, FmtNumbersSheet);
+ if MyWorksheet=nil then
+ fail('Error in test code. Failed to get named worksheet');
+ MyCell := MyWorksheet.FindCell(0, 0);
+ if MyCell = nil then
+ fail('Error in test code. Failed to get word-wrapped cell.');
+ CheckEquals((uffWordWrap in MyCell^.UsedFormattingFields), true, 'failed to return correct word-wrap flag, cell ' + CellNotation(MyWorksheet,0,0));
+ MyCell := MyWorksheet.FindCell(1, 0);
+ if MyCell = nil then
+ fail('Error in test code. Failed to get non-wrapped cell.');
+ CheckEquals((uffWordWrap in MyCell^.UsedFormattingFields), false, 'failed to return correct word-wrap flag, cell ' + CellNotation(MyWorksheet,0,0));
+ // Finalization
+ MyWorkbook.Free;
+
+ DeleteFile(TempFile);
+end;
initialization
RegisterTest(TSpreadWriteReadFormatTests);
diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas
index 463d0ea7a..6beae8cde 100755
--- a/components/fpspreadsheet/xlsbiff8.pas
+++ b/components/fpspreadsheet/xlsbiff8.pas
@@ -66,6 +66,7 @@ type
TXFRecordData = class
public
FormatIndex: Integer;
+ WordWrap: Boolean;
Borders: TsCellBorders;
{
FontIndex: Integer;
@@ -156,6 +157,10 @@ type
protected
procedure AddDefaultFormats(); override;
procedure WriteColInfo(AStream: TStream; ASheet: TsWorksheet; ACol: PCol);
+ procedure WriteXF(AStream: TStream; AFontIndex: Word;
+ AFormatIndex: Word; AXF_TYPE_PROT, ATextRotation: Byte; ABorders: TsCellBorders;
+ AddWordWrap: Boolean = false; AddBackground: Boolean = false;
+ ABackgroundColor: TsColor = scSilver);
public
// constructor Create;
// destructor Destroy; override;
@@ -181,9 +186,6 @@ type
procedure WriteStyle(AStream: TStream);
procedure WriteWindow1(AStream: TStream);
procedure WriteWindow2(AStream: TStream; ASheetSelected: Boolean);
- procedure WriteXF(AStream: TStream; AFontIndex: Word;
- AFormatIndex: Word; AXF_TYPE_PROT, ATextRotation: Byte; ABorders: TsCellBorders;
- AddBackground: Boolean = False; ABackgroundColor: TsColor = scSilver);
end;
implementation
@@ -302,7 +304,9 @@ const
MASK_XF_TYPE_PROT = $0007;
MASK_XF_TYPE_PROT_PARENT = $FFF0;
+ MASK_XF_HOR_ALIGN = $07;
MASK_XF_VERT_ALIGN = $70;
+ MASK_XF_TEXTWRAP = $08;
{
Exported functions
@@ -392,6 +396,7 @@ var
lBorders: TsCellBorders;
lAddBackground: Boolean;
lBackgroundColor: TsColor;
+ lWordWrap: Boolean;
fmt: String;
begin
// The first 4 styles were already added
@@ -402,7 +407,6 @@ begin
lFormatIndex := 0; //General format (one of the built-in number formats)
lTextRotation := XF_ROTATION_HORIZONTAL;
lBorders := [];
- lAddBackground := False;
lBackgroundColor := FFormattingStyles[i].BackgroundColor;
// Now apply the modifications.
@@ -480,11 +484,12 @@ begin
if uffBold in FFormattingStyles[i].UsedFormattingFields then
lFontIndex := 1;
- if uffBackgroundColor in FFormattingStyles[i].UsedFormattingFields then
- lAddBackground := True;
+ lAddBackground := (uffBackgroundColor in FFormattingStyles[i].UsedFormattingFields);
+ lWordwrap := (uffWordwrap in FFormattingStyles[i].UsedFormattingFields);
// And finally write the style
- WriteXF(AStream, lFontIndex, lFormatIndex, 0, lTextRotation, lBorders, lAddBackground, lBackgroundColor);
+ WriteXF(AStream, lFontIndex, lFormatIndex, 0, lTextRotation, lBorders, lWordwrap,
+ lAddBackground, lBackgroundColor);
end;
end;
@@ -1520,7 +1525,8 @@ end;
*******************************************************************}
procedure TsSpreadBIFF8Writer.WriteXF(AStream: TStream; AFontIndex: Word;
AFormatIndex: Word; AXF_TYPE_PROT, ATextRotation: Byte; ABorders: TsCellBorders;
- AddBackground: Boolean = False; ABackgroundColor: TsColor = scSilver);
+ AddWordWrap: Boolean = false; AddBackground: Boolean = false;
+ ABackgroundColor: TsColor = scSilver);
var
XFOptions: Word;
XFAlignment, XFOrientationAttrib: Byte;
@@ -1546,6 +1552,8 @@ begin
{ Alignment and text break }
XFAlignment := MASK_XF_VERT_ALIGN_BOTTOM;
+ if AddWordWrap then
+ XFAlignment := XFAlignment or MASK_XF_TEXTWRAP;
AStream.WriteByte(XFAlignment);
@@ -2050,6 +2058,12 @@ begin
if Assigned(lCell) then begin
XFData := TXFRecordData(FXFList.Items[XFIndex]);
+ // Word wrap
+ if XFData.WordWrap then
+ Include(lCell^.UsedFormattingFields, uffWordWrap)
+ else
+ Exclude(lCell^.UsedFormattingFields, uffWordWrap);
+
// Borders
if XFData.Borders <> [] then begin
Include(lCell^.UsedFormattingFields, uffBorder);
@@ -2389,6 +2403,9 @@ begin
// Format index
lData.FormatIndex := WordLEToN(xf.FormatIndex);
+ // Word wrap
+ lData.WordWrap := (xf.Align_TextBreak and MASK_XF_TEXTWRAP) <> 0;
+
// Cell borders
xf.Border_Background_1 := DWordLEToN(xf.Border_Background_1);
lData.Borders := [];