是否可以在Google Docs电子表格中将编辑者的用户名写入单元格

时间:2014-09-18 14:55:01

标签: google-apps-script google-sheets

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

我想完成看似简单的任务,即只要编辑列中的单元格,就可以将时间戳和编辑器的用户名写入相邻的单元格。

这是我到目前为止尝试过的代码:

/**
 * 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会发生什么。我们都在同一个域名。

1 个答案:

答案 0 :(得分:1)

这实际上是可行的,正确的方法就是这样做         Session.getActiveUser().getEmail()

谷歌在文档中说:

  

如果安全策略不允许访问用户的身份,User.getEmail()将返回一个空字符串。电子邮件地址可用的情况各不相同:例如,用户的电子邮件地址在任何允许脚本在没有该用户授权的情况下运行的上下文中都不可用,例如简单的onOpen(e)或onEdit(e)触发器

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