🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Google スプレッドシート

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

Google Apps Script

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

ChatWork

業務の効率化を目的としたコミュニケーションツール。 グループチャット、ビデオ・音声通話、ファイル共有、タスク管理などの機能を備えています。マルチデバイス対応で、ブラウザだけでなくタブレットやスマートフォンでも利用可能です。

Q&A

解決済

1回答

1769閲覧

Chatworkに通知するGoogle Apps Scriptが動作しない

SECU

総合スコア4

Google スプレッドシート

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

Google Apps Script

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

ChatWork

業務の効率化を目的としたコミュニケーションツール。 グループチャット、ビデオ・音声通話、ファイル共有、タスク管理などの機能を備えています。マルチデバイス対応で、ブラウザだけでなくタブレットやスマートフォンでも利用可能です。

0グッド

0クリップ

投稿2019/11/21 08:12

前提・実現したいこと

前任者から引き続いたGoogleSpreadSheetに編集した内容をChatworkに通知するスクリプトが動作しません。
※作成者のGoogleアカウントは削除済みな為、スプレッドシート及びスクリプトエディタを新規ファイルにコピーして作成しました。

①ガード節(投稿を行わないタイミングの場合、プログラムを終了する)
②メッセージボックスによるユーザーへの確認
③chatworkにメッセージを投稿
④後処理

このファイルは上記4つの処理の流れで作成されているようですが、対象のSpreadSheetを開いたときに再下部のセルへジャンプする
動きしか実現できておりません。
再下部の行に必要事項すべて入力すると投稿しますか?のポップアップが出るようなのですが、特にでませんでした。

恥ずかしながらプログラム未経験の為、ネット情報を手掛かりに「関数をデバッグ」を実行して以下のエラーまで辿りついたレベルです。
各エラーをどのように修正したらよいか不明なエラーがある為、相談させてください。
よろしくお願いいたします。

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

それぞれの関数をデバッグしたところ、以下のエラーが出ております。

■エラー1<関数getLastRowのエラー> 範囲は見つかりませんでした at getLastRow(通知:21) ■エラー2<関数createMessageのエラー> メソッド getRange((class),number,number,number) が見つかりません。 at createMessage(通知:143) ■エラー3<関数cronPostIncompleteQuestionsのエラー> ReferenceError: 「spreadsheet」が定義されていません。 at cronPostIncompleteQuestions(通知:158) ■エラー4<関数postChatworkMessageのエラー> 指定された属性の値が無効です: Header:null at postChatworkMessage(通知:180) ■エラー5<関数getChatworkMembersInfoByRoomIdのエラー> 指定された属性の値が無効です: Header:null at getChatworkMembersInfoByRoomId(通知:195)

該当のソースコード

GoogleAPPS

1///** 2// * ファイルオープン時の処理 3// * シートの最下行を選択する。 4// * (毎回一番下までスクロールするのが面倒くさいため・・) 5// */ 6function onOpen() { 7 if(SpreadsheetApp.getActiveSheet().getSheetName()!=SHEET_NAME_INQUIRY){ 8 return; 9 } 10 11 SpreadsheetApp.getActiveSheet().setActiveSelection("B" + getLastRow("B")); 12 SpreadsheetApp.getActiveSpreadsheet().toast("カーソルを最下行に移動しました"); 13} 14// 15///** 16// * 最下行の取得 17// * column:列名 18// */ 19function getLastRow(column) { 20 var lastRow = SpreadsheetApp.getActiveSheet().getMaxRows(); 21 var values = SpreadsheetApp.getActiveSheet().getRange(column + "1:" + column + lastRow).getValues(); 22 23 for (; values[lastRow - 1] == "" && lastRow > 0; lastRow--) {} 24 return lastRow; 25} 26 27/** 28* シートの値変更時に動作するイベント 29* ①ガード節(投稿不要なタイミングであれば、プログラムは何も行わず終了する) 30* ②メッセージボックスによるユーザーへの確認(chatworkに投稿を行うかどうか / chatworkに投稿を行う場合、To通知を行うかどうか) 31* ③chatworkにメッセージを投稿 32* ④後処理 33*/ 34function onValueEdit(event){ 35//function onEdit(event){ 36 Logger.log("start"); 37 38 /************************ 39 ①ガード節(投稿を行わないタイミングの場合、プログラムを終了する) 40 ************************/ 41 // 問い合わせ一覧シートを取得 42 const inquiriesSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME_INQUIRY); 43 // 編集されたセルを取得 44 try { 45 const editedRange = event.source.getActiveRange(); 46 }catch(e){ 47 // 時々エラー[まず有効なシートを選択してください。]が発生する模様・・ 48 // 問題はないがエラー通知メールが邪魔なので握りつぶす 49 Logger.log(e); 50 return; 51 } 52  Logger.log("check"); 53 const editedRow = editedRange.getRow(); 54 const editedColumn = editedRange.getColumn(); 55 // 1. 対象シートでなければ、終了 56 if(editedRange.getSheet().getSheetId() != inquiriesSheet.getSheetId()){return;} 57 // 2. 記入した行のchatwork通知状態が[済]なら、終了 58 if(inquiriesSheet.getRange(editedRow, COLUMN_CHATWORK_POST_STATUS).getValue()==="済"){return;} 59 // 3. 記入したセルの行が問い合わせの記入欄でなければ、終了 60 if(editedRow < ROW_FIRST_DATA){ return;} 61 // 4. 記入したセルの列が[必須 問い合わせ記入欄]でなければ、終了 62 if(editedColumn < COLUMN_FIRST_REQUIRED || editedColumn > COLUMN_LAST_REQUIRED + 1){ return;} 63 // 5. 記入したセルの行の[必須 問い合わせ記入欄]の列が全て入力されていなければ、終了 64 const requiredValues = inquiriesSheet.getRange(editedRow, COLUMN_FIRST_REQUIRED, 1, COLUMN_LAST_REQUIRED - COLUMN_FIRST_REQUIRED + 1).getValues(); 65 for(var i = 0; i < requiredValues[0].length; i++){ 66 if(!requiredValues[0][i].toString()){ 67 return; 68 } 69 } 70 71 /************************ 72 ②メッセージボックスによるユーザーへの確認 73 ************************/ 74 // 全員にTo指定をするかどうか確認する 75 var selection = Browser.msgBox("【chatwork通知の確認】","chatworkに通知を行います\n\n全員にTo指定して、投稿を行いますか?\n・はい:全員にTo指定でメッセージを投稿する\n・いいえ:Toを指定せずにメッセージのみ投稿する\n・キャンセル:投稿を行わず終了します", Browser.Buttons.YES_NO_CANCEL); 76 // canselの場合、通知を行わず終了 77 if(selection === "cancel"){ 78 SpreadsheetApp.getActiveSpreadsheet().toast("通知を行いませんでした。"); 79 return; 80 } 81 // ChatworkのTo通知を行うかどうか、ユーザーの選択によって決定する 82 var notifyAllMembers = selection == "yes" ? true : false; 83 84 /************************ 85 ③chatworkにメッセージを投稿 86 **************************/ 87 // chatworkのメッセージを作成する 88 var body = createMessage(notifyAllMembers,editedRow); 89 90 // chatworkの通知設定シートから、必要な情報を取得 91 const configSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME_CHATWORK_CONFIG); 92 const API_TOKEN = configSheet.getRange(RANGE_API_TOKEN).getValue(); 93 const ROOM_ID = configSheet.getRange(RANGE_ROOM_ID).getValue(); 94 // メッセージを投稿する 95 postChatworkMessage(API_TOKEN, ROOM_ID, body); 96 97 /************************ 98 ④後処理 99 ************************/ 100 // 投稿完了メッセージを画面に表示する 101 SpreadsheetApp.getActiveSpreadsheet().toast("Chatworkに投稿しました"); 102 // 投稿済みフラグをシートに記載する 103 inquiriesSheet.getRange(editedRow, COLUMN_CHATWORK_POST_STATUS).setValue("済"); 104} 105 106/** 107* 投稿メッセージの作成 108* 109* ・notifyAllMembers:メンバーにTo通知を行うかどうか(true:To通知する / false:To通知しない) 110* ・editedRow:編集が行われた行番号 111*/ 112function createMessage(notifyAllMembers, editedRow){ 113 /** ②投稿メッセージの作成 **/ 114 const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); 115 // 問い合わせ一覧シートを取得 116 const inquiriesSheet = spreadsheet.getSheetByName(SHEET_NAME_INQUIRY); 117 // chatworkの通知設定シートから、必要な情報を取得 118 const configSheet = spreadsheet.getSheetByName(SHEET_NAME_CHATWORK_CONFIG); 119 120 // 投稿本文を作成 121 var body = ""; 122 // To通知を行う場合、chatworkの該当ルームに所属する全員のAccountIDを取得し、Toメッセージを追加する 123 if(notifyAllMembers){ 124 const API_TOKEN = configSheet.getRange(RANGE_API_TOKEN).getValue(); 125 const ROOM_ID = configSheet.getRange(RANGE_ROOM_ID).getValue(); 126 127 // chatwork APIで当該roomに所属する全メンバーの 名前/アカウントID を取得 128 const membersInfo = getChatworkMembersInfoByRoomId(API_TOKEN, ROOM_ID); 129 // APIのレスポンスからメッセージを作成 130 var toMembers = ""; 131 for(var i = 0; i < membersInfo.length; i++){ 132 Logger.log(membersInfo[i].name); 133 toMembers += "[To:" + membersInfo[i].account_id + "]" + membersInfo[i].name + "さん\n"; 134 } 135 body += toMembers + "担当者を決定し、スプレッドシートに担当を記載して下さい(bow)"; 136 } 137 138 // メッセージ部分を作成(テンプレートをシートから取得し、置換) 139 var message = configSheet.getRange(RANGE_MESSAGE_TEMPLATE).getValue(); 140 141 // 入力された行の全データを取得 142 var lastColumn = inquiriesSheet.getLastColumn(); 143 var targetRowValues = inquiriesSheet.getRange(editedRow, 1, 1, lastColumn).getValues()[0]; 144 // 最初のデータ入力行の1行上を、置換対象文字列として取得 145 var replaceValues = inquiriesSheet.getRange(ROW_FIRST_DATA -1, 1, 1, lastColumn).getValues()[0]; 146 // メッセージのテンプレートのうち、置換対象文字列を入力データで全て置換する 147 for(var j = 0; j < lastColumn; j++){ 148 message = message.replace(new RegExp("%" + replaceValues[j] + "%", 'g'),targetRowValues[j]); 149 } 150 // 投稿本文に置換後のメッセージを追記する 151 body += message; 152 153 return body; 154} 155 156function cronPostIncompleteQuestions(){ 157 // 問い合わせ一覧シートを取得 158 const inquiriesSheet = spreadsheet.getSheetByName(SHEET_NAME_INQUIRY); 159 // chatworkの通知設定シートから、必要な情報を取得 160 const configSheet = spreadsheet.getSheetByName(SHEET_NAME_CHATWORK_CONFIG); 161 162 163} 164 165/** 166* chatworkにメッセージを投稿 167* ・apiToken:chatwork API Token 168* ・roomId:chatwork 投稿対象の部屋番号 (URL末尾#!rid*********のrid以降の部分) 169* ・body:投稿メッセージ 170*/ 171function postChatworkMessage(apiToken, roomId, body){ 172 var params = { 173 headers : {"X-ChatWorkToken" : apiToken} 174 , method : "post" 175 , payload : { 176 body : body 177 } 178 }; 179 var url = "https://api.chatwork.com/v2/rooms/" + roomId + "/messages"; 180 UrlFetchApp.fetch(url, params); //チャットワークAPIにリクエスト 181} 182 183/** 184* chatwork ルームに所属するユーザーの情報を取得 185* ・apiToken:chatwork API Token 186* ・roomId:chatwork 情報取得対象の部屋番号 (URL末尾#!rid*********のrid以降の部分) 187*/ 188function getChatworkMembersInfoByRoomId(apiToken, roomId){ 189 var params = { 190 headers : {"X-ChatWorkToken" : apiToken} 191 , method : "get" 192 }; 193 194 const url = "https://api.chatwork.com/v2/rooms/" + roomId + "/members"; 195 const response = UrlFetchApp.fetch(url, params); //チャットワークAPIにリクエスト 196 const result = JSON.parse(response.getContentText()); 197 198 return JSON.parse(response.getContentText()); 199} 200 201// 最初の問い合わせデータ行 202var ROW_FIRST_DATA = 4; 203// 最初の必須問い合わせ記入欄の行 204var COLUMN_FIRST_REQUIRED = 3; 205// 最後の必須問い合わせ記入欄の行 206var COLUMN_LAST_REQUIRED = 10; 207// chatwork投稿状態の列 208var COLUMN_CHATWORK_POST_STATUS = 12; 209 210 211/** 設定シート内のセル番地 **/ 212// API TOKENの記載セル 213var RANGE_API_TOKEN = "C2"; 214// RoomIDの記載セル 215var RANGE_ROOM_ID = "C3"; 216// 投稿メッセージの記載セル 217var RANGE_MESSAGE_TEMPLATE = "C4"; 218 219var SHEET_NAME_CHATWORK_CONFIG = "chatwork通知設定"; 220var SHEET_NAME_INQUIRY = "問い合わせ一覧";

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

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

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

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

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

macaron_xxx

2019/11/25 00:32

トリガー設定してます?
SECU

2019/11/25 07:58 編集

ありがとうございます。 トリガーを以下の通り設定することでChatworkへの通知まで問題なく動作致しましたが、 各トリガーの関数についてのデバック時のエラーは今まで通りログとして通知されてきました。 2019/11/25 16:13:20 Head スプレッドシートから - 起動時 onOpen 2019/11/25 16:13:20 Head スプレッドシートから - 起動時 getLastRow 2019/11/25 16:10:13 Head スプレッドシートから - 編集時 onValueEdit 2019/11/25 16:10:13 Head スプレッドシートから - 編集時 getChatworkMembersInfoByRoomId 2019/11/25 16:10:13 Head スプレッドシートから - 編集時 postChatworkMessage 2019/11/25 16:10:13 Head スプレッドシートから - 編集時 createMessage 2019/11/25 16:10:13 Head スプレッドシートから - 編集時 cronPostIncompleteQuestions 問題なく動作するのでこのまま利用はできますが、もしエラーを取り除く方法が分かればありがたいです。最悪エラーログを吐かないようにするだけでも結構です。
macaron_xxx

2019/11/25 07:59

トリガーを設定するのはonValueEditだけでよいです。
SECU

2019/11/25 08:17

onValueEditだけ残したところ、エラーログは発生せず、正常に動作するようになりました! 誠にありがとうございました。
guest

回答1

0

自己解決

macaron_xxxさんのアドバイス通り、onValueEditをトリガー設定にすることで、
正常に動作するようになりました。ありがとうございました。

投稿2019/11/25 08:21

SECU

総合スコア4

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問