Google表格中的自定义排序行,同时保留格式

时间:2018-03-26 20:25:46

标签: google-apps-script google-sheets

我试图找出一种方法,除了升序/降序之外,还按照特定顺序对Google电子表格中的数据进行排序。我可以通过使用Range.getValues()获取2D数组,对其进行排序,然后使用Range.setValues()来实现此目的。

但问题在于它只是复制数据,对数据进行排序,并将数据粘贴到旧数据上。因此,如果我将A1突出显示为红色,并且通过对范围值进行排序将数据移至B2,则不会将红色突出显示为红色,而使用放在其中的任何内容的A1将突出显示为红色。

是否有任何方法可以实际排序范围并使用格式移动行,并且所有内容仍然完好无损。

1 个答案:

答案 0 :(得分:1)

强制使用Range.sort进行任意排序的方法是在范围中附加临时列并将其用于排序。可以动态插入列,然后将其删除,以避免损坏正在排序的范围旁边的数据。

以下是按内容长度对A2:A7进行排序的示例。

function sortRangeByLength() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var range = sheet.getRange("A2:A7");
  sheet.insertColumnAfter(range.getLastColumn());
  var keys = range.getValues().map(function(row) {
    return [row[0].length];
  });
  range.offset(0, range.getNumColumns(), range.getNumRows(), 1).setValues(keys);
  var extendedRange = range.offset(0, 0, range.getHeight(), range.getWidth() + 1);
  extendedRange.sort({"column": extendedRange.getWidth(), "ascending": true});
  range.offset(0, 1).clear();
  sheet.deleteColumn(extendedRange.getLastColumn());  
}

范围extendedRangerange,附加列,用于排序然后删除。在要删除的列上调用clear可能看起来多余,但它可以防止不需要的格式化扩散到右侧的列(插入到范围右侧的列继承其格式)。

对于某些种类,可能没有明显的键,只有比较功能。在这种情况下,可以通过比较函数计算密钥,如下所示:

function sortRangeByLength() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var range = sheet.getRange("A2:A7");
  sheet.insertColumnAfter(range.getLastColumn());

  // begin computing the keys
  var indexed = range.getValues().map(function(row, i) {
    return {"index": i, "content": row};
  });
  indexed.sort(function(a, b) {
    return (a.content[0].length < b.content[0].length ? -1 : (a.content[0].length > b.content[0].length ? 1 : 0));
  });
  var keys = Array(indexed.length);
  for (i in indexed) {
    keys[indexed[i].index] = [i];
  }

  // proceed as before
  range.offset(0, range.getNumColumns(), range.getNumRows(), 1).setValues(keys);
  var extendedRange = range.offset(0, 0, range.getHeight(), range.getWidth() + 1);
  extendedRange.sort({"column": extendedRange.getWidth(), "ascending": true});
  range.offset(0, 1).clear();
  sheet.deleteColumn(extendedRange.getLastColumn());  
}

该方法是标准的:创建了一个“索引”数组,其中包含每行的数据和索引。根据您的算法对此数组进行排序。由此产生的索引排列显示了哪一行去了哪里。它需要被反转成为“按此升序排序”的关键列。此反转为keys[indexed[i].index] = [i];