【问题标题】:Call bound script from external application - Google spreadsheet从外部应用程序调用绑定脚本 - Google 电子表格
【发布时间】:2015-09-10 00:32:36
【问题描述】:

我想将 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。对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,来源 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();

如果我尝试将请求代码放在脚本标签中,也会导致“不允许”错误。

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

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);
}

【问题讨论】:

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


    【解决方案1】:

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

    因此,如果您希望外部应用程序与您的 google 应用程序脚本进行交互,您可以向脚本的 url 发出 http 请求。

    例如,如果您在 code.gs 中编写以下内容,然后将其发布为具有正确设置的 webapp,则任何点击脚本 url 的人最终都会收到消息 Hello World,因为这将是对脚本 url 的 GET 请求并且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 Script 发送数据,请将您的脚本发布为 webapp,然后您可以通过向已发布 webapp 的 url 发出 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

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      您说您想通过 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. 在代码编辑器中,发布 > 部署为 Web 应用程序
      2. 选择以我身份执行应用,允许访问:任​​何人,甚至匿名
      3. 单击部署,然后单击授权并允许。
      4. 复制并记下给出的 URL。我得到了https: //script.google.com/macros/s/AKfycbyTi0NOZdTm5J_tZnUXw9skWfYlLADvkDDdCd593XC-H6LN4A/exec
      5. ?somedata=ABC123 添加到 URL 并从隐身浏览器窗口中点击完整的 URL。 https://script.google.com/macros/s/AKfycbyTi0NOZdTm5J_tZnUXw9skWfYlLADvkDDdCd593XC-H6LN4A/exec?somedata=ABC123

      这会导致在单元格 B1 中设置“ABC123”并且浏览器消息:{“data”:“Thanks, I received: ABC123”,"error":null}

      这是一个指向source spreadsheet 的链接,您可以从中进行文件 > 制作副本。

      【讨论】:

      • 太棒了!一些混乱消失了!我可以从工作表中获取数据并发送非常简单的数据。但每当我尝试通过“JSON”发送数据时,我都会收到此错误:XMLHttpRequest 无法加载https://script.google.com/macros/s/xxxx/exec。对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin https://xxxxxxxxx.com 不允许访问。响应的 HTTP 状态代码为 405。
      • 您的 chrome 扩展代码 impl 可能需要使用 JSONP 进行跨源调用,因为 same origin policy(Google Apps 服务器不提供 CORS 标头)。见小节Serving JSONP in web pages
      • 似乎没有办法将 JSON“发送”到电子表格......我一直在尝试 JSONP,但同样,它不允许我“发送”JSON .
      • Stackoverflow 都是关于真实的实际代码,因此您需要编辑您的问题以显示工作/失败的代码,以便其他人尽可能有机会为您提供最好的答案。
      【解决方案3】:

      是的,当然有可能。但是,就目前而言,您的问题过于开放。您需要将其分解为 2 或 3 个不同的问题,并附上您编写并尝试过的代码。然后有人可以帮助你,而不是他们自己完成整个写作。

      您与脚本通信的最简单方法是使用 doGet() 或 doPost()。通过尝试阅读更多内容并执行 google 文档中显示的示例,这可能会有点令人困惑。一旦你掌握了它的窍门,它就会很容易。 URLFetch 是为向任意 URL 发出请求而设计的,因此跨域不应该是这样的。同样,除非您自己编写一些代码,否则请尝试一下然后将其发布在这里,这很难提供帮助。

      【讨论】:

      • 示例在哪里?我找不到他们。 doGet() 和 doPost() 应该写在哪里?我不知道。没有“完整的写作”。只是说做一个“doGet()”和一个“doPost()”是到处都在说的,如果我不知道它们应该写在哪里或者谁会调用或者如何调用这些方法,它并没有真正的帮助。
      • @Daniel 在这里:developers.google.com/apps-script/guides/html 还有更多:labnol.org编程涉及为自己尝试和寻找事物。
      • 这真的不是我想要的。我不想提供 HTML(事实上我已经读过这个,而且我的电子表格确实包含 HTML 接口)。问题是“如何调用电子表格中的脚本”,例如 chrome 扩展。
      • @Daniel 答案是:调用它的方法是在脚本中使用 doGet() 或 doPost()。您不必提供任何 html,但 doGet() 仍然可以工作。请仔细阅读,以便您更好地理解。
      猜你喜欢
      • 2012-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多