Объединение столбцов с одинаковым названием

Мне нужно объединить ячейки с одинаковыми данными в строке. На прилагающемся фото красным цветом продемонстрировала, что хочу увидеть в итоге.

исходная таблица

Также объединённые ячейки хочу окрасить в Красный. Я не умею писать скрипты , но немного поизучав, смогла написать это:

function mergeSameCells() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const data = sheet.getDataRange().getValues();
  const numCols = data.length;
  const numRows = data[0].length;

  for (let j= 0; j< numCols; j++) {
    for (let i= 0; i < numRows; i++) {
      if (data[j][i] !== "") {
        let currentValue = data[j][i];
        let startCol = j;
        let endCol = j;
        while (endCol + 1 < numCols && data[endCol + 1][i] === currentValue) {
          endCol++;
        }

        if (endCol > startCol) {
          sheet.getRange(startCol + 1, i + 1, endCol - startCol + 1).merge().setBackground('#e06666');
      
        }
      }
    }
  }
}

Код работает, но не с первого раза. Также код объединяет ячейки по вертикали, то есть в столбце, а мне необходимо объединять ячейки, находящиеся в одной строке.

Вот такой результат после первого использования кода:

первый результат

Вот такой после второго:

второй результат

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


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

Автор решения: Vitalizzare ушел в монастырь

Рискну предположить, что вам не нужен скрипт. Более того, вам скорее всего не нужно объединять ячейки (Merge Cells). Объединение ячеек влечет за собой целый ряд неприятностей, с которыми вам придется считаться. Например:

  • Если вы решите убрать пару часов мероприятия, вам придется разъединит всё и заново объединить ту часть, которая актуальна.
  • Разъединение сохранит значение в левом верхнем углу, остальные ячейки нужно заполнять заново.
  • После разъединения нужно заново восстанавливать окраску фона и границ.

Скорее всего, будет достаточно добавить условное форматирование в виде окраски фона в красный цвет, если ячейка не пуста:

условное форматирование фона

Если в силу не названных соображений вы выбираете использование скрипта, то в исходном коде нужно как минимум исправить порядок обращения к строкам и столбцам - у вас он везде "навыворот". Скрипт всё ещё будет не оптимальным (вы по нескольку раз будете объединять вложенные области), но выполнит объединение двух и более непустых соседних ячеек с одинаковым значением вдоль каждой строки. Замечу, что метод merge сам по себе не надёжен и выполняется не всегда; вам может понадобиться повторный запуск программы.

function mergeSameCells() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const data = sheet.getDataRange().getValues();

  // numRows, numCols у вас выставлены не верно
  const numRows = data.length;
  const numCols = data[0].length;

  for (let j= 0; j< numCols; j++) {
    for (let i= 0; i < numRows; i++) {

      // при обращении к данным первая координата - строка, вторая - столбец
      // data[j][i] - не верно, data[i][j] - верно
      if (data[i][j] !== "") {
        let currentValue = data[i][j];
        let startCol = j;
        let endCol = j;
        while (endCol + 1 < numCols && data[i][endCol + 1] === currentValue) {
          endCol++;
        }

        if (endCol > startCol) {
          // в getRange() первые две координаты - это строка и столбец
          // левого верхнего угла, вторые две - количество строк и столбцов
          // выделяемого диапазона 
          sheet.getRange(i+1, startCol + 1, 1, endCol - startCol + 1).merge().setBackground('#e06666');
        }
      }
    }
  }
}

Чтобы решить задачу объединения по дням, каждый из которых охватывает две строки, нужно определиться, как вы будете указывать диапазон изменяемых данных. Например, вы могли бы выделить перед запуском левую верхнюю ячейку изменяемой области (в вашем примере, вероятно нужно активировать ячейку C2), используя её координаты как начало отсчета при итерации по столбцам и строкам. Код ранее исправленного скрипта меняется условно в трех местах (см. комментарии). При этом предполагается, что на странице строго одна таблица указанного типа (как минимум, ниже или справа другой таблицы нет):

function mergeSameCells() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const data = sheet.getDataRange().getValues();
  const numRows = data.length;
  const numCols = data[0].length;

  // используем активную ячейку как левый верхний угол изменяемой области
  const TopLeftCell = sheet.getActiveCell();
  const firstRow = TopLeftCell.getRow() - 1;
  const firstCol = TopLeftCell.getColumn() - 1;

  // в исходных циклах меняем начальную позицию
  // на координаты активной ячейки; вдоль строк делаем шаг 2
  for (let j = firstCol; j< numCols; j++) {
    for (let i = firstRow; i < numRows; i = i + 2) {
      if (data[i][j] !== "") {
        let currentValue = data[i][j];
        let startCol = j;
        let endCol = j;
        while (endCol + 1 < numCols && data[i][endCol + 1] === currentValue) {
          endCol++;
        }
        if (endCol > startCol) {
          // при объединении ячеек меняем третий параметр (количество строк) на двойку
          sheet.getRange(i+1, startCol + 1, 2, endCol - startCol + 1).merge().setBackground('#e06666');
        }
      }
    }
  }
}

Если на странице больше одной таблицы, то подход должен быть другим. Например, через выделение нужной области перед выполнением скрипта, замену const data = sheet.getDataRange().getValues() на const data = sheet.getActiveRange().getValues() и добавление координат верхнего левого угла выделенной области при обращении к sheet.getRange.

→ Ссылка