google-apps-script - 是否可以将编辑器的用户名写入 Google Docs 电子表格中的单元格

标签 google-apps-script google-sheets

我对 Google 脚本不断发展的功能/限制感到沮丧。

我想完成看似简单的任务,即每当编辑者编辑列中的单元格时,将时间戳和编辑者的用户名写入相邻的单元格。

这是我迄今为止尝试过的代码:

/**
 * Get current user's name, by accessing their contacts.
 *
 * @returns {String} First name (GivenName) if available,
 *                   else FullName, or login ID (userName)
 *                   if record not found in contacts.
 */
function getOwnName(){
  var email = Session.getEffectiveUser().getEmail();
  var self = ContactsApp.getContact(email);

  // If user has themselves in their contacts, return their name
  if (self) {
    // Prefer given name, if that's available
    var name = self.getGivenName();
    // But we will settle for the full name
    if (!name) 
      name = self.getFullName();
    return name;
  }
  // If they don't have themselves in Contacts, return the bald userName.
  else {
    var userName = Session.getEffectiveUser().getUsername();
    return userName;
  }
}

但是,getEffectiveUser 仅获取我的用户名,而不是当前编辑器。 getActiveUser 不返回任何内容。

替代方案并不漂亮。我看到一些示例,当前用户在打开电子表格时会从所有编辑器的列表中选择他们的电子邮件。电子邮件将存储在草稿纸上的某个位置,并在用户进行编辑时以某种方式粘贴到单元格中,尽管示例中省略了电子邮件存储和检索。
作为一种可怕且极其缓慢/低效的黑客行为,我插入时间戳,然后弹出一个带有列表框和按钮的页面,从单元格范围中获取用户名,当编辑器选择他们的名称时,它应该将值粘贴到相邻的单元格中。然而,由于某些尚未确定的原因,这似乎会随机遇到授权问题,更不用说速度非常慢了:

function show() {
   var doc = SpreadsheetApp.getActiveSpreadsheet();
var specialSheet = doc.getSheetByName("ADDL. INFO");
   var app = UiApp.createApplication().setTitle('Select Name').setWidth(150).setHeight(150);
   var panel = app.createVerticalPanel();
   var lb = app.createListBox(true).setId('myId').setName('myLbName');

   // add items to ListBox
   lb.setVisibleItemCount(4);

    // Getting a known named range from spreadsheet object.
  empLocRange = specialSheet.getRange("A28:A32");
  //.getRangeByName('EmployeeLocations');
  empLocs = empLocRange.getValues();
  empLocs.sort()

    for (i=0; i < empLocs.length; ++i) {    
      empLoc = empLocs[i][0].toString().trim();
      if (!(empLoc=='')) {
        lb.addItem(empLoc);
      }
    }
   panel.add(lb);
   var button = app.createButton('Select');
   var handler = app.createServerClickHandler('click').addCallbackElement(panel);
   button.addClickHandler(handler);
   panel.add(button);
   app.add(panel);
   doc.show(app);
 }


 function click(eventInfo) {
   var app = UiApp.getActiveApplication();
   // get values of ListBox
   var value = eventInfo.parameter.myLbName;
   // multi select box returns a comma separated string
   var n = value.split(',');
    var s = SpreadsheetApp.getActiveSheet();
    var r = s.getActiveCell();
    var p = r.getRow();
  var nextCell = r.offset(0, 2);    
var app = UiApp.getActiveApplication();
  nextCell.setValue(value);
   app.close();
   return app;
 }

我读到将脚本发布为独立应用程序,您可以访问当前用户名,但这似乎不是正确的解决方案。我想我也许可以为每个用户安装这个脚本作为解决方案,但它似乎并没有以这种方式运行。

任何帮助或将不胜感激。

编辑。 忘记包含调用此函数的函数:

function timestamp() {
  var s = SpreadsheetApp.getActiveSheet();
    var r = s.getActiveCell();
    var p = r.getRow();
    if( r.getColumn() == 14 ) //checks the column
    { 
      var nextCell = r.offset(0, 1);      
        nextCell.setValue(new Date());
      //s.setActiveSelection(p + "15");
      show();
      //SpecialonOpen();
      //nextCell = r.offset(0,2);
    //nextCell.setValue(getOwnName());
    }
}

我将上述时间戳函数设置为在编辑时触发 - 时间戳,来自电子表格,编辑时。




更新: 我一直在努力反对这一点。
这就是结果,尽管有奇怪的、无法解释的行为。 我当前的脚本:

function getOwnName(){

  var email = Session.getEffectiveUser().getEmail();
  //Browser.msgBox("getOwnName");
  //var self = ContactsApp.getContact(email);
  var self = false; 

  // If user has themselves in their contacts, return their name
  if (self) {
    // Prefer given name, if that's available
    var name = self.getGivenName();
    // But we will settle for the full name
    if (!name) 
    {
      name = self.getFullName();
    }
    //Browser.msgBox(name);
    return name;
  }
  // If they don't have themselves in Contacts, return the bald userName.
  else {
    var userName = Session.getEffectiveUser().getUsername();
    //Browser.msgBox(userName);
    return userName;
  }
}

function onEdit() {
  var s = SpreadsheetApp.getActiveSheet();
    var r = s.getActiveCell();
    var p = r.getRow();
    if( r.getColumn() == 14 ) //checks the column
    { 
      var nextCell = r.offset(0, 1);      
        nextCell.setValue(new Date());
      //Browser.msgBox("hey!");
      //s.setActiveSelection(p + "15");
      //show();
      //SpecialonOpen();
      var nCell = r.offset(0,2);
      //Browser.msgBox("olah:" + getOwnName());
    nCell.setValue(getOwnName());
    }
}

我注释掉了 //var self = ContactsApp.getContact(email); 因为它似乎使脚本崩溃。
这样做之后,我去找我的一位用户并询问他们来测试。仍然没有用户名写入单元格。我告诉他打开脚本并使用播放按钮执行该函数。这会弹出一条授权消息。他同意授权脚本,返回电子表格后,他的名字已成功插入到单元格中。
但是,当 onEdit 触发时,脚本仍然不会将他的用户名写入单元格。所以我真的不知道GS是怎么回事。我们都在同一个域中。

最佳答案

这实际上是可能的,正确的方法是 Session.getActiveUser().getEmail()

Google 在文档中指出:

If security policies do not allow access to the user's identity, User.getEmail() returns a blank string. The circumstances in which the email address is available vary: for example, the user's email address is not available in any context that allows a script to run without that user's authorization, like a simple onOpen(e) or onEdit(e) trigger

虽然我们有这个工作。我不清楚为什么会这样,但是一旦我添加了一个菜单条目,调用与 onEdit 相同的函数,并且在关闭和打开电子表格后,我收到了一个授权请求,从那时起它就起作用了。

关于google-apps-script - 是否可以将编辑器的用户名写入 Google Docs 电子表格中的单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25916035/

相关文章:

javascript - 有没有办法从 Google Apps 脚本环境访问 Google Data API?

ios - 获取谷歌电子表格 ios

google-sheets - 大于或等于自定义数字格式

google-sheets - 删除 ArrayFormula 导入的空白条目

python - 有人可以用 python 和 google sheets api 帮助我解决这个问题吗?

html - 将 Google 字体导入 HTML 服务

javascript - 在 Google 文档中添加文本和删除文本(插件)

google-apps-script - Google Apps 脚本函数 getActiveSheet() 不返回事件工作表

postgresql - 使用Google电子表格中的Google Apps脚本连接到Postgresql数据库

google-sheets - Google 电子表格使用 importxml 获取文本