【GAS】実践・ping送信

2021-01-13

GAS プログラミング

B!

自前ping送信。
矩形に関数を割り当てる方法、別シートの操作などを理解する。




システム要件・完成目標とイメージ

  • bloggerを更新したとき、ping送信を簡単に行えるようなツールを作成する
  • ping送信するURLの個数に制限はしない
  • データは別シートにまとめて、管理シートにボタンを設置する
  • 更新がうまくいったかどうかエラーチェックをする

スプレッドシートの準備

スプレッドシート名は任意で、2つのシートを用意します。

「manage」シート。この後ボタンを挿入します。レイアウトはお好きにどうぞ。
「data」シート。pingURLは可変にしますので、要素的には最後に置いた方がスマートです。

矩形(図形)に関数を割り当てる

まず矩形を追加します。
メニューから「挿入」→「図形描画」を選択すると、「図形描画」ウインドウが起動します。
図形を描きます。好みで良いです。今回は角丸四角形で作りました。
適当に色も変え、ダブルクリックでテキストの追加もしました。
納得いく出来になったら「保存して終了」を押して終了します。
表示位置を整え、矩形右上の「・」が縦に3つ並んだボタンを押し、「スクリプトを割り当て」を選択します。
スクリプトファイルすらまだ追加していませんが、デフォルトで「myFunction」だったはずなので、とりあえず「myFunction」にしてみます。
※もし気に食わなければ、自分の好きな関数を作ったうえで、修正をかけてください。
これで、矩形をクリックすると動作する関数の入り口が準備できました。

スクリプトエディタを起動し、プロジェクト名を適宜入力しましょう。次からコードを書いていきます。

ソースコード

  1. // -----------------------------------------------------------------------------
  2. // ping送信テスト.
  3. // -----------------------------------------------------------------------------
  4. var MngSheetName = "manage"; // 管理シート名.
  5. var DataSheetName = "data"; // データ一覧シート名.
  6. // manageシート.
  7. var MngSelectTitle = "C2"; // 更新するブログ名.
  8. var MngDebugLogX = 3; // 結果表示列.
  9. var MngDebugLogY = 11; // 〃   行.
  10. // dataシート.
  11. var DataUpdateX = 1; // 更新日記録列.
  12. var DataBlogTitleX = 2; // ブログタイトル列.
  13. var DataBlogURLX = 3; // ブログURL列.
  14. var DataBlogPingX = 4; // pingURL列.
  15. // -----------------------------------------------------------------------------
  16. // myFunction
  17. // 外部から呼び出される関数.
  18. // -----------------------------------------------------------------------------
  19. function myFunction() {
  20. var mngSheet = GetSheet( MngSheetName );
  21. var dataSheet = GetSheet( DataSheetName );
  22. var indexY = getIndexY( dataSheet, DataBlogTitleX, mngSheet.getRange( MngSelectTitle ).getValue() );
  23. var logY = MngDebugLogY;
  24. var urls = [];
  25. var data = [];
  26. // ブログタイトルが見つからなかった.
  27. if ( indexY === -1 ) {
  28. mngSheet.getRange( MngDebugLogY, MngDebugLogX ).setValue( mngSheet.getRange( MngSelectTitle ).getValue() + "が見つかりませんでした" );
  29. return;
  30. }
  31. // ping送信先を追加していく.
  32. var endX = dataSheet.getRange(indexY,dataSheet.getMaxColumns()).getNextDataCell(SpreadsheetApp.Direction.PREVIOUS).getColumn();
  33. for ( var i = DataBlogPingX; i <= endX; ++i ) {
  34. urls.push( dataSheet.getRange( indexY, i ).getValue() );
  35. }
  36. //
  37. data.push('<?xml version="1.0"?>');
  38. data.push('<methodCall>');
  39. data.push('<methodName>weblogUpdates.ping</methodName>');
  40. data.push('<params>');
  41. data.push('<param><value>' + dataSheet.getRange(indexY,DataBlogTitleX).getValue() + '</value></param>');
  42. data.push('<param><value>' + dataSheet.getRange(indexY,DataBlogURLX).getValue() + '</value></param>');
  43. data.push('</params>');
  44. data.push('</methodCall>');
  45. // 送信内容.
  46. var options = {
  47. method: "POST",
  48. payload: data.join('\n'),
  49. muteHttpExceptions : true
  50. };
  51. // 送信実行.
  52. var response = 0;
  53. for (var i=0; i < urls.length; i++) {
  54. response = UrlFetchApp.fetch( urls[i], options );
  55. // responseが200番台なら成功.
  56. // 400番台ならクライアントエラー、500番台ならサーバエラー.
  57. mngSheet.getRange( logY, MngDebugLogX ).setValue( urls[i] );
  58. ++logY;
  59. if ( (400 <= response.getResponseCode()) && (response.getResponseCode() < 600)) {
  60. // 失敗か?とりあえずlogだけ残す.
  61. mngSheet.getRange( logY, MngDebugLogX ).setValue( "エラー:" + response.getResponseCode() );
  62. ++logY;
  63. }
  64. }
  65. // 更新日の記録.
  66. dataSheet.getRange( indexY, DataUpdateX ).setValue( Utilities.formatDate( new Date(), 'Asia/Tokyo', 'yyyy/MM/dd HH:mm') );
  67. // 送信内容の確認.
  68. for (var i = 0; i < data.length; i++) {
  69. mngSheet.getRange( (logY + i), MngDebugLogX ).setValue( data[i] );
  70. }
  71. }
  72. // -----------------------------------------------------------------------------
  73. // 現在のスプレッドシートの中の指定の名前のシートを取得.
  74. // -----------------------------------------------------------------------------
  75. function GetSheet( sheetName ) {
  76. return SpreadsheetApp.getActive().getSheetByName( sheetName );
  77. }
  78. // -----------------------------------------------------------------------------
  79. // Y取得.
  80. // -----------------------------------------------------------------------------
  81. function getIndexY( sheet, indexX, defineName ) {
  82. var listEnd = sheet.getRange(sheet.getMaxRows(), indexX).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
  83. for ( var j = 2; j <= listEnd; ++j ) {
  84. if ( sheet.getRange( j, indexX ).getValue() === defineName ) {
  85. return j;
  86. }
  87. }
  88. // 見つからなかった.
  89. Logger.log( defineName + "が見つかりません" );
  90. return -1;
  91. }

実行結果

「更新ブログ」の入力部分はデータの入力規則でリスト選択形式にしました。

解説

25行目・89行目:

  1. var mngSheet = GetSheet( MngSheetName );
  2. var dataSheet = GetSheet( DataSheetName );
  1. function GetSheet( sheetName ) {
  2. return SpreadsheetApp.getActive().getSheetByName( sheetName );
  3. }
【GAS】実践・スクレイピングでは、シートIDからスプレッドシートを操作する方法を取りましたが、IDをいちいち取るのは面倒なので、GetSheet()で名前からシートを取得・操作します。
使い分けとしては、組み込まれたGASなら名前から。外部からスプレッドシートを指定する場合などはIDから。という感じでしょうか。

27行目・95行目:

  1. var indexY = getIndexY( dataSheet, DataBlogTitleX, mngSheet.getRange( MngSelectTitle ).getValue() );
  1. function getIndexY( sheet, indexX, defineName ) {
  2. var listEnd = sheet.getRange(sheet.getMaxRows(), indexX).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
  3. for ( var j = 2; j <= listEnd; ++j ) {
  4. if ( sheet.getRange( j, indexX ).getValue() === defineName ) {
  5. return j;
  6. }
  7. }
  8. // 見つからなかった.
  9. Logger.log( defineName + "が見つかりません" );
  10. return -1;
  11. }
getIndexY()でmanageシートで指定したブログ名から送信するデータの行番号を取得しています。
単なる総当たり処理です。

33行目:

  1. if ( indexY === -1 ) {
  2. mngSheet.getRange( MngDebugLogY, MngDebugLogX ).setValue( mngSheet.getRange( MngSelectTitle ).getValue() + "が見つかりませんでした" );
  3. return;
  4. }
ブログ名の検索に失敗したらログ表示用に取ったエリアにその旨を入力し、処理を終了します。

39行目:

  1. var endX = dataSheet.getRange(indexY,dataSheet.getMaxColumns()).getNextDataCell(SpreadsheetApp.Direction.PREVIOUS).getColumn();
  2. for ( var i = DataBlogPingX; i <= endX; ++i ) {
  3. urls.push( dataSheet.getRange( indexY, i ).getValue() );
  4. }
pingURLが入力されているセルがどこまであるかチェックして、urls[]に追加していきます。

45行目:

  1. data.push('<?xml version="1.0"?>');
  2. data.push('<methodCall>');
  3. data.push('<methodName>weblogUpdates.ping</methodName>');
  4. data.push('<params>');
  5. data.push('<param><value>' + dataSheet.getRange(indexY,DataBlogTitleX).getValue() + '</value></param>');
  6. data.push('<param><value>' + dataSheet.getRange(indexY,DataBlogURLX).getValue() + '</value></param>');
  7. data.push('</params>');
  8. data.push('</methodCall>');
  9. // 送信内容.
  10. var options = {
  11. method: "POST",
  12. payload: data.join('\n'),
  13. muteHttpExceptions : true
  14. };
この辺りは決まり事、という事で。詳しく知りたい方はこちら(ブログ更新ping(weblogUpdates.ping)のxmlrpcの仕様:infoScoop開発者ブログ)

62行目:

  1. var response = 0;
  2. for (var i=0; i < urls.length; i++) {
  3. response = UrlFetchApp.fetch( urls[i], options );
  4. // responseが200番台なら成功.
  5. // 400番台ならクライアントエラー、500番台ならサーバエラー.
  6. mngSheet.getRange( logY, MngDebugLogX ).setValue( urls[i] );
  7. ++logY;
  8. if ( (400 <= response.getResponseCode()) && (response.getResponseCode() < 600)) {
  9. // 失敗か?とりあえずlogだけ残す.
  10. mngSheet.getRange( logY, MngDebugLogX ).setValue( "エラー:" + response.getResponseCode() );
  11. ++logY;
  12. }
  13. }
UrlFetchAppでPOSTします。
返ってくるgetResponseCode()で成功しているかどうかチェックしていますが、ちょっとザルすぎるかもしれません。

77行目:

  1. dataSheet.getRange( indexY, DataUpdateX ).setValue( Utilities.formatDate( new Date(), 'Asia/Tokyo', 'yyyy/MM/dd HH:mm') );
日付の記録です。フォーマットを色々いじってみると面白いです。

80行目:

  1. for (var i = 0; i < data.length; i++) {
  2. mngSheet.getRange( (logY + i), MngDebugLogX ).setValue( data[i] );
  3. }
dataの中身を念のため確認しておきます。



ブログランキング・にほんブログ村へ

Translate

魔王と愉快な仲間

このブログを検索

ラベル

ブログ アーカイブ

メッセージ

名前

メール *

メッセージ *

Powered by Blogger.

フリー写真素材ぱくたそ

QooQ