fpspreadsheet: Use interfaces in the notification mechanism of the visual controls - this avoids requiring the TAChart package even in case of non-chart-aware spreadsheet programs.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3872 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2015-01-06 17:42:54 +00:00
parent b450c32ad3
commit 157a1133fb
9 changed files with 140 additions and 87 deletions

View File

@ -28,13 +28,10 @@
<FormatVersion Value="1"/> <FormatVersion Value="1"/>
</local> </local>
</RunParams> </RunParams>
<RequiredPackages Count="2"> <RequiredPackages Count="1">
<Item1> <Item1>
<PackageName Value="TAChartLazarusPkg"/>
</Item1>
<Item2>
<PackageName Value="LCL"/> <PackageName Value="LCL"/>
</Item2> </Item1>
</RequiredPackages> </RequiredPackages>
<Units Count="2"> <Units Count="2">
<Unit0> <Unit0>

View File

@ -7,7 +7,7 @@ uses
cthreads, cthreads,
{$ENDIF}{$ENDIF} {$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset Interfaces, // this includes the LCL widgetset
Forms, tachartlazaruspkg, main; Forms, main;
{$R *.res} {$R *.res}

View File

@ -51,13 +51,10 @@
<FormatVersion Value="1"/> <FormatVersion Value="1"/>
</local> </local>
</RunParams> </RunParams>
<RequiredPackages Count="2"> <RequiredPackages Count="1">
<Item1> <Item1>
<PackageName Value="TAChartLazarusPkg"/>
</Item1>
<Item2>
<PackageName Value="LCL"/> <PackageName Value="LCL"/>
</Item2> </Item1>
</RequiredPackages> </RequiredPackages>
<Units Count="2"> <Units Count="2">
<Unit0> <Unit0>

View File

@ -7,7 +7,7 @@ uses
cthreads, cthreads,
{$ENDIF}{$ENDIF} {$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset Interfaces, // this includes the LCL widgetset
Forms, tachartlazaruspkg, mainfrm Forms, mainfrm
{ you can add units after this }; { you can add units after this };
{$R *.res} {$R *.res}

View File

@ -82,7 +82,7 @@ type
TsXYRange = (rngX, rngY); TsXYRange = (rngX, rngY);
TsWorkbookChartSource = class(TCustomChartSource) TsWorkbookChartSource = class(TCustomChartSource, IsSpreadsheetControl)
private private
FWorkbookSource: TsWorkbookSource; FWorkbookSource: TsWorkbookSource;
FWorkbook: TsWorkbook; FWorkbook: TsWorkbook;
@ -108,10 +108,13 @@ type
procedure SetYCount(AValue: Cardinal); override; procedure SetYCount(AValue: Cardinal); override;
public public
destructor Destroy; override; destructor Destroy; override;
procedure ListenerNotification(AChangedItems: TsNotificationItems; AData: Pointer = nil);
procedure Reset; procedure Reset;
property PointsNumber: Cardinal read FPointsNumber; property PointsNumber: Cardinal read FPointsNumber;
property Workbook: TsWorkbook read GetWorkbook; property Workbook: TsWorkbook read GetWorkbook;
public
// Interface to TsWorkbookSource
procedure ListenerNotification(AChangedItems: TsNotificationItems; AData: Pointer = nil);
procedure RemoveWorkbookSource;
published published
property WorkbookSource: TsWorkbookSource read FWorkbookSource write SetWorkbookSource; property WorkbookSource: TsWorkbookSource read FWorkbookSource write SetWorkbookSource;
property XRange: String index rngX read GetRange write SetRange; property XRange: String index rngX read GetRange write SetRange;
@ -119,9 +122,9 @@ type
end; end;
procedure Register; procedure Register;
implementation implementation
uses uses
@ -586,6 +589,15 @@ begin
end; end;
end; end;
{@@ ----------------------------------------------------------------------------
Removes the link of the ChartSource to the WorkbookSource.
Required before destruction.
-------------------------------------------------------------------------------}
procedure TsWorkbookChartSource.RemoveWorkbookSource;
begin
SetWorkbookSource(nil);
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Resets internal buffers and notfies chart elements of the changes, Resets internal buffers and notfies chart elements of the changes,
in particular, enforces recalculation of axis limits in particular, enforces recalculation of axis limits

View File

@ -159,12 +159,23 @@ type
end; end;
const
GUID_SpreadsheetControl = '{CBCAAE52-D29E-4D0C-A7F4-1016C873448A}';
type
{ IsSpreadsheetControl }
IsSpreadsheetControl = interface [GUID_SpreadsheetControl]
procedure ListenerNotification(AChangedItems: TsNotificationItems;
AData: Pointer = nil);
procedure RemoveWorkbookSource;
end;
{ TsWorkbookTabControl } { TsWorkbookTabControl }
{@@ TsWorkbookTabControl is a tab control which displays the sheets of the {@@ TsWorkbookTabControl is a tab control which displays the sheets of the
workbook currently loaded by the WorkbookSource in tabs. Selecting another workbook currently loaded by the WorkbookSource in tabs. Selecting another
tab is communicated to other spreadsheet controls via the WorkbookSource. } tab is communicated to other spreadsheet controls via the WorkbookSource. }
TsWorkbookTabControl = class(TTabControl) TsWorkbookTabControl = class(TTabControl, IsSpreadsheetControl)
private private
FWorkbookSource: TsWorkbookSource; FWorkbookSource: TsWorkbookSource;
FLockCount: Integer; FLockCount: Integer;
@ -179,6 +190,7 @@ type
destructor Destroy; override; destructor Destroy; override;
procedure ListenerNotification(AChangedItems: TsNotificationItems; procedure ListenerNotification(AChangedItems: TsNotificationItems;
AData: Pointer = nil); AData: Pointer = nil);
procedure RemoveWorkbookSource;
{@@ The worksheet names of this workbook are currently displayed as tabs of the TabControl. } {@@ The worksheet names of this workbook are currently displayed as tabs of the TabControl. }
property Workbook: TsWorkbook read GetWorkbook; property Workbook: TsWorkbook read GetWorkbook;
{@@ Identifies the worksheet which corresponds to the selected tab } {@@ Identifies the worksheet which corresponds to the selected tab }
@ -193,7 +205,7 @@ type
{@@ TsCellEdit allows to edit the content or formula of the active cell of a {@@ TsCellEdit allows to edit the content or formula of the active cell of a
worksheet, simular to Excel's cell editor above the cell grid. } worksheet, simular to Excel's cell editor above the cell grid. }
TsCellEdit = class(TMemo) TsCellEdit = class(TMemo, IsSpreadsheetControl)
private private
FWorkbookSource: TsWorkbookSource; FWorkbookSource: TsWorkbookSource;
function GetSelectedCell: PCell; function GetSelectedCell: PCell;
@ -209,6 +221,7 @@ type
procedure EditingDone; override; procedure EditingDone; override;
procedure ListenerNotification(AChangedItems: TsNotificationItems; procedure ListenerNotification(AChangedItems: TsNotificationItems;
AData: Pointer = nil); AData: Pointer = nil);
procedure RemoveWorkbookSource;
{@@ Pointer to the currently active cell in the workbook. This cell is {@@ Pointer to the currently active cell in the workbook. This cell is
displayed in the control and can be edited. } displayed in the control and can be edited. }
property SelectedCell: PCell read GetSelectedCell; property SelectedCell: PCell read GetSelectedCell;
@ -227,7 +240,7 @@ type
{@@ TsCellIndicator displays the address of the currently active cell of the {@@ TsCellIndicator displays the address of the currently active cell of the
worksheet and workbook. Editing the address allows to jump to the corresponding worksheet and workbook. Editing the address allows to jump to the corresponding
cell. } cell. }
TsCellIndicator = class(TEdit) TsCellIndicator = class(TEdit, IsSpreadsheetControl)
private private
FWorkbookSource: TsWorkbookSource; FWorkbookSource: TsWorkbookSource;
function GetWorkbook: TsWorkbook; function GetWorkbook: TsWorkbook;
@ -241,6 +254,7 @@ type
procedure EditingDone; override; procedure EditingDone; override;
procedure ListenerNotification(AChangedItems: TsNotificationItems; procedure ListenerNotification(AChangedItems: TsNotificationItems;
AData: Pointer = nil); AData: Pointer = nil);
procedure RemoveWorkbookSource;
{@@ Refers to the underlying worksheet to which the edited cell belongs. } {@@ Refers to the underlying worksheet to which the edited cell belongs. }
property Workbook: TsWorkbook read GetWorkbook; property Workbook: TsWorkbook read GetWorkbook;
{@@ Refers to the underlying worksheet to which the edited cell belongs. } {@@ Refers to the underlying worksheet to which the edited cell belongs. }
@ -262,7 +276,7 @@ type
{@@ TsCellCombobox is a multi-purpose combobox for selection of formatting {@@ TsCellCombobox is a multi-purpose combobox for selection of formatting
items of a cell } items of a cell }
TsCellCombobox = class(TCustomCombobox) TsCellCombobox = class(TCustomCombobox, IsSpreadsheetControl)
private private
FWorkbookSource: TsWorkbookSource; FWorkbookSource: TsWorkbookSource;
FFormatItem: TsCellFormatItem; FFormatItem: TsCellFormatItem;
@ -290,6 +304,7 @@ type
destructor Destroy; override; destructor Destroy; override;
procedure ListenerNotification(AChangedItems: TsNotificationItems; procedure ListenerNotification(AChangedItems: TsNotificationItems;
AData: Pointer = nil); AData: Pointer = nil);
procedure RemoveWorkbookSource;
{@@ Refers to the underlying workbook } {@@ Refers to the underlying workbook }
property Workbook: TsWorkbook read GetWorkbook; property Workbook: TsWorkbook read GetWorkbook;
{@@ Refers to the underlying worksheet containing the displayed cell } {@@ Refers to the underlying worksheet containing the displayed cell }
@ -383,7 +398,7 @@ type
{@@ TsSpreadsheetInspector displays all properties of a workbook, worksheet, {@@ TsSpreadsheetInspector displays all properties of a workbook, worksheet,
cell content and cell formatting in a way similar to the Object Inspector cell content and cell formatting in a way similar to the Object Inspector
of Lazarus. } of Lazarus. }
TsSpreadsheetInspector = class(TValueListEditor) TsSpreadsheetInspector = class(TValueListEditor, IsSpreadsheetControl)
private private
FWorkbookSource: TsWorkbookSource; FWorkbookSource: TsWorkbookSource;
FMode: TsInspectorMode; FMode: TsInspectorMode;
@ -403,6 +418,7 @@ type
destructor Destroy; override; destructor Destroy; override;
procedure ListenerNotification(AChangedItems: TsNotificationItems; procedure ListenerNotification(AChangedItems: TsNotificationItems;
AData: Pointer = nil); AData: Pointer = nil);
procedure RemoveWorkbookSource;
{@@ Refers to the underlying workbook which is displayed by the inspector. } {@@ Refers to the underlying workbook which is displayed by the inspector. }
property Workbook: TsWorkbook read GetWorkbook; property Workbook: TsWorkbook read GetWorkbook;
{@@ Refers to the underlying worksheet which is displayed by the inspector. } {@@ Refers to the underlying worksheet which is displayed by the inspector. }
@ -427,7 +443,7 @@ implementation
uses uses
Types, Math, TypInfo, LCLType, Dialogs, Forms, Types, Math, TypInfo, LCLType, Dialogs, Forms,
fpsStrings, fpsUtils, fpSpreadsheetGrid, fpSpreadsheetChart; fpsStrings, fpsUtils; //, fpSpreadsheetGrid, fpSpreadsheetChart;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
@ -437,7 +453,7 @@ uses
procedure Register; procedure Register;
begin begin
RegisterComponents('FPSpreadsheet', [ RegisterComponents('FPSpreadsheet', [
TsWorkbookSource, TsWorkbookTabControl, TsWorksheetGrid, TsWorkbookSource, TsWorkbookTabControl, //TsWorksheetGrid,
TsCellEdit, TsCellIndicator, TsCellCombobox, TsCellEdit, TsCellIndicator, TsCellCombobox,
TsSpreadsheetInspector TsSpreadsheetInspector
]); ]);
@ -884,36 +900,18 @@ end;
procedure TsWorkbookSource.NotifyListeners(AChangedItems: TsNotificationItems; procedure TsWorkbookSource.NotifyListeners(AChangedItems: TsNotificationItems;
AData: Pointer = nil); AData: Pointer = nil);
var var
i: Integer; j: Integer;
I: IsSpreadsheetControl;
C: TComponent;
begin begin
for i:=0 to FListeners.Count-1 do for j:=0 to FListeners.Count-1 do begin
if TObject(FListeners[i]) is TsCellCombobox then C := TComponent(FListeners[j]);
TsCellCombobox(FListeners[i]).ListenerNotification(AChangedItems, AData) if C.GetInterface(GUID_SpreadsheetControl, I) then
I.ListenerNotification(AChangedItems, AData)
else else
if TObject(FListeners[i]) is TsCellIndicator then
TsCellIndicator(FListeners[i]).ListenerNotification(AChangedItems, AData)
else
if TObject(FListeners[i]) is TsCellEdit then
TsCellEdit(FListeners[i]).ListenerNotification(AChangedItems, AData)
else
if TObject(FListeners[i]) is TsWorkbookTabControl then
TsWorkbookTabControl(FListeners[i]).ListenerNotification(AChangedItems, AData)
else
if TObject(FListeners[i]) is TsWorksheetGrid then
TsWorksheetGrid(FListeners[i]).ListenerNotification(AChangedItems, AData)
else
if TObject(FListeners[i]) is TsSpreadsheetInspector then
TsSpreadsheetInspector(FListeners[i]).ListenerNotification(AChangedItems, AData)
else
if TObject(FListeners[i]) is TsWorkbookChartSource then
TsWorkbookChartSource(FListeners[i]).ListenerNotification(AChangedItems, AData)
else
{
if TObject(FListeners[i]) is TsSpreadsheetAction then
TsSpreadsheetAction(FListeners[i]).ListenerNotifiation(AChangedItems, AData)
else }
raise Exception.CreateFmt('Class %s is not prepared to be a spreadsheet listener.', raise Exception.CreateFmt('Class %s is not prepared to be a spreadsheet listener.',
[TObject(FListeners[i]).ClassName]); [C.ClassName]);
end;
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
@ -924,40 +922,21 @@ end;
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
procedure TsWorkbookSource.RemoveListener(AListener: TComponent); procedure TsWorkbookSource.RemoveListener(AListener: TComponent);
var var
i: Integer; j: Integer;
I: IsSpreadsheetControl;
C: TComponent;
begin begin
for i:= FListeners.Count-1 downto 0 do for j:=FListeners.Count-1 downto 0 do begin
if TComponent(FListeners[i]) = AListener then C := TComponent(FListeners[j]);
if C = AListener then
begin begin
FListeners.Delete(i); FListeners.Delete(j);
if (AListener is TsCellCombobox) then if C.GetInterface(GUID_SpreadsheetControl, I) then
TsCellCombobox(AListener).WorkbookSource := nil I.RemoveWorkbookSource
else else
if (AListener is TsCellIndicator) then
TsCellIndicator(AListener).WorkbookSource := nil
else
if (AListener is TsCellEdit) then
TsCellEdit(AListener).WorkbookSource := nil
else
if (AListener is TsWorkbookTabControl) then
TsWorkbookTabControl(AListener).WorkbookSource := nil
else
if (AListener is TsWorksheetGrid) then
TsWorksheetGrid(AListener).WorkbookSource := nil
else
if (AListener is TsSpreadsheetInspector) then
TsSpreadsheetInspector(AListener).WorkbookSource := nil
else
if (AListener is TsWorkbookChartSource) then
TsWorkbookChartSource(AListener).WorkbookSource := nil
else
{
if (AListener is TsSpreadsheetAction) then
TsSpreadsheetAction(AListener).WorksheetLink := nil
else }
raise Exception.CreateFmt('Class %s not prepared for listening.',[AListener.ClassName]); raise Exception.CreateFmt('Class %s not prepared for listening.',[AListener.ClassName]);
exit;
end; end;
end;
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
@ -1455,6 +1434,15 @@ begin
SetWorkbookSource(nil); SetWorkbookSource(nil);
end; end;
{@@ ----------------------------------------------------------------------------
Removes the link of the TabControl to the WorkbookSource. Required before
destruction.
-------------------------------------------------------------------------------}
procedure TsWorkbookTabControl.RemoveWorkbookSource;
begin
SetWorkbookSource(nil);
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Setter method for the WorkbookSource Setter method for the WorkbookSource
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
@ -1593,6 +1581,15 @@ begin
SetWorkbookSource(nil); SetWorkbookSource(nil);
end; end;
{@@ ----------------------------------------------------------------------------
Removes the link of the CellEdit to the WorkbookSource. Required before
destruction.
-------------------------------------------------------------------------------}
procedure TsCellEdit.RemoveWorkbookSource;
begin
SetWorkbookSource(nil);
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Setter method for the WorkbookSource Setter method for the WorkbookSource
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
@ -1751,6 +1748,15 @@ begin
SetWorkbooksource(nil); SetWorkbooksource(nil);
end; end;
{@@ ----------------------------------------------------------------------------
Removes the link of the CellIndicator to the WorkbookSource. Required before
destruction.
-------------------------------------------------------------------------------}
procedure TsCellIndicator.RemoveWorkbookSource;
begin
SetWorkbookSource(nil);
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Setter method for the WorkbookSource Setter method for the WorkbookSource
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
@ -2120,6 +2126,15 @@ begin
end; end;
end; end;
{@@ ----------------------------------------------------------------------------
Removes the link of the CellCombobox to the WorkbookSource. Required before
destruction.
-------------------------------------------------------------------------------}
procedure TsCellCombobox.RemoveWorkbookSource;
begin
SetWorkbookSource(nil);
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
A new item in the combobox is selected. Calls "ProcessValue" to changes the A new item in the combobox is selected. Calls "ProcessValue" to changes the
selected cells according to the Mode property by calling ApplyFormatToCell. selected cells according to the Mode property by calling ApplyFormatToCell.
@ -2477,6 +2492,15 @@ begin
SetWorkbookSource(nil); SetWorkbookSource(nil);
end; end;
{@@ ----------------------------------------------------------------------------
Removes the link of the SpreadsheetInspector to the WorkbookSource.
Required before destruction.
-------------------------------------------------------------------------------}
procedure TsSpreadsheetInspector.RemoveWorkbookSource;
begin
SetWorkbookSource(nil);
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Setter method for the Mode property. This property filters groups of properties Setter method for the Mode property. This property filters groups of properties
for display (workbook-, worksheet-, cell value- or cell formatting-related for display (workbook-, worksheet-, cell value- or cell formatting-related

View File

@ -1,7 +1,7 @@
{ fpspreadsheetgrid } { fpspreadsheetgrid }
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Grid component which can load and write data from / to FPSpreadsheet documents. Grid component which can load and write data from/to FPSpreadsheet documents.
Can either be used alone or in combination with a TsWorkbookSource component. Can either be used alone or in combination with a TsWorkbookSource component.
The latter case requires less written code. The latter case requires less written code.
@ -34,7 +34,7 @@ type
{@@ TsCustomWorksheetGrid is the ancestor of TsWorksheetGrid and is able to {@@ TsCustomWorksheetGrid is the ancestor of TsWorksheetGrid and is able to
display spreadsheet data along with their formatting. } display spreadsheet data along with their formatting. }
TsCustomWorksheetGrid = class(TCustomDrawGrid) TsCustomWorksheetGrid = class(TCustomDrawGrid, IsSpreadsheetControl)
private private
{ Private declarations } { Private declarations }
FWorkbookSource: TsWorkbookSource; FWorkbookSource: TsWorkbookSource;
@ -225,9 +225,10 @@ type
procedure Convert_Font_to_sFont(AFont: TFont; sFont: TsFont); procedure Convert_Font_to_sFont(AFont: TFont; sFont: TsFont);
function FindNearestPaletteIndex(AColor: TColor): TsColor; function FindNearestPaletteIndex(AColor: TColor): TsColor;
{ Interfacing with WorkbookLink } { Interfacing with WorkbookSource}
procedure ListenerNotification(AChangedItems: TsNotificationItems; procedure ListenerNotification(AChangedItems: TsNotificationItems;
AData: Pointer = nil); AData: Pointer = nil);
procedure RemoveWorkbookSource;
{ public properties } { public properties }
{@@ Link to the workbook } {@@ Link to the workbook }
@ -555,6 +556,7 @@ type
property OnContextPopup; property OnContextPopup;
end; end;
procedure Register;
implementation implementation
@ -3189,14 +3191,12 @@ begin
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Splits a merged cell block into single cells Removes the link of the WorksheetGrid to the WorkbookSource.
Required before destruction.
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
procedure TsCustomWorksheetGrid.UnmergeCells; procedure TsCustomWorksheetGrid.RemoveWorkbookSource;
begin begin
Worksheet.UnmergeCells( SetWorkbookSource(nil);
GetWorksheetRow(Selection.Top),
GetWorksheetCol(Selection.Left)
);
end; end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
@ -3462,6 +3462,17 @@ begin
Delete(Result, Length(Result), 1); Delete(Result, Length(Result), 1);
end; end;
{@@ ----------------------------------------------------------------------------
Splits a merged cell block into single cells
-------------------------------------------------------------------------------}
procedure TsCustomWorksheetGrid.UnmergeCells;
begin
Worksheet.UnmergeCells(
GetWorksheetRow(Selection.Top),
GetWorksheetCol(Selection.Left)
);
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Updates column widths according to the data in the TCol records Updates column widths according to the data in the TCol records
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
@ -4186,6 +4197,16 @@ begin
end; end;
{@@ ----------------------------------------------------------------------------
Registers the worksheet grid in the Lazarus component palette,
page "FPSpreadsheet".
-------------------------------------------------------------------------------}
procedure Register;
begin
RegisterComponents('FPSpreadsheet', [TsWorksheetGrid]);
end;
initialization initialization
fpsutils.ScreenPixelsPerInch := Screen.PixelsPerInch; fpsutils.ScreenPixelsPerInch := Screen.PixelsPerInch;

View File

@ -28,6 +28,7 @@ It provides graphical components like a grid and chart."/>
</Item1> </Item1>
<Item2> <Item2>
<Filename Value="fpspreadsheetgrid.pas"/> <Filename Value="fpspreadsheetgrid.pas"/>
<HasRegisterProc Value="True"/>
<UnitName Value="fpspreadsheetgrid"/> <UnitName Value="fpspreadsheetgrid"/>
</Item2> </Item2>
<Item3> <Item3>

View File

@ -15,6 +15,7 @@ implementation
procedure Register; procedure Register;
begin begin
RegisterUnit('fpspreadsheetctrls', @fpspreadsheetctrls.Register); RegisterUnit('fpspreadsheetctrls', @fpspreadsheetctrls.Register);
RegisterUnit('fpspreadsheetgrid', @fpspreadsheetgrid.Register);
RegisterUnit('fpspreadsheetchart', @fpspreadsheetchart.Register); RegisterUnit('fpspreadsheetchart', @fpspreadsheetchart.Register);
RegisterUnit('fpsActions', @fpsActions.Register); RegisterUnit('fpsActions', @fpsActions.Register);
end; end;