Скрипт для суммирования данных не обновляется

у меня есть таблица Google данных расписания; он имеет лист для каждого месяца, каждый лист много шести блоков столбцов, один блок на клиента.

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

function getClientTotals(sheetname, colcount)
{  
  colcount = colcount ? colcount : 6;
  var res;      
  var ss = SpreadsheetApp.openById('myid_goes_here');
  if(ss)
  {
    res = [];
    var totrow = ss.getRange(sheetname + '!A1:ZZ1').getValues()[0];
    for(var i = 0; i < totrow.length; i += colcount)
    {
      res.push([totrow[i], totrow[i + colcount - 1]]);
    }
  }   
  return res;
}

Я только что добавил ячейку в мой сводный лист, содержащий =getClientTotals($C,$C) который проходит в названии листа за месяц и количество столбцов для каждого клиента (в случае " схемы" варианта исполнения.

все работает нормально, однако, она не обновляется при изменении исходных данных. Я добавил onEdit триггер; никакой радости. Он обновляется, если вы идете в редактор сценариев и нажимаете Save, но это не полезно. Я что-то упускаю?

8 ответов


вам не хватает привередливого кэширования ошибка характеристика. Он работает следующим образом:

Google считает, что все пользовательские функции зависят только на их значениях параметров сразу для того чтобы возвратить их результат (вы можете выборочно зависеть от других статических данных).

учитывая это условие, они могут оценивать ваши функции только при изменении параметра. например,

предположим, что у нас есть текст "10" на ячейке B1, а затем на какой - то другой ячейке мы типа =myFunction(B1)

myFunction будет оценена и ее результат будет получен. Затем, если вы измените значение ячейки B1 на "35", custom будет повторно оценен, как ожидалось, и новый результат будет получен нормально. Теперь, если вы снова измените ячейку B1 на исходную "10", повторной оценки не будет, исходный результат будет немедленно получен из кэша.

Итак, когда вы используете имя листа в качестве параметра для его динамического извлечения и возврата результата, вы нарушаете кэширование правило.

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


другое решение проблемы кэширования.

есть переменная в методе. пас

Filter(<the cell or cell range>,1=1)

Как значение этого параметра.

например

=getValueScript("B1","B4:Z10", filter(B4:Z10,1=1))

выход фильтра не используется. однако это указывает на электронную таблицу, что эта формула чувствительна к диапазону B4:Z10.


у меня была аналогичная проблема создания панели мониторинга для работы. Решение Chamil выше (а именно, использование функции фильтра листа, переданной как значение фиктивной переменной в вашей функции) работает просто отлично, несмотря на более недавний комментарий от Arsen. В моем случае я использовал функцию для мониторинга диапазона и не мог использовать фильтр в том же диапазоне, поскольку он создал круговую ссылку. Поэтому у меня просто была ячейка (в моем случае E45 в коде ниже), в которой я менял номер в любое время, когда хотел свою функцию обновление:

=myFunction("E3:E43","D44",filter(E45,1=1))

Как указал Шамиль, фильтр не используется в скрипте:

function myFunction(range, colorRef, dummy) {
  variable 'dummy' not used in code here
}

Я использую фиктивную переменную в функции, эта переменная относится к ячейке в электронной таблице тогда y имеет Myfunction () в скрипте, который пишет математику.Количество Ramdon в этой ячейке. Эта "MyFunction" находится под службой триггеров (Edit / Current Project Triggers), и вы можете выбрать разные триггеры событий, например On-Open или time driven, там вы можете выбрать, например, период времени, от 1 минуты до месяца


Что вы можете сделать, это настроить другую ячейку где-то в электронной таблице, которая будет обновляться каждый раз, когда добавляется новый лист. Убедитесь, что он не обновляется для каждого изменения, но только тогда, когда вы хотите сделать расчет (в вашем случае, когда вы добавляете лист). Затем вы передаете ссылку на эту ячейку своей пользовательской функции. Как уже упоминалось, пользовательская функция может игнорировать этот параметр.


учитывая эту функцию, объясненную Энрике Абреу, вы можете попробовать стандартные функции электронной таблицы запрос, что SQL liked query-это то, что я часто использую в работе на необработанных данных и получить данные в виде сводки на другую вкладку, результирующие данные обновляются в режиме реального времени после изменения необработанных данных.

мое предложение основано на том, что ваш скрипт не имеет расширенной работы, такой как URL fetch, просто работа с данными, так как без фактического чтения данных я не могу дать точную решение с запросом.

о кэш упомянутый Энрике Абреу (у меня недостаточно репутации, чтобы комментировать непосредственно под его ответом), я сделал тестирование и обнаружил, что:

  1. looks нет работы кэша, скрипт функции тестирования, показанный ниже:

    сумматор функции (основание) { Коммунальные услуги.сон(5000); возвращение базы + 10; }

применение этого настраиваемого сумматора функций () в листе путем вызова ячейка, а затем изменил это значение ячейки вперед и назад, каждый раз, когда я вижу сообщение загрузки и общее время более 5 секунд. Это может быть связано с обновлением, упомянутым в этом газовый вопрос:

эта проблема теперь исправлена. Пользовательские функции на новых листах теперь осознают контекст и не кэшируют значения так агрессивно.

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

    • изменяется значение, непосредственно вызываемое функцией.

    функция getCellValue(sheetName, row, col) { ВАР СС= SpreadsheetApp.getActiveSpreadsheet(); var sh = ss.getSheetByName(sheetName); возвращение sh.getRange (row, col).метод GetValue(); }

    enter image description here
    Изменение любого значения в желтых ячейках приведет к пересчету пользовательской функции; реальное изменение значения источника данных игнорируется функцией.

    • функция, содержащая местоположение ячейки, изменяется в листе. бывший. вставить / удалить строку / столбец сверху или слева.

Я не хотел иметь фиктивный параметр. YMMV на этом.

1 ячейка, которая является "списком элементов", одна из которых "обновить"

2 скрипт с 'onEdit', если ячейка "обновить":

a) очистить кэш документов

b) заполните кэш doc внешними данными (таблица в моем случае)

c)для всех ячеек с моим ' getStockoData(...'пользовательская функция

  • получим формулу

  • установить '=0'

  • установить fromula

d) установите ячейку в (1) со значением "Ready"

Это обновляет биты, которые вы хотите, но не быстро.


Как сказал @Brionius, поместите дополнительный динамический аргумент в функцию. если вы используете now (), у вас могут возникнуть проблемы с таймаутом, сделайте обновление немного медленнее...

cell A1 = int(now()*1000)
cell A2 = function(args..., A1)