如何获得Row& A1Notation的列值

时间:2015-05-07 22:09:14

标签: javascript google-apps-script google-sheets

有时候为Google电子表格编写脚本很困难,因为采用行编号和列编号的Google电子表格方法使用基于1的索引,而Javascript数组使用从0开始。

screenshot

在此示例中,单元格A2包含row == 2column == 1。 SpreadsheetApp方法反向列&从A1Notation中的行开始,因此这两个范围是等价的:

var range1 = sheet.getRange("A2");
var range2 = sheet.getRange(2, 1);

一旦我将一张纸的内容读入一个数组,事情就会再次发生变化。

var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var data = sheet.getDataRange().getValues();

之后,我的电子表格中单元格A2中的值位于data[1][0]。排&列的顺序与SpreadsheetApp API的顺序相同,但每个只有1个。

screenshot 2

这里有很多问题的答案(example)归结为这些不同形式的索引不匹配。充满row+1col-1语句的代码可能很难调试。

最后:如果我知道A1Notation中单元格的引用,比如说AZ342,我怎样才能找到与2D数组中该单元格对应的正确索引值{{ 1}},从完整的数据范围获得?

2 个答案:

答案 0 :(得分:6)

显然,你可以非常小心地跟踪你使用任何一种索引类型的地方,你会没事的。

但做这样的事情会更容易:

var importantCell = "AZ342";
var cellIndexConverted = cellA1ToIndex( importantCell );
var data[cellIndexConverted.row][cellIndexConverted.col] = "Some new value";

ConvertA1.gs

以下是三个辅助函数,可简化A1Notation的转换。

这些辅助函数也是available as a gist

/**
 * Convert a cell reference from A1Notation to 0-based indices (for arrays)
 * or 1-based indices (for Spreadsheet Service methods).
 *
 * @param {String}    cellA1   Cell reference to be converted.
 * @param {Number}    index    (optional, default 0) Indicate 0 or 1 indexing
 *
 * @return {object}            {row,col}, both 0-based array indices.
 *
 * @throws                     Error if invalid parameter
 */
function cellA1ToIndex( cellA1, index ) {
  // Ensure index is (default) 0 or 1, no other values accepted.
  index = index || 0;
  index = (index == 0) ? 0 : 1;

  // Use regex match to find column & row references.
  // Must start with letters, end with numbers.
  // This regex still allows induhviduals to provide illegal strings like "AB.#%123"
  var match = cellA1.match(/(^[A-Z]+)|([0-9]+$)/gm);

  if (match.length != 2) throw new Error( "Invalid cell reference" );

  var colA1 = match[0];
  var rowA1 = match[1];

  return { row: rowA1ToIndex( rowA1, index ),
           col: colA1ToIndex( colA1, index ) };
}

/**
 * Return a 0-based array index corresponding to a spreadsheet column
 * label, as in A1 notation.
 *
 * @param {String}    colA1    Column label to be converted.
 *
 * @return {Number}            0-based array index.
 * @param {Number}    index    (optional, default 0) Indicate 0 or 1 indexing
 *
 * @throws                     Error if invalid parameter
 */
function colA1ToIndex( colA1, index ) {
  if (typeof colA1 !== 'string' || colA1.length > 2) 
    throw new Error( "Expected column label." );

  // Ensure index is (default) 0 or 1, no other values accepted.
  index = index || 0;
  index = (index == 0) ? 0 : 1;

  var A = "A".charCodeAt(0);

  var number = colA1.charCodeAt(colA1.length-1) - A;
  if (colA1.length == 2) {
    number += 26 * (colA1.charCodeAt(0) - A + 1);
  }
  return number + index;
}


/**
 * Return a 0-based array index corresponding to a spreadsheet row
 * number, as in A1 notation. Almost pointless, really, but maintains
 * symmetry with colA1ToIndex().
 *
 * @param {Number}    rowA1    Row number to be converted.
 * @param {Number}    index    (optional, default 0) Indicate 0 or 1 indexing
 *
 * @return {Number}            0-based array index.
 */
function rowA1ToIndex( rowA1, index ) {
  // Ensure index is (default) 0 or 1, no other values accepted.
  index = index || 0;
  index = (index == 0) ? 0 : 1;

  return rowA1 - 1 + index;
}

答案 1 :(得分:0)

我想发布另一个解决方案,因为我通常考虑使用循环而不是检查其长度来转换字符串。

function convertSheetNotation(a1_notation) {
    const match = a1_notation.match(/(^[A-Z]+)|([0-9]+$)/gm);

    if (match.length !== 2) {
        throw new Error('The given value was invalid. Cannot convert Google Sheet A1 notation to indexes');
    }

    const column_notation = match[0];
    const row_notation = match[1];

    const column = convertColumnNotationToIndex(column_notation);
    const row = convertRowNotationToIndex(row_notation);

    return [row, column];
}

function convertColumnNotationToIndex(a1_column_notation) {
    const A = 'A'.charCodeAt(0);

    let output = 0;
    for (let i = 0; i < a1_column_notation.length; i++) {
        const next_char = a1_column_notation.charAt(i);
        const column_shift = 26 * i;

        output += column_shift + (next_char.charCodeAt(0) - A);
    }

    return output;
}

function convertRowNotationToIndex(a1_row_notation) {
    const num = parseInt(a1_row_notation, 10);
    if (Number.isNaN(num)) {
        throw new Error('The given value was not a valid number. Cannot convert Google Sheet row notation to index');
    }

    return num - 1;
}

感谢@Mogsdad,因为这是对您答案的一个小修改,尽管我认为我的解决方案效率较低。