Dismissing the designer's File Menu after a custom button's action is executed

Posted by: eberridge on 17 April 2025, 12:01 pm EST

    • Post Options:
    • Link

    Posted 17 April 2025, 12:01 pm EST

    Hello, I’ve been unable to figure out how to dismiss the designer’s File Menu after executing custom code associated with a button I added to the menu. In my scenario I add a custom “Export Excel” button directly to the menu under the default “Info” list item:

    const fileMenuPanelCommandName = DesignerGC.Spread.Sheets.Designer.CommandNames.FileMenuPanel;
    
    initializeDesignerTemplates
    Gets a copy of any default templates that need to be modified, modifies them, then
    registers the updated templates.
    Currently only needs to initialize the FileMenuPanelTemplate.
    */
    export const initializeDesignerTemplates = () => {
      const fileMenu = DesignerGC.Spread.Sheets.Designer.getTemplate(
        DesignerGC.Spread.Sheets.Designer.TemplateNames.FileMenuPanelTemplate
      )!;
    
      // Mescius documentation uses square bracket notation for template modifications,
      // apparently because type coersions cause the code to get too complicated.
      // To make this more robust we introduce some TypeScript types with type guards
      // in a targeted manner.
    
      // Effective root of sidebar (left) and panels (right)
      const root = fileMenu.content[0]['children'][0]['children'] as IColumnSetOption;
    
      // 1. Modify items from the side menu
      const menuList: (IListOption | ILabelLineOption | IButtonOption)[] = root[0].children[0].children;
    
    ...
      // 1e. Add Export Excel button to the bottom
      menuList.push({
        type: 'Button',
        margin: '10px 50px',
        text: 'Export Excel',
        width: 120,
        height: 120,
        bindingPath: 'button_custom_export_excel',
        iconPosition: 'top',
        iconClass: 'icon-common icon-excel'
      } as IButtonOption);
    ...
    }
    ...
      const fileMenuCmd = DesignerGC.Spread.Sheets.Designer.getCommand(fileMenuPanelCommandName)!;
      const prevExecuteFn = fileMenuCmd.execute;
      ...
    
      fileMenuCmd.execute = (...args: [DesignerGC.Spread.Sheets.Designer.Designer, string, object]) => {
        // args is designer, propertyName, newValue
        const result = prevExecuteFn?.apply?.(fileMenuCmd, args);
        const [, propertyName] = args;
    ...
        if (propertyName === 'button_custom_export_excel') {
          handleExportExcel();
        }
        return result;
      };
    ...
      config.commandMap = {
        ...config.commandMap,
        fileMenuPanel: fileMenuCmd
      };
    
      designer.setConfig(config);
      // Export Excel handler used by the Designer File Menu
      const handleExportExcel = useCallback(() => {
        if (!designer) return;
    
        const workbook = designer.getWorkbook() as Workbook;
    
        excelIO.save(
          JSON.stringify(workbook.toJSON()),
          (blob: Blob) => {
            saveAs(blob, 'myfilename.xlsx');
          },
          ({ errorMessage }: { errorCode: ExcelIO.IO.ErrorCode; errorMessage: string }) => {
            notificationApi.error({
              message: 'Excel export error',
              description: `${errorMessage}`
            });
          }
        );
      }, [designer, excelIO, notificationApi]);

    The button works, but it leaves me in the File Menu.

    I’ve tried doing this:

    designer.activeRibbonTab("home");

    That sets the ribbon tab to “home” but doesn’t dismiss the File Menu backstage view, so I can’t even see the tabs. The user must manually click the file menu’s “back” button to return to the ribbon.

  • Posted 17 April 2025, 6:59 pm EST

    For anyone with the same question, I figured it out. All you have to do is this:

    designer.setData('FileMenu_show', false);

    In a real-world scenario, the execute command’s args include the designer instance, which can be passed to your custom code.

  • Posted 20 April 2025, 11:20 pm EST

    Hi,

    You are right that setting the value of FileMenu_show to false will dismiss the Designer’s File Menu from the UI:

    designerInstance.setData('FileMenu_show', false);

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

    Best Regards,

    Ankit

Need extra support?

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

Learn More

Forum Channels