fpspreadsheet: Initial version of searching in workbook/worksheet, not perfect yet.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4214 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
parent
42f5ce9be2
commit
ef69632cea
@ -60,7 +60,7 @@
|
||||
<PackageName Value="LCL"/>
|
||||
</Item2>
|
||||
</RequiredPackages>
|
||||
<Units Count="8">
|
||||
<Units Count="9">
|
||||
<Unit0>
|
||||
<Filename Value="demo_ctrls.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
@ -117,6 +117,14 @@
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
<UnitName Value="sNumFormatForm"/>
|
||||
</Unit7>
|
||||
<Unit8>
|
||||
<Filename Value="..\shared\ssearchform.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<ComponentName Value="SearchForm"/>
|
||||
<HasResources Value="True"/>
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
<UnitName Value="sSearchForm"/>
|
||||
</Unit8>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
@ -7,7 +7,7 @@ uses
|
||||
cthreads,
|
||||
{$ENDIF}{$ENDIF}
|
||||
Interfaces, // this includes the LCL widgetset
|
||||
Forms, main, sHyperlinkForm, sNumFormatForm;
|
||||
Forms, main, sHyperlinkForm, sNumFormatForm, sSearchForm;
|
||||
|
||||
{$R *.res}
|
||||
|
||||
|
@ -2,10 +2,10 @@ object MainForm: TMainForm
|
||||
Left = 338
|
||||
Height = 621
|
||||
Top = 118
|
||||
Width = 940
|
||||
Width = 997
|
||||
Caption = 'demo_ctrls'
|
||||
ClientHeight = 601
|
||||
ClientWidth = 940
|
||||
ClientWidth = 997
|
||||
Menu = MainMenu
|
||||
ShowHint = True
|
||||
LCLVersion = '1.5'
|
||||
@ -13,7 +13,7 @@ object MainForm: TMainForm
|
||||
Left = 0
|
||||
Height = 518
|
||||
Top = 83
|
||||
Width = 654
|
||||
Width = 711
|
||||
TabIndex = 0
|
||||
Tabs.Strings = (
|
||||
'Sheet1'
|
||||
@ -25,7 +25,7 @@ object MainForm: TMainForm
|
||||
Left = 2
|
||||
Height = 493
|
||||
Top = 23
|
||||
Width = 650
|
||||
Width = 707
|
||||
FrozenCols = 0
|
||||
FrozenRows = 0
|
||||
ReadFormulas = False
|
||||
@ -50,7 +50,7 @@ object MainForm: TMainForm
|
||||
end
|
||||
end
|
||||
object InspectorTabControl: TTabControl
|
||||
Left = 659
|
||||
Left = 716
|
||||
Height = 518
|
||||
Top = 83
|
||||
Width = 281
|
||||
@ -123,7 +123,7 @@ object MainForm: TMainForm
|
||||
end
|
||||
end
|
||||
object InspectorSplitter: TSplitter
|
||||
Left = 654
|
||||
Left = 711
|
||||
Height = 518
|
||||
Top = 83
|
||||
Width = 5
|
||||
@ -135,7 +135,7 @@ object MainForm: TMainForm
|
||||
Left = 0
|
||||
Height = 26
|
||||
Top = 24
|
||||
Width = 940
|
||||
Width = 997
|
||||
AutoSize = True
|
||||
ButtonHeight = 26
|
||||
ButtonWidth = 24
|
||||
@ -400,7 +400,7 @@ object MainForm: TMainForm
|
||||
Left = 0
|
||||
Height = 24
|
||||
Top = 0
|
||||
Width = 940
|
||||
Width = 997
|
||||
AutoSize = True
|
||||
ButtonHeight = 24
|
||||
ButtonWidth = 24
|
||||
@ -432,7 +432,7 @@ object MainForm: TMainForm
|
||||
Style = tbsDivider
|
||||
end
|
||||
object ToolButton2: TToolButton
|
||||
Left = 480
|
||||
Left = 509
|
||||
Top = 0
|
||||
Action = AcFileExit
|
||||
end
|
||||
@ -561,12 +561,25 @@ object MainForm: TMainForm
|
||||
Caption = 'ToolButton54'
|
||||
Style = tbsDivider
|
||||
end
|
||||
object ToolButton4: TToolButton
|
||||
Left = 480
|
||||
Top = 0
|
||||
Action = AcSearch
|
||||
end
|
||||
object ToolButton55: TToolButton
|
||||
Left = 504
|
||||
Height = 24
|
||||
Top = 0
|
||||
Width = 5
|
||||
Caption = 'ToolButton55'
|
||||
Style = tbsDivider
|
||||
end
|
||||
end
|
||||
object ToolBar3: TToolBar
|
||||
Left = 0
|
||||
Height = 28
|
||||
Top = 50
|
||||
Width = 940
|
||||
Width = 997
|
||||
AutoSize = True
|
||||
Caption = 'ToolBar3'
|
||||
Constraints.MinHeight = 28
|
||||
@ -597,7 +610,7 @@ object MainForm: TMainForm
|
||||
Left = 144
|
||||
Height = 24
|
||||
Top = 0
|
||||
Width = 796
|
||||
Width = 853
|
||||
Align = alClient
|
||||
BorderSpacing.Bottom = 2
|
||||
TabOrder = 1
|
||||
@ -616,7 +629,7 @@ object MainForm: TMainForm
|
||||
Left = 0
|
||||
Height = 5
|
||||
Top = 78
|
||||
Width = 940
|
||||
Width = 997
|
||||
Align = alTop
|
||||
ResizeAnchor = akTop
|
||||
end
|
||||
@ -664,6 +677,7 @@ object MainForm: TMainForm
|
||||
Caption = 'E&xit'
|
||||
Hint = 'Exit'
|
||||
ImageIndex = 0
|
||||
ShortCut = 32856
|
||||
end
|
||||
object AcFontBold: TsFontStyleAction
|
||||
Category = 'FPSpreadsheet'
|
||||
@ -1540,12 +1554,20 @@ object MainForm: TMainForm
|
||||
Hint = 'Delete hyperlink from selected cell'
|
||||
ImageIndex = 58
|
||||
end
|
||||
object AcSearch: TAction
|
||||
Category = 'Edit'
|
||||
Caption = 'Search...'
|
||||
Hint = 'Search for cells'
|
||||
ImageIndex = 70
|
||||
OnExecute = AcSearchExecute
|
||||
ShortCut = 16454
|
||||
end
|
||||
end
|
||||
object ImageList: TImageList
|
||||
left = 176
|
||||
top = 312
|
||||
Bitmap = {
|
||||
4C69460000001000000010000000003F9300003F9300003F9300003F9424003F
|
||||
4C69470000001000000010000000003F9300003F9300003F9300003F9424003F
|
||||
948A003E93CC004095CC004095CC004095CC004095CC004095CC004095CC0040
|
||||
95CC004095CC00409599003F9400003F9300003F9324003F938A0E4B9CD33F76
|
||||
C0EC5D90D4FF3365A9FFA0A0A0FFA9A9A9FFA9A9A9FFAAAAAAFFACACACFFAEAE
|
||||
@ -3785,6 +3807,38 @@ object MainForm: TMainForm
|
||||
6FFF4C9750FB529C56344E995222FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0060A664315BA25FCC569F
|
||||
5A4BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FCDEC102FADCBF97F9D9
|
||||
BBE3F6D6B8FDF4D3B4FDF1CFAFE3EECBAB97EBC6A602FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FCDEC002FADBBEC0F9E2CDFFFAEC
|
||||
DEFFF9EEE2FFF9EDE2FFF8E9DAFFF0D5BDFFE7C09FC0E3BC9A02FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FADBBD97F8E2CCFFFAEEE3FFF7E7
|
||||
D6FFF6E2CEFFF6E1CBFFF6E3D0FFF9EADDFFECCFB5FFDFB69397FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F7D7B9E3F9EBDEFFF7E7D6FFF6E1
|
||||
CCFFF5E0CAFFF5DEC8FFF5DDC5FFF6E1CBFFF5E2D0FFDBB08CE3FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F4D3B4FDF9EDE1FFF6E1CCFFF5DF
|
||||
C9FFF5DEC7FFF4DCC4FFF4DBC2FFF4DAC0FFF8E7D6FFD7AA86FDFFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F0CEAEFDF9ECDFFFF5DFC8FFF5DD
|
||||
C6FFF4DCC3FFF4DAC1FFF3D9BEFFF3D7BDFFF8E6D3FFD3A57FFDFFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00ECC8A8E3F7E7D7FFF6E1CCFFF4DB
|
||||
C2FFF4DAC0FFF3D8BDFFF3D7BBFFF4DBC2FFF3DEC9FFCD9F7BE7FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E8C3A297EDD0B7FFF8E8D9FFF5DE
|
||||
C8FFF3D8BDFFF3D6BBFFF4DBC2FFF7E4D2FFDFBB9DFF9D9492F74B84BC27FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E4BD9B02E1B896C0E8C9AEFFF5E1
|
||||
CDFFF7E5D3FFF7E5D1FFF3DDC8FFDFBA9CFFC7A891FF86AED5FF417DB5EB3977
|
||||
AF27FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00DDB28F02D9AE8A97D6A9
|
||||
85E3D3A57FFDD0A07BFDCD9C76E4A2938ADE75A2CCFFABCBE8FF76A4CEFF3070
|
||||
A8EB286BA327FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00447FB7063C79B1AD6497C5FF9DC1E4FF6699
|
||||
C7FF1F659DEBFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003272AA062B6DA5AD558DBCFF89B5
|
||||
DDFF185F97FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0022669E061B629AAD2267
|
||||
9DFF115B9387FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00145D9503105A
|
||||
921AFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00
|
||||
}
|
||||
end
|
||||
@ -4337,6 +4391,48 @@ object MainForm: TMainForm
|
||||
}
|
||||
end
|
||||
end
|
||||
object MenuItem131: TMenuItem
|
||||
Caption = '-'
|
||||
end
|
||||
object MenuItem132: TMenuItem
|
||||
Action = AcSearch
|
||||
Bitmap.Data = {
|
||||
36040000424D3604000000000000360000002800000010000000100000000100
|
||||
2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00145D9503105A921AFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF0022669E061B629AAD22679DFF115B9387FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003272
|
||||
AA062B6DA5AD558DBCFF89B5DDFF185F97FFFFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00447FB7063C79
|
||||
B1AD6497C5FF9DC1E4FF6699C7FF1F659DEBFFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00DDB28F02D9AE8A97D6A985E3D3A57FFDD0A07BFDCD9C76E4A2938ADE75A2
|
||||
CCFFABCBE8FF76A4CEFF3070A8EB286BA327FFFFFF00FFFFFF00FFFFFF00E4BD
|
||||
9B02E1B896C0E8C9AEFFF5E1CDFFF7E5D3FFF7E5D1FFF3DDC8FFDFBA9CFFC7A8
|
||||
91FF86AED5FF417DB5EB3977AF27FFFFFF00FFFFFF00FFFFFF00FFFFFF00E8C3
|
||||
A297EDD0B7FFF8E8D9FFF5DEC8FFF3D8BDFFF3D6BBFFF4DBC2FFF7E4D2FFDFBB
|
||||
9DFF9D9492F74B84BC27FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00ECC8
|
||||
A8E3F7E7D7FFF6E1CCFFF4DBC2FFF4DAC0FFF3D8BDFFF3D7BBFFF4DBC2FFF3DE
|
||||
C9FFCD9F7BE7FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F0CE
|
||||
AEFDF9ECDFFFF5DFC8FFF5DDC6FFF4DCC3FFF4DAC1FFF3D9BEFFF3D7BDFFF8E6
|
||||
D3FFD3A57FFDFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F4D3
|
||||
B4FDF9EDE1FFF6E1CCFFF5DFC9FFF5DEC7FFF4DCC4FFF4DBC2FFF4DAC0FFF8E7
|
||||
D6FFD7AA86FDFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F7D7
|
||||
B9E3F9EBDEFFF7E7D6FFF6E1CCFFF5E0CAFFF5DEC8FFF5DDC5FFF6E1CBFFF5E2
|
||||
D0FFDBB08CE3FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FADB
|
||||
BD97F8E2CCFFFAEEE3FFF7E7D6FFF6E2CEFFF6E1CBFFF6E3D0FFF9EADDFFECCF
|
||||
B5FFDFB69397FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FCDE
|
||||
C002FADBBEC0F9E2CDFFFAECDEFFF9EEE2FFF9EDE2FFF8E9DAFFF0D5BDFFE7C0
|
||||
9FC0E3BC9A02FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FCDEC102FADCBF97F9D9BBE3F6D6B8FDF4D3B4FDF1CFAFE3EECBAB97EBC6
|
||||
A602FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
|
||||
}
|
||||
end
|
||||
end
|
||||
object MnuFormat: TMenuItem
|
||||
Caption = 'Format'
|
||||
|
@ -21,6 +21,7 @@ type
|
||||
AcSettingsCSVParams: TAction;
|
||||
AcSettingsCurrency: TAction;
|
||||
AcSettingsFormatSettings: TAction;
|
||||
AcSearch: TAction;
|
||||
AcViewInspector: TAction;
|
||||
ActionList: TActionList;
|
||||
AcFileExit: TFileExit;
|
||||
@ -61,6 +62,8 @@ type
|
||||
MenuItem128: TMenuItem;
|
||||
MenuItem129: TMenuItem;
|
||||
MenuItem130: TMenuItem;
|
||||
MenuItem131: TMenuItem;
|
||||
MenuItem132: TMenuItem;
|
||||
MnuSettings: TMenuItem;
|
||||
MenuItem11: TMenuItem;
|
||||
MenuItem12: TMenuItem;
|
||||
@ -299,6 +302,7 @@ type
|
||||
ToolButton38: TToolButton;
|
||||
ToolButton39: TToolButton;
|
||||
TbCommentAdd: TToolButton;
|
||||
ToolButton4: TToolButton;
|
||||
ToolButton40: TToolButton;
|
||||
ToolButton41: TToolButton;
|
||||
ToolButton42: TToolButton;
|
||||
@ -317,6 +321,7 @@ type
|
||||
ToolButton52: TToolButton;
|
||||
ToolButton53: TToolButton;
|
||||
ToolButton54: TToolButton;
|
||||
ToolButton55: TToolButton;
|
||||
ToolButton6: TToolButton;
|
||||
ToolButton7: TToolButton;
|
||||
ToolButton8: TToolButton;
|
||||
@ -333,6 +338,7 @@ type
|
||||
AWorkbook: TsWorkbook; var ANumFormatStr: String);
|
||||
procedure AcRowAddExecute(Sender: TObject);
|
||||
procedure AcRowDeleteExecute(Sender: TObject);
|
||||
procedure AcSearchExecute(Sender: TObject);
|
||||
procedure AcSettingsCSVParamsExecute(Sender: TObject);
|
||||
procedure AcSettingsCurrencyExecute(Sender: TObject);
|
||||
procedure AcSettingsFormatSettingsExecute(Sender: TObject);
|
||||
@ -344,6 +350,7 @@ type
|
||||
const AHyperlink: TsHyperlink);
|
||||
private
|
||||
{ private declarations }
|
||||
procedure SearchFound(Sender: TObject; ACell: PCell);
|
||||
procedure UpdateCaption;
|
||||
protected
|
||||
procedure ReadFromIni;
|
||||
@ -364,7 +371,7 @@ uses
|
||||
LCLIntf, inifiles, uriparser,
|
||||
fpsUtils, fpsCSV,
|
||||
sCSVParamsForm, sCurrencyForm, sFormatSettingsForm, sSortParamsForm,
|
||||
sHyperlinkForm, sNumFormatForm;
|
||||
sHyperlinkForm, sNumFormatForm, sSearchForm;
|
||||
|
||||
function CreateIni: TCustomIniFile;
|
||||
begin
|
||||
@ -476,6 +483,14 @@ begin
|
||||
WorksheetGrid.Row := r;
|
||||
end;
|
||||
|
||||
procedure TMainForm.AcSearchExecute(Sender: TObject);
|
||||
begin
|
||||
if SearchForm = nil then
|
||||
SearchForm := TSearchForm.Create(self);
|
||||
SearchForm.OnFound := @SearchFound;
|
||||
SearchForm.Execute(WorkbookSource.Workbook, DefaultSearchParams);
|
||||
end;
|
||||
|
||||
procedure TMainForm.AcSettingsCSVParamsExecute(Sender: TObject);
|
||||
var
|
||||
F: TCSVParamsForm;
|
||||
@ -568,6 +583,22 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.SearchFound(Sender: TObject; ACell: PCell);
|
||||
begin
|
||||
// There could be status message "search string found", here
|
||||
end;
|
||||
|
||||
procedure TMainForm.UpdateCaption;
|
||||
begin
|
||||
if WorkbookSource = nil then
|
||||
Caption := 'demo_ctrls'
|
||||
else
|
||||
Caption := Format('demo_ctrls - "%s" [%s]', [
|
||||
AnsiToUTF8(WorkbookSource.Filename),
|
||||
GetFileFormatName(WorkbookSource.Workbook.FileFormat)
|
||||
]);
|
||||
end;
|
||||
|
||||
procedure TMainForm.WriteToIni;
|
||||
var
|
||||
ini: TCustomIniFile;
|
||||
@ -596,16 +627,5 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.UpdateCaption;
|
||||
begin
|
||||
if WorkbookSource = nil then
|
||||
Caption := 'demo_ctrls'
|
||||
else
|
||||
Caption := Format('demo_ctrls - "%s" [%s]', [
|
||||
AnsiToUTF8(WorkbookSource.Filename),
|
||||
GetFileFormatName(WorkbookSource.Workbook.FileFormat)
|
||||
]);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
@ -22,6 +22,7 @@ unit fpspreadsheet;
|
||||
|
||||
{$ifdef fpc}
|
||||
{$mode delphi}{$H+}
|
||||
// {$mode objpas}{$H+}
|
||||
{$endif}
|
||||
|
||||
{$include fps.inc}
|
||||
@ -389,6 +390,11 @@ type
|
||||
function GetCell(AddressStr: String): PCell; overload;
|
||||
function GetCellCount: Cardinal;
|
||||
|
||||
function FindNextCellInCol(ARow, ACol: Cardinal): PCell;
|
||||
function FindNextCellInRow(ARow, ACol: Cardinal): PCell;
|
||||
function FindPrevCellInCol(ARow, ACol: Cardinal): PCell;
|
||||
function FindPrevCellInRow(ARow, ACol: Cardinal): PCell;
|
||||
|
||||
function GetFirstColIndex(AForceCalculation: Boolean = false): Cardinal;
|
||||
function GetLastColIndex(AForceCalculation: Boolean = false): Cardinal;
|
||||
function GetLastColNumber: Cardinal; deprecated 'Use GetLastColIndex';
|
||||
@ -434,6 +440,10 @@ type
|
||||
function GetSelectionCount: Integer;
|
||||
procedure SetSelection(const ASelection: TsCellRangeArray);
|
||||
|
||||
// Searching
|
||||
function Search(ASearchText: String; AOptions: TsSearchOptions;
|
||||
AStartRow: Cardinal = $FFFFFFFF; AStartCol: Cardinal = $FFFFFFFF): PCell;
|
||||
|
||||
// Comments
|
||||
function FindComment(ACell: PCell): PsComment;
|
||||
function HasComment(ACell: PCell): Boolean;
|
||||
@ -711,6 +721,11 @@ type
|
||||
function UsesColor(AColorIndex: TsColor): Boolean;
|
||||
*)
|
||||
|
||||
{ Searching }
|
||||
function Search(ASearchText: String; AOptions: TsSearchOptions;
|
||||
AStartSheet: TsWorksheet = nil; AStartRow: Cardinal = $FFFFFFFF;
|
||||
AStartCol: Cardinal = $FFFFFFFF): PCell;
|
||||
|
||||
{ Utilities }
|
||||
procedure UpdateCaches;
|
||||
|
||||
@ -806,7 +821,7 @@ procedure CopyCellFormat(AFromCell, AToCell: PCell);
|
||||
implementation
|
||||
|
||||
uses
|
||||
Math, StrUtils, DateUtils, TypInfo, lazutf8, lazFileUtils, URIParser,
|
||||
Math, StrUtils, DateUtils, TypInfo, lazutf8, lazFileUtils, URIParser, RegExpr,
|
||||
fpsStrings, uvirtuallayer_ole,
|
||||
fpsUtils, fpsreaderwriter, fpsCurrency, fpsExprParser,
|
||||
fpsNumFormatParser;
|
||||
@ -860,8 +875,8 @@ var
|
||||
begin
|
||||
Assert(AFromCell <> nil);
|
||||
Assert(AToCell <> nil);
|
||||
sourceSheet := TsWorksheet(AFromCell.Worksheet);
|
||||
destSheet := TsWorksheet(AToCell.Worksheet);
|
||||
sourceSheet := TsWorksheet(AFromCell^.Worksheet);
|
||||
destSheet := TsWorksheet(AToCell^.Worksheet);
|
||||
if (sourceSheet=nil) or (destSheet=nil) or (sourceSheet.Workbook = destSheet.Workbook) then
|
||||
AToCell^.FormatIndex := AFromCell^.FormatIndex
|
||||
else
|
||||
@ -891,19 +906,19 @@ end;
|
||||
|
||||
function CompareCells(Item1, Item2: Pointer): Integer;
|
||||
begin
|
||||
result := LongInt(PCell(Item1).Row) - PCell(Item2).Row;
|
||||
result := LongInt(PCell(Item1)^.Row) - PCell(Item2)^.Row;
|
||||
if Result = 0 then
|
||||
Result := LongInt(PCell(Item1).Col) - PCell(Item2).Col;
|
||||
Result := LongInt(PCell(Item1)^.Col) - PCell(Item2)^.Col;
|
||||
end;
|
||||
|
||||
function CompareRows(Item1, Item2: Pointer): Integer;
|
||||
begin
|
||||
Result := LongInt(PRow(Item1).Row) - PRow(Item2).Row;
|
||||
Result := LongInt(PRow(Item1)^.Row) - PRow(Item2)^.Row;
|
||||
end;
|
||||
|
||||
function CompareCols(Item1, Item2: Pointer): Integer;
|
||||
begin
|
||||
Result := LongInt(PCol(Item1).Col) - PCol(Item2).Col;
|
||||
Result := LongInt(PCol(Item1)^.Col) - PCol(Item2)^.Col;
|
||||
end;
|
||||
|
||||
function CompareMergedCells(Item1, Item2: Pointer): Integer;
|
||||
@ -1938,6 +1953,56 @@ begin
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
function TsWorksheet.FindNextCellInCol(ARow, ACol: Cardinal): PCell;
|
||||
var
|
||||
last: Cardinal;
|
||||
begin
|
||||
last := GetLastRowIndex;
|
||||
if ARow = last then
|
||||
Result := nil
|
||||
else
|
||||
repeat
|
||||
inc(ARow);
|
||||
Result := FindCell(ARow, ACol);
|
||||
until (Result <> nil) or (ARow = last);
|
||||
end;
|
||||
|
||||
function TsWorksheet.FindNextCellInRow(ARow, ACol: Cardinal): PCell;
|
||||
var
|
||||
last: Cardinal;
|
||||
begin
|
||||
last := GetLastColIndex;
|
||||
if ACol = last then
|
||||
Result := nil
|
||||
else
|
||||
Repeat
|
||||
inc(ACol);
|
||||
Result := Findcell(ARow, ACol);
|
||||
until (Result <> nil) or (ACol = last);
|
||||
end;
|
||||
|
||||
function TsWorksheet.FindPrevCellInCol(ARow, ACol: Cardinal): PCell;
|
||||
begin
|
||||
if ARow = 0 then
|
||||
Result := nil
|
||||
else
|
||||
repeat
|
||||
dec(ARow);
|
||||
Result := FindCell(ARow, ACol);
|
||||
until (Result <> nil) or (ARow = 0);
|
||||
end;
|
||||
|
||||
function TsWorksheet.FindPrevCellInRow(ARow, ACol: Cardinal): PCell;
|
||||
begin
|
||||
if ACol = 0 then
|
||||
Result := nil
|
||||
else
|
||||
repeat
|
||||
dec(ACol);
|
||||
Result := FindCell(ARow, ACol);
|
||||
until (Result <> nil) or (ACol = 0);
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Obtains an allocated cell at the desired location.
|
||||
|
||||
@ -2732,7 +2797,7 @@ begin
|
||||
if ACell <> nil then
|
||||
begin
|
||||
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
|
||||
for b in fmt.Border do
|
||||
for b in fmt^.Border do
|
||||
Result[b] := fmt^.BorderStyles[b];
|
||||
end;
|
||||
end;
|
||||
@ -2812,7 +2877,7 @@ begin
|
||||
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
|
||||
if (uffNumberFormat in fmt^.UsedFormattingFields) then
|
||||
begin
|
||||
numFmt := Workbook.GetNumberFormat(fmt.NumberFormatIndex);
|
||||
numFmt := Workbook.GetNumberFormat(fmt^.NumberFormatIndex);
|
||||
if numFmt <> nil then
|
||||
begin
|
||||
ANumFormat := numFmt.NumFormat;
|
||||
@ -3468,6 +3533,185 @@ begin
|
||||
FSelection[i] := ASelection[i];
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Searches the cell containing a specified text. The search begins with the
|
||||
cell "AStartCell". A set of options is respected. Returns a pointer to the
|
||||
first cell meeting the criteria.
|
||||
-------------------------------------------------------------------------------}
|
||||
function TsWorksheet.Search(ASearchText: String; AOptions: TsSearchOptions;
|
||||
AStartRow: Cardinal = $FFFFFFFF; AStartCol: Cardinal = $FFFFFFFF): PCell;
|
||||
var
|
||||
regex: TRegExpr;
|
||||
cell, startCell: PCell;
|
||||
r, c: Cardinal;
|
||||
firstR, firstC, lastR, lastC: Cardinal;
|
||||
|
||||
function CellMatches(ACell: PCell): boolean;
|
||||
var
|
||||
txt: String;
|
||||
begin
|
||||
txt := ReadAsUTF8Text(ACell);
|
||||
if (soRegularExpr in AOptions) then
|
||||
Result := regex.Exec(txt)
|
||||
else
|
||||
if (soIgnoreCase in AOptions) then
|
||||
txt := UTF8Lowercase(txt);
|
||||
if (soCompareFullCell in AOptions) then
|
||||
exit(txt = ASearchText);
|
||||
if UTF8Pos(ASearchText, txt) > 0 then
|
||||
exit(true);
|
||||
Result := false;
|
||||
end;
|
||||
|
||||
begin
|
||||
Result := nil;
|
||||
regex := nil;
|
||||
firstR := 0;
|
||||
firstC := 0;
|
||||
lastR := GetLastRowIndex;
|
||||
lastC := GetLastColIndex;
|
||||
|
||||
// Find first occupied cell to start with
|
||||
if (soBackward in AOptions) then
|
||||
begin
|
||||
if AStartRow = $FFFFFFFF then AStartRow := lastR;
|
||||
if AStartCol = $FFFFFFFF then AStartCol := lastC;
|
||||
end else
|
||||
begin
|
||||
if AStartRow = $FFFFFFFF then AStartRow := firstR;
|
||||
if AStartCol = $FFFFFFFF then AStartCol := firstC;
|
||||
end;
|
||||
startcell := FindCell(AStartRow, AStartCol);
|
||||
if startcell = nil then
|
||||
// Backward search along rows
|
||||
if (AOptions * [soBackward, soAlongRows] = [soBackward, soAlongRows]) then
|
||||
begin
|
||||
startcell := FindPrevCellInRow(AStartRow, AStartCol);
|
||||
// Not found in this row? Go to previous row
|
||||
while (startcell = nil) and (AStartRow > 0) do begin
|
||||
AStartCol := lastC;
|
||||
dec(AStartRow);
|
||||
startcell := FindPrevCellInRow(AStartRow, AStartCol);
|
||||
end;
|
||||
end
|
||||
else
|
||||
// Backward search along columns
|
||||
if (AOptions * [soBackward, soAlongRows] = [soBackward]) then
|
||||
begin
|
||||
startcell := FindPrevCellInCol(AStartRow, AStartCol);
|
||||
// not found in this column? Go to previous column.
|
||||
while (startcell = nil) and (AStartcol > 0) do begin
|
||||
AStartRow := lastR;
|
||||
dec(AStartCol);
|
||||
startcell := FindPrevCellInCol(AStartRow, AStartCol);
|
||||
end;
|
||||
end
|
||||
else
|
||||
// Forward search along rows
|
||||
if (AOptions * [soBackward, soAlongRows] = [soAlongRows]) then
|
||||
begin
|
||||
startcell := FindNextCellInRow(AStartRow, AStartCol);
|
||||
// Not found in this row? Proceed to next row
|
||||
while (startcell = nil) and (AStartRow <= lastR) do begin
|
||||
AStartCol := firstC;
|
||||
inc(AStartRow);
|
||||
startcell := FindNextCellInRow(AStartRow, AStartCol);
|
||||
end;
|
||||
end
|
||||
else
|
||||
// Forward search along columns
|
||||
if (AOptions * [soBackward, soAlongRows] = []) then
|
||||
begin
|
||||
startCell := FindNextCellInCol(AStartRow, AStartCol);
|
||||
// Not found in this column? Proceed to next column
|
||||
while (startcell = nil) and (AStartCol <= lastC) do begin
|
||||
AStartRow := firstR;
|
||||
inc(AStartCol);
|
||||
startcell := FindNextCellinCol(AStartRow, AStartCol);
|
||||
end;
|
||||
end;
|
||||
|
||||
// Still no occupied cell found for starting? Nothing to do...
|
||||
if startcell = nil then
|
||||
exit;
|
||||
|
||||
// Iterate through cells in order defined by the search options
|
||||
try
|
||||
if soRegularExpr in AOptions then
|
||||
begin
|
||||
regex := TRegExpr.Create;
|
||||
regex.Expression := ASearchText
|
||||
end else
|
||||
if soIgnoreCase in AOptions then
|
||||
ASearchText := UTF8Lowercase(ASearchText);
|
||||
|
||||
// Perform backward search along rows
|
||||
if (AOptions * [soBackward, soAlongRows] = [soBackward, soAlongRows]) then
|
||||
begin
|
||||
r := startCell^.Row;
|
||||
for cell in Cells.GetReverseRowEnumerator(r, startCell^.Col) do
|
||||
if CellMatches(cell) then exit(cell);
|
||||
if r = 0 then
|
||||
exit;
|
||||
while r > 0 do begin
|
||||
dec(r);
|
||||
for cell in Cells.GetReverseRowEnumerator(r) do
|
||||
if CellMatches(cell) then exit(cell);
|
||||
end;
|
||||
end
|
||||
else
|
||||
// Perform forward search along rows
|
||||
if (AOptions * [soBackward, soAlongRows] = [soAlongRows]) then
|
||||
begin
|
||||
r := startCell^.Row;
|
||||
for cell in Cells.GetRowEnumerator(r, startCell^.Col) do
|
||||
if CellMatches(cell) then exit(cell);
|
||||
if r = lastR then
|
||||
exit;
|
||||
while (r < lastR) do
|
||||
begin
|
||||
inc(r);
|
||||
for cell in Cells.GetRowEnumerator(r) do
|
||||
if CellMatches(cell) then exit(cell);
|
||||
end;
|
||||
end
|
||||
else
|
||||
// Perform backward search along columns
|
||||
if (AOptions * [soBackward, soAlongRows] = [soBackward]) then
|
||||
begin
|
||||
c := startCell^.Col;
|
||||
for cell in Cells.GetReverseColEnumerator(c, 0, startCell^.Row) do
|
||||
if CellMatches(cell) then exit(cell);
|
||||
if c = 0 then
|
||||
exit;
|
||||
while (c > 0) do
|
||||
begin
|
||||
dec(c);
|
||||
for cell in Cells.GetReverseColEnumerator(c) do
|
||||
if CellMatches(cell) then exit(cell);
|
||||
end;
|
||||
end
|
||||
else
|
||||
// Perform forward search along columns
|
||||
if (AOptions * [soBackward, soAlongRows] = []) then
|
||||
begin
|
||||
c := startCell^.Col;
|
||||
for cell in Cells.GetColEnumerator(c, startCell^.Row) do
|
||||
if CellMatches(cell) then exit(cell);
|
||||
if c = lastC then
|
||||
exit;
|
||||
while (c < lastC) do
|
||||
begin
|
||||
inc(c);
|
||||
for cell in Cells.GetColEnumerator(c) do
|
||||
if CellMatches(cell) then exit(cell);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
if regex <> nil then regex.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Helper method to update internal caching variables
|
||||
-------------------------------------------------------------------------------}
|
||||
@ -6096,7 +6340,7 @@ end;
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsWorkbook.PrepareBeforeSaving;
|
||||
var
|
||||
sheet: TsWorksheet;
|
||||
sheet: pointer;
|
||||
begin
|
||||
// Clear error log
|
||||
FLog.Clear;
|
||||
@ -6107,7 +6351,7 @@ begin
|
||||
// Calculated formulas (if requested)
|
||||
if (boCalcBeforeSaving in FOptions) then
|
||||
for sheet in FWorksheets do
|
||||
sheet.CalcFormulas;
|
||||
TsWorksheet(sheet).CalcFormulas;
|
||||
|
||||
// Abort if virtual mode is active without an event handler
|
||||
if (boVirtualMode in FOptions) and not Assigned(FOnWriteCellData) then
|
||||
@ -6119,10 +6363,10 @@ end;
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsWorkbook.Recalc;
|
||||
var
|
||||
sheet: TsWorksheet;
|
||||
sheet: pointer;
|
||||
begin
|
||||
for sheet in FWorksheets do
|
||||
sheet.CalcFormulas;
|
||||
TsWorksheet(sheet).CalcFormulas;
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
@ -6134,6 +6378,65 @@ begin
|
||||
TsWorksheet(data).Free;
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Searches the entire workbook for the first cell (after AStartCell) containing
|
||||
a specified text.
|
||||
-------------------------------------------------------------------------------}
|
||||
function TsWorkbook.Search(ASearchText: String; AOptions: TsSearchOptions;
|
||||
AStartSheet: TsWorksheet = nil; AStartRow: Cardinal = $FFFFFFFF;
|
||||
AStartCol: Cardinal = $FFFFFFFF): PCell;
|
||||
var
|
||||
i, idxSheet: Integer;
|
||||
sheet: TsWorksheet;
|
||||
begin
|
||||
// Setup missing default parameters
|
||||
if soBackward in AOptions then
|
||||
begin
|
||||
if (AStartRow = $FFFFFFFF) and (AStartCol = $FFFFFFFF) and (AStartSheet = nil)
|
||||
then AStartsheet := GetWorksheetByIndex(GetWorksheetCount-1);
|
||||
if AStartRow = $FFFFFFFF then
|
||||
AStartRow := AStartsheet.GetLastRowIndex;
|
||||
if AStartCol = $FFFFFFFF then
|
||||
AStartCol := AStartsheet.GetLastColIndex;
|
||||
end else
|
||||
begin
|
||||
if (AStartRow = $FFFFFFFF) and (AStartCol = $FFFFFFFF) and (AStartSheet = nil)
|
||||
then AStartsheet := GetWorksheetByIndex(0);
|
||||
if (AStartRow = $FFFFFFFF) then
|
||||
AStartRow := AStartsheet.GetFirstRowIndex;
|
||||
if (AStartCol = $FFFFFFFF) then
|
||||
AStartCol := AStartsheet.GetFirstColIndex;
|
||||
end;
|
||||
if AStartSheet = nil then
|
||||
AStartSheet := ActiveWorksheet;
|
||||
|
||||
// Search this worksheet
|
||||
Result := AStartSheet.Search(ASearchText, AOptions, AStartRow, AStartCol);
|
||||
if Result <> nil then
|
||||
exit;
|
||||
|
||||
// If not found continue with other sheets in requested order...
|
||||
idxSheet := GetWorksheetIndex(AStartSheet);
|
||||
if (soBackward in AOptions) then
|
||||
// ... backward
|
||||
for i := idxSheet - 1 downto 0 do
|
||||
begin
|
||||
sheet := GetWorksheetByIndex(i);
|
||||
Result := sheet.Search(ASearchText, AOptions);
|
||||
if Result <> nil then
|
||||
exit;
|
||||
end
|
||||
else
|
||||
// ... forward
|
||||
for i := idxSheet + 1 to GetWorksheetCount-1 do
|
||||
begin
|
||||
sheet := GetWorksheetByIndex(i);
|
||||
Result := sheet.Search(ASearchText, AOptions);
|
||||
if Result <> nil then
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Helper method to update internal caching variables
|
||||
-------------------------------------------------------------------------------}
|
||||
|
@ -676,6 +676,12 @@ type
|
||||
{@@ Pointer to a page layout record }
|
||||
PsPageLayout = ^TsPageLayout;
|
||||
|
||||
{@@ Search option }
|
||||
TsSearchOption = (soCompareFullCell, soIgnoreCase, soRegularExpr,
|
||||
soBackward, soAlongRows);
|
||||
TsSearchOptions = set of TsSearchOption;
|
||||
|
||||
|
||||
const
|
||||
{@@ Indexes to be used for the various headers and footers }
|
||||
HEADER_FOOTER_INDEX_FIRST = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user