How to apply a GoogleSheet Filterview via Google Apps Script?

拥有回忆 提交于 2020-01-06 03:35:14

问题


I have created some Google Apps Script code which creates GSheets FilterViews. I cannot see how to apply a specific FilterViews (not Filters) to the current sheet.

The code i have sets FilterSettings and then applies it to a basic filter but i cannot see in the documentation how to apply a similar approach to filterview.

if (condition!=0 && hiddenValues.length>0)
  {
    filterSettings['criteria'][COLUMNS.ASSIGNEE.pos] = {
      'hiddenValues': hiddenValues,
      'condition': condition
    };    
  }
  else if(hiddenValues.length>0)
  {
    filterSettings['criteria'][COLUMNS.ASSIGNEE.pos] = {
      'hiddenValues': hiddenValues,
    };    
  }
  else if(condition!=0)
  {
    filterSettings['criteria'][COLUMNS.ASSIGNEE.pos] = {
      'condition': condition
    };    
  }

  // Using BASIC FILTER not FILTER VIEW   
  var request = {
    "setBasicFilter": {
      "filter": filterSettings
    }
  }

Sheets.Spreadsheets.batchUpdate({'requests': [request]}, ss.getId());

Have looked at this doc:-

https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/sheets#FilterView https://developers.google.com/sheets/api/reference/rest/v4/FilterCriteria https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/other#ConditionType https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/other#ConditionValue

I can see that historically its not been supported but I wonder if that is still the case.

I can see if i look at the requests API there are request types for:-

  • addFilterView
  • deleteFilterView
  • updateFilterView
  • duplicateFilterView

There is no SetFilterView.

What is the right way to activate a filter view via GAS.

Thanks


回答1:


Issue:

  • FilterView could not be set from apps script

Workaround:

In this workaround, The main con is that, You'd need to open the Google sheets through a url and that url tab/window will run in the background. You can also easily do this with plain =HYPERLINK() formulas using the same logic without any apps script.

  • FilterViews has the following url hash appended to sheets edit url:
    gid=SHEET_ID&fvid=FILTERVIEW_ID
  • Publish a web app(HookService) for the explicit purpose of opening Google sheets url.
  • Using the web-app, It is possible to change Google sheets url.
  • Sidebar can be opened in Google sheets with filterview buttons
  • Sidebar will then connect to the web-app(through window.postMessage) and command it to change Google sheets url. This is needed because sidebar cannot directly change the Google sheets url, but a web-app can.

Sample script:

WebApp: hookService.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title></title>
  </head>
  <body>
    <h1><span>Starting</span> HookService on Google sheets....</h1>
    <div id="main">
      <p>This is needed to set filter views</p>
      <p>Kindly allow pop ups to continue....</p>
      <label
        >Your Google sheets ID:<input
          id="sheets"
          type="text"
          value="<?=id?>"
          autocomplete/></label
      ><br />
      <label>Sidebar Origin:<input id="origin" type="url" autocomplete/></label
      ><br />
      <button>START HOOK</button>
    </div>
    <script>
      var win1, win1url;
      let [div, input, origin, button] = [
        ...document.querySelectorAll('div,input,button'),
      ];
      origin.value = window.location.origin;
      function openSheets() {
        win1 = window.open(
          (win1url =
            'https://docs.google.com/spreadsheets/d/' + input.value + '/edit'),
          '_blank'
        );
        if (win1) {
          document.querySelector('span').textContent = 'Running';
          window.addEventListener('message', receiveMessage, false);
          div.innerHTML = 'Close this window to stop Hook Service';
        } else {
          alert('Pop up blockers must be disabled on this site to run hook');
        }
      }
      openSheets();
      button.addEventListener('click', openSheets);
      function receiveMessage(event) {
        //[SECURITY] Check event origin
        if (event.origin !== origin.value) {
          console.error('origin disallowed');
          alert('Origin not allowed');
          return;
        }
        win1.location.replace(win1url + event.data);
      }
    </script>
  </body>
</html>

SideBar: hookSubService.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title></title>
    <style>
      div {
        display: flex;
        flex-direction: column;
      }
    </style>
  </head>
  <body>
    <div>
      <button id="1">FILTER VIEW 1</button>
      <button id="2">FILTER VIEW 2</button>
    </div>
    <script>
      const win0 = window.top.opener;
      if (!win0) {
        alert('Hook service not found! Exiting...');
        google.script.host.close();
      }
      /************TODO: Set sheet ids and filterview ids************/
      const gids = ['Sheetid for filter view1', 'Sheetid for filterview2'];
      const fvids = ['filterviewid1', 'filterviewid2'];

      let div = document.querySelector('div');
      div.addEventListener('click', e => {
        let id = Number(e.target.id) - 1;
        let [gid, fvid] = [gids[id], fvids[id]];
        let message = '#gid=' + gid + '&fvid=' + fvid;

        //TODO:[SECURTY] Provide webapp origin url instead
        win0.postMessage(message, window.location.origin);
      });
    </script>
  </body>
</html>

Server side code:code.gs

function doGet(e){
var page=e.parameter.page
var out = HtmlService.createTemplateFromFile(page || 'hookService');
  out.id = SpreadsheetApp.getActive().getId();
  return out.evaluate().addMetaTag('viewport', 'width=device-width, initial-scale=1');
}
function onOpen(e) {
  SpreadsheetApp.getUi()
    .createMenu('Sidebar').addItem('Show FilterView', 'showSidebar').addToUi();
}

function showSidebar() {
  SpreadsheetApp.getUi().showSidebar(
    HtmlService.createHtmlOutputFromFile('hookSubService.html')
  )
}
  • Set sheet Ids and filterview ids above in HookSubService.html
  • Publish the web-app from script editor
  • Open the web app from the published link
  • Web app must be bound to the Spreadsheet's script editor

References:

  • Window#postMessage
  • Same origin policy


来源:https://stackoverflow.com/questions/57785797/how-to-apply-a-googlesheet-filterview-via-google-apps-script

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!