😊

「GASでGoogleスプレッドシートをPDFに自動保存する」を動かしてみた(エラー対処まとめ)

2023/11/14に公開

はじめに

コバユタさんの「GASでGoogle スプレッドシートの任意のシートをPDFで保存する」の記事を参考に、実際にGASを動かしてみました。
https://zenn.dev/kobayutapon/articles/c0a35632715054
自分の環境で試したところ、ところどころエラーが出てしまい、ChatGPTに聞きながら対処したので、備忘用にやったことをまとめます。

コード(引用)

const Spreadsheet_ID = 'スプレッドシートのID';
const drive_ID = '保存するGoogle DriveのID';
const sheet_Name = '保存するシート名';
const output_file = '出力するファイル名.pdf'

function savePDF() {
  var spreadsheets = SpreadsheetApp.openById(Spreadsheet_ID);
  var form_sheet = spreadsheets.getSheetByName(sheet_Name)
  var sheet_id = form_sheet.getSheetId();

  var output_url = createUrlForPdf(spreadsheets);
  Logger.log(output_url);

  /** @type {string} ユーザーのOAuth2.0アクセストークン */
  const token = ScriptApp.getOAuthToken();
  // URLからblobデータを取得する
  const blob = UrlFetchApp.fetch(output_url, {headers: {'Authorization': 'Bearer ' + token}}).getBlob();

  var folder_id = getFolderIdBySpreadsheet(spreadsheets);
  var fileName = output_file;

  // ファイル名を設定してフォルダにPDFファイルを出力する
  DriveApp.getFolderById(folder_id).createFile(blob.setName(fileName));
}

/**
 * PDF出力用のURLを作成する.
 * @param {Spreadsheet} 出力対象のスプレッドシート.
 */
function createUrlForPdf(spreadsheet) {
  const params = {
    'exportFormat': 'pdf',
    'format': 'pdf',
    'gid': spreadsheet.getSheetByName('Application_form').getSheetId(), // シート名を指定して出力対象シートのIDを指定
    'size': 'A4', // 用紙サイズ:A4
    'portrait': true, // 用紙向き:縦
    'fitw': true, // 幅を用紙に合わせる
    'horizontal_alignment': 'CENTER', // 水平方向:中央
    'gridlines': false, // グリッドライン:非表示
  }
  const query = Object.keys(params).map(function(key) {
    return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
  }).join('&');
  return `https://docs.google.com/spreadsheets/d/${spreadsheet.getId()}/export?${query}`;
}

/**
 * スプレッドシートが格納されているフォルダのIDを取得する.
 * @param {Spreadsheet} 対象のスプレッドシート.
 */
function getFolderIdBySpreadsheet(spreadsheet) {
  const parents = DriveApp.getFileById(spreadsheet.getId()).getParents();
  const folder = parents.next();
  return folder.getId();
}

※以下は事前に修正しました
・1行目)const Spreadsheet_ID = "hoge" → 'hoge'
・表記ゆれ)SpreadSheet_ID → Spreadsheet

エラーが起きてしまったところ

・34行目)シート名を変更する必要があった

TypeError: Cannot read properties of null (reading 'getSheetId')
    at createUrlForPdf(コード:34:58)
    at savePDF(コード:11:20)

ChatGPTの回答

createUrlForPdf関数の34行目で、spreadsheet.getSheetByName('Application_form').getSheetId()を使用しているとされています。このコードは、'Application_form'という名前のシートを取得した後、そのシートのIDを取得することを意図しているようです。しかし、もし'Sheet'という名前のシートが存在しない場合、getSheetByNameメソッドはnullを返し、その後のgetSheetIdメソッドでエラーが発生します。

・フォルダ内に、スプレッドシートを格納しておく必要があった

Exception: Cannot retrieve the next object: iterator has reached the end.
    at getFolderIdBySpreadsheet(コード:53:26)
    at savePDF(コード:19:19)

ChatGPTの回答

getFolderIdBySpreadsheet関数で、イテレータが終端に達している可能性があります。フォルダがスプレッドシートに紐付いていない場合や、フォルダへのアクセス権がない場合に起こる可能性があります。
解決策としては、次のようなことが考えられます:
スプレッドシートがフォルダに格納されていることを確認してください。もしフォルダに格納されていない場合は、正しいフォルダにスプレッドシートを移動してください。
フォルダへのアクセス権を確認してください。スプレッドシートとフォルダが異なるアカウントで共有されている場合、正しいアクセス権が設定されていることを確認してください。

対処したところ、ちゃんと動きました◎

関連

自動保存したいシートを、自分が作成したフォルダに移動するということができなかったため(共有設定されてなかったから??)、コピー版のシート(ファイル)を作成し、自動で転記させるという中間開発をかませました。WTF!

参考にした記事はこちら
https://rabit.radix.ad.jp/column/google-spreadsheet-auto/#13

転記先/転記元それぞれのシート名を指定するので、うっかりシート名を変えてしまうことがないように注意が必要ですね。

あわせて、今回の実装で、初めてスプレッドシートとGoogleドライブのIDの概念を知ったので、それもメモします。
https://docs.google.com/spreadsheets/d/スプレッドシートID/edit#gid=シートID

https://drive.google.com/drive/u/0/folders/フォルダID

Discussion