感謝 Stack 人員的幫助,提供了以下腳本以使我撰寫的保護腳本運行得更快。雖然新腳本確實應用了指定范圍之外的保護,但獲得編輯器訪問權限的用戶能夠在所需范圍之外進行編輯。
我希望確保用戶只能輸入特定范圍內的資料,但為了輸入資料,他們需要編輯器訪問權限。是否可以限制編輯器只編輯所需的范圍?
// This script is from https://tanaikech.github.io/2017/07/31/converting-a1notation-to-gridrange-for-google-sheets-api/
function a1notation2gridrange1(a1notation) {
var data = a1notation.match(/(^. )!(. ):(. $)/);
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(data[1]);
var range = ss.getRange(data[2] ":" data[3]);
var gridRange = {
sheetId: ss.getSheetId(),
startRowIndex: range.getRow() - 1,
endRowIndex: range.getRow() - 1 range.getNumRows(),
startColumnIndex: range.getColumn() - 1,
endColumnIndex: range.getColumn() - 1 range.getNumColumns(),
};
if (!data[2].match(/[0-9]/)) delete gridRange.startRowIndex;
if (!data[3].match(/[0-9]/)) delete gridRange.endRowIndex;
return gridRange;
}
// Please run this function.
function myFunction() {
// Please set your sheet names and unprotected ranges you want to use.
const obj = [
{ sheetName: "Ordering", unprotectedRanges: ["O5:P", "C2:E2"] },
{ sheetName: "Accessory INV", unprotectedRanges: ["E5:H"] },
{ sheetName: "Apparel INV", unprotectedRanges: ["E5:F"] },
{sheetName: "Pending TOs", unprotectedRanges: ["E6:H"] },
{sheetName: "INV REF", unprotectedRanges: ["C6:C"] },
];
// 1. Retrieve sheet IDs and protected range IDs.
const spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
const sheets = Sheets.Spreadsheets.get(spreadsheetId, { ranges: obj.map(({ sheetName }) => sheetName), fields: "sheets(protectedRanges(protectedRangeId),properties(sheetId))" }).sheets;
const { protectedRangeIds, sheetIds } = sheets.reduce((o, { protectedRanges, properties: { sheetId } }) => {
if (protectedRanges && protectedRanges.length > 0) o.protectedRangeIds.push(protectedRanges.map(({ protectedRangeId }) => protectedRangeId));
o.sheetIds.push(sheetId);
return o;
}, { protectedRangeIds: [], sheetIds: [] });
// 2. Convert A1Notation to Gridrange.
const gridranges = obj.map(({ sheetName, unprotectedRanges }, i) => unprotectedRanges.map(f => a1notation2gridrange1(`${sheetName}!${f}`)));
// 3. Create request body.
const deleteProptectedRanges = protectedRangeIds.flatMap(e => e.map(id => ({ deleteProtectedRange: { protectedRangeId: id } })));
const protects = sheetIds.map((sheetId, i) => ({ addProtectedRange: { protectedRange: { range: { sheetId }, unprotectedRanges: gridranges[i] } } }));
// 4. Request to Sheets API with the created request body.
Sheets.Spreadsheets.batchUpdate({ requests: [...deleteProptectedRanges, ...protects] }, spreadsheetId);
}
編輯:Tanaike 提供的解決方案可以將編輯器限制為我(所有者),但是當其他用戶使用以下內容插入一行時,腳本將由其他用戶運行:
function addNewApparelSKU() {
const ss = SpreadsheetApp.getActive();
const ui = SpreadsheetApp.getUi();
const sheet = ss.getSheetByName('Apparel INV');
const response = ui.prompt('Enter New SKU', ui.ButtonSet.OK_CANCEL);
if (response.getSelectedButton() === ui.Button.OK) {
const text = response.getResponseText();
sheet.appendRow([text]);
sheet.sort(1);
myFunction(); //references the Protection script
}
}
當這個腳本被另一個編輯器使用時,它會給出一個錯誤,因為用戶由于限制而不能插入一行。
uj5u.com熱心網友回復:
我相信你的目標如下。
- 您希望保護每個作業表中的特定范圍,并希望用戶僅編輯特定范圍。
- 根據您更新的問題,
addNewApparelSKU通過單擊電子表格上的按鈕運行腳本。
關于the following script was provided to make a protection script I had written run faster.,如果用你上題的腳本,下面修改的腳本怎么樣?
而且,在這種情況下,需要myFunction()由所有者(您)運行腳本(在這種情況下,它是.)。為此,我想使用 Web Apps 運行此腳本。這樣,腳本就可以由所有者運行了。
用法:
1. 示例腳本:
請將以下腳本復制并粘貼到電子表格的腳本編輯器中。并且請在高級 Google 服務中啟用 Sheets API。
并且,請將您的電子郵件地址設定為const email = "###";in myFunction。
function addNewApparelSKU() {
// This is from addNewApparelSKU().
const ss = SpreadsheetApp.getActive();
const ui = SpreadsheetApp.getUi();
const response = ui.prompt('Enter New SKU', ui.ButtonSet.OK_CANCEL);
if (response.getSelectedButton() === ui.Button.OK) {
const text = response.getResponseText();
const webAppsUrl = "https://script.google.com/macros/s/###/exec"; // Pleas set your Web Apps URL.
const url = webAppsUrl "?text=" text;
const res = UrlFetchApp.fetch(url, {muteHttpExceptions: true});
// ui.alert(res.getContentText()); // You can see the response value using this line.
}
}
function doGet(e) {
const text = e.parameter.text;
const sheet = SpreadsheetApp.getActive().getSheetByName('Apparel INV');
sheet.appendRow([text]);
sheet.sort(1);
myFunction();
return ContentService.createTextOutput(text);
}
// This script is from https://tanaikech.github.io/2017/07/31/converting-a1notation-to-gridrange-for-google-sheets-api/
function a1notation2gridrange1(a1notation) {
var data = a1notation.match(/(^. )!(. ):(. $)/);
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(data[1]);
var range = ss.getRange(data[2] ":" data[3]);
var gridRange = {
sheetId: ss.getSheetId(),
startRowIndex: range.getRow() - 1,
endRowIndex: range.getRow() - 1 range.getNumRows(),
startColumnIndex: range.getColumn() - 1,
endColumnIndex: range.getColumn() - 1 range.getNumColumns(),
};
if (!data[2].match(/[0-9]/)) delete gridRange.startRowIndex;
if (!data[3].match(/[0-9]/)) delete gridRange.endRowIndex;
return gridRange;
}
// Please run this function.
function myFunction() {
const email = "###"; // <--- Please set your email address.
// Please set your sheet names and unprotected ranges you want to use.
const obj = [
{ sheetName: "Ordering", unprotectedRanges: ["O5:P", "C2:E2"] },
{ sheetName: "Accessory INV", unprotectedRanges: ["E5:H"] },
{ sheetName: "Apparel INV", unprotectedRanges: ["E5:F"] },
{sheetName: "Pending TOs", unprotectedRanges: ["E6:H"] },
{sheetName: "INV REF", unprotectedRanges: ["C6:C"] },
];
// 1. Retrieve sheet IDs and protected range IDs.
const spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
const sheets = Sheets.Spreadsheets.get(spreadsheetId, { ranges: obj.map(({ sheetName }) => sheetName), fields: "sheets(protectedRanges(protectedRangeId),properties(sheetId))" }).sheets;
const { protectedRangeIds, sheetIds } = sheets.reduce((o, { protectedRanges, properties: { sheetId } }) => {
if (protectedRanges && protectedRanges.length > 0) o.protectedRangeIds.push(protectedRanges.map(({ protectedRangeId }) => protectedRangeId));
o.sheetIds.push(sheetId);
return o;
}, { protectedRangeIds: [], sheetIds: [] });
// 2. Convert A1Notation to Gridrange.
const gridranges = obj.map(({ sheetName, unprotectedRanges }, i) => unprotectedRanges.map(f => a1notation2gridrange1(`${sheetName}!${f}`)));
// 3. Create request body.
const deleteProptectedRanges = protectedRangeIds.flatMap(e => e.map(id => ({ deleteProtectedRange: { protectedRangeId: id } })));
const protects = sheetIds.map((sheetId, i) => ({ addProtectedRange: { protectedRange: { editors: {users: [email]}, range: { sheetId }, unprotectedRanges: gridranges[i] } } }));
// 4. Request to Sheets API with the created request body.
Sheets.Spreadsheets.batchUpdate({ requests: [...deleteProptectedRanges, ...protects] }, spreadsheetId);
}
2. 部署 Web 應用程式。
詳細資訊可以查看官方檔案。
在腳本編輯器中,在腳本編輯器的右上角,請單擊“單擊部署”->“新建部署”。
請單擊“選擇型別”->“Web 應用程式”。
請在“部署配置”下的欄位中輸入有關 Web App 的資訊。
請為“執行為”選擇“我”。
- 這就是此解決方法的重要性。
請為“誰有權訪問”選擇“任何人”。
- 在你的情況下,我認為這個設定可能是合適的。
請單擊“部署”按鈕。
復制 Web 應用程式的 URL。就像
https://script.google.com/macros/s/###/exec.- 當您修改 Google Apps 腳本時,請將部署修改為新版本。這樣,修改后的腳本就會反映在 Web Apps 中。請注意這一點。
- 您可以在“重新部署 Web 應用程式而不更改新 IDE 的 Web 應用程式的 URL ”的報告中看到這方面的詳細資訊。
請
const url = "https://script.google.com/macros/s/###/exec";在上述腳本中設定 Web Apps URL 。請將部署修改為新版本。這樣,修改后的腳本就會反映在 Web Apps 中。請注意這一點。您可以在此處查看此流程。
3. 測驗。
請addNewApparelSKU()點擊按鈕運行。這樣,腳本由所有者運行。
筆記:
- 當您修改 Google Apps 腳本時,請將部署修改為新版本。這樣,修改后的腳本就會反映在 Web Apps 中。請注意這一點。
- 您可以在“重新部署 Web 應用程式而不更改新 IDE 的 Web 應用程式的 URL ”的報告中看到這方面的詳細資訊。
- 我建議的腳本是一個簡單的腳本。所以請根據您的實際情況進行修改。
參考:
- 網路應用程式
- 通過 Google Apps 腳本利用網路應用
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/380487.html
上一篇:無法檢索下一個物件:迭代器已結束
