fpspreadsheet: Prepare TsWorksheetGrid for multiselection of ranges (not activated by default, requires the patch of issue #0027000). Add information on selected cell and selected ranges to TsWorksheet (stored/restored on changes of active sheet). Some more information in TsSpreadsheetInspector.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3704 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-11-05 23:45:48 +00:00
parent 2b4925f0a8
commit 1b86c7e3dd
7 changed files with 385 additions and 120 deletions

View File

@ -28,7 +28,7 @@ object Form1: TForm1
end
object CellIndicator: TsCellIndicator
Left = 95
Height = 28
Height = 23
Top = 9
Width = 80
TabOrder = 1
@ -37,7 +37,7 @@ object Form1: TForm1
end
object CellEdit: TsCellEdit
Left = 184
Height = 28
Height = 23
Top = 9
Width = 731
Anchors = [akTop, akLeft, akRight]
@ -60,12 +60,13 @@ object Form1: TForm1
WorkbookSource = WorkbookSource
object WorksheetGrid: TsWorksheetGrid
Left = 2
Height = 528
Top = 28
Height = 533
Top = 23
Width = 668
FrozenCols = 0
FrozenRows = 0
ReadFormulas = False
TextOverflow = True
WorkbookSource = WorkbookSource
Align = alClient
AutoAdvance = aaDown
@ -127,8 +128,8 @@ object Form1: TForm1
TabOrder = 2
object Inspector: TsSpreadsheetInspector
Left = 2
Height = 528
Top = 28
Height = 533
Top = 23
Width = 244
Align = alClient
RowCount = 24
@ -136,10 +137,10 @@ object Form1: TForm1
Strings.Strings = (
'FileName='
'FileFormat=sfExcel8'
'Options='
'Options=boAutoCalc, boCalcBeforeSaving, boReadFormulas'
'FormatSettings='
' ThousandSeparator=.'
' DecimalSeparator=,'
' DecimalSeparator=.'
' ListSeparator=;'
' DateSeparator=.'
' TimeSeparator=:'
@ -165,8 +166,8 @@ object Form1: TForm1
WorkbookSource = WorkbookSource
Mode = imWorkbook
ColWidths = (
109
110
120
120
)
end
end

View File

@ -125,11 +125,11 @@ object Form1: TForm1
end
object CbLoader: TComboBox
Left = 104
Height = 28
Height = 23
Top = 8
Width = 148
ItemHeight = 20
ItemIndex = 0
ItemHeight = 15
ItemIndex = 1
Items.Strings = (
'Workbook'
'WorkbookSource'
@ -137,13 +137,13 @@ object Form1: TForm1
)
Style = csDropDownList
TabOrder = 1
Text = 'Workbook'
Text = 'WorkbookSource'
end
object Label1: TLabel
Left = 13
Height = 20
Height = 15
Top = 11
Width = 73
Width = 58
Caption = 'Loaded by:'
ParentColor = False
end

View File

@ -157,18 +157,18 @@ begin
if MessageDlg('Do you really want to delete this worksheet?', mtConfirmation,
[mbYes, mbNo], 0) = mrYes
then
WorkbookSource.Workbook.RemoveWorksheet(WorkbookSource.SelectedWorksheet);
WorkbookSource.Workbook.RemoveWorksheet(WorkbookSource.Worksheet);
end;
procedure TForm1.SpeedButton3Click(Sender: TObject);
var
s: String;
begin
s := WorkbookSource.SelectedWorksheet.Name;
s := WorkbookSource.Worksheet.Name;
if InputQuery('Edit worksheet name', 'New name', s) then
begin
if WorkbookSource.Workbook.ValidWorksheetName(s) then
WorkbookSource.SelectedWorksheet.Name := s
WorkbookSource.Worksheet.Name := s
else
MessageDlg('Invalid worksheet name.', mtError, [mbOK], 0);
end;

View File

@ -512,6 +512,7 @@ type
FRows, FCols: TIndexedAVLTree; // This lists contain only rows or cols with styles different from default
FActiveCellRow: Cardinal;
FActiveCellCol: Cardinal;
FSelection: TsCellRangeArray;
FLeftPaneWidth: Integer;
FTopPaneHeight: Integer;
FOptions: TsSheetOptions;
@ -794,8 +795,13 @@ type
ARowFrom, AColFrom, ARowTo, AColTo: Cardinal); overload;
procedure Sort(ASortParams: TsSortParams; ARange: String); overload;
// Selected cell
// Selected cell and ranges
procedure SelectCell(ARow, ACol: Cardinal);
procedure ClearSelection;
function GetSelection: TsCellRangeArray;
function GetSelectionAsString: String;
function GetSelectionCount: Integer;
procedure SetSelection(const ASelection: TsCellRangeArray);
{ Properties }
@ -907,11 +913,13 @@ type
FWriting: Boolean;
FCalculationLock: Integer;
FOptions: TsWorkbookOptions;
FActiveWorksheet: TsWorksheet;
FOnWriteCellData: TsWorkbookWriteCellDataEvent;
FOnReadCellData: TsWorkbookReadCellDataEvent;
FOnChangeWorksheet: TsWorksheetEvent;
FOnAddWorksheet: TsWorksheetEvent;
FOnRemoveWorksheet: TsRemoveWorksheetEvent;
FOnSelectWorksheet: TsWorksheetEvent;
FFileName: String;
FLog: TStringList;
@ -964,6 +972,7 @@ type
function GetWorksheetIndex(AWorksheet: TsWorksheet): Integer;
procedure RemoveAllWorksheets;
procedure RemoveWorksheet(AWorksheet: TsWorksheet);
procedure SelectWorksheet(AWorksheet: TsWorksheet);
function ValidWorksheetName(var AName: String;
ReplaceDuplicateName: Boolean = false): Boolean;
@ -1005,6 +1014,8 @@ type
procedure AddErrorMsg(const AMsg: String; const Args: array of const); overload;
procedure ClearErrorList;
{@@ Identifies the "active" worksheet (only for visual controls)}
property ActiveWorksheet: TsWorksheet read FActiveWorksheet;
{@@ This property is only used for formats which don't support unicode
and support a single encoding for the whole document, like Excel 2 to 5 }
property Encoding: TsEncoding read FEncoding write FEncoding;
@ -1023,6 +1034,8 @@ type
property OnChangeWorksheet: TsWorksheetEvent read FOnChangeWorksheet write FOnChangeWorksheet;
{@@ This event fires when a worksheet is deleted }
property OnRemoveWorksheet: TsRemoveWorksheetEvent read FOnRemoveWorksheet write FOnRemoveWorksheet;
{@@ This event fires when a worksheet is made "active"}
property OnSelectWorksheet: TsWorksheetEvent read FOnSelectWorksheet write FOnSelectWorksheet;
{@@ This event allows to provide external cell data for writing to file,
standard cells are ignored. Intended for converting large database files
to a spreadsheet format. Requires Option boVirtualMode to be set. }
@ -3532,6 +3545,70 @@ begin
end;
end;
{@@ ----------------------------------------------------------------------------
Clears the list of seleccted cell ranges
Only needed by the visual controls.
-------------------------------------------------------------------------------}
procedure TsWorksheet.ClearSelection;
begin
SetLength(FSelection, 0);
end;
{@@ ----------------------------------------------------------------------------
Returns the list of selected cell ranges
-------------------------------------------------------------------------------}
function TsWorksheet.GetSelection: TsCellRangeArray;
var
i: Integer;
begin
SetLength(Result, Length(FSelection));
for i:=0 to High(FSelection) do
Result[i] := FSelection[i];
end;
{@@ ----------------------------------------------------------------------------
Returns all selection ranges as an Excel string
-------------------------------------------------------------------------------}
function TsWorksheet.GetSelectionAsString: String;
const
RELATIVE = [rfRelRow, rfRelCol, rfRelRow2, rfRelCol2];
var
i: Integer;
L: TStringList;
begin
L := TStringList.Create;
try
for i:=0 to Length(FSelection)-1 do
with FSelection[i] do
L.Add(GetCellRangeString(Row1, Col1, Row2, Col2, RELATIVE, true));
L.Delimiter := DefaultFormatSettings.ListSeparator;
L.StrictDelimiter := true;
Result := L.DelimitedText;
finally
L.Free;
end;
end;
{@@ ----------------------------------------------------------------------------
Returns the number of selected cell ranges
-------------------------------------------------------------------------------}
function TsWorksheet.GetSelectionCount: Integer;
begin
Result := Length(FSelection);
end;
{@@ ----------------------------------------------------------------------------
Marks an array of cell ranges as "selected". Only needed for visual controls
-------------------------------------------------------------------------------}
procedure TsWorksheet.SetSelection(const ASelection: TsCellRangeArray);
var
i: Integer;
begin
SetLength(FSelection, Length(ASelection));
for i:=0 to High(FSelection) do
FSelection[i] := ASelection[i];
end;
{@@ ----------------------------------------------------------------------------
Helper method to update internal caching variables
-------------------------------------------------------------------------------}
@ -6574,6 +6651,19 @@ begin
end;
end;
{@@ ----------------------------------------------------------------------------
Makes the specified worksheet "active". Only needed for visual controls.
The active worksheet is displayed in a TsWorksheetGrid and in the selected
tab of a TsWorkbookTabControl.
-------------------------------------------------------------------------------}
procedure TsWorkbook.SelectWorksheet(AWorksheet: TsWorksheet);
begin
if (AWorksheet <> nil) and (FWorksheets.IndexOf(AWorksheet) = -1) then
raise Exception.Create('[TsWorkbook.SelectSheet] Worksheet does not belong to the workbook');
FActiveWorksheet := AWorksheet;
if Assigned(FOnSelectWorksheet) then FOnSelectWorksheet(self, AWorksheet);
end;
{@@ ----------------------------------------------------------------------------
Checks whether the passed string is a valid worksheet name according to Excel
(ODS seems to be a bit less restrictive, but if we follow Excel's convention

View File

@ -38,6 +38,7 @@ type
procedure WorksheetAddedHandler(Sender: TObject; ASheet: TsWorksheet);
procedure WorksheetChangedHandler(Sender: TObject; ASheet: TsWorksheet);
procedure WorksheetRemovedHandler(Sender: TObject; ASheetIndex: Integer);
procedure WorksheetSelectedHandler(Sender: TObject; AWorksheet: TsWorksheet);
protected
procedure DoShowError(const AErrorMsg: String);
@ -67,7 +68,7 @@ type
public
property Workbook: TsWorkbook read FWorkbook;
property SelectedWorksheet: TsWorksheet read FWorksheet;
property Worksheet: TsWorksheet read FWorksheet;
published
property AutoDetectFormat: Boolean read FAutoDetectFormat write FAutoDetectFormat;
@ -165,10 +166,10 @@ type
protected
procedure DoUpdate; virtual;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure UpdateCellValue(ACell: PCell); virtual;
procedure UpdateCellProperties(ACell: PCell); virtual;
procedure UpdateWorkbook(AWorkbook: TsWorkbook); virtual;
procedure UpdateWorksheet(ASheet: TsWorksheet); virtual;
procedure UpdateCellValue(ACell: PCell; AStrings: TStrings); virtual;
procedure UpdateCellProperties(ACell: PCell; AStrings: TStrings); virtual;
procedure UpdateWorkbook(AWorkbook: TsWorkbook; AStrings: TStrings); virtual;
procedure UpdateWorksheet(ASheet: TsWorksheet; AStrings: TStrings); virtual;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
@ -292,7 +293,7 @@ begin
FWorksheet := FWorkbook.AddWorksheet('Sheet1');
SelectWorksheet(FWorksheet);
// notify dependent controls
// notify listeners
NotifyListeners([lniWorkbook, lniWorksheet, lniSelection]);
end;
@ -318,6 +319,7 @@ begin
FWorkbook.OnAddWorksheet := @WorksheetAddedHandler;
FWorkbook.OnChangeWorksheet := @WorksheetChangedHandler;
FWorkbook.OnRemoveWorksheet := @WorksheetRemovedHandler;
FWorkbook.OnSelectWorksheet := @WorksheetSelectedHandler;
// Pass options to workbook
SetOptions(FOptions);
end;
@ -521,7 +523,7 @@ end;
-------------------------------------------------------------------------------}
procedure TsWorkbookSource.SelectCell(ASheetRow, ASheetCol: Cardinal);
begin
if SelectedWorksheet <> nil then
if FWorksheet <> nil then
FWorksheet.SelectCell(ASheetRow, ASheetCol);
NotifyListeners([lniSelection]);
end;
@ -534,6 +536,10 @@ end;
-------------------------------------------------------------------------------}
procedure TsWorkbookSource.SelectWorksheet(AWorkSheet: TsWorksheet);
begin
FWorksheet := AWorksheet;
if (FWorkbook <> nil) then
FWorkbook.SelectWorksheet(AWorksheet);
{
if AWorksheet = nil then
exit;
FWorksheet := AWorkSheet;
@ -541,6 +547,7 @@ begin
FWorksheet.OnSelectCell := @CellSelectedHandler;
NotifyListeners([lniWorksheet]);
SelectCell(FWorksheet.ActiveCellRow, FWorksheet.ActiveCellCol);
}
end;
{@@ ----------------------------------------------------------------------------
@ -633,6 +640,23 @@ begin
SelectWorksheet(sheet);
end;
{@@ ----------------------------------------------------------------------------
Event handler called whenever a the workbook makes a worksheet "active".
-------------------------------------------------------------------------------}
procedure TsWorkbookSource.WorksheetSelectedHandler(Sender: TObject;
AWorksheet: TsWorksheet);
begin
FWorksheet := AWorksheet;
if FWorksheet <> nil then
begin
FWorksheet.OnChangeCell := @CellChangedHandler;
FWorksheet.OnSelectCell := @CellSelectedHandler;
NotifyListeners([lniWorksheet]);
SelectCell(FWorksheet.ActiveCellRow, FWorksheet.ActiveCellCol);
end else
NotifyListeners([lniWorksheet]);
end;
{------------------------------------------------------------------------------}
{ TsWorkbookTabControl }
@ -663,6 +687,16 @@ end;
Creates a (string) list containing the names of the workbook's sheet names
-------------------------------------------------------------------------------}
procedure TsWorkbookTabControl.GetSheetList(AList: TStrings);
var
i: Integer;
begin
AList.Clear;
if Workbook <> nil then
for i:=0 to Workbook.GetWorksheetCount-1 do
AList.Add(Workbook.GetWorksheetByIndex(i).Name);
end;
{
procedure TsWorkbookTabControl.GetSheetList(AList: TStrings);
var
i: Integer;
oldTabIndex: Integer;
@ -680,7 +714,7 @@ begin
TabIndex := oldTabIndex;
end;
end;
}
{@@ ----------------------------------------------------------------------------
Getter method for property "Workbook"
-------------------------------------------------------------------------------}
@ -698,7 +732,7 @@ end;
function TsWorkbookTabControl.GetWorksheet: TsWorksheet;
begin
if FWorkbookSource <> nil then
Result := FWorkbookSource.SelectedWorksheet
Result := FWorkbookSource.Worksheet
else
Result := nil;
end;
@ -714,9 +748,39 @@ procedure TsWorkbookTabControl.ListenerNotification(
AChangedItems: TsNotificationItems; AData: Pointer = nil);
var
i: Integer;
oldTabIndex: Integer;
list: TStringList;
begin
Unused(AData);
// Workbook changed
if (lniWorkbook in AChangedItems) then
begin
oldTabIndex := TabIndex;
list := TStringList.Create;
Tabs.BeginUpdate;
try
GetSheetList(list);
Tabs.Assign(list);
if (oldTabIndex = -1) and (Tabs.Count > 0) then
TabIndex := 0
else
if oldTabIndex < Tabs.Count then
TabIndex := oldTabIndex;
finally
list.Free;
Tabs.EndUpdate;
end;
end;
// Worksheet changed
if (lniWorksheet in AChangedItems) and (Worksheet <> nil) then
begin
i := Tabs.IndexOf(Worksheet.Name);
if i <> TabIndex then
TabIndex := i;
end;
{
// Workbook changed
if (lniWorkbook in AChangedItems) then
GetSheetList(Tabs);
@ -728,6 +792,7 @@ begin
if i <> TabIndex then
TabIndex := i;
end;
}
end;
{@@ ----------------------------------------------------------------------------
@ -840,7 +905,7 @@ end;
function TsCellEdit.GetWorksheet: TsWorksheet;
begin
if FWorkbookSource <> nil then
Result := FWorkbookSource.SelectedWorksheet
Result := FWorkbookSource.Worksheet
else
Result := nil;
end;
@ -963,7 +1028,7 @@ end;
function TsCellIndicator.GetWorksheet: TsWorksheet;
begin
if FWorkbookSource <> nil then
Result := FWorkbookSource.SelectedWorksheet
Result := FWorkbookSource.Worksheet
else
Result := nil;
end;
@ -1038,6 +1103,38 @@ end;
setting (workbook, worksheet, cell values, cell properties).
-------------------------------------------------------------------------------}
procedure TsSpreadsheetInspector.DoUpdate;
var
cell: PCell;
sheet: TsWorksheet;
book: TsWorkbook;
list: TStringList;
begin
cell := nil;
sheet := nil;
book := nil;
if FWorkbookSource <> nil then
begin
book := FWorkbookSource.Workbook;
sheet := FWorkbookSource.Worksheet;
if sheet <> nil then
cell := sheet.FindCell(sheet.ActiveCellRow, sheet.ActiveCellCol);
end;
list := TStringList.Create;
try
case FMode of
imCellValue : UpdateCellValue(cell, list);
imCellProperties : UpdateCellProperties(cell, list);
imWorksheet : UpdateWorksheet(sheet, list);
imWorkbook : UpdateWorkbook(book, list);
end;
Strings.Assign(list);
finally
list.Free;
end;
end;
(*
procedure TsSpreadsheetInspector.DoUpdate;
var
cell: PCell;
sheet: TsWorksheet;
@ -1051,7 +1148,7 @@ begin
if FWorkbookSource <> nil then
begin
book := FWorkbookSource.Workbook;
sheet := FWorkbookSource.SelectedWorksheet;
sheet := FWorkbookSource.Worksheet;
if sheet <> nil then
cell := sheet.FindCell(sheet.ActiveCellRow, sheet.ActiveCellCol);
end;
@ -1063,6 +1160,7 @@ begin
imWorkbook : UpdateWorkbook(book);
end;
end;
*)
function TsSpreadsheetInspector.GetWorkbook: TsWorkbook;
begin
@ -1075,7 +1173,7 @@ end;
function TsSpreadsheetInspector.GetWorksheet: TsWorksheet;
begin
if FWorkbookSource <> nil then
Result := FWorkbookSource.SelectedWorksheet
Result := FWorkbookSource.Worksheet
else
Result := nil;
end;
@ -1084,6 +1182,15 @@ procedure TsSpreadsheetInspector.ListenerNotification(
AChangedItems: TsNotificationItems; AData: Pointer = nil);
begin
Unused(AData);
case FMode of
imWorkbook:
if ([lniWorkbook, lniWorksheet]*AChangedItems <> []) then DoUpdate;
imWorksheet:
if ([lniWorksheet, lniSelection]*AChangedItems <> []) then DoUpdate;
imCellValue, imCellProperties:
if ([lniCell, lniSelection]*AChangedItems <> []) then DoUpdate;
end;
{
case FMode of
imWorkbook:
if lniWorkbook in AChangedItems then DoUpdate;
@ -1093,6 +1200,7 @@ begin
imCellProperties:
if ([lniCell, lniSelection]*AChangedItems <> []) then DoUpdate;
end;
}
end;
procedure TsSpreadsheetInspector.Notification(AComponent: TComponent;
@ -1123,39 +1231,40 @@ begin
ListenerNotification([lniWorkbook, lniWorksheet, lniSelection]);
end;
procedure TsSpreadsheetInspector.UpdateCellProperties(ACell: PCell);
procedure TsSpreadsheetInspector.UpdateCellProperties(ACell: PCell;
AStrings: TStrings);
var
s: String;
cb: TsCellBorder;
r1, r2, c1, c2: Cardinal;
begin
if (ACell = nil) or not (uffFont in ACell^.UsedFormattingFields)
then Strings.Add('FontIndex=')
else Strings.Add(Format('FontIndex=%d (%s)', [
then AStrings.Add('FontIndex=')
else AStrings.Add(Format('FontIndex=%d (%s)', [
ACell^.FontIndex,
Workbook.GetFontAsString(ACell^.FontIndex)
]));
if (ACell=nil) or not (uffTextRotation in ACell^.UsedFormattingFields)
then Strings.Add('TextRotation=')
else Strings.Add(Format('TextRotation=%s', [
then AStrings.Add('TextRotation=')
else AStrings.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', [
then AStrings.Add('HorAlignment=')
else AStrings.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', [
then AStrings.Add('VertAlignment=')
else AStrings.Add(Format('VertAlignment=%s', [
GetEnumName(TypeInfo(TsVertAlignment), ord(ACell^.VertAlignment))
]));
if (ACell=nil) or not (uffBorder in ACell^.UsedFormattingFields) then
Strings.Add('Borders=')
AStrings.Add('Borders=')
else
begin
s := '';
@ -1163,84 +1272,85 @@ begin
if cb in ACell^.Border then
s := s + ', ' + GetEnumName(TypeInfo(TsCellBorder), ord(cb));
if s <> '' then Delete(s, 1, 2);
Strings.Add('Borders='+s);
AStrings.Add('Borders='+s);
end;
for cb in TsCellBorder do
if ACell = nil then
Strings.Add(Format('BorderStyles[%s]=', [
AStrings.Add(Format('BorderStyles[%s]=', [
GetEnumName(TypeInfo(TsCellBorder), ord(cb))]))
else
Strings.Add(Format('BorderStyles[%s]=%s, %s', [
AStrings.Add(Format('BorderStyles[%s]=%s, %s', [
GetEnumName(TypeInfo(TsCellBorder), ord(cb)),
GetEnumName(TypeInfo(TsLineStyle), ord(ACell^.BorderStyles[cbEast].LineStyle)),
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)', [
then AStrings.Add('BackgroundColor=')
else AStrings.Add(Format('BackgroundColor=%d (%s)', [
ACell^.BackgroundColor,
Workbook.GetColorName(ACell^.BackgroundColor)]));
if (ACell = nil) or not (uffNumberFormat in ACell^.UsedFormattingFields) then
begin
Strings.Add('NumberFormat=');
Strings.Add('NumberFormatStr=');
AStrings.Add('NumberFormat=');
AStrings.Add('NumberFormatStr=');
end else
begin
Strings.Add(Format('NumberFormat=%s', [
AStrings.Add(Format('NumberFormat=%s', [
GetEnumName(TypeInfo(TsNumberFormat), ord(ACell^.NumberFormat))]));
Strings.Add('NumberFormatStr=' + ACell^.NumberFormatStr);
AStrings.Add('NumberFormatStr=' + ACell^.NumberFormatStr);
end;
if (Worksheet = nil) or not Worksheet.IsMerged(ACell) then
Strings.Add('Merged range=')
AStrings.Add('Merged range=')
else
begin
Worksheet.FindMergedRange(ACell, r1, c1, r2, c2);
Strings.Add('Merged range=' + GetCellRangeString(r1, c1, r2, c2));
AStrings.Add('Merged range=' + GetCellRangeString(r1, c1, r2, c2));
end;
end;
procedure TsSpreadsheetInspector.UpdateCellValue(ACell: PCell);
procedure TsSpreadsheetInspector.UpdateCellValue(ACell: PCell; AStrings: TStrings);
begin
if ACell = nil then
begin
if Worksheet <> nil then
begin
Strings.Add(Format('Row=%d', [Worksheet.ActiveCellRow]));
Strings.Add(Format('Col=%d', [Worksheet.ActiveCellCol]));
AStrings.Add(Format('Row=%d', [Worksheet.ActiveCellRow]));
AStrings.Add(Format('Col=%d', [Worksheet.ActiveCellCol]));
end else
begin
Strings.Add('Row=');
Strings.Add('Col=');
AStrings.Add('Row=');
AStrings.Add('Col=');
end;
Strings.Add('ContentType=(none)');
AStrings.Add('ContentType=(none)');
end else
begin
Strings.Add(Format('Row=%d', [ACell^.Row]));
Strings.Add(Format('Col=%d', [ACell^.Col]));
Strings.Add(Format('ContentType=%s', [
AStrings.Add(Format('Row=%d', [ACell^.Row]));
AStrings.Add(Format('Col=%d', [ACell^.Col]));
AStrings.Add(Format('ContentType=%s', [
GetEnumName(TypeInfo(TCellContentType), ord(ACell^.ContentType))
]));
Strings.Add(Format('NumberValue=%g', [ACell^.NumberValue]));
Strings.Add(Format('DateTimeValue=%g', [ACell^.DateTimeValue]));
Strings.Add(Format('UTF8StringValue=%s', [ACell^.UTF8StringValue]));
Strings.Add(Format('BoolValue=%s', [BoolToStr(ACell^.BoolValue)]));
Strings.Add(Format('ErrorValue=%s', [
AStrings.Add(Format('NumberValue=%g', [ACell^.NumberValue]));
AStrings.Add(Format('DateTimeValue=%g', [ACell^.DateTimeValue]));
AStrings.Add(Format('UTF8StringValue=%s', [ACell^.UTF8StringValue]));
AStrings.Add(Format('BoolValue=%s', [BoolToStr(ACell^.BoolValue)]));
AStrings.Add(Format('ErrorValue=%s', [
GetEnumName(TypeInfo(TsErrorValue), ord(ACell^.ErrorValue))
]));
Strings.Add(Format('FormulaValue=%s', [Worksheet.ReadFormulaAsString(ACell, true)])); //^.FormulaValue]));
AStrings.Add(Format('FormulaValue=%s', [Worksheet.ReadFormulaAsString(ACell, true)])); //^.FormulaValue]));
if ACell^.SharedFormulaBase = nil then
Strings.Add('SharedFormulaBase=')
AStrings.Add('SharedFormulaBase=')
else
Strings.Add(Format('SharedFormulaBase=%s', [GetCellString(
AStrings.Add(Format('SharedFormulaBase=%s', [GetCellString(
ACell^.SharedFormulaBase^.Row, ACell^.SharedFormulaBase^.Col)
]));
end;
end;
procedure TsSpreadsheetInspector.UpdateWorkbook(AWorkbook: TsWorkbook);
procedure TsSpreadsheetInspector.UpdateWorkbook(AWorkbook: TsWorkbook;
AStrings: TStrings);
var
bo: TsWorkbookOption;
s: String;
@ -1248,75 +1358,87 @@ var
begin
if AWorkbook = nil then
begin
Strings.Add('FileName=');
Strings.Add('FileFormat=');
Strings.Add('Options=');
Strings.Add('FormatSettings=');
AStrings.Add('FileName=');
AStrings.Add('FileFormat=');
AStrings.Add('Options=');
AStrings.Add('ActiveWorksheet=');
AStrings.Add('FormatSettings=');
end else
begin
Strings.Add(Format('FileName=%s', [AWorkbook.FileName]));
Strings.Add(Format('FileFormat=%s', [
AStrings.Add(Format('FileName=%s', [AWorkbook.FileName]));
AStrings.Add(Format('FileFormat=%s', [
GetEnumName(TypeInfo(TsSpreadsheetFormat), ord(AWorkbook.FileFormat))
]));
if AWorkbook.ActiveWorksheet <> nil then
AStrings.Add('ActiveWorksheet=' + AWorkbook.ActiveWorksheet.Name)
else
AStrings.Add('ActiveWorksheet=');
s := '';
for bo in TsWorkbookOption do
if bo in AWorkbook.Options then
s := s + ', ' + GetEnumName(TypeInfo(TsWorkbookOption), ord(bo));
if s <> '' then Delete(s, 1, 2);
Strings.Add('Options='+s);
AStrings.Add('Options='+s);
Strings.Add('FormatSettings=');
Strings.Add(' ThousandSeparator='+AWorkbook.FormatSettings.ThousandSeparator);
Strings.Add(' DecimalSeparator='+AWorkbook.FormatSettings.DecimalSeparator);
Strings.Add(' ListSeparator='+AWorkbook.FormatSettings.ListSeparator);
Strings.Add(' DateSeparator='+AWorkbook.FormatSettings.DateSeparator);
Strings.Add(' TimeSeparator='+AWorkbook.FormatSettings.TimeSeparator);
Strings.Add(' ShortDateFormat='+AWorkbook.FormatSettings.ShortDateFormat);
Strings.Add(' LongDateFormat='+AWorkbook.FormatSettings.LongDateFormat);
Strings.Add(' ShortTimeFormat='+AWorkbook.FormatSettings.ShortTimeFormat);
Strings.Add(' LongTimeFormat='+AWorkbook.FormatSettings.LongTimeFormat);
Strings.Add(' TimeAMString='+AWorkbook.FormatSettings.TimeAMString);
Strings.Add(' TimePMString='+AWorkbook.FormatSettings.TimePMString);
AStrings.Add('FormatSettings=');
AStrings.Add(' ThousandSeparator='+AWorkbook.FormatSettings.ThousandSeparator);
AStrings.Add(' DecimalSeparator='+AWorkbook.FormatSettings.DecimalSeparator);
AStrings.Add(' ListSeparator='+AWorkbook.FormatSettings.ListSeparator);
AStrings.Add(' DateSeparator='+AWorkbook.FormatSettings.DateSeparator);
AStrings.Add(' TimeSeparator='+AWorkbook.FormatSettings.TimeSeparator);
AStrings.Add(' ShortDateFormat='+AWorkbook.FormatSettings.ShortDateFormat);
AStrings.Add(' LongDateFormat='+AWorkbook.FormatSettings.LongDateFormat);
AStrings.Add(' ShortTimeFormat='+AWorkbook.FormatSettings.ShortTimeFormat);
AStrings.Add(' LongTimeFormat='+AWorkbook.FormatSettings.LongTimeFormat);
AStrings.Add(' TimeAMString='+AWorkbook.FormatSettings.TimeAMString);
AStrings.Add(' TimePMString='+AWorkbook.FormatSettings.TimePMString);
s := AWorkbook.FormatSettings.ShortMonthNames[1];
for i:=2 to 12 do
s := s + ', ' + AWorkbook.FormatSettings.ShortMonthNames[i];
Strings.Add(' ShortMonthNames='+s);
AStrings.Add(' ShortMonthNames='+s);
s := AWorkbook.FormatSettings.LongMonthnames[1];
for i:=2 to 12 do
s := s +', ' + AWorkbook.FormatSettings.LongMonthNames[i];
Strings.Add(' LongMontNames='+s);
AStrings.Add(' LongMontNames='+s);
s := AWorkbook.FormatSettings.ShortDayNames[1];
for i:=2 to 7 do
s := s + ', ' + AWorkbook.FormatSettings.ShortDayNames[i];
Strings.Add(' ShortMonthNames='+s);
AStrings.Add(' ShortMonthNames='+s);
s := AWorkbook.FormatSettings.LongDayNames[1];
for i:=2 to 7 do
s := s +', ' + AWorkbook.FormatSettings.LongDayNames[i];
Strings.Add(' LongMontNames='+s);
Strings.Add(' CurrencyString='+AWorkbook.FormatSettings.CurrencyString);
Strings.Add(' PosCurrencyFormat='+IntToStr(AWorkbook.FormatSettings.CurrencyFormat));
Strings.Add(' NegCurrencyFormat='+IntToStr(AWorkbook.FormatSettings.NegCurrFormat));
Strings.Add(' TwoDigitYearCenturyWindow='+IntToStr(AWorkbook.FormatSettings.TwoDigitYearCenturyWindow));
AStrings.Add(' LongMontNames='+s);
AStrings.Add(' CurrencyString='+AWorkbook.FormatSettings.CurrencyString);
AStrings.Add(' PosCurrencyFormat='+IntToStr(AWorkbook.FormatSettings.CurrencyFormat));
AStrings.Add(' NegCurrencyFormat='+IntToStr(AWorkbook.FormatSettings.NegCurrFormat));
AStrings.Add(' TwoDigitYearCenturyWindow='+IntToStr(AWorkbook.FormatSettings.TwoDigitYearCenturyWindow));
end;
end;
procedure TsSpreadsheetInspector.UpdateWorksheet(ASheet: TsWorksheet);
procedure TsSpreadsheetInspector.UpdateWorksheet(ASheet: TsWorksheet;
AStrings: TStrings);
begin
if ASheet = nil then
begin
Strings.Add('First row=');
Strings.Add('Last row=');
Strings.Add('First column=');
Strings.Add('Last column=');
AStrings.Add('Name=');
AStrings.Add('First row=');
AStrings.Add('Last row=');
AStrings.Add('First column=');
AStrings.Add('Last column=');
AStrings.Add('Active cell=');
AStrings.Add('Selection=');
end else
begin
Strings.Add(Format('First row=%d', [Integer(ASheet.GetFirstRowIndex)]));
Strings.Add(Format('Last row=%d', [ASheet.GetLastRowIndex]));
Strings.Add(Format('First column=%d', [Integer(ASheet.GetFirstColIndex)]));
Strings.Add(Format('Last column=%d', [ASheet.GetLastColIndex]));
AStrings.Add(Format('Name=%s', [ASheet.Name]));
AStrings.Add(Format('First row=%d', [Integer(ASheet.GetFirstRowIndex)]));
AStrings.Add(Format('Last row=%d', [ASheet.GetLastRowIndex]));
AStrings.Add(Format('First column=%d', [Integer(ASheet.GetFirstColIndex)]));
AStrings.Add(Format('Last column=%d', [ASheet.GetLastColIndex]));
AStrings.Add(Format('Active cell=%s', [GetCellString(ASheet.ActiveCellRow, ASheet.ActiveCellCol)]));
AStrings.Add(Format('Selection=%s', [ASheet.GetSelectionAsString]));
end;
end;
end.

View File

@ -17,6 +17,8 @@ unit fpspreadsheetgrid;
{$mode objfpc}{$H+}
{.$DEFINE ENABLE_MULTI_SELECT} // requires Laz trunk younger than r...??? (containing grid multisel patch)
interface
uses
@ -325,6 +327,12 @@ type
by the rectangle is activated. }
property Wordwraps[ARect: TGridRect]: Boolean
read GetWordwraps write SetWordwraps;
// inherited
{$IFDEF ENABLE_MULTI_SELECT}
{@@ Allow multiple selections}
property RangeSelectMode default rsmMulti;
{$ENDIF}
end;
{ TsWorksheetGrid }
@ -760,6 +768,9 @@ begin
FInitRowCount := 100;
FCellFont := TFont.Create;
FOwnsWorkbook := true;
{$IFDEF ENABLE_MULTI_SELECT}
RangeSelectMode := rsmMulti;
{$ENDIF}
end;
{@@ ----------------------------------------------------------------------------
@ -3212,9 +3223,45 @@ end;
old thick selection border.
-------------------------------------------------------------------------------}
procedure TsCustomWorksheetGrid.MoveSelection;
var
sel: TsCellRangeArray;
{$IFDEF ENABLE_MULTI_SELECT}
i: Integer;
{$ENDIF}
begin
if (WorkbookSource <> nil) then
WorkbookSource.SelectCell(GetWorksheetRow(Row), GetWorksheetCol(Col));
if Worksheet <> nil then
begin
{$IFDEF ENABLE_MULTI_SELECT}
if HasMultiSelection then
begin
SetLength(sel, SelectedRangeCount);
for i:=0 to High(sel) do
with SelectedRange[i] do
begin
sel[i].Row1 := GetWorksheetRow(Top);
sel[i].Col1 := GetWorksheetCol(Left);
sel[i].Row2 := GetWorksheetRow(Bottom);
sel[i].Col2 := GetWorksheetCol(Right);
end;
end else
begin
SetLength(sel, 1);
sel[0].Row1 := GetWorksheetRow(Selection.Top);
sel[0].Col1 := GetWorksheetCol(Selection.Left);
sel[0].Row2 := GetWorksheetRow(Selection.Bottom);
sel[0].Col2 := GetWorksheetRow(Selection.Right);
end;
{$ELSE}
SetLength(sel, 1);
sel[0].Row1 := GetWorksheetRow(Selection.Top);
sel[0].Col1 := GetWorksheetCol(Selection.Left);
sel[0].Row2 := GetWorksheetRow(Selection.Bottom);
sel[0].Col2 := GetWorksheetRow(Selection.Right);
{$ENDIF}
Worksheet.SetSelection(sel);
Worksheet.SelectCell(GetWorksheetRow(Row), GetWorksheetCol(Col));
end;
//Refresh;
inherited;
Refresh;
@ -3743,7 +3790,7 @@ end;
function TsCustomWorksheetGrid.GetWorksheet: TsWorksheet;
begin
if FWorkbookSource <> nil then
Result := FWorkbooksource.SelectedWorksheet
Result := FWorkbooksource.Worksheet
else
Result := FOwnedWorksheet;
end;

View File

@ -83,7 +83,8 @@ function ParseCellColString(const AStr: string;
function GetColString(AColIndex: Integer): String;
function GetCellString(ARow,ACol: Cardinal; AFlags: TsRelFlags = [rfRelRow, rfRelCol]): String;
function GetCellRangeString(ARow1, ACol1, ARow2, ACol2: Cardinal;
AFlags: TsRelFlags = [rfRelRow, rfRelCol, rfRelRow2, rfRelCol2]): String;
AFlags: TsRelFlags = [rfRelRow, rfRelCol, rfRelRow2, rfRelCol2];
Compact: Boolean = false): String;
function GetErrorValueStr(AErrorValue: TsErrorValue): String;
@ -737,8 +738,12 @@ end;
--> $A1:$B3
-------------------------------------------------------------------------------}
function GetCellRangeString(ARow1, ACol1, ARow2, ACol2: Cardinal;
AFlags: TsRelFlags = [rfRelRow, rfRelCol, rfRelRow2, rfRelCol2]): String;
AFlags: TsRelFlags = [rfRelRow, rfRelCol, rfRelRow2, rfRelCol2];
Compact: Boolean = false): String;
begin
if Compact and (ARow1 = ARow2) and (ACol1 = ACol2) then
Result := GetCellString(ARow1, ACol1, AFlags)
else
Result := Format('%s%s%s%d:%s%s%s%d', [
RELCHAR[rfRelCol in AFlags], GetColString(ACol1),
RELCHAR[rfRelRow in AFlags], ARow1 + 1,