2013-06-27 4 views
55

Я написал собственный скрипт Google Apps, который получит id и получит информацию из веб-сервиса (цена).Обновить данные, полученные с помощью специальной функции в Листе Google

Я использую этот скрипт в электронной таблице, и он работает отлично. Моя проблема в том, что эти цены меняются, и моя таблица не обновляется.

Как я могу заставить его перезапустить скрипт и обновить ячейки (без ручного перемещения по каждой ячейке)?

+1

Да, вот объяснение, которое я сделал по этому поводу: http://stackoverflow.com/questions/9022984/google-apps-script-to-summarise-data-not-updating/9023954#9023954 –

+0

Я прочитал ваше объяснение как часть моих исследований. Очень полезно, спасибо. Я добавил ссылку на мой ответ. – tbkn23

+0

Для тех, кто сталкивается с подобным (определенным и логичным, но иногда неудачным) поведением, он может помочь продвинуть этот запрос функции в Google Issue Tracker: https://issuetracker.google.com/issues/36763858. –

ответ

54

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

Смотреть подробнее здесь: https://code.google.com/p/google-apps-script-issues/issues/detail?id=888

и здесь: Script to summarise data not updating

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

Поэтому всякий раз, когда я вызываю функцию, для дополнительного параметра передаю «$ A $ 1». Я также создал пункт меню refresh, и когда я его запустил, он помещает текущую дату и время в A1, поэтому все вызовы сценария с $ A $ 1 в качестве второго параметра должны будут пересчитываться. Вот код из моего сценария:

function onOpen() { 
    var sheet = SpreadsheetApp.getActiveSpreadsheet(); 
    var entries = [{ 
    name : "Refresh", 
    functionName : "refreshLastUpdate" 
    }]; 
    sheet.addMenu("Refresh", entries); 
}; 

function refreshLastUpdate() { 
    SpreadsheetApp.getActiveSpreadsheet().getRange('A1').setValue(new Date().toTimeString()); 
} 

function getPrice(itemId, datetime) { 
    var headers = 
     { 
     "method" : "get", 
     "contentType" : "application/json", 
     headers : {'Cache-Control' : 'max-age=0'} 
     }; 

    var jsonResponse = UrlFetchApp.fetch("http://someURL?item_id=" + itemId, headers); 
    var jsonObj = eval('(' + jsonResponse + ')'); 
    return jsonObj.Price; 
    SpreadsheetApp.flush(); 
} 

И когда я хочу поставить цену товара с идентификатором 5 в ячейке, я использую следующую формулу:

=getPrice(5, $A$1) 

Когда я хочу, чтобы обновить цены, я просто нажимаю пункт меню «Обновить» -> «Обновить». Помните, что вам необходимо перезагрузить таблицу после изменения сценария onOpen().

+3

Почему бы не использовать now() в качестве дополнительного параметра? – Advanced

+5

Вы видите, так же как моя функция не будет переоценена, потому что ее параметры не изменились (т.е. значения ячеек), now() не будет переоцениваться либо потому, что у нее нет параметров, следовательно, это возвращаемое значение не изменится, и поэтому параметры моей функции не изменятся. Кроме того, использование now() заставит мою функцию переоценивать все время, которое немного тяжело, учитывая, что он генерирует несколько HTTP-вызовов ... – tbkn23

+1

Хорошая находка. У меня была эта проблема при использовании именованных диапазонов в качестве входных данных. Используя ваш ответ, я понял, что это часто достаточно хорошо, чтобы передать фиктивную сумму по диапазону входов, как в «sum (B: D)», где строки B-D находятся в диапазоне, просмотренном пользовательской функцией. Изменение любой ячейки приведет к изменению суммы и пользовательской функции для обновления.Кстати, кажется, что пользовательская функция даже не должна объявлять игнорируемый параметр. –

-2

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

Если вы хотите просто взглянуть на электронную таблицу и хотите, чтобы ее значения изменились, подумайте о добавлении синхронизированного триггера, который будет обновлять ячейки. Узнайте больше о триггерах here

+8

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

25

Я знаю, что это старый вопрос. Но этот метод не требует каких-либо действий пользователя, кроме внесения изменений.

То, что я сделал, было похоже на tbkn23.

Функция, которую я хочу переоценить, имеет дополнительный неиспользованный параметр $ A $ 1.Таким образом, вызов функции

=myFunction(firstParam, $A$1) 

Но в коде функция подписи

function myFunction(firstParam) 

Вместо того, чтобы иметь функцию Refresh я использовал onEdit (е) функции, как этот

function onEdit(e) 
{ 
    SpreadsheetApp.getActiveSheet().getRange('A1').setValue(Math.random()); 
} 

Эта функция запускается всякий раз, когда редактируется какая-либо ячейка в электронной таблице. Итак, теперь вы редактируете ячейку, случайное число помещается в A1, это обновляет список параметров, как предлагается tbkn23, в результате чего пользовательская функция будет переоценена.

+2

Отлично работает. Downside is, undo (ctrl + z) история испорчена. – Jon

+1

Хороший трюк с раздражающим недостатком, как указал Джон ... Я надеюсь, что кто-то его улучшит :-) – Enissay

-1

Это может быть супер-старая нить, но может быть полезной для тех, кто пытается это сделать, как я был сейчас.

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

Итак, декларация вроде: function myFunction (firstParam, dummy), а затем вызов ее будет таким, как было предложено. Это сработало для меня.

Кроме того, если это неудобство для случайной переменной появляться на всех ваших листах, отредактированные, легко средство ограничить до одного листа выглядит следующим образом:

function onEdit(e) 
{ 
    e.source.getSheetByName('THESHEETNAME').getRange('J1').setValue(Math.random()); 
} 
+1

Это почти то же самое, что http://stackoverflow.com/a/27656313/1595451 –

+0

@ Rubén очень похоже но с хорошей неприятностью; вместо использования активного листа используется определенное имя листа, улучшая вашу историю. –

7

Это очень поздно, и Я не знаю, что это было бы полезно, но на самом деле есть здесь настроек вы можете сделать NOW() обновления автоматически

enter image description here

+1

'NOW()' - это встроенная функция, а не настраиваемая функция. –

+0

@ Rubén Суть в том, что вы можете включить функцию NOW() в любую настраиваемую функцию, которую вы хотите обновить. – Thaina

+5

В это время аргументы настраиваемых функций должны быть детерминированными, другими словами, они не являются allo NOW() в качестве аргумента. См. Https://developers.google.com/apps-script/guides/sheets/functions –

2

Если вы пользовательскими функции внутри определенного столбца просто заказать электронную таблицу с помощью этой седловины итп.

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

 Смежные вопросы

  • Нет связанных вопросов^_^