質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Q&A

解決済

1回答

2636閲覧

個人書類PDFを一括で大量に自動作成したい

shiyuh

総合スコア21

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

0グッド

0クリップ

投稿2022/05/31 13:16

編集2022/06/02 16:42

プルダウンで名前を選択すると、
選択した名前から情報を検索し、自動で請求書を作成する(vlookupなどを使用し、名前で検索する)システムを作りました。

しかし、100名以上の書類を作る場合、ひとりひとりを選択して印刷するのはとても手間です。

こう言った場合、普通どんなシステムを組むのでしょうか??

やりたいのは、全顧客の必要情報をまとめたスプレッドシートのデータを使って個人書類を作成し、簡単に全顧客分のPDFを作成することです。

良い提案があればご教示ください。

コード1

function

1 //PDFの保存先 2 //★★★フォルダーIDを入力してください★★★ 3 let folderId = "**************"; 4 5 //アクティブなスプレッドシートを取得する 6 let ss = SpreadsheetApp.getActiveSpreadsheet(); 7 8 //スプレッドシートIDを取得する 9 let ssId = ss.getId(); 10 11 //シートIDを取得する 12 let shId = ss.getActiveSheet().getSheetId(); 13 14 //D4セルを取得する 15 let fileNum = ss.getActiveSheet().getRange("D4").getValue(); 16 17 //★★★PDFのファイル名を入力してください★★★ 18 //※ポイント: ファイル名が重複しないようにしましょう 19 let fileName = fileNum; 20 21 //関数createPdfを実行し、PDFを作成して保存する 22 createPdf(folderId, ssId, shId, fileName); 23} 24 25//PDFを作成し指定したフォルダーに保存する関数 26//以下4つの引数を指定する必要がある 27//1: フォルダーID (folderId) 28//2: スプレッドシートID (ssId) 29//3: シートID (shId) 30//4: ファイル名 (fileName) 31function createPdf(folderId, ssId, shId, fileName){ 32 //PDFを作成するためのベースとなるURL 33 let baseUrl = "https://docs.google.com/spreadsheets/d/" 34 + ssId 35 + "/export?gid=" 36 + shId; 37 38 //★★★自由にカスタマイズしてください★★★ 39 //PDFのオプションを指定 40 let pdfOptions = "&exportFormat=pdf&format=pdf" 41 + "&size=A4" //用紙サイズ (A4) 42 + "&portrait=false" //用紙の向き true: 縦向き / false: 横向き 43 + "&fitw=true" //ページ幅を用紙にフィットさせるか true: フィットさせる / false: 原寸大 44 + "&top_margin=0.50" //上の余白 45 + "&right_margin=0.50" //右の余白 46 + "&bottom_margin=0.50" //下の余白 47 + "&left_margin=0.50" //左の余白 48 + "&horizontal_alignment=CENTER" //水平方向の位置 49 + "&vertical_alignment=TOP" //垂直方向の位置 50 + "&printtitle=false" //スプレッドシート名の表示有無 51 + "&sheetnames=false" //シート名の表示有無 52 + "&gridlines=false" //グリッドラインの表示有無 53 + "&fzr=false" //固定行の表示有無 54 + "&fzc=false" //固定列の表示有無; 55 56 //PDFを作成するためのURL 57 let url = baseUrl + pdfOptions; 58 59 //アクセストークンを取得する 60 let token = ScriptApp.getOAuthToken(); 61 62 //headersにアクセストークンを格納する 63 let options = { 64 headers: { 65 'Authorization': 'Bearer ' + token 66 } 67 }; 68 69 //PDFを作成する 70 let blob = UrlFetchApp.fetch(url, options).getBlob().setName(fileName + '.pdf'); 71 72 //PDFの保存先フォルダー 73 //フォルダーIDは引数のfolderIdを使用します 74 let folder = DriveApp.getFolderById(folderId); 75 76 //PDFを指定したフォルダに保存する 77 folder.createFile(blob); 78} 79

コード2

function

1 let ui = SpreadsheetApp.getUi() 2 3 //メニュー名を決定 4 //★★★メニュー名は好きなものに置き換えてください★★★ 5 let menu = ui.createMenu("GAS実行"); 6 7 //メニューに実行ボタン名と関数を割り当て 8 //★★★実行ボタン名は好きなものに置き換えてください★★★ 9 menu.addItem("PDF作成","savePdf"); 10 11 //スプレッドシートに反映 12 menu.addToUi(); 13} 14

エラー文↓
イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ソースコードを追記していただく前の回答

「システム」というか、流れ/考え方としては下記のようになるでしょうか。

(質問では具体的なコードが全く提示されていないので、こちらの回答としても具体的なコードでは示せませんが)
<やりたいこと>
複数の対象を"指定"し、それぞれの請求書pdfを作成する。

<現状の課題>
対象の指定を「ひとりひとりを、プルダウンから選択する」という作業で行っているが、これが煩雑であること。

<解決案>
対象の指定を「一括で」できればよい。

<現状の実装>
今のプログラムがたとえば下記のようになっていると仮定する。
①プルダウンのセルの変更をトリガーで検知
②変更されたプルダウンのセルの名前を読み取る
③②で得られた名前を請求書作成関数のパラメータに設定して呼び出す。
④請求書作成関数の中で指定された引数の名前を持つ請求書pdfを作成する。

<修正実装方針>
これを下記のように修正する。
①請求書pdfを作成したい複数の名前を入力するシートを用意する。
② ①のシートに、請求書pdfを作成したい対象の名前を、あらかじめ全部入力しておく。
③ ボタンを押すと④以降を実行するように設定しておく
④ (処理本体)for文で ①から作成対象の名前を1つずつ取得し、請求書pdf作成関数のパラメータに設定して渡す。
⑤ 請求書作成関数の中で指定された引数の名前を持つ請求書pdfを作成する。
⑥ ④~⑤の処理について、最後の名前に到達するまで繰り返す。


上記により、「課題を解決する処理」を、単純な作業に分解しました。
あとは
・ボタンを押すと指定したスクリプトを実行するような設定
・for文の基本的な使用法
・指定したシートから指定したセルのデータを読み取るコード
・請求書pdfを作成する具体的なコード
をそれぞれ実装して、つなげればよいだけです。


ソースコードを追記していただいた後の回答

下記の部分が「プルダウンのセルから出力対象となる名前を取得する部分」になっています。

//D4セルを取得する let fileNum = ss.getActiveSheet().getRange("D4").getValue();

したがって、この部分を、「入力シートから1つずつ名前を取得してcreatePdf関数に渡す処理」に変えればよいということになります。

・準備
①D4セルにプルダウンのあるシートの名前を「PDF」に変えてください。
②スプレッドシート内に名前一覧を入力するシートを新規作成し、名前を「リスト」に変えてください。
③ ②の「リスト」シートのA列1行目から、PDF出力したい名前を入力してください。
④ プルダウンに入力規則が設定されているままだと実行時にエラーになる可能性があるので、PDFシートのD4セルのプルダウンは解除(削除)しておいてください。
イメージ説明

コードを下記のように直します。

コード1

js

1function savePdf() { 2 //PDFの保存先 3 let folderId = "**************"; 4 5 let ss = SpreadsheetApp.getActiveSpreadsheet(); 6 7 let ssId = ss.getId(); 8 9 // 名前リストシートの名前 10 const listSheetName = 'リスト'; 11 const shList = ss.getSheetByName(listSheetName); 12 // PDFテンプレートシートの名前 13 const pdfSheetName = 'PDF'; 14 const shPdf = ss.getSheetByName(pdfSheetName); 15 16 if (shList == null) { 17 console.log(`シート「${listSheetName}」が見つかりません。`); 18 Browser.msgBox(`シート「${listSheetName}」が見つかりません。`); 19 return; 20 } 21 22 if (shPdf == null) { 23 console.log(`シート「${pdfSheetName}」が見つかりません。`); 24 Browser.msgBox(`シート「${pdfSheetName}」が見つかりません。`); 25 return; 26 } 27 28 const shId = shPdf.getSheetId(); 29 const names = shList.getRange(1, 1, shList.getLastRow(), 1).getValues().flat(); 30 31 // リストから1つずつ名前を読み取って実行する 32 for (const name of names) { 33 // D4セルに名前を入力 34 shPdf.getRange('D4').setValue(name); 35 SpreadsheetApp.flush(); 36 //関数createPdfを実行し、PDFを作成して保存する 37 createPdf(folderId, ssId, shId, name); 38 console.log(`ファイル名「${name}.pdf」を生成しました。`); 39 } 40} 41 42//PDFを作成し指定したフォルダーに保存する関数 43//以下4つの引数を指定する必要がある 44//1: フォルダーID (folderId) 45//2: スプレッドシートID (ssId) 46//3: シートID (shId) 47//4: ファイル名 (fileName) 48function createPdf(folderId, ssId, shId, fileName) { 49 //PDFを作成するためのベースとなるURL 50 let baseUrl = "https://docs.google.com/spreadsheets/d/" 51 + ssId 52 + "/export?gid=" 53 + shId; 54 55 //★★★自由にカスタマイズしてください★★★ 56 //PDFのオプションを指定 57 let pdfOptions = "&exportFormat=pdf&format=pdf" 58 + "&size=A4" //用紙サイズ (A4) 59 + "&portrait=false" //用紙の向き true: 縦向き / false: 横向き 60 + "&fitw=true" //ページ幅を用紙にフィットさせるか true: フィットさせる / false: 原寸大 61 + "&top_margin=0.50" //上の余白 62 + "&right_margin=0.50" //右の余白 63 + "&bottom_margin=0.50" //下の余白 64 + "&left_margin=0.50" //左の余白 65 + "&horizontal_alignment=CENTER" //水平方向の位置 66 + "&vertical_alignment=TOP" //垂直方向の位置 67 + "&printtitle=false" //スプレッドシート名の表示有無 68 + "&sheetnames=false" //シート名の表示有無 69 + "&gridlines=false" //グリッドラインの表示有無 70 + "&fzr=false" //固定行の表示有無 71 + "&fzc=false" //固定列の表示有無; 72 73 //PDFを作成するためのURL 74 let url = baseUrl + pdfOptions; 75 76 //アクセストークンを取得する 77 let token = ScriptApp.getOAuthToken(); 78 79 //headersにアクセストークンを格納する 80 let options = { 81 headers: { 82 'Authorization': 'Bearer ' + token 83 } 84 }; 85 86 //PDFを作成する 87 let blob = UrlFetchApp.fetch(url, options).getBlob().setName(fileName + '.pdf'); 88 89 //PDFの保存先フォルダー 90 //フォルダーIDは引数のfolderIdを使用します 91 let folder = DriveApp.getFolderById(folderId); 92 93 //PDFを指定したフォルダに保存する 94 folder.createFile(blob); 95}

コード2

js

1function onOpen() { 2 let ui = SpreadsheetApp.getUi() 3 4 //メニュー名を決定 5 //★★★メニュー名は好きなものに置き換えてください★★★ 6 let menu = ui.createMenu("GAS実行"); 7 8 //メニューに実行ボタン名と関数を割り当て 9 //★★★実行ボタン名は好きなものに置き換えてください★★★ 10 menu.addItem("PDF作成","savePdf"); 11 12 //スプレッドシートに反映 13 menu.addToUi(); 14}

あとは、上記を保存して、スプレッドシートを開きなおし、メニューの「GAS実行」→「PDF作成」を実行します。

投稿2022/05/31 13:36

編集2022/05/31 22:03
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shiyuh

2022/05/31 14:20

ご返答ありがとうございます。 元の投稿に追記したのですが、現在二つのコードを使ってPDF作成ボタンを実装し、プルダウンで名前を選択した後、そのボタンを押して一つ一つ作ってる状況です。(プルダウン選択だけで書類自体は完成する) これをワンクリックで自動で全て作成できたら・・と思ったのですが、初心者すぎてfor文を活用する方法もよくわからないです・・・サンプルコードなどあれば教えていただきたいです。。。。。 (PDF作成実装ボタンはネットで拾った情報をもとに作りました)
shiyuh

2022/05/31 14:25

・・・続き ロジック自体は理解しました。”名簿シート”を新たに作り、プルダウン作成時に引っ張ってきてるデータを貼り、”名簿シート”の列データをもとにfor分でプルダウンの内容を変えていってPDFを自動作成するということだと思うのですが・・・具体的なコードがどう書いたら良いかわからず・・・
退会済みユーザー

退会済みユーザー

2022/05/31 14:58 編集

確認なのですが、プルダウンのD4セルの内容が、同じシートの他のセルに計算式等でリンクされていて、 シートの内容が自動的に変わるようになっていたりしますか?
shiyuh

2022/05/31 15:32

はい。D4セルの内容を、同シート内の計算式でリンクさせています!
退会済みユーザー

退会済みユーザー

2022/06/02 08:38

回答追記しました。確認よろしくお願いします。
shiyuh

2022/06/02 16:41

バタついておりお返事遅くなりました>< 今試してみたところ、都有までは順調に進んだのですが、6枚目が書き出されたあたりで、以下のエラーが発生いたしました。。。解決方法はありますでしょうか?? エラー文①↓ Exception: https://docs.google.com のリクエストに失敗しました(エラー: 429)。 エラー文詳細を開くと・・・(元の質問に追記してます。)
shiyuh

2022/06/02 17:05

調べてみたとこと処理の多さでエラーになってたみたいですね・・・ //PDFを指定したフォルダに保存する folder.createFile(blob); } の後に Utilities.sleep(10000); を追加したところ正常に動作しました!! 今回も大変助かりました!! いつもありがとうございます(泣) またお願いいたします!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問