问题
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