Почему copyTo (... PASTE_VALUES) не работает в середине макроса? - PullRequest
0 голосов
/ 05 мая 2018

Один из моих давних методов работы с электронными таблицами - это специальные значения копирования / вставки (C / PSV). Используя формулы для получения значений, которые меня интересуют, я делаю C / PSV и могу затем удалить исходные данные.

Итак, я написал макрос, который использует эту технику, но клетки оказываются пустыми. Но если я разделю макрос на два, заканчивая первый макрос перед C / PSV, то все будет работать так, как задумано. Почему это? Есть ли лучший способ обойти эту проблему? Вот мои три макроса.

function Step1() {
  var spreadsheet = SpreadsheetApp.getActive();
  var range = spreadsheet.getActiveRange();
  CopyRangeToNewSheet(spreadsheet, range);
  spreadsheet.getCurrentCell().offset(-1, 6).activate();
  FillInHeaders(spreadsheet);
  spreadsheet.getCurrentCell().offset(1, -4).activate();
  FillInFormulas(spreadsheet);
  spreadsheet.getCurrentCell().offset(0, -4, range.getNumRows(), 5).activate();
  spreadsheet.getCurrentCell().offset(0, 0, 1, 5).copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
};

function Step2() {
  var spreadsheet = SpreadsheetApp.getActive();
  var keepers = spreadsheet.getRange('G:J');
  keepers.activate();
  keepers.copyTo(keepers, SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
  var discard = spreadsheet.getRange('A:F')
  discard.activate();
  spreadsheet.getActiveSheet().deleteColumns(discard.getColumn(), discard.getNumColumns());
};

function BothSteps() {
  var spreadsheet = SpreadsheetApp.getActive();
  var range = spreadsheet.getActiveRange();
  CopyRangeToNewSheet(spreadsheet, range);
  spreadsheet.getCurrentCell().offset(-1, 6).activate();
  FillInHeaders(spreadsheet);
  spreadsheet.getCurrentCell().offset(1, -4).activate();
  FillInFormulas(spreadsheet);
  spreadsheet.getCurrentCell().offset(0, -4, range.getNumRows(), 5).activate();
  spreadsheet.getCurrentCell().offset(0, 0, 1, 5).copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
  var keepers = spreadsheet.getRange('G:J');
  keepers.activate();
  keepers.copyTo(keepers, SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
  var discard = spreadsheet.getRange('A:F')
  discard.activate();
  spreadsheet.getActiveSheet().deleteColumns(discard.getColumn(), discard.getNumColumns());
};

function FillInHeaders(spreadsheet) {
  spreadsheet.getCurrentCell().setValue('First Name');
  spreadsheet.getCurrentCell().offset(0, 1).activate();
  spreadsheet.getCurrentCell().setValue('Last Name');
  spreadsheet.getCurrentCell().offset(0, 1).activate();
  spreadsheet.getCurrentCell().setValue('Middle Name');
  spreadsheet.getCurrentCell().offset(0, 1).activate();
  spreadsheet.getCurrentCell().setValue('Email');
}

function FillInFormulas(spreadsheet) {
  spreadsheet.getCurrentCell().setFormulaR1C1('=find(" ",R[0]C[-2])');
  spreadsheet.getCurrentCell().offset(0, 1).activate();
  spreadsheet.getCurrentCell().setFormulaR1C1('=if(iserr(R[0]C[-1]),R[0]C[-3],mid(R[0]C[-3],1,R[0]C[-1]))');
  spreadsheet.getCurrentCell().offset(0, 1).activate();
  spreadsheet.getCurrentCell().setFormulaR1C1('=if(iserr(R[0]C[-2]),"",mid(R[0]C[-4],R[0]C[-2]+1,50))');
  spreadsheet.getCurrentCell().offset(0, 2).activate();
  spreadsheet.getCurrentCell().setFormulaR1C1('=R[0]C[-5]');
}

function CopyRangeToNewSheet(spreadsheet, range) {
  var newSheet = spreadsheet.insertSheet(1);
  spreadsheet.setActiveSheet(newSheet, true);  
  spreadsheet.getCurrentCell().offset(1, 0).activate();
  range.copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
}

Вот сама таблица с вкладками Основная, Результат шага 1, Шаг 2 и Результат комбинированных шагов: https://docs.google.com/spreadsheets/d/1_nabq_mHuegz_eMIPPAlIgonv71Jh6OPi6qKzeNGGTI/edit?usp=sharing

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

Столкнулся с аналогичной проблемой (например, копирование результата вычисления из одного диапазона ячеек в другой диапазон, в котором мне нужен был только один результат без формул), с использованием {contentsOnly:true} вместо SpreadsheetApp.CopyPasteType.PASTE_VALUES. 1003 *

0 голосов
/ 06 мая 2018

SpreadsheetApp.flush(), вероятно, недостающий шаг в вашем макросе. По сути, Apps Script оптимизирует внутреннее чтение и запись, и если вы не вызываете этот метод, он может делать все по-своему.

Добавление этого, где вы в настоящее время разделяете свою задачу на «Макрос 1» и «Макрос 2», должно решить проблему:

...
  spreadsheet.getCurrentCell().offset(0, 0, 1, 5).copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
  // Force formulas to calculate and pending writes to be written.
  SpreadsheetApp.flush();
  // Read formula results and save as values.
  var keepers = spreadsheet.getRange('G:J');
...

Дополнительным методом будет сжатие ваших сценариев из «транзакционного» подхода записанного макроса к пакетному / эффективному представлению «большой картинки» с использованием setValues() вместо copyTo:

...
  SpreadsheetApp.flush();
  var toKeep = spreadsheet.getRange('G:J');
  toKeep.setValues(toKeep.getValues());
  toKeep.getSheet().deleteColumns(1, toKeep.getColumn() - 1);
}

Обратите внимание, что вы все еще хотите позвонить на .flush().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...