Как выровнять только видимые (нефильтрованные) ячейки в Google App script / Google sheets?

#google-apps-script #google-sheets

#google-приложения-скрипт #google-таблицы

Вопрос:

В настоящее время у меня есть базовая электронная таблица: https://docs.google.com/spreadsheets/d/1nlLdD48PfqrhyQzmJrhx_Tlw73C194YUqKeRkXoCOLg/edit?usp=sharing , и я создал скрипт, который выравнивает значения формул в электронной таблице:

   function freezeValues() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('Sheet1');  // or whatever name
  var range = sheet.getRange("A2:C");    // assuming data appears in A2-C 
  range.copyTo(range, {contentsOnly: true});
}
 

Проблема с моим текущим скриптом заключается в том, что он выравнивает все формулы, даже если строка скрыта фильтром, есть ли способ отредактировать мой скрипт так, чтобы он выравнивал только видимые ячейки?

Я обнаружил, что эта операция для Google app script isRowHiddenByFilter, но я не уверен, как я мог бы поместить ее в свой текущий скрипт.

P.S. Я, скорее всего, буду использовать это для разных фильтров, поэтому не ищу обходного пути. Например, если вы посмотрите на мой пример электронной таблицы, я бы не хотел, чтобы в скрипте приложения указывалось «цвет фона = белый» и т. Д.)

Ответ №1:

Вы можете перебирать все строки и запрашивать, скрыто ли это перед копированием

Пример

 function freezeValues() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('Sheet1');  // or whatever name
  var firstRow = 2;
  var firstColumn = 1;
  var lastColumn = 3;
  var range = sheet.getRange(firstRow, firstColumn, sheet.getLastRow() - firstRow   1, lastColumn - firstColumn  1);    // assuming data appears in A2-C 
  var rowHeight = range.getHeight();
  for (var i = 0; i < rowHeight; i  ){
    if(!sheet.isRowHiddenByFilter((firstRow i))){
      var row = sheet.getRange((firstRow i), firstColumn, 1, lastColumn - firstColumn  1);
      row.setValues(row.getValues());
    }
  }
}
 

Этот пример копирует нескрытые строки одну за другой, поэтому имеет смысл использовать метод setValues() вместо copyTo()

Комментарии:

1. О, я вижу, это отлично работает. Один быстрый вопрос, если все в порядке, если я использую его на листе большего размера (20 тысяч строк), как вы думаете, все будет в порядке или это будет действительно плохо с точки зрения производительности?

2. Для такого объема данных более эффективно использовать forEach() цикл. Кроме того, в этом случае лучше сократить количество звонков setValues() . Поэтому, если вы не возражаете потратить некоторое время на оптимизацию кода, возможно, имеет смысл создать временный массив, вставив vlaues в этот массив ` if(!sheet. isRowHiddenByFilter((firstRow i)))` и формулы в else инструкции. А затем верните массив обратно в лист одним вызовом.