Как переносить строки с одного листа на другой, основываясь на содержимом ячеек?

Есть сырые данные, несколько десятков тысяч строк, вперемешку бухгалтера, аудиторы, юристы, адвокаты. Нужно отсортировать данные, основываясь на названии или описании. Например, ячейки, содержащие "двокат", будут адвокатскими кабинетами, адвокатами, коллегиями адвокатов. Я не владею языком, нагуглил несколько скриптов, пытаюсь их между собой связать, не получается.

UPD - Вот ссылка на пример того, как выглядят исходные данные

Вот текущий вариант:

var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('РФ');//указываю вкладку источник данных
var r = s.getRange('B:B');//столбец с нужными данными
var v = r.getValues();
for(var i=v.length-1;i>=1;i--)
if(v[i][0].includes("двокат")) {//содержание к переносу
console.log('deleted row ' + v[i][0]); 
var targetSheet = ss.getSheetByName('РФ адвокат');//вкладка на которую хочу перенести, до этого момента код работает

var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
sheet.getRange(range.getRow(), 1, 1, sheet.getLastColumn()).moveTo(targetRange);
sheet.deleteRow(range.getRow());
}
};

Еще час поэкспериментировал, вот этот вариант кода работает - переносит строки на новую вкладку, удаляет со старой

function moveRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ins = ss.getSheetByName('РФ');//вкладка исходник
var outs = ss.getSheetByName('РФ адвокат');//вкладка целевая
var r = ins.getRange('B:B');//диапазон вкладки исходника
var v = r.getValues();

var icRange = ins.getRange(1, ins.getLastRow()); //не понимаю, взял из другого примера
var icValues = icRange.getValues(); // получаем данные из строки
var ivRange = ins.getRange(1, 1, ins.getLastRow(), ins.getLastColumn()); //берем данные до последнего столбца
const ivValues = ivRange.getValues(); //копируем данные



for(var i=v.length-1;i>=1;i--)
if(v[i][0].includes("двокат")) {//содержание к переносу

console.log('перенос строки ' + v[i][0]); //пишем в консоль о переносе
outs.appendRow(ivValues[i]); //создаем строку в целевой вкладке
ins.deleteRow(i+1); //удаляем строку в исходной вкладке

}


}

В общем, я сам себе помог, всем спасибо! Единственное, медленно работает скрипт, 6 минут не хватает и на 1000 строк. Если есть идеи, как ускорить код - сообщите здесь, пожалуйста!

PS. Еще через пару часов я догадался - скрипт каждый раз ищет последнюю строку, а их там несколько десятков тысяч. На что заменить getLastRow, пока не знаю. Эх, жалко, что я не программист...

Написать быстро работающий код здесь я не смог (ну не программист я), из-за ограничений работы кода в 6 минут перехожу в Эксель, чтобы на моем компе все считалось...


Ответы (1 шт):

Автор решения: contributorpw

Это не совсем перенос строк, но очень простой подход:

  1. Разделить исходный массив на подходящие и нет
  2. Добавить подходящие в нужный лист
  3. Переписать исходные на неподходящие
function run() {
  const from = SpreadsheetApp.getActive().getSheetByName('РФ');
  const to = SpreadsheetApp.getActive().getSheetByName('РФ адвокат');

  const condition = (row, i) => i > 0 && /двокат/.test(row.join(' '));

  const data = splitDataByConditional_(from, condition);

  from.clearContents().getRange(1, 1, data.negative.length, data.negative[0].length).setValues(data.negative);
  to.getRange(to.getLastRow() + 1, 1, data.positive.length, data.positive[0].length).setValues(data.positive);
}

В данном случае, проверка это i > 0 && /двокат/.test(row.join(' ')) - проверяет во всей строке. А вот так проверяет только во второй колонке i > 0 && /двокат/.test(row[1])

Функция разделения

function splitDataByConditional_(sheet, condition) {
  return sheet
    .getDataRange()
    .getValues()
    .reduce(
      (acc, row, i, arr) => {
        if (condition(row, i, arr)) acc.positive.push(row);
        else acc.negative.push(row);
        return acc;
      },
      { positive: [], negative: [] }
    );
}

Обратить внимание:

  • Лист-источник перезаписывается
  • Лисе-приемник пополняется (не перезаписывается)

это сделано для примера, лист-приемник может просто перезаписываться.

Можно вообще не использовать скрипты, а использовать формулу FILTER

Пример в Таблице https://docs.google.com/spreadsheets/d/1UJBui0uCXDO-ZgF4u1IWtbBzAvOHi8hGDn5_C6mDY2E/edit?usp=sharing

→ Ссылка