【问题标题】:How to use Google sheets query or Google visualization api from apps script?如何从应用程序脚本中使用 Google 表格查询或 Google 可视化 api?
【发布时间】:2018-12-22 00:05:16
【问题描述】:

我正在使用绑定到 Google 表格的 Google 脚本以编程方式生成以下查询:

=query('16 Jul - 20 Jul Responses'!A1:I31, "SELECT C WHERE D = 'Available'", 0)

Google Scripts 中是否有任何方法可以解析该查询结果的对象表示?我希望能够编写如下代码:

var queryString = '=query('16 Jul - 20 Jul Responses'!A1:I31, "SELECT C WHERE D = 'Available'", 0)'; var results = new Query(queryString); for(var i = 0; i < results.length; i++) { var result = results[i]; // do something }

据我所知,除非您使用的是 Google Web App,否则 Query 对象不存在。这是真的?或者有没有办法实现这个想法?

【问题讨论】:

    标签: google-apps-script google-sheets google-visualization google-sheets-query google-query-language


    【解决方案1】:

    =QUERY 是一个电子表格功能。如果您想在 Apps 脚本中使用该功能,您可以利用 Google's Visualization API and Query Language。我在 GAS 中为它编写了一个自定义模块。摘录如下:

    (function(context) {
    
        const Utils = (context.Utils || (context.Utils = {}));
    
    
        /**
         * Queries a spreadsheet using Google Visualization API's Datasoure Url.
         *
         * @param        {String} ssId    Spreadsheet ID.
         * @param        {String} query   Query string.
         * @param {String|Number} sheetId Sheet Id (gid if number, name if string). [OPTIONAL]
         * @param        {String} range   Range                                     [OPTIONAL]
         * @param        {Number} headers Header rows.                              [OPTIONAL]
         */
        Utils.gvizQuery = function(ssId, query, sheetId, range, headers) {
            var response = JSON.parse( UrlFetchApp
                    .fetch(
                        Utilities.formatString(
                            "https://docs.google.com/spreadsheets/d/%s/gviz/tq?tq=%s%s%s%s",
                            ssId,
                            encodeURIComponent(query),
                            (typeof sheetId === "number") ? "&gid=" + sheetId :
                            (typeof sheetId === "string") ? "&sheet=" + sheetId :
                            "",
                            (typeof range === "string") ? "&range=" + range :
                            "",
                            "&headers=" + ((typeof headers === "number" && headers > 0) ? headers : "0")
                        ), 
                        {
                            "headers":{
                                "Authorization":"Bearer " + ScriptApp.getOAuthToken()
                            }
                        }
                    )
                    .getContentText()
                    .replace("/*O_o*/\n", "") // remove JSONP wrapper
                    .replace(/(google\.visualization\.Query\.setResponse\()|(\);)/gm, "") // remove JSONP wrapper
                ),
                table = response.table,
                rows;
    
            if (typeof headers === "number") {
    
                rows = table.rows.map(function(row) {
                    return table.cols.reduce(
                        function(acc, col, colIndex) {
                            acc[col.label] = row.c[colIndex] && row.c[colIndex].v;
                            return acc;
                        }, 
                        {}
                    );
                });
    
            } else {
    
                rows = table.rows.map(function(row) {
                    return row.c.reduce(
                        function(acc, col) {
                            acc.push(col && col.v);
                            return acc;
                        },
                        []
                    );
                });
            }
    
            return rows;
    
        };
    
        Object.freeze(Utils);
    
    })(this);
    

    只需将该模块放入您的 GAS 编辑器中自己的文件中,然后您可以按如下方式调用它:

    // result is an array of objects if header row is specified, otherwise it is an array of arrays
    var result = Utils.gvizQuery(
        "<YOUR_SPREADSHEET_ID>", 
        "<YOUR_QUERY_STRING>", 
        <SHEET_ID_IF_NEEDED>, // can be a number (the sheetId), or the name of the sheet; if not needed, but headers are, pass in undefined
        <RANGE>, // specify range, ex: `A2:O`
        <HEADER_ROW_INDEX_IF_NEEDED> // always a number
    );
    

    【讨论】:

    • 我尝试使用以下调用调用您的模块:var result = Utils.gvizQuery( ss.getId(), '=query(\'16 Jul - 20 Jul Responses\'!A1:I31, "SELECT C WHERE D = \'Not Available\'", 0)' ); 我收到此错误:TypeError: Cannot read property "rows" from undefined. (line 53, file "GViz")
    • 试试这个:var result = Utils.gvizQuery(ss.getId(), "SELECT C WHERE D ='Not Available'", "16 Jul - 20 Jul Responses", 0);
    • 这给出了同样的错误。行table = response.table 正在返回undefined。将相同的查询复制并粘贴到电子表格中可以正常工作。
    • 更新了调用以引用工作表名称。如果这不起作用,请转到 here 并发布指向您的工作表副本的链接,以便我进行故障排除。
    • @RouteMapper 很高兴听到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-05
    • 1970-01-01
    相关资源
    最近更新 更多