用户可以在没有电子表格的权限的情况下从电子表格复制数据并将其发送(粘贴)到“主”电子表格吗?

时间:2019-09-03 15:31:03

标签: google-apps-script

我正在开发一个简单的电子表格应用程序,供用户(工作同事)在年底提交绩效评估。我对他们能够通过一个按钮编辑电子表格A并将数据提交到电子表格B(数据库)感兴趣。问题在于电子表格B中的数据是私人/敏感的,因此必须与所有人共享才能解决。

我已经使代码正常工作,但是用户提交数据时收到警报。我猜这是因为他们没有共享电子表格B。他们正在收到此消息:“缺少文档X(也许它已被删除,或者您没有读取权限?)。”

//Displays spreadsheet use instructions.
function showInstructions() {
  var ui = SpreadsheetApp.getUi().alert('IMPORTANTE: Haz una copia del documento marcado como (Template) y trabaja sobre ella. \n \n Instrucciones: \n 1. Renombra la copia que creaste como “RecursosHumanos-EvaluadorDeDesempeno-TuNombre. \n 2. Lee los comentarios de cada rubro a evaluar desplazando el cursor/mouse por su encabezado. \n 3. Evalúa a tus colegas. \n 4. Ingresa los datos en el menú BIMmx > Submit.');
}

//Displays thanks banner after submitting form.
function showThanks() {
  var ui = SpreadsheetApp.getUi().alert('¡Gracias por participar!');
}

//Pops instructions and creates menus.
function onOpen() {   

  showInstructions();

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var menuButtons = [ {name: "Submit", functionName: "submit"} ];
  ss.addMenu("BIMmx", menuButtons);
}

function submit() {
  askName();
  copyData();
  showThanks();
  clear();
}

//Asks for user name before submitting data to master sheet.
function askName() {

  var ui = SpreadsheetApp.getUi();

  //Display prompt.
  var result; 
  var text = "";

  while (text == ""){
    result = ui.prompt(
      '¡Completa la evaluación!',
      'Ingresa tu nombre:',
      ui.ButtonSet.OK_CANCEL);

    // Process user's response.
    var button = result.getSelectedButton();
    text = result.getResponseText();
    if (text == "") 
      ui.alert('Nombre no puede estar vacío.');
    else if (button == ui.Button.OK) {
      // User clicked "OK".
      ui.alert('Tu nombre es ' + text + '.');
    } else if (button == ui.Button.CANCEL) {
      // User clicked "Cancel".
      ui.alert('No entendí eso.');
    } else if (button == ui.Button.CLOSE) {
      // User clicked X in the title bar.
      ui.alert('Cerraste el diálogo.');
    }


  }

 fillUser(text);

}

//Fills rows with submitting username.
function fillUser(result) {
  var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  ss.getRange("K2").setValue(result);  
  var lr = ss.getLastRow();
  var lc = ss.getLastColumn();
  var fillDownRange = ss.getRange(2, lc, lr-1);
  ss.getRange("K2").copyTo(fillDownRange);
}

//Backup data to master spreadsheet.  
function copyData(result) {
  var sss=SpreadsheetApp.getActive();
  var dss=SpreadsheetApp.openByUrl('InsertYourURL'); //I would just open by id
  var sh=sss.getSheetByName('Input');  
  var rg=sh.getRange(2,1,sh.getLastRow()-1,11);
  var sData=rg.getValues();
  var dsh=dss.getSheetByName('Output'); 
  dsh.getRange(dsh.getLastRow()+1,1,sData.length,sData[0].length).setValues(sData);

}

//Clean sheet once submission is done.  
function clear() {
  var sheet = SpreadsheetApp.getActive().getSheetByName('Input');
  sheet.getRange('A2:H').clearContent();
}
}

我正在完全复制该代码,可能与该问题无关。

很想听听有关如何解决此问题的任何想法。非常感谢!

2 个答案:

答案 0 :(得分:1)

您可以创建一个实现了doPost()函数的Web应用程序[1],该脚本可以像对待您一样操作电子表格。发布Web应用程序时,需要将“将应用程序执行为:”选项设置为“我”。

在源电子表格的脚本中,您可以使用fetch()函数[2]发出发布请求,将请求从源工作表将数据作为字符串发送到Web应用程序,您只需将copyData函数更改为此:

function copyData(result) {

  var sss=SpreadsheetApp.getActive();
  var sh=sss.getSheetByName('Input');  
  var rg=sh.getRange(2,1,sh.getLastRow()-1,11);
  var sData=rg.getValues().join(";");

  var options = {
    'method' : 'post',
    'payload' : sData
  };
  UrlFetchApp.fetch('[Web App URL]', options);
}

在Web App脚本中,您将处理接收到的数据,首先将字符串转换为2D数组,然后编辑目标工作表。 doPost函数将如下所示:

function doPost(e) {
  //Get the data from the fetch call  
  var sData = e.postData.contents;

  //Convert string to a 1D array
  var sData = sData.split(";");

  //Convert 1D array to 2D array
  for(var i=0; i<sData.length ; i++) {
    sData[i] = sData[i].split(",");
  }

  //Use your spreadsheetID to get Output Sheet
  var dss=SpreadsheetApp.openById('SPREADSHEET-ID'); //I would just open by id
  var dsh=dss.getSheetByName('Output');

  //Use setValues() function to put the 2D array into Sheet 
  dsh.getRange(dsh.getLastRow()+1,1,sData.length,sData[0].length).setValues(sData);

  return ContentService.createTextOutput('');
}

我通过上述更改测试了您的代码,并在没有目标电子表格权限的情况下按预期工作了用户。

[1] https://developers.google.com/apps-script/guides/web

[2] https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetch(String,Object)

答案 1 :(得分:0)

最后,在我的一个好朋友,显然是@AndresDuarte的帮助下,完成了它。谢谢!

答案是:构建一个Web应用程序,通过该应用程序发送数据,以便可以像仅由一个帐户发送数据一样对其进行标记(这样,它就不需要每个用户的编辑权限),并且包括一些JSON和Array解析以将字符串转换为矩阵。

这是脚本。

电子表格脚本

//Displays spreadsheet use instructions.
function showInstructions() {
  var ui = SpreadsheetApp.getUi().alert('IMPORTANTE: Haz una copia del documento marcado como (Template) y trabaja sobre ella. \n \n Instrucciones: \n 1. Renombra la copia que creaste como “RecursosHumanos-EvaluadorDeDesempeno-TuNombre. \n 2. Lee los comentarios de cada rubro a evaluar desplazando el cursor/mouse por su encabezado. \n 3. Evalúa a tus colegas. \n 4. Ingresa los datos en el menú BIMmx > Submit.');
}

//Displays thanks banner after submitting form.
function showThanks() {
  var ui = SpreadsheetApp.getUi().alert('¡Gracias por participar!');
}

//Pops instructions and creates menus.
function onOpen() {   

  showInstructions();

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var menuButtons = [ {name: "Submit", functionName: "submit"} ];
  ss.addMenu("X", menuButtons);
}

function submit() {
  askName();
  copyData();
  showThanks();
  clear();
}

//Asks for user name before submitting data to master sheet.
function askName() {

  var ui = SpreadsheetApp.getUi();

  //Display prompt.
  var result; 
  var text = "";

  while (text == ""){
    result = ui.prompt(
      '¡Completa la evaluación!',
      'Ingresa tu nombre:',
      ui.ButtonSet.OK_CANCEL);

    // Process user's response.
    var button = result.getSelectedButton();
    text = result.getResponseText();
    if (text == "") 
      ui.alert('Nombre no puede estar vacío.');
    else if (button == ui.Button.OK) {
      // User clicked "OK".
      ui.alert('Tu nombre es ' + text + '.');
    } else if (button == ui.Button.CANCEL) {
      // User clicked "Cancel".
      ui.alert('No entendí eso.');
    } else if (button == ui.Button.CLOSE) {
      // User clicked X in the title bar.
      ui.alert('Cerraste el diálogo.');
    }


  }

 fillUser(text);

}

//Fills rows with submitting username.
function fillUser(result) {
  var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  ss.getRange("K2").setValue(result);  
  var lr = ss.getLastRow();
  var lc = ss.getLastColumn();
  var fillDownRange = ss.getRange(2, lc, lr-1);
  ss.getRange("K2").copyTo(fillDownRange);
}

//Backup data to master spreadsheet.  
function copyData() {

  var sss=SpreadsheetApp.getActive();
  var sh=sss.getSheetByName('Input');  
  var rg=sh.getRange(2,1,sh.getLastRow()-1,11);
  var sData=rg.getValues().join(";");

  //This is the Web App URL.
  var url = "Enter you URL here";  

  var payload = {    
    "sData" : JSON.stringify(sData),    
  }

  var options = {
    "method" : "POST",
    "payload" : payload,
    "followRedirects" : true,
    "muteHttpExceptions" : true,
  };

  var result = UrlFetchApp.fetch(url, options);
  //Logger.log(JSON.parse(result));  


}

//Clean sheet once submission is done.  
function clear() {
  var sheet = SpreadsheetApp.getActive().getSheetByName('Input');
  sheet.getRange('A2:K').clearContent();
}

网络应用脚本

function doPost(e) {

  var sData = JSON.parse(e.parameters.sData);  

  var response = {
    "status" : "FAILED",
    "sData" : sData,
  };  

  sData = sData.split(";");

  //Convert 1D array to 2D array
  for(var i = 0; i < sData.length ; i++) {
    sData[i] = sData[i].split(",");
  }

  //Use your spreadsheetID to get Output Sheet
  var dss=SpreadsheetApp.openById('Enter your ID here.');
  var dsh=dss.getSheetByName('Output');

  //Use setValues() function to put the 2D array into Sheet 
  dsh.getRange(dsh.getLastRow()+1,1,sData.length,sData[0].length).setValues(sData);

  MailApp.sendEmail("Enter your email here","New Response","A new response has been registered.");  

  var response = {
    "status" : "SUCCESS",
    "sData" : sData,
  };     

  return ContentService.createTextOutput(JSON.stringify(response));

}