Пользовательская функция не обновляется при изменении входных данных - PullRequest
0 голосов
/ 04 июля 2019

У меня есть пользовательская функция, которая находит значение другой ячейки и отображает его. При изменении исходной ячейки функция не отражает.

https://docs.google.com/spreadsheets/d/1wfFe__g0VdXGAAaPthuhmWQo3A2nQtSVUhfGBt6aIQ0/edit?usp=sharing

Обновление листов Google

function findRate() {
  var accountName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(1,1).getValue(); //determine the account name to use in the horizontal search
  var rateTab = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Rates'); //hold the name of the rate tab for further dissection
  var rateNumColumns =rateTab.getLastColumn(); //count the number of columns on the rate tab so we can later create an array
  var rateNumRows = rateTab.getLastRow(); //count the number of rows on the rate tab so we can create an array
  var rateSheet = rateTab.getRange(1,1,rateNumRows,rateNumColumns).getValues(); //create an array based on the number of rows & columns on the rate tab
  var currentRow = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getActiveCell().getRow(); //gets the current row so we can get the name of the rate to search
  var rateToSearch = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(currentRow,1).getValue(); //gets the name of the rate to search on the rates tab
  for(rr=0;rr<rateSheet.length;++rr){
    if (rateSheet[rr][0]==rateToSearch){break} ;// if we find the name of the 
      }
  for(cc=0;cc<rateNumColumns;++cc){
    if (rateSheet[0][cc]==accountName){break};
      }
  var rate = rateSheet[rr][cc] ; //the value of the rate as specified by rate name and account name
  return rate;
}

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

1 Ответ

1 голос
/ 05 июля 2019
  • Вы хотите пересчитать пользовательскую функцию =findRate(), когда ячейки с именем листа Rates редактируются.

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

Решение:

Чтобы пересчитать пользовательскую функцию, в этом ответе формула =findRate() перезаписывается скриптом, запущенным с триггером события OnEdit (в данном случае это простой триггер.). Таким образом, пересчет выполняется. Но когда формула напрямую заменяется той же формулой, пересчет не выполняется. Поэтому я использовал следующий поток.

  1. Извлечь все диапазоны ячеек, имеющих формулу =findRate(), из листа «Прогнозируемый доход».
  2. Очистить формулы диапазонов.
  3. Поместите формулы в диапазоны.

С помощью этого потока при редактировании ячейки листа «Тарифы» пользовательская функция =findRate() пересчитывается путем автоматического запуска onEdit().

Пример сценария:

Пожалуйста, скопируйте и вставьте следующий скрипт в редактор скриптов. Затем, пожалуйста, отредактируйте ячейки имени листа Rates. При этом onEdit() автоматически запускается триггером события OnEdit.

function onEdit(e) {
  var range = e.range;
  if (range.getSheet().getSheetName() == "Rates" && range.rowStart > 1 && range.columnStart > 1) {
    var sheetName = "Projected Revenue"; // If you want to change the sheet name, please modify this.
    var formula = "=findRate()";// If you want to change the function name, please modify this.

    var sheet = e.source.getSheetByName(sheetName);
    var ranges = sheet.createTextFinder(formula).matchFormulaText(true).findAll().map(function(e) {return e.getA1Notation()});
    sheet.getRangeList(ranges).clearContent();
    SpreadsheetApp.flush();
    sheet.getRangeList(ranges).setFormula(formula);
  }
}

Примечание:

  • onEdit(e) запускается триггером события OnEdit. Поэтому при непосредственном запуске onEdit(e) возникает ошибка. Пожалуйста, будьте осторожны с этим.
  • В этом примере сценария, в качестве примера, даже при редактировании строки 1 и столбца «А» листа «Тарифы» пользовательская функция не пересчитывается. Если вы хотите изменить это и указать ограничение диапазона, который хотите редактировать, измените приведенный выше скрипт.

Ссылки:

Если я неправильно понял ваш вопрос, и это был не тот результат, которого вы хотите, я прошу прощения.

Добавлено:

Предложение от Комментарий TheMaster было отражено в сценарии. Когда можно использовать sheet.createTextFinder(formula).matchFormulaText(true).replaceAllWith(formula), я также думаю, что стоимость процесса будет значительно снижена. Но в моей среде казалось, что формулы необходимо очищать один раз, чтобы обновить пользовательскую функцию, даже если используется flush(). Поэтому я предложил выше поток.

Но теперь я мог заметить обходной путь, используя replaceAllWith() TextFinder. Поэтому я хотел бы добавить это. Ход этого обходного пути выглядит следующим образом.

  1. Заменить все значения =findRate() значением в листе Projected Revenue, используя replaceAllWith() ..
    • В этом случае в качестве тестового примера формулы заменяются на sample.
  2. Заменить sample на =findRate(), используя replaceAllWith().

Этим потоком я могу подтвердить, что =findRate() пересчитан. А также, похоже, что flush() не требуется для этой ситуации.

Пример сценария:

Пожалуйста, скопируйте и вставьте следующий скрипт в редактор скриптов. Затем отредактируйте ячейки с именем листа Rates. При этом onEdit() автоматически запускается триггером события OnEdit.

function onEdit(e) {
  var range = e.range;
  if (range.getSheet().getSheetName() == "Rates" && range.rowStart > 1 && range.columnStart > 1) {
    var sheetName = "Projected Revenue";
    var formula = "=findRate()";
    var tempValue = "sample";

    var sheet = e.source.getSheetByName(sheetName);
    sheet.createTextFinder(formula).matchFormulaText(true).replaceAllWith(tempValue);
    sheet.createTextFinder(tempValue).matchFormulaText(true).replaceAllWith(formula);
  }
}
...