Google E-Tablosundaki özel bir işlev tarafından alınan verileri yenileyin


92

idBir web hizmetinden bilgi alacak ve getirecek (bir fiyat) özel bir Google Apps Komut Dosyası yazdım .

Bu komut dosyasını bir elektronik tabloda kullanıyorum ve gayet iyi çalışıyor. Benim sorunum, bu fiyatların değişmesi ve elektronik tablomun güncellenmemesi.

Komut dosyasını yeniden çalıştırmaya ve hücreleri güncellemeye (her hücrenin üzerinden manuel olarak geçmeden) nasıl zorlayabilirim?


1
Evet, işte bununla ilgili yaptığım bir açıklama: stackoverflow.com/questions/9022984/…
Henrique G. Abreu

Araştırmamın bir parçası olarak açıklamanızı okudum. Çok yardımcı oldu, teşekkürler. Bağlantıyı cevabıma ekledim.
tbkn23

Benzer (tanımlanmış ve mantıklı, ancak bazen talihsiz) davranışla karşılaşanlar için, bu özellik isteğini Google Sorun İzleyici'de yükseltmek işe yarayabilir : issuetracker.google.com/issues/36763858 .
Timothy Johns

İşte yaptığım basit bir cevap .
antenleri

Yanıtlar:


92

Tamam, benim sorunum Google'ın garip bir şekilde davranması gibi görünüyor - komut dosyası parametreleri benzer olduğu sürece komut dosyasını yeniden çalıştırmıyor, önceki çalıştırmalardan önbelleğe alınmış sonuçları kullanıyor. Dolayısıyla, API'ye yeniden bağlanmaz ve fiyatı yeniden getirmez, yalnızca önbelleğe alınmış önceki komut dosyası sonucunu döndürür.

Daha fazla bilgiyi burada bulabilirsiniz: https://code.google.com/p/google-apps-script-issues/issues/detail?id=888

ve burada: Güncellenmeyen verileri özetleyen komut dosyası

Çözümüm betiğime kullanmadığım başka bir parametre eklemekti. Şimdi, işlevi önceki çağrılardan farklı bir parametre ile çağırdığınızda, bu parametrelerin sonucu önbellekte olmayacağından betiği yeniden çalıştırması gerekecektir.

Bu yüzden fonksiyonu ne zaman çağırsam, ekstra parametre için "$ A $ 1" i geçiyorum. Ayrıca yenileme adında bir menü öğesi oluşturdum ve çalıştırdığımda, geçerli tarih ve saati A1'e koyuyor, bu nedenle komut dosyasına yapılan tüm aramalar $ A $ 1 ile ikinci parametre olarak yeniden hesaplanacak. Komut dosyamdan bazı kodlar:

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();
}   

Ve kimliği 5 olan öğenin fiyatını bir hücreye koymak istediğimde, aşağıdaki formülü kullanıyorum:

=getPrice(5, $A$1)

Fiyatları yenilemek istediğimde, sadece "Yenile" -> "Yenile" menü öğesini tıklıyorum. onOpen()Komut dosyasını değiştirdikten sonra elektronik tabloyu yeniden yüklemeniz gerektiğini unutmayın .


4
neden now () ek bir parametre olarak kullanılmıyor?
Gelişmiş

5
Gördüğünüz gibi, fonksiyonumun parametreleri değişmediği için (yani hücrelerin değerleri) yeniden değerlendirilmeyeceği gibi, şimdi () parametresi olmadığı için de yeniden değerlendirilmeyecek, dolayısıyla dönüş değeri değişmez ve bu nedenle işlevimin parametreleri değişmez. Ayrıca now () kullanmak, işlevimin her zaman yeniden değerlendirmesine neden olur ve bu, birkaç HTTP çağrısı oluşturduğu düşünüldüğünde biraz ağırdır ...
tbkn23

2
İyi bul. Girdi olarak adlandırılmış aralıkları kullanırken bu sorunu yaşadım. Cevabınızı kullanarak, BD satırlarının özel işlev tarafından aranan aralıkta olduğu "sum (B: D)" örneğinde olduğu gibi, girdi aralığı üzerinden bir kukla toplam geçirmenin genellikle yeterince iyi olduğunu anladım. Herhangi bir hücrenin değiştirilmesi, toplamın değişmesini ve özel işlevin yenilenmesini tetikler. Bu arada, özel işlevin göz ardı edilen parametreyi bildirmesi bile gerekmiyor gibi görünüyor.
Shawn Hoover

1
Bunun hala bu soruna bulduğum en iyi çözüm olması utanç verici. Google'ın sadece belirli işlev çağrıları için önbelleği devre dışı bırakmamıza izin vermesi yerine, yalnızca önbelleğe alınmış bir değer almadığımızdan emin olmak için önbellekte depolananları keyfi olarak artırıyoruz ... Yine de, gönderi için teşekkürler,
GrayedFox

Özel fonksiyon için bir parametre kullanmayı deneyin bu örnekte olduğu gibi
Antenler

33

Bunun biraz eski bir soru olduğunu biliyorum. Ancak bu yöntem, değişiklik yapmak dışında herhangi bir kullanıcı eylemi gerektirmez.

Yaptığım şey tbkn23'e benziyordu.

Yeniden değerlendirmek istediğim işlevin fazladan kullanılmayan bir parametresi var: $ A $ 1. Yani işlev çağrısı

=myFunction(firstParam, $A$1)

Ancak kodda işlev imzası

function myFunction(firstParam)

Yenileme işlevi yerine, onEdit (e) işlevini şu şekilde kullandım

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

Bu işlev, elektronik tablodaki herhangi bir hücre düzenlendiğinde tetiklenir. Şimdi bir hücreyi düzenlersiniz, A1'e rastgele bir sayı yerleştirilir, bu, tbkn23'ün önerdiği gibi parametre listesini yeniler ve özel işlevin yeniden değerlendirilmesine neden olur.


5
Harika çalışıyor. Dezavantajı ise, geri alma (ctrl + z) geçmişinin karışık olmasıdır.
Jon

1
Jon'un da belirttiği gibi can sıkıcı bir dezavantajı olan güzel numara ... Umarım birisi onu geliştirir :-)
Enissay

Bu cevapla ilgili küçük ve bilgiçlikli uyarı; inanılmaz derecede olası olmayan bir olayda Math.random aynı sayıyı döndürür, bu durumda belirli sayı önceden önbelleğe alındığı için güncellenmez.
Woody Payne

12

Bu çok geç ve faydalı olacağını bilmiyorum ama aslında burada ayarlar var, NOW()otomatik olarak güncelleme yapabilirsiniz.

görüntü açıklamasını buraya girin


1
NOW()yerleşik bir işlevdir, özel bir işlev değildir.
Rubén

@ Rubén Önemli olan şu ki, güncellemesini istediğiniz herhangi bir özel işleve ŞİMDİ () işlevini dahil edebilirsiniz
Thaina

13
Şu anda özel işlevler argümanları deterministik olmalıdır, başka bir deyişle, ŞİMDİ () argüman olarak kullanılmazlar. Developers.google.com/apps-script/guides/sheets/functions'ı
Rubén

3
ŞİMDİ () özel bir işlev içinde kullanmaya çalışırsanız bir hata atar
Stefano Giacone

6

Özel işleviniz belirli bir sütunun içindeyse, e-tablonuzu o sütuna göre sıralamanız yeterlidir.

Sıralama eylemi, o sütunun tüm satırları için özel işlevinizi aynı anda çağıran verilerin yenilenmesini zorlar.


1

Bu çok eski bir konu olabilir, ancak şimdi olduğu gibi bunu yapmaya çalışan biri için yararlı olabilir.

Lexi'nin komut dosyası olduğu gibi çalışarak, artık mevcut E-Tablolar ile çalışmıyor gibi görünüyor, ancak kukla değişkeni bir parametre olarak işlevime eklersem (işlevin içinde gerçekten kullanmaya gerek yoktur), gerçekten de google sayfalarını sayfayı tekrar yenilemeye zorlayın.

Bu nedenle, işlev myFunction (firstParam, dummy) gibi bir bildirim ve ardından onu çağırma önerildiği gibi olacaktır. Bu benim için çalıştı.

Ayrıca, düzenlediğiniz tüm sayfalarınızda rastgele bir değişkenin görünmesi bir sıkıntı oluşturuyorsa, tek bir sayfayla sınırlamanın kolay bir çözümü aşağıdaki gibidir:

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

1
@ Rubén çok benzer, ancak iyi bir baş belası; yerine geçmişinizi, bir tanımlanmış sayfa adı kullanan aktif sayfasını kullanarak iyileştirme
Jonas D.

1

Komut Dosyası Mantığı:

  • Özel İşlevler, bağımsız değişkenler değişmedikçe güncellenmez.
  • TextFinder'ı kullanarak elektronik tablodaki tüm özel işlevlerin tüm bağımsız değişkenlerini değiştirmek için bir onChange tetikleyicisi oluşturun

Snippet:

/*@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) + ')'
    );
}

Okumak:


1

Daha önce belirtildiği gibi:

Özel İşlevler, bağımsız değişkenler değişmedikçe güncellenmez.

Olası çözüm, tek bir hücrede bir onay kutusu oluşturmak ve bu hücreyi özel işlev için bağımsız değişken olarak kullanmaktır:

  1. Bir onay kutusu oluşturun: boş hücreyi seçin, örneğin [A1], [Ekle]> [Onay Kutusu] 'na gidin
  2. Bu hücreyi bir argüman yapın: =myFunction(A1)
  3. Formülü yenilemek için onay kutusunu tıklayın

-3

Özel bir işlev yazdıysanız ve bunu elektronik tablonuzda formül olarak kullandıysanız, elektronik tabloyu her açtığınızda veya herhangi bir başvuruda bulunan hücre değiştirildiğinde formül yeniden hesaplanır.

Elektronik tabloya bakmaya devam etmek ve değerlerinin değişmesini istiyorsanız, hücreleri güncelleyecek zamanlanmış bir tetikleyici eklemeyi düşünün. Tetikleyiciler hakkında daha fazlasını buradan okuyun


10
Bu harika olurdu, ancak işe yaramaz ... Sayfayı yeniden yüklemek değerleri yenilemez. Dahası, hücreyi silmek ve aynı işlev çağrısını tekrar girmek eski değeri hala korur. Aynı işlevi tam olarak başka bir hücreden çağırırsam, yeni değeri gösterecek, ancak eski hücrede göstermeyecektir.
tbkn23
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.