diff --git a/components/fpspreadsheet/examples/excel2demo/excel2write.lpr b/components/fpspreadsheet/examples/excel2demo/excel2write.lpr
index 9f6f595c7..27dba658f 100644
--- a/components/fpspreadsheet/examples/excel2demo/excel2write.lpr
+++ b/components/fpspreadsheet/examples/excel2demo/excel2write.lpr
@@ -31,6 +31,8 @@ begin
//MyWorksheet.WriteColWidth(0, 5);
//MyWorksheet.WriteColWidth(1, 30);
+ MyWorksheet.WriteRowHeight(0, 30); // 30 mm
+
// Turn off grid lines and hide headers
MyWorksheet.Options := MyWorksheet.Options - [soShowGridLines, soShowHeaders];
diff --git a/components/fpspreadsheet/examples/excel5demo/excel5write.lpr b/components/fpspreadsheet/examples/excel5demo/excel5write.lpr
index e7d1e2be4..7c3945b13 100644
--- a/components/fpspreadsheet/examples/excel5demo/excel5write.lpr
+++ b/components/fpspreadsheet/examples/excel5demo/excel5write.lpr
@@ -43,6 +43,14 @@ begin
MyWorkbook.AddFont('Calibri', 20, [], scRed);
+ // Change row height
+ MyWorksheet.WriteRowHeight(0, 20); // modify height of row 0 to 20 mm
+
+ // Change colum widths
+ MyWorksheet.WriteColWidth(0, 40);
+ MyWorksheet.WriteColWidth(1, 20);
+ MyWorksheet.WriteColWidth(2, 20);
+
// Write some cells
MyWorksheet.WriteNumber(0, 0, 1.0);// A1
MyWorksheet.WriteVertAlignment(0, 0, vaCenter);
diff --git a/components/fpspreadsheet/examples/excel8demo/excel8write.lpr b/components/fpspreadsheet/examples/excel8demo/excel8write.lpr
index 9667a2e49..2f11383c8 100644
--- a/components/fpspreadsheet/examples/excel8demo/excel8write.lpr
+++ b/components/fpspreadsheet/examples/excel8demo/excel8write.lpr
@@ -46,7 +46,7 @@ begin
myWorksheet.LeftPaneWidth := 1;
MyWorksheet.TopPaneHeight := 2;
- { non-frozen panes not working, at the moment. Require SELECTION records?
+ { non-frozen panes not working, at the moment. Requires SELECTION records?
MyWorksheet.LeftPaneWidth := 20*72*2; // 72 pt = inch --> 2 inches = 5 cm
}
@@ -122,15 +122,16 @@ begin
MyWorksheet.WriteFont(8, 3, 'Courier New', 12, [fssUnderline], scBlue);
MyWorksheet.WriteBackgroundColor(8, 3, scYellow);
-{ Uncomment this to test large XLS files
- for i := 2 to 20 do
+
+ // Uncomment this to test large XLS files
+ for i := 40 to 1000 do
begin
- MyWorksheet.WriteAnsiText(i, 0, ParamStr(0));
- MyWorksheet.WriteAnsiText(i, 1, ParamStr(0));
- MyWorksheet.WriteAnsiText(i, 2, ParamStr(0));
- MyWorksheet.WriteAnsiText(i, 3, ParamStr(0));
+// MyWorksheet.WriteUTF8Text(i, 0, ParamStr(0));
+// MyWorksheet.WriteUTF8Text(i, 1, ParamStr(0));
+// MyWorksheet.WriteUTF8Text(i, 2, ParamStr(0));
+ MyWorksheet.WriteUTF8Text(i, 3, ParamStr(0));
end;
-}
+
// Write the formula E1 = A1 + B1
SetLength(MyRPNFormula, 3);
@@ -209,17 +210,15 @@ begin
MyWorksheet.WriteUTF8Text(37, 0, 'nfTimeInterval');
MyWorksheet.WriteDateTime(37, 1, number, nfTimeInterval);
- // Set width of columns 1 and 5
- lCol.Width := 30;
+ // Set width of columns 0, 1 and 5
+ MyWorksheet.WriteColWidth(0, 25);
+ lCol.Width := 20;
MyWorksheet.WriteColInfo(1, lCol);
lCol.Width := 5;
MyWorksheet.WriteColInfo(5, lCol);
- // Set height of rows 5 and 6
- lRow.Height := 10;
- MyWorksheet.WriteRowInfo(5, lRow);
- lRow.Height := 5;
- MyWorksheet.WriteRowInfo(6, lRow);
+ // Set height of rows 0
+ MyWorksheet.WriteRowHeight(0, 30); // 30 mm
// Creates a new worksheet
MyWorksheet := MyWorkbook.AddWorksheet(Str_Worksheet2);
diff --git a/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi b/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi
index 57cce23ec..fb3d43d42 100644
--- a/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi
+++ b/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi
@@ -127,11 +127,10 @@
-
-
+
@@ -139,7 +138,7 @@
-
+
@@ -149,10 +148,11 @@
+
-
-
+
+
@@ -222,7 +222,6 @@
-
@@ -230,7 +229,6 @@
-
@@ -252,12 +250,10 @@
-
-
@@ -269,7 +265,7 @@
-
+
@@ -294,17 +290,17 @@
-
+
-
-
+
+
-
+
@@ -314,7 +310,7 @@
-
+
@@ -332,12 +328,10 @@
-
-
@@ -357,143 +351,139 @@
-
-
-
-
-
-
-
-
+
+
+
+
-
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
-
+
-
-
-
-
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
+
+
+
+
-
+
-
-
+
+
-
+
-
+
-
+
-
-
+
+
diff --git a/components/fpspreadsheet/examples/fpsgrid/mainform.lfm b/components/fpspreadsheet/examples/fpsgrid/mainform.lfm
index ba4b318f4..ec5f4582e 100644
--- a/components/fpspreadsheet/examples/fpsgrid/mainform.lfm
+++ b/components/fpspreadsheet/examples/fpsgrid/mainform.lfm
@@ -4,7 +4,7 @@ object Form1: TForm1
Top = 258
Width = 518
Caption = 'fpsGrid'
- ClientHeight = 366
+ ClientHeight = 361
ClientWidth = 518
Menu = MainMenu1
OnActivate = FormActivate
@@ -12,19 +12,19 @@ object Form1: TForm1
LCLVersion = '1.3'
object Panel1: TPanel
Left = 0
- Height = 70
- Top = 296
+ Height = 73
+ Top = 288
Width = 518
Align = alBottom
BevelOuter = bvNone
- ClientHeight = 70
+ ClientHeight = 73
ClientWidth = 518
TabOrder = 0
object btnPopulateGrid: TButton
- Left = 400
- Height = 25
- Top = 13
- Width = 112
+ Left = 392
+ Height = 31
+ Top = 24
+ Width = 120
Caption = 'Populate Grid'
OnClick = btnPopulateGridClick
TabOrder = 0
@@ -32,9 +32,9 @@ object Form1: TForm1
end
object CbShowHeaders: TCheckBox
Left = 8
- Height = 19
- Top = 8
- Width = 93
+ Height = 24
+ Top = 11
+ Width = 116
Caption = 'Show headers'
Checked = True
OnClick = CbShowHeadersClick
@@ -43,9 +43,9 @@ object Form1: TForm1
end
object CbShowGridLines: TCheckBox
Left = 8
- Height = 19
- Top = 29
- Width = 100
+ Height = 24
+ Top = 36
+ Width = 125
Caption = 'Show grid lines'
Checked = True
OnClick = CbShowGridLinesClick
@@ -53,35 +53,35 @@ object Form1: TForm1
TabOrder = 2
end
object EdFrozenCols: TSpinEdit
- Left = 208
- Height = 23
+ Left = 238
+ Height = 28
Top = 8
Width = 52
OnChange = EdFrozenColsChange
TabOrder = 3
end
object EdFrozenRows: TSpinEdit
- Left = 208
- Height = 23
- Top = 36
+ Left = 238
+ Height = 28
+ Top = 39
Width = 52
OnChange = EdFrozenRowsChange
TabOrder = 4
end
object Label1: TLabel
- Left = 135
- Height = 15
+ Left = 152
+ Height = 20
Top = 13
- Width = 62
+ Width = 77
Caption = 'Frozen cols:'
FocusControl = EdFrozenCols
ParentColor = False
end
object Label2: TLabel
- Left = 136
- Height = 15
- Top = 39
- Width = 66
+ Left = 153
+ Height = 20
+ Top = 40
+ Width = 82
Caption = 'Frozen rows:'
FocusControl = EdFrozenRows
ParentColor = False
@@ -89,7 +89,7 @@ object Form1: TForm1
end
object PageControl1: TPageControl
Left = 0
- Height = 270
+ Height = 262
Top = 26
Width = 518
ActivePage = TabSheet1
@@ -99,17 +99,24 @@ object Form1: TForm1
OnChange = PageControl1Change
object TabSheet1: TTabSheet
Caption = 'Sheet1'
- ClientHeight = 242
+ ClientHeight = 229
ClientWidth = 510
object sWorksheetGrid1: TsWorksheetGrid
Left = 0
- Height = 242
+ Height = 229
Top = 0
Width = 510
Align = alClient
+ ColCount = 2
+ ExtendedSelect = False
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goRowSizing, goColSizing, goThumbTracking, goSmoothScroll, goFixedColSizing]
+ RowCount = 2
TabOrder = 0
TitleStyle = tsNative
+ ColWidths = (
+ 56
+ 64
+ )
end
end
end
diff --git a/components/fpspreadsheet/examples/fpsgrid/mainform.lrs b/components/fpspreadsheet/examples/fpsgrid/mainform.lrs
index 65910124a..c59c1159a 100644
--- a/components/fpspreadsheet/examples/fpsgrid/mainform.lrs
+++ b/components/fpspreadsheet/examples/fpsgrid/mainform.lrs
@@ -2,37 +2,38 @@
LazarusResources.Add('TForm1','FORMDATA',[
'TPF0'#6'TForm1'#5'Form1'#4'Left'#3'r'#1#6'Height'#3#130#1#3'Top'#3#2#1#5'Wid'
- +'th'#3#6#2#7'Caption'#6#7'fpsGrid'#12'ClientHeight'#3'n'#1#11'ClientWidth'#3
+ +'th'#3#6#2#7'Caption'#6#7'fpsGrid'#12'ClientHeight'#3'i'#1#11'ClientWidth'#3
+#6#2#4'Menu'#7#9'MainMenu1'#10'OnActivate'#7#12'FormActivate'#8'ShowHint'#9
- +#10'LCLVersion'#6#3'1.3'#0#6'TPanel'#6'Panel1'#4'Left'#2#0#6'Height'#2'F'#3
- +'Top'#3'('#1#5'Width'#3#6#2#5'Align'#7#8'alBottom'#10'BevelOuter'#7#6'bvNone'
- +#12'ClientHeight'#2'F'#11'ClientWidth'#3#6#2#8'TabOrder'#2#0#0#7'TButton'#15
- +'btnPopulateGrid'#4'Left'#3#144#1#6'Height'#2#25#3'Top'#2#13#5'Width'#2'p'#7
+ +#10'LCLVersion'#6#3'1.3'#0#6'TPanel'#6'Panel1'#4'Left'#2#0#6'Height'#2'I'#3
+ +'Top'#3' '#1#5'Width'#3#6#2#5'Align'#7#8'alBottom'#10'BevelOuter'#7#6'bvNone'
+ +#12'ClientHeight'#2'I'#11'ClientWidth'#3#6#2#8'TabOrder'#2#0#0#7'TButton'#15
+ +'btnPopulateGrid'#4'Left'#3#136#1#6'Height'#2#31#3'Top'#2#24#5'Width'#2'x'#7
+'Caption'#6#13'Populate Grid'#7'OnClick'#7#20'btnPopulateGridClick'#8'TabOrd'
+'er'#2#0#7'Visible'#8#0#0#9'TCheckBox'#13'CbShowHeaders'#4'Left'#2#8#6'Heigh'
- +'t'#2#19#3'Top'#2#8#5'Width'#2']'#7'Caption'#6#12'Show headers'#7'Checked'#9
+ +'t'#2#24#3'Top'#2#11#5'Width'#2't'#7'Caption'#6#12'Show headers'#7'Checked'#9
+#7'OnClick'#7#18'CbShowHeadersClick'#5'State'#7#9'cbChecked'#8'TabOrder'#2#1
- +#0#0#9'TCheckBox'#15'CbShowGridLines'#4'Left'#2#8#6'Height'#2#19#3'Top'#2#29
- +#5'Width'#2'd'#7'Caption'#6#15'Show grid lines'#7'Checked'#9#7'OnClick'#7#20
+ +#0#0#9'TCheckBox'#15'CbShowGridLines'#4'Left'#2#8#6'Height'#2#24#3'Top'#2'$'
+ +#5'Width'#2'}'#7'Caption'#6#15'Show grid lines'#7'Checked'#9#7'OnClick'#7#20
+'CbShowGridLinesClick'#5'State'#7#9'cbChecked'#8'TabOrder'#2#2#0#0#9'TSpinEd'
- +'it'#12'EdFrozenCols'#4'Left'#3#208#0#6'Height'#2#23#3'Top'#2#8#5'Width'#2'4'
+ +'it'#12'EdFrozenCols'#4'Left'#3#238#0#6'Height'#2#28#3'Top'#2#8#5'Width'#2'4'
+#8'OnChange'#7#18'EdFrozenColsChange'#8'TabOrder'#2#3#0#0#9'TSpinEdit'#12'Ed'
- +'FrozenRows'#4'Left'#3#208#0#6'Height'#2#23#3'Top'#2'$'#5'Width'#2'4'#8'OnCh'
- +'ange'#7#18'EdFrozenRowsChange'#8'TabOrder'#2#4#0#0#6'TLabel'#6'Label1'#4'Le'
- +'ft'#3#135#0#6'Height'#2#15#3'Top'#2#13#5'Width'#2'>'#7'Caption'#6#12'Frozen'
- +' cols:'#12'FocusControl'#7#12'EdFrozenCols'#11'ParentColor'#8#0#0#6'TLabel'
- +#6'Label2'#4'Left'#3#136#0#6'Height'#2#15#3'Top'#2''''#5'Width'#2'B'#7'Capti'
- +'on'#6#12'Frozen rows:'#12'FocusControl'#7#12'EdFrozenRows'#11'ParentColor'#8
- +#0#0#0#12'TPageControl'#12'PageControl1'#4'Left'#2#0#6'Height'#3#14#1#3'Top'
- +#2#26#5'Width'#3#6#2#10'ActivePage'#7#9'TabSheet1'#5'Align'#7#8'alClient'#8
- +'TabIndex'#2#0#8'TabOrder'#2#1#8'OnChange'#7#18'PageControl1Change'#0#9'TTab'
- +'Sheet'#9'TabSheet1'#7'Caption'#6#6'Sheet1'#12'ClientHeight'#3#242#0#11'Clie'
- +'ntWidth'#3#254#1#0#15'TsWorksheetGrid'#15'sWorksheetGrid1'#4'Left'#2#0#6'He'
- +'ight'#3#242#0#3'Top'#2#0#5'Width'#3#254#1#5'Align'#7#8'alClient'#7'Options'
- +#11#15'goFixedVertLine'#15'goFixedHorzLine'#10'goVertLine'#10'goHorzLine'#13
- +'goRangeSelect'#11'goRowSizing'#11'goColSizing'#15'goThumbTracking'#14'goSmo'
- +'othScroll'#16'goFixedColSizing'#0#8'TabOrder'#2#0#10'TitleStyle'#7#8'tsNati'
- +'ve'#0#0#0#0#8'TToolBar'#8'ToolBar1'#4'Left'#2#0#6'Height'#2#26#3'Top'#2#0#5
+ +'FrozenRows'#4'Left'#3#238#0#6'Height'#2#28#3'Top'#2''''#5'Width'#2'4'#8'OnC'
+ +'hange'#7#18'EdFrozenRowsChange'#8'TabOrder'#2#4#0#0#6'TLabel'#6'Label1'#4'L'
+ +'eft'#3#152#0#6'Height'#2#20#3'Top'#2#13#5'Width'#2'M'#7'Caption'#6#12'Froze'
+ +'n cols:'#12'FocusControl'#7#12'EdFrozenCols'#11'ParentColor'#8#0#0#6'TLabel'
+ +#6'Label2'#4'Left'#3#153#0#6'Height'#2#20#3'Top'#2'('#5'Width'#2'R'#7'Captio'
+ +'n'#6#12'Frozen rows:'#12'FocusControl'#7#12'EdFrozenRows'#11'ParentColor'#8
+ +#0#0#0#12'TPageControl'#12'PageControl1'#4'Left'#2#0#6'Height'#3#6#1#3'Top'#2
+ +#26#5'Width'#3#6#2#10'ActivePage'#7#9'TabSheet1'#5'Align'#7#8'alClient'#8'Ta'
+ +'bIndex'#2#0#8'TabOrder'#2#1#8'OnChange'#7#18'PageControl1Change'#0#9'TTabSh'
+ +'eet'#9'TabSheet1'#7'Caption'#6#6'Sheet1'#12'ClientHeight'#3#229#0#11'Client'
+ +'Width'#3#254#1#0#15'TsWorksheetGrid'#15'sWorksheetGrid1'#4'Left'#2#0#6'Heig'
+ +'ht'#3#229#0#3'Top'#2#0#5'Width'#3#254#1#5'Align'#7#8'alClient'#8'ColCount'#2
+ +#2#14'ExtendedSelect'#8#7'Options'#11#15'goFixedVertLine'#15'goFixedHorzLine'
+ +#10'goVertLine'#10'goHorzLine'#13'goRangeSelect'#11'goRowSizing'#11'goColSiz'
+ +'ing'#15'goThumbTracking'#14'goSmoothScroll'#16'goFixedColSizing'#0#8'RowCou'
+ +'nt'#2#2#8'TabOrder'#2#0#10'TitleStyle'#7#8'tsNative'#9'ColWidths'#1#2'8'#2
+ +'@'#0#0#0#0#0#8'TToolBar'#8'ToolBar1'#4'Left'#2#0#6'Height'#2#26#3'Top'#2#0#5
+'Width'#3#6#2#12'ButtonHeight'#2#24#7'Caption'#6#8'ToolBar1'#11'EdgeBorders'
+#11#0#6'Images'#7#10'ImageList1'#8'TabOrder'#2#2#0#11'TToolButton'#11'ToolBu'
+'tton1'#4'Left'#2#1#3'Top'#2#0#6'Action'#7#6'AcOpen'#0#0#11'TToolButton'#11
@@ -64,8 +65,8 @@ LazarusResources.Add('TForm1','FORMDATA',[
+#248#255#137#227#248#255#130#225#247#255'z'#223#247#255'q'#222#246#255'g'#219
+#245#255'['#216#244#255'M'#212#243#255'@'#209#242#255#202#242#251#255'5'#148
+#218#255#255#255#255#0#255#255#255#0'6'#154#218#248#242#250#253#255#148#230
- +#248#255#146#229#248#255#144#229#248#255#139#227#248#255#134#226#247#255#127
- ,#225#247#255'w'#222#246#255'l'#220#246#255'^'#217#244#255'O'#213#243#255#204
+ ,#248#255#146#229#248#255#144#229#248#255#139#227#248#255#134#226#247#255#127
+ +#225#247#255'w'#222#246#255'l'#220#246#255'^'#217#244#255'O'#213#243#255#204
+#242#251#255'5'#148#218#255#255#255#255#0#255#255#255#0'6'#161#218#249#246
+#252#254#255#148#229#248#255#147#229#248#255#147#229#248#255#145#229#248#255
+#147#219#233#255#147#215#227#255#147#210#220#255#144#206#215#255#140#200#207
@@ -128,8 +129,8 @@ LazarusResources.Add('TForm1','FORMDATA',[
+#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248#255#254#251#248
+#255#254#251#248#255#254#251#248#255#254#251#248#255#211#150'm'#255#210#167
+#138#255#171'b2'#255#187'j6'#255#240#210#190#255#226#163'z'#255#226#163'z'
- +#255#225#163'z'#255#226#163'{'#255#225#163'{'#255#224#161'x'#255#222#159'w'
- ,#255#221#159'v'#255#220#157't'#255#217#155'r'#255#216#153'q'#255#214#153'p'
+ ,#255#225#163'z'#255#226#163'{'#255#225#163'{'#255#224#161'x'#255#222#159'w'
+ +#255#221#159'v'#255#220#157't'#255#217#155'r'#255#216#153'q'#255#214#153'p'
+#255#213#171#142#255#173'c3'#255#187'j6'#255#242#213#194#255#227#163'z'#255
+#227#163'z'#255#226#163'{'#255#226#163'{'#255#226#164'{'#255#225#162'y'#255
+#224#161'x'#255#222#160'w'#255#222#158'u'#255#220#157't'#255#218#155's'#255
@@ -192,8 +193,8 @@ LazarusResources.Add('TForm1','FORMDATA',[
+#145'K'#255'?'#141'H'#255'='#137'E'#255']'#164'e'#255'Z'#160'a'#255'E'#131'K'
+#255#158#158#158#255#158#158#158#255'`'#146#201#255#158#199#226#255#131#184
+#218#255'}'#180#215#255'~'#179#215#255'O'#137#180#255';y'#177#234#255#255#255
- +#0#255#255#255#0'www'#255#154#154#154#255'='#138'E'#255'I'#138'O'#255#156#156
- ,#156#255#157#157#157#255#157#157#157#255'f'#150#204#255#162#203#227#255#137
+ ,#0#255#255#255#0'www'#255#154#154#154#255'='#138'E'#255'I'#138'O'#255#156#156
+ +#156#255#157#157#157#255#157#157#157#255'f'#150#204#255#162#203#227#255#137
+#189#220#255#131#185#218#255#132#185#218#255'Q'#139#181#255'C~'#182#234#255
+#255#255#0#255#255#255#0'zzz'#255#153#153#153#255'R'#145'Y'#255#153#154#153
+#255#155#155#155#255#156#156#156#255#156#156#156#255'l'#154#208#255#167#206
@@ -256,8 +257,8 @@ LazarusResources.Add('TForm1','FORMDATA',[
+#255'l'#220#246#255'^'#217#244#255'O'#213#243#255#204#242#251#255'5'#148#218
+#255#255#255#255#0#255#255#255#0'5'#148#218#247#239#250#254#255#147#229#248
+#255#143#228#248#255#137#227#248#255#130#225#247#255'z'#223#247#255'q'#222
- +#246#255'g'#219#245#255'['#216#244#255'M'#212#243#255'@'#209#242#255#202#242
- ,#251#255'5'#148#218#255#255#255#255#0#255#255#255#0'3'#142#217#251#220#240
+ ,#246#255'g'#219#245#255'['#216#244#255'M'#212#243#255'@'#209#242#255#202#242
+ +#251#255'5'#148#218#255#255#255#255#0#255#255#255#0'3'#142#217#251#220#240
+#250#255#152#225#246#255#149#224#246#255#146#223#246#255#142#222#245#255#137
+#220#245#255#133#218#244#255#128#217#244#255'z'#215#243#255't'#213#243#255'p'
+#211#242#255#194#234#248#255'5'#148#218#255#255#255#255#0#255#255#255#0','
@@ -320,8 +321,8 @@ LazarusResources.Add('TForm1','FORMDATA',[
+#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255
+#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0'p'#158#214#219
+'m'#156#212#255#133#177#218#255'Z'#145#185#255'`'#147#203#234#255#255#255#0
- +#255#255#255#0#128#128#128#255'~~~'#255'|||'#255'zzz'#255'www'#255'uuu'#255
- ,'rrr'#255'q'#158#212#255'o'#158#214#255#135#178#220#255#171#211#232#255#169
+ ,#255#255#255#0#128#128#128#255'~~~'#255'|||'#255'zzz'#255'www'#255'uuu'#255
+ +'rrr'#255'q'#158#212#255'o'#158#214#255#135#178#220#255#171#211#232#255#169
+#208#230#255'X'#144#184#255'Y'#142#198#234#255#255#255#0#255#255#255#0'}}}'
+#255#153#153#153#255#153#153#153#255#154#154#154#255#154#154#154#255#155#155
+#155#255#155#155#155#255'o'#157#211#255#170#209#231#255#171#209#231#255#152
diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas
index fadb034f2..cd056e275 100755
--- a/components/fpspreadsheet/fpspreadsheet.pas
+++ b/components/fpspreadsheet/fpspreadsheet.pas
@@ -290,7 +290,6 @@ type
TRow = record
Row: Cardinal;
Height: Single; // in millimeters
- AutoHeight: Boolean; // true: height corresponds to font; false: use Height
end;
PRow = ^TRow;
@@ -337,6 +336,8 @@ type
function GetCellCount: Cardinal;
function GetFirstCell(): PCell;
function GetNextCell(): PCell;
+ function GetFirstCellOfRow(ARow: Cardinal): PCell;
+ function GetLastCellOfRow(ARow: Cardinal): PCell;
function GetLastColNumber: Cardinal;
function GetLastRowNumber: Cardinal;
function ReadAsUTF8Text(ARow, ACol: Cardinal): ansistring;
@@ -385,6 +386,7 @@ type
procedure RemoveAllRows;
procedure RemoveAllCols;
procedure WriteRowInfo(ARow: Cardinal; AData: TRow);
+ procedure WriteRowHeight(ARow: Cardinal; AHeight: Single);
procedure WriteColInfo(ACol: Cardinal; AData: TCol);
procedure WriteColWidth(ACol: Cardinal; AWidth: Single);
{ Properties }
@@ -1014,6 +1016,32 @@ begin
end;
end;
+function TsWorksheet.GetFirstCellOfRow(ARow: Cardinal): PCell;
+var
+ c, n: Cardinal;
+begin
+ n := GetLastColNumber;
+ c := 0;
+ Result := FindCell(ARow, c);
+ while (result = nil) and (c < n) do begin
+ inc(c);
+ result := FindCell(ARow, c);
+ end;
+end;
+
+function TsWorksheet.GetLastCellOfRow(ARow: Cardinal): PCell;
+var
+ c, n: Cardinal;
+begin
+ n := GetLastColNumber;
+ c := n;
+ Result := FindCell(ARow, c);
+ while (Result = nil) and (c > 0) do begin
+ dec(c);
+ Result := FindCell(ARow, c);
+ end;
+end;
+
{@@
Returns the 0-based number of the last row with a cell with contents.
@@ -1624,14 +1652,10 @@ end;
function TsWorksheet.GetRow(ARow: Cardinal): PRow;
begin
Result := FindRow(ARow);
-
- if (Result = nil) then
- begin
+ if (Result = nil) then begin
Result := GetMem(SizeOf(TRow));
FillChar(Result^, SizeOf(TRow), #0);
-
Result^.Row := ARow;
-
FRows.Add(Result);
end;
end;
@@ -1639,14 +1663,10 @@ end;
function TsWorksheet.GetCol(ACol: Cardinal): PCol;
begin
Result := FindCol(ACol);
-
- if (Result = nil) then
- begin
+ if (Result = nil) then begin
Result := GetMem(SizeOf(TCol));
FillChar(Result^, SizeOf(TCol), #0);
-
Result^.Col := ACol;
-
FCols.Add(Result);
end;
end;
@@ -1656,8 +1676,7 @@ var
Node: Pointer;
i: Integer;
begin
- for i := FRows.Count-1 downto 0 do
- begin
+ for i := FRows.Count-1 downto 0 do begin
Node := FRows.Items[i];
FreeMem(Node, SizeOf(TRow));
end;
@@ -1669,8 +1688,7 @@ var
Node: Pointer;
i: Integer;
begin
- for i := FCols.Count-1 downto 0 do
- begin
+ for i := FCols.Count-1 downto 0 do begin
Node := FCols.Items[i];
FreeMem(Node, SizeOf(TCol));
end;
@@ -1685,6 +1703,14 @@ begin
AElement^.Height := AData.Height;
end;
+procedure TsWorksheet.WriteRowHeight(ARow: Cardinal; AHeight: Single);
+var
+ AElement: PRow;
+begin
+ AElement := GetRow(ARow);
+ AElement^.Height := AHeight;
+end;
+
procedure TsWorksheet.WriteColInfo(ACol: Cardinal; AData: TCol);
var
AElement: PCol;
diff --git a/components/fpspreadsheet/fpspreadsheetgrid.pas b/components/fpspreadsheet/fpspreadsheetgrid.pas
index 6bc469314..ddce9c575 100644
--- a/components/fpspreadsheet/fpspreadsheetgrid.pas
+++ b/components/fpspreadsheet/fpspreadsheetgrid.pas
@@ -876,7 +876,7 @@ begin
end;
for i := FHeaderCount to RowCount-1 do begin
lRow := FWorksheet.FindRow(i - FHeaderCount);
- if (lRow = nil) or lRow^.AutoHeight then
+ if (lRow = nil) then
RowHeights[i] := CalcAutoRowHeight(i)
else
RowHeights[i] := CalcRowHeight(lRow^.Height);
diff --git a/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas b/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas
index 75f4354ac..a61e0a934 100644
--- a/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas
+++ b/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas
@@ -535,7 +535,7 @@ begin
s := '$0005=WB globals, $0006=VB module, ' + s + ', $0100=Workspace';
w := WordLEToN(w);
if Row = FCurrRow then begin
- FDetails.Add('Type of data:');
+ FDetails.Add('Type of data:'#13);
FDetails.Add(Format('$%.4x = %s', [w, BofName(w)]));
end;
ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.4x', [w]),
@@ -906,7 +906,6 @@ begin
ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(DWordLEToN(dw)),
'Index to first used row');
- numBytes := 4;
Move(FBuffer[FBufferIndex], dw, numBytes);
ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(DWordLEToN(dw)),
'Index to last used row, increased by 1');
@@ -916,7 +915,6 @@ begin
ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)),
'Index to first used row');
- numBytes := 2;
Move(FBuffer[FBufferIndex], w, numBytes);
ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)),
'Index to last used row, increased by 1');
@@ -932,9 +930,11 @@ begin
ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)),
'Index to last used column, increased by 1');
- numBytes := 2;
- ShowInRow(FCurrRow, FBufferIndex, numBytes, '',
- '(not used)');
+ if FFormat <> sfExcel2 then begin
+ numBytes := 2;
+ ShowInRow(FCurrRow, FBufferIndex, numBytes, '',
+ '(not used)');
+ end;
end;
@@ -2714,7 +2714,17 @@ begin
numBytes := 2;
Move(FBuffer[FBufferIndex], w, numbytes);
- ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.4x', [WordLEToN(w)]),
+ w := WordLEToN(w);
+ if Row = FCurrRow then begin
+ FDetails.Add('Row height:'#13);
+ FDetails.Add(Format('Bits 14-0 = %d: Row height in twips (1/20 pt) --> %.1f-pt',
+ [w and $7FFF, (w and $7FFF)/20.0])
+ );
+ if w and $8000 = 0
+ then FDetails.Add('Bit 15 = 0: Row has custom height')
+ else FDetails.Add('Bit 15 = 1: Row has default height');
+ end;
+ ShowInRow(FCurrRow, FBufferIndex, numBytes, Format('$%.4x', [w]),
'Bits 14-0: Height of row in twips (1/20 pt), Bit 15: Row has default height');
numBytes := 2;
diff --git a/components/fpspreadsheet/reference/BIFFExplorer/bemain.pas b/components/fpspreadsheet/reference/BIFFExplorer/bemain.pas
index 9d71f403a..f2dbcbd24 100644
--- a/components/fpspreadsheet/reference/BIFFExplorer/bemain.pas
+++ b/components/fpspreadsheet/reference/BIFFExplorer/bemain.pas
@@ -720,7 +720,6 @@ end;
procedure TMainForm.LoadFile(const AFileName: String);
var
- fmt: TsSpreadsheetFormat;
valid: Boolean;
excptn: Exception = nil;
begin
@@ -735,19 +734,19 @@ begin
exit;
end;
- fmt := sfExcel8;
+ FFormat := sfExcel8;
while True do begin
try
- LoadFile(AFileName, fmt);
+ LoadFile(AFileName, FFormat);
valid := True;
except
on E: Exception do begin
- if fmt = sfExcel8 then excptn := E;
+ if FFormat = sfExcel8 then excptn := E;
valid := False
end;
end;
- if valid or (fmt = sfExcel2) then Break;
- fmt := Pred(fmt);
+ if valid or (FFormat = sfExcel2) then Break;
+ FFormat := Pred(FFormat);
end;
// A failed attempt to read a file should bring an exception, so re-raise
@@ -755,8 +754,6 @@ begin
// since this is the most common format
if (not valid) and (excptn <> nil) then
raise excptn;
-
- FFormat := fmt;
end;
@@ -793,7 +790,9 @@ begin
FFileName := ExpandFileName(AFileName);
ReadFromStream(MemStream);
+ FFormat := AFormat;
UpdateCaption;
+
FMRUMenuManager.AddToRecent(AFileName);
end;
@@ -1062,9 +1061,9 @@ begin
while AStream.Position < AStream.Size do begin
p := AStream.Position;
recType := WordLEToN(AStream.ReadWord);
- if recType = 0 then
- break;
recSize := WordLEToN(AStream.ReadWord);
+ if (recType = 0) and (recSize = 0) then
+ break;
s := RecTypeName(recType);
i := pos(':', s);
// in case of BOF record: create new parent node for this substream
diff --git a/components/fpspreadsheet/tests/formattests.pas b/components/fpspreadsheet/tests/formattests.pas
index a3da9ffe0..c0406372d 100644
--- a/components/fpspreadsheet/tests/formattests.pas
+++ b/components/fpspreadsheet/tests/formattests.pas
@@ -29,6 +29,7 @@ var
SollDateTimeFormatStrings: array[0..9] of String;
SollColWidths: array[0..1] of Single;
+ SollRowHeights: Array[0..2] of Single;
SollBorders: array[0..15] of TsCellBorders;
SollBorderLineStyles: array[0..6] of TsLineStyle;
SollBorderColors: array[0..5] of TsColor;
@@ -53,6 +54,8 @@ type
procedure TestWriteReadBorderStyles(AFormat: TsSpreadsheetFormat);
// Test column widths
procedure TestWriteReadColWidths(AFormat: TsSpreadsheetFormat);
+ // Test row heights
+ procedure TestWriteReadRowHeights(AFormat: TsSpreadsheetFormat);
// Test text rotation
procedure TestWriteReadTextRotation(AFormat:TsSpreadsheetFormat);
// Test word wrapping
@@ -70,6 +73,7 @@ type
procedure TestWriteReadBIFF2_Alignment;
procedure TestWriteReadBIFF2_Border;
procedure TestWriteReadBIFF2_ColWidths;
+ procedure TestWriteReadBIFF2_RowHeights;
procedure TestWriteReadBIFF2_DateTimeFormats;
procedure TestWriteReadBIFF2_NumberFormats;
// These features are not supported by Excel2 --> no test cases required!
@@ -82,6 +86,7 @@ type
procedure TestWriteReadBIFF5_Border;
procedure TestWriteReadBIFF5_BorderStyles;
procedure TestWriteReadBIFF5_ColWidths;
+ procedure TestWriteReadBIFF5_RowHeights;
procedure TestWriteReadBIFF5_DateTimeFormats;
procedure TestWriteReadBIFF5_NumberFormats;
procedure TestWriteReadBIFF5_TextRotation;
@@ -92,6 +97,7 @@ type
procedure TestWriteReadBIFF8_Border;
procedure TestWriteReadBIFF8_BorderStyles;
procedure TestWriteReadBIFF8_ColWidths;
+ procedure TestWriteReadBIFF8_RowHeights;
procedure TestWriteReadBIFF8_DateTimeFormats;
procedure TestWriteReadBIFF8_NumberFormats;
procedure TestWriteReadBIFF8_TextRotation;
@@ -101,12 +107,13 @@ type
implementation
uses
- TypInfo;
+ TypInfo, fpsutils;
const
FmtNumbersSheet = 'NumbersFormat'; //let's distinguish it from the regular numbers sheet
FmtDateTimesSheet = 'DateTimesFormat';
ColWidthSheet = 'ColWidths';
+ RowHeightSheet = 'RowHeights';
BordersSheet = 'CellBorders';
AlignmentSheet = 'TextAlignments';
TextRotationSheet = 'TextRotation';
@@ -189,6 +196,11 @@ begin
SollColWidths[0] := 20; // characters based on width of "0"
SollColWidths[1] := 40;
+ // Row heights
+ SollRowHeights[0] := 5;
+ SollRowHeights[1] := 10;
+ SollRowHeights[2] := 50;
+
// Cell borders
SollBorders[0] := [];
SollBorders[1] := [cbEast];
@@ -672,7 +684,8 @@ begin
if lpCol = nil then
fail('Error in test code. Failed to return saved column width');
ActualColWidth := lpCol^.Width;
- CheckEquals(SollColWidths[Col], ActualColWidth, 'Test saved colwidth mismatch column '+ColNotation(MyWorkSheet,Col));
+ CheckEquals(SollColWidths[Col], ActualColWidth,
+ 'Test saved colwidth mismatch, column '+ColNotation(MyWorkSheet,Col));
end;
// Finalization
MyWorkbook.Free;
@@ -695,6 +708,68 @@ begin
TestWriteReadColWidths(sfExcel8);
end;
+procedure TSpreadWriteReadFormatTests.TestWriteReadRowHeights(AFormat: TsSpreadsheetFormat);
+var
+ MyWorksheet: TsWorksheet;
+ MyWorkbook: TsWorkbook;
+ ActualRowHeight: Single;
+ Row: Integer;
+ lpRow: PRow;
+ 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
+ MyWorkbook := TsWorkbook.Create;
+ MyWorkSheet:= MyWorkBook.AddWorksheet(RowHeightSheet);
+ for Row := Low(SollRowHeights) to High(SollRowHeights) do
+ MyWorksheet.WriteRowHeight(Row, SollRowHeights[Row]);
+ MyWorkBook.WriteToFile(TempFile, AFormat, true);
+ MyWorkbook.Free;
+
+ // Open the spreadsheet, as biff8
+ MyWorkbook := TsWorkbook.Create;
+ MyWorkbook.ReadFromFile(TempFile, AFormat);
+ if AFormat = sfExcel2 then
+ MyWorksheet := MyWorkbook.GetFirstWorksheet
+ else
+ MyWorksheet := GetWorksheetByName(MyWorkBook, RowHeightSheet);
+ if MyWorksheet=nil then
+ fail('Error in test code. Failed to get named worksheet');
+ for Row := Low(SollRowHeights) to High(SollRowHeights) do begin
+ lpRow := MyWorksheet.GetRow(Row);
+ if lpRow = nil then
+ fail('Error in test code. Failed to return saved row height');
+ // Rounding to twips in Excel would cause severe rounding error if we'd compare millimeters
+ // --> go back to twips
+ ActualRowHeight := MillimetersToTwips(lpRow^.Height);
+ CheckEquals(MillimetersToTwips(SollRowHeights[Row]), ActualRowHeight,
+ 'Test saved row height mismatch, row '+RowNotation(MyWorkSheet,Row));
+ end;
+ // Finalization
+ MyWorkbook.Free;
+
+ DeleteFile(TempFile);
+end;
+
+procedure TSpreadWriteReadFormatTests.TestWriteReadBIFF2_RowHeights;
+begin
+ TestWriteReadRowHeights(sfExcel2);
+end;
+
+procedure TSpreadWriteReadFormatTests.TestWriteReadBIFF5_RowHeights;
+begin
+ TestWriteReadRowHeights(sfExcel5);
+end;
+
+procedure TSpreadWriteReadFormatTests.TestWriteReadBIFF8_RowHeights;
+begin
+ TestWriteReadRowHeights(sfExcel8);
+end;
+
procedure TSpreadWriteReadFormatTests.TestWriteReadTextRotation(AFormat: TsSpreadsheetFormat);
const
col = 0;
diff --git a/components/fpspreadsheet/tests/spreadtestgui.lpi b/components/fpspreadsheet/tests/spreadtestgui.lpi
index 1f365e8f6..ddd31284d 100644
--- a/components/fpspreadsheet/tests/spreadtestgui.lpi
+++ b/components/fpspreadsheet/tests/spreadtestgui.lpi
@@ -37,7 +37,6 @@
-
diff --git a/components/fpspreadsheet/tests/testsutility.pas b/components/fpspreadsheet/tests/testsutility.pas
index 9d31c9bb9..2418881cf 100644
--- a/components/fpspreadsheet/tests/testsutility.pas
+++ b/components/fpspreadsheet/tests/testsutility.pas
@@ -28,6 +28,9 @@ function CellNotation(WorkSheet: TsWorksheet; Row: integer; Column: integer=0):
// Returns an A notation of column based on sheet and column
function ColNotation(WorkSheet: TsWorksheet; Column:Integer): String;
+// Returns a notation for row bassed on sheet and row
+function RowNotation(Worksheet: TsWorksheet; Row: Integer): String;
+
// Note: using this function instead of GetWorkSheetByName for compatibility with
// older fpspreadsheet versions that don't have that function
function GetWorksheetByName(AWorkBook: TsWorkBook; AName: String): TsWorksheet;
@@ -97,5 +100,13 @@ begin
Result := WorkSheet.Name + '!' + ColumnToLetter(Column);
end;
+function RowNotation(Worksheet: TsWorksheet; Row: Integer): String;
+begin
+ if not Assigned(Worksheet) then
+ Result := 'RowNotation: error getting worksheet.'
+ else
+ Result := Worksheet.Name + '!' + IntToStr(Row+1);
+end;
+
end.
diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas
index d8c52dbcb..014d67267 100755
--- a/components/fpspreadsheet/xlsbiff2.pas
+++ b/components/fpspreadsheet/xlsbiff2.pas
@@ -89,13 +89,15 @@ type
AddBackground: Boolean = false);
procedure WriteXFFieldsForFormattingStyles(AStream: TStream);
procedure WriteXFRecords(AStream: TStream);
- procedure WriteWindow1(AStream: TStream); override;
- procedure WriteWindow2(AStream: TStream; ASheet: TsWorksheet);
protected
procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal; ACell: PCell); override;
procedure WriteRPNFormula(AStream: TStream; const ARow, ACol: Cardinal; const AFormula: TsRPNFormula; ACell: PCell); override;
procedure WriteLabel(AStream: TStream; const ARow, ACol: Cardinal; const AValue: string; ACell: PCell); override;
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double; ACell: PCell); override;
+ procedure WriteRow(AStream: TStream; ASheet: TsWorksheet;
+ ARowIndex, AFirstColIndex, ALastColIndex: Cardinal; ARow: PRow); override;
+ procedure WriteWindow1(AStream: TStream); override;
+ procedure WriteWindow2(AStream: TStream; ASheet: TsWorksheet);
public
{ General writing methods }
procedure WriteToStream(AStream: TStream); override;
@@ -155,10 +157,9 @@ const
INT_EXCEL_ID_INTEGER = $0002;
INT_EXCEL_ID_NUMBER = $0003;
INT_EXCEL_ID_LABEL = $0004;
- INT_EXCEL_ID_FORMULA = $0006;
- INT_EXCEL_ID_ROWINFO = $0008;
+ INT_EXCEL_ID_ROW = $0008;
INT_EXCEL_ID_BOF = $0009;
- INT_EXCEL_ID_EOF = $000A;
+ INT_EXCEL_ID_INDEX = $000B;
INT_EXCEL_ID_FORMAT = $001E;
INT_EXCEL_ID_FORMATCOUNT= $001F;
INT_EXCEL_ID_COLWIDTH = $0024;
@@ -427,7 +428,7 @@ begin
INT_EXCEL_ID_LABEL : ReadLabel(AStream);
INT_EXCEL_ID_FORMULA : ReadFormula(AStream);
INT_EXCEL_ID_COLWIDTH : ReadColWidth(AStream);
- INT_EXCEL_ID_ROWINFO : ReadRowInfo(AStream);
+ INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
INT_EXCEL_ID_PANE : ReadPane(AStream);
INT_EXCEL_ID_XF : ReadXF(AStream);
@@ -565,8 +566,7 @@ begin
lRow := FWorksheet.GetRow(WordLEToN(rowrec.RowIndex));
// Row height is encoded into the 15 remaining bits in units "twips" (1/20 pt)
lRow^.Height := TwipsToMillimeters(h and $7FFF);
- end else
- lRow^.AutoHeight := true;
+ end;
end;
{ Reads the WINDOW2 record containing information like "show grid lines",
@@ -828,6 +828,7 @@ begin
WriteFormats(AStream);
WriteXFRecords(AStream);
WriteColWidths(AStream);
+ WriteRows(AStream, sheet);
WriteCellsToStream(AStream, sheet.Cells);
WriteWindow1(AStream);
@@ -1533,6 +1534,55 @@ begin
AStream.WriteBuffer(AValue, 8);
end;
+procedure TsSpreadBIFF2Writer.WriteRow(AStream: TStream; ASheet: TsWorksheet;
+ ARowIndex, AFirstColIndex, ALastColIndex: Cardinal; ARow: PRow);
+var
+ containsXF: Boolean;
+ rowheight: Word;
+ w: Word;
+begin
+ containsXF := false;
+
+ { BIFF record header }
+ AStream.WriteWord(WordToLE(INT_EXCEL_ID_ROW));
+ AStream.WriteWord(WordToLE(IfThen(containsXF, 18, 13)));
+
+ { Index of row }
+ AStream.WriteWord(WordToLE(Word(ARowIndex)));
+
+ { Index to column of the first cell which is described by a cell record }
+ AStream.WriteWord(WordToLE(Word(AFirstColIndex)));
+
+ { Index to column of the last cell which is described by a cell record, increased by 1 }
+ AStream.WriteWord(WordToLE(Word(ALastColIndex) + 1));
+
+ { Row height (in twips, 1/20 point) and info on custom row height }
+ if (ARow = nil) or (ARow^.Height = 0) then
+ rowheight := round(Workbook.GetFont(0).Size*20)
+ else
+ rowheight := MillimetersToTwips(ARow^.Height);
+ w := rowheight and $7FFF;
+ AStream.WriteWord(WordToLE(w));
+
+ { not used }
+ AStream.WriteWord(0);
+
+ { Contains row attribute field and XF index }
+ AStream.WriteByte(ord(containsXF));
+
+ { Relative offset to calculate stream position of the first cell record for this row }
+ AStream.WriteWord(0);
+
+ if containsXF then begin
+ { Default row attributes }
+ AStream.WriteByte(0);
+ AStream.WriteByte(0);
+ AStream.WriteByte(0);
+
+ { Index to XF record }
+ AStream.WriteWord(WordToLE(15));
+ end;
+end;
{*******************************************************************
* Initialization section
diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas
index 36fcd8f22..b18a103f1 100755
--- a/components/fpspreadsheet/xlsbiff5.pas
+++ b/components/fpspreadsheet/xlsbiff5.pas
@@ -219,20 +219,7 @@ implementation
const
{ Excel record IDs }
- INT_EXCEL_ID_BOF = $0809;
- INT_EXCEL_ID_BOUNDSHEET = $0085; // Renamed to SHEET in the latest OpenOffice docs
- INT_EXCEL_ID_EOF = $000A;
- INT_EXCEL_ID_DIMENSIONS = $0200;
- INT_EXCEL_ID_FORMAT = $041E;
- INT_EXCEL_ID_FORMULA = $0006;
- INT_EXCEL_ID_INDEX = $020B;
- INT_EXCEL_ID_ROWINFO = $0208;
- INT_EXCEL_ID_STYLE = $0293;
- INT_EXCEL_ID_WINDOW1 = $003D;
- INT_EXCEL_ID_RSTRING = $00D6;
- INT_EXCEL_ID_RK = $027E;
- INT_EXCEL_ID_MULRK = $00BD;
- INT_EXCEL_ID_CODEPAGE = xlscommon.INT_EXCEL_ID_CODEPAGE;
+ // see: in xlscommon
{ Cell Addresses constants }
MASK_EXCEL_ROW = $3FFF;
@@ -412,6 +399,7 @@ begin
WriteDimensions(AStream, sheet);
WriteWindow2(AStream, sheet);
WritePane(AStream, sheet, true); // true for "is BIFF5 or BIFF8"
+ WriteRows(AStream, sheet);
WriteCellsToStream(AStream, sheet.Cells);
WriteEOF(AStream);
end;
@@ -1284,7 +1272,7 @@ begin
INT_EXCEL_ID_RK : ReadRKValue(AStream); //(RK) This record represents a cell that contains an RK value (encoded integer or floating-point value). If a floating-point value cannot be encoded to an RK value, a NUMBER record will be written. This record replaces the record INTEGER written in BIFF2.
INT_EXCEL_ID_MULRK : ReadMulRKValues(AStream);
INT_EXCEL_ID_COLINFO : ReadColInfo(AStream);
- INT_EXCEL_ID_ROWINFO : ReadRowInfo(AStream);
+ INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
INT_EXCEL_ID_FORMULA : ReadFormulaExcel(AStream);
INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
INT_EXCEL_ID_PANE : ReadPane(AStream);
diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas
index 680a5efb5..c745bdea1 100755
--- a/components/fpspreadsheet/xlsbiff8.pas
+++ b/components/fpspreadsheet/xlsbiff8.pas
@@ -217,23 +217,8 @@ implementation
const
{ Excel record IDs }
- INT_EXCEL_ID_BOF = $0809;
- INT_EXCEL_ID_BOUNDSHEET = $0085; // Renamed to SHEET in the latest OpenOffice docs
- INT_EXCEL_ID_COUNTRY = $008C;
- INT_EXCEL_ID_EOF = $000A;
- INT_EXCEL_ID_DIMENSIONS = $0200;
- INT_EXCEL_ID_FORMULA = $0006;
- INT_EXCEL_ID_INDEX = $020B;
- INT_EXCEL_ID_ROWINFO = $0208;
- INT_EXCEL_ID_STYLE = $0293;
- INT_EXCEL_ID_WINDOW2 = $023E;
- INT_EXCEL_ID_RSTRING = $00D6;
- INT_EXCEL_ID_RK = $027E;
- INT_EXCEL_ID_MULRK = $00BD;
INT_EXCEL_ID_SST = $00FC; //BIFF8 only
- INT_EXCEL_ID_CONTINUE = $003C;
INT_EXCEL_ID_LABELSST = $00FD; //BIFF8 only
- INT_EXCEL_ID_FORMAT = $041E;
INT_EXCEL_ID_FORCEFULLCALCULATION = $08A3;
{ Cell Addresses constants }
@@ -447,6 +432,8 @@ end;
*
*******************************************************************}
procedure TsSpreadBIFF8Writer.WriteToStream(AStream: TStream);
+const
+ isBIFF8 = true;
var
MyData: TMemoryStream;
CurrentPos: Int64;
@@ -492,14 +479,17 @@ begin
WriteIndex(AStream);
WriteColInfos(AStream, sheet);
WriteDimensions(AStream, sheet);
+ //WriteRowAndCellBlock(AStream, sheet);
+
+ WriteRows(AStream, sheet);
WriteCellsToStream(AStream, sheet.Cells);
+
WriteWindow2(AStream, sheet);
- WritePane(AStream, sheet, true); // true for "is BIFF5 or BIFF8"
+ WritePane(AStream, sheet, isBIFF8);
WriteEOF(AStream);
end;
{ Cleanup }
-
SetLength(Boundsheets, 0);
end;
@@ -1535,7 +1525,7 @@ begin
INT_EXCEL_ID_MULRK : ReadMulRKValues(AStream);
INT_EXCEL_ID_LABELSST: ReadLabelSST(AStream); //BIFF8 only
INT_EXCEL_ID_COLINFO : ReadColInfo(AStream);
- INT_EXCEL_ID_ROWINFO : ReadRowInfo(AStream);
+ INT_EXCEL_ID_ROW : ReadRowInfo(AStream);
INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream);
INT_EXCEL_ID_PANE : ReadPane(AStream);
INT_EXCEL_ID_BOF : ;
diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas
index 5167ecacf..74c074c9b 100644
--- a/components/fpspreadsheet/xlscommon.pas
+++ b/components/fpspreadsheet/xlscommon.pas
@@ -16,21 +16,41 @@ uses
const
{ RECORD IDs which didn't change across versions 2-8 }
+ INT_EXCEL_ID_EOF = $000A;
INT_EXCEL_ID_SELECTION = $001D;
- INT_EXCEL_ID_FONT = $0031;
+ INT_EXCEL_ID_CONTINUE = $003C;
INT_EXCEL_ID_PANE = $0041;
INT_EXCEL_ID_CODEPAGE = $0042;
- INT_EXCEL_ID_COLINFO = $007D;
INT_EXCEL_ID_DATEMODE = $0022;
- INT_EXCEL_ID_PALETTE = $0092;
INT_EXCEL_ID_WINDOW1 = $003D;
- INT_EXCEL_ID_XF = $00E0;
+
+ { RECORD IDs which did not change across versions 2, 5, 8}
+ INT_EXCEL_ID_FORMULA = $0006; // BIFF3: $0206, BIFF4: $0406
+ INT_EXCEL_ID_FONT = $0031; // BIFF3-4: $0231
+
+ { RECORD IDs which did not change across version 3-8}
+ INT_EXCEL_ID_COLINFO = $007D; // does not exist in BIFF2
+ INT_EXCEL_ID_COUNTRY = $008C; // does not exist in BIFF2
+ INT_EXCEL_ID_PALETTE = $0092; // does not exist in BIFF2
+ INT_EXCEL_ID_DIMENSIONS = $0200; // BIFF2: $0000
+ INT_EXCEL_ID_BLANK = $0201; // BIFF2: $0001
+ INT_EXCEL_ID_NUMBER = $0203; // BIFF2: $0003
+ INT_EXCEL_ID_LABEL = $0204; // BIFF2: $0004
+ INT_EXCEL_ID_ROW = $0208; // BIFF2: $0008
+ INT_EXCEL_ID_INDEX = $020B; // BIFF2: $000B
+ INT_EXCEL_ID_WINDOW2 = $023E; // BIFF2: $003E
+ INT_EXCEL_ID_RK = $027E; // does not exist in BIFF2
+ INT_EXCEL_ID_STYLE = $0293; // does not exist in BIFF2
+
+ { RECORD IDs which did not change across version 4-8 }
+ INT_EXCEL_ID_FORMAT = $041E; // BIFF2-3: $001E
{ RECORD IDs which did not change across versions 5-8 }
- INT_EXCEL_ID_BLANK = $0201;
- INT_EXCEL_ID_NUMBER = $0203;
- INT_EXCEL_ID_LABEL = $0204;
- INT_EXCEL_ID_WINDOW2 = $023E;
+ INT_EXCEL_ID_BOUNDSHEET = $0085; // Renamed to SHEET in the latest OpenOffice docs, does not exist before 5
+ INT_EXCEL_ID_MULRK = $00BD; // does not exist before BIFF5
+ INT_EXCEL_ID_XF = $00E0; // BIFF2:$0043, BIFF3:$0243, BIFF4:$0443
+ INT_EXCEL_ID_RSTRING = $00D6; // does not exist before BIFF5
+ INT_EXCEL_ID_BOF = $0809; // BIFF2:$0009, BIFF3:$0209; BIFF4:$0409
{ FONT record constants }
INT_FONT_WEIGHT_NORMAL = $0190;
@@ -408,6 +428,12 @@ type
// Write out BLANK cell record
procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal;
ACell: PCell); override;
+
+ {
+ procedure WriteCellBlock(AStream: TStream; ASheet: TsWorksheet;
+ AFirstRow, ALastRow: Cardinal);
+ }
+
// Write out used codepage for character encoding
procedure WriteCodepage(AStream: TStream; AEncoding: TsEncoding);
// Writes out column info(s)
@@ -425,6 +451,11 @@ type
procedure WritePalette(AStream: TStream);
// Writes out a PANE record
procedure WritePane(AStream: TStream; ASheet: TsWorksheet; IsBiff58: Boolean);
+ // Writes out a ROW record
+ procedure WriteRow(AStream: TStream; ASheet: TsWorksheet;
+ ARowIndex, AFirstColIndex, ALastColIndex: Cardinal; ARow: PRow); virtual;
+ // Write all ROW records for a sheet
+ procedure WriteRows(AStream: TStream; ASheet: TsWorksheet);
// Writes out a SELECTION record
procedure WriteSelection(AStream: TStream; ASheet: TsWorksheet; APane: Byte);
procedure WriteSelections(AStream: TStream; ASheet: TsWorksheet);
@@ -924,8 +955,8 @@ begin
lRow^.Height := TwipsToMillimeters(h and $7FFF);
end else
lRow^.Height := 0;
- lRow^.AutoHeight := rowrec.Flags and $00000040 = 0;
- // If this bit is set row height does not change font height, i.e. has been
+ //lRow^.AutoHeight := rowrec.Flags and $00000040 = 0;
+ // If this bit is set row height does not change with font height, i.e. has been
// changed manually.
end;
@@ -1410,6 +1441,88 @@ begin
{ Not used (BIFF5-BIFF8 only, not written in BIFF2-BIFF4 }
end;
+{ Writes an Excel 3-8 ROW record
+ Valid for BIFF3-BIFF8 }
+procedure TsSpreadBIFFWriter.WriteRow(AStream: TStream; ASheet: TsWorksheet;
+ ARowIndex, AFirstColIndex, ALastColIndex: Cardinal; ARow: PRow);
+var
+ w: Word;
+ dw: DWord;
+ cell: PCell;
+ spaceabove, spacebelow: Boolean;
+ colindex: Cardinal;
+ rowheight: Word;
+begin
+ // Check for additional space above/below row
+ spaceabove := false;
+ spacebelow := false;
+ colindex := AFirstColIndex;
+ while colindex <= ALastColIndex do begin
+ cell := ASheet.FindCell(ARowindex, colindex);
+ if (cell <> nil) and (uffBorder in cell^.UsedFormattingFields) then begin
+ if (cbNorth in cell^.Border) and (cell^.BorderStyles[cbNorth].LineStyle = lsThick)
+ then spaceabove := true;
+ if (cbSouth in cell^.Border) and (cell^.BorderStyles[cbSouth].LineStyle = lsThick)
+ then spacebelow := true;
+ end;
+ if spaceabove and spacebelow then break;
+ inc(colindex);
+ end;
+
+ { BIFF record header }
+ AStream.WriteWord(WordToLE(INT_EXCEL_ID_ROW));
+ AStream.WriteWord(WordToLE(16));
+
+ { Index of row }
+ AStream.WriteWord(WordToLE(Word(ARowIndex)));
+
+ { Index to column of the first cell which is described by a cell record }
+ AStream.WriteWord(WordToLE(Word(AFirstColIndex)));
+
+ { Index to column of the last cell which is described by a cell record, increased by 1 }
+ AStream.WriteWord(WordToLE(Word(ALastColIndex) + 1));
+
+ { Row height (in twips, 1/20 point) and info on custom row height }
+ if (ARow = nil) or (ARow^.Height = 0) then
+ rowheight := round(Workbook.GetFont(0).Size*20)
+ else
+ rowheight := MillimetersToTwips(ARow^.Height);
+ w := rowheight and $7FFF;
+ AStream.WriteWord(WordToLE(w));
+
+ { 2 words not used }
+ AStream.WriteDWord(0);
+
+ { Option flags }
+ dw := $00000100; // bit 8 is always 1
+ if spaceabove then dw := dw or $10000000;
+ if spacebelow then dw := dw or $20000000;
+ if (ARow <> nil) then
+ dw := dw or $00000040; // Row height and font height do not match
+ AStream.WriteDWord(DWordToLE(dw));
+end;
+
+{ Writes all ROW records for the given sheet.
+ Note that the OpenOffice documentation says that rows must be written in
+ groups of 32, followed by the cells on these rows, etc. THIS IS NOT NECESSARY!
+ Valid for BIFF2-BIFF8 }
+procedure TsSpreadBIFFWriter.WriteRows(AStream: TStream; ASheet: TsWorksheet);
+var
+ row: PRow;
+ i: Integer;
+ cell1, cell2: PCell;
+begin
+ for i := 0 to ASheet.Rows.Count-1 do begin
+ row := ASheet.Rows[i];
+ cell1 := ASheet.GetFirstCellOfRow(row^.Row);
+ if cell1 <> nil then begin
+ cell2 := ASheet.GetLastCellOfRow(row^.Row);
+ WriteRow(AStream, ASheet, row^.Row, cell1^.Col, cell2^.Col, row);
+ end else
+ WriteRow(AStream, ASheet, row^.Row, 0, 0, row);
+ end;
+end;
+
{ Writes an Excel 2-8 SELECTION record
Writes just reasonable default values
APane is 0..3 (see below)
@@ -1420,19 +1533,19 @@ var
activeCellRow, activeCellCol: Word;
begin
case APane of
- 0: begin // right-bottom
+ 0: begin // right-bottom
activeCellRow := ASheet.TopPaneHeight;
activeCellCol := ASheet.LeftPaneWidth;
end;
- 1: begin // right-top
+ 1: begin // right-top
activeCellRow := 0;
activeCellCol := ASheet.LeftPaneWidth;
end;
- 2: begin // left-bottom
+ 2: begin // left-bottom
activeCellRow := ASheet.TopPaneHeight;
activeCellCol := 0;
end;
- 3: begin // left-top
+ 3: begin // left-top
activeCellRow := 0;
activeCellCol := 0;
end;