質問するログイン新規登録

回答編集履歴

2

修正

2021/04/24 06:28

投稿

退会済みユーザー
answer CHANGED
@@ -8,26 +8,135 @@
8
8
  シートIDが書かれているセルの右隣に「シート不存在」と書き込み
9
9
  次のシートIDの処理に移ります。
10
10
 
11
+ ------
12
+
13
+ **追記** 
14
+
15
+ ※修正前の回答コードではシートIDの存在確認が正常にできていなかったため、
16
+ 冒頭に`existSheetId(spreadsheet, sheetId)`関数を追加しております。
17
+
18
+ あと、動作確認の際にいくつか不具合を見つけたので修正しています。
19
+  赤色[行頭がマイナス記号]の行 -> 削除
20
+  緑色[行頭がプラス記号]の行 -> 追加
21
+
22
+ mergePdfs関数については、コメントに記載の通り、https://qiita.com/mat_aaa/items/d77320769b5ac837a98b に記載のコードを参照してください。 
23
+ (長すぎて回答欄に書けないため)
24
+
25
+
11
26
  ```diff
12
- function CreatePdf(){
13
27
 
28
+ // シートIDの存在を確認する関数。
29
+ // 指定したspreadsheetにsheetIdで指定したIDのシートが存在するか確認する。
30
+ // 引数:spreadsheet:対象のスプレッドシート。sheetId:確認対象のシートID
31
+ // 返値:存在する場合true, 存在しない場合false。
32
+ +function existSheetId(spreadsheet, sheetId){
33
+ + var sheets = spreadsheet.getSheets();
34
+ + for(var i = 0; i < sheets.length; i++){
35
+ + if(sheets[i].getSheetId() === sheetId) return true; // 「===」にしないと、sheetIdが空白の場合trueとなってしまう。
14
- (略)
36
+ + }
37
+ + return false;
38
+ +}
15
39
 
16
- //表紙の6〜i行目に記載されたSheetIdに基づきPDFを生成する。
17
- for (var i = 6; i <= SheetIds.length + 6; i++) {
18
- var shId = sheet.getRange(i, 29).getValue(); //指定シート指定範囲値を取得
40
+ function CreatePdf(){ //当該スプレッドシートをPDFに変換して指定のフォルダに保存するScript
19
- + if (!ss.getSheetByName(shId)){ // 指定したシートIDが存在しない場合
20
- + Logger.log(`シートID:${shId}は存在しません。`);
21
- + sheet.getRange(i, 30).setValue("シート不存在"); //シートIDの右隣りのセルに「シート不存在」と書き込む
22
- + continue; // PDF書き込み処理をスキップして、次の行に移る
23
- + }
24
41
 
42
+ var folderId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; //一時保管用のフォルダIDを定義
43
+ var ss = SpreadsheetApp.getActiveSpreadsheet(); //アクティブなスプレッドシートを取得
44
+ var sheet = ss.getSheetByName(sheetName2); //スプレッドシートの名前を取得
45
+ var LastRow = sheet.getRange(6, 29, 205, 1).getValues().filter(String).length; //空白の要素を除いた取得指定のスプレッドシートの長さを取得
46
+ - var SheetIds = sheet.getRange(6, 29, LastRow, 1).getValues(); //指定範囲の値(シートID)を取得
47
+ + // LastRowに入っているのは、最終行番号ではなく、シートIDの要素数なので、6を足す必要あり。(途中に空白のセルがない前提ならば本当は5(6-1)でよい。)
48
+ + var SheetIds = sheet.getRange(6, 29, LastRow + 6, 1).getValues(); //指定範囲の値(シートID)を取得
49
+ var ssId = ss.getId(); //アクティブなスプレッドシートのIDを取得
50
+ var date = new Date(); //今日の日時情報を取得
51
+ var dateString = Utilities.formatDate(date, "Asia/Tokyo", "yyyyMMddHHmmss"); //日時情報を文字列に変換
52
+
25
- var name = i + ".pdf";
53
+ + var tempFileNames = [] // 一時ファイルのファイル名格納用の配列。
54
+ //表紙の6〜i行目に記載されたSheetIdに基づきPDFを生成する。
55
+ for (var i = 6; i <= SheetIds.length + 6; i++) { //「6」は繰り返しスタートの行数分をプラス
56
+ var shId = sheet.getRange(i, 29).getValue(); //指定シートの指定範囲の値を取得
57
+ + if (existSheetId(ss, shId) == false){ //シートIDが存在するかどうか判定
58
+ + Logger.log(`シートID:${shId}(${i}行目)は存在しません。`);
59
+ + sheet.getRange(i, 30).setValue("シートID不存在"); //シートIDが存在しない場合右隣りのセルに書き込む
60
+ + continue;
61
+ + }
62
+
63
+ var name = i + ".pdf"; //保存ファイルの名前を形式指定
26
- var token = ScriptApp.getOAuthToken();
64
+ + tempFileNames.push(name) // 一時ファイル名を格納する。
65
+ var token = ScriptApp.getOAuthToken(); //アクセストークンを取得しAPIリクエストを送信する
27
- var baseUrl = "https://docs.google.com/spreadsheets/d/" + ssId + "/export?gid=" + shId;
66
+ var baseUrl = "https://docs.google.com/spreadsheets/d/" + ssId + "/export?gid=" + shId; //スプレッドシートをPDF出力するためのURLを設定
67
+ var pdfOptions //PDF出力のオプションを設定(URLの組み立て)
68
+ = "&exportFormat=pdf&format=pdf" //ファイル形式の指定 pdf / csv / xls / xlsx
69
+ + "&size=A4" //用紙サイズ (A4)
70
+ + "&portrait=true" //用紙の向き true: 縦向き / false: 横向き
71
+ + "&fitw=true" //ページ幅を用紙にフィットさせるか true: フィットさせる / false: 原寸大
72
+ + "&top_margin=0.50" //上の余白を設定
73
+ + "&right_margin=0.50" //右の余白を設定
74
+ + "&bottom_margin=0.50" //下の余白を設定
75
+ + "&left_margin=0.50" //左の余白を設定
76
+ + "&horizontal_alignment=CENTER" //水平方向の位置を設定
77
+ + "&vertical_alignment=TOP" //垂直方向の位置を設定
78
+ + "&printtitle=false" //スプレッドシート名の表示有無 trueで表示あり、falseで表示なし(記述方法 "&sheetnames=true")
79
+ + "&sheetnames=false" //シート名の表示有無 trueで表示あり、falseで表示なし(記述方法 "&sheetnames==true")
80
+ + "&note=false" //???
81
+ var url = baseUrl + pdfOptions; //PDFを作成するためのURL
82
+ var options = {headers: {'Authorization': 'Bearer ' + token}}; //headersにアクセストークンを格納する
83
+ var blob = UrlFetchApp.fetch(url, options).getBlob().setName(name); //PDFを作成する
84
+ var folder = DriveApp.getFolderById(folderId); //PDFの保存先フォルダを指定
85
+ folder.createFile(blob) //PDFを指定したフォルダに保存する
86
+ Logger.log(i) //
87
+ var staySecond = 2 //「秒数」を設定(PDFにする処理がHTTP(S)の通信を必要とするため以下の処理が必要)
88
+ Utilities.sleep(staySecond * 1000); //意図しないエラーを防ぐため一時的に処理を遅らせる処理を設定(時間がミリ秒単位のため1000掛ける)
89
+ }
90
+
91
+ //一時保管フォルダのファイル一覧を取得して、1つのPDFに統合する。
92
+ - var iteratorList = folder.getFiles(); //「folder」に対して全てのファイルを取得する
93
+ - var pdfList = []; //リスト用の空の一次元配列を作成
94
+ - var pattern = /.*.pdf$/; //拡張子(ファイルのタイプのこと:「.xlsx」「.pdf」など)の指定(正規表現)
95
+ - while (iteratorList.hasNext()){ //「iteratorList」に対して一時保管フォルダにまだ取り出していないファイルが存在するかを判定
96
+ - var file = iteratorList.next(); //「iteratorList」に対して反復処理でまだ取り出していないファイルがあれば「file」に格納
97
+ - if (pattern.test(file.getName())){ //ファイルの拡張子(ファイルのタイプのこと:「.xlsx」「.pdf」など)をチェック
98
+ - pdfList.push(file); //一次元配列に格納
28
- var pdfOptions
99
+ - }
100
+ - }
29
101
 
102
+ +// getFilesだと、作成日時が新しい順に取得してしまい、統合後のページの順番が逆になるため
103
+ +// 一時ファイル名を格納した配列を利用して、出力順に格納する。
104
+ + var pdfList = [];
105
+ + for(var i = 0; i < tempFileNames.length; i++){
106
+ + pdfList.push(folder.getFilesByName(tempFileNames[i]).next());
30
- (以下略)
107
+ + }
31
108
 
109
+ var mergedFileName = FileName + dateString + ".pdf"; //結合後のPDFファイルのファイル名を指定
110
+ mergedFile = mergePdfs(folder, mergedFileName, pdfList); //PDFの結合を実行
111
+ - a = merge // 不要なので削除。
112
+ Logger.log("PDFs merged")
113
+
114
+ //一時保管フォルダから統合したPDFを検索して、指定フォルダに移動させる。
115
+ var files = folder.getFilesByName(mergedFileName); //「folder」に対して全ての結合後のPDFファイルのファイル名を「files」に格納       
116
+ while (files.hasNext()) { //「filse」に対して一時保管フォルダにまだ取り出していないファイルが存在するかを判定
117
+ var file = files.next();
118
+ var fileName = file.getName(); //「file」に対して格納されている全てのファイル名を「fileName」に格納
119
+ console.log(fileName);
120
+ }
121
+ var storage = DriveApp.getFolderById("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); //結合後のPDFファイルを格納するフォルダIDを設定
122
+ file.moveTo(storage); //「file」に対して作成したファイルを指定先のフォルダに移動させる
123
+ Logger.log("Merged PDF moved")
32
124
 
125
+ //一時保管フォルダに残された個別PDFを削除する。
126
+ var individualFiles = folder.getFiles(); //「folder」に対して全てのファイル名を取得
127
+ while(individualFiles.hasNext()){       //「individualFiles」に対してまだ取り出していないファイルが存在するかを判定
128
+ var file = individualFiles.next(); //「individualFiles」に対して反復処理でまだ取り出していないファイルがあれば「file」に格納
129
+ file.setTrashed(true); //「file」に対してファイルを削除
130
+ }
131
+ Logger.log("Individual files trashed")
132
+
133
+ //おめでとう
134
+ Browser.msgBox("指定のフォルダにPDFが出力されました") //
135
+
136
+ }
137
+
138
+ function mergePdfs(directory, name, pdf_list) {
139
+
140
+ https://qiita.com/mat_aaa/items/d77320769b5ac837a98b に記載のコードを参照のこと。
141
+ }
33
142
  ```

1

エラー処理について追加

2021/04/24 06:28

投稿

退会済みユーザー
answer CHANGED
@@ -3,4 +3,31 @@
3
3
  ```
4
4
  の部分で取得しているシートIDが誤っている(存在しないシートIDを指定している)可能性があります。
5
5
 
6
+ 下記のコード例(色つきの追加部分)では、
7
+ 指定されたシートIDが存在しない場合、そのシートのPDF出力をスキップし
8
+ シートIDが書かれているセルの右隣に「シート不存在」と書き込み
9
+ 次のシートIDの処理に移ります。
10
+
11
+ ```diff
12
+ function CreatePdf(){
13
+
14
+ (略)
15
+
16
+ //表紙の6〜i行目に記載されたSheetIdに基づきPDFを生成する。
17
+ for (var i = 6; i <= SheetIds.length + 6; i++) {
18
+ var shId = sheet.getRange(i, 29).getValue(); //指定シートの指定範囲の値を取得
19
+ + if (!ss.getSheetByName(shId)){ // 指定したシートIDが存在しない場合
6
- `Logger.log(shId)` 等して、適切なシートIDが変数`shId`に入っているか確認していかがでょうか
20
+ + Logger.log(`シートID:${shId}存在ません`);
21
+ + sheet.getRange(i, 30).setValue("シート不存在"); //シートIDの右隣りのセルに「シート不存在」と書き込む
22
+ + continue; // PDF書き込み処理をスキップして、次の行に移る
23
+ + }
24
+
25
+ var name = i + ".pdf";
26
+ var token = ScriptApp.getOAuthToken();
27
+ var baseUrl = "https://docs.google.com/spreadsheets/d/" + ssId + "/export?gid=" + shId;
28
+ var pdfOptions
29
+
30
+ (以下略)
31
+
32
+
33
+ ```