You've already forked lazarus-ccr
fpspreadsheet: Avoid duplicate code in TsWorkbookChartSource. Fix crashes of the chartsource when used worksheets are renamed or deleted. More refined notification of visual controls.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3867 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -28,10 +28,13 @@
|
|||||||
<FormatVersion Value="1"/>
|
<FormatVersion Value="1"/>
|
||||||
</local>
|
</local>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<RequiredPackages Count="1">
|
<RequiredPackages Count="2">
|
||||||
<Item1>
|
<Item1>
|
||||||
<PackageName Value="LCL"/>
|
<PackageName Value="TAChartLazarusPkg"/>
|
||||||
</Item1>
|
</Item1>
|
||||||
|
<Item2>
|
||||||
|
<PackageName Value="LCL"/>
|
||||||
|
</Item2>
|
||||||
</RequiredPackages>
|
</RequiredPackages>
|
||||||
<Units Count="2">
|
<Units Count="2">
|
||||||
<Unit0>
|
<Unit0>
|
||||||
|
@ -7,7 +7,7 @@ uses
|
|||||||
cthreads,
|
cthreads,
|
||||||
{$ENDIF}{$ENDIF}
|
{$ENDIF}{$ENDIF}
|
||||||
Interfaces, // this includes the LCL widgetset
|
Interfaces, // this includes the LCL widgetset
|
||||||
Forms, main;
|
Forms, tachartlazaruspkg, main;
|
||||||
|
|
||||||
{$R *.res}
|
{$R *.res}
|
||||||
|
|
||||||
|
@ -51,10 +51,13 @@
|
|||||||
<FormatVersion Value="1"/>
|
<FormatVersion Value="1"/>
|
||||||
</local>
|
</local>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<RequiredPackages Count="1">
|
<RequiredPackages Count="2">
|
||||||
<Item1>
|
<Item1>
|
||||||
<PackageName Value="LCL"/>
|
<PackageName Value="TAChartLazarusPkg"/>
|
||||||
</Item1>
|
</Item1>
|
||||||
|
<Item2>
|
||||||
|
<PackageName Value="LCL"/>
|
||||||
|
</Item2>
|
||||||
</RequiredPackages>
|
</RequiredPackages>
|
||||||
<Units Count="2">
|
<Units Count="2">
|
||||||
<Unit0>
|
<Unit0>
|
||||||
|
@ -7,7 +7,7 @@ uses
|
|||||||
cthreads,
|
cthreads,
|
||||||
{$ENDIF}{$ENDIF}
|
{$ENDIF}{$ENDIF}
|
||||||
Interfaces, // this includes the LCL widgetset
|
Interfaces, // this includes the LCL widgetset
|
||||||
Forms, mainfrm
|
Forms, tachartlazaruspkg, mainfrm
|
||||||
{ you can add units after this };
|
{ you can add units after this };
|
||||||
|
|
||||||
{$R *.res}
|
{$R *.res}
|
||||||
|
@ -969,8 +969,10 @@ type
|
|||||||
FOnWriteCellData: TsWorkbookWriteCellDataEvent;
|
FOnWriteCellData: TsWorkbookWriteCellDataEvent;
|
||||||
FOnReadCellData: TsWorkbookReadCellDataEvent;
|
FOnReadCellData: TsWorkbookReadCellDataEvent;
|
||||||
FOnChangeWorksheet: TsWorksheetEvent;
|
FOnChangeWorksheet: TsWorksheetEvent;
|
||||||
|
FOnRenameWorksheet: TsWorksheetEvent;
|
||||||
FOnAddWorksheet: TsWorksheetEvent;
|
FOnAddWorksheet: TsWorksheetEvent;
|
||||||
FOnRemoveWorksheet: TsRemoveWorksheetEvent;
|
FOnRemoveWorksheet: TsRemoveWorksheetEvent;
|
||||||
|
FOnRemovingWorksheet: TsWorksheetEvent;
|
||||||
FOnSelectWorksheet: TsWorksheetEvent;
|
FOnSelectWorksheet: TsWorksheetEvent;
|
||||||
FOnChangePalette: TNotifyEvent;
|
FOnChangePalette: TNotifyEvent;
|
||||||
FFileName: String;
|
FFileName: String;
|
||||||
@ -1033,6 +1035,14 @@ type
|
|||||||
function ValidWorksheetName(var AName: String;
|
function ValidWorksheetName(var AName: String;
|
||||||
ReplaceDuplicateName: Boolean = false): Boolean;
|
ReplaceDuplicateName: Boolean = false): Boolean;
|
||||||
|
|
||||||
|
{ String-to-cell/range conversion }
|
||||||
|
function TryStrToCell(AText: String; out AWorksheet: TsWorksheet;
|
||||||
|
out ARow,ACol: Cardinal; AListSeparator: Char = #0): Boolean;
|
||||||
|
function TryStrToCellRange(AText: String; out AWorksheet: TsWorksheet;
|
||||||
|
out ARange: TsCellRange; AListSeparator: Char = #0): Boolean;
|
||||||
|
function TryStrToCellRanges(AText: String; out AWorksheet: TsWorksheet;
|
||||||
|
out ARanges: TsCellRangeArray; AListSeparator: Char = #0): Boolean;
|
||||||
|
|
||||||
{ Font handling }
|
{ Font handling }
|
||||||
function AddFont(const AFontName: String; ASize: Single;
|
function AddFont(const AFontName: String; ASize: Single;
|
||||||
AStyle: TsFontStyles; AColor: TsColor): Integer; overload;
|
AStyle: TsFontStyles; AColor: TsColor): Integer; overload;
|
||||||
@ -1093,8 +1103,12 @@ type
|
|||||||
property OnChangeWorksheet: TsWorksheetEvent read FOnChangeWorksheet write FOnChangeWorksheet;
|
property OnChangeWorksheet: TsWorksheetEvent read FOnChangeWorksheet write FOnChangeWorksheet;
|
||||||
{@@ This event fires whenever a workbook is loaded }
|
{@@ This event fires whenever a workbook is loaded }
|
||||||
property OnOpenWorkbook: TNotifyEvent read FOnOpenWorkbook write FOnOpenWorkbook;
|
property OnOpenWorkbook: TNotifyEvent read FOnOpenWorkbook write FOnOpenWorkbook;
|
||||||
{@@ This event fires when a worksheet is deleted }
|
{@@ This event fires whenever a worksheet is renamed }
|
||||||
|
property OnRenameWorksheet: TsWorksheetEvent read FOnRenameWorksheet write FOnRenameWorksheet;
|
||||||
|
{@@ This event fires AFTER a worksheet has been deleted }
|
||||||
property OnRemoveWorksheet: TsRemoveWorksheetEvent read FOnRemoveWorksheet write FOnRemoveWorksheet;
|
property OnRemoveWorksheet: TsRemoveWorksheetEvent read FOnRemoveWorksheet write FOnRemoveWorksheet;
|
||||||
|
{@@ This event fires BEFORE a worksheet is deleted }
|
||||||
|
property OnRemovingWorksheet: TsWorksheetEvent read FOnRemovingWorksheet write FOnRemovingWorksheet;
|
||||||
{@@ This event fires when a worksheet is made "active"}
|
{@@ This event fires when a worksheet is made "active"}
|
||||||
property OnSelectWorksheet: TsWorksheetEvent read FOnSelectWorksheet write FOnSelectWorksheet;
|
property OnSelectWorksheet: TsWorksheetEvent read FOnSelectWorksheet write FOnSelectWorksheet;
|
||||||
{@@ This event allows to provide external cell data for writing to file,
|
{@@ This event allows to provide external cell data for writing to file,
|
||||||
@ -3597,7 +3611,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
FName := AName;
|
FName := AName;
|
||||||
if (FWorkbook.FLockCount = 0) and Assigned(FWorkbook.FOnChangeWorksheet) then
|
if (FWorkbook.FLockCount = 0) and Assigned(FWorkbook.FOnChangeWorksheet) then
|
||||||
FWorkbook.FOnChangeWorksheet(FWorkbook, self);
|
FWorkbook.FOnRenameWorksheet(FWorkbook, self);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -7098,6 +7112,8 @@ begin
|
|||||||
i := GetWorksheetIndex(AWorksheet);
|
i := GetWorksheetIndex(AWorksheet);
|
||||||
if (i <> -1) and (AWorksheet <> nil) then
|
if (i <> -1) and (AWorksheet <> nil) then
|
||||||
begin
|
begin
|
||||||
|
if Assigned(FOnRemovingWorksheet) then
|
||||||
|
FOnRemovingWorksheet(self, AWorksheet);
|
||||||
FWorksheets.Delete(i);
|
FWorksheets.Delete(i);
|
||||||
AWorksheet.Free;
|
AWorksheet.Free;
|
||||||
if Assigned(FOnRemoveWorksheet) then
|
if Assigned(FOnRemoveWorksheet) then
|
||||||
@ -7199,6 +7215,150 @@ begin
|
|||||||
end;
|
end;
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
{ String-to-cell/range conversion }
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Analyses a string which can contain an array of cell ranges along with a
|
||||||
|
worksheet name. Extracts the worksheet (if missing the "active" worksheet of
|
||||||
|
the workbook is returned) and the cell's row and column indexes.
|
||||||
|
|
||||||
|
@param AText General cell range string in Excel notation,
|
||||||
|
i.e. worksheet name + ! + cell in A1 notation.
|
||||||
|
Example: Sheet1!A1:A10; A1:A10 or A1 are valid as well.
|
||||||
|
@param AWorksheet Pointer to the worksheet referred to by AText. If AText
|
||||||
|
does not contain the worksheet name, the active worksheet
|
||||||
|
of the workbook is returned
|
||||||
|
@param ARow, ACol Zero-based row and column index of the cell identified
|
||||||
|
by ATest. If AText contains one ore more cell ranges
|
||||||
|
then the upper left corner of the first range is returned.
|
||||||
|
@param AListSeparator Character to separate the cell blocks in the text
|
||||||
|
If #0 then the ListSeparator of the workbook's FormatSettings
|
||||||
|
is used.
|
||||||
|
@returns TRUE if AText is a valid list of cell ranges, FALSE if not. If the
|
||||||
|
result is FALSE then AWorksheet, ARow and ACol may have unpredictable
|
||||||
|
values.
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
function TsWorkbook.TryStrToCell(AText: String; out AWorksheet: TsWorksheet;
|
||||||
|
out ARow,ACol: Cardinal; AListSeparator: Char = #0): Boolean;
|
||||||
|
var
|
||||||
|
ranges: TsCellRangeArray;
|
||||||
|
begin
|
||||||
|
Result := TryStrToCellRanges(AText, AWorksheet, ranges, AListSeparator);
|
||||||
|
if Result then
|
||||||
|
begin
|
||||||
|
ARow := ranges[0].Row1;
|
||||||
|
ACol := ranges[0].Col1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Analyses a string which can contain an array of cell ranges along with a
|
||||||
|
worksheet name. Extracts the worksheet (if missing the "active" worksheet of
|
||||||
|
the workbook is returned) and the cell range (or the first cell range, if there
|
||||||
|
are several ranges).
|
||||||
|
|
||||||
|
@param AText General cell range string in Excel notation,
|
||||||
|
i.e. worksheet name + ! + cell in A1 notation.
|
||||||
|
Example: Sheet1!A1:A10; A1:A10 or A1 are valid as well.
|
||||||
|
@param AWorksheet Pointer to the worksheet referred to by AText. If AText
|
||||||
|
does not contain the worksheet name, the active worksheet
|
||||||
|
of the workbook is returned
|
||||||
|
@param ARange TsCellRange records identifying the cell block. If AText
|
||||||
|
contains several cell ranges the first one is returned.
|
||||||
|
@param AListSeparator Character to separate the cell blocks in the text
|
||||||
|
If #0 then the ListSeparator of the workbook's FormatSettings
|
||||||
|
is used.
|
||||||
|
@returns TRUE if AText is a valid cell range, FALSE if not. If the
|
||||||
|
result is FALSE then AWorksheet and ARange may have unpredictable
|
||||||
|
values.
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
function TsWorkbook.TryStrToCellRange(AText: String; out AWorksheet: TsWorksheet;
|
||||||
|
out ARange: TsCellRange; AListSeparator: Char = #0): Boolean;
|
||||||
|
var
|
||||||
|
ranges: TsCellRangeArray;
|
||||||
|
begin
|
||||||
|
Result := TryStrToCellRanges(AText, AWorksheet, ranges, AListSeparator);
|
||||||
|
if Result then ARange := ranges[0];
|
||||||
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Analyses a string which can contain an array of cell ranges along with a
|
||||||
|
worksheet name. Extracts the worksheet (if missing the "active" worksheet of
|
||||||
|
the workbook is returned) and the range array.
|
||||||
|
|
||||||
|
@param AText General cell range string in Excel notation,
|
||||||
|
i.e. worksheet name + ! + cell in A1 notation.
|
||||||
|
Example: Sheet1!A1:A10; A1:A10 or A1 are valid as well.
|
||||||
|
@param AWorksheet Pointer to the worksheet referred to by AText. If AText
|
||||||
|
does not contain the worksheet name, the active worksheet
|
||||||
|
of the workbook is returned
|
||||||
|
@param ARanges Array of TsCellRange records identifying the cell blocks
|
||||||
|
@param AListSeparator Character to separate the cell blocks in the text
|
||||||
|
If #0 then the ListSeparator of the workbook's FormatSettings
|
||||||
|
is used.
|
||||||
|
@returns TRUE if AText is a valid list of cell ranges, FALSE if not. If the
|
||||||
|
result is FALSE then AWorksheet and ARanges may have unpredictable
|
||||||
|
values.
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
function TsWorkbook.TryStrToCellRanges(AText: String; out AWorksheet: TsWorksheet;
|
||||||
|
out ARanges: TsCellRangeArray; AListSeparator: Char = #0): Boolean;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
s: String;
|
||||||
|
L: TStrings;
|
||||||
|
begin
|
||||||
|
Result := false;
|
||||||
|
AWorksheet := nil;
|
||||||
|
SetLength(ARanges, 0);
|
||||||
|
|
||||||
|
if AText = '' then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
i := pos(SHEETSEPARATOR, AText);
|
||||||
|
if i = 0 then
|
||||||
|
AWorksheet := FActiveWorksheet
|
||||||
|
else begin
|
||||||
|
AWorksheet := GetWorksheetByName(Copy(AText, 1, i-1));
|
||||||
|
if AWorksheet = nil then
|
||||||
|
exit;
|
||||||
|
AText := Copy(AText, i+1, Length(AText));
|
||||||
|
end;
|
||||||
|
|
||||||
|
L := TStringList.Create;
|
||||||
|
try
|
||||||
|
if AListSeparator = #0 then
|
||||||
|
L.Delimiter := FormatSettings.ListSeparator
|
||||||
|
else
|
||||||
|
L.Delimiter := AListSeparator;
|
||||||
|
L.StrictDelimiter := true;
|
||||||
|
L.DelimitedText := AText;
|
||||||
|
if L.Count = 0 then
|
||||||
|
begin
|
||||||
|
AWorksheet := nil;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
SetLength(ARanges, L.Count);
|
||||||
|
for i:=0 to L.Count-1 do begin
|
||||||
|
if pos(':', L[i]) = 0 then begin
|
||||||
|
Result := ParseCellString(L[i], ARanges[i].Row1, ARanges[i].Col1);
|
||||||
|
if Result then begin
|
||||||
|
ARanges[i].Row2 := ARanges[i].Row1;
|
||||||
|
ARanges[i].Col2 := ARanges[i].Col1;
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
Result := ParseCellRangeString(L[i], ARanges[i]);
|
||||||
|
if not Result then begin
|
||||||
|
SetLength(ARanges, 0);
|
||||||
|
AWorksheet := nil;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
L.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ Font handling }
|
{ Font handling }
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
{
|
{ fpspreadsheetchart.pas }
|
||||||
fpspreadsheetgrid.pas
|
|
||||||
|
|
||||||
Chart data source designed to work together with TChart from Lazarus to display the data
|
{@@ ----------------------------------------------------------------------------
|
||||||
and with TsWorksheetGrid from FPSpreadsheet to load data from a grid.
|
Chart data source designed to work together with TChart from Lazarus
|
||||||
|
to display the data and with FPSpreadsheet to load data.
|
||||||
|
|
||||||
|
AUTHORS: Felipe Monteiro de Carvalho, Werner Pamler
|
||||||
|
|
||||||
|
LICENSE: See the file COPYING.modifiedLGPL.txt, included in the Lazarus
|
||||||
|
distribution, for details about the license.
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
|
||||||
AUTHORS: Felipe Monteiro de Carvalho
|
|
||||||
}
|
|
||||||
unit fpspreadsheetchart;
|
unit fpspreadsheetchart;
|
||||||
|
|
||||||
{$mode objfpc}{$H+}
|
{$mode objfpc}{$H+}
|
||||||
@ -15,11 +19,11 @@ interface
|
|||||||
uses
|
uses
|
||||||
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
|
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
|
||||||
// TChart
|
// TChart
|
||||||
{tasources,} TACustomSource,
|
TACustomSource,
|
||||||
// FPSpreadsheet Visual
|
|
||||||
fpspreadsheetctrls, fpspreadsheetgrid,
|
|
||||||
// FPSpreadsheet
|
// FPSpreadsheet
|
||||||
fpspreadsheet, fpsutils;
|
fpspreadsheet, fpsutils,
|
||||||
|
// FPSpreadsheet Visual
|
||||||
|
fpspreadsheetctrls, fpspreadsheetgrid;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -83,8 +87,8 @@ type
|
|||||||
FWorkbookSource: TsWorkbookSource;
|
FWorkbookSource: TsWorkbookSource;
|
||||||
FWorkbook: TsWorkbook;
|
FWorkbook: TsWorkbook;
|
||||||
FWorksheets: array[TsXYRange] of TsWorksheet;
|
FWorksheets: array[TsXYRange] of TsWorksheet;
|
||||||
|
FRangeStr: array[TsXYRange] of String;
|
||||||
FRanges: array[TsXYRange] of TsCellRangeArray;
|
FRanges: array[TsXYRange] of TsCellRangeArray;
|
||||||
FDirections: array[TsXYRange] of TsSelectionDirection;
|
|
||||||
FPointsNumber: Cardinal;
|
FPointsNumber: Cardinal;
|
||||||
function GetRange(AIndex: TsXYRange): String;
|
function GetRange(AIndex: TsXYRange): String;
|
||||||
function GetWorkbook: TsWorkbook;
|
function GetWorkbook: TsWorkbook;
|
||||||
@ -94,10 +98,13 @@ type
|
|||||||
procedure SetWorkbookSource(AValue: TsWorkbookSource);
|
procedure SetWorkbookSource(AValue: TsWorkbookSource);
|
||||||
protected
|
protected
|
||||||
FCurItem: TChartDataItem;
|
FCurItem: TChartDataItem;
|
||||||
|
function BuildRangeStr(AIndex: TsXYRange; AListSeparator: char = #0): String;
|
||||||
function CountValues(AIndex: TsXYRange): Integer;
|
function CountValues(AIndex: TsXYRange): Integer;
|
||||||
function GetCount: Integer; override;
|
function GetCount: Integer; override;
|
||||||
function GetItem(AIndex: Integer): PChartDataItem; override;
|
function GetItem(AIndex: Integer): PChartDataItem; override;
|
||||||
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
||||||
|
procedure Prepare; overload;
|
||||||
|
procedure Prepare(AIndex: TsXYRange); overload;
|
||||||
procedure SetYCount(AValue: Cardinal); override;
|
procedure SetYCount(AValue: Cardinal); override;
|
||||||
public
|
public
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -270,27 +277,65 @@ end;
|
|||||||
{ TsWorkbookChartSource }
|
{ TsWorkbookChartSource }
|
||||||
{------------------------------------------------------------------------------}
|
{------------------------------------------------------------------------------}
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Destructor of the WorkbookChartSource.
|
||||||
|
Removes itself from the WorkbookSource's listener list.
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
destructor TsWorkbookChartSource.Destroy;
|
destructor TsWorkbookChartSource.Destroy;
|
||||||
begin
|
begin
|
||||||
if FWorkbookSource <> nil then FWorkbookSource.RemoveListener(self);
|
if FWorkbookSource <> nil then FWorkbookSource.RemoveListener(self);
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Constructs the range string from the stored internal information. Is needed
|
||||||
|
to have the worksheet name in the range string in order to make the range
|
||||||
|
string unique.
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
function TsWorkbookChartSource.BuildRangeStr(AIndex: TsXYRange;
|
||||||
|
AListSeparator: Char = #0): String;
|
||||||
|
var
|
||||||
|
L: TStrings;
|
||||||
|
range: TsCellRange;
|
||||||
|
begin
|
||||||
|
if (FWorkbook = nil) or (FWorksheets[AIndex] = nil) or (Length(FRanges) = 0) then
|
||||||
|
exit('');
|
||||||
|
|
||||||
|
L := TStringList.Create;
|
||||||
|
try
|
||||||
|
if AListSeparator = #0 then
|
||||||
|
L.Delimiter := FWorkbook.FormatSettings.ListSeparator
|
||||||
|
else
|
||||||
|
L.Delimiter := AListSeparator;
|
||||||
|
L.StrictDelimiter := true;
|
||||||
|
for range in FRanges[AIndex] do
|
||||||
|
L.Add(GetCellRangeString(range, rfAllRel, true));
|
||||||
|
Result := FWorksheets[AIndex].Name + SHEETSEPARATOR + L.DelimitedText;
|
||||||
|
finally
|
||||||
|
L.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Counts the number of x or y values contained in the x/y ranges
|
Counts the number of x or y values contained in the x/y ranges
|
||||||
|
|
||||||
|
@param AIndex Identifies whether values in the x or y ranges are counted.
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
function TsWorkbookChartSource.CountValues(AIndex: TsXYRange): Integer;
|
function TsWorkbookChartSource.CountValues(AIndex: TsXYRange): Integer;
|
||||||
var
|
var
|
||||||
ir: Integer;
|
ir: Integer;
|
||||||
|
range: TsCellRange;
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Result := 0;
|
||||||
case FDirections[AIndex] of
|
for range in FRanges[AIndex] do
|
||||||
fpsVerticalSelection:
|
begin
|
||||||
for ir:=0 to High(FRanges[AIndex]) do
|
if range.Col1 = range.Col2 then
|
||||||
inc(Result, FRanges[AIndex, ir].Row2 - FRanges[AIndex, ir].Row1 + 1);
|
inc(Result, range.Row2 - range.Row1 + 1)
|
||||||
fpsHorizontalSelection:
|
else
|
||||||
for ir:=0 to High(FRanges[AIndex]) do
|
if range.Row1 = range.Row2 then
|
||||||
inc(Result, FRanges[AIndex, ir].Col2 - FRanges[AIndex, ir].Col1 + 1);
|
inc(Result, range.Col2 - range.Col1 + 1)
|
||||||
|
else
|
||||||
|
raise Exception.Create('x/y ranges can only be 1 column wide or 1 row high.');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -306,6 +351,10 @@ end;
|
|||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Main ChartSource method called from the series requiring data for plotting.
|
Main ChartSource method called from the series requiring data for plotting.
|
||||||
Retrieves the data from the workbook.
|
Retrieves the data from the workbook.
|
||||||
|
|
||||||
|
@param AIndex Index of the data point in the series.
|
||||||
|
@return Pointer to a TChartDataItem record containing the x and y coordinates,
|
||||||
|
the data point mark text, and the individual data point color.
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
function TsWorkbookChartSource.GetItem(AIndex: Integer): PChartDataItem;
|
function TsWorkbookChartSource.GetItem(AIndex: Integer): PChartDataItem;
|
||||||
var
|
var
|
||||||
@ -325,25 +374,8 @@ end;
|
|||||||
by the workbook's FormatSettings.
|
by the workbook's FormatSettings.
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
function TsWorkbookChartsource.GetRange(AIndex: TsXYRange): String;
|
function TsWorkbookChartsource.GetRange(AIndex: TsXYRange): String;
|
||||||
var
|
|
||||||
L: TStrings;
|
|
||||||
ir: Integer;
|
|
||||||
begin
|
begin
|
||||||
if FWorksheets[AIndex] = nil then
|
Result := FRangeStr[AIndex];
|
||||||
begin
|
|
||||||
Result := '';
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
L := TStringList.Create;
|
|
||||||
try
|
|
||||||
L.Delimiter := Workbook.FormatSettings.ListSeparator;
|
|
||||||
for ir:=0 to High(FRanges[AIndex]) do
|
|
||||||
L.Add(GetCellRangeString(FRanges[AIndex, ir], rfAllRel, true));
|
|
||||||
Result := FWorksheets[AIndex].Name + SHEETSEPARATOR + L.DelimitedText;
|
|
||||||
finally
|
|
||||||
L.Free;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
@ -358,45 +390,59 @@ begin
|
|||||||
FWorkbook := Result;
|
FWorkbook := Result;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Helper method the prepare the information required for the series data point.
|
||||||
|
|
||||||
|
@param XOrY Identifies whether the method retrieves the x or y
|
||||||
|
coordinate.
|
||||||
|
@param APointIndex Index of the data point for which the data are required
|
||||||
|
@param ANumber (output) x or y coordinate of the data point
|
||||||
|
@param AText Data point marks label text
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsWorkbookChartSource.GetXYItem(XOrY:TsXYRange; APointIndex: Integer;
|
procedure TsWorkbookChartSource.GetXYItem(XOrY:TsXYRange; APointIndex: Integer;
|
||||||
out ANumber: Double; out AText: String);
|
out ANumber: Double; out AText: String);
|
||||||
var
|
var
|
||||||
range: TsCellRange;
|
range: TsCellRange;
|
||||||
i, j: Integer;
|
idx, ir: Integer;
|
||||||
len: Integer;
|
len: Integer;
|
||||||
row, col: Cardinal;
|
row, col: Cardinal;
|
||||||
cell: PCell;
|
cell: PCell;
|
||||||
begin
|
begin
|
||||||
cell := nil;
|
cell := nil;
|
||||||
i := 0;
|
idx := 0;
|
||||||
case FDirections[XOrY] of
|
if FRanges[XOrY] = nil then
|
||||||
fpsVerticalSelection:
|
exit;
|
||||||
for j:=0 to High(FRanges[XOrY]) do begin
|
|
||||||
range := FRanges[XOrY, j];
|
|
||||||
len := range.Row2 - range.Row1 + 1;
|
|
||||||
if (APointIndex >= i) and (APointIndex < i + len) then begin
|
|
||||||
row := range.Row1 + APointIndex - i;
|
|
||||||
col := range.Col1;
|
|
||||||
cell := FWorksheets[XOrY].FindCell(row, col);
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
inc(i, len);
|
|
||||||
end;
|
|
||||||
|
|
||||||
fpsHorizontalSelection:
|
for range in FRanges[XOrY] do
|
||||||
for j:=0 to High(FRanges[XOrY]) do begin
|
begin
|
||||||
range := FRanges[XOrY, j];
|
if (range.Col1 = range.Col2) then // vertical range
|
||||||
len := range.Col2 - range.Col1 + 1;
|
begin
|
||||||
if (APointIndex >= i) and (APointIndex < i + len) then begin
|
len := range.Row2 - range.Row1 + 1;
|
||||||
row := range.Row1;
|
if (APointIndex >= idx) and (APointIndex < idx + len) then
|
||||||
col := range.Col1 + APointIndex - i;
|
begin
|
||||||
cell := FWorksheets[XOrY].FindCell(row, col);
|
row := range.Row1 + APointIndex - idx;
|
||||||
break;
|
col := range.Col1;
|
||||||
end;
|
break;
|
||||||
inc(i, len);
|
|
||||||
end;
|
end;
|
||||||
|
inc(idx, len);
|
||||||
|
end else // horizontal range
|
||||||
|
if (range.Row1 = range.Row2) then
|
||||||
|
begin
|
||||||
|
len := range.Col2 - range.Col1 + 1;
|
||||||
|
if (APointIndex >= idx) and (APointIndex < idx + len) then
|
||||||
|
begin
|
||||||
|
row := range.Row1;
|
||||||
|
col := range.Col1 + APointIndex - idx;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
raise Exception.Create('x/y ranges can only be 1 column wide or 1 row high');
|
||||||
end;
|
end;
|
||||||
if cell = nil then begin
|
|
||||||
|
cell := FWorksheets[XOrY].FindCell(row, col);
|
||||||
|
|
||||||
|
if cell = nil then
|
||||||
|
begin
|
||||||
ANumber := NaN;
|
ANumber := NaN;
|
||||||
AText := '';
|
AText := '';
|
||||||
end else
|
end else
|
||||||
@ -417,9 +463,11 @@ end;
|
|||||||
and to worksheet changes by selecting the tab corresponding to the selected
|
and to worksheet changes by selecting the tab corresponding to the selected
|
||||||
worksheet.
|
worksheet.
|
||||||
|
|
||||||
@param AChangedItems Set with elements identifying whether workbook, worksheet
|
@param AChangedItems Set with elements identifying whether workbook,
|
||||||
cell content or cell formatting has changed
|
worksheet, cell content or cell formatting has changed
|
||||||
@param AData Additional data, not used here
|
@param AData Additional data, not used here
|
||||||
|
|
||||||
|
@see TsNotificationItem
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsWorkbookChartSource.ListenerNotification(
|
procedure TsWorkbookChartSource.ListenerNotification(
|
||||||
AChangedItems: TsNotificationItems; AData: Pointer = nil);
|
AChangedItems: TsNotificationItems; AData: Pointer = nil);
|
||||||
@ -431,9 +479,26 @@ var
|
|||||||
begin
|
begin
|
||||||
Unused(AData);
|
Unused(AData);
|
||||||
|
|
||||||
// Worksheet changes
|
// Workbook has been successfully loaded, all sheets are ready
|
||||||
if (lniWorksheet in AChangedItems) and (Workbook <> nil) then
|
if (lniWorkbook in AChangedItems) then
|
||||||
Reset;
|
Prepare;
|
||||||
|
|
||||||
|
// Used worksheet has been renamed?
|
||||||
|
if (lniWorksheetRename in AChangedItems) then
|
||||||
|
for xy in TsXYRange do
|
||||||
|
if TsWorksheet(AData) = FWorksheets[xy] then begin
|
||||||
|
FRangeStr[xy] := BuildRangeStr(xy);
|
||||||
|
Prepare(xy);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Used worksheet will be deleted?
|
||||||
|
if (lniWorksheetRemoving in AChangedItems) then
|
||||||
|
for xy in TsXYRange do
|
||||||
|
if TsWorksheet(AData) = FWorksheets[xy] then begin
|
||||||
|
FWorksheets[xy] := nil;
|
||||||
|
FRangeStr[xy] := BuildRangeStr(xy);
|
||||||
|
Prepare(xy);
|
||||||
|
end;
|
||||||
|
|
||||||
// Cell changes: Enforce recalculation of axes if modified cell is within the
|
// Cell changes: Enforce recalculation of axes if modified cell is within the
|
||||||
// x or y range(s).
|
// x or y range(s).
|
||||||
@ -457,6 +522,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Standard component notification: The ChartSource is notified that the
|
Standard component notification: The ChartSource is notified that the
|
||||||
WorkbookSource is being removed.
|
WorkbookSource is being removed.
|
||||||
@ -469,6 +535,57 @@ begin
|
|||||||
SetWorkbookSource(nil);
|
SetWorkbookSource(nil);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Parses the x and y cell range strings and extracts internal information
|
||||||
|
(worksheet used, cell range coordinates)
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsWorkbookChartSource.Prepare;
|
||||||
|
begin
|
||||||
|
Prepare(rngX);
|
||||||
|
Prepare(rngY);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Parses the range string of the data specified by AIndex and extracts internal
|
||||||
|
information (worksheet used, cell range coordinates)
|
||||||
|
|
||||||
|
@param AIndex Identifies whether x or y cell ranges are analyzed
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsWorkbookChartSource.Prepare(AIndex: TsXYRange);
|
||||||
|
const
|
||||||
|
XY: array[TsXYRange] of string = ('x', 'y');
|
||||||
|
var
|
||||||
|
range: TsCellRange;
|
||||||
|
begin
|
||||||
|
if (FWorkbook = nil) or (FRangeStr[AIndex] = '') then begin
|
||||||
|
FWorksheets[AIndex] := nil;
|
||||||
|
SetLength(FRanges[AIndex], 0);
|
||||||
|
FPointsNumber := 0;
|
||||||
|
Reset;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if FWorkbook.TryStrToCellRanges(FRangeStr[AIndex], FWorksheets[AIndex], FRanges[AIndex])
|
||||||
|
then begin
|
||||||
|
for range in FRanges[AIndex] do
|
||||||
|
if (range.Col1 <> range.Col2) and (range.Row1 <> range.Row2) then
|
||||||
|
raise Exception.Create('x/y ranges can only be 1 column wide or 1 row high');
|
||||||
|
FPointsNumber := Max(CountValues(rngX), CountValues(rngY));
|
||||||
|
// If x and y ranges are of different size empty data points will be plotted.
|
||||||
|
Reset;
|
||||||
|
// Make sure to include worksheet name in RangeString.
|
||||||
|
FRangeStr[AIndex] := BuildRangeStr(AIndex);
|
||||||
|
end else
|
||||||
|
if (FWorkbook.GetWorksheetCount > 0) then begin
|
||||||
|
if FWorksheets[AIndex] = nil then
|
||||||
|
raise Exception.CreateFmt('Worksheet of %s cell range "%s" does not exist.',
|
||||||
|
[XY[AIndex], FRangeStr[AIndex]])
|
||||||
|
else
|
||||||
|
raise Exception.CreateFmt('No valid %s cell range in "%s".',
|
||||||
|
[XY[AIndex], FRangeStr[AIndex]]);
|
||||||
|
end;
|
||||||
|
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
|
||||||
@ -491,59 +608,9 @@ end;
|
|||||||
character defined in the Workbook's FormatSettings.
|
character defined in the Workbook's FormatSettings.
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsWorkbookChartSource.SetRange(AIndex: TsXYRange; const AValue: String);
|
procedure TsWorkbookChartSource.SetRange(AIndex: TsXYRange; const AValue: String);
|
||||||
var
|
|
||||||
s: String;
|
|
||||||
p, i: Integer;
|
|
||||||
L: TStrings;
|
|
||||||
sd: TsSelectionDirection;
|
|
||||||
sd0: TsSelectionDirection;
|
|
||||||
begin
|
begin
|
||||||
if (FWorkbook = nil) then
|
FRangeStr[AIndex] := AValue;
|
||||||
exit;
|
Prepare;
|
||||||
|
|
||||||
p := pos(SHEETSEPARATOR, AValue);
|
|
||||||
if p = 0 then
|
|
||||||
begin
|
|
||||||
FWorksheets[AIndex] := FWorkbook.ActiveWorksheet;
|
|
||||||
s := AValue;
|
|
||||||
end else
|
|
||||||
begin
|
|
||||||
s := Copy(AValue, 1, p-1);
|
|
||||||
FWorksheets[AIndex] := FWorkbook.GetWorksheetByName(s);
|
|
||||||
if FWorksheets[AIndex] = nil then
|
|
||||||
raise Exception.CreateFmt('%s cell range "%s" is in a non-existing '+
|
|
||||||
'worksheet.', [''+char(ord('x')+ord(AIndex)), AValue]);
|
|
||||||
s := Copy(AValue, p+1, Length(AValue));
|
|
||||||
end;
|
|
||||||
L := TStringList.Create;
|
|
||||||
try
|
|
||||||
L.Delimiter := FWorkbook.FormatSettings.ListSeparator;
|
|
||||||
L.DelimitedText := s;
|
|
||||||
if L.Count = 0 then
|
|
||||||
raise Exception.CreateFmt('No %s cell range contained in "%s".',
|
|
||||||
[''+char(ord('x')+ord(AIndex)), AValue]
|
|
||||||
);
|
|
||||||
sd := fpsVerticalSelection;
|
|
||||||
SetLength(FRanges[AIndex], L.Count);
|
|
||||||
for i:=0 to L.Count-1 do
|
|
||||||
if ParseCellRangeString(L[i], FRanges[AIndex, i]) then begin
|
|
||||||
if FRanges[AIndex, i].Col1 = FRanges[AIndex, i].Col2 then
|
|
||||||
sd := fpsVerticalSelection
|
|
||||||
else
|
|
||||||
if FRanges[AIndex, i].Row1 = FRanges[AIndex, i].Row2 then
|
|
||||||
sd := fpsHorizontalSelection
|
|
||||||
else
|
|
||||||
raise Exception.Create('Selection can only be 1 column wide or 1 row high');
|
|
||||||
end else
|
|
||||||
raise Exception.CreateFmt('No valid %s cell range in "%s".',
|
|
||||||
[''+char(ord('x')+ord(AIndex)), L[i]]
|
|
||||||
);
|
|
||||||
FPointsNumber := Max(CountValues(rngX), CountValues(rngY));
|
|
||||||
// If x and y ranges are of different size empty data points will be plotted.
|
|
||||||
Reset;
|
|
||||||
finally
|
|
||||||
L.Free;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
@ -564,12 +631,11 @@ end;
|
|||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Inherited ChartSource method telling the series how many y values are used.
|
Inherited ChartSource method telling the series how many y values are used.
|
||||||
Currently we support only single valued data
|
Currently we support only single valued data (YCount = 1).
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsWorkbookChartSource.SetYCount(AValue: Cardinal);
|
procedure TsWorkbookChartSource.SetYCount(AValue: Cardinal);
|
||||||
begin
|
begin
|
||||||
FYCount := AValue;
|
FYCount := AValue;
|
||||||
// currently not used
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,8 +39,10 @@ type
|
|||||||
{@@ Describes during communication between WorkbookSource and visual controls
|
{@@ Describes during communication between WorkbookSource and visual controls
|
||||||
which kind of item has changed: the workbook, the worksheet, a cell value,
|
which kind of item has changed: the workbook, the worksheet, a cell value,
|
||||||
or a cell formatting, etc. }
|
or a cell formatting, etc. }
|
||||||
TsNotificationItem = (lniWorkbook, lniWorksheet, lniCell, lniSelection,
|
TsNotificationItem = (lniWorkbook,
|
||||||
lniAbortSelection, lniRow, lniPalette);
|
lniWorksheet, lniWorksheetAdd, lniWorksheetRemoving, lniWorksheetRemove,
|
||||||
|
lniWorksheetRename,
|
||||||
|
lniCell, lniSelection, lniAbortSelection, lniRow, lniPalette);
|
||||||
{@@ This set accompanies the notification between WorkbookSource and visual
|
{@@ This set accompanies the notification between WorkbookSource and visual
|
||||||
controls and describes which items have changed in the spreadsheet. }
|
controls and describes which items have changed in the spreadsheet. }
|
||||||
TsNotificationItems = set of TsNotificationItem;
|
TsNotificationItems = set of TsNotificationItem;
|
||||||
@ -81,6 +83,8 @@ type
|
|||||||
procedure WorksheetAddedHandler(Sender: TObject; ASheet: TsWorksheet);
|
procedure WorksheetAddedHandler(Sender: TObject; ASheet: TsWorksheet);
|
||||||
procedure WorksheetChangedHandler(Sender: TObject; ASheet: TsWorksheet);
|
procedure WorksheetChangedHandler(Sender: TObject; ASheet: TsWorksheet);
|
||||||
procedure WorksheetRemovedHandler(Sender: TObject; ASheetIndex: Integer);
|
procedure WorksheetRemovedHandler(Sender: TObject; ASheetIndex: Integer);
|
||||||
|
procedure WorksheetRemovingHandler(Sender: TObject; AWorksheet: TsWorksheet);
|
||||||
|
procedure WorksheetRenamedHandler(Sender: TObject; AWorksheet: TsWorksheet);
|
||||||
procedure WorksheetSelectedHandler(Sender: TObject; AWorksheet: TsWorksheet);
|
procedure WorksheetSelectedHandler(Sender: TObject; AWorksheet: TsWorksheet);
|
||||||
|
|
||||||
protected
|
protected
|
||||||
@ -772,6 +776,8 @@ begin
|
|||||||
FWorkbook.OnAddWorksheet := @WorksheetAddedHandler;
|
FWorkbook.OnAddWorksheet := @WorksheetAddedHandler;
|
||||||
FWorkbook.OnChangeWorksheet := @WorksheetChangedHandler;
|
FWorkbook.OnChangeWorksheet := @WorksheetChangedHandler;
|
||||||
FWorkbook.OnRemoveWorksheet := @WorksheetRemovedHandler;
|
FWorkbook.OnRemoveWorksheet := @WorksheetRemovedHandler;
|
||||||
|
FWorkbook.OnRemovingWorksheet := @WorksheetRemovingHandler;
|
||||||
|
FWorkbook.OnRenameWorksheet := @WorksheetRenamedHandler;
|
||||||
FWorkbook.OnSelectWorksheet := @WorksheetSelectedHandler;
|
FWorkbook.OnSelectWorksheet := @WorksheetSelectedHandler;
|
||||||
FWorkbook.OnChangePalette := @WorkbookChangedPaletteHandler;
|
FWorkbook.OnChangePalette := @WorkbookChangedPaletteHandler;
|
||||||
// Pass options to workbook
|
// Pass options to workbook
|
||||||
@ -1227,7 +1233,7 @@ procedure TsWorkbookSource.WorksheetAddedHandler(Sender: TObject;
|
|||||||
ASheet: TsWorksheet);
|
ASheet: TsWorksheet);
|
||||||
begin
|
begin
|
||||||
Unused(Sender);
|
Unused(Sender);
|
||||||
NotifyListeners([lniWorkbook]);
|
NotifyListeners([lniWorksheetAdd]);
|
||||||
SelectWorksheet(ASheet);
|
SelectWorksheet(ASheet);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1275,10 +1281,34 @@ begin
|
|||||||
end else
|
end else
|
||||||
sheet := FWorksheet;
|
sheet := FWorksheet;
|
||||||
FWorksheet := sheet; // is needed by listeners!
|
FWorksheet := sheet; // is needed by listeners!
|
||||||
NotifyListeners([lniWorkbook]);
|
NotifyListeners([lniWorksheetRemove]);
|
||||||
SelectWorksheet(sheet);
|
SelectWorksheet(sheet);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Event handler called BEFORE a worksheet is deleted.
|
||||||
|
|
||||||
|
@param Sender Workbook containing the worksheet
|
||||||
|
@param AWorksheet Worksheet which is to be deleted
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsWorkbookSource.WorksheetRemovingHandler(Sender: TObject;
|
||||||
|
AWorksheet: TsWorksheet);
|
||||||
|
begin
|
||||||
|
NotifyListeners([lniWorksheetRemoving], AWorksheet);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Event handler called after a worksheet has been renamed
|
||||||
|
|
||||||
|
@param Sender Workbook containing the worksheet
|
||||||
|
@param AWorksheet Worksheet which has been renamed
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
|
procedure TsWorkbookSource.WorksheetRenamedHandler(Sender: TObject;
|
||||||
|
AWorksheet: TsWorksheet);
|
||||||
|
begin
|
||||||
|
NotifyListeners([lniWorksheetRename], AWorksheet);
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Event handler called whenever a the workbook makes a worksheet "active".
|
Event handler called whenever a the workbook makes a worksheet "active".
|
||||||
|
|
||||||
@ -1388,16 +1418,23 @@ var
|
|||||||
begin
|
begin
|
||||||
Unused(AData);
|
Unused(AData);
|
||||||
|
|
||||||
// Workbook changed
|
// Workbook changed: new workbook, worksheet added/renamed/deleted
|
||||||
if (lniWorkbook in AChangedItems) then
|
if (AChangedItems * [lniWorkbook, lniWorksheetAdd, lniWorksheetRemove, lniWorksheetRename] <> []) then
|
||||||
begin
|
begin
|
||||||
inc(FLockCount); // avoid WorkbookSelect message when adding each tab
|
inc(FLockCount); // avoid WorkbookSelect message when adding each tab
|
||||||
GetSheetList(Tabs);
|
GetSheetList(Tabs);
|
||||||
TabIndex := Tabs.Count-1;
|
if (lniWorkbook in AChangedItems) then
|
||||||
|
TabIndex := 0
|
||||||
|
else
|
||||||
|
if (lniWorksheetAdd in AChangedItems) then
|
||||||
|
TabIndex := Tabs.Count-1
|
||||||
|
else
|
||||||
|
if (lniWorksheetRename in AChangedItems) then
|
||||||
|
TabIndex := Workbook.GetWorksheetIndex(TsWorksheet(AData));
|
||||||
dec(FLockCount);
|
dec(FLockCount);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Worksheet changed
|
// Worksheet selected
|
||||||
if (lniWorksheet in AChangedItems) and (Worksheet <> nil) then
|
if (lniWorksheet in AChangedItems) and (Worksheet <> nil) then
|
||||||
begin
|
begin
|
||||||
i := Tabs.IndexOf(Worksheet.Name);
|
i := Tabs.IndexOf(Worksheet.Name);
|
||||||
|
@ -2902,7 +2902,8 @@ end;
|
|||||||
procedure TsCustomWorksheetGrid.Loaded;
|
procedure TsCustomWorksheetGrid.Loaded;
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
NewWorkbook(FInitColCount, FInitRowCount);
|
if FWorkbookSource = nil then
|
||||||
|
NewWorkbook(FInitColCount, FInitRowCount);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user