Customising the error shown for protected sheets

Posted by: srinivas.suravarapu on 15 April 2025, 4:57 am EST

    • Post Options:
    • Link

    Posted 15 April 2025, 4:57 am EST

    Is there someway we can override or customise the message shown when a user tries to edit a protected sheet

    The alert shown is “The cell or chart you’re trying to change is on a protected sheet. To make a change, unprotect the sheet.”,

    We want to show our own message for this

  • Posted 15 April 2025, 6:28 am EST

    Hi,

    As I understand, you want to display a custom alert message when a user tries to edit a cell in a protected sheet.

    This can be done using the InvalidOperation event. In the event handler, check if the invalidType is GC.Spread.Sheets.InvalidOperationType.editProtected and then set your custom message. Refer to the below snippet and sample: https://jscodemine.mescius.io/share/r_xHTX2SR0WFV04zjCQtjw/?defaultOpen={"OpenedFileName"%3A["%2Findex.html"%2C"%2Fpackage.json"%2C"%2Fsrc%2Fdata.js"%2C"%2Fsrc%2Fapp.js"]%2C"ActiveFile"%3A"%2Fsrc%2Fapp.js"}

    spread.bind(GC.Spread.Sheets.Events.InvalidOperation, (e, args) => {
        if (args.invalidType === GC.Spread.Sheets.InvalidOperationType.editProtected) {
            args.message = "Custom message!!";
        }
    });

    References:

    Regards,

    Priyam

  • Posted 16 April 2025, 12:13 am EST

    Worked well , thank you

  • Posted 16 April 2025, 4:20 am EST

    I just noticed when the sheet is protected and someone does

    1. ‘Clear’ from the editing menu the default message shows up, i thought i might step into this method you have the handler for but seems like the event that gets hit is different
    2. The other situation is when a user uses the find and replace option on a protected sheet, may be there is way of disabling the find and replace option ?
  • Posted 16 April 2025, 7:46 am EST - Updated 16 April 2025, 7:51 am EST

    Hi,

    It is possible to control the Find and Replace Dialog pop-up based on the sheet protection. Please refer to the attached sample that illustrates the same (see below).

    Additionally, could you please explain how you are using the “Clear” from the context menu on a protected sheet? On our end, the option is disabled. Please refer to the attached recording.

    Sample: https://jscodemine.mescius.io/share/QNLHU1KIpUyWc22j8jgKow/?defaultOpen={"OpenedFileName"%3A["%2Findex.html"%2C"%2Fsrc%2Fapp.js"]%2C"ActiveFile"%3A"%2Fsrc%2Fapp.js"}

    Regards,

    Ankit

  • Posted 16 April 2025, 8:12 am EST - Updated 16 April 2025, 8:17 am EST

    See attached screnshot which shows the clear option I clicked and the error i am seeing , hopefully this helps

  • Posted 16 April 2025, 8:28 am EST

    While the find and replace dialog solution works in preventing the dialog, we just realised this means users who can view the sheets (but not change it) will not be able to use the find text option which is quite important when they load up large sheets. Are you able to suggest if I can may be intercept the replace operation / hide the replace tab in the dialog

  • Posted 17 April 2025, 3:00 am EST - Updated 17 April 2025, 3:05 am EST

    Hi,

    Thanks for sharing the additional details. We can replicate the behavior you mentioned on our end. However, the error message displayed while performing a clear operation from the Editing menu can be customized by customizing the designer resources. Please refer to the code snippet below that illustrates the same:

    let customProtectionErrorMessage = "Custom Message!!";
    var resources = GC.Spread.Sheets.Designer.getResources();
    resources["protectionOptionDialog"]["errorMessage"] = customProtectionErrorMessage;
    GC.Spread.Sheets.Designer.setResources(resources);

    Additionally, it is possible to display only the Find dialog when the sheet is protected and the Find & Replace dialog when it is in an unprotected state. Please refer to the code snippet below that illustrates the same:

    const findDialogCommand = GC.Spread.Sheets.Designer.getCommand(GC.Spread.Sheets.Designer.CommandNames.FindDialogFind);
    var findDialogTemplate = GC.Spread.Sheets.Designer.getTemplate(GC.Spread.Sheets.Designer.TemplateNames.FindDialogTemplate);
    const onlyFindTemplate = {
      ...findDialogTemplate,
      content: [...findDialogTemplate.content],
      buttons: [...findDialogTemplate.buttons],
    };
    onlyFindTemplate.content[0] = {
      ...findDialogTemplate.content[0],
      children: [...findDialogTemplate.content[0].children],
    };
    onlyFindTemplate.content[0].children.splice(1, 1);
    onlyFindTemplate.buttons.splice(0, 2);
    onlyFindTemplate.title = "Find";
    function executeFindDialogCommand() {
        if(spread.getActiveSheet().options.isProtected) {
          GC.Spread.Sheets.Designer.registerTemplate(GC.Spread.Sheets.Designer.TemplateNames.FindDialogTemplate, onlyFindTemplate);
        }
        else {
          GC.Spread.Sheets.Designer.registerTemplate(GC.Spread.Sheets.Designer.TemplateNames.FindDialogTemplate, findDialogTemplate);
        }
        findDialogCommand.execute(designer);
    }
    document.addEventListener("keydown", function (event) {
      if (event.ctrlKey && event.key.toLowerCase() === "f") {
        event.preventDefault();
        executeFindDialogCommand();
      }
    });

    You can further refer to the attached sample: https://jscodemine.mescius.io/share/QNLHU1KIpUyWc22j8jgKow/?defaultOpen={"OpenedFileName"%3A["%2Findex.html"%2C"%2Fsrc%2Fdata.js"%2C"%2Fsrc%2Fapp.js"]%2C"ActiveFile"%3A"%2Fsrc%2Fapp.js"}, which uses the above code snippets and achieves the required results (see below).

    GIF:

    Please feel free to reach out if you require additional guidance.

    Best Regards

  • Posted 18 April 2025, 2:02 am EST

    The solution to customise the error message worked for us. On the code to disable replace option we came up with something like this

    const findAndReplaceDialogTemplate = GC.Spread.Sheets.Designer.getTemplate(GC.Spread.Sheets.Designer.TemplateNames.FindDialogTemplate);
    const onlyFindDialog = GC.Spread.Sheets.Designer.getTemplate(GC.Spread.Sheets.Designer.TemplateNames.FindDialogTemplate);
    const onlyFindTemplate = {
        content: [...onlyFindDialog.content],
        buttons: [...onlyFindDialog.buttons],
    };
    onlyFindTemplate.content[0].children.splice(1, 1);
    onlyFindTemplate.buttons.splice(0, 2);
    onlyFindTemplate.title = "Find";
    
    const disableReplace =  function() {
        GC.Spread.Sheets.Designer.registerTemplate(GC.Spread.Sheets.Designer.TemplateNames.FindDialogTemplate, onlyFindTemplate);
    }
    
    const enableReplace = function() {
        GC.Spread.Sheets.Designer.registerTemplate(GC.Spread.Sheets.Designer.TemplateNames.FindDialogTemplate, findAndReplaceDialogTemplate);
    }

    Can you tell us if you see any potential issues with it, we call the disableReplace if we have sheets protected and enabeReplace if the sheets are not protected.

  • Posted 21 April 2025, 2:25 am EST

    Hi,

    Apologies for the delay caused over the weekend.

    We cannot find any potential issues with the code you provided. We have included this code in our sample, and everything works as expected. Please refer to the attached code sample (see below).

    Please feel free to reach out if you encounter any further issues or require additional guidance.

    Custom Error Message And FR Dialog Handler : https://jscodemine.mescius.io/share/QNLHU1KIpUyWc22j8jgKow/?defaultOpen={"OpenedFileName"%3A["%2Findex.html"%2C"%2Fsrc%2Fapp.js"]%2C"ActiveFile"%3A"%2Fsrc%2Fapp.js"}

    Best Regards,

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels