Napisałem niestandardowy skrypt Google Apps, który otrzyma plik id
i pobiera informacje z usługi internetowej (cena).
Używam tego skryptu w arkuszu kalkulacyjnym i działa dobrze. Mój problem polega na tym, że te ceny się zmieniają, a mój arkusz kalkulacyjny nie jest aktualizowany.
Jak mogę zmusić go do ponownego uruchomienia skryptu i zaktualizowania komórek (bez ręcznego przeglądania każdej komórki)?
Odpowiedzi:
Ok, wydaje mi się, że moim problemem było to, że Google zachowuje się dziwnie - nie uruchamia ponownie skryptu, o ile parametry skryptu są podobne, używa buforowanych wyników z poprzednich uruchomień. W związku z tym nie łączy się ponownie z interfejsem API i nie pobiera ponownie ceny, po prostu zwraca wynik poprzedniego skryptu, który został zapisany w pamięci podręcznej.
Zobacz więcej informacji tutaj: https://code.google.com/p/google-apps-script-issues/issues/detail?id=888
i tutaj: skrypt podsumowujący dane, które nie są aktualizowane
Moim rozwiązaniem było dodanie kolejnego parametru do mojego skryptu, którego nawet nie używam. Teraz, gdy wywołasz funkcję z parametrem innym niż poprzednie wywołania, będzie ona musiała ponownie uruchomić skrypt, ponieważ wynik dla tych parametrów nie będzie w pamięci podręcznej.
Więc ilekroć wywołuję tę funkcję, jako dodatkowy parametr przekazuję „$ A $ 1”. Utworzyłem również element menu o nazwie odświeżanie, a kiedy go uruchamiam, umieszcza bieżącą datę i godzinę w A1, stąd wszystkie wywołania skryptu z $ A $ 1 jako drugim parametrem będą musiały zostać przeliczone ponownie. Oto kod z mojego skryptu:
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(); }
A kiedy chcę umieścić w komórce cenę przedmiotu o identyfikatorze 5, używam następującego wzoru:
=getPrice(5, $A$1)
Kiedy chcę odświeżyć ceny, po prostu klikam opcję „Odśwież” -> „Odśwież”. Pamiętaj, że po zmianie
onOpen()
skryptu musisz ponownie załadować arkusz kalkulacyjny .źródło
Wiem, że to trochę stare pytanie. Ale ta metoda nie wymaga żadnych działań użytkownika poza wprowadzeniem zmiany.
To, co zrobiłem, było podobne do tbkn23.
Funkcja, którą chcę ponownie ocenić, ma dodatkowy nieużywany parametr $ A $ 1. Więc wywołanie funkcji to
=myFunction(firstParam, $A$1)
Ale w kodzie jest podpis funkcji
function myFunction(firstParam)
Zamiast mieć funkcję Refresh, użyłem funkcji onEdit (e) w ten sposób
function onEdit(e) { SpreadsheetApp.getActiveSheet().getRange('A1').setValue(Math.random()); }
Ta funkcja jest uruchamiana za każdym razem, gdy edytowana jest dowolna komórka w arkuszu kalkulacyjnym. Więc teraz edytujesz komórkę, losowa liczba jest umieszczana w A1, co odświeża listę parametrów zgodnie z sugestią tbkn23, powodując ponowne oszacowanie funkcji niestandardowej.
źródło
Jest bardzo późno i nie wiem, czy byłoby to przydatne, ale w rzeczywistości są tutaj ustawienia, które można
NOW()
aktualizować automatycznieźródło
NOW()
jest funkcją wbudowaną, a nie funkcją niestandardową.Jeśli Twoja funkcja niestandardowa znajduje się w określonej kolumnie, po prostu uporządkuj arkusz kalkulacyjny według tej kolumny.
Akcja porządkowania wymusza odświeżenie danych, co wywołuje funkcję niestandardową dla wszystkich wierszy tej kolumny jednocześnie.
źródło
To może być bardzo stary wątek, ale może być przydatny dla kogoś, kto próbuje to zrobić, tak jak przed chwilą.
Pracując ze skryptu Lexi w obecnym stanie, nie wydawało się już działać z bieżącymi Arkuszami, ale jeśli dodam zmienną zastępczą do mojej funkcji jako parametr (nie ma potrzeby używania jej w funkcji), rzeczywiście wymuś ponowne odświeżenie strony w arkuszach Google.
Tak więc, zadeklaruj taką funkcję jak: function myFunction (firstParam, dummy), a następnie wywołaj ją zgodnie z sugestią. To zadziałało dla mnie.
Ponadto, jeśli pojawianie się zmiennej losowej na wszystkich arkuszach, które edytujesz, jest uciążliwe, prostym sposobem na ograniczenie do jednego arkusza jest następujący:
function onEdit(e) { e.source.getSheetByName('THESHEETNAME').getRange('J1').setValue(Math.random()); }
źródło
Logika skryptów:
Skrawek:
/*@customfunction*/ function sheetNames(e) { return SpreadsheetApp.getActive() .getSheets() .map(function(sheet) { return sheet.getName(); }); } /*Create a installable trigger to listen to grid changes on the sheet*/ function onChange(e) { if (!/GRID/.test(e.changeType)) return; //Listen only to grid change SpreadsheetApp.getActive() .createTextFinder('=SHEETNAMES\\([^)]*\\)') .matchFormulaText(true) .matchCase(false) .useRegularExpression(true) .replaceAllWith( '=SHEETNAMES(' + (Math.floor(Math.random() * 500) + 1) + ')' ); }
Czytać:
źródło
Jak już wspomniano:
Możliwym rozwiązaniem jest utworzenie pola wyboru w pojedynczej komórce i użycie tej komórki jako argumentu funkcji niestandardowej:
=myFunction(A1)
źródło
Jeśli napisałeś funkcję niestandardową i użyłeś jej w arkuszu kalkulacyjnym jako formuły, to za każdym razem, gdy otwierasz arkusz kalkulacyjny lub modyfikowana jest dowolna komórka odniesienia, formuła jest ponownie obliczana.
Jeśli chcesz po prostu wpatrywać się w arkusz kalkulacyjny i chcesz zmienić jego wartości, rozważ dodanie wyzwalacza czasowego, który zaktualizuje komórki. Przeczytaj więcej o wyzwalaczach tutaj
źródło