web-dev-qa-db-ja.com

「サービス呼び出しエラー」なしでGoogleシートで複数の運転時間を取得するにはどうすればよいですか?

このエラーが引き続き発生します。

「1日にサービスが何度も呼び出されました:ルート(3行目)。」

ここに私のサンプルシートへのリンクがあります。スクリプトを添付

https://docs.google.com/spreadsheets/d/1RZWMcI1vJW551VmoqYj_Orpv5Cqvgi99Ot53J4hTMj4/edit?usp=sharing

これが私の機能の基本的なセットアップです。これを配列式にする方法はありますか?それも助けになりますか?また、一度計算すると、再計算する必要はありません。

function DrivingSeconds(Origin, destination) {
  var directions = Maps.newDirectionFinder()
  .setOrigin(Origin)
  .setDestination(destination)
  .getDirections();
  return directions.routes[0].legs[0].duration.value;  
}

シートがフォームから入力を受け取ることに注意することが重要だと思います。フォームは1日に10〜30件の回答を受け取ります。また、同じ設定で約16枚の個別のシートを実行する必要があります。それは本当にAPIの手当を燃やします。


関数にカウンターを追加しましたが、それでも1分ごとに実行されているようです。これは、「if」が真である場合にのみカウントすべきではありませんか?

function DrivingSeconds() {
   var sheet = SpreadsheetApp.getActive().getSheetByName('ETA');
   var input = sheet.getRange("G2:G").getValues();
   var counter = sheet.getRange("K3").getValue();
   var output = sheet.getRange("J2:J").getValues();

     for (var i = 1; i < output.length; i++) {
       if (!output[i][0] && input[i-1][0] && input[i][0]) {
          output[i][0] = Maps.newDirectionFinder()
          .setOrigin(input[i-1][0])
          .setDestination(input[i][0])
          .getDirections()
          .routes[0].legs[0].duration.value;
          sheet.getRange("K3").setValue(counter++);
       }
     }
     sheet.getRange("J2:J").setValues(output);
 }
2
Sumguyinabox

エラーメッセージはマップサービスに関するものだと思います。配列式への変換は、マップを何度も呼び出すため、役に立ちません。できることは次のとおりです。

マップサービスを不必要に呼び出さないでください。今、あなたはempty宛先とOriginで何十回も呼び出しています。事前に空でない文字列であることを確認してください。

カスタム関数から、フォーム送信によってトリガーされる関数に切り替えます。つまり、スプレッドシートに=DrivingSeconds(...)を配置する代わりに、 トリガーを追加 がフォーム送信時に呼び出されます。この関数は次のようになります。

function DrivingSeconds() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var input = sheet.getRange("A2:A").getValues();
  var output = sheet.getRange("B2:B").getValues();
  for (var i = 1; i < output.length; i++) {
    if (!output[i][0] && input[i-1][0] && input[i][0]) {
      output[i][0] = Maps.newDirectionFinder()
      .setOrigin(input[i-1][0])
      .setDestination(input[i][0])
      .getDirections()
      .routes[0].legs[0].duration.value;
    }
  }
  sheet.getRange("B2:B").setValues(output);
}

Maps APIは、出発地と目的地の両方があり、期間がまだない場合にのみ呼び出されることに注意してください。出力:

+---+-------------------------------------------------+-----+
|   |                        A                        |  B  |
+---+-------------------------------------------------+-----+
| 1 | Address                                         | ETA |
| 2 | 5020 IMPERIAL AVENUE, SAN DIEGO, CA,92113       |     |
| 3 | 4699 EL CAJON BLVD, SAN DIEGO, CA,92115         | 604 |
| 4 | 8620 LA MESA BLVD, LA MESA, CA,91942            | 674 |
| 5 | 2820 VIA ORANGE WAY #Q, SPRING VALLEY, CA,91978 | 638 |
+---+-------------------------------------------------+-----+
2
user79865

関数内のスプレッドシートの範囲参照を削除したい場合、別のオプションはキャッシングを使用することです、例えば:

function DrivingSeconds(Origin, destination) {
  if (Origin && destination) {
    var cache = CacheService.getDocumentCache();
    var key = Origin + '|' + destination;
    var value = cache.get(key);
    if (!value) {
      value = Maps.newDirectionFinder()
        .setOrigin(Origin)
        .setDestination(destination)
        .getDirections()
        .routes[0].legs[0].duration.value;
      Utilities.sleep(1000);
      cache.put(key, value);
    }
    return value;
  }
  return -1;
}

CacheService.getDocumentCache()は、すでに計算されている値を追跡し、Utilities.sleep(1000)は、一度に多くの値が変更された場合にサービスのオーバーロードを回避します。

2
Anton