使用 App Script 在多个电子表格上一次执行一个功能

Use App Script to carry out one function, once, on many spreadsheets

我想在 Google 个工作表上运行一个 Google 脚本来规范化单元格范围。或者更准确地说,我希望(技术含量较低的)用户能够执行此操作。我似乎找不到合理的工作流程。

我能看到的选项有:

Copy/paste 脚本作为每个电子表格的绑定脚本

这很麻烦,因为脚本有很多副本,通常不会再次运行,而且有很多开销和点击为每个脚本安装宏。

使用图书馆

我可以将代码主体放入库中,然后将 copy/paste 设为存根(就像已接受的答案 here 一样)。

然而,这对用户体验来说仍然很糟糕,而且各种报告称库处理起来很麻烦。

制作一个插件

“正确的方法”似乎是创建一个用户可以为每个电子表格启用的插件。然而,附加组件似乎仍处于“开发者预览”模式,授权周期不确定且可能很慢。 Google 还希望 该脚本已经过多个活跃用户的测试。 这很难 - 当我彻底测试它时,工作基本上就完成了.在不发布附加组件的情况下如何测试它?

其他选项?

是否有其他方法,也许使用未绑定脚本?由于需要一些用户输入(电子表格中的范围等),不可能运行一次单个脚本并让它遍历所有电子表格。

有没有一种方法可以让用户安装一个未绑定的脚本,运行它,然后它会询问要在哪个电子表格上运行它?

openByUrl() 非常接近,但它实际上并没有打开电子表格用户界面,所以我无法使用 getActiveRange() 等功能

如果它是相关的,这里是脚本:

/*function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Normalize')
      .addItem('Normalize Crosstab', 'normalizeCrossTab')
      .addToUi();
}*/

function onOpen() {
  var ss = SpreadsheetApp.getActive();
  var items = [
    {name: 'Normalize Crosstab', functionName: 'normalizeCrosstab'},
  ];
  ss.addMenu('Normalize', items);
}

/* Converts crosstab format to normalized form. Given columns abcDE, the user puts the cursor somewhere in column D.
The result is a new sheet, NormalizedResult, like this:

a     b     c    Field Value
a1    b1    c1   D     D1
a1    b1    c1   E     E1
a2    b2    c2   D     D2
a2    b2    c2   E     E2
...

*/
function normalizeCrosstab() {
  var sheet = SpreadsheetApp.getActiveSheet(); 
  var rows = sheet.getDataRange();
  var numRows = rows.getNumRows();
  var values = rows.getValues();
  var firstDataCol = SpreadsheetApp.getActiveRange().getColumn();
  var dataCols = values[0].slice(firstDataCol-1);

  if (Browser.msgBox("This will create a new sheet, NormalizedResult. Place your cursor is in the first data column.\n\n" +
                     "These will be your data columns: " + dataCols,Browser.Buttons.OK_CANCEL) == "cancel") {
    return;
  }


  var resultssheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("NormalizedResult");
  if (resultssheet != null) {
    SpreadsheetApp.getActive().deleteSheet(resultssheet);
  }
  var header = values[0].slice(0, firstDataCol - 1);

  var newRows = [];
  
  header.push("Field");
  header.push("Value");
  newRows.push(header);

  for (var i = 1; i <= numRows - 1; i++) {
    var row = values[i];
    for (var datacol = 0; datacol < dataCols.length; datacol ++) {
      newRow = row.slice(0, firstDataCol - 1); // copy repeating portion of each row
      newRow.push(values[0][firstDataCol - 1 + datacol]); // field name
      newRow.push(values[i][firstDataCol - 1 + datacol]); // field value
      newRows.push(newRow);
    }
  }
  var newSheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet("NormalizedResult");
  var r = newSheet.getRange(1,1,newRows.length, header.length);
  r.setValues(newRows);
};

您可以检索用户提供 URL 的 sheet,将它们显示在简单的 HTML 中,一个 sheet 在另一个下面,并附加一个按钮列,这将为该行调用 normalizeCrosstab()。这是已发布的HTML解决方案,任何人无需登录即可使用。

如果有定义数量的 sheet,您也可以在 HTML 中使用名称旁边的按钮生成它们,它会生成 TABLE HTML.

或者使用图书馆,我怀疑你有什么需要但不能做的,那个答案很旧 (12')。

我正在使用库并且没有遇到任何问题,对所有事情都非常方便,所有 sheets 必须具有这 3 个函数才能工作,就好像脚本在 sheet 本身中一样:

function onOpen() {
  library.onInitialize();
}

function onEdit(celEd) {
  library.onMakeEdit(celEd);
}

function libraryFuncs( funcName, args ){ // Needed for sideBars to use library functions
  if(args)
    args = args.split("\!|"); // Predefined separation of args
  else
    args = [];

  return library[ funcao ]().apply(this, args);
}

第一个问题是:"Who is the owner of all these sheets?"如果是所有这些工作表的所有者,那么您有权远程访问它们。如果您不拥有它们,则所有者需要共享并授予试图修改其文件的任何代码的编辑权限。

如果您拥有所有电子表格,则可以创建一个独立应用程序,从一个中心点进行所有处理。然后,您可以将 Stand Alone App 的 link 通过电子邮件发送给每个人,或者让每个用户在他们的电子表格中输入一个 link 到 Stand Alone App。正如您所提到的,对于该选项,您将无法使用 getActiveSheet().

等方法

无论您使用什么选项,您都需要让人们向他们的电子表格添加内容,或者创建一些新的集中式界面。最适合您的选择可能归结为所有权和设置权限。

我猜如果电子表格的用户是所有者,并且不想授予您许可,他们将需要使用您的前三个选项之一。我会先从图书馆开始。

如果您可以轻松获取电子表格的文件 ID,则可以创建一个将用户与文件 ID 相匹配的对象。

var objUserToFileID = {"user1":"abc34ciu89384u", "user2":"FileID_Two", "user3":"FileID_Three"};

然后让用户从列表中选择他们的名字,(下拉列表)然后 运行 代码。那是针对独立应用程序的。当然,您需要弄清楚如果用户为其他人的电子表格选择文件 ID 会发生什么情况。那么您需要有一种方法来确定应用程序的用户是谁。