В Google Таблицах как сканировать все столбцы на наличие ячеек с ошибками и заменять содержимое содержимым из ячейки выше?

#javascript #google-apps-script #google-sheets

Вопрос:

У меня есть лист, на котором внизу записываются новые строки с новыми значениями каждый час или около того. Иногда вызов API вызывает некоторую ошибку. Я изменил сообщение об ошибке для loading… , но я все равно хотел бы, чтобы был способ отфильтровать эти ошибки из столбцов и заменить эти значения значениями, взятыми из ячейки чуть выше, если в этой нет ошибки.

Итак, это пример ячеек с ошибками: введите описание изображения здесь

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

Я начал с этого:

 function deleteErrors () {
let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CELL_ERRORS");
let checkRange = sheet.getRange(1, 1, sheet.getLastRow(), 2).getDisplayValues();
let rangeReversed = checkRange.reverse();
console.log(rangeReversed);
}
 

Как я могу удалить "Loading…" и заменить его значением ячейки чуть выше, если в ячейке выше нет ошибки, или в случае массива массивов со значением ниже, так как я использовал обратный. Я использовал обратный, потому что идея состоит в том, чтобы фильтровать снизу, когда строки записываются снизу.

Итак, вот как это должно выглядеть после применения правильного сценария: введите описание изображения здесь

И массив массивов должен выглядеть так: введите описание изображения здесь

Но я думаю, что этот массив массивов не так уж важен. В принципе, мне просто нужно, чтобы ячейки с Loading… ошибкой были перезаписаны значением ячейки чуть выше, если эта ячейка выше тоже Loading… , конечно, отсутствует.

Возможно ли это? Возможно, для этого есть какой-то способ использовать формулу, но я предпочитаю использовать сценарий приложений.

Я попробовал что-то вроде этого:

 function deleteErrors () {

let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CELL_ERRORS");
let checkRange = sheet.getRange(1, 1, sheet.getLastRow(), 2).getDisplayValues();
let rangeReversed = checkRange.reverse();
console.log(rangeReversed);

// Get row numbers of cells on col 1 with errors
let cellsCol1 = sheet.getRange(1, 1, sheet.getLastRow(), 1).createTextFinder("Loading…").findAll().map(x => x.getRowIndex());
console.log(cellsCol1);

// Get row numbers of cells on col 1 above the ones with error (hopefully these won't have errors!)
let okCellsCol1 = cellsCol1.map(x => x - 1);
console.log(okCellsCol1);

// Get row numbers of cells on col 2 with errors
let cellsCol2 = sheet.getRange(1, 2, sheet.getLastRow(), 2).createTextFinder("Loading…").findAll().map(x => x.getRowIndex());
console.log(cellsCol2);

// Get row numbers of cells on col 2 above the ones with error (hopefully these won't have errors!)
let okCellsCol2 = cellsCol2.map(x => x - 1);
console.log(okCellsCol2);

}
 

Это не работает, но как я могу уйти отсюда?

Мое досье: https://docs.google.com/spreadsheets/d/1ExXtmQ8nyuV1o_UtabVJ-TifIbORItFMWjtN6ZlruWc/edit?usp=sharing

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

1. «Итак, вот пример:» является ли ситуация ввода образца? Если я правильно понимаю, можете ли вы предоставить пример выходной ситуации, которую вы ожидаете, в виде изображения?

2. Хорошо, я просто отредактировал вопрос. Я надеюсь, что это более ясно.

3. Благодарим вас за ответ и предоставление примера ситуации с выводом. Из вашего обновленного вопроса я предложил ответ. Не могли бы вы, пожалуйста, подтвердить это? Если это было бесполезно, я приношу свои извинения.

Ответ №1:

  • Вы хотите добиться следующей ситуации. (Эти изображения взяты из вопроса ОП.)
    • От

    • Для

В этом случае, как насчет следующего измененного сценария?

Измененный сценарий:

 let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CELL_ERRORS");
let checkRange = sheet.getRange(1, 1, sheet.getLastRow(), 2).getDisplayValues();

// I modified below script.
const values = checkRange.map(([a, b], i, ar) => {
  if (i > 0) {
    return [a == "Loading…" ? ar[i - 1][0] : a, b == "Loading…" ? ar[i - 1][1] : b];
  }
  return [a, b];
});
console.log(values)
 

Примечание:

  • В этом измененном скрипте используется, когда 1-я строка включает Loading… Loading… . Если вы хотите заменить это другими, пожалуйста, скажите мне.

Ссылка:

Добавлен:

О How can we overwrite the values back onto the cells? и How can we overwrite the values back onto the cells? Also in my main file I have 21 columns. This will work for 2 columns. If I add the 3rd it won't do the same for the 3rd column in the array. Finally if 2 cells in a row have error (one on top of the other), the Loading… won't disappear. в комментарии я обновил приведенный выше сценарий следующим образом.

Измененный сценарий:

 let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CELL_ERRORS");
let checkRange = sheet.getRange(1, 1, sheet.getLastRow(), 3);
const currentValues = checkRange.getDisplayValues();
const transposed = currentValues[0].map((_, c) => currentValues.map(r => r[c]));
const transposedValues = transposed.map(row => {
  let temp = "";
  return row.map((e, i) => {
    if (i > 0) {
      if (e == "Loading…") {
        return temp;
      } else {
        temp = e;
      }
    } else {
      temp = e;
    }
    return e;
  });
});
const values = transposedValues[0].map((_, c) => transposedValues.map(r => r[c]));
console.log(values)
checkRange.setValues(values);
 
  • В этой модификации, я думаю, что ваши дополнительные ситуации могут быть заполнены.

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

1. @Verminous Из About Него работает на массиве.`, Я рад. Что касается ваших дополнительных ситуаций, я добавил в свой ответ еще один измененный сценарий. Не могли бы вы, пожалуйста, подтвердить это? Если это был не тот результат, которого вы ожидали, я приношу свои извинения.

2. @Verminous Спасибо, что ответили. Я должен извиниться за свое плохое знание английского языка. К сожалению, я не могу понять вашу текущую проблему с вашим дополнительным вопросом (1,1) , (100, 2) checkRange = sheet.getRange(100, 2, sheet.getLastRow(), sheet.getLastColumn()); который не используется в моем измененном сценарии и в вашем сценарии. Итак, можете ли вы предоставить подробную информацию об этом? Под этим я хотел бы попытаться понять это.

3. @Verminous Спасибо, что ответили. О sheet.getRange(6500, 2, sheet.getLastRow(), 3); , в данном случае, sheet.getLastRow() это все строки данных. В этом случае строки извлекаются от 6500 до 6500 sheet.getLastRow() . Если вы хотите получить строки данных от 6500 до последней строки, как насчет того, чтобы изменить их на sheet.getRange(6500, 2, sheet.getLastRow() - 6499, 3); ? Но если я неправильно понял ваш дополнительный вопрос, я еще раз приношу свои извинения.

4. @Verminous Кстати, в этом случае, пожалуйста, будьте осторожны с номером столбца. sheet.getRange(6500, 2, sheet.getLastRow() - 6499, 3); извлекает столбцы B, C и D.

5. @Verminous А также, о let checkRange = sheet.getRange(2, 2, sheet.getLastRow(), 3); , в данном случае, как насчет let checkRange = sheet.getRange(2, 2, sheet.getLastRow() - 1, 3); ?