【问题标题】:Javascript extract subarray from 2D array using spreadsheet range A1 notationJavascript使用电子表格范围A1表示法从二维数组中提取子数组
【发布时间】:2019-10-24 10:54:56
【问题描述】:

在众多Google Apps Script best practices中,对于脚本性能的提升,建议尽量减少对其他服务的调用:

在脚本中使用 JavaScript 操作比调用其他服务要快得多。您可以在 Google Apps 脚本本身内完成的任何操作都比进行需要从 Google 的服务器或外部服务器获取数据的调用(例如对电子表格、文档、站点、翻译、UrlFetch 等的请求)要快得多。如果您能找到将脚本对这些服务的调用降至最低的方法,您的脚本将会运行得更快。

因此,在处理电子表格上的 GAS 时,通常的做法是将工作表中的值作为一个整体复制到二维数组中,对数组进行所有操作,然后将数组中的所有数据刷新回工作表。

一旦您将工作表中的所有数据复制到二维数组中,处理列可能会很棘手,尤其是对于大型列集,因此使用使用 A1 从二维数组中提取/设置数据的函数可能会很方便表示法,因为这允许在工作表上直观地确定正确的范围是什么,同时使用 Javascript 转码函数来相应地识别列和行。

在没有重新发明轮子的情况下,我想知道是否有人编写了一些代码来从二维数组中提取数据作为子数组,使用电子表格范围 A1 表示法来引用子数组的边界。

例如,假设一个自定义函数getRange

var SS = SpreadsheetApp.openById(myID); // open spreadsheet
var sheet = SS.getSheetByName("Test"); // get sheet
var sheetValues = sheet.getSheetValues(1,1,-1,-1); // copy all values from sheet to 2D array

// samples: how the function could be invoked to extract subarray using A1 notation 
var subArray = getRange(sheetValues, "A2:A"); // returns a "column" from the array begin at row 2
subArray = getRange(sheetValues, "A2"); // returns a "cell" from the array (1,0)
subArray = getRange(sheetValues, "B2:D3"); // returns a 2D subarray

类似于this

编辑:

我从another similar post 复制了以下代码,现在我已经正确设置了参数:

var matrix = [
          ["a1", "b1", "c1", "d1"],
          ["a2", "b2", "c2", "d2"],
          ["a3", "b3", "c3", "d3"],
          ["a4", "b4", "c4", "d4"]
        ]
var startRow = 1
var startCol = 0
var endRow = 2
var endCol = 0

var section = matrix.slice(startRow, endRow + 1).map(i => i.slice(startCol, endCol + 1))
console.log(JSON.stringify(section))

我会进一步研究A1转码!

【问题讨论】:

    标签: javascript arrays google-apps-script multidimensional-array google-sheets


    【解决方案1】:

    我已经开始工作了,结合了来自here 的 sn-p。

    这是最终代码,可能会进一步优化(并且需要输入数据验证)。

    var matrix = [
       ["a1", "b1", "c1", "d1"],
       ["a2", "b2", "c2", "d2"],
       ["a3", "b3", "c3", "d3"],
       ["a4", "b4", "c4", "d4"]
    ]
    
    console.log("getRange('a2:2') returns:\n" + JSON.stringify(getRange("a2:2")));
    
    function getRange(textRange) {
       var startRow, startCol, endRow, endCol;
       var range = textRange.split(":");
       var ret = cellToRoWCol(range[0]);
       startRow = ret[0]
       startCol = ret[1]
       if (startRow == -1) {
          startRow = 0;
       }
       if (startCol == -1) {
          startCol = 0;
       }
    
       if (range[1]) {
          ret = cellToRoWCol(range[1]);
          endRow = ret[0]
          endCol = ret[1]
          if (endRow == -1) {
             endRow = matrix.length;
          }
          if (endCol == -1) {
             endCol = matrix.length;
          }
       } else { // only one cell
          endRow = startRow
          endCol = startCol
       }
    
       return matrix.slice(startRow, endRow + 1).map(function(i) {
          return i.slice(startCol, endCol + 1);
       });
    }
    
    function cellToRoWCol(cell) {
       // returns row & col from A1 notation
       var row = cell.replace(/[^0-9]+/g, '');
       var letter = cell.replace(/[^a-zA-Z]+/g, '').toUpperCase();
    
       var column = 0,
          length = letter.length;
       for (var i = 0; i < length; i++) {
          column += (letter.charCodeAt(i) - 64) * Math.pow(26, length - i - 1);
       }
    
       row = Number(row) - 1;
       column--;
    
       return [row, column];
    }

    【讨论】:

      【解决方案2】:

      从你的问题中我可以理解,一种从范围中提取子数组的简单方法:

      示例 1:

      var subarray = sheet.getRange('B1:E1').getValues()[0];
      

      现在,假设您在该行中有值,并且因为它只是一行,您实际上并不需要它作为另一行中的数组,因此将 [0] 您可以将子数组作为 一维数组.

      要返回一列,您可以使用上面的相同示例,但要更改类似这样的范围

      示例 2:

      var subarray = sheet.getRange('A2:A5').getValue();
      

      如果你只想指定一个单元格,你可以使用

      示例 3:

      var subarray = sheet.getRange('A5').getValue();
      

      编辑:

      我可以在您的问题中看到您找到了一种获取行的方法。我会给你一个函数来获取你想要的列在某个位置

      function getRangeCol(two_d, colPosition, rowToStart) {
          var col = two_d.map(function(value, index) { 
            if(rowToStart <= index)
            return value[colPosition]; 
          }).filter(function (el) {
            return el != null;
          });
          Logger.log(col);
      }
      
      

      如果这对你有帮助,请告诉我

      【讨论】:

      • 谢谢 Alberto,但目标是不要使用原生 GAS 函数来提高脚本速度
      • 哦,好的,所以您想要的是使用您的var sheetValues = sheet.getSheetValues(1,1,-1,-1); 从您的工作表中获取所有值,并以此避免使用 GAS 函数,然后使用 JavaScript 调用自定义函数来获取值矩阵sheetValues,我做对了吗?
      • 没错!我认为使用数组存储工作表值并允许使用 A1 表示法从主数组中获取数据会更快。会提高代码的可读性
      • 我很高兴它对你有用!您能否考虑给我的答案点赞,以便更多人可以轻松看到它?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 2020-07-12
      • 1970-01-01
      • 1970-01-01
      • 2016-06-11
      • 2013-02-16
      • 1970-01-01
      相关资源
      最近更新 更多