From 482eac242ad5f9b18fcf56108c91b5ed512ea7ad Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Sun, 4 May 2014 18:07:54 +0000 Subject: [PATCH] fpspreadsheet: Add support for frozen panes in BIFF5/BIFF8 (BIFF2 not working at the moment), fpSpreadsheetGrid, and BIFFExplorer. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3005 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../examples/excel2demo/excel2write.lpr | 6 + .../examples/excel5demo/excel5write.lpr | 7 + .../examples/excel8demo/excel8write.lpr | 10 +- .../examples/fpsgrid/fpsgrid.lpi | 209 +++--- .../examples/fpsgrid/mainform.lfm | 52 +- .../examples/fpsgrid/mainform.lrs | 674 +++++++++--------- .../examples/fpsgrid/mainform.pas | 27 +- components/fpspreadsheet/fpspreadsheet.pas | 19 +- .../fpspreadsheet/fpspreadsheetgrid.pas | 169 +++-- .../reference/BIFFExplorer/bebiffgrid.pas | 39 + components/fpspreadsheet/xlsbiff2.pas | 116 ++- components/fpspreadsheet/xlsbiff5.pas | 36 +- components/fpspreadsheet/xlsbiff8.pas | 38 +- components/fpspreadsheet/xlscommon.pas | 118 ++- 14 files changed, 956 insertions(+), 564 deletions(-) diff --git a/components/fpspreadsheet/examples/excel2demo/excel2write.lpr b/components/fpspreadsheet/examples/excel2demo/excel2write.lpr index c11655985..3d0e764be 100644 --- a/components/fpspreadsheet/examples/excel2demo/excel2write.lpr +++ b/components/fpspreadsheet/examples/excel2demo/excel2write.lpr @@ -31,6 +31,12 @@ begin //MyWorksheet.WriteColWidth(0, 5); //MyWorksheet.WriteColWidth(1, 30); + { -- currently not working + MyWorksheet.Options := MyWorksheet.Options + [soHasFrozenPanes]; + MyWorksheet.LeftPaneWidth := 1; + MyWorksheet.TopPaneHeight := 2; + } + // Write some number cells MyWorksheet.WriteNumber(0, 0, 1.0); MyWorksheet.WriteUsedFormatting(0, 0, [uffBold, uffNumberFormat]); diff --git a/components/fpspreadsheet/examples/excel5demo/excel5write.lpr b/components/fpspreadsheet/examples/excel5demo/excel5write.lpr index 13db944ae..e7d1e2be4 100644 --- a/components/fpspreadsheet/examples/excel5demo/excel5write.lpr +++ b/components/fpspreadsheet/examples/excel5demo/excel5write.lpr @@ -34,6 +34,13 @@ begin MyWorkbook := TsWorkbook.Create; MyWorksheet := MyWorkbook.AddWorksheet(Str_Worksheet1); + MyWorksheet.Options := MyWorksheet.Options + [soHasFrozenPanes]; + MyWorksheet.LeftPaneWidth := 1; + MyWorksheet.TopPaneHeight := 2; + + { unfrozen panes not working at the moment + MyWorksheet.LeftPaneWidth := 20*72*2; // 72 pt = inch --> 2 inches = 5 cm } + MyWorkbook.AddFont('Calibri', 20, [], scRed); // Write some cells diff --git a/components/fpspreadsheet/examples/excel8demo/excel8write.lpr b/components/fpspreadsheet/examples/excel8demo/excel8write.lpr index 33fd381cd..9667a2e49 100644 --- a/components/fpspreadsheet/examples/excel8demo/excel8write.lpr +++ b/components/fpspreadsheet/examples/excel8demo/excel8write.lpr @@ -40,7 +40,15 @@ begin MyWorkbook.UsePalette(@PALETTE_BIFF8, Length(PALETTE_BIFF8)); MyWorksheet := MyWorkbook.AddWorksheet(Str_Worksheet1); - MyWorksheet.ShowGridLines := false; + MyWorksheet.Options := MyWorksheet.Options - [soShowGridLines]; + + MyWorksheet.Options := MyWorksheet.Options + [soHasFrozenPanes]; + myWorksheet.LeftPaneWidth := 1; + MyWorksheet.TopPaneHeight := 2; + + { non-frozen panes not working, at the moment. Require SELECTION records? + MyWorksheet.LeftPaneWidth := 20*72*2; // 72 pt = inch --> 2 inches = 5 cm + } // Write some cells MyWorksheet.WriteNumber(0, 0, 1.0);// A1 diff --git a/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi b/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi index ea5f6363c..57cce23ec 100644 --- a/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi +++ b/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi @@ -117,7 +117,7 @@ - + @@ -130,9 +130,9 @@ - - - + + + @@ -141,9 +141,9 @@ - - - + + + @@ -151,9 +151,9 @@ - - - + + + @@ -162,7 +162,7 @@ - + @@ -170,7 +170,7 @@ - + @@ -178,7 +178,7 @@ - + @@ -186,14 +186,14 @@ - + - + @@ -201,7 +201,7 @@ - + @@ -209,7 +209,7 @@ - + @@ -217,16 +217,19 @@ - + - - - + + + + + + @@ -236,7 +239,7 @@ - + @@ -244,7 +247,7 @@ - + @@ -253,7 +256,7 @@ - + @@ -261,16 +264,16 @@ - + - - - + + + @@ -279,23 +282,23 @@ - + - + - - - + + + @@ -303,9 +306,9 @@ - - - + + + @@ -313,9 +316,9 @@ - - - + + + @@ -324,7 +327,7 @@ - + @@ -333,7 +336,7 @@ - + @@ -342,14 +345,14 @@ - + - + @@ -358,7 +361,7 @@ - + @@ -367,130 +370,130 @@ - + - - + + - - + + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -526,7 +529,7 @@ - + diff --git a/components/fpspreadsheet/examples/fpsgrid/mainform.lfm b/components/fpspreadsheet/examples/fpsgrid/mainform.lfm index 9c4655c6f..ba4b318f4 100644 --- a/components/fpspreadsheet/examples/fpsgrid/mainform.lfm +++ b/components/fpspreadsheet/examples/fpsgrid/mainform.lfm @@ -1,10 +1,10 @@ object Form1: TForm1 Left = 370 - Height = 379 + Height = 386 Top = 258 Width = 518 Caption = 'fpsGrid' - ClientHeight = 359 + ClientHeight = 366 ClientWidth = 518 Menu = MainMenu1 OnActivate = FormActivate @@ -12,12 +12,12 @@ object Form1: TForm1 LCLVersion = '1.3' object Panel1: TPanel Left = 0 - Height = 55 - Top = 304 + Height = 70 + Top = 296 Width = 518 Align = alBottom BevelOuter = bvNone - ClientHeight = 55 + ClientHeight = 70 ClientWidth = 518 TabOrder = 0 object btnPopulateGrid: TButton @@ -52,10 +52,44 @@ object Form1: TForm1 State = cbChecked TabOrder = 2 end + object EdFrozenCols: TSpinEdit + Left = 208 + Height = 23 + Top = 8 + Width = 52 + OnChange = EdFrozenColsChange + TabOrder = 3 + end + object EdFrozenRows: TSpinEdit + Left = 208 + Height = 23 + Top = 36 + Width = 52 + OnChange = EdFrozenRowsChange + TabOrder = 4 + end + object Label1: TLabel + Left = 135 + Height = 15 + Top = 13 + Width = 62 + Caption = 'Frozen cols:' + FocusControl = EdFrozenCols + ParentColor = False + end + object Label2: TLabel + Left = 136 + Height = 15 + Top = 39 + Width = 66 + Caption = 'Frozen rows:' + FocusControl = EdFrozenRows + ParentColor = False + end end object PageControl1: TPageControl Left = 0 - Height = 278 + Height = 270 Top = 26 Width = 518 ActivePage = TabSheet1 @@ -65,15 +99,15 @@ object Form1: TForm1 OnChange = PageControl1Change object TabSheet1: TTabSheet Caption = 'Sheet1' - ClientHeight = 250 + ClientHeight = 242 ClientWidth = 510 object sWorksheetGrid1: TsWorksheetGrid Left = 0 - Height = 250 + Height = 242 Top = 0 Width = 510 Align = alClient - Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goRowSizing, goColSizing, goThumbTracking, goSmoothScroll] + Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goRowSizing, goColSizing, goThumbTracking, goSmoothScroll, goFixedColSizing] TabOrder = 0 TitleStyle = tsNative end diff --git a/components/fpspreadsheet/examples/fpsgrid/mainform.lrs b/components/fpspreadsheet/examples/fpsgrid/mainform.lrs index 67413e64a..65910124a 100644 --- a/components/fpspreadsheet/examples/fpsgrid/mainform.lrs +++ b/components/fpspreadsheet/examples/fpsgrid/mainform.lrs @@ -1,348 +1,356 @@ { This is an automatically generated lazarus resource file } LazarusResources.Add('TForm1','FORMDATA',[ - 'TPF0'#6'TForm1'#5'Form1'#4'Left'#3'r'#1#6'Height'#3'{'#1#3'Top'#3#2#1#5'Widt' - +'h'#3#6#2#7'Caption'#6#7'fpsGrid'#12'ClientHeight'#3'g'#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'7'#3'Top' - +#3'0'#1#5'Width'#3#6#2#5'Align'#7#8'alBottom'#10'BevelOuter'#7#6'bvNone'#12 - +'ClientHeight'#2'7'#11'ClientWidth'#3#6#2#8'TabOrder'#2#0#0#7'TButton'#15'bt' - +'nPopulateGrid'#4'Left'#3#144#1#6'Height'#2#25#3'Top'#2#13#5'Width'#2'p'#7'C' - +'aption'#6#13'Populate Grid'#7'OnClick'#7#20'btnPopulateGridClick'#8'TabOrde' - +'r'#2#0#7'Visible'#8#0#0#9'TCheckBox'#13'CbShowHeaders'#4'Left'#2#8#6'Height' - +#2#19#3'Top'#2#8#5'Width'#2']'#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'C' - +'bShowGridLinesClick'#5'State'#7#9'cbChecked'#8'TabOrder'#2#2#0#0#0#12'TPage' - +'Control'#12'PageControl1'#4'Left'#2#0#6'Height'#3#22#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'TTabSheet'#9'TabShee' - +'t1'#7'Caption'#6#6'Sheet1'#12'ClientHeight'#3#250#0#11'ClientWidth'#3#254#1 - +#0#15'TsWorksheetGrid'#15'sWorksheetGrid1'#4'Left'#2#0#6'Height'#3#250#0#3'T' - +'op'#2#0#5'Width'#3#254#1#5'Align'#7#8'alClient'#7'Options'#11#15'goFixedVer' - +'tLine'#15'goFixedHorzLine'#10'goVertLine'#10'goHorzLine'#13'goRangeSelect' - +#11'goRowSizing'#11'goColSizing'#15'goThumbTracking'#14'goSmoothScroll'#0#8 - +'TabOrder'#2#0#10'TitleStyle'#7#8'tsNative'#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'Ta' - +'bOrder'#2#2#0#11'TToolButton'#11'ToolButton1'#4'Left'#2#1#3'Top'#2#0#6'Acti' - +'on'#7#6'AcOpen'#0#0#11'TToolButton'#11'ToolButton2'#4'Left'#2#24#3'Top'#2#0 - +#6'Action'#7#8'AcSaveAs'#0#0#11'TToolButton'#11'ToolButton3'#4'Left'#2'4'#3 - +'Top'#2#0#6'Action'#7#6'AcQuit'#0#0#11'TToolButton'#11'ToolButton5'#4'Left'#2 - +'/'#3'Top'#2#0#5'Width'#2#5#7'Caption'#6#11'ToolButton5'#5'Style'#7#10'tbsDi' - +'vider'#0#0#0#11'TOpenDialog'#11'OpenDialog1'#10'DefaultExt'#6#4'.xls'#6'Fil' - +'ter'#6#192'Excel spreadsheet (*.xls)|*.xls|Excel XML spreadsheet (*.xlsx)|*' - +'.xlxs|LibreOffice/OpenOffice spreadsheet (*.ods)|*.ods|Wikitable (pipes) (.' - +'wikitable_pipes)|.wikitable_pipes|All files (*.*)|*.*'#7'Options'#11#20'ofE' - +'xtensionDifferent'#14'ofEnableSizing'#12'ofViewDetail'#0#4'left'#2'@'#3'top' - +#3#176#0#0#0#11'TSaveDialog'#11'SaveDialog1'#10'DefaultExt'#6#4'.xls'#6'Filt' - +'er'#6#185'Excel spreadsheet (*.xls)|*.xls|Excel XML spreadsheet (*.xlsx)|*.' - +'xlsx|LibreOffice/OpenOffice spreadsheet (*.ods)|*.ods|Wikitable (wikimedia)' - +' (.wikitable_wikimedia)|*.wikitable_wikimedia'#7'Options'#11#20'ofExtension' - +'Different'#14'ofEnableSizing'#12'ofViewDetail'#0#4'left'#3#176#0#3'top'#3 - +#176#0#0#0#9'TMainMenu'#9'MainMenu1'#6'Images'#7#10'ImageList1'#4'left'#3' ' - +#1#3'top'#3#176#0#0#9'TMenuItem'#7'mnuFile'#7'Caption'#6#5'&File'#0#9'TMenuI' - +'tem'#7'mnuOpen'#6'Action'#7#6'AcOpen'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0 - +'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4 - +#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0','#134#216#0'-'#136#216#247'-'#135#216 - +#247'-'#136#216#247'-'#136#216#247'-'#136#216#247'-'#136#216#247'-'#136#216 - +#247'-'#136#216#247'-'#136#216#247'-'#136#216#247'-'#135#216#247'-'#136#216 - +#247','#134#216#0#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'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'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#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#255#134#193#198#255#201#216#214 - +#255'5'#148#218#255#197'tD'#232#202#127'S'#241'7'#166#218#250#254#255#255#255 - +#248#253#255#255#246#253#255#255#245#252#255#255#243#252#254#255#154#228#244 - +#255#154#230#247#255#155#230#246#255#157#229#245#255#158#229#245#255#159#229 - +#244#255#218#243#248#255'5'#148#218#255#253#244#238#255#202#128'T'#249'5'#171 - ,#218#250#232#246#251#255'p'#188#231#255'U'#170#226#255'M'#165#224#255#145#201 - +#235#255#250#243#239#255#253#254#253#255#255#253#252#255#255#253#252#255#254 - +#253#252#255#254#252#251#255#254#254#253#255'5'#148#218#255#239#242#232#255 - +#206#129'V'#255'6'#170#218#242#241#250#253#255#148#222#245#255#147#220#244 - +#255'd'#188#233#255'5'#148#218#255'5'#148#218#255'5'#148#218#255'5'#148#218 - +#255'5'#148#218#255'5'#148#218#255'5'#148#218#255'5'#148#218#255'5'#148#218 - +#255#251#246#239#255#204#131'U'#254'5'#175#218#240#247#252#254#255#142#228 - +#248#255#145#222#245#255#159#224#245#255#172#225#246#255#202#132'R'#255#255 - +#247#241#255#255#233#217#255#255#234#219#255#255#233#217#255#255#231#215#255 - +#255#229#210#255#255#226#203#255#255#247#241#255#203#133'U'#254'6'#179#218 - +#248#253#254#254#255#254#255#255#255#254#254#255#255#253#254#255#255#254#255 - +#255#255#228#186#145#255#255#247#240#255#255#231#213#255#253#231#214#255#253 - +#230#212#255#252#228#208#255#251#227#203#255#250#220#194#255#254#243#232#255 - +#204#134'V'#254'4'#180#217#208'^'#194#225#250'`'#195#226#250'`'#195#226#250 - +'`'#195#226#250'_'#195#226#250#228#187#145#255#255#247#242#255#254#231#213 - +#255#254#231#213#255#253#229#209#255#250#224#202#255#249#222#196#255#247#217 - +#188#255#253#242#231#255#204#135'W'#254#255#255#255#0#255#255#255#0#255#255 - +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#228#187#146#255#254#247#241 - +#255#252#229#210#255#252#228#209#255#251#226#204#255#249#221#196#255#246#215 - +#187#255#243#209#175#255#250#239#228#255#204#135'X'#254#255#255#255#0#255#255 - +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#228#187#146 - +#255#254#246#240#255#252#226#205#255#252#227#205#255#250#223#200#255#247#217 - +#188#255#245#233#221#255#250#243#235#255#251#248#243#255#202#131'S'#254#255 + '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 + +#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 + +'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 + +#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 + +'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' + +#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 + +'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 + +'ToolButton2'#4'Left'#2#24#3'Top'#2#0#6'Action'#7#8'AcSaveAs'#0#0#11'TToolBu' + +'tton'#11'ToolButton3'#4'Left'#2'4'#3'Top'#2#0#6'Action'#7#6'AcQuit'#0#0#11 + +'TToolButton'#11'ToolButton5'#4'Left'#2'/'#3'Top'#2#0#5'Width'#2#5#7'Caption' + +#6#11'ToolButton5'#5'Style'#7#10'tbsDivider'#0#0#0#11'TOpenDialog'#11'OpenDi' + +'alog1'#10'DefaultExt'#6#4'.xls'#6'Filter'#6#192'Excel spreadsheet (*.xls)|*' + +'.xls|Excel XML spreadsheet (*.xlsx)|*.xlxs|LibreOffice/OpenOffice spreadshe' + +'et (*.ods)|*.ods|Wikitable (pipes) (.wikitable_pipes)|.wikitable_pipes|All ' + +'files (*.*)|*.*'#7'Options'#11#20'ofExtensionDifferent'#14'ofEnableSizing' + +#12'ofViewDetail'#0#4'left'#2'@'#3'top'#3#176#0#0#0#11'TSaveDialog'#11'SaveD' + +'ialog1'#10'DefaultExt'#6#4'.xls'#6'Filter'#6#185'Excel spreadsheet (*.xls)|' + +'*.xls|Excel XML spreadsheet (*.xlsx)|*.xlsx|LibreOffice/OpenOffice spreadsh' + +'eet (*.ods)|*.ods|Wikitable (wikimedia) (.wikitable_wikimedia)|*.wikitable_' + +'wikimedia'#7'Options'#11#20'ofExtensionDifferent'#14'ofEnableSizing'#12'ofV' + +'iewDetail'#0#4'left'#3#176#0#3'top'#3#176#0#0#0#9'TMainMenu'#9'MainMenu1'#6 + +'Images'#7#10'ImageList1'#4'left'#3' '#1#3'top'#3#176#0#0#9'TMenuItem'#7'mnu' + +'File'#7'Caption'#6#5'&File'#0#9'TMenuItem'#7'mnuOpen'#6'Action'#7#6'AcOpen' + +#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16 + +#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0',' + +#134#216#0'-'#136#216#247'-'#135#216#247'-'#136#216#247'-'#136#216#247'-'#136 + +#216#247'-'#136#216#247'-'#136#216#247'-'#136#216#247'-'#136#216#247'-'#136 + +#216#247'-'#135#216#247'-'#136#216#247','#134#216#0#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'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'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 + +#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 + +#255#134#193#198#255#201#216#214#255'5'#148#218#255#197'tD'#232#202#127'S' + +#241'7'#166#218#250#254#255#255#255#248#253#255#255#246#253#255#255#245#252 + +#255#255#243#252#254#255#154#228#244#255#154#230#247#255#155#230#246#255#157 + +#229#245#255#158#229#245#255#159#229#244#255#218#243#248#255'5'#148#218#255 + +#253#244#238#255#202#128'T'#249'5'#171#218#250#232#246#251#255'p'#188#231#255 + +'U'#170#226#255'M'#165#224#255#145#201#235#255#250#243#239#255#253#254#253 + +#255#255#253#252#255#255#253#252#255#254#253#252#255#254#252#251#255#254#254 + +#253#255'5'#148#218#255#239#242#232#255#206#129'V'#255'6'#170#218#242#241#250 + +#253#255#148#222#245#255#147#220#244#255'd'#188#233#255'5'#148#218#255'5'#148 + +#218#255'5'#148#218#255'5'#148#218#255'5'#148#218#255'5'#148#218#255'5'#148 + +#218#255'5'#148#218#255'5'#148#218#255#251#246#239#255#204#131'U'#254'5'#175 + +#218#240#247#252#254#255#142#228#248#255#145#222#245#255#159#224#245#255#172 + +#225#246#255#202#132'R'#255#255#247#241#255#255#233#217#255#255#234#219#255 + +#255#233#217#255#255#231#215#255#255#229#210#255#255#226#203#255#255#247#241 + +#255#203#133'U'#254'6'#179#218#248#253#254#254#255#254#255#255#255#254#254 + +#255#255#253#254#255#255#254#255#255#255#228#186#145#255#255#247#240#255#255 + +#231#213#255#253#231#214#255#253#230#212#255#252#228#208#255#251#227#203#255 + +#250#220#194#255#254#243#232#255#204#134'V'#254'4'#180#217#208'^'#194#225#250 + +'`'#195#226#250'`'#195#226#250'`'#195#226#250'_'#195#226#250#228#187#145#255 + +#255#247#242#255#254#231#213#255#254#231#213#255#253#229#209#255#250#224#202 + +#255#249#222#196#255#247#217#188#255#253#242#231#255#204#135'W'#254#255#255 + +#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0 + +#228#187#146#255#254#247#241#255#252#229#210#255#252#228#209#255#251#226#204 + +#255#249#221#196#255#246#215#187#255#243#209#175#255#250#239#228#255#204#135 + +'X'#254#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0 + +#255#255#255#0#228#187#146#255#254#246#240#255#252#226#205#255#252#227#205 + +#255#250#223#200#255#247#217#188#255#245#233#221#255#250#243#235#255#251#248 + +#243#255#202#131'S'#254#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255 + +#0#255#255#255#0#255#255#255#0#228#187#147#255#254#245#237#255#252#222#197 + +#255#251#224#199#255#249#220#194#255#245#211#180#255#254#249#243#255#250#226 + +#196#255#236#193#147#255#195'}H'#147#255#255#255#0#255#255#255#0#255#255#255 + +#0#255#255#255#0#255#255#255#0#255#255#255#0#229#190#150#255#255#255#254#255 + +#253#243#233#255#253#243#234#255#252#242#232#255#250#239#227#255#250#242#231 + +#255#234#187#136#255#207#133'U'#179#180'i='#12#255#255#255#0#255#255#255#0 + +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#234#195#157#255#230 + +#191#150#255#228#187#146#255#228#187#146#255#209#160'l'#245#208#158'm'#246 + +#204#150'_'#218#196'yB~'#178'g<'#9#255#255#255#0#7'OnClick'#7#13'acOpenExecu' + +'te'#0#0#9'TMenuItem'#9'mnuSaveAs'#6'Action'#7#8'AcSaveAs'#11'Bitmap.Data'#10 + +':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0 + +' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#186'j6'#0#185'i5'#181 + +#184'i5'#238#183'h5'#255#181'h5'#255#180'g4'#255#178'f4'#255#176'e3'#255#174 + +'d3'#255#172'c2'#255#170'b2'#255#169'a2'#255#168'`1'#255#167'`1'#254#166'`1' + +#241#168'a1'#196#186'j5'#222#235#198#173#255#234#197#173#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#254#251#248#255#254#251#248#255#254#251#248#255#200#154 + +'|'#255#199#152'y'#255#167'`1'#237#186'k7'#254#237#202#179#255#224#162'z'#255 + +#254#250#247#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255 + +'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255#253#249#246#255 + +#202#141'e'#255#201#155'|'#255#167'`1'#254#187'l8'#255#238#204#182#255#225 + +#162'z'#255#254#250#247#255#191#220#194#255#191#220#194#255#191#220#194#255 + +#191#220#194#255#191#220#194#255#191#220#194#255#191#220#194#255#191#220#194 + +#255#253#249#246#255#205#144'h'#255#204#158#129#255#168'a2'#255#187'k8'#255 + +#239#206#184#255#225#162'y'#255#254#250#247#255'b'#192#136#255'b'#192#136#255 + +'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255 + +'b'#192#136#255#253#249#246#255#207#147'j'#255#206#163#132#255#170'a2'#255 + +#186'j6'#255#239#208#187#255#226#162'z'#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#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#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 + +#217#155's'#255#218#176#149#255#175'd3'#255#187'j6'#255#242#216#197#255#227 + +#164'{'#255#227#163'z'#255#227#164'z'#255#226#164'{'#255#226#163'{'#255#225 + +#163'{'#255#225#162'y'#255#223#160'w'#255#222#159'v'#255#221#158't'#255#219 + +#156'r'#255#220#157't'#255#221#181#154#255#177'e4'#255#187'k6'#255#244#217 + +#199#255#230#166'}'#255#200#140'd'#255#201#141'e'#255#201#142'g'#255#203#146 + +'l'#255#203#146'm'#255#202#144'i'#255#200#140'e'#255#200#140'd'#255#200#140 + +'d'#255#200#140'd'#255#218#156't'#255#225#186#159#255#179'f4'#255#187'k6'#254 + +#244#220#201#255#231#167'}'#255#249#236#225#255#249#236#225#255#249#237#227 + +#255#252#244#238#255#253#250#247#255#253#247#243#255#250#237#229#255#247#231 + +#219#255#247#229#217#255#246#229#216#255#222#160'w'#255#228#190#164#255#180 + +'g4'#255#188'k6'#250#245#221#204#255#231#168'~'#255#250#240#232#255#250#240 + +#232#255#201#141'f'#255#250#240#233#255#253#248#243#255#254#250#248#255#252 + +#244#239#255#249#233#223#255#247#231#219#255#247#229#217#255#224#162'x'#255 + +#231#194#169#255#182'h5'#255#188'k6'#240#246#223#208#255#232#168'~'#255#252 + +#246#241#255#252#246#241#255#200#140'd'#255#250#241#233#255#251#244#238#255 + +#253#250#247#255#253#249#246#255#250#240#232#255#248#232#221#255#247#230#219 + +#255#225#163'z'#255#239#213#195#255#183'i5'#254#188'k6'#216#246#223#209#255 + +#233#170#128#255#254#250#246#255#253#250#246#255#200#140'd'#255#251#243#238 + +#255#251#241#234#255#252#246#242#255#254#251#248#255#252#246#241#255#249#236 + +#226#255#248#231#219#255#238#208#186#255#236#208#189#255#187'p>'#248#188'k6' + +#155#246#224#209#255#247#224#209#255#254#251#248#255#254#251#247#255#253#249 + +#246#255#252#245#240#255#250#240#234#255#251#242#237#255#253#249#246#255#253 + +#250#247#255#251#241#235#255#248#233#223#254#236#208#189#251#201#137'^'#236 + +#181'i5c'#188'k6q'#188'k6'#144#188'k6'#204#188'k6'#238#188'k6'#250#187'k6' + +#254#187'k6'#255#187'j6'#255#187'j6'#255#188'l9'#255#189'n;'#255#187'm:'#255 + +#187'k8'#239#187'p>'#203#182'i5T'#255#255#255#0#7'OnClick'#7#15'acSaveAsExec' + +'ute'#0#0#9'TMenuItem'#9'MenuItem1'#7'Caption'#6#1'-'#0#0#9'TMenuItem'#7'mnu' + +'Quit'#6'Action'#7#6'AcQuit'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0 + +#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0 + +#0'd'#0#0#0#0#0#0#0#0#0#0#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 + +#29'c'#155#22#25'`'#152'9'#20']'#149'b'#16'Z'#146#136#13'X'#144#164#19'\'#146 + +#252#12'W'#143#237#153#153#153#255'qqq'#255'TTT'#255'QQQ'#255'OOO'#255'LLL' + +#255'JJJ'#255'GGG'#255'EEE'#255'%g'#157#255'2t'#168#255'=|'#175#255'G'#132 + +#181#255'N'#138#186#255'>~'#173#255#12'W'#143#234#255#255#255#0#255#255#255#0 + +'XXX'#255#162#162#162#255#162#162#162#255#163#163#163#255#164#164#164#255#164 + +#164#164#255#165#165#165#255'/o'#165#255'x'#171#210#255'x'#171#211#255's'#167 + +#209#255'i'#160#205#255'@'#127#174#255#15'Y'#145#234#255#255#255#0#255#255 + +#255#0'\\\'#255#161#161#161#255''#255'4~;'#255'1y7' + +#255'.u4'#255'I'#145'P'#255'F'#143'L'#255'9s='#255#161#161#161#255#162#162 + +#162#255'E~'#180#255#136#183#217#255'g'#163#207#255'a'#158#204#255'c'#159#204 + +#255'E'#131#177#255#31'd'#156#234';'#135'B'#255#137#203#146#255#132#200#141 + +#255#128#198#136#255'{'#195#131#255'w'#193#127#255'G'#143'M'#255';t?'#255#161 + +#161#161#255'L'#132#186#255#141#187#219#255'n'#168#209#255'f'#166#209#255'_' + +#180#223#255'G'#133#177#255'%i'#161#234'>'#139'F'#255#143#206#153#255'}'#198 + +#135#255'x'#195#129#255's'#192'|'#255't'#192'|'#255'y'#194#129#255'I'#144'O' + +#255'T'#127'W'#255'T'#137#191#255#148#191#221#255'u'#173#212#255'c'#184#225 + +#255'K'#212#255#255'B'#139#184#255',n'#166#234'A'#144'J'#255#148#210#159#255 + +#145#208#154#255#141#205#150#255#137#203#146#255#132#200#141#255'Q'#152'X' + +#255'A|F'#255#159#159#159#255'Z'#142#196#255#152#195#224#255'|'#179#215#255 + +'t'#175#214#255'^'#196#237#255'K'#136#179#255'4s'#171#234'D'#148'M'#255'B' + +#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 + +#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 + +#229#255#143#193#223#255#137#189#220#255#139#189#220#255'S'#141#182#255'K' + +#132#188#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#199#225#255#145#194#222#255'V' + +#143#183#255'R'#137#193#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#208#230#255'X'#144#184#255'Y'#142 + +#198#234#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#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#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#255#255#255#0#255#255#255#0'm'#156#212#137'j'#154#210#251'f' + +#151#207#238#7'OnClick'#7#13'acQuitExecute'#0#0#0#0#10'TImageList'#10'ImageL' + +'ist1'#4'left'#3#176#0#3'top'#2'x'#6'Bitmap'#10#14#12#0#0'Li'#3#0#0#0#16#0#0 + +#0#16#0#0#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#234#195#157#255#230#191#150#255#228#187#146#255#228#187 + +#146#255#209#160'l'#245#208#158'm'#246#204#150'_'#218#196'yB~'#178'g<'#9#255 +#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255 - +#255#0#228#187#147#255#254#245#237#255#252#222#197#255#251#224#199#255#249 - +#220#194#255#245#211#180#255#254#249#243#255#250#226#196#255#236#193#147#255 - +#195'}H'#147#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255 +#255#0#255#255#255#0#229#190#150#255#255#255#254#255#253#243#233#255#253#243 +#234#255#252#242#232#255#250#239#227#255#250#242#231#255#234#187#136#255#207 +#133'U'#179#180'i='#12#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255 - +#0#255#255#255#0#255#255#255#0#234#195#157#255#230#191#150#255#228#187#146 - +#255#228#187#146#255#209#160'l'#245#208#158'm'#246#204#150'_'#218#196'yB~' - +#178'g<'#9#255#255#255#0#7'OnClick'#7#13'acOpenExecute'#0#0#9'TMenuItem'#9'm' - +'nuSaveAs'#6'Action'#7#8'AcSaveAs'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6' - +#4#0#0#0#0#0#0'6'#0#0#0'('#0#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0 - +'d'#0#0#0'd'#0#0#0#0#0#0#0#0#0#0#0#186'j6'#0#185'i5'#181#184'i5'#238#183'h5' - +#255#181'h5'#255#180'g4'#255#178'f4'#255#176'e3'#255#174'd3'#255#172'c2'#255 - +#170'b2'#255#169'a2'#255#168'`1'#255#167'`1'#254#166'`1'#241#168'a1'#196#186 - +'j5'#222#235#198#173#255#234#197#173#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 - +#254#251#248#255#254#251#248#255#254#251#248#255#200#154'|'#255#199#152'y' - +#255#167'`1'#237#186'k7'#254#237#202#179#255#224#162'z'#255#254#250#247#255 - +'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255 - +'b'#192#136#255'b'#192#136#255'b'#192#136#255#253#249#246#255#202#141'e'#255 - +#201#155'|'#255#167'`1'#254#187'l8'#255#238#204#182#255#225#162'z'#255#254 - +#250#247#255#191#220#194#255#191#220#194#255#191#220#194#255#191#220#194#255 - +#191#220#194#255#191#220#194#255#191#220#194#255#191#220#194#255#253#249#246 - +#255#205#144'h'#255#204#158#129#255#168'a2'#255#187'k8'#255#239#206#184#255 - +#225#162'y'#255#254#250#247#255'b'#192#136#255'b'#192#136#255'b'#192#136#255 - +'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255 - +#253#249#246#255#207#147'j'#255#206#163#132#255#170'a2'#255#186'j6'#255#239 - +#208#187#255#226#162'z'#255#254#251#248#255#254#251#248#255#254#251#248#255 + +#0#255#255#255#0#255#255#255#0#228#187#147#255#254#245#237#255#252#222#197 + +#255#251#224#199#255#249#220#194#255#245#211#180#255#254#249#243#255#250#226 + +#196#255#236#193#147#255#195'}H'#147#255#255#255#0#255#255#255#0#255#255#255 + +#0#255#255#255#0#255#255#255#0#255#255#255#0#228#187#146#255#254#246#240#255 + +#252#226#205#255#252#227#205#255#250#223#200#255#247#217#188#255#245#233#221 + +#255#250#243#235#255#251#248#243#255#202#131'S'#254#255#255#255#0#255#255#255 + +#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#228#187#146#255 + +#254#247#241#255#252#229#210#255#252#228#209#255#251#226#204#255#249#221#196 + +#255#246#215#187#255#243#209#175#255#250#239#228#255#204#135'X'#254'4'#180 + +#217#208'^'#194#225#250'`'#195#226#250'`'#195#226#250'`'#195#226#250'_'#195 + +#226#250#228#187#145#255#255#247#242#255#254#231#213#255#254#231#213#255#253 + +#229#209#255#250#224#202#255#249#222#196#255#247#217#188#255#253#242#231#255 + +#204#135'W'#254'6'#179#218#248#253#254#254#255#254#255#255#255#254#254#255 + +#255#253#254#255#255#254#255#255#255#228#186#145#255#255#247#240#255#255#231 + +#213#255#253#231#214#255#253#230#212#255#252#228#208#255#251#227#203#255#250 + +#220#194#255#254#243#232#255#204#134'V'#254'5'#175#218#240#247#252#254#255 + +#142#228#248#255#145#222#245#255#159#224#245#255#172#225#246#255#202#132'R' + +#255#255#247#241#255#255#233#217#255#255#234#219#255#255#233#217#255#255#231 + +#215#255#255#229#210#255#255#226#203#255#255#247#241#255#203#133'U'#254'6' + +#170#218#242#241#250#253#255#148#222#245#255#147#220#244#255'd'#188#233#255 + +'5'#148#218#255'5'#148#218#255'5'#148#218#255'5'#148#218#255'5'#148#218#255 + +'5'#148#218#255'5'#148#218#255'5'#148#218#255'5'#148#218#255#251#246#239#255 + +#204#131'U'#254'5'#171#218#250#232#246#251#255'p'#188#231#255'U'#170#226#255 + +'M'#165#224#255#145#201#235#255#250#243#239#255#253#254#253#255#255#253#252 + +#255#255#253#252#255#254#253#252#255#254#252#251#255#254#254#253#255'5'#148 + +#218#255#239#242#232#255#206#129'V'#255'7'#166#218#250#254#255#255#255#248 + +#253#255#255#246#253#255#255#245#252#255#255#243#252#254#255#154#228#244#255 + +#154#230#247#255#155#230#246#255#157#229#245#255#158#229#245#255#159#229#244 + +#255#218#243#248#255'5'#148#218#255#253#244#238#255#202#128'T'#249'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#255#134#193#198#255#201#216#214#255'5'#148#218#255#197'tD'#232#202 + +#127'S'#241'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#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 + +#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',' + +#134#216#0'-'#136#216#247'-'#135#216#247'-'#136#216#247'-'#136#216#247'-'#136 + +#216#247'-'#136#216#247'-'#136#216#247'-'#136#216#247'-'#136#216#247'-'#136 + +#216#247'-'#135#216#247'-'#136#216#247','#134#216#0#255#255#255#0#255#255#255 + +#0#188'k6q'#188'k6'#144#188'k6'#204#188'k6'#238#188'k6'#250#187'k6'#254#187 + +'k6'#255#187'j6'#255#187'j6'#255#188'l9'#255#189'n;'#255#187'm:'#255#187'k8' + +#239#187'p>'#203#182'i5T'#255#255#255#0#188'k6'#155#246#224#209#255#247#224 + +#209#255#254#251#248#255#254#251#247#255#253#249#246#255#252#245#240#255#250 + +#240#234#255#251#242#237#255#253#249#246#255#253#250#247#255#251#241#235#255 + +#248#233#223#254#236#208#189#251#201#137'^'#236#181'i5c'#188'k6'#216#246#223 + +#209#255#233#170#128#255#254#250#246#255#253#250#246#255#200#140'd'#255#251 + +#243#238#255#251#241#234#255#252#246#242#255#254#251#248#255#252#246#241#255 + +#249#236#226#255#248#231#219#255#238#208#186#255#236#208#189#255#187'p>'#248 + +#188'k6'#240#246#223#208#255#232#168'~'#255#252#246#241#255#252#246#241#255 + +#200#140'd'#255#250#241#233#255#251#244#238#255#253#250#247#255#253#249#246 + +#255#250#240#232#255#248#232#221#255#247#230#219#255#225#163'z'#255#239#213 + +#195#255#183'i5'#254#188'k6'#250#245#221#204#255#231#168'~'#255#250#240#232 + +#255#250#240#232#255#201#141'f'#255#250#240#233#255#253#248#243#255#254#250 + +#248#255#252#244#239#255#249#233#223#255#247#231#219#255#247#229#217#255#224 + +#162'x'#255#231#194#169#255#182'h5'#255#187'k6'#254#244#220#201#255#231#167 + +'}'#255#249#236#225#255#249#236#225#255#249#237#227#255#252#244#238#255#253 + +#250#247#255#253#247#243#255#250#237#229#255#247#231#219#255#247#229#217#255 + +#246#229#216#255#222#160'w'#255#228#190#164#255#180'g4'#255#187'k6'#255#244 + +#217#199#255#230#166'}'#255#200#140'd'#255#201#141'e'#255#201#142'g'#255#203 + +#146'l'#255#203#146'm'#255#202#144'i'#255#200#140'e'#255#200#140'd'#255#200 + +#140'd'#255#200#140'd'#255#218#156't'#255#225#186#159#255#179'f4'#255#187'j6' + +#255#242#216#197#255#227#164'{'#255#227#163'z'#255#227#164'z'#255#226#164'{' + +#255#226#163'{'#255#225#163'{'#255#225#162'y'#255#223#160'w'#255#222#159'v' + +#255#221#158't'#255#219#156'r'#255#220#157't'#255#221#181#154#255#177'e4'#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#217#155's'#255#218#176#149#255#175 + +'d3'#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#213#171#142 + +#255#173'c3'#255#186'j6'#255#239#208#187#255#226#162'z'#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#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#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#217#155's'#255#218 - +#176#149#255#175'd3'#255#187'j6'#255#242#216#197#255#227#164'{'#255#227#163 - +'z'#255#227#164'z'#255#226#164'{'#255#226#163'{'#255#225#163'{'#255#225#162 - +'y'#255#223#160'w'#255#222#159'v'#255#221#158't'#255#219#156'r'#255#220#157 - +'t'#255#221#181#154#255#177'e4'#255#187'k6'#255#244#217#199#255#230#166'}' - ,#255#200#140'd'#255#201#141'e'#255#201#142'g'#255#203#146'l'#255#203#146'm' - +#255#202#144'i'#255#200#140'e'#255#200#140'd'#255#200#140'd'#255#200#140'd' - +#255#218#156't'#255#225#186#159#255#179'f4'#255#187'k6'#254#244#220#201#255 - +#231#167'}'#255#249#236#225#255#249#236#225#255#249#237#227#255#252#244#238 - +#255#253#250#247#255#253#247#243#255#250#237#229#255#247#231#219#255#247#229 - +#217#255#246#229#216#255#222#160'w'#255#228#190#164#255#180'g4'#255#188'k6' - +#250#245#221#204#255#231#168'~'#255#250#240#232#255#250#240#232#255#201#141 - +'f'#255#250#240#233#255#253#248#243#255#254#250#248#255#252#244#239#255#249 - +#233#223#255#247#231#219#255#247#229#217#255#224#162'x'#255#231#194#169#255 - +#182'h5'#255#188'k6'#240#246#223#208#255#232#168'~'#255#252#246#241#255#252 - +#246#241#255#200#140'd'#255#250#241#233#255#251#244#238#255#253#250#247#255 - +#253#249#246#255#250#240#232#255#248#232#221#255#247#230#219#255#225#163'z' - +#255#239#213#195#255#183'i5'#254#188'k6'#216#246#223#209#255#233#170#128#255 - +#254#250#246#255#253#250#246#255#200#140'd'#255#251#243#238#255#251#241#234 - +#255#252#246#242#255#254#251#248#255#252#246#241#255#249#236#226#255#248#231 - +#219#255#238#208#186#255#236#208#189#255#187'p>'#248#188'k6'#155#246#224#209 - +#255#247#224#209#255#254#251#248#255#254#251#247#255#253#249#246#255#252#245 - +#240#255#250#240#234#255#251#242#237#255#253#249#246#255#253#250#247#255#251 - +#241#235#255#248#233#223#254#236#208#189#251#201#137'^'#236#181'i5c'#188'k6q' - +#188'k6'#144#188'k6'#204#188'k6'#238#188'k6'#250#187'k6'#254#187'k6'#255#187 - +'j6'#255#187'j6'#255#188'l9'#255#189'n;'#255#187'm:'#255#187'k8'#239#187'p>' - +#203#182'i5T'#255#255#255#0#7'OnClick'#7#15'acSaveAsExecute'#0#0#9'TMenuItem' - +#9'MenuItem1'#7'Caption'#6#1'-'#0#0#9'TMenuItem'#7'mnuQuit'#6'Action'#7#6'Ac' - +'Quit'#11'Bitmap.Data'#10':'#4#0#0'6'#4#0#0'BM6'#4#0#0#0#0#0#0'6'#0#0#0'('#0 - +#0#0#16#0#0#0#16#0#0#0#1#0' '#0#0#0#0#0#0#4#0#0'd'#0#0#0'd'#0#0#0#0#0#0#0#0#0 - +#0#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#29'c'#155#22#25'`' - +#152'9'#20']'#149'b'#16'Z'#146#136#13'X'#144#164#19'\'#146#252#12'W'#143#237 - +#153#153#153#255'qqq'#255'TTT'#255'QQQ'#255'OOO'#255'LLL'#255'JJJ'#255'GGG' - +#255'EEE'#255'%g'#157#255'2t'#168#255'=|'#175#255'G'#132#181#255'N'#138#186 - +#255'>~'#173#255#12'W'#143#234#255#255#255#0#255#255#255#0'XXX'#255#162#162 - +#162#255#162#162#162#255#163#163#163#255#164#164#164#255#164#164#164#255#165 - +#165#165#255'/o'#165#255'x'#171#210#255'x'#171#211#255's'#167#209#255'i'#160 - +#205#255'@'#127#174#255#15'Y'#145#234#255#255#255#0#255#255#255#0'\\\'#255 - +#161#161#161#255''#255'4~;'#255'1y7'#255'.u4'#255'I' - +#145'P'#255'F'#143'L'#255'9s='#255#161#161#161#255#162#162#162#255'E~'#180 - +#255#136#183#217#255'g'#163#207#255'a'#158#204#255'c'#159#204#255'E'#131#177 - +#255#31'd'#156#234';'#135'B'#255#137#203#146#255#132#200#141#255#128#198#136 - +#255'{'#195#131#255'w'#193#127#255'G'#143'M'#255';t?'#255#161#161#161#255'L' - +#132#186#255#141#187#219#255'n'#168#209#255'f'#166#209#255'_'#180#223#255'G' - +#133#177#255'%i'#161#234'>'#139'F'#255#143#206#153#255'}'#198#135#255'x'#195 - +#129#255's'#192'|'#255't'#192'|'#255'y'#194#129#255'I'#144'O'#255'T'#127'W' - +#255'T'#137#191#255#148#191#221#255'u'#173#212#255'c'#184#225#255'K'#212#255 - +#255'B'#139#184#255',n'#166#234'A'#144'J'#255#148#210#159#255#145#208#154#255 - +#141#205#150#255#137#203#146#255#132#200#141#255'Q'#152'X'#255'A|F'#255#159 - +#159#159#255'Z'#142#196#255#152#195#224#255'|'#179#215#255't'#175#214#255'^' - +#196#237#255'K'#136#179#255'4s'#171#234'D'#148'M'#255'B'#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'w' - +'ww'#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#229#255#143#193#223 - +#255#137#189#220#255#139#189#220#255'S'#141#182#255'K'#132#188#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#199#225#255#145#194#222#255'V'#143#183#255'R'#137 - ,#193#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#208#230#255'X'#144#184#255'Y'#142#198#234#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#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#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#255#255 - +#255#0#255#255#255#0'm'#156#212#137'j'#154#210#251'f'#151#207#238#7'OnClick' - +#7#13'acQuitExecute'#0#0#0#0#10'TImageList'#10'ImageList1'#4'left'#3#176#0#3 - +'top'#2'x'#6'Bitmap'#10#14#12#0#0'Li'#3#0#0#0#16#0#0#0#16#0#0#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#234 - +#195#157#255#230#191#150#255#228#187#146#255#228#187#146#255#209#160'l'#245 - +#208#158'm'#246#204#150'_'#218#196'yB~'#178'g<'#9#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#229 - +#190#150#255#255#255#254#255#253#243#233#255#253#243#234#255#252#242#232#255 - +#250#239#227#255#250#242#231#255#234#187#136#255#207#133'U'#179#180'i='#12 - +#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255 - +#255#255#0#228#187#147#255#254#245#237#255#252#222#197#255#251#224#199#255 - +#249#220#194#255#245#211#180#255#254#249#243#255#250#226#196#255#236#193#147 - +#255#195'}H'#147#255#255#255#0#255#255#255#0#255#255#255#0#255#255#255#0#255 - +#255#255#0#255#255#255#0#228#187#146#255#254#246#240#255#252#226#205#255#252 - +#227#205#255#250#223#200#255#247#217#188#255#245#233#221#255#250#243#235#255 - +#251#248#243#255#202#131'S'#254#255#255#255#0#255#255#255#0#255#255#255#0#255 - +#255#255#0#255#255#255#0#255#255#255#0#228#187#146#255#254#247#241#255#252 - +#229#210#255#252#228#209#255#251#226#204#255#249#221#196#255#246#215#187#255 - +#243#209#175#255#250#239#228#255#204#135'X'#254'4'#180#217#208'^'#194#225#250 - +'`'#195#226#250'`'#195#226#250'`'#195#226#250'_'#195#226#250#228#187#145#255 - +#255#247#242#255#254#231#213#255#254#231#213#255#253#229#209#255#250#224#202 - +#255#249#222#196#255#247#217#188#255#253#242#231#255#204#135'W'#254'6'#179 - +#218#248#253#254#254#255#254#255#255#255#254#254#255#255#253#254#255#255#254 - +#255#255#255#228#186#145#255#255#247#240#255#255#231#213#255#253#231#214#255 - +#253#230#212#255#252#228#208#255#251#227#203#255#250#220#194#255#254#243#232 - +#255#204#134'V'#254'5'#175#218#240#247#252#254#255#142#228#248#255#145#222 - +#245#255#159#224#245#255#172#225#246#255#202#132'R'#255#255#247#241#255#255 - +#233#217#255#255#234#219#255#255#233#217#255#255#231#215#255#255#229#210#255 - +#255#226#203#255#255#247#241#255#203#133'U'#254'6'#170#218#242#241#250#253 - +#255#148#222#245#255#147#220#244#255'd'#188#233#255'5'#148#218#255'5'#148#218 - +#255'5'#148#218#255'5'#148#218#255'5'#148#218#255'5'#148#218#255'5'#148#218 - +#255'5'#148#218#255'5'#148#218#255#251#246#239#255#204#131'U'#254'5'#171#218 - +#250#232#246#251#255'p'#188#231#255'U'#170#226#255'M'#165#224#255#145#201#235 - +#255#250#243#239#255#253#254#253#255#255#253#252#255#255#253#252#255#254#253 - +#252#255#254#252#251#255#254#254#253#255'5'#148#218#255#239#242#232#255#206 - +#129'V'#255'7'#166#218#250#254#255#255#255#248#253#255#255#246#253#255#255 - +#245#252#255#255#243#252#254#255#154#228#244#255#154#230#247#255#155#230#246 - +#255#157#229#245#255#158#229#245#255#159#229#244#255#218#243#248#255'5'#148 - +#218#255#253#244#238#255#202#128'T'#249'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#255#134#193#198 - +#255#201#216#214#255'5'#148#218#255#197'tD'#232#202#127'S'#241'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#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#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','#134#216#0'-'#136#216#247'-'#135#216 - +#247'-'#136#216#247'-'#136#216#247'-'#136#216#247'-'#136#216#247'-'#136#216 - +#247'-'#136#216#247'-'#136#216#247'-'#136#216#247'-'#135#216#247'-'#136#216 - +#247','#134#216#0#255#255#255#0#255#255#255#0#188'k6q'#188'k6'#144#188'k6' - +#204#188'k6'#238#188'k6'#250#187'k6'#254#187'k6'#255#187'j6'#255#187'j6'#255 - ,#188'l9'#255#189'n;'#255#187'm:'#255#187'k8'#239#187'p>'#203#182'i5T'#255#255 - +#255#0#188'k6'#155#246#224#209#255#247#224#209#255#254#251#248#255#254#251 - +#247#255#253#249#246#255#252#245#240#255#250#240#234#255#251#242#237#255#253 - +#249#246#255#253#250#247#255#251#241#235#255#248#233#223#254#236#208#189#251 - +#201#137'^'#236#181'i5c'#188'k6'#216#246#223#209#255#233#170#128#255#254#250 - +#246#255#253#250#246#255#200#140'd'#255#251#243#238#255#251#241#234#255#252 - +#246#242#255#254#251#248#255#252#246#241#255#249#236#226#255#248#231#219#255 - +#238#208#186#255#236#208#189#255#187'p>'#248#188'k6'#240#246#223#208#255#232 - +#168'~'#255#252#246#241#255#252#246#241#255#200#140'd'#255#250#241#233#255 - +#251#244#238#255#253#250#247#255#253#249#246#255#250#240#232#255#248#232#221 - +#255#247#230#219#255#225#163'z'#255#239#213#195#255#183'i5'#254#188'k6'#250 - +#245#221#204#255#231#168'~'#255#250#240#232#255#250#240#232#255#201#141'f' - +#255#250#240#233#255#253#248#243#255#254#250#248#255#252#244#239#255#249#233 - +#223#255#247#231#219#255#247#229#217#255#224#162'x'#255#231#194#169#255#182 - +'h5'#255#187'k6'#254#244#220#201#255#231#167'}'#255#249#236#225#255#249#236 - +#225#255#249#237#227#255#252#244#238#255#253#250#247#255#253#247#243#255#250 - +#237#229#255#247#231#219#255#247#229#217#255#246#229#216#255#222#160'w'#255 - +#228#190#164#255#180'g4'#255#187'k6'#255#244#217#199#255#230#166'}'#255#200 - +#140'd'#255#201#141'e'#255#201#142'g'#255#203#146'l'#255#203#146'm'#255#202 - +#144'i'#255#200#140'e'#255#200#140'd'#255#200#140'd'#255#200#140'd'#255#218 - +#156't'#255#225#186#159#255#179'f4'#255#187'j6'#255#242#216#197#255#227#164 - +'{'#255#227#163'z'#255#227#164'z'#255#226#164'{'#255#226#163'{'#255#225#163 - +'{'#255#225#162'y'#255#223#160'w'#255#222#159'v'#255#221#158't'#255#219#156 - +'r'#255#220#157't'#255#221#181#154#255#177'e4'#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#217#155's'#255#218#176#149#255#175'd3'#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#213#171#142#255#173'c3'#255#186 - +'j6'#255#239#208#187#255#226#162'z'#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 - +#254#251#248#255#254#251#248#255#254#251#248#255#211#150'm'#255#210#167#138 - +#255#171'b2'#255#187'k8'#255#239#206#184#255#225#162'y'#255#254#250#247#255 - +'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255 - +'b'#192#136#255'b'#192#136#255'b'#192#136#255#253#249#246#255#207#147'j'#255 - +#206#163#132#255#170'a2'#255#187'l8'#255#238#204#182#255#225#162'z'#255#254 - +#250#247#255#191#220#194#255#191#220#194#255#191#220#194#255#191#220#194#255 - +#191#220#194#255#191#220#194#255#191#220#194#255#191#220#194#255#253#249#246 - +#255#205#144'h'#255#204#158#129#255#168'a2'#255#186'k7'#254#237#202#179#255 - +#224#162'z'#255#254#250#247#255'b'#192#136#255'b'#192#136#255'b'#192#136#255 - +'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255 - +#253#249#246#255#202#141'e'#255#201#155'|'#255#167'`1'#254#186'j5'#222#235 - +#198#173#255#234#197#173#255#254#251#248#255#254#251#248#255#254#251#248#255 + +#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'k8'#255#239#206#184#255#225#162'y' + +#255#254#250#247#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136 + +#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255#253#249#246 + +#255#207#147'j'#255#206#163#132#255#170'a2'#255#187'l8'#255#238#204#182#255 + +#225#162'z'#255#254#250#247#255#191#220#194#255#191#220#194#255#191#220#194 + +#255#191#220#194#255#191#220#194#255#191#220#194#255#191#220#194#255#191#220 + +#194#255#253#249#246#255#205#144'h'#255#204#158#129#255#168'a2'#255#186'k7' + +#254#237#202#179#255#224#162'z'#255#254#250#247#255'b'#192#136#255'b'#192#136 + +#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136#255'b'#192#136 + +#255'b'#192#136#255#253#249#246#255#202#141'e'#255#201#155'|'#255#167'`1'#254 + +#186'j5'#222#235#198#173#255#234#197#173#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#254#251#248#255#254#251#248#255#200#154'|'#255#199#152'y'#255#167'`1' - +#237#186'j6'#0#185'i5'#181#184'i5'#238#183'h5'#255#181'h5'#255#180'g4'#255 - +#178'f4'#255#176'e3'#255#174'd3'#255#172'c2'#255#170'b2'#255#169'a2'#255#168 - +'`1'#255#167'`1'#254#166'`1'#241#168'a1'#196#255#255#255#0#255#255#255#0#255 + +#255#254#251#248#255#254#251#248#255#254#251#248#255#200#154'|'#255#199#152 + +'y'#255#167'`1'#237#186'j6'#0#185'i5'#181#184'i5'#238#183'h5'#255#181'h5'#255 + +#180'g4'#255#178'f4'#255#176'e3'#255#174'd3'#255#172'c2'#255#170'b2'#255#169 + +'a2'#255#168'`1'#255#167'`1'#254#166'`1'#241#168'a1'#196#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#255#255#255#0#255#255#255#0#255#255#255#0 - +'m'#156#212#137'j'#154#210#251'f'#151#207#238#255#255#255#0#255#255#255#0#255 + +#255#255#255#0'm'#156#212#137'j'#154#210#251'f'#151#207#238#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#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#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#199#225#255 - +#145#194#222#255'V'#143#183#255'R'#137#193#234#255#255#255#0#255#255#255#0'z' - +'zz'#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#229#255#143#193#223#255 - +#137#189#220#255#139#189#220#255'S'#141#182#255'K'#132#188#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 - +#189#220#255#131#185#218#255#132#185#218#255'Q'#139#181#255'C~'#182#234'D' - +#148'M'#255'B'#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 - +'A'#144'J'#255#148#210#159#255#145#208#154#255#141#205#150#255#137#203#146 - +#255#132#200#141#255'Q'#152'X'#255'A|F'#255#159#159#159#255'Z'#142#196#255 - +#152#195#224#255'|'#179#215#255't'#175#214#255'^'#196#237#255'K'#136#179#255 - +'4s'#171#234'>'#139'F'#255#143#206#153#255'}'#198#135#255'x'#195#129#255's' - +#192'|'#255't'#192'|'#255'y'#194#129#255'I'#144'O'#255'T'#127'W'#255'T'#137 - +#191#255#148#191#221#255'u'#173#212#255'c'#184#225#255'K'#212#255#255'B'#139 - +#184#255',n'#166#234';'#135'B'#255#137#203#146#255#132#200#141#255#128#198 - +#136#255'{'#195#131#255'w'#193#127#255'G'#143'M'#255';t?'#255#161#161#161#255 - +'L'#132#186#255#141#187#219#255'n'#168#209#255'f'#166#209#255'_'#180#223#255 - +'G'#133#177#255'%i'#161#234'7'#130'>'#255'4~;'#255'1y7'#255'.u4'#255'I'#145 - +'P'#255'F'#143'L'#255'9s='#255#161#161#161#255#162#162#162#255'E~'#180#255 - +#136#183#217#255'g'#163#207#255'a'#158#204#255'c'#159#204#255'E'#131#177#255 - +#31'd'#156#234#255#255#255#0#255#255#255#0'```'#255#160#160#160#255'=vA'#255 - +'6q9'#255#162#162#162#255#162#162#162#255#163#163#163#255'=y'#176#255#130#179 - +#215#255'b'#159#204#255'Z'#154#201#255'^'#155#202#255'C'#129#175#255#25'`' - +#152#234#255#255#255#0#255#255#255#0'\\\'#255#161#161#161#255''#139'F'#255#143#206#153#255'}'#198#135#255'x'#195#129 + +#255's'#192'|'#255't'#192'|'#255'y'#194#129#255'I'#144'O'#255'T'#127'W'#255 + +'T'#137#191#255#148#191#221#255'u'#173#212#255'c'#184#225#255'K'#212#255#255 + +'B'#139#184#255',n'#166#234';'#135'B'#255#137#203#146#255#132#200#141#255#128 + +#198#136#255'{'#195#131#255'w'#193#127#255'G'#143'M'#255';t?'#255#161#161#161 + +#255'L'#132#186#255#141#187#219#255'n'#168#209#255'f'#166#209#255'_'#180#223 + +#255'G'#133#177#255'%i'#161#234'7'#130'>'#255'4~;'#255'1y7'#255'.u4'#255'I' + +#145'P'#255'F'#143'L'#255'9s='#255#161#161#161#255#162#162#162#255'E~'#180 + +#255#136#183#217#255'g'#163#207#255'a'#158#204#255'c'#159#204#255'E'#131#177 + +#255#31'd'#156#234#255#255#255#0#255#255#255#0'```'#255#160#160#160#255'=vA' + +#255'6q9'#255#162#162#162#255#162#162#162#255#163#163#163#255'=y'#176#255#130 + +#179#215#255'b'#159#204#255'Z'#154#201#255'^'#155#202#255'C'#129#175#255#25 + +'`'#152#234#255#255#255#0#255#255#255#0'\\\'#255#161#161#161#255' 0 then @@ -130,13 +146,18 @@ var pages: TStrings; i: Integer; begin + // Load file sWorksheetGrid1.LoadFromSpreadsheetFile(AFileName); + + // Update user interface Caption := Format('fpsGrid - %s (%s)', [ AFilename, GetFileFormatName(sWorksheetGrid1.Workbook.FileFormat) ]); - CbShowGridLines.Checked := sWorksheetGrid1.Worksheet.ShowGridLines; - CbShowHeaders.Checked := sWorksheetGrid1.Worksheet.ShowHeaders; + CbShowGridLines.Checked := (soShowGridLines in sWorksheetGrid1.Worksheet.Options); + CbShowHeaders.Checked := (soShowHeaders in sWorksheetGrid1.Worksheet.Options); + EdFrozenCols.Value := sWorksheetGrid1.FrozenCols; + EdFrozenRows.Value := sWorksheetGrid1.FrozenRows; // Create a tab in the pagecontrol for each worksheet contained in the workbook // This would be easer with a TTabControl. This has display issues, though. diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas index 50e6762ce..82dfac923 100755 --- a/components/fpspreadsheet/fpspreadsheet.pas +++ b/components/fpspreadsheet/fpspreadsheet.pas @@ -302,6 +302,9 @@ type PCol = ^TCol; + TsSheetOption = (soShowGridLines, soShowHeaders, soHasFrozenPanes, soSelected); + TsSheetOptions = set of TsSheetOption; + type TsCustomSpreadReader = class; @@ -316,9 +319,9 @@ type FCells: TAvlTree; // Items are TCell FCurrentNode: TAVLTreeNode; // For GetFirstCell and GetNextCell FRows, FCols: TIndexedAVLTree; // This lists contain only rows or cols with styles different from the standard - FShowGridLines: Boolean; - FShowHeaders: Boolean; - FSelected: Boolean; + FLeftPaneWidth: Integer; + FTopPaneHeight: Integer; + FOptions: TsSheetOptions; procedure RemoveCallback(data, arg: pointer); public Name: string; @@ -389,9 +392,9 @@ type property Rows: TIndexedAVLTree read FRows; property Workbook: TsWorkbook read FWorkbook; // These are properties to interface to fpspreadsheetgrid. - property ShowGridLines: Boolean read FShowGridLines write FShowGridLines; - property ShowHeaders: Boolean read FShowHeaders write FShowHeaders; - property Selected: Boolean read FSelected write FSelected; + property Options: TsSheetOptions read FOptions write FOptions; + property LeftPaneWidth: Integer read FLeftPaneWidth write FLeftPaneWidth; + property TopPaneHeight: Integer read FTopPaneHeight write FTopPaneHeight; end; { TsWorkbook } @@ -813,9 +816,7 @@ begin FRows := TIndexedAVLTree.Create(@CompareRows); FCols := TIndexedAVLTree.Create(@CompareCols); - FShowGridLines := true; - FShowHeaders := true; - FSelected := true; + FOptions := [soShowGridLines, soShowHeaders]; end; {@@ diff --git a/components/fpspreadsheet/fpspreadsheetgrid.pas b/components/fpspreadsheet/fpspreadsheetgrid.pas index 98f7cfbcc..6bc469314 100644 --- a/components/fpspreadsheet/fpspreadsheetgrid.pas +++ b/components/fpspreadsheet/fpspreadsheetgrid.pas @@ -25,15 +25,20 @@ type FWorkbook: TsWorkbook; FWorksheet: TsWorksheet; FHeaderCount: Integer; + FFrozenCols: Integer; + FFrozenRows: Integer; function CalcAutoRowHeight(ARow: Integer): Integer; function CalcColWidth(AWidth: Single): Integer; function CalcRowHeight(AHeight: Single): Integer; function GetShowGridLines: Boolean; function GetShowHeaders: Boolean; + procedure SetFrozenCols(AValue: Integer); + procedure SetFrozenRows(AValue: Integer); procedure SetShowGridLines(AValue: Boolean); procedure SetShowHeaders(AValue: Boolean); protected { Protected declarations } + procedure DefaultDrawCell(ACol, ARow: Integer; var ARect: TRect; AState: TGridDrawState); override; procedure DoPrepareCanvas(ACol, ARow: Integer; AState: TGridDrawState); override; procedure DrawAllRows; override; procedure DrawTextInCell(ACol, ARow: Integer; ARect: TRect; AState: TGridDrawState); override; @@ -42,6 +47,8 @@ type procedure Loaded; override; procedure Setup; property DisplayFixedColRow: Boolean read GetShowHeaders write SetShowHeaders default true; + property FrozenCols: Integer read FFrozenCols write SetFrozenCols; + property FrozenRows: Integer read FFrozenRows write SetFrozenRows; property ShowGridLines: Boolean read GetShowGridLines write SetShowGridLines default true; property ShowHeaders: Boolean read GetShowHeaders write SetShowHeaders default true; public @@ -65,6 +72,8 @@ type published // inherited from TsCustomWorksheetGrid property DisplayFixedColRow; deprecated 'Use ShowHeaders'; + property FrozenCols; + property FrozenRows; property ShowGridLines; property ShowHeaders; @@ -305,6 +314,37 @@ begin Result := round(AHeight / 25.4 * Screen.PixelsPerInch) + 4; end; +procedure TsCustomWorksheetGrid.DefaultDrawCell(aCol, aRow: Integer; var aRect: TRect; + AState: TGridDrawState); +var + wasFixed: Boolean; +begin + wasFixed := false; + if (gdFixed in AState) then + if ShowHeaders then begin + if ((ARow < FixedRows) and (ARow > 0) and (ACol > 0)) or + ((ACol < FixedCols) and (ACol > 0) and (ARow > 0)) + then + wasFixed := true; + end else begin + if (ARow < FixedRows) or (ACol < FixedCols) then + wasFixed := true; + end; + + if wasFixed then begin + wasFixed := true; + AState := AState - [gdFixed]; + Canvas.Brush.Color := clWindow; + end; + + inherited DefaultDrawCell(ACol, ARow, ARect, AState); + + if wasFixed then begin + DrawCellGrid(ACol, ARow, ARect, AState); + AState := AState + [gdFixed]; + end; +end; + { Adjusts the grid's canvas before painting a given cell. Considers, e.g. background color, horizontal alignment, vertical alignment, etc. } procedure TsCustomWorksheetGrid.DoPrepareCanvas(ACol, ARow: Integer; @@ -372,6 +412,7 @@ begin end; end; Canvas.TextStyle := ts; + inherited DoPrepareCanvas(ACol, ARow, AState); end; @@ -380,9 +421,9 @@ end; procedure TsCustomWorksheetGrid.DrawAllRows; var cell: PCell; - c, r: Integer; - rect: TRect; - headerRect: TRect; + c, r, tmp: Integer; + rect, cliprect: TRect; + rgn: HRGN; procedure DrawBorderLine(ACell: PCell; ARect: TRect; ABorder: TsCellBorder; ALineStyle: TsLineStyle); @@ -397,7 +438,6 @@ var ($FFFFFFFF, $FFFFFFFF, $07070707, $AAAAAAAA, $FFFFFFFF, $FFFFFFFF); var w: Integer; - r: TRect; begin if ALineStyle = lsDouble then case ABorder of @@ -424,16 +464,11 @@ var //Canvas.Pen.Pattern := PEN_PATTERNS[ACell^.BorderStyles[ABorder].LineStyle]; //Canvas.Pen.EndCap := pecSquare; - if ARect.Bottom < headerRect.Bottom then exit; - r := ARect; - if ARect.Top < headerRect.Bottom then r.Top := headerRect.Bottom; - case ABorder of - cbEast : Canvas.Line(ARect.Right-1, r.Top, ARect.Right-1, ARect.Bottom-w); + cbEast : Canvas.Line(ARect.Right-1, ARect.Top, ARect.Right-1, ARect.Bottom-w); cbSouth: Canvas.Line(ARect.Left-1, ARect.Bottom-1, ARect.Right-w, ARect.Bottom-1); - cbWest : Canvas.Line(ARect.Left-1, r.Top, ARect.Left-1, ARect.Bottom-w); - cbNorth: if ARect.Top >= headerRect.Bottom then - Canvas.Line(ARect.Left-1, ARect.Top-1, ARect.Right-w, ARect.Top-1); + cbWest : Canvas.Line(ARect.Left-1, ARect.Top, ARect.Left-1, ARect.Bottom-w); + cbNorth: Canvas.Line(ARect.Left-1, ARect.Top-1, ARect.Right-w, ARect.Top-1); end; end; end; @@ -442,27 +477,37 @@ begin inherited; if FWorksheet = nil then exit; - if (FHeaderCount > 0) then - HeaderRect := CellRect(0, 0) - else - HeaderRect := Classes.Rect(0, 0, 0, 0); + Canvas.SaveHandleState; + try + // Avoid painting into the fixed cells + cliprect := ClientRect; + if FixedCols > 0 then + ColRowToOffset(True, True, FixedCols-1, tmp, cliprect.Left); + if FixedRows > 0 then + ColRowToOffset(False, True, FixedRows-1, tmp, cliprect.Top); + rgn := CreateRectRgn(cliprect.Left, cliprect.top, cliprect.Right, cliprect.Bottom); + SelectClipRgn(Canvas.Handle, Rgn); - cell := FWorksheet.GetFirstCell; - while cell <> nil do begin - if (uffBorder in cell^.UsedFormattingFields) then begin - c := cell^.Col + FHeaderCount; - r := cell^.Row + FHeaderCount; - rect := CellRect(c, r); - if (cbNorth in cell^.Border) then - DrawBorderLine(cell, rect, cbNorth, cell^.BorderStyles[cbNorth].LineStyle); - if cbEast in cell^.Border then - DrawBorderLine(cell, rect, cbEast, cell^.BorderStyles[cbEast].LineStyle); - if cbSouth in cell^.Border then - DrawBorderLine(cell, rect, cbSouth, cell^.BorderStyles[cbSouth].LineStyle); - if cbWest in cell^.Border then - DrawBorderLine(cell, rect, cbWest, cell^.BorderStyles[cbWest].LineStyle); + cell := FWorksheet.GetFirstCell; + while cell <> nil do begin + if (uffBorder in cell^.UsedFormattingFields) then begin + c := cell^.Col + FHeaderCount; + r := cell^.Row + FHeaderCount; + rect := CellRect(c, r); + if (cbNorth in cell^.Border) then + DrawBorderLine(cell, rect, cbNorth, cell^.BorderStyles[cbNorth].LineStyle); + if cbEast in cell^.Border then + DrawBorderLine(cell, rect, cbEast, cell^.BorderStyles[cbEast].LineStyle); + if cbSouth in cell^.Border then + DrawBorderLine(cell, rect, cbSouth, cell^.BorderStyles[cbSouth].LineStyle); + if cbWest in cell^.Border then + DrawBorderLine(cell, rect, cbWest, cell^.BorderStyles[cbWest].LineStyle); + end; + cell := FWorksheet.GetNextCell; end; - cell := FWorksheet.GetNextCell; + DeleteObject(rgn); + finally + Canvas.RestoreHandleState; end; end; @@ -764,6 +809,18 @@ begin Setup; end; +procedure TsCustomWorksheetGrid.SetFrozenCols(AValue: Integer); +begin + FFrozenCols := AValue; + Setup; +end; + +procedure TsCustomWorksheetGrid.SetFrozenRows(AValue: Integer); +begin + FFrozenRows := AValue; + Setup; +end; + procedure TsCustomWorksheetGrid.SetShowGridLines(AValue: Boolean); begin if AValue = GetShowGridLines then Exit; @@ -785,6 +842,7 @@ var i: Integer; lCol: PCol; lRow: PRow; + fc, fr: Integer; begin if (FWorksheet = nil) or (FWorksheet.GetCellCount = 0) then begin if ShowHeaders then begin @@ -800,13 +858,15 @@ begin RowCount := 0; end; end else - if ShowHeaders then begin - ColCount := FWorksheet.GetLastColNumber + 2; - RowCount := FWorksheet.GetLastRowNumber + 2; - FixedCols := 1; - FixedRows := 1; - ColWidths[0] := Canvas.TextWidth(' 999999 '); - // Setup column widths + if FWorksheet <> nil then begin + ColCount := FWorksheet.GetLastColNumber + 1 + FHeaderCount; + RowCount := FWorksheet.GetLastRowNumber + 1 + FHeaderCount; + FixedCols := FFrozenCols + FHeaderCount; + FixedRows := FFrozenRows + FHeaderCount; + if ShowHeaders then begin + ColWidths[0] := Canvas.TextWidth(' 999999 '); + RowHeights[0] := DefaultRowHeight; + end; for i := FHeaderCount to ColCount-1 do begin lCol := FWorksheet.FindCol(i - FHeaderCount); if (lCol <> nil) then @@ -814,21 +874,6 @@ begin else ColWidths[i] := DefaultColWidth; end; - end else begin - ColCount := FWorksheet.GetLastColNumber + 1; - RowCount := FWorksheet.GetLastRowNumber + 1; - FixedCols := 0; - FixedRows := 0; - for i := 0 to ColCount-1 do begin - lCol := FWorksheet.FindCol(i); - if (lCol <> nil) then - ColWidths[i] := CalcColWidth(lCol^.Width) - else - ColWidths[i] := DefaultColWidth; - end; - end; - if FWorksheet <> nil then begin - RowHeights[0] := DefaultRowHeight; for i := FHeaderCount to RowCount-1 do begin lRow := FWorksheet.FindRow(i - FHeaderCount); if (lRow = nil) or lRow^.AutoHeight then @@ -836,20 +881,22 @@ begin else RowHeights[i] := CalcRowHeight(lRow^.Height); end; - end - else - for i:=0 to RowCount-1 do begin - RowHeights[i] := DefaultRowHeight; - end; - Invalidate; + end; end; procedure TsCustomWorksheetGrid.LoadFromWorksheet(AWorksheet: TsWorksheet); begin FWorksheet := AWorksheet; if FWorksheet <> nil then begin - ShowHeaders := FWorksheet.ShowHeaders; - ShowGridLines := FWorksheet.ShowGridLines; + ShowHeaders := (soShowHeaders in FWorksheet.Options); + ShowGridLines := (soShowGridLines in FWorksheet.Options); + if (soHasFrozenPanes in FWorksheet.Options) then begin + FrozenCols := FWorksheet.LeftPaneWidth; + FrozenRows := FWorksheet.TopPaneHeight; + end else begin + FrozenCols := 0; + FrozenRows := 0; + end; end; Setup; end; diff --git a/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas b/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas index 8c6f37a3f..f0b1e3574 100644 --- a/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas +++ b/components/fpspreadsheet/reference/BIFFExplorer/bebiffgrid.pas @@ -64,6 +64,7 @@ type procedure ShowNumberCell; procedure ShowObj; procedure ShowPalette; + procedure ShowPane; procedure ShowPassword; procedure ShowPrecision; procedure ShowPrintGridLines; @@ -297,6 +298,8 @@ begin ShowWindow2; $0040: ShowBackup; + $0041: + ShowPane; $0042: ShowCodePage; $0043: @@ -2345,6 +2348,42 @@ begin end; +procedure TBIFFGrid.ShowPane; +var + numBytes: Integer; + w: Word; + b: Byte; +begin + RowCount := FixedRows + IfThen(FFormat < sfExcel5, 5, 6); + + numBytes := 2; + Move(FBuffer[FBufferIndex], w, numBytes); + ShowInRow(FCurrRow, FBufferIndex, numBytes, IntToStr(WordLEToN(w)), + 'Position of vertical split (twips or columns (if frozen))'); + + Move(FBuffer[FBufferIndex], w, numBytes); + ShowInRow(FCurrRow, FBUfferIndex, numBytes, IntToStr(WordLEToN(w)), + 'Position of horizontal split (twips or rows (if frozen))'); + + Move(FBuffer[FBufferIndex], w, numBytes); + ShowInRow(FCurrRow, FBUfferIndex, numBytes, IntToStr(WordLEToN(w)), + 'Index to first visible row in bottom pane(s)'); + + Move(FBuffer[FBufferIndex], w, numBytes); + ShowInRow(FCurrRow, FBUfferIndex, numBytes, IntToStr(WordLEToN(w)), + 'Index to first visible column in right pane(s)'); + + numBytes := 1; + b := FBuffer[FBufferIndex]; + ShowInRow(FCurrRow, FBUfferIndex, numBytes, IntToStr(b), + 'Identifier of pane with active cell cursor'); + + if FFormat >= sfExcel5 then begin + b := FBuffer[FBufferIndex]; + ShowInRow(FCurrRow, FBUfferIndex, numBytes, IntToStr(b), 'not used'); + end; +end; + procedure TBIFFGrid.ShowPassword; var numBytes: Integer; diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas index 3a8d791f4..f3510958a 100755 --- a/components/fpspreadsheet/xlsbiff2.pas +++ b/components/fpspreadsheet/xlsbiff2.pas @@ -60,6 +60,7 @@ type procedure ReadNumber(AStream: TStream); override; procedure ReadRowColXF(AStream: TStream; out ARow, ACol: Cardinal; out AXF: Word); override; procedure ReadRowInfo(AStream: TStream); override; + procedure ReadWindow2(AStream: TStream); override; procedure ReadXF(AStream: TStream); public { General reading methods } @@ -88,6 +89,7 @@ type AddBackground: Boolean = false); procedure WriteXFFieldsForFormattingStyles(AStream: TStream); procedure WriteXFRecords(AStream: TStream); + 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; @@ -143,6 +145,9 @@ var implementation +uses + Math; + const { Excel record IDs } INT_EXCEL_ID_BLANK = $0001; @@ -156,6 +161,7 @@ const INT_EXCEL_ID_FORMAT = $001E; INT_EXCEL_ID_FORMATCOUNT= $001F; INT_EXCEL_ID_COLWIDTH = $0024; + INT_EXCEL_ID_WINDOW2 = $003E; INT_EXCEL_ID_XF = $0043; INT_EXCEL_ID_IXFE = $0044; INT_EXCEL_ID_FONTCOLOR = $0045; @@ -421,6 +427,8 @@ begin INT_EXCEL_ID_FORMULA : ReadFormula(AStream); INT_EXCEL_ID_COLWIDTH : ReadColWidth(AStream); INT_EXCEL_ID_ROWINFO : ReadRowInfo(AStream); + INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream); + INT_EXCEL_ID_PANE : ReadPane(AStream); INT_EXCEL_ID_XF : ReadXF(AStream); INT_EXCEL_ID_BOF : ; INT_EXCEL_ID_EOF : BIFF2EOF := True; @@ -560,6 +568,51 @@ begin lRow^.AutoHeight := true; end; +{ Reads the WINDOW2 record containing information like "show grid lines", + "show sheet headers", "panes are frozen", etc. } +procedure TsSpreadBIFF2Reader.ReadWindow2(AStream: TStream); +var + b: byte; + w: Word; + rgb: DWord; +begin + // Show formulas, not results + b := AStream.ReadByte; + + // Show grid lines + if AStream.ReadByte <> 0 then + FWorksheet.Options := FWorksheet.Options + [soShowGridLines] + else + FWorksheet.Options := FWorksheet.Options - [soShowGridLines]; + + // Show sheet headers + if AStream.ReadByte <> 0 then + FWorksheet.Options := FWorksheet.Options + [soShowHeaders] + else + FWorksheet.Options := FWorksheet.Options - [soShowHeaders]; + + // Panes are frozen + if AStream.ReadByte <> 0 then + FWorksheet.Options := FWorksheet.Options + [soHasFrozenPanes] + else + FWorksheet.Options := FWorksheet.Options - [soHasFrozenPanes]; + + // Show zero values + b := AStream.ReadByte; + + // Index to first visible row + w := WordLEToN(AStream.ReadWord); + + // Indoex to first visible column + w := WordLEToN(AStream.ReadWord); + + // Use automatic grid line color (0= manual) + b := AStream.ReadByte; + + // Manual grid line line color (rgb) + rgb := DWordToLE(AStream.ReadDWord); +end; + procedure TsSpreadBIFF2Reader.ReadXF(AStream: TStream); { Offset Size Contents 0 1 Index to FONT record (➜5.45) @@ -764,18 +817,67 @@ end; so only the first will be written. } procedure TsSpreadBIFF2Writer.WriteToStream(AStream: TStream); +var + sheet: TsWorksheet; begin + sheet := Workbook.GetFirstWorksheet; + WriteBOF(AStream); - - WriteFonts(AStream); - WriteFormats(AStream); - WriteXFRecords(AStream); - WriteColWidths(AStream); - WriteCellsToStream(AStream, Workbook.GetFirstWorksheet.Cells); - + WriteFonts(AStream); + WriteFormats(AStream); + WriteXFRecords(AStream); + WriteColWidths(AStream); + { -- currently not working + WriteWindow2(AStream, sheet); + WritePane(AStream, sheet, false); // false for "is not BIFF5 or BIFF8" + } + WriteCellsToStream(AStream, sheet.Cells); WriteEOF(AStream); end; +{ + Writes an Excel 2 WINDOW2 record +} +procedure TsSpreadBIFF2Writer.WriteWindow2(AStream: TStream; + ASheet: TsWorksheet); +var + b: Byte; +begin + { BIFF Record header } + AStream.WriteWord(WordToLE(INT_EXCEL_ID_WINDOW2)); + AStream.WriteWord(WordToLE(14)); + + { Show formulas, not results } + AStream.WriteByte(0); + + { Show grid lines } + b := IfThen(soShowGridLines in ASheet.Options, 1, 0); + AStream.WriteByte(b); + + { Show sheet headers } + b := IfThen(soShowHeaders in ASheet.Options, 1, 0); + AStream.WriteByte(b); + + { Panes are frozen? } + b := IfThen(soHasFrozenPanes in ASheet.Options, 1, 0); + AStream.WriteByte(b); + + { Show zero values as zeros, not empty cells } + AStream.WriteByte(1); + + { Index to first visible row } + AStream.WriteWord(0); + + { Index to first visible column } + AStream.WriteWord(0); + + { Use automatic grid line color } + AStream.WriteByte(1); + + { RGB of manual grid line color } + AStream.WriteDWord(0); +end; + procedure TsSpreadBIFF2Writer.WriteXF(AStream: TStream; AFontIndex, AFormatIndex: byte; ABorders: TsCellBorders = []; AHorAlign: TsHorAlignment = haLeft; AddBackground: Boolean = false); diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas index 50b5ea96d..bd5773061 100755 --- a/components/fpspreadsheet/xlsbiff5.pas +++ b/components/fpspreadsheet/xlsbiff5.pas @@ -412,6 +412,7 @@ begin WriteColInfos(AStream, sheet); WriteDimensions(AStream, sheet); WriteWindow2(AStream, sheet); + WritePane(AStream, sheet, true); // true for "is BIFF5 or BIFF8" WriteCellsToStream(AStream, sheet.Cells); WriteEOF(AStream); end; @@ -1017,11 +1018,13 @@ begin MASK_WINDOW2_OPTION_SHOW_OUTLINE_SYMBOLS or MASK_WINDOW2_OPTION_SHEET_ACTIVE; - if ASheet.ShowGridLines then + if (soShowGridLines in ASheet.Options) then Options := Options or MASK_WINDOW2_OPTION_SHOW_GRID_LINES; - if ASheet.ShowHeaders then + if (soShowHeaders in ASheet.Options) then Options := Options or MASK_WINDOW2_OPTION_SHOW_SHEET_HEADERS; - if ASheet.Selected then + if (soHasFrozenPanes in ASheet.Options) then + Options := Options or MASK_WINDOW2_OPTION_PANES_ARE_FROZEN; + if (soSelected in ASheet.Options) then Options := Options or MASK_WINDOW2_OPTION_SHEET_SELECTED; AStream.WriteWord(WordToLE(Options)); @@ -1033,7 +1036,7 @@ begin AStream.WriteWord(WordToLE(0)); { Grid line RGB colour } - AStream.WriteDWord(WordToLE(0)); + AStream.WriteDWord(DWordToLE(0)); end; {******************************************************************* @@ -1332,18 +1335,19 @@ begin case RecordType of - INT_EXCEL_ID_BLANK: ReadBlank(AStream); - INT_EXCEL_ID_NUMBER: ReadNumber(AStream); - INT_EXCEL_ID_LABEL: ReadLabel(AStream); - INT_EXCEL_ID_RSTRING: ReadRichString(AStream); //(RSTRING) This record stores a formatted text cell (Rich-Text). In BIFF8 it is usually replaced by the LABELSST record. Excel still uses this record, if it copies formatted text cells to the clipboard. - 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_FORMULA: ReadFormulaExcel(AStream); - INT_EXCEL_ID_WINDOW2: ReadWindow2(AStream); - INT_EXCEL_ID_BOF: ; - INT_EXCEL_ID_EOF: SectionEOF := True; + INT_EXCEL_ID_BLANK : ReadBlank(AStream); + INT_EXCEL_ID_NUMBER : ReadNumber(AStream); + INT_EXCEL_ID_LABEL : ReadLabel(AStream); + INT_EXCEL_ID_RSTRING : ReadRichString(AStream); //(RSTRING) This record stores a formatted text cell (Rich-Text). In BIFF8 it is usually replaced by the LABELSST record. Excel still uses this record, if it copies formatted text cells to the clipboard. + 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_FORMULA : ReadFormulaExcel(AStream); + INT_EXCEL_ID_WINDOW2 : ReadWindow2(AStream); + INT_EXCEL_ID_PANE : ReadPane(AStream); + INT_EXCEL_ID_BOF : ; + INT_EXCEL_ID_EOF : SectionEOF := True; // Show unsupported record types to console. {.$DEFINE SHOWUNSUPPORTED} {$IFDEF SHOWUNSUPPORTED} diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas index bdb69b389..41c5e0e54 100755 --- a/components/fpspreadsheet/xlsbiff8.pas +++ b/components/fpspreadsheet/xlsbiff8.pas @@ -501,8 +501,9 @@ begin WriteIndex(AStream); WriteColInfos(AStream, sheet); WriteDimensions(AStream, sheet); - WriteWindow2(AStream, sheet); WriteCellsToStream(AStream, sheet.Cells); + WriteWindow2(AStream, sheet); + WritePane(AStream, sheet, true); // true for "is BIFF5 or BIFF8" WriteEOF(AStream); end; @@ -1187,11 +1188,13 @@ begin MASK_WINDOW2_OPTION_SHOW_OUTLINE_SYMBOLS or MASK_WINDOW2_OPTION_SHEET_ACTIVE; - if ASheet.ShowGridLines then + if (soShowGridLines in ASheet.Options) then Options := Options or MASK_WINDOW2_OPTION_SHOW_GRID_LINES; - if ASheet.ShowHeaders then + if (soShowHeaders in ASheet.Options) then Options := Options or MASK_WINDOW2_OPTION_SHOW_SHEET_HEADERS; - if ASheet.Selected then + if (soHasFrozenPanes in ASheet.Options) then + Options := Options or MASK_WINDOW2_OPTION_PANES_ARE_FROZEN; + if (soSelected in ASheet.Options) then Options := Options or MASK_WINDOW2_OPTION_SHEET_SELECTED; AStream.WriteWord(WordToLE(Options)); @@ -1575,26 +1578,27 @@ begin case RecordType of - INT_EXCEL_ID_BLANK: ReadBlank(AStream); - INT_EXCEL_ID_NUMBER: ReadNumber(AStream); - INT_EXCEL_ID_LABEL: ReadLabel(AStream); - INT_EXCEL_ID_FORMULA: ReadFormula(AStream); + INT_EXCEL_ID_BLANK : ReadBlank(AStream); + INT_EXCEL_ID_NUMBER : ReadNumber(AStream); + INT_EXCEL_ID_LABEL : ReadLabel(AStream); + INT_EXCEL_ID_FORMULA : ReadFormula(AStream); //(RSTRING) This record stores a formatted text cell (Rich-Text). // In BIFF8 it is usually replaced by the LABELSST record. Excel still // uses this record, if it copies formatted text cells to the clipboard. - INT_EXCEL_ID_RSTRING: ReadRichString(AStream); + INT_EXCEL_ID_RSTRING : ReadRichString(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_RK: ReadRKValue(AStream); - 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_WINDOW2: ReadWindow2(AStream); - INT_EXCEL_ID_BOF: ; - INT_EXCEL_ID_EOF: SectionEOF := True; + INT_EXCEL_ID_RK : ReadRKValue(AStream); + 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_WINDOW2 : ReadWindow2(AStream); + INT_EXCEL_ID_PANE : ReadPane(AStream); + INT_EXCEL_ID_BOF : ; + INT_EXCEL_ID_EOF : SectionEOF := True; else // nothing end; diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas index dec566939..acc97d571 100644 --- a/components/fpspreadsheet/xlscommon.pas +++ b/components/fpspreadsheet/xlscommon.pas @@ -17,6 +17,7 @@ uses const { RECORD IDs which didn't change across versions 2-8 } INT_EXCEL_ID_FONT = $0031; + INT_EXCEL_ID_PANE = $0041; INT_EXCEL_ID_CODEPAGE = $0042; INT_EXCEL_ID_COLINFO = $007D; INT_EXCEL_ID_DATEMODE = $0022; @@ -368,6 +369,8 @@ type procedure ReadNumber(AStream: TStream); override; // Read palette procedure ReadPalette(AStream: TStream); + // Read PANE record + procedure ReadPane(AStream: TStream); // Read the row, column, and XF index at the current stream position procedure ReadRowColXF(AStream: TStream; out ARow, ACol: Cardinal; out AXF: Word); virtual; // Read row info @@ -411,6 +414,8 @@ type const AValue: Double; ACell: PCell); override; // Writes out a PALETTE record containing all colors defined in the workbook procedure WritePalette(AStream: TStream); + // Writes out a PANE record + procedure WritePane(AStream: TStream; ASheet: TsWorksheet; IsBiff58: Boolean); // Writes the index of the XF record used in the given cell procedure WriteXFIndex(AStream: TStream; ACell: PCell); @@ -845,6 +850,28 @@ begin FPaletteFound := true; end; +{ Read pane sizes + Valid for all BIFF versions } +procedure TsSpreadBIFFReader.ReadPane(AStream: TStream); +begin + { Position of horizontal split: + - Unfrozen pane: Width of the left pane(s) (in twips = 1/20 of a point) + - Frozen pane: Number of visible columns in left pane(s) } + FWorksheet.LeftPaneWidth := WordLEToN(AStream.ReadWord); + + { Position of vertical split: + - Unfrozen pane: Height of the top pane(s) (in twips = 1/20 of a point) + - Frozen pane: Number of visible rows in top pane(s) } + FWorksheet.TopPaneHeight := WordLEToN(AStream.ReadWord); + + { There's more information which is not supported here: + Offset Size Description + 4 2 Index to first visible row in bottom pane(s) + 6 2 Index to first visible column in right pane(s) + 8 1 Identifier of pane with active cell cursor (see below) + [9] 1 Not used (BIFF5-BIFF8 only, not written in BIFF2-BIFF4) } +end; + // Read the row, column and xf index // NOT VALID for BIFF2 procedure TsSpreadBIFFReader.ReadRowColXF(AStream: TStream; @@ -888,8 +915,8 @@ begin // changed manually. end; -{ Reads the WINDOW2 record containing information like "show grid lines", or - "show sheet headers". +{ Reads the WINDOW2 record containing information like "show grid lines", + "show sheet headers", "panes are frozen", etc. The record structure is different for BIFF5 and BIFF8, but we use here only the common part. BIFF2 is completely different and has to be overridden. } @@ -898,9 +925,26 @@ var flags: Word; begin flags := WordLEToN(AStream.ReadWord); - FWorksheet.ShowGridLines := (flags and MASK_WINDOW2_OPTION_SHOW_GRID_LINES <> 0); - FWorksheet.ShowHeaders := (flags and MASK_WINDOW2_OPTION_SHOW_SHEET_HEADERS <> 0); - FWorksheet.Selected := (flags and MASK_WINDOW2_OPTION_SHEET_SELECTED <> 0); + + if (flags and MASK_WINDOW2_OPTION_SHOW_GRID_LINES <> 0) then + FWorksheet.Options := FWorksheet.Options + [soShowGridLines] + else + FWorksheet.Options := FWorksheet.Options - [soShowGridLines]; + + if (flags and MASK_WINDOW2_OPTION_SHOW_SHEET_HEADERS <> 0) then + FWorksheet.Options := FWorksheet.Options + [soShowHeaders] + else + FWorksheet.Options := FWorksheet.Options - [soShowHeaders]; + + if (flags and MASK_WINDOW2_OPTION_SHEET_SELECTED <> 0) then + FWorksheet.Options := FWorksheet.Options + [soSelected] + else + FWorksheet.Options := FWorksheet.Options - [soSelected]; + + if (flags and MASK_WINDOW2_OPTION_PANES_ARE_FROZEN <> 0) then + FWorksheet.Options := FWorksheet.Options + [soHasFrozenPanes] + else + FWorksheet.Options := FWorksheet.Options - [soHasFrozenPanes]; end; @@ -1283,6 +1327,70 @@ begin AStream.WriteDWord(DWordToLE($FFFFFF)); end; +{ Writes a PANE record to the stream. + Valid for all BIFF versions. The difference for BIFF5-BIFF8 is a non-used + byte at the end. Activate IsBiff58 in these cases. } +procedure TsSpreadBIFFWriter.WritePane(AStream: TStream; ASheet: TsWorksheet; + IsBiff58: Boolean); +var + n: Word; + active_pane: Byte; +begin + if (ASheet.LeftPaneWidth = 0) and (ASheet.TopPaneHeight = 0) then + exit; + + if not (soHasFrozenPanes in ASheet.Options) then + exit; + { Non-frozen panes should work in principle, but they are not read without + error. They possibly require an additional SELECTION record. } + + { BIFF record header } + AStream.WriteWord(WordToLE(INT_EXCEL_ID_PANE)); + if isBIFF58 then n := 10 else n := 9; + AStream.WriteWord(WordToLE(n)); + + { Position of the vertical split (px, 0 = No vertical split): + - Unfrozen pane: Width of the left pane(s) (in twips = 1/20 of a point) + - Frozen pane: Number of visible columns in left pane(s) } + AStream.WriteWord(WordToLE(ASheet.LeftPaneWidth)); + + { Position of the horizontal split (py, 0 = No horizontal split): + - Unfrozen pane: Height of the top pane(s) (in twips = 1/20 of a point) + - Frozen pane: Number of visible rows in top pane(s) } + AStream.WriteWord(WordToLE(ASheet.TopPaneHeight)); + + { Index to first visible row in bottom pane(s) } + if (soHasFrozenPanes in ASheet.Options) then + AStream.WriteWord(WordToLE(ASheet.TopPaneHeight)) + else + AStream.WriteWord(WordToLE(0)); + + { Index to first visible column in right pane(s) } + if (soHasFrozenPanes in ASheet.Options) then + AStream.WriteWord(WordToLE(ASheet.LeftPaneWidth)) + else + AStream.WriteWord(WordToLE(0)); + + { Identifier of pane with active cell cursor } + if (soHasFrozenPanes in ASheet.Options) then begin + if (ASheet.LeftPaneWidth = 0) and (ASheet.TopPaneHeight = 0) then + active_pane := 3 + else + if (ASheet.LeftPaneWidth = 0) then + active_pane := 2 + else + if (ASheet.TopPaneHeight =0) then + active_pane := 1 + else + active_pane := 0; + end else + active_pane := 0; + AStream.WriteByte(active_pane); + + if IsBIFF58 then + AStream.WriteByte(0); + { Not used (BIFF5-BIFF8 only, not written in BIFF2-BIFF4 } +end; { Write the index of the XF record, according to formatting of the given cell Valid for BIFF5 and BIFF8.