从外部应用程序调用绑定脚本 - Google电子表格

时间:2015-06-24 00:49:20

标签: google-chrome-extension google-apps-script google-sheets xmlhttprequest urlfetch

我想将Chrome扩展程序与Google电子表格集成。

简单来说:我希望我的Chrome扩展程序能够打开电子表格并调用电子表格中包含的其中一个脚本。特别是JSON数据(请参阅最后的更新)。

  • 我处理扩展的知识很好。
  • 另外,我在电子表格中创建绑定脚本的知识。
  • 但是,我对Google网络应用,doGets等事情的了解非常困惑,他们的文档从我应该知道他们在说什么的地方开始,但我不是。所以我需要有关事情如何流动的细节。谈论身份验证和内容,而不知道代码应该是什么和哪里似乎没有任何亮点。
  

所以我需要一个详细的答案。 where 部分是绝对必要的。

到目前为止,我有一个非常好的脚本运行(脚本不是这个问题的范围),绑定到电子表格。 (该脚本应仅针对此工作表运行,因此除非出于技术原因,否则保持绑定不是问题)。

工作表需要获取一些外部数据(我无法控制)才能运行带有该数据的脚本。如果我使用UrlFetch从电子表格中进行尝试,我会遇到跨域问题并且Google会阻止我(如果您可以帮助我绕过此跨域问题,那么它也会很棒)。

在Chrome扩展程序中,附加到检索数据的页面,我可以执行所需的所有请求并实际获取数据,但是,我不知道如何发送此数据数据到表格。

所以,我希望扩展程序和工作表能够相互交谈。它不需要是双向谈话。如果只是扩展程序可以在工作表中输入数据而没有得到答案,那就可以了。

这可以实现吗?

还有另一种方法吗?

更新

在@Peter Herrmann的帮助下,我能够摆脱零。设置了doGetdoPost(如本问题末尾所示),现在我正努力发送" JSON"数据到表格。我创建了" JSON"和" JSONP"在单独的表格中进行测试。

如果我在浏览器的导航栏中输入exec链接,它就可以正常使用(但我相信这只是一个" GET",是吗?我可以通过导航栏发送JSON吗?)。

如果我使用浏览器的控制台发送XMLHttpRequest,则会出现以下错误,因为它是" JSON"或者" JSONP"脚本的版本:

  • Chrome控制台:" XMLHttpRequest无法加载https://script.google.com/macros/s/xxxx/exec。对预检请求的响应没有通过访问控制检查:否'访问控制 - 允许 - 来源'标头出现在请求的资源上。因此,不允许原点https://xxxxxxxxx.com访问。响应的HTTP状态代码为405。"
  • Mozilla的控制台---" 405方法不允许"。

用于请求的代码是:

var req = new XMLHttpRequest();     
req.open("POST", "https://script.google.com/macros/.../exec", true);
req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
req.send(JSON.stringify({d1:"hey", d2:"there"}));

然而,使用标准" JSONP"像这样的脚本标记中的请求是有效的(但是这并不会将JSON发送到工作表,是吗?):

 $("<script src='https://script.google.com/macros/s/AKfycbza11ABUxtxn-rcv-1v2ZM3uCzpARx1-t6KkPJk4rtAta_4SQc/exec?prefix=window.alert'></script>").appendTo($(document.head)).remove();

如果我尝试将请求代码放在脚本标记内,它也会导致&#34;不允许&#34;错误。

在表格代码中,相关部分是:

function doGet(request) {

   var result = JSON.stringify({data: 'Thanks, I received the request'});

   //JSON
   return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JSON);

   //JSONP
   result = request.parameters.prefix + "(" + result + ");";
   return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JAVASCRIPT);
}


function doPost(request) {

   var result = JSON.stringify({data: 'Thanks, I received the request'});

   //JSON 
   return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JSON);

   //JSONP
   result = request.parameters.prefix + "(" + result + ");";
   return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JAVASCRIPT);
}

3 个答案:

答案 0 :(得分:5)

您说要更新电子表格,例如Chrome扩展程序。您可以在脚本中使用ContentService公开更新功能,然后从您的扩展程序中调用该URL。这是一个在电子表格单元格中设置数据并返回消息的示例:

function doGet(request) {

  //get the data from the request's "somedata" querystring parameter ..../exec?somedata=mydata
  var data = request.parameters.somedata;

  //update the bound spreadsheet (workaround https://code.google.com/p/google-apps-script-issues/issues/detail?id=5734)
  SpreadsheetApp.openById('1cm6tK0Io4lnbRZ0OhlvZijhrQoqCt01adyYlUbZgUZY')
  .getSheetByName('Sheet1')
  .getRange('B1')
  .setValue(data);

  //send some data back as a response
  var result = {
    data: 'Thanks, I received: ' + data,
    error: null
  };
  return ContentService.createTextOutput(JSON.stringify(result))
    .setMimeType(ContentService.MimeType.JSON);
}

测试:

  1. 在代码编辑器中,发布&gt;部署为Web App
  2. 选择以我身份执行应用,允许访问:任​​何人,甚至匿名
  3. 单击“部署”,然后单击“授权”和“允许”。
  4. 复制并记下给定的URL。我得到了https: //script.google.com/macros/s/AKfycbyTi0NOZdTm5J_tZnUXw9skWfYlLADvkDDdCd593XC-H6LN4A/exec
  5. ?somedata=ABC123添加到网址,然后点击隐身浏览器窗口中的完整网址。 https://script.google.com/macros/s/AKfycbyTi0NOZdTm5J_tZnUXw9skWfYlLADvkDDdCd593XC-H6LN4A/exec?somedata=ABC123
  6. 这导致&#34; ABC123&#34;在单元格B1和浏览器消息中设置:{&#34;数据&#34;:&#34;谢谢,我收到:ABC123&#34;,&#34;错误&#34;:null}

    这是指向source spreadsheet的链接,您可以从中添加文件&gt;制作副本。

答案 1 :(得分:2)

当然可以。但你现在的问题是太开放了。您需要将其分解为2到3个不同的问题,并附上您已编写并尝试过的代码。然后有人可以帮助你,而不是他们自己完成整个写作。

与脚本通信的最简单方法是使用doGet()或doPost()。这可能有点令人困惑,尝试阅读更多内容并执行google文档中显示的示例。一旦掌握了它,它就会很容易。 URLFetch 旨在向任意网址发出请求,因此跨域名称不应该因此而存在。再说一遍,除非你自己编写一些代码,试试看然后在这里发布,很难提供帮助。

答案 2 :(得分:2)

当Google App脚本作为Web应用程序发布时,将根据是否对脚本的URL发出GET或POST请求,自动调用特殊回调函数doGet()和doPost()。

因此,如果您希望外部应用程序与您的Google应用程序脚本进行交互,则可以对脚本的网址发出http请求。

例如,如果您在code.gs中编写以下内容,然后将其作为具有正确设置的webapp发布,那么点击该脚本网址的任何人都将收到消息Hello World,因为它将是对此的GET请求自动调用脚本的URL和doGet(),在这种情况下编程为返回字符串

function doGet() {
  return ContentService.createTextOutput('Hello, world!');
}

例如,尝试this url

同样,你可以编写代码来返回其他mime类型即。 ATOM, CSV, iCal, JavaScript, JSON, RSS, vCard, XML

假设您想要返回json数据,只需更改mime类型即可。例如,如果您更改代码如下:

function doGet(request) {

 var employees = {"employees": [  { "firstName": "John", "lastName": "Doe"}, { "firstName": "Anna", "lastName": "Smith"} ] }

  return ContentService.createTextOutput(JSON.stringify(employees))
    .setMimeType(ContentService.MimeType.JSON);
}

将它作为webapp发布并访问url后,您将获得json输出。

尝试this url

输出看起来像{"employees":[{"firstName":"John","lastName":"Doe"},{"firstName":"Anna","lastName":"Smith"}]},现在是json格式。

因此,如果您的Chrome扩展程序需要进行通信,则会通过向脚本的URL发出http请求来实现。

现在进入身份验证部分,您可以在将脚本发布为Web应用程序时设置所需的身份验证,并记住外部应用程序与您的应用程序脚本进行通信,您必须将其发布。

如果您想将数据发送到Google App脚本,然后将您的脚本发布为webapp,然后您可以通过向已发布的网络应用的网址发出GET或POST请求来发送数据。

例如,您可以像这样编写code.gs:

function doGet(e) 
{
  Logger.log( Utilities.jsonStringify(e) );

  if (e.parameter.data) 
  {
    var dataInQueryString = e.parameter['data']

    // now we can write dataInQueryString to a spreadhseet using spreadhsheet api

    return ContentService.createTextOutput('Content received : '+ dataInQueryString);

  }
}

现在照常发布并使用查询参数数据调用url以查看结果。

我的意思是:https://*published_url*?data='Test Data'

当你在浏览器中调用这个url时,会对url发出GET请求,并且会自动调用doGet()。

试试这个网址:

https://script.google.com/macros/s/AKfycbzl-LnNIYtOCs8iEB9FjrCSUl9cS0iy7a8JmnG-RfpOfIf7m98/exec?data=I am great

为了在查询字符串中发送json数据,请参阅此answer

希望这有帮助!