From b7361039038f923456b90e2343341811da38e361 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Mon, 20 Mar 2017 11:10:02 +0000 Subject: [PATCH] fpspreadsheet: Make WorksheetGrid respect the spSelectLockedCells and spSelectUnlockedCells flags in the worksheet's Protection set. Like in Excel, TsCellEdit displays an error message box if the user tries to focus it in case of a locked cell. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5815 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../fpspreadsheet/source/common/fpstypes.pas | 2 +- .../source/visual/fpspreadsheetctrls.pas | 36 +++++++++++++++++-- .../source/visual/fpspreadsheetgrid.pas | 27 +++++++++++++- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/components/fpspreadsheet/source/common/fpstypes.pas b/components/fpspreadsheet/source/common/fpstypes.pas index 77287f76a..5bcef293f 100644 --- a/components/fpspreadsheet/source/common/fpstypes.pas +++ b/components/fpspreadsheet/source/common/fpstypes.pas @@ -674,7 +674,7 @@ type TsCellProtection = (cpLockCell, cpHideFormulas); TsCellProtections = set of TsCellProtection; -const +const // all this actions are FORBIDDEN is included and ALLOWED of excluded! ALL_SHEET_PROTECTIONS = [spFormatCells, spFormatColumns, spFormatRows, spDeleteColumns, spDeleteRows, spInsertColumns, spInsertRows, spInsertHyperlinks, spCells, spSort, spObjects, spSelectLockedCells, spSelectUnlockedCells diff --git a/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas b/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas index 686e16742..89a87185b 100644 --- a/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas +++ b/components/fpspreadsheet/source/visual/fpspreadsheetctrls.pas @@ -241,6 +241,9 @@ type function GetWorksheet: TsWorksheet; procedure SetWorkbookSource(AValue: TsWorkbookSource); protected + function CanEditCell(ACell: PCell): Boolean; overload; + function CanEditCell(ARow, ACol: Cardinal): Boolean; overload; + procedure DoEnter; override; procedure KeyDown(var Key : Word; Shift : TShiftState); override; procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure ShowCell(ACell: PCell); virtual; @@ -1856,6 +1859,36 @@ begin inherited Destroy; end; +function TsCellEdit.CanEditCell(ACell: PCell): Boolean; +begin + if Worksheet.IsMerged(ACell) then + ACell := Worksheet.FindMergeBase(ACell); + Result := not ( + Worksheet.IsProtected and + (spCells in Worksheet.Protection) and + ((ACell = nil) or (cpLockcell in Worksheet.ReadCellProtection(ACell))) + ); +end; + +function TsCellEdit.CanEditCell(ARow, ACol: Cardinal): Boolean; +var + cell: PCell; +begin + cell := Worksheet.Findcell(Worksheet.ActiveCellRow, Worksheet.ActiveCellCol); + Result := CanEditCell(cell); +end; + +procedure TsCellEdit.DoEnter; +begin + if not CanEditCell(Worksheet.ActiveCellRow, Worksheet.ActiveCellCol) then + begin + MessageDlg('This cell is protected from editing. Unlock worksheet protection '+ + 'before continuing.', mtInformation, [mbOK], 0); + Abort; + end; + inherited; +end; + {@@ ---------------------------------------------------------------------------- EditingDone is called when the user presses the RETURN key to finish editing, or the TAB key which removes focus from the control, or clicks somewhere else @@ -2051,8 +2084,7 @@ begin FOldText := Lines.Text; - ReadOnly := Worksheet.IsProtected and (spCells in Worksheet.Protection) and - (cpLockCell in Worksheet.ReadCellProtection(ACell)); + ReadOnly := not CanEditCell(ACell); end; diff --git a/components/fpspreadsheet/source/visual/fpspreadsheetgrid.pas b/components/fpspreadsheet/source/visual/fpspreadsheetgrid.pas index dfc9ef923..08bb551a7 100644 --- a/components/fpspreadsheet/source/visual/fpspreadsheetgrid.pas +++ b/components/fpspreadsheet/source/visual/fpspreadsheetgrid.pas @@ -261,6 +261,7 @@ type procedure PrepareCanvasFont; function RelaxAutoExpand: TsAutoExpandModes; procedure RestoreAutoExpand(AValue: TsAutoExpandModes); + function SelectCell(ACol, ARow: Integer): Boolean; override; procedure SelPenChangeHandler(Sender: TObject); procedure SetEditText(ACol, ARow: Longint; const AValue: string); override; procedure Setup; @@ -4831,8 +4832,32 @@ begin GetWorkbookSource.SelectWorksheet(Workbook.GetWorksheetByIndex(AIndex)); end; +{@@ ---------------------------------------------------------------------------- + Standard method inherited from TCustomGrid. Is overridden to prevent + selection of cells in a protected worksheet. Details depend on whether + the elements spSelectLockedCells and/or spSelectUnlockedCells are included in + the worksheet's set of protections, and whether the cell to be selected is + locked or not. +-------------------------------------------------------------------------------} +function TsCustomWorksheetGrid.SelectCell(ACol, ARow: Integer): Boolean; +var + cell: PCell; + cp: TsCellprotections; +begin + Result := true; + if Worksheet.IsProtected then + begin + cell := Worksheet.FindCell(GetWorksheetRow(ARow), GetWorksheetCol(ACol)); + cp := Worksheet.ReadCellProtection(cell); + if (cpLockCell in cp) and (spSelectLockedCells in Worksheet.Protection) then + Result := false; + if not (cpLockCell in cp) and (spSelectUnlockedCells in Worksheet.Protection) then + Result := false; + end; +end; + {@@ Event handler which fires when an element of the SelectionPen changes. } -procedure TsCustomWOrksheetGrid.SelPenChangeHandler(Sender: TObject); +procedure TsCustomWorksheetGrid.SelPenChangeHandler(Sender: TObject); begin InvalidateGrid; end;