Скрипт для суммирования данных не обновляется - PullRequest
12 голосов
/ 26 января 2012

У меня есть таблица данных табеля 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 триггер; нет радости Он обновляется, если вы идете в редактор сценариев и нажимаете Сохранить, но это бесполезно. Я что-то упустил?

Ответы [ 9 ]

34 голосов
/ 26 января 2012

Вам не хватает привередливой функции кэширования bug . Это работает так:

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

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

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

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

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

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

1 голос
/ 04 сентября 2018

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

1 голос
/ 28 января 2016

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

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

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

function myFunction(range, colorRef, dummy) {
  variable 'dummy' not used in code here
}
1 голос
/ 21 марта 2014

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

имеет фиктивную переменную в вашем методе.передайте

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

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

например,

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

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

0 голосов
/ 06 июня 2019

Поскольку скрипт приложения Google является расширением JS, функции должны иметь возможность обрабатывать больше аргументов, чем определено в сигнатуре функции, или меньше. Так что если у вас есть какая-то функция, как

function ADD(a, b) {
  return CONSTANTS!$A$1 + a + b
}

тогда вы бы назвали этот функционал как

=ADD(A1, B1, $A$2)

где $ A $ 2 - это какой-то флажок (вставка -> флажок), который можно нажать, чтобы «обновить» после того, как вам нужно изменить значение из листа и ячейки.

0 голосов
/ 25 апреля 2018

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

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

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

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

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

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

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

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

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

d) Установите в ячейке (1) значение «Готово»

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

0 голосов
/ 16 февраля 2017

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

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

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

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

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

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

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

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

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

    функция getCellValue (sheetName, row, col) { var ss = SpreadsheetApp.getActiveSpreadsheet (); var sh = ss.getSheetByName (sheetName); return sh.getRange (row, col) .getValue (); }

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

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

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

0 голосов
/ 08 апреля 2014

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

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