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

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

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

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

Google Apps Script

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

Q&A

解決済

2回答

1112閲覧

最終行のみスクリプトを実行したいです

MAIMAIMAIN

総合スコア2

Google スプレッドシート

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

Google Apps Script

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

0グッド

0クリップ

投稿2022/11/25 05:58

編集2022/11/25 13:16

前提

ここに質問の内容を詳しく書いてください。

送付履歴一覧(Google Seets)から
自動で書類送付状(Google Doc)を作成するシステムを作っています。

実現したいこと

ここに実現したいことを箇条書きで書いてください。

新たに追加記入した行のみ、スクリプトを実行させたい
トリガーの設定 19番目にあたるT列に”作成”と入力があった場合に、送付状作成を開始させたい。

 

発生している問題・エラーメッセージ

①実行を押すと、一覧表の最初の送付物データから最終行まで、実行のたびに全部の送付状が実行の度毎回作られてしまします、、、、、。
②トリガーを編集に設定したら、送付内容を記載している最中に送付状作成が自動で始まってしまい、作成された送付状が必要事項が入っていなかったです。

該当のソースコード

GAS

試したこと

ネット検索しても、分からずこちらに質問をさせていただきました。どうぞよろしくお願い致します。

やってほしいことだけを記載した丸投げの質問とのコメントを頂きました。
申し訳ありませんでした。
初めてコードを触ります。インターネットで解説を探しながらここまで作成したのですが、
かれこれ数日検索しておりますが私の知識不足もありこれだ!と思う解決方法が見つけられずにおります。
恥ずかしながら書いているものがどう動いているのか、数値を変えたりして確認、納得して進めている状態です。
現在、最終行の取得方法を見つけた為、
最終行を取得、その行に対して、下記のスクリプトが動いてくれればよいのではと考え、
下記スクリプトの中に取得した最終行の情報をそのように入れれば、
その行のみ実行してくれるのかを探しています。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

以下、作成しているコード?です。

//テンプレートをコピーしスプレッドシートの単語に置換する
function MakeDocFromTemplate() {

const SH_NAME = "記入シート" //読み込みシート名  ★このシートの作業させるシートタブ名 固定
const BASE_URI = "//////" //元となる送付状たたきファイルのURI ★固定
const DEST_FOLDER = "//////" //コピー先格納フォルダのURI ★固定

const sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SH_NAME)

//元となるファイルを取得
const basefile = DriveApp.getFileById(BASE_URI)

//コピー先のフォルダ
const destfolder = DriveApp.getFolderById(DEST_FOLDER)

const values = sh.getDataRange().getValues()

console.log(values[0])

let setdata = [] //ステータスとURL用のバッファ 

for (i = 5; i < values.length; i++) {
setDocdata(values[i],basefile,destfolder)
console.log(values[i][ID_URL])

setdata.push(["",values[i][ID_URL]]) //バッファに要素を追加する

}
//setdata() "作成済み",URL をシートに反映させる
console.log(setdata)
sh.getRange(6, 20, values.length -5, 2).setValues(setdata)
}

// 0 1 2 3 4 5 6 7 8 9 10         19
//'担当者名','Date','集計月','Summary','自社/立替 返信用付','立替先社名','To','Remarks column 2','Remarks column 1','自社確認用/内容詳細/備忘録等','payee invoice number','送付状URL',
const ID_REQUESTER = 5 //依頼者・立替先下記社名
const ID_NAME = 6 //送付をする先の人の会社・名前
const ID_DOCUMENT2 = 7 //送付物の種類
const ID_DOCUMENT1 = 8 //送付の内容詳細
const ID_URL = 20 //URL
const ID_DATE = 21 // 文字変換した日付

function setDocdata(setdata, bfile, dfolder) {

//新しいファイル名
console.log(setdata[1])

const newfile = bfile.makeCopy(setdata[21]+""+setdata[5]+""+setdata[6], dfolder)

const newid = newfile.getId()
const newurl = newfile.getUrl()

console.log(newurl)

const basedoc = DocumentApp.openById(newid)

console.log(basedoc.getName())

const basebody = basedoc.getBody()

//文字列の置換
//'', '名前', '郵便番号', '住所', '受注番号', '商品名', 'ステータス', 'URL'
basebody.replaceText('{To}', setdata[ID_NAME])
basebody.replaceText('{立替先社名}', setdata[ID_REQUESTER])
basebody.replaceText('{Remarks column 2}', setdata[ID_DOCUMENT2])
basebody.replaceText('{Remarks column 1}', setdata[ID_DOCUMENT1])

setdata[ID_URL] = newurl //新しいURL

}
イメージ説明
イメージ説明

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

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

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

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

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

bebebe_

2022/11/25 08:00

参考にしたサイトなどあればURLもあったほうがいいかと思います。 最終行の取得について const values = sh.getDataRange().getValues()の次の行から const lastvalues = values[values.length - 1]; console.log(lastvalues); let setdata = [] //ステータスとURL用のバッファ  setDocdata(lastvalues,basefile,destfolder) console.log(lastvalues[ID_URL]) setdata.push(["",lastvalues[ID_URL]]) //バッファに要素を追加する //setdata() "作成済み",URL をシートに反映させる とした場合はどうですか?
Cocode

2022/11/25 10:33 編集

①確認させてください。 ・間違った内容を記入してしまっても問答無用でdocが作成されてしまいますが、そういったヒューマンエラーは考慮されていますか? ・「新たに追加記入」とは具体的にどう言う意味でしょうか?最終行に追加されたものということでしょうか? ・その場合、修正した既存行に変更を加えた場合どうなりますか? ・変更を加えた場合もdocを作成し直すとして、特定のセルが「作成」のまま変更を加えたら、全部の列を変更し終わってないのに、1セル変更するたびにdocが作成されてしまうというヒューマンエラー発生の可能性が高いのではないのでしょうか。 ・以上から、「記入したら実行」は個人的には非推奨です。 ・代わりに全行チェックボックスを設け、発行したい行にチェックをいれ、「送付状を発行する」ボタンをクリックしたら発行されるようにするのはいかがでしょうか?または特定のセルが「作成」になっている行のみ「送付状を発行する」ボタンをクリックすることで発行される仕様はいかがでしょうか。 ②お願い こちらで不具合の再現を行いたいと思います。 スプレッドシートとドキュメントのスクリーンショットを提示していただくことは可能でしょうか? それをみて同じものをつくって検証します。
MAIMAIMAIN

2022/11/25 11:51

bebebe_様 そうなのですね!お教えくださりありがとうございました。 参考にしたものは、こちらです。部分的に数字を変え 私の利用している送付履歴一覧スプレットシートに対応するものにまでは、完成ていると思っております。 参考にしたURLはこちらです。 https://technical.verybestcbp.com/gasdosfromsp/ https://technical.verybestcbp.com/gasdocfromsp2/ また、最終行の取得について・・・についても重ねてありがとうございます。 やってみようとおもいます!
MAIMAIMAIN

2022/11/25 12:26

Cocode 様 私のつたない説明文章をご丁寧に見ていただき、ありがとうございました。 現物があるほうがずっとわかりやすいですね、ご指摘ありがとうございました。 後ほど、位置が同じ簡易スプレットシートを作成してUP致します。 もしお時間がありました見てみていただけましたら幸いです。 頂いたご質問に回答をさせてください。 ①送付物一覧表  スプレットシートで、発生した毎に最下行に入力。 入力内容は左から処理担当者名、日付、送付先、内容物・・・・を右に向かって横に入力をしていく形です。 ■間違った内容を記入したら・・・ 元となる送付履歴一覧はヒューマンエラー防止として7割がたプルダウン選択にしました。 日付と送付先担当者名、内容物名が手入力になります。ここに関しては毎度全く異なる為、致し方ない部分と認識しております。 ■修正した既存行に変更を加えた場合 基本的に送付物一覧に記入した(最下行)直後に、作成された送付リストを出力します。 よって、内容に誤りがあったら出力したものを確認若しくは出力する際に気がつきたいところです。 もし3件の発送物ABCがありいっぺんに出力しようとした場合、(こちらのほうが現実的な動きですね) その一番最初に入力したデータは下から3番目、送付状は誤った情報で作成済みになるとおもいます。 誤りがあった場合には、その行を消して、一番下に書き直すのがよいのでしょうか・・・。 変更したら、送付状データも作り直してくれたらういいですが、そこまで作れるか少し自信がありません。 ■変更を加えた場合もdocを作成し直すとして、特定のセルが「作成」のまま変更を加えたら、全部の列を変更し終わってないのに、1セル変更するたびにdocが作成されてしまうというヒューマンエラー発生の可能性が高いのではないのでしょうか。 この部分は、②の不具合より考えました。 列を1つ増やし、プルダウンで【作成(なんでもよいのですが)】をチョイス。その【作成】の入力が行われた(変更があった)列に対応する[行]データにのみ上記スクリプトが働いてくれるような式を作れたらた良いのかな?と考えていました。 ■以上から、「記入したら実行」は個人的には非推奨です。→はい、そう思いました。 ■代わりに全行チェックボックスを設け、発行したい行にチェックをいれ、「送付状を発行する」ボタンをクリックしたら発行されるようにするのはいかがでしょうか?または特定のセルが「作成」になっている行のみ「送付状を発行する」ボタンをクリックすることで発行される仕様はいかがでしょうか。 チェックボックスは非常に魅力的です(既存行もチェックボックスなら再作成が容易です)し、 送付状を発行するボタンも同じく。 まだそこまでたどり着けませんが、私では思いつけない的確なご意見とアイデアです。 ありがとうございます。 どのような形にしていったら良のかが見えて気持ちが楽になりました。 ②お願い こちらで不具合の再現を行いたいと思います。 スプレッドシートとドキュメントのスクリーンショットを提示していただくことは可能でしょうか? それをみて同じものをつくって検証します。 可能です。実物に似ているものを作成してみます。申し訳ございませんが少々お待ちください。 見ず知らずのものに親切にしてくださり、恐縮です。
MAIMAIMAIN

2022/11/25 14:07

Cocode様の教えてくださったコードを試しましたが、うまくいかずでした。 シートのデータ開始が、6行目からなのが関係しているのかもしれません。もう少し調べてみます。 ありがとうございました。 23:02:36 エラー Exception: The number of rows in the data does not match the number of rows in the range. The data has 1 but the range has 4. MakeDocFromTemplate @ (自宅作成の式)送付状自動作成.gs:25
Cocode

2022/11/25 14:32 編集

あら?私のコードとはなんでしょう…?
MAIMAIMAIN

2022/11/25 14:39

Cocode様 別の方(bebebe_様)のコードを入力してみての結果報告でした。 大変失礼いたしました。
Cocode

2022/11/25 16:30

現物サンプルありがとうございます! コードの件了解です!
MAIMAIMAIN

2022/11/25 16:37

こちらこそです。ありがとうございます。 あれから、ボタン、ボタンにスクリプトを付ける、ボタンクリックすると送付状URLが貼り付けられる(ただし一斉に全行分) チェックボックスをつける この部分までできました!本日はここまでで断念しました。引き続き頑張ります。
MAIMAIMAIN

2022/11/27 10:13

ryouuuuoyr様 ありがとうございます!試してみます!! Cocode様 ご連絡が遅くなり申し訳ございません。 ありがとうございます!今から作業致します!! ここまで見てくださり感謝しかありません。
guest

回答2

0

ベストアンサー

ご提案

コメント欄でのやりとりを踏まえ、「入力されたら」ではなく「チェックボックスにチェックした上でボタンを押したら」発行する仕様をご提案いたします。

図形へのスクリプト割り付けはご自身でお調べになってできたとのことで、そちらの解説については割愛させていただきます。

画面

イメージ説明
イメージ説明
イメージ説明
イメージ説明

コード例

javascript

1function issueCoverLetters() { 2 // テンプレートとして仕様するGoogleドキュメント 3 const TEMPLATE_DOC = DriveApp.getFileById('テンプレートドキュメントのファイルID'); 4 // 発行した送付状を保存するフォルダ 5 const DEST_FOLDER = DriveApp.getFolderById('保存先のフォルダID'); 6 // スプレッドシートの一覧表のデータ開始行番号 7 const DATA_START_ROW = 6; 8 9 const ss = SpreadsheetApp.getActiveSpreadsheet(); 10 const sheet = ss.getActiveSheet(); 11 12 const lastRow = sheet.getLastRow(); 13 const lastCol = sheet.getLastColumn(); 14 15 // データがが入力されている範囲を取得(私の画像だと、6−9行&A-U列) 16 const range = sheet.getRange(DATA_START_ROW, 1, lastRow - DATA_START_ROW + 1, lastCol); 17 // 上記範囲で全ての値を取得してきた上で、チェックボックスにチェックがいれられているものだけに絞った2次元配列を生成+先頭に行番号を追加 18 const checkedRows = range.getValues().flatMap((arr, i) => arr[0] ? [[i + DATA_START_ROW, ...arr]] : []); // ① 19 // 2次元配列の中身が何個かカウント=trueの行がが何個あるか 20 const count = checkedRows.length; 21 22 // あとでポップアップ表示するためにuiを生成 23 const ui = SpreadsheetApp.getUi(); 24 25 // 1つもチェックされていなかったら(trueの要素が0こだったら) 26 if (!count) { 27 // お知らせのポップアップを表示 28 ui.alert('処理中止', '選択されていません。', ui.ButtonSet.OK); 29 // ここで処理を終了(以降の行は実行されない) 30 return; 31 } 32 33 // 書類発行確認のポップアップ表示 34 const response = ui.alert('作成確認', `${count}件の書類送付状を発行しますか?`, ui.ButtonSet.YES_NO_CANCEL); 35 36 // 「いいえ」「キャンセル」が選択されたら 37 if (response !== ui.Button.YES) { 38 // お知らせのポップアップを表示 39 ui.alert('処理中止', '発行をキャンセルしました。', ui.ButtonSet.OK); 40 // ここで処理を終了(以降の行は実行されない) 41 return; 42 } 43 44 // 現在の年月日を取得 45 const now = new Date(); 46 const year = now.getFullYear(); 47 const month = now.getMonth() + 1; 48 const date = now.getDate(); 49 50 // trueの行たち1つずつに繰り返し処理 51 for (const row of checkedRows) { 52 // スプシから取得してきた値で使用する分を、変数に格納 53 const rowNumber = row[0]; // 行番号 54 const sender = row[7]; // 立替先社名 55 const to = row[8]; // 宛名 56 const docType = row[9]; // 書類の種類 57 const detail = row[10]; // 内容 58 59 // テンプレートドキュメントを複製 60 const newDoc = TEMPLATE_DOC.makeCopy(`書類送付状_${sender}_${to}_${year}${month}${date}`, DEST_FOLDER); 61 // 複製したドキュメントのIDを取得して開く 62 const newDocId = newDoc.getId(); 63 const doc = DocumentApp.openById(newDocId); 64 // 複製したドキュメントの本文を取得 65 const docBody = doc.getBody(); 66 67 // 本文の文字を書き換え 68 docBody.replaceText('{年月日}', `${year}${month}${date}`) 69 .replaceText('{To}', to) 70 .replaceText('{立替先社名}', sender) 71 .replaceText('{書類の種類}', docType) 72 .replaceText('{内容}', detail); 73 74 // 複製したドキュメントのURLを取得 75 const newDocUrl = newDoc.getUrl(); 76 // スプシの該当セルを取得し、URLを出力 77 const urlCell = sheet.getRange('U' + rowNumber); 78 urlCell.setValue(newDocUrl); 79 } 80 81 // 完了のお知らせポップアップを表示 82 ui.alert('✅ 処理完了', `${count}件の書類送付状を発行しました。`, ui.ButtonSet.OK); 83}
①について

checkedRowsの中身はこんな感じです。

javascript

1[ 2 [7, 3 true, 4 '早川', 5 Sat Nov 26 2022 00: 00: 00 GMT + 0900(Japan Standard Time), 6 Tue Nov 01 2022 00: 00: 00 GMT + 0900(Japan Standard Time), 7 '失念', 8 '立替', 9 'BBBB社', 10 '企画部 高橋様', 11 '返信書類', 12 '▲▲▲▲▲書類', 13 '', 14 '', 15 '', 16 '', 17 '', 18 '', 19 '', 20 '', 21 '', 22 '', 23 '' 24 ], 25 [8, 26 true, 27 '早川', 28 Sun Nov 27 2022 00: 00: 00 GMT + 0900(Japan Standard Time), 29 Tue Nov 01 2022 00: 00: 00 GMT + 0900(Japan Standard Time), 30 '失念', 31 '立替', 32 'CCCC社', 33 '統括事業本部 谷様', 34 '指図書', 35 '●●の◆◆、・・・', 36 '速達で送付', 37 '', 38 '', 39 '', 40 '', 41 '', 42 '', 43 '', 44 '', 45 '', 46 '' 47 ] 48]

投稿2022/11/26 15:06

Cocode

総合スコア2314

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

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

MAIMAIMAIN

2022/11/27 11:49

Cocode様 この度は素晴らしいコードをありがとうございました。 チェックボタンを入れた後にボタンを押すと無事に送付状が作成され、 しかも既に作成してURL表示がされてしまっている行にて修正をして再度ボタンクリックしても、最新情報のURLに書き換わっていました。 涙が出そうです。 落ちている動画やサイト説明からコピーして作ったコードを、何とか自分仕様にとがんばっておりましたが、 どう頑張っても書いてくださったコードを作ることはできなかった思います。 きっとあまりの知識のなさに部分サポートではなく、すべてのコードをお教えいただき、 Feeを取るべきプロのお仕事だったのだと思います。 大きなお礼はできないのですが心ばかりですがお礼をしたいです。 どのようにご連絡をお取りすればよろしいでしょうか。 今回いただいたコードを元に、今後自分できちんと管理できるよう 一つずつコードを勉強をさせていただこうと思います。 他の方の質問なども拝見し全くの素人が書き込む掲示板ではないことに後から気がつき、 にもかかわらずこのような対応を下さる方に巡り合え感謝いたします。
Cocode

2022/11/27 12:01

お役に立ててよかったです…! 本来は質問者様のコードのどこが不具合を起こしているのか指摘できれば、より質問者様のためにはなったのでしょうが、私は他の方のコードを読み込む力があまりなく(泣) 一からコードを書いてみた次第ですので、あまり負担に思われないでください。 (私が楽しただけです笑) ここまで喜んでいただけて、こちらも本当に嬉しいです。
MAIMAIMAIN

2023/08/01 02:15 編集

cocode様 その節は大変お世話になりありがとうございました。 ご相談があるのですが、個人的に有償でエクセル若しくはGASでの、やりたい事をご依頼をさせて頂く事は可能でしょうか? どのようにご連絡をしたら良いか分からず、以前の質問版にてすみません。
Cocode

2023/08/01 22:09

お世話になります。頼っていただけて光栄です。 GASは趣味程度に触れているだけですので、お仕事を受けるほどの実力はなく、大変心苦しいのですがご遠慮させていただきたく存じます。 お力になれず申し訳ございません。お声がけくださりありがとうございました。
guest

0

for (i = 5; i < values.length; i++) { setDocdata(values[i],basefile,destfolder)

これでDocを作成しているのだと思いますがsetDocdataを

for (i = 5; i < values.length; i++) { if(sh.getRange(i,19).isBlank()){ setDocdata(values[i],basefile,destfolder) console.log(values[i][ID_URL]) //以下略 } }

のようにすれば①は解決するかもしれません。

投稿2022/11/26 07:58

編集2022/11/26 09:32
ryouuuuoyr

総合スコア5

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問