it-swarm.com.ru

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

У меня есть таблица данных табеля 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$7,$C$8), в которой указывается имя листа для месяца и количество столбцов для каждого клиента (в случае изменения схемы).

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

12
Whelkaholism

Вам не хватает привередливого кеширования ошибка особенность. Это работает так:

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

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

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

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

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

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

32
Henrique G. Abreu

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

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

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

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

Я использую фиктивную переменную в функции, эта переменная ссылается на ячейку в электронной таблице, тогда у меня есть сценарий Myfunction (), который записывает число Math.Ramdon в этой ячейке. Эта "MyFunction" находится в службе триггеров (триггеры редактирования/текущего проекта), и вы можете выбрать разные триггеры событий, например, при открытии или по времени, там вы можете выбрать, например, период времени от 1 минуты до месяца.

1
Paulino Seoane

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

есть фиктивная переменная в вашем методе. проходить

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

в качестве значения этого параметра.

например.

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

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

1
Chamil

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

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

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

а) Очистить кеш документов

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

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

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

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

  • установить офулу

г) Установите ячейку в (1) со значением "Готово"

Это обновляет нужные биты, НО IS НЕ БЫСТРО.

0
andrewdb

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

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

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

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

    функция сумматора (база) {Utilities.sleep (5000); возврат базы + 10; }

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

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

  1. проблема, упомянутая в этой теме, остается, мое тестирование показывает, что лист Google каждый раз пересчитывает пользовательскую функцию ТОЛЬКО КОГДА

    • значение ПРЯМО, вызванное функцией, изменено.

    function getCellValue (sheetName, row, col) {var ss = SpreadsheetApp.getActiveSpreadsheet (); var sh = ss.getSheetByName (sheetName); return sh.getRange (row, col) .getValue (); }

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

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

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

0
theworldismyoyster