【问题标题】:Add row to Google Spreadhseet via API通过 API 将行添加到 Google 电子表格
【发布时间】:2015-03-14 13:57:57
【问题描述】:

我正在构建一个 Chrome 扩展程序,它应该将新行写入 Google 电子表格。我设法阅读了工作表内容,但无法再写一行。目前我的错误是“400(错误请求)”。知道我在这里做错了什么吗?

我在这里查看了Google Sheets API documentation 和其他发布的问题,但找不到任何解决方案。

这是我用来获取工作表内容的代码(有效):

function loadSpreadsheet(token) {

    var y = new XMLHttpRequest();
    y.open('GET', 'https://spreadsheets.google.com/feeds/list/spreadsheet_id/default/private/values?access_token=' + token);
    y.onload = function() {
        console.log(y.response);
    };
    y.send();

}

这是我尝试发布新行的代码(给我“400 - 错误请求”):

function appendRow(token){

    function constructAtomXML(foo){
        var atom = ["<?xml version='1.0' encoding='UTF-8'?>",
            '<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gsx="http://schemas.google.com/spreadsheets/2006/extended">',//'--END_OF_PART\r\n',
            '<gsx:name>',foo,'</gsx:name>',//'--END_OF_PART\r\n',
            '</entry>'].join('');
        return atom;
    };

    var params = {
        'body': constructAtomXML("foo")
    };

    url = 'https://spreadsheets.google.com/feeds/list/spreadsheet_id/default/private/full?alt=json&access_token=' + token;

    var z = new XMLHttpRequest();
    z.open("POST", url, true);
    z.setRequestHeader("Content-type", "application/atom+xml");
    z.setRequestHeader("GData-Version", "3.0");
    z.setRequestHeader("Authorization", 'Bearer '+ token);
    z.onreadystatechange = function() {//Call a function when the state changes.
        if(z.readyState == 4 && z.status == 200) {
            alert(z.responseText);
        }
    }
    z.send(params); 

}

注意:spreadsheet_id 是我实际工作表 ID 的占位符。

【问题讨论】:

  • 表示在该网址找不到电子表格。确保您拥有正确的 URL,并且电子表格的所有者没有删除它。
  • URL 与有效的 GET 请求完全相同。所以电子表格id绝对是正确的,电子表格存在并且用户具有访问权限。但是可能设置的网址不正确?

标签: ajax google-chrome-extension xmlhttprequest google-spreadsheet-api


【解决方案1】:

遵循协议并使其发挥作用。

假设电子表格 ID 为 '1TCLgzG-AFsERoibIUOUUE8aNftoE7476TWYKqXQ0xb8'

首先使用电子表格 ID 检索工作表列表:

获取https://spreadsheets.google.com/feeds/worksheets/1TCLgzG-AFsERoibIUOUUE8aNftoE7476TWYKqXQ0xb8/private/full?alt=json

您可以在此处阅读工作表列表及其 ID。让我们使用示例中的第一个工作表。您将在 feed &gt; entry[0] &gt; link 数组中找到它的 id。寻找“rel”等于 'http://schemas.google.com/spreadsheets/2006#listfeed'

在我的示例中,此工作表的 URL 是(工作表 URL):https://spreadsheets.google.com/feeds/list/1TCLgzG-AFsERoibIUOUUE8aNftoE7476TWYKqXQ0xb8/ofs6ake/private/full

现在,要阅读其内容,请使用:

GET [工作表 URL]?alt=json

除了列表行供稿之外,您还可以找到一个“发布”网址,用于使用列表行供稿更改电子表格。这是feed &gt; link下的“rel”等于“http://schemas.google.com/g/2005#post”的那个。

碰巧它与 GET 请求的 URL 相同。就我而言:https://spreadsheets.google.com/feeds/list/1TCLgzG-AFsERoibIUOUUE8aNftoE7476TWYKqXQ0xb8/ofs6ake/private/full。请确保不要附加 alt=json。

现在,要使用列表行提要插入新行,您需要发送带有在文档中指定的有效负载的 POST。您需要发送一个以“gsx:”为前缀的列名作为标签名。但是,它可能与电子表格中的列名不同。您需要删除所有空格,使其全部小写并且没有任何国家字符。因此,要使您的示例工作,您需要将&lt;gsx:Name&gt; 替换为&lt;gsx:name&gt;。 在更改之前,您可能有以下有效负载消息:

不能写入空白行;改用删除。

这是因为 API 不理解“名称”是什么,它只是从请求中删除了这部分条目。没有它就没有更多的项目,该行是空白的。

或者,您可以从 GET 响应中读取列名。 feed &gt; entry 数组中以 gsk$ 开头的对象的键是列定义($ 符号之后的所有内容都是列名)。

================================================ ===================

编辑

回答cmets的问题。

我从你的例子中改变了两件事:

function appendRow(token){

    function constructAtomXML(foo){
        var atom = ["<?xml version='1.0' encoding='UTF-8'?>",
            '<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gsx="http://schemas.google.com/spreadsheets/2006/extended">',
            '<gsx:name>',foo,'</gsx:name>',
            '</entry>'].join('');
        return atom;
    };

    /*
    var params = {
        'body': constructAtomXML("foo")
    };
    */
    var params = constructAtomXML("foo");

    url = 'https://spreadsheets.google.com/feeds/list/'+spredsheetId+'/default/private/full?alt=json&access_token=' + token;

    var z = new XMLHttpRequest();
    z.open("POST", url, true);
    z.setRequestHeader("Content-type", "application/atom+xml");
    z.setRequestHeader("GData-Version", "3.0");
    z.setRequestHeader("Authorization", 'Bearer '+ token);
    z.onreadystatechange = function() {//Call a function when the state changes.
        if(z.readyState == 4 && z.status == 200) {
            alert(z.responseText);
        }
    }
    z.send(params); 
}

1) &lt;gsx:Name&gt;&lt;gsx:name&gt;。没有它你会收到一个错误。 2)params 对象应该是一个字符串!不是带有“body”键的对象。你只需要传递一个你想要发送到服务器的值。

【讨论】:

  • 感谢您的回复。我已经有了正确的电子表格 ID,并使用了应该可以使用的工作表 ID default。根据您的建议,我删除了 alt=json 帖子 URL 似乎仍然不起作用。还有什么我可能会丢失的吗? 发送带有有效负载的 POST 是什么意思?
  • 有效负载只是请求正文。您是否将 更改为 ?在我测试了您的请求后,它在此更改后开始工作。
  • 不幸的是,即使我将 更改为 ,它仍然无法正常工作。我仍然收到相同的 400 错误。你能过去你的代码吗?
  • 我一回到家,是的。在一个小时之内。你能告诉我什么是响应体吗?来自服务器的消息。
  • POST spreadsheets.google.com/feeds/list... 400 (Bad Request)background.js:88 appendRowbackground.js:44 (anonymous function)extensions::SafeBuiltins:19 target.(anonymous function)extensions::sendRequest :21 safeCallbackApplyextensions::sendRequest:73 handleResponse
猜你喜欢
  • 1970-01-01
  • 2016-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-23
  • 2013-05-01
  • 1970-01-01
相关资源
最近更新 更多