Googleスプレッドシートのカスタム関数によって取得されたデータを更新する


92

idWebサービス(価格)から情報を受け取り、取得するカスタムGoogle AppsScriptを作成しました。

このスクリプトをスプレッドシートで使用していますが、問題なく機能します。私の問題は、これらの価格が変更され、スプレッドシートが更新されないことです。

スクリプトを強制的に再実行してセルを更新するにはどうすればよいですか(各セルを手動で確認する必要はありません)。


1
はい、これについて私が行った説明は次のとおりです:stackoverflow.com/questions/9022984/…–
Henrique G. Abreu

私は私の研究の一部としてあなたの説明を読みました。とても助かりました、ありがとう。回答にリンクを追加しました。
tbkn23 2013年

同様の(定義された論理的ですが、時には不幸な)動作に遭遇した場合は、Google Issue Tracker(issuetracker.google.com/issues/36763858)でこの機能リクエストに賛成することが役立つ場合があります。
ティモシージョンズ

これが私がした簡単な答えです。
アンテナ

回答:


93

わかりました、私の問題はグーグルが奇妙な方法で動作することだったようです-スクリプトパラメータが類似している限りスクリプトを再実行せず、以前の実行からのキャッシュされた結果を使用します。したがって、APIに再接続せず、価格を再フェッチせず、キャッシュされた前のスクリプト結果を返すだけです。

詳細については、https//code.google.com/p/google-apps-script-issues/issues/detail?id = 888をご覧ください。

そしてここ:更新されていないデータを要約するスクリプト

私の解決策は、スクリプトに別のパラメーターを追加することでしたが、これも使用していません。これで、以前の呼び出しとは異なるパラメーターを使用して関数を呼び出すと、これらのパラメーターの結果がキャッシュにないため、スクリプトを再実行する必要があります。

したがって、関数を呼び出すときはいつでも、追加のパラメーターに「$ A $ 1」を渡します。また、refreshというメニュー項目を作成しました。これを実行すると、現在の日付と時刻がA1に格納されるため、2番目のパラメーターとして$ 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();
}   

また、ID 5のアイテムの価格をセルに入れたい場合は、次の数式を使用します。

=getPrice(5, $A$1)

価格を更新したい場合は、「更新」->「更新」メニュー項目をクリックするだけです。onOpen()スクリプトを変更した後、スプレッドシートをリロードする必要があることに注意してください。


4
now()を追加パラメーターとして使用しないのはなぜですか?
高度な

5
ご覧のとおり、パラメーターが変更されていないために関数が再評価されないのと同じように(つまり、セルの値)、now()もパラメーターがないため再評価されないため、戻り値は変更されないため、関数のパラメーターは変更されません。また、now()を使用すると、関数が常に再評価されるため、複数のHTTP呼び出しが生成されることを考えると、少し重いです...
tbkn23 2013

2
良い発見。名前付き範囲を入力として使用しているときにこの問題が発生しました。あなたの答えを使用して、「sum(B:D)」のように、入力の範囲全体にダミーの合計を渡すだけで十分であることがよくあることがわかりました。ここで、行BDはカスタム関数によって検索された範囲内にあります。セルを変更すると、合計が変更され、カスタム関数が更新されます。ちなみに、カスタム関数は無視されたパラメータを宣言する必要さえないようです。
Shawn Hoover

1
これがまだこの問題に対して私が見つけた最良の解決策であるのは残念です。Googleが特定の関数呼び出しのキャッシュを無効にすることを許可するのではなく、キャッシュされた値を取得しないようにするために、キャッシュに格納されているものを任意に増やします...それでも、投稿に感謝します
GrayedFox


33

これは少し古い質問だと思います。ただし、この方法では、変更を加える以外にユーザーの操作は必要ありません。

私がしたことはtbkn23に似ていました。

再評価したい関数には、未使用のパラメーター$ A $ 1が追加されています。したがって、関数呼び出しは

=myFunction(firstParam, $A$1)

しかし、コードでは、関数のシグネチャは

function myFunction(firstParam)

更新関数を使用する代わりに、次のようなonEdit(e)関数を使用しました

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

この関数は、スプレッドシートのセルが編集されるたびにトリガーされます。したがって、セルを編集すると、A1に乱数が配置され、tbkn23が提案するようにパラメーターリストが更新され、カスタム関数が再評価されます。


5
よく働く。欠点は、元に戻す(ctrl + z)履歴が台無しになっていることです。
ジョン

1
ジョンが指摘したように厄介な欠点を伴う素晴らしいトリック...誰かがそれを改善することを願っています:
Enissay 2016

2
この答えに関する小さくて衒学的な警告。信じられないほどありそうもないイベントで、Math.randomは同じ番号を返します。その場合、その特定の番号はすでにキャッシュされているため、更新されません。
ウッディペイン

12

これは非常に遅く、それが役立つかどうかはわかりませんが、実際にはここに設定があり、NOW()自動的に更新できます

ここに画像の説明を入力してください


1
NOW()は組み込み関数であり、カスタム関数ではありません。
ルベン・

@Rubén重要なのは、更新したいカスタム関数にNOW()関数を含めることができるということです
Thaina 2016年

13
現時点では、カスタム関数の引数は決定論的である必要があります。つまり、引数としてNOW()を割り当てません。参照してくださいdevelopers.google.com/apps-script/guides/sheets/functions
ルベン・

3
カスタム関数内でNOW()を使用しようとすると、エラーがスローされます
Stefano Giacone 2018年

7

カスタム関数が特定の列内にある場合は、スプレッドシートをその列で並べ替えるだけです。

順序付けアクションにより、データが強制的に更新され、その列のすべての行に対してカスタム関数が一度に呼び出されます。


シートがまだ注文されていない場合にのみ機能します
Sanfer 2010

2

これは非常に古いスレッドかもしれませんが、私がちょうど今だったので、これを行おうとしている誰かにとって役立つかもしれません。

Lexiのスクリプトをそのまま使用すると、現在のスプレッドシートでは機能しなくなったようですが、ダミー変数をパラメーターとして関数に追加すると(実際に関数内で使用する必要はありません)、実際に機能します。 Googleスプレッドシートにページを再度更新するように強制します。

したがって、次のような宣言:function myFunction(firstParam、dummy)を呼び出してから、それを呼び出すと、提案されているとおりになります。それは私のために働いた。

また、編集するすべてのシートに確率変数が表示されるのが面倒な場合、1つのシートに制限する簡単な解決策は次のとおりです。

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

1
@Rubénそれは非常に似ていますが、かなり迷惑です。アクティブなシートを使用する代わりに、定義されたシート名を使用して、履歴を改善します
Jonas D.

1

スクリプトロジック:

  • カスタム関数は、引数が変更されない限り更新されません。
  • onChangeトリガーを作成して、textFinderを使用してスプレッドシート内のすべてのカスタム関数のすべての引数を変更します

スニペット:

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

読むには:


1

前に述べたように:

カスタム関数は、引数が変更されない限り更新されません。

考えられる解決策は、単一のセルにチェックボックスを作成し、このセルをカスタム関数の引数として使用することです。

  1. チェックボックスを作成します。[A1]などのフリーセルを選択し、[挿入]> [チェックボックス]に移動します。
  2. このセルを引数にします。 =myFunction(A1)
  3. チェックボックスをクリックして、数式を更新します

-3

カスタム関数を作成し、それをスプレッドシートで数式として使用した場合、スプレッドシートを開くか、参照セルが変更されるたびに、数式が再計算されます。

スプレッドシートを見つめ続けてその値を変更したい場合は、セルを更新する時限トリガーを追加することを検討してください。トリガーについて詳しくはこちらをご覧ください


10
それが機能しないことを除いて、それはちょうど素晴らしいでしょう...ページをリロードしても値は更新されません。さらに、セルを削除して同じ関数呼び出しを再入力しても、古い値が保持されます。同じ関数を別のセルから正確に呼び出すと、新しい値が表示されますが、古いセルには表示されません。
tbkn23 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.