Google Apps Script / Programming

「フォームのデータを取得できませんでした。しばらくしてからもう一度お試しください。」の解決策 (GAS)

最近、このエラーに遭遇しました。ググったら同じ問題に直面している人が他にもいました。再現性がなく、エラーが出たり出なかったりで厄介です。恐らくGoogle側の問題で、自動連携設定をしているスプレッドシートには問題なく値が入っているのに、スクリプト側で回答取得ができず「フォームのデータを取得できませんでした。しばらくしてからもう一度お試しください。」がエラーとして表示されます。いつ直るかわからないため、とりあえずの解決方法をご紹介します。ご参考にしてください。

フォーム直送は諦める

フォームから取得するのは不安定なためスプレッドシートから取得します。これは実行時間は伸びますが確実な方法だと思います。

事前にフォームの回答が自動でスプレッドシートに反映されるように設定します。今回使用するフォームスプレッドシートは誰でも確認できるよう設定しているので参考にしてください。

答えだけが必要な方はこちら

事前準備

1. フォーム編集画面の回答タブをクリックし、スプレッドシートマークを押します。

2. 連携先スプレッドシートを指定する画面が表示されるので状況に合ったものを選択してください。

3. スプレッドシートが自動表示されるので確認しましょう。各質問がヘッダーとして1行目に固定表示されます。

スクリプト

const noText = '';

function getDataFromForm(e) {
  let formResponse;
  let timestamp;
  let question1;
  let question2;
  let question3;
  let question4;

  try {
    formResponse = e.response;
  } catch(e) {
    Logger.log(e);
    formResponse = null;
  }

  if (formResponse !== null) {
    timestamp = formResponse.getTimestamp();
    [
      question1,
      question2,
      question3,
      question4
    ] = getObjectFromFormData(formResponse.getItemResponses());
  } else {
    [
      timestamp,
      question1,
      question2,
      question3,
      question4
    ] = getDataFromSpreadsheet();
  }

  Logger.log(timestamp);
  Logger.log(question1);
  Logger.log(question2);
  Logger.log(question3);
  Logger.log(question4);
}

function getObjectFromFormData(itemResponses) {
  const response = [];

  for (itemResponse of itemResponses) {
    const item = itemResponse.getResponse();

    if (item === null || item === noText) continue;
    response.push(itemResponse.getResponse());
  }

  return response;
}

function getDataFromSpreadsheet() {
  const spreadsheetIdKey = 'SPREADSHEET_ID';
  const spreadsheetId = PropertiesService.getScriptProperties().getProperty(spreadsheetIdKey);
  const spreadsheet = SpreadsheetApp.openById(spreadsheetId);
  const sheetName = 'フォームの回答 1';
  const sheet = spreadsheet.getSheetByName(sheetName);
  const firstRow = sheet.getLastRow();
  const firstColumn = 1;
  const numberOfRows = 1;
  const numberOfColumns = sheet.getLastColumn();
  const range = sheet.getRange(firstRow, firstColumn, numberOfRows, numberOfColumns);
  const valueTable = range.getValues();
  const imageFileRowNumber = 4;
  const imageFileUrlPrefix = 'https://drive.google.com/open?id=';
  const response = [];
  
  for (valueRows of valueTable) {
    for (let i = 0; i < valueRows.length; i++) {
      if (valueRows[i] === noText) continue;
      if (i === imageFileRowNumber) {
        response.push(valueRows[i].replaceAll(imageFileUrlPrefix, noText));
        continue;
      }

      response.push(valueRows[i]);
    }
  }
  return response;
}

データが詰まっている「e」に対して操作を行う部分でエラーが発生するためtry-catch文で囲んでいます。また、getObjectFromFormDataではitemResponseからデータを取り出し、配列に詰め直すことでformResponseがnullであろうとなかろうとその後の処理が大体同じになり可読性が上がると思います。

まとめ

一旦はこれで難を逃れられますが、スプレッドシートから値を取得してくる方はどうしても実行時間が長くなってしまうので早く問題なく使えるようにして欲しいです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です