Files
lazarus-ccr/components/fpspreadsheet/examples/spready/mainform.pas
wp_xxyyzz e07e322170 fpspreadsheet: Redo internal structure of merged cells (use MergeBase cell instead of neighbor links).
Suppress TsWorksheetGrid painting of inner grid lines of merged cells.
Fix inserting columns and rows running through merged cells. 
Silence some warnings. 
Fix ods reading merged cells incorrectly.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3569 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2014-09-15 20:54:39 +00:00

1235 lines
38 KiB
ObjectPascal

unit mainform;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
StdCtrls, Menus, ExtCtrls, ComCtrls, ActnList, Spin, Grids,
ColorBox, ValEdit,
fpspreadsheetgrid, fpspreadsheet, fpsallformats;
type
{ TMainFrm }
TMainFrm = class(TForm)
AcOpen: TAction;
AcSaveAs: TAction;
AcQuit: TAction;
AcEdit: TAction;
AcLeftAlign: TAction;
AcHorCenterAlign: TAction;
AcRightAlign: TAction;
AcHorDefaultAlign: TAction;
AcFontBold: TAction;
AcFontItalic: TAction;
AcFontStrikeout: TAction;
AcFontUnderline: TAction;
AcFont: TAction;
AcBorderTop: TAction;
AcBorderBottom: TAction;
AcBorderBottomDbl: TAction;
AcBorderBottomMedium: TAction;
AcBorderLeft: TAction;
AcBorderRight: TAction;
AcBorderNone: TAction;
AcBorderHCenter: TAction;
AcBorderVCenter: TAction;
AcBorderTopBottom: TAction;
AcBorderTopBottomThick: TAction;
AcBorderInner: TAction;
AcBorderAll: TAction;
AcBorderOuter: TAction;
AcBorderOuterMedium: TAction;
AcTextHoriz: TAction;
AcTextVertCW: TAction;
AcTextVertCCW: TAction;
AcTextStacked: TAction;
AcNFFixed: TAction;
AcNFFixedTh: TAction;
AcNFPercentage: TAction;
AcIncDecimals: TAction;
AcDecDecimals: TAction;
AcNFGeneral: TAction;
AcNFExp: TAction;
AcCopyFormat: TAction;
AcNFCurrency: TAction;
AcNFCurrencyRed: TAction;
AcNFShortDateTime: TAction;
AcNFShortDate: TAction;
AcNFLongDate: TAction;
AcNFShortTime: TAction;
AcNFLongTime: TAction;
AcNFShortTimeAM: TAction;
AcNFLongTimeAM: TAction;
AcNFTimeInterval: TAction;
AcNFCustomDM: TAction;
AcNFCustomMY: TAction;
AcNFCusstomMS: TAction;
AcNFCustomMSZ: TAction;
AcNew: TAction;
AcAddColumn: TAction;
AcAddRow: TAction;
AcMergeCells: TAction;
AcShowHeaders: TAction;
AcShowGridlines: TAction;
AcViewInspector: TAction;
AcWordwrap: TAction;
AcVAlignDefault: TAction;
AcVAlignTop: TAction;
AcVAlignCenter: TAction;
AcVAlignBottom: TAction;
ActionList: TActionList;
CbBackgroundColor: TColorBox;
CbReadFormulas: TCheckBox;
CbHeaderStyle: TComboBox;
CbAutoCalcFormulas: TCheckBox;
CbTextOverflow: TCheckBox;
EdFormula: TEdit;
EdCellAddress: TEdit;
FontComboBox: TComboBox;
EdFrozenRows: TSpinEdit;
FontDialog: TFontDialog;
FontSizeComboBox: TComboBox;
ImageList: TImageList;
Label1: TLabel;
Label2: TLabel;
MainMenu: TMainMenu;
MenuItem1: TMenuItem;
MenuItem10: TMenuItem;
MenuItem11: TMenuItem;
MenuItem12: TMenuItem;
MenuItem13: TMenuItem;
MenuItem14: TMenuItem;
MenuItem15: TMenuItem;
MenuItem16: TMenuItem;
MenuItem17: TMenuItem;
MenuItem18: TMenuItem;
MenuItem19: TMenuItem;
MenuItem2: TMenuItem;
MenuItem20: TMenuItem;
MenuItem21: TMenuItem;
MenuItem22: TMenuItem;
MenuItem23: TMenuItem;
MenuItem24: TMenuItem;
MenuItem25: TMenuItem;
MenuItem26: TMenuItem;
MenuItem27: TMenuItem;
MenuItem28: TMenuItem;
MenuItem29: TMenuItem;
MenuItem30: TMenuItem;
MenuItem31: TMenuItem;
MenuItem32: TMenuItem;
MenuItem33: TMenuItem;
MenuItem34: TMenuItem;
MenuItem35: TMenuItem;
MenuItem36: TMenuItem;
MenuItem37: TMenuItem;
MenuItem38: TMenuItem;
MenuItem39: TMenuItem;
MenuItem40: TMenuItem;
MenuItem41: TMenuItem;
MenuItem42: TMenuItem;
MenuItem43: TMenuItem;
MenuItem44: TMenuItem;
MenuItem45: TMenuItem;
MenuItem46: TMenuItem;
MenuItem47: TMenuItem;
MenuItem48: TMenuItem;
MenuItem49: TMenuItem;
MenuItem50: TMenuItem;
MenuItem51: TMenuItem;
MenuItem52: TMenuItem;
MenuItem53: TMenuItem;
MenuItem54: TMenuItem;
MenuItem55: TMenuItem;
MenuItem56: TMenuItem;
MenuItem57: TMenuItem;
MenuItem58: TMenuItem;
MenuItem59: TMenuItem;
MenuItem60: TMenuItem;
MenuItem61: TMenuItem;
MenuItem62: TMenuItem;
MenuItem63: TMenuItem;
MenuItem64: TMenuItem;
MenuItem65: TMenuItem;
MenuItem66: TMenuItem;
MenuItem67: TMenuItem;
MenuItem68: TMenuItem;
MenuItem69: TMenuItem;
MenuItem70: TMenuItem;
MenuItem71: TMenuItem;
mnuInspector: TMenuItem;
mnuView: TMenuItem;
MnuFmtDateTimeMSZ: TMenuItem;
MnuTimeInterval: TMenuItem;
MnuShortTimeAM: TMenuItem;
MnuLongTimeAM: TMenuItem;
MnuFmtDateTimeMY: TMenuItem;
MnuFmtDateTimeDM: TMenuItem;
MnuShortTime: TMenuItem;
MnuShortDate: TMenuItem;
MnuLongTime: TMenuItem;
MnuLongDate: TMenuItem;
MnuShortDateTime: TMenuItem;
MnuCurrencyRed: TMenuItem;
MnuCurrency: TMenuItem;
MnuNumberFormat: TMenuItem;
MnuNFFixed: TMenuItem;
MnuNFFixedTh: TMenuItem;
MnuNFPercentage: TMenuItem;
MnuNFExp: TMenuItem;
MnuNFGeneral: TMenuItem;
MnuTextRotation: TMenuItem;
MenuItem3: TMenuItem;
MenuItem4: TMenuItem;
MenuItem5: TMenuItem;
MenuItem6: TMenuItem;
MenuItem7: TMenuItem;
MenuItem8: TMenuItem;
MenuItem9: TMenuItem;
MnuWordwrap: TMenuItem;
MnuVertBottom: TMenuItem;
MnuVertCentered: TMenuItem;
MnuVertTop: TMenuItem;
MnuVertDefault: TMenuItem;
MnuVertAlignment: TMenuItem;
MnuFOnt: TMenuItem;
MnuHorDefault: TMenuItem;
MnuHorAlignment: TMenuItem;
mnuFormat: TMenuItem;
mnuEdit: TMenuItem;
mnuFile: TMenuItem;
mnuOpen: TMenuItem;
mnuQuit: TMenuItem;
mnuSaveAs: TMenuItem;
OpenDialog: TOpenDialog;
InspectorPageControl: TPageControl;
Panel1: TPanel;
BordersPopupMenu: TPopupMenu;
NumFormatPopupMenu: TPopupMenu;
SaveDialog: TSaveDialog;
EdFrozenCols: TSpinEdit;
FormulaToolBar: TToolBar;
FormulaToolbarSplitter: TSplitter;
InspectorSplitter: TSplitter;
PgCellValue: TTabSheet;
PgProperties: TTabSheet;
TabControl: TTabControl;
ToolButton22: TToolButton;
ToolButton23: TToolButton;
ToolButton27: TToolButton;
CellInspector: TValueListEditor;
ToolButton28: TToolButton;
WorksheetGrid: TsWorksheetGrid;
ToolBar1: TToolBar;
FormatToolBar: TToolBar;
ToolButton1: TToolButton;
ToolButton10: TToolButton;
ToolButton11: TToolButton;
ToolButton12: TToolButton;
ToolButton13: TToolButton;
ToolButton14: TToolButton;
ToolButton15: TToolButton;
ToolButton16: TToolButton;
ToolButton17: TToolButton;
ToolButton18: TToolButton;
ToolButton19: TToolButton;
ToolButton2: TToolButton;
TbBorders: TToolButton;
TbNumFormats: TToolButton;
ToolButton20: TToolButton;
ToolButton21: TToolButton;
ToolButton24: TToolButton;
ToolButton25: TToolButton;
ToolButton26: TToolButton;
ToolButton3: TToolButton;
ToolButton4: TToolButton;
ToolButton5: TToolButton;
ToolButton6: TToolButton;
ToolButton7: TToolButton;
ToolButton8: TToolButton;
ToolButton9: TToolButton;
procedure AcAddColumnExecute(Sender: TObject);
procedure AcAddRowExecute(Sender: TObject);
procedure AcBorderExecute(Sender: TObject);
procedure AcCopyFormatExecute(Sender: TObject);
procedure AcEditExecute(Sender: TObject);
procedure AcFontExecute(Sender: TObject);
procedure AcFontStyleExecute(Sender: TObject);
procedure AcHorAlignmentExecute(Sender: TObject);
procedure AcIncDecDecimalsExecute(Sender: TObject);
procedure AcMergeCellsExecute(Sender: TObject);
procedure AcNewExecute(Sender: TObject);
procedure AcNumFormatExecute(Sender: TObject);
procedure AcOpenExecute(Sender: TObject);
procedure AcQuitExecute(Sender: TObject);
procedure AcSaveAsExecute(Sender: TObject);
procedure AcShowGridlinesExecute(Sender: TObject);
procedure AcShowHeadersExecute(Sender: TObject);
procedure AcTextRotationExecute(Sender: TObject);
procedure AcVertAlignmentExecute(Sender: TObject);
procedure AcViewInspectorExecute(Sender: TObject);
procedure AcWordwrapExecute(Sender: TObject);
procedure CbAutoCalcFormulasChange(Sender: TObject);
procedure CbBackgroundColorSelect(Sender: TObject);
procedure CbHeaderStyleChange(Sender: TObject);
procedure CbReadFormulasChange(Sender: TObject);
procedure CbBackgroundColorGetColors(Sender: TCustomColorBox; Items: TStrings);
procedure CbTextOverflowChange(Sender: TObject);
procedure EdCellAddressEditingDone(Sender: TObject);
procedure EdFormulaEditingDone(Sender: TObject);
procedure EdFrozenColsChange(Sender: TObject);
procedure EdFrozenRowsChange(Sender: TObject);
procedure FontComboBoxSelect(Sender: TObject);
procedure FontSizeComboBoxSelect(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure InspectorPageControlChange(Sender: TObject);
procedure TabControlChange(Sender: TObject);
procedure WorksheetGridSelection(Sender: TObject; aCol, aRow: Integer);
private
FCopiedFormat: TCell;
procedure LoadFile(const AFileName: String);
procedure SetupBackgroundColorBox;
procedure UpdateBackgroundColorIndex;
procedure UpdateCellInfo(ACell: PCell);
procedure UpdateFontNameIndex;
procedure UpdateFontSizeIndex;
procedure UpdateFontStyleActions;
procedure UpdateHorAlignmentActions;
procedure UpdateInspector;
procedure UpdateNumFormatActions;
procedure UpdateTextRotationActions;
procedure UpdateVertAlignmentActions;
procedure UpdateWordwraps;
public
procedure BeforeRun;
end;
var
MainFrm: TMainFrm;
implementation
uses
StrUtils, TypInfo, LCLIntf, LCLType,
fpcanvas, fpsutils, fpsnumformatparser;
const
DROPDOWN_COUNT = 24;
HORALIGN_TAG = 100;
VERTALIGN_TAG = 110;
TEXTROT_TAG = 130;
NUMFMT_TAG = 1000; // difference 10 per format item
LEFT_BORDER_THIN = $0001;
LEFT_BORDER_THICK = $0002;
LR_INNER_BORDER_THIN = $0008;
RIGHT_BORDER_THIN = $0010;
RIGHT_BORDER_THICK = $0020;
TOP_BORDER_THIN = $0100;
TOP_BORDER_THICK = $0200;
TB_INNER_BORDER_THIN = $0800;
BOTTOM_BORDER_THIN = $1000;
BOTTOM_BORDER_THICK = $2000;
BOTTOM_BORDER_DOUBLE = $3000;
LEFT_BORDER_MASK = $0007;
RIGHT_BORDER_MASK = $0070;
TOP_BORDER_MASK = $0700;
BOTTOM_BORDER_MASK = $7000;
LR_INNER_BORDER = $0008;
TB_INNER_BORDER = $0800;
// Use a combination of these bits for the "Tag" of the Border actions - see FormCreate.
{ TMainFrm }
procedure TMainFrm.AcEditExecute(Sender: TObject);
begin
if AcEdit.Checked then
WorksheetGrid.Options := WorksheetGrid.Options + [goEditing]
else
WorksheetGrid.Options := WorksheetGrid.Options - [goEditing];
end;
procedure TMainFrm.AcBorderExecute(Sender: TObject);
const
LINESTYLES: Array[1..3] of TsLinestyle = (lsThin, lsMedium, lsDouble);
var
r,c: Integer;
ls: integer;
bs: TsCellBorderStyle;
begin
bs.Color := scBlack;
with WorksheetGrid do begin
TbBorders.Action := TAction(Sender);
BeginUpdate;
try
if TAction(Sender).Tag = 0 then begin
CellBorders[Selection] := [];
exit;
end;
// Top and bottom edges
for c := Selection.Left to Selection.Right do begin
ls := (TAction(Sender).Tag and TOP_BORDER_MASK) shr 8;
if (ls <> 0) then begin
CellBorder[c, Selection.Top] := CellBorder[c, Selection.Top] + [cbNorth];
bs.LineStyle := LINESTYLES[ls];
CellBorderStyle[c, Selection.Top, cbNorth] := bs;
end;
ls := (TAction(Sender).Tag and BOTTOM_BORDER_MASK) shr 12;
if ls <> 0 then begin
CellBorder[c, Selection.Bottom] := CellBorder[c, Selection.Bottom] + [cbSouth];
bs.LineStyle := LINESTYLES[ls];
CellBorderStyle[c, Selection.Bottom, cbSouth] := bs;
end;
end;
// Left and right edges
for r := Selection.Top to Selection.Bottom do begin
ls := (TAction(Sender).Tag and LEFT_BORDER_MASK);
if ls <> 0 then begin
CellBorder[Selection.Left, r] := CellBorder[Selection.Left, r] + [cbWest];
bs.LineStyle := LINESTYLES[ls];
CellBorderStyle[Selection.Left, r, cbWest] := bs;
end;
ls := (TAction(Sender).Tag and RIGHT_BORDER_MASK) shr 4;
if ls <> 0 then begin
CellBorder[Selection.Right, r] := CellBorder[Selection.Right, r] + [cbEast];
bs.LineStyle := LINESTYLES[ls];
CellBorderStyle[Selection.Right, r, cbEast] := bs;
end;
end;
// Inner edges along row (vertical border lines) - we assume only thin lines.
bs.LineStyle := lsThin;
if (TAction(Sender).Tag and LR_INNER_BORDER <> 0) and (Selection.Right > Selection.Left)
then
for r := Selection.Top to Selection.Bottom do begin
CellBorder[Selection.Left, r] := CellBorder[Selection.Left, r] + [cbEast];
CellBorderStyle[Selection.Left, r, cbEast] := bs;
for c := Selection.Left+1 to Selection.Right-1 do begin
CellBorder[c,r] := CellBorder[c, r] + [cbEast, cbWest];
CellBorderStyle[c, r, cbEast] := bs;
CellBorderStyle[c, r, cbWest] := bs;
end;
CellBorder[Selection.Right, r] := CellBorder[Selection.Right, r] + [cbWest];
CellBorderStyle[Selection.Right, r, cbWest] := bs;
end;
// Inner edges along column (horizontal border lines)
if (TAction(Sender).Tag and TB_INNER_BORDER <> 0) and (Selection.Bottom > Selection.Top)
then
for c := Selection.Left to Selection.Right do begin
CellBorder[c, Selection.Top] := CellBorder[c, Selection.Top] + [cbSouth];
CellBorderStyle[c, Selection.Top, cbSouth] := bs;
for r := Selection.Top+1 to Selection.Bottom-1 do begin
CellBorder[c, r] := CellBorder[c, r] + [cbNorth, cbSouth];
CellBorderStyle[c, r, cbNorth] := bs;
CellBorderStyle[c, r, cbSouth] := bs;
end;
CellBorder[c, Selection.Bottom] := CellBorder[c, Selection.Bottom] + [cbNorth];
CellBorderStyle[c, Selection.Bottom, cbNorth] := bs;
end;
finally
EndUpdate;
end;
end;
end;
procedure TMainFrm.AcAddColumnExecute(Sender: TObject);
begin
WorksheetGrid.InsertCol(WorksheetGrid.Col);
WorksheetGrid.Col := WorksheetGrid.Col + 1;
end;
procedure TMainFrm.AcAddRowExecute(Sender: TObject);
begin
WorksheetGrid.InsertRow(WorksheetGrid.Row);
WorksheetGrid.Row := WorksheetGrid.Row + 1;
end;
procedure TMainFrm.AcCopyFormatExecute(Sender: TObject);
var
cell: PCell;
r, c: Cardinal;
begin
with WorksheetGrid do begin
if Workbook = nil then
exit;
if AcCopyFormat.Checked then begin
r := GetWorksheetRow(Row);
c := GetWorksheetCol(Col);
cell := Worksheet.FindCell(r, c);
if cell <> nil then
FCopiedFormat := cell^;
end;
end;
end;
{ Changes the font of the selected cell by calling a standard font dialog. }
procedure TMainFrm.AcFontExecute(Sender: TObject);
begin
with WorksheetGrid do begin
if Workbook = nil then
exit;
FontDialog.Font := CellFonts[Selection];
if FontDialog.Execute then
CellFonts[Selection] := FontDialog.Font;
end;
end;
procedure TMainFrm.AcFontStyleExecute(Sender: TObject);
var
style: TsFontstyles;
begin
with WorksheetGrid do begin
if Workbook = nil then
exit;
style := [];
if AcFontBold.Checked then Include(style, fssBold);
if AcFontItalic.Checked then Include(style, fssItalic);
if AcFontStrikeout.Checked then Include(style, fssStrikeout);
if AcFontUnderline.Checked then Include(style, fssUnderline);
CellFontStyles[Selection] := style;
end;
end;
procedure TMainFrm.AcHorAlignmentExecute(Sender: TObject);
var
hor_align: TsHorAlignment;
begin
if TAction(Sender).Checked then
hor_align := TsHorAlignment(TAction(Sender).Tag - HORALIGN_TAG)
else
hor_align := haDefault;
with WorksheetGrid do HorAlignments[Selection] := hor_align;
UpdateHorAlignmentActions;
end;
procedure TMainFrm.AcIncDecDecimalsExecute(Sender: TObject);
var
cell: PCell;
decs: Byte;
currsym: String;
begin
currsym := Sender.ClassName;
with WorksheetGrid do begin
if Workbook = nil then
exit;
cell := Worksheet.FindCell(GetWorksheetRow(Row), GetWorksheetCol(Col));
if (cell <> nil) then begin
if cell^.NumberFormat = nfGeneral then begin
Worksheet.WriteNumberFormat(cell, nfFixed, '0.00');
exit;
end;
Worksheet.GetNumberFormatAttributes(cell, decs, currSym);
if (Sender = AcIncDecimals) then
Worksheet.WriteDecimals(cell, decs+1)
else
if (Sender = AcDecDecimals) and (decs > 0) then
Worksheet.WriteDecimals(cell, decs-1);
end;
end;
end;
procedure TMainFrm.AcMergeCellsExecute(Sender: TObject);
begin
AcMergeCells.Checked := not AcMergeCells.Checked;
if AcMergeCells.Checked then
WorksheetGrid.MergeCells
else
WorksheetGrid.UnmergeCells;
WorksheetGridSelection(nil, WorksheetGrid.Col, WorksheetGrid.Row);
end;
procedure TMainFrm.AcNewExecute(Sender: TObject);
begin
WorksheetGrid.NewWorkbook(26, 100);
WorksheetGrid.BeginUpdate;
try
WorksheetGrid.Col := WorksheetGrid.FixedCols;
WorksheetGrid.Row := WorksheetGrid.FixedRows;
SetupBackgroundColorBox;
WorksheetGridSelection(nil, WorksheetGrid.Col, WorksheetGrid.Row);
finally
WorksheetGrid.EndUpdate;
end;
end;
procedure TMainFrm.AcNumFormatExecute(Sender: TObject);
const
DATETIME_CUSTOM: array[0..4] of string = ('', 'dd/mmm', 'mmm/yy', 'nn:ss', 'nn:ss.zzz');
var
nf: TsNumberFormat;
c, r: Cardinal;
cell: PCell;
fmt: String;
decs: Byte;
cs: String;
isDateTimeFmt: Boolean;
begin
if TAction(Sender).Checked then
nf := TsNumberFormat((TAction(Sender).Tag - NUMFMT_TAG) div 10)
else
nf := nfGeneral;
fmt := '';
isDateTimeFmt := IsDateTimeFormat(nf);
if nf = nfCustom then begin
fmt := DATETIME_CUSTOM[TAction(Sender).Tag mod 10];
isDateTimeFmt := true;
end;
with WorksheetGrid do begin
c := GetWorksheetCol(Col);
r := GetWorksheetRow(Row);
cell := Worksheet.GetCell(r, c);
Worksheet.GetNumberFormatAttributes(cell, decs, cs);
if cs = '' then cs := '?';
case cell^.ContentType of
cctNumber, cctDateTime:
if isDateTimeFmt then begin
if IsDateTimeFormat(cell^.NumberFormat) then
Worksheet.WriteDateTime(cell, cell^.DateTimeValue, nf, fmt)
else
Worksheet.WriteDateTime(cell, cell^.NumberValue, nf, fmt);
end else
if IsCurrencyFormat(nf) then begin
if IsDateTimeFormat(cell^.NumberFormat) then
Worksheet.WriteCurrency(cell, cell^.DateTimeValue, nf, decs, cs)
else
Worksheet.WriteCurrency(cell, cell^.Numbervalue, nf, decs, cs);
end else begin
if IsDateTimeFormat(cell^.NumberFormat) then
Worksheet.WriteNumber(cell, cell^.DateTimeValue, nf, decs)
else
Worksheet.WriteNumber(cell, cell^.NumberValue, nf, decs)
end;
else
Worksheet.WriteNumberformat(cell, nf, fmt);
end;
end;
UpdateNumFormatActions;
end;
procedure TMainFrm.acOpenExecute(Sender: TObject);
begin
if OpenDialog.Execute then
LoadFile(OpenDialog.FileName);
end;
procedure TMainFrm.acQuitExecute(Sender: TObject);
begin
Close;
end;
procedure TMainFrm.acSaveAsExecute(Sender: TObject);
// Saves sheet in grid to file, overwriting existing file
var
err: String = '';
begin
if WorksheetGrid.Workbook = nil then
exit;
if SaveDialog.Execute then
begin
Screen.Cursor := crHourglass;
try
WorksheetGrid.SaveToSpreadsheetFile(SaveDialog.FileName);
finally
Screen.Cursor := crDefault;
err := WorksheetGrid.Workbook.ErrorMsg;
if err <> '' then
MessageDlg(err, mtError, [mbOK], 0);
end;
end;
end;
procedure TMainFrm.AcShowGridlinesExecute(Sender: TObject);
begin
WorksheetGrid.ShowGridLines := AcShowGridLines.Checked;
end;
procedure TMainFrm.AcShowHeadersExecute(Sender: TObject);
begin
WorksheetGrid.ShowHeaders := AcShowHeaders.Checked;
end;
procedure TMainFrm.AcTextRotationExecute(Sender: TObject);
var
text_rot: TsTextRotation;
begin
if TAction(Sender).Checked then
text_rot := TsTextRotation(TAction(Sender).Tag - TEXTROT_TAG)
else
text_rot := trHorizontal;
with WorksheetGrid do TextRotations[Selection] := text_rot;
UpdateTextRotationActions;
end;
procedure TMainFrm.AcVertAlignmentExecute(Sender: TObject);
var
vert_align: TsVertAlignment;
begin
if TAction(Sender).Checked then
vert_align := TsVertAlignment(TAction(Sender).Tag - VERTALIGN_TAG)
else
vert_align := vaDefault;
with WorksheetGrid do VertAlignments[Selection] := vert_align;
UpdateVertAlignmentActions;
end;
procedure TMainFrm.AcViewInspectorExecute(Sender: TObject);
begin
InspectorPageControl.Visible := AcViewInspector.Checked;
InspectorSplitter.Visible := AcViewInspector.Checked;
InspectorSplitter.Left := 0;
end;
procedure TMainFrm.AcWordwrapExecute(Sender: TObject);
begin
with WorksheetGrid do Wordwraps[Selection] := TAction(Sender).Checked;
end;
procedure TMainFrm.BeforeRun;
begin
if ParamCount > 0 then
LoadFile(ParamStr(1));
end;
procedure TMainFrm.CbAutoCalcFormulasChange(Sender: TObject);
begin
WorksheetGrid.AutoCalc := CbAutoCalcFormulas.Checked;;
end;
procedure TMainFrm.CbBackgroundColorGetColors(Sender: TCustomColorBox; Items: TStrings);
var
clr: TColor;
clrName: String;
i: Integer;
begin
if WorksheetGrid.Workbook <> nil then begin
Items.Clear;
Items.AddObject('no fill', TObject(PtrInt(clNone)));
for i:=0 to WorksheetGrid.Workbook.GetPaletteSize-1 do begin
clr := WorksheetGrid.Workbook.GetPaletteColor(i);
clrName := WorksheetGrid.Workbook.GetColorName(i);
Items.AddObject(Format('%d: %s', [i, clrName]), TObject(PtrInt(clr)));
end;
end;
end;
procedure TMainFrm.CbTextOverflowChange(Sender: TObject);
begin
WorksheetGrid.TextOverflow := CbTextOverflow.Checked;
WorksheetGrid.Invalidate;
end;
procedure TMainFrm.CbBackgroundColorSelect(Sender: TObject);
begin
if CbBackgroundColor.ItemIndex <= 0 then
with WorksheetGrid do BackgroundColors[Selection] := scNotDefined
else
with WorksheetGrid do BackgroundColors[Selection] := CbBackgroundColor.ItemIndex - 1;
end;
procedure TMainFrm.CbHeaderStyleChange(Sender: TObject);
begin
WorksheetGrid.TitleStyle := TTitleStyle(CbHeaderStyle.ItemIndex);
end;
procedure TMainFrm.CbReadFormulasChange(Sender: TObject);
begin
WorksheetGrid.ReadFormulas := CbReadFormulas.Checked;
end;
procedure TMainFrm.EdCellAddressEditingDone(Sender: TObject);
var
c, r: cardinal;
begin
if ParseCellString(EdCellAddress.Text, r, c) then begin
WorksheetGrid.Row := WorksheetGrid.GetGridRow(r);
WorksheetGrid.Col := WorksheetGrid.GetGridCol(c);
end;
end;
procedure TMainFrm.EdFormulaEditingDone(Sender: TObject);
var
r, c: Cardinal;
s: String;
begin
r := WorksheetGrid.GetWorksheetRow(WorksheetGrid.Row);
c := WorksheetGrid.GetWorksheetCol(WorksheetGrid.Col);
s := EdFormula.Text;
if (s <> '') and (s[1] = '=') then
WorksheetGrid.Worksheet.WriteFormula(r, c, Copy(s, 2, Length(s)), true)
else
WorksheetGrid.Worksheet.WriteCellValueAsString(r, c, EdFormula.Text);
end;
procedure TMainFrm.EdFrozenColsChange(Sender: TObject);
begin
WorksheetGrid.FrozenCols := EdFrozenCols.Value;
end;
procedure TMainFrm.EdFrozenRowsChange(Sender: TObject);
begin
WorksheetGrid.FrozenRows := EdFrozenRows.Value;
end;
procedure TMainFrm.FontComboBoxSelect(Sender: TObject);
var
fname: String;
begin
fname := FontCombobox.Items[FontCombobox.ItemIndex];
if fname <> '' then
with WorksheetGrid do CellFontNames[Selection] := fName;
end;
procedure TMainFrm.FontSizeComboBoxSelect(Sender: TObject);
var
sz: Integer;
begin
sz := StrToInt(FontSizeCombobox.Items[FontSizeCombobox.ItemIndex]);
if sz > 0 then
with WorksheetGrid do CellFontSizes[Selection] := sz;
end;
procedure TMainFrm.FormActivate(Sender: TObject);
begin
WorksheetGridSelection(nil, WorksheetGrid.Col, WorksheetGrid.Row);
end;
procedure TMainFrm.FormCreate(Sender: TObject);
begin
// Adjust format toolbar height, looks strange at 120 dpi
FormatToolbar.Height := FontCombobox.Height + 2*FontCombobox.Top;
FormatToolbar.ButtonHeight := FormatToolbar.Height - 4;
CbBackgroundColor.ItemHeight := FontCombobox.ItemHeight;
CbBackgroundColor.ColorRectWidth := CbBackgroundColor.ItemHeight - 6; // to get a square box...
// Populate font combobox
FontCombobox.Items.Assign(Screen.Fonts);
// Set the Tags of the Border actions
AcBorderNone.Tag := 0;
AcBorderLeft.Tag := LEFT_BORDER_THIN;
AcBorderHCenter.Tag := LR_INNER_BORDER_THIN;
AcBorderRight.Tag := RIGHT_BORDER_THIN;
AcBorderTop.Tag := TOP_BORDER_THIN;
AcBorderVCenter.Tag := TB_INNER_BORDER_THIN;
AcBorderBottom.Tag := BOTTOM_BORDER_THIN;
AcBorderBottomDbl.Tag := BOTTOM_BORDER_DOUBLE;
AcBorderBottomMedium.Tag := BOTTOM_BORDER_THICK;
AcBorderTopBottom.Tag := TOP_BORDER_THIN + BOTTOM_BORDER_THIN;
AcBorderTopBottomThick.Tag := TOP_BORDER_THIN + BOTTOM_BORDER_THICK;
AcBorderInner.Tag := LR_INNER_BORDER_THIN + TB_INNER_BORDER_THIN;
AcBorderOuter.Tag := LEFT_BORDER_THIN + RIGHT_BORDER_THIN + TOP_BORDER_THIN + BOTTOM_BORDER_THIN;
AcBorderOuterMedium.Tag := LEFT_BORDER_THICK + RIGHT_BORDER_THICK + TOP_BORDER_THICK + BOTTOM_BORDER_THICK;
AcBorderAll.Tag := AcBorderOuter.Tag + AcBorderInner.Tag;
FontCombobox.DropDownCount := DROPDOWN_COUNT;
FontSizeCombobox.DropDownCount := DROPDOWN_COUNT;
CbBackgroundColor.DropDownCount := DROPDOWN_COUNT;
// Initialize a new empty workbook
AcNewExecute(nil);
// Initialize Inspector
//UpdateCellInfo(nil);
ActiveControl := WorksheetGrid;
end;
procedure TMainFrm.InspectorPageControlChange(Sender: TObject);
begin
CellInspector.Parent := InspectorPageControl.ActivePage;
UpdateInspector;
end;
procedure TMainFrm.LoadFile(const AFileName: String);
// Loads first worksheet from file into grid
var
pages: TStrings;
i: Integer;
err: String;
begin
// Load file
Screen.Cursor := crHourglass;
try
try
WorksheetGrid.LoadFromSpreadsheetFile(UTF8ToSys(AFileName));
except
on E: Exception do begin
// In an error occurs show at least an empty valid worksheet
AcNewExecute(nil);
MessageDlg(E.Message, mtError, [mbOk], 0);
exit;
end;
end;
// Update user interface
Caption := Format('spready - %s (%s)', [
AFilename,
GetFileFormatName(WorksheetGrid.Workbook.FileFormat)
]);
AcShowGridLines.Checked := WorksheetGrid.ShowGridLines;
AcShowHeaders.Checked := WorksheetGrid.ShowHeaders;
EdFrozenCols.Value := WorksheetGrid.FrozenCols;
EdFrozenRows.Value := WorksheetGrid.FrozenRows;
WorksheetGrid.TextOverflow := CbTextOverflow.Checked;
SetupBackgroundColorBox;
// Load names of worksheets into tabcontrol and show first sheet
WorksheetGrid.GetSheets(TabControl.Tabs);
TabControl.TabIndex := 0;
// Update display
WorksheetGridSelection(nil, WorksheetGrid.Col, WorksheetGrid.Row);
finally
Screen.Cursor := crDefault;
err := WorksheetGrid.Workbook.ErrorMsg;
if err <> '' then
MessageDlg(err, mtError, [mbOK], 0);
end;
end;
procedure TMainFrm.SetupBackgroundColorBox;
begin
// This change triggers re-reading of the workbooks palette by the OnGetColors
// event of the ColorBox.
CbBackgroundColor.Style := CbBackgroundColor.Style - [cbCustomColors];
CbBackgroundColor.Style := CbBackgroundColor.Style + [cbCustomColors];
Application.ProcessMessages;
end;
procedure TMainFrm.TabControlChange(Sender: TObject);
begin
WorksheetGrid.SelectSheetByIndex(TabControl.TabIndex);
end;
procedure TMainFrm.UpdateBackgroundColorIndex;
var
sClr: TsColor;
begin
with WorksheetGrid do sClr := BackgroundColors[Selection];
if sClr = scNotDefined then
CbBackgroundColor.ItemIndex := 0 // no fill
else
CbBackgroundColor.ItemIndex := sClr + 1;
end;
procedure TMainFrm.UpdateHorAlignmentActions;
var
i: Integer;
ac: TAction;
hor_align: TsHorAlignment;
begin
with WorksheetGrid do hor_align := HorAlignments[Selection];
for i:=0 to ActionList.ActionCount-1 do begin
ac := TAction(ActionList.Actions[i]);
if (ac.Tag >= HORALIGN_TAG) and (ac.Tag < HORALIGN_TAG+10) then
ac.Checked := ((ac.Tag - HORALIGN_TAG) = ord(hor_align));
end;
end;
procedure TMainFrm.UpdateCellInfo(ACell: PCell);
var
i: Integer;
s: String;
cb: TsCellBorder;
r1,r2,c1,c2: Cardinal;
begin
with CellInspector do begin
TitleCaptions[0] := 'Properties';
TitleCaptions[1] := 'Values';
Strings.Clear;
if InspectorPageControl.ActivePage = PgCellValue then
begin
if ACell=nil
then Strings.Add('Row=')
else Strings.Add(Format('Row=%d', [ACell^.Row]));
if ACell=nil
then Strings.Add('Column=')
else Strings.Add(Format('Column=%d', [ACell^.Col]));
if ACell=nil
then Strings.Add('ContentType=')
else Strings.Add(Format('ContentType=%s', [GetEnumName(TypeInfo(TCellContentType), ord(ACell^.ContentType))]));
if ACell=nil
then Strings.Add('NumberValue=')
else Strings.Add(Format('NumberValue=%g', [ACell^.NumberValue]));
if ACell=nil
then Strings.Add('DateTimeValue=')
else Strings.Add(Format('DateTimeValue=%g', [ACell^.DateTimeValue]));
if ACell=nil
then Strings.Add('UTF8StringValue=')
else Strings.Add(Format('UTF8StringValue=%s', [ACell^.UTF8StringValue]));
if ACell=nil
then Strings.Add('BoolValue=')
else Strings.Add(Format('BoolValue=%s', [BoolToStr(ACell^.BoolValue)]));
if ACell=nil
then Strings.Add('ErrorValue=')
else Strings.Add(Format('ErrorValue=%s', [
GetEnumName(TypeInfo(TsErrorValue), ord(ACell^.ErrorValue)) ]));
if (ACell=nil) or (Length(ACell^.FormulaValue)=0)
then Strings.Add('FormulaValue=')
else Strings.Add(Format('FormulaValue="%s"', [ACell^.FormulaValue]));
if (ACell=nil) or (ACell^.SharedFormulaBase=nil)
then Strings.Add('SharedFormulaBase=')
else Strings.Add(Format('SharedFormulaBase=%s', [GetCellString(
ACell^.SharedFormulaBase^.Row, ACell^.SharedFormulaBase^.Col)]));
end
else
begin
if (ACell=nil) or not (uffFont in ACell^.UsedFormattingFields)
then Strings.Add('FontIndex=')
else Strings.Add(Format('FontIndex=%d (%s(', [
ACell^.FontIndex,
WorksheetGrid.Workbook.GetFontAsString(ACell^.FontIndex)]));
if (ACell=nil) or not (uffTextRotation in ACell^.UsedFormattingFields)
then Strings.Add('TextRotation=')
else Strings.Add(Format('TextRotation=%s', [GetEnumName(TypeInfo(TsTextRotation), ord(ACell^.TextRotation))]));
if (ACell=nil) or not (uffHorAlign in ACell^.UsedFormattingFields)
then Strings.Add('HorAlignment=')
else Strings.Add(Format('HorAlignment=%s', [GetEnumName(TypeInfo(TsHorAlignment), ord(ACell^.HorAlignment))]));
if (ACell=nil) or not (uffVertAlign in ACell^.UsedFormattingFields)
then Strings.Add('VertAlignment=')
else Strings.Add(Format('VertAlignment=%s', [GetEnumName(TypeInfo(TsVertAlignment), ord(ACell^.VertAlignment))]));
if (ACell=nil) or not (uffBorder in ACell^.UsedFormattingFields) then
Strings.Add('Borders=')
else begin
s := '';
if cbNorth in ACell^.Border then s := s + ', cbNorth';
if cbSouth in ACell^.Border then s := s + ', cbSouth';
if cbEast in ACell^.Border then s := s + ', cbEast';
if cbWest in ACell^.Border then s := s + ', cbWest';
if cbDiagUp in ACell^.Border then s := s + ', cbDiagUp';
if cbDiagDown in ACell^.Border then s := s + ', cbDiagDown';
if s <> '' then Delete(s, 1, 2);
Strings.Add('Borders='+s);
end;
for cb in TsCellBorder do
if ACell=nil then
Strings.Add(Format('BorderStyles[%s]=', [
GetEnumName(TypeInfo(TsCellBorder), ord(cb))
]))
else
Strings.Add(Format('BorderStyles[%s]=%s, %s', [
GetEnumName(TypeInfo(TsCellBorder), ord(cb)),
GetEnumName(TypeInfo(TsLineStyle), ord(ACell^.BorderStyles[cbEast].LineStyle)),
WorksheetGrid.Workbook.GetColorName(ACell^.BorderStyles[cbEast].Color)
]));
if (ACell=nil) or not (uffBackgroundColor in ACell^.UsedformattingFields)
then Strings.Add('BackgroundColor=')
else Strings.Add(Format('BackgroundColor=%d (%s)', [
ACell^.BackgroundColor,
WorksheetGrid.Workbook.GetColorName(Acell^.BackgroundColor)
]));
if (ACell=nil) or not (uffNumberFormat in ACell^.UsedFormattingFields)
then Strings.Add('NumberFormat=')
else Strings.Add(Format('NumberFormat=%s', [GetEnumName(TypeInfo(TsNumberFormat), ord(ACell^.NumberFormat))]));
if (ACell=nil) or not (uffNumberFormat in ACell^.UsedFormattingFields)
then Strings.Add('NumberFormatStr=')
else Strings.Add('NumberFormatStr=' + ACell^.NumberFormatStr);
if not WorksheetGrid.Worksheet.IsMerged(ACell) then
Strings.Add('Merged range=')
else begin
WorksheetGrid.Worksheet.FindMergedRange(ACell, r1, c1, r2, c2);
Strings.Add('Merged range=' + GetCellRangeString(r1, c1, r2, c2));
end;
end;
end;
end;
procedure TMainFrm.UpdateFontNameIndex;
var
fname: String;
begin
with WorksheetGrid do fname := CellFontNames[Selection];
if fname = '' then
FontCombobox.ItemIndex := -1
else
FontCombobox.ItemIndex := FontCombobox.Items.IndexOf(fname);
end;
procedure TMainFrm.UpdateFontSizeIndex;
var
sz: Single;
begin
with WorksheetGrid do sz := CellFontSizes[Selection];
if sz < 0 then
FontSizeCombobox.ItemIndex := -1
else
FontSizeCombobox.ItemIndex := FontSizeCombobox.Items.IndexOf(IntToStr(Round(sz)));
end;
procedure TMainFrm.UpdateFontStyleActions;
var
style: TsFontStyles;
begin
with WorksheetGrid do style := CellFontStyles[Selection];
AcFontBold.Checked := fssBold in style;
AcFontItalic.Checked := fssItalic in style;
AcFontUnderline.Checked := fssUnderline in style;
AcFontStrikeout.Checked := fssStrikeOut in style;
end;
procedure TMainFrm.UpdateInspector;
var
r, c: Cardinal;
cell: PCell;
begin
r := WorksheetGrid.GetWorksheetRow(WorksheetGrid.Row);
c := WorksheetGrid.GetWorksheetCol(WorksheetGrid.Col);
cell := WorksheetGrid.Worksheet.FindCell(r, c);
UpdateCellInfo(cell);
end;
procedure TMainFrm.UpdateNumFormatActions;
var
i: Integer;
ac: TAction;
nf: TsNumberFormat;
cell: PCell;
r,c: Cardinal;
found: Boolean;
begin
with WorksheetGrid do begin
r := GetWorksheetRow(Row);
c := GetWorksheetCol(Col);
cell := Worksheet.FindCell(r, c);
if (cell = nil) or not (cell^.ContentType in [cctNumber, cctDateTime]) then
nf := nfGeneral
else
nf := cell^.NumberFormat;
for i:=0 to ActionList.ActionCount-1 do begin
ac := TAction(ActionList.Actions[i]);
if (ac.Tag >= NUMFMT_TAG) and (ac.Tag < NUMFMT_TAG + 200) then begin
found := ((ac.Tag - NUMFMT_TAG) div 10 = ord(nf));
if nf = nfCustom then
case (ac.Tag - NUMFMT_TAG) mod 10 of
1: found := cell^.NumberFormatStr = 'dd/mmm';
2: found := cell^.NumberFormatStr = 'mmm/yy';
3: found := cell^.NumberFormatStr = 'nn:ss';
4: found := cell^.NumberFormatStr = 'nn:ss.z';
end;
ac.Checked := found;
end;
end;
Invalidate;
end;
end;
procedure TMainFrm.UpdateTextRotationActions;
var
i: Integer;
ac: TAction;
text_rot: TsTextRotation;
begin
with WorksheetGrid do text_rot := TextRotations[Selection];
for i:=0 to ActionList.ActionCount-1 do begin
ac := TAction(ActionList.Actions[i]);
if (ac.Tag >= TEXTROT_TAG) and (ac.Tag < TEXTROT_TAG+10) then
ac.Checked := ((ac.Tag - TEXTROT_TAG) = ord(text_rot));
end;
end;
procedure TMainFrm.UpdateVertAlignmentActions;
var
i: Integer;
ac: TAction;
vert_align: TsVertAlignment;
begin
with WorksheetGrid do vert_align := VertAlignments[Selection];
for i:=0 to ActionList.ActionCount-1 do begin
ac := TAction(ActionList.Actions[i]);
if (ac.Tag >= VERTALIGN_TAG) and (ac.Tag < VERTALIGN_TAG+10) then
ac.Checked := ((ac.Tag - VERTALIGN_TAG) = ord(vert_align));
end;
end;
procedure TMainFrm.UpdateWordwraps;
var
wrapped: Boolean;
begin
with WorksheetGrid do wrapped := Wordwraps[Selection];
AcWordwrap.Checked := wrapped;
end;
procedure TMainFrm.WorksheetGridSelection(Sender: TObject; ACol, ARow: Integer);
var
r, c: Cardinal;
cell: PCell;
s: String;
begin
if WorksheetGrid.Workbook = nil then
exit;
r := WorksheetGrid.GetWorksheetRow(ARow);
c := WorksheetGrid.GetWorksheetCol(ACol);
if AcCopyFormat.Checked then begin
WorksheetGrid.Worksheet.CopyFormat(@FCopiedFormat, r, c);
AcCopyFormat.Checked := false;
end;
cell := WorksheetGrid.Worksheet.FindCell(r, c);
if cell <> nil then begin
s := WorksheetGrid.Worksheet.ReadFormulaAsString(cell, true);
if s <> '' then begin
if s[1] <> '=' then s := '=' + s;
EdFormula.Text := s;
end
else
case cell^.ContentType of
cctNumber:
EdFormula.Text := FloatToStr(cell^.NumberValue);
cctDateTime:
if cell^.DateTimeValue < 1.0 then
EdFormula.Text := FormatDateTime('tt', cell^.DateTimeValue)
else
EdFormula.Text := FormatDateTime('c', cell^.DateTimeValue);
cctUTF8String:
EdFormula.Text := cell^.UTF8StringValue;
else
EdFormula.Text := WorksheetGrid.Worksheet.ReadAsUTF8Text(cell);
end;
end else
EdFormula.Text := '';
EdCellAddress.Text := GetCellString(r, c, [rfRelRow, rfRelCol]);
AcMergeCells.Checked := WorksheetGrid.Worksheet.IsMerged(cell);
UpdateHorAlignmentActions;
UpdateVertAlignmentActions;
UpdateWordwraps;
UpdateBackgroundColorIndex;
// UpdateFontActions;
UpdateFontNameIndex;
UpdateFontSizeIndex;
UpdateFontStyleActions;
UpdateTextRotationActions;
UpdateNumFormatActions;
UpdateCellInfo(cell);
end;
initialization
{$I mainform.lrs}
end.