かずきち。の日記

サーバサイドエンジニアのつぶやき

【自営業必見?】3時間位で完全無料でポイント照会やパケット使用量などの会員情報照会システムを作ってみた!

あらすじ

検索システムを作ろうとした場合、検索エンジンなどの大規模なものであればSQLなどを駆使して作成をしますが…
社内システムの場合Googleが提供しているGoogleフォームやGoogleスプレッドシートといった無料範囲でサクッと作ってみました。
利用者2000人弱の利用者情報を検索するシステムになります。
Googleフォームを魔改造して、利用者に情報を返却するプログラムを作ってみます。

【完成したインターフェース】
f:id:kazukichi_0914:20211114223531g:plain

単なるGoogleフォームです。
でもこのGoogleフォームには仕掛けがしてありまして、情報を入力すると裏でデータベースを検索して利用者情報を指定されたメールアドレスに返却するプログラムです。
こんな形でGoogleフォーム知りたい情報を入力してみます。

f:id:kazukichi_0914:20211114223907g:plain

すると裏で情報を検索して、利用量と順位を返却します。

f:id:kazukichi_0914:20211114224120g:plain

先程、入力してもらった連絡先に返却します。

45行のソース
function myFunction() {
  //現在のスプレッドシートを取得
  var spreadsheet = SpreadsheetApp.openById('*******************************');
  //現在のシートを取得
  var sheet = spreadsheet.getActiveSheet();
  //指定するセルの範囲(A1)を取得

  var lastRow = spreadsheet.getLastRow();
  Logger.log(lastRow);

  //通知先メールアドレス
  var range = sheet.getRange("B"+lastRow);
  //値を取得する
  var value = range.getValue();
  Logger.log(value);
  

  // 検索機器管理番号
  var range2 = sheet.getRange("C"+lastRow);
  //値を取得する
  var value2 = range2.getValue();
  Logger.log(value2);

  //現在のスプレッドシートを取得
  var spreadsheet2 = SpreadsheetApp.openById('***');
  var sheet2 = spreadsheet2.getActiveSheet();
        
  var textFinder = sheet2.createTextFinder(value2);
  var cells = textFinder.findAll();
        
  Logger.log('ヒット数 : ' + cells.length);
        
  for(var i=0; i<cells.length; i++){
    Logger.log('セル位置 : ' + cells[i].getA1Notation()) ; //getA1NotationでGASからのセル位置を取得します
    Logger.log(cells[i].offset(0, 1).getValue());
    var giga = cells[i].offset(0, 1).getValue(); //ここで使用量を格納します
    Logger.log(cells[i].offset(0, 2).getValue());
    var rank = cells[i].offset(0, 2).getValue();

    GmailApp.sendEmail(value, "【管理番号】"+value2+"のSIM使用量通知", "今月の使用GB数:"+giga+"GB\n利用順位:"+rank+"位\n\n本システムは当月のSIM使用容量の端末別ランキングを抽出しております。また当システムではシステム検索ログを収集しております。");
    //スプレッドシート値を検索

  }

以上45行で社内簡易検索システムが完成しました。

仕上げは検索値をユーザに返却するタイミングを指定

このままでは単純に値を取得して終わるので、最後にユーザ通知して終わりにしましょう。
=ユーザにメールを返却するタイミングを指定します。

f:id:kazukichi_0914:20211114224939g:plain

トリガーに「スプレッドシートからフォーム送信時」に起動を選択します。

試しに「ABC1234」と検索してみてください。

f:id:kazukichi_0914:20211114232738g:plain

こんなメールが帰ってくるはずです。
このランキング順位は裏で変動するように作り込んでいますので、完飲情報などをリアルタイムで読み込みたい方は参考にしてみてください。
個人経営などで会員情報などを扱っている人はぜひkazukichi.0914+coconala@gmail.comにご相談ください。

業務集計の上司報告プログラムを作成して、完全自動化をした話

f:id:kazukichi_0914:20211020155629g:plain

作ったきっかけ

毎週会社で何かしら報告する場面があります。
でも人手で集計して、同じ作業を繰り返すのはイマイチ効率の悪さを感じます。
というより、もはや自動化以外にあり得ないなと…
なので、報告系の業務をいっその事自動化してしまいましょうと思い立って、数時間ほど作業をしてすぐ完成しました。
逆に今までやっていた人手の作業はなんだったんだという…
それか自分のスキルが上がったのか…

//プログラムの二次利用にあたって

//利用権限設定のお願い
//本プログラムはGASに対するカレンダーへの書き込み権限・Gmailの送信権限(左サイドバーのサービスからGmailとCalendarの利用をオンにしてください)を利用します。
//実行時のスクリプトへの実行権限を許可してください。

//おすすめの設定
//GASのコードは自動実行(金曜日定時間際)が可能です。
//左サイドバー「時計マーク→時計マーク」から本プログラムの実行条件を設定ができます。
//毎週金曜日終業間際に今週のタスク処理件数を自動集計して、指定のメールアドレスに送信しています。
//54行目のメールアドレスの設定先・59行目がメール本文になります。

//このプログラムを稼働させる条件
//このプログラムが行っていることは、毎週ポータルから割り当たるタスクを自動集計してしますが、Gmailラベル「@@@」というラベルの付いたGmailを自動集計します。
//2次利用される方はGmailApp.searchスレッドの検索条件を変更してください。

//※重要 日本のタイムゾーンの設定
//本プログラムは毎週のタスクの自動集計を目的としますが、Googleのプログラムは初期設定でアメリカ時間での実行をデフォルトとします。
//ですので、送信時刻を取り扱う・今週の予定を集計する場合はformatDateがJSTであることを確認してください。
//Googleカレンダー歯車マーク→カレンダーのタイムゾーンの設定JSTを設定してください。

//プログラムの実行上限
//xxx社のGoogleアカウントはGoogleWorkplaceの条件が適用されます。
//https://developers.google.com/apps-script/guides/services/quotas?hl=ja#current_limitations
//上記URLの上限をオーバーした場合、数時間~1日のGoogleサービス利用停止措置がGoogleによって取られ、Googleサービスの利用が制限されます

//以下、プログラム本体

function getUserLabelsSample() {
  //日付けオブジェクトを作る
  var date = new Date();
 
  //スプレッドシートのkeyを指定して取得(スプレッドシートURL末尾のID)
  var spreadsheet = SpreadsheetApp.openById('スプレッドシート 末尾IDに置き換える');

  const start = 0;
  const max = 100;
 
  var date = new Date(); //現在日時のDateオブジェクトを作る
  var today = Utilities.formatDate(date, 'JST', 'yyyy/MM/dd');
  Logger.log(today); //2019/09/05
 
  //現在の「日」を取得
  var day = date.getDate();
  //Logger.log(day); //5
 
  //前日日付にしたいので-1する
  date.setDate(day-7);
  //Logger.log(date); //Wed Sep 04 19:33:33 GMT+09:00 2019
  var startday = date;
 
  //日付の表示形式を整形する
  var lastweek = Utilities.formatDate(startday, 'JST', 'yyyy/MM/dd');
  //Logger.log(lastweek); //2021/06/14
 
  const threads = GmailApp.search("label:@@@ after:"+lastweek);
  const messagesForThreads = GmailApp.getMessagesForThreads(threads);
  Logger.log("新しいタスク件数"+messagesForThreads.length);
 
  var title3 = ""
  
  for(const messages of messagesForThreads){
    //Logger.log(messages[0].getSubject());
    var title1 = messages[0].getSubject().replace("新しいタスク","")
    var title2 = title1.replace(" があなたに割り振られました!","")
    var title3 = title3.concat("\n"+title2);
    Logger.log(title3);
  }
 
   const recipient = 'xxx@xxx.co.jp'; //送信先のメールアドレス
   const subject = '今週の処理件数';

  const recipientName = 'xxx';
  const body = '本メールは今週分のポータルの自割り当てのタスク件数を自動集計しています。\n割り当てタスクの内容は下記カレンダーURLのメモ欄に記入してあります。\n\n'+messagesForThreads.length+'件\n\nhttps://calendar.google.com/calendar/u/0?cid=123456789';
 
  GmailApp.sendEmail(recipient,subject,body);
  
  //createAllDatEvent で終日イベントを登録
  CalendarApp.getDefaultCalendar().createAllDayEvent("今週のポータル割り当て数"+messagesForThreads.length+"件",new Date(today),{description:title3})  

  //例
  /*
'xxx権限IDの貸出しの設定をお願いします'
 'yyy利用申請'
 'zzzサイトの閲覧制限解除作業 または eeeダウンロード作業のお願い'
 'aaaの変更依頼'
 'aaaの変更依頼'
 'yyy利用申請'
 'cccの変更依頼'
 'dddの変更依頼'
 などが金曜日定時後に自動集計されます。
 */

}

これで下準備おしまいです。
すると毎週金曜日23時に過去1週間のメール内容を自動分析して、アウトプット用のグラフを自分に送りつけます。

f:id:kazukichi_0914:20211020155629g:plain

f:id:kazukichi_0914:20211020160622g:plain

これで資料作成完了なので、あとは上司に報告すればおしまいです。

トリガー(自動起動)ってなんなんだ?

トリガーというのはプログラミングをする上で非常に重要な概念です。
f:id:kazukichi_0914:20211020154111g:plain
引用:
https://www.irasutoya.com/2015/02/blog-post_458.html

銃のピストルの引き金をトリガーというといいます。
そうです。

「引き金」です。

自分が業務をする時に何かきっかけがあるはずです。
〜〜に依頼されたら、雨が降ったら、月末になったら

takakisan.com
引用:
https://takakisan.com/gas-trigger-introduction/

プログラム発動して上司に報告をしましょう。
楽ちんですね。

可用性をチェックしよう

f:id:kazukichi_0914:20211020154711g:plain

プログラムは通勤電車のように決まった時刻、決まった条件で動きます。
しかし人身事故があるように時にミスってしまいます。
プログラムも絶対じゃないんですね。

基本的にITに疎い人はコンピュータが壊れると怒ります。

機械のくせにどうしてミスるんだと…
でも機械も完璧じゃないんですよ。
なので、ちゃんと動作しているかを人間の目でたまにチェックしてあげましょう。

【初心者向け】GASでエラーが出たときにデバッカツールを使って、プログラム中の変数をトレースする方法

スクリプトを書いていると、何行目でどこの変数に何が定義されているのかわからなくなりませんか?

プログラムが100行とか超えてくると、条件分岐、繰り返しが複雑になってきて
どこの変数にどこのタイミングで何が格納されているかわからなくなります。
そしてGoogleにURLのfetch回数が多すぎますとか怒られます。

f:id:kazukichi_0914:20211010150946g:plain
引用:
https://developers.google.com/apps-script/guides/services/quotas

例えば、URL fetch callは無料アカウントの場合1日1000回叩いていいよ!
と実行回数に上限があります。

わかりやすく、説明しましょうか。
焼き肉食べ放題に行ったら、

90分とか上限ありますよね?

昨今は〜〜放題みたいな文言が溢れていますが、厳密には〜〜放題ではないです。

www.youtube.com
引用:
https://www.youtube.com/watch?v=y1BKJjRsLik

そりゃそうですよね?
お皿がなくなったら、食べ放題できませんし
材料がなくなっても、食べ放題はできないです。

一方、コンピュータの世界って比較的〜〜し放題だと思いませんか?

YouTubeはいくら見ても無料だし
Google検索はいくら検索しても無料です。
とは言っても、100億回とかクエリを投げたりするとさすがに怒られます。
今回は特にGoogleAppsScriptで変数のコールスタック方法をお教えします。

コールスタックって何だよ?

複数階層の関数を呼び出したスクリプト内の位置を追跡し続けることです。 — どの関数が現在実行されているのか、その関数の中でどの関数が呼び出されたか、などです。
引用;
https://developer.mozilla.org/ja/docs/Glossary/Call_stack#:~:text=%E3%82%B3%E3%83%BC%E3%83%AB%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF%20(call%20stack)%20%E3%81%AF,%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%95%E3%82%8C%E3%81%9F%E3%81%8B%E3%80%81%E3%81%AA%E3%81%A9%E3%81%A7%E3%81%99%E3%80%82


わかりやすく説明しましょう。

今回はプログラミングコードを完成されること=料理をしていると考えてください。

f:id:kazukichi_0914:20211010152235g:plain

実行時間の最大時間を超えましたと怒られるわけです。

カップラーメンの湯で時間3分を超えたら、ラーメンが伸びるのでわかるんですが…
プログラミングの場合、なんで怒られているのかさっぱるわかりません。

そのためにデバッガツールを使かおう!

デバッガツールはコンソール画面で「デバック」ボタンを教えて下さい。

f:id:kazukichi_0914:20211010152805g:plain

すると各行ごとに変数をトレースするモードに切り替わって、1行ごとソース内で何が起きているのかがわかります。

f:id:kazukichi_0914:20211010150514g:plain

あるあるの話をすると
例えば文字列型aに12345という文字を代入したとします。
その後にb=a+1
を実行していたら、Typeエラーとか出て「なに?」みたいなことになります。

文字列型に数字足してるけど大丈夫?と気がつくためにデバッガツールは使いましょうということです。

別に自分の目で見て確認すればいいじゃん?
って思いますよね?
10000行のソースコードのバグ取りはほぼ不可能です。
デバッガツールでトレースをしないと…

エクセルVBAでも変数をウォッチしよう

f:id:kazukichi_0914:20211010153902p:plain
引用:
https://www.wanichan.com/pc/excel/2016/8/39.html

エクセルとかはエラーウォッチ機能が充実していて、

「ここ間違えてるけど、この変数・この数式で大丈夫?」

と聞いてきてくれるので、エラーに関するヘルプっていうのを見て修正するだけです。

なんでこんなエラー取り機能が充実してるか?

コンピュータの世界にあるあるですが、ルール変更の回数が多いからです。
ワード・エクセル・パワポなどなど、ルール変更が日常茶飯事で起きるので、

もはやルール覚える意味なくないか?

なので、どちらかというとデバッグツールで出たエラーコードを使って正しくバグ取りをできることが重要です。
基本的にプログラミング系は開発段階ではミスったところで人は死にません。

開発環境→テスト→本番環境リリース

なので、いきなり100%を目指さなくても大丈夫です。
途中で仕様変更もあります。
昨日Googleのルールと次の日Googleのルールが違うことは大いにあります。

f:id:kazukichi_0914:20211010154759g:plain

それはITの世界がGAFAの鶴の一声でいくらでも変わるからです。
なので、どちらかというと現行のルールをよく覚えておくというよりも、プログラマーの人にはルールに柔軟に対応できる素養が求められます。

f:id:kazukichi_0914:20211010155109g:plain

蓮舫Googleさん、ちょっと対応が場当たりすぎるんじゃないですか?」

でもコンピュータの世界は別に場当たり的でも、「いい」と思った方に進む世界なので、いきなり完璧を目指すのではなく、エラーが出たときに修正できる能力が大事です。

YouTubeチャンネルに投稿されるコメントを抽出するスクリプトを書く

Youtubeチャンネルに投稿されるコメントを自動抽出する

Youtubeに書き込まれている他人のコメントを見ると他人が何を考えているかわかります。
でも、コメントを1つ1つ読んでいたら時間がくれるので、特定ちゃんねるに書き込まれたコメントを記録するスクリプトを書いてしまいましょう。

YouTubeAPIをオンにする

[:p。lain]

YouTubeのコメントのfetchをオンにして動画に書き込まれたコメントを抽出しましょう

function youtubeCommentFetcher() {
  var SS = SpreadsheetApp.getActiveSpreadsheet();
  // video_listにVID(YouTube動画のID)を入力してください
  // ex. "l9F1J0DGFg0", 'J9IDKbPbQVY'
  var video_list   = [
    '~~~~~~~~~~~~~~'
  ];
  
  // =================ここから下は書き換えない=================
  for (var v = 0; v < video_list.length; v++) {
    var video_id  = video_list[v];
    var video = YouTube.Videos.list('id,snippet, statistics', {
      id: video_id,
    });
    
    if (v == 0) {
      var sheet = SS.insertSheet();
      var sheet = SS.getActiveSheet();
    } else {
      var sheet = SS.insertSheet();
    }
    sheet.setName(video.items[0].snippet.title);
    
    var row          = 2;
    var col          = 1;
    sheet.getRange(1, 1).setValue("ビデオ名");
    sheet.getRange(1, 2).setValue("チャンネル名");
    sheet.getRange(1, 3).setValue("コメントユーザー名");
    sheet.getRange(1, 4).setValue("コメント日");
    sheet.getRange(1, 5).setValue("コメント");

    

    var PageToken = ''
    
    while (true) {
      var comment_list = YouTube.CommentThreads.list('id, replies, snippet', {
        videoId: video_id,
        maxResults: 100,
        pageToken: PageToken,
      });
    
      for (var i = 0; i < comment_list.items.length; i++) {
        sheet.getRange(row, col).setValue(video.items[0].snippet.title);
        sheet.getRange(row, col + 1).setValue(video.items[0].snippet.channelTitle);
        sheet.getRange(row, col + 2).setValue(comment_list.items[i].snippet.topLevelComment.snippet.authorDisplayName);
        sheet.getRange(row, col + 3).setValue(comment_list.items[i].snippet.topLevelComment.snippet.publishedAt);
        sheet.getRange(row, col + 4).setValue(comment_list.items[i].snippet.topLevelComment.snippet.textDisplay);
        row += 1;
        if (typeof comment_list.items[i].replies !== "undefined") {
           for (var r = 0; r < comment_list.items[i].replies.comments.length; r++) {             
             sheet.getRange(row, col).setValue(video.items[0].snippet.title);
             sheet.getRange(row, col + 1).setValue(video.items[0].snippet.channelTitle);
             sheet.getRange(row, col + 2).setValue(comment_list.items[i].replies.comments[r].snippet.authorDisplayName);
             sheet.getRange(row, col + 3).setValue(comment_list.items[i].replies.comments[r].snippet.publishedAt);
             sheet.getRange(row, col + 4).setValue(comment_list.items[i].replies.comments[r].snippet.textDisplay);
             row += 1;
           }
         }
      }
      PageToken = comment_list.nextPageToken
      if (typeof PageToken == "undefined") {
        break
      }
    }
  }
}
<<

video listのIDを指定すると他人のチャンネルに書き込まれたコメントを永遠に記録し続けます。

サイト運営者必見!10行で広告ブロック解除をお願いするjavascriptを書く!


広告収入を得ている人にとって、「AdBlock」は恐怖

chrome.google.com
引用:
https://chrome.google.com/webstore/detail/adblock-%E2%80%94-best-ad-blocker/gighmmpiobklfepjocnamgkkbiglidom?hl=ja

AdBlockというのはサイトに表示される広告をブロックする拡張機能です。
世界でも1000万人が利用していまして、評価も4.5を超える代物です。

入れるとネットで広告が非表示になります。

サイトを見る人にとっては、広告がなくなっていいのですが…
サイト運営者からすると「AdBlock」はやめてほしいんです。

というわけでAdBlockを解除をお願いするスクリプトを書いてみました。

コードは13行
<div id="adframe">AdBlockの解除のご協力ありがとうございます!</div>
<script>
setTimeout(function() {

var element = document.getElementById( "adframe" ) ;
var cssStyleDeclaration = getComputedStyle( element, null ) ;
var ad_display= cssStyleDeclaration.getPropertyValue( "display" ) ;
 
if(ad_display=="none") {
    alert('サイト運営のため、Adblockの解除のご協力お願いいたします');
  }
}, 1000);
</script>

と記載をヘッダに記述します。
display:noneで広告非表示にしている輩をあぶり出します。
ぜひ広告収入を伸ばしたい人はこのコード使ってみてください。

f:id:kazukichi_0914:20210925201624g:plain

広告ブロッカーを使っている人には上記アラートを出すようにしてみました!!

GASで変数をグローバルの変数に設定して、変数の引き継ぎを行ってブレークポイントを見てみよう

GASの質問をいただきました

f:id:kazukichi_0914:20210925162625p:plain

「form.gsで定義したtextをmain.gsでも再利用したい」

という質問です。GoogleAppsScriptでは変数をどのようにグローバルに持てばいいのでしょうか?
例えば、コード1で定義したperson = '大島優子'をコード2で呼び出して実行しようとすると

f:id:kazukichi_0914:20210925165541g:plain

f:id:kazukichi_0914:20210925163535g:plain

personは定義してないから使えないよ!と怒られます。

それそうですよね。personはコード1でしか宣言していないので、コード2から呼び出そうとしても無理です。

変数を複数のコード間で共有したい

例えばコード.gsでperson = '大島優子';と宣言してみます。

f:id:kazukichi_0914:20210925165541g:plain

myFunction内でpersonを定義しているので、コード1のmyfunctionの中でしかpersonは有効ではないです。
ではどうすれば、gunction2へ他のスクリプトに変数を引き渡せるの?

function外で変数を定義することです

先程の「大島優子」のサンプルに戻りましょう

もしも大島優子をmyFunction外で定義します。

f:id:kazukichi_0914:20210925170027g:plain

コード1でfunctionが始まる前にpersonを宣言してみました。
するとコード2でもpersonという変数が使用できます。

f:id:kazukichi_0914:20210925170228g:plain

するとperson='大島優子'が引き継がれます。

これは変数を定義している場所が重要です。

これは子供が「お母さん」って呼ぶのに似ています。

f:id:kazukichi_0914:20210925170449g:plain
引用:
https://www.irasutoya.com/2019/12/blog-post_239.html

変数を共有するのは「子供がお母さん」って呼ぶのに似ているんです。
家の中で子供が「お母さんー!!」って読んだら、自分のお母さんが振り返ってくれます。

でも新宿駅で子供が「お母さんー!!」って叫んだら、他の人も振り返りますよね?
f:id:kazukichi_0914:20210925170449g:plain
f:id:kazukichi_0914:20210925170449g:plain
f:id:kazukichi_0914:20210925170449g:plain

なんででしょう?それは誰のお母さんかわからないからです。
もしかしたら田中家で「お母さん」と言ったら…田中〇〇さん1人だけです。
でも    日本全国で「お母さん」と言ったら…複数人います。

プログラミングでも同様のことが言えて、他のfunction内で関数を共有したいのであれば、

その変数をどこで定義するのかが大事です

会社で複数人でコードを書いて、変数を共有しているときは変数を定義している領域が大事になってくるわけです。

これでも解決しない場合

f:id:kazukichi_0914:20210925171749g:plain

ファイルを上に移動をしないといけないケースがあります。
上から順次実行されるので、実行順序を変えると解決する場合があります。

ブレークポイントを設定して変数に何が入っているか確認する。

プログラミングをしていると、どこの行数で変数に何が入っているかパニックになります。
そのためにはブレークポイントを設定して、その時の変数状況を確認するとスムーズにコーディングができます。

f:id:kazukichi_0914:20210925172727g:plain

途中段階を知りたい行数番号をダブルクリックすると、ローカル変数には今何が入っていますという確認ができますので、ぜひ使ってみてください。

ファイルの圧縮技術にも使われるハフマン符号ってなんなの?どうやってファイルの圧縮をしているの?

パソコンでファイルの圧縮などしたことはありますか?

f:id:kazukichi_0914:20210913215133j:plain

zipファイルだったり、lzhだったりする拡張子を持っていて、
5MBのファイルを3MBにしてくれたりします。
なのでパソコンの中身を圧縮します。
みなさんzipなどいろいろ使ったことがあるでしょう!

f:id:kazukichi_0914:20210913215544g:plain

現実世界だったら、布団を圧縮袋で圧縮しますが、
パソコンの中身はそんなことができません。
ではパソコンはどうやってデータを圧縮しているのでしょうか?

データは0101の連続で表されるって聞きませんか?

例えばです。

Aを00
Bを01
Cを10
Dを11

と表すとしましょう。

AABBAABBCCDD~~~~~~~~~~~~~みたいな文字列は0000010100101011~~~~と表されると思います。

でも待て待てと…
このAを00 Bを01 Cを10 Dを11に置き換えようって言う発想はA、B、C、Dのそれぞれの出現頻度を考慮しておらず…

とりあえずAを1、Bを01、Cを001、Dを000って決めればいいんじゃね?

という発想です。

ピアノの楽譜だって同じ部分の小節を楽譜にもう一度書きません。

f:id:kazukichi_0914:20210913220343j:plain

こういう反復記号で省略します。
コンピュータの世界でも何度も登場するビットは省略してしまおうという考えがあります。

ここで登場するのが「ハフマン符号」ってやつです。

入力 DAEBCBACBBBC に対して上記のアルゴリズムを適用すると…

純粋にA~Dを2進法で書くより…

f:id:kazukichi_0914:20210913221039g:plain

文字の出現回数で
0,10,110,1110,1111を割り当てれば文字数=スペースを省略できます。

例えば…
「11111110」という文字列があったとしましょう…

0=A B=10=B 110=C 1110=D 1111=Eを左から当てはめていき迷う。

11111110を見ます。

いきなり1が7連続やんけ!

ってことは11111110 の最初の1111は

Eで確定です。

11111110→E+1110

あとはこの1110のハフマン符号を解けば解決です。
1110=Dなので、 1111110=「DE」を表していたことがわかります。

0を区切りにすることで圧縮が可能になる。

f:id:kazukichi_0914:20171020003526j:plain

010を見たら…「0」「10」

でも01101→ハフマン記号のルールに則っていないのでこのデータは壊れています。

01101のデータがなぜ壊れているとわかるのでしょう?

0=A B=10=B 110=C 1110=D 1111=E

まず01101の一番左の0はA以外にありません。
01101=A1101

次にA1101はAB1 になるはずです。
0が出てきたらしれは文字の区切りです。

そうすると最後の1は?

これがファイルを正しく回答できなかったり、文字化けの原因です。
ハフマン符号などの一定のルールに基づいてファイルを圧縮したけれど、配送途中でハフマン符号のルールを満たす文字列ではなくなり、ハフマン符号で圧縮した文字列をもとに戻せなくなったことを意味しています。
最後に1で終わるのは1111=Eしかないはずなのに、この文字列はどんなに上手に区切っても元に戻せない01の羅列になっています。

これがハフマン符号による文字列の圧縮の仕組みです。

プログラミングでわからなくなったときの解決方法!GASを自分だけで書く心得について

プログラミングでわからなくなったら?

f:id:kazukichi_0914:20210914144555g:plain
引用:
https://www.irasutoya.com/2018/12/blog-post_627.html

プログラミングをしていてわからなくなった時、あなたはどうしていますか?

「ググりましょう」

よくある話じゃないか?と思いますが、
ここには教訓があります。

先頭を走るということは先人はいないということ

f:id:kazukichi_0914:20210914144936g:plain

GASでGmailが送れなかったら、どうしますか?
誰かに聞いちゃいますか?自分で調べますか?それともGASでGmailを送ったことがある人なんかいないから考える?
いろいろ解決策はあります。

今自分が抱えている疑問は世界中で自分だけなのか?考えてください。

この考え方は大事ですよ!
今抱えている疑問や問題は世界中で自分だけの問題なのか?です。

風邪にかかったらお医者さんに行きますよね?
なんで行くのか、よく考えてください。

風邪にかかったようだ→風邪は一般的な病気だからそのへんの医者でも解決できるだろう→医者に行こう

っていうロジックが働いているはずです。

世界で1億人の1人の難病の直し方がググって出てきますか?

ノーベル賞受賞者とか凄腕のエンジニアにはもう先人がいないからすごい

プログラミングは山登りと一緒

f:id:kazukichi_0914:20210914145607j:plain
引用:
http://naturelog.main.jp/sangaku96.html

道なき道の山登りはプログラミングと似ています。
プログラミングに正解がないのと同じく…
山登りにも正解がないです。

山に登れれば、どんなルートでもいいですから。
コードが動けば、どんなコードでもいいです。

じゃあ今自分が書いているコードが全人類の中で自分が一番最初に書いているのか?考えてください。

自分が「これ、めっちゃ画期的じゃね?」って思ってること
自分が「あー困った困った」って思っていることは
今まで世界中の誰かが経験してます。

全人類の中で自分が一番最初に経験したなんてことは大抵ないです。
なので、コードを書いていてぶち当たったらググってください。

できないことでググれば大抵のことは解決できる

f:id:kazukichi_0914:20210914150041g:plain

何かを聞く時にどこで聞くかって大事です。
ドコモのPhoneが動かない   →ビックカメラで聞く✗ ドコモで聞く○ Appleで聞く○
スプレッドシートが動かない  →チャットで誰かに聞く✗ Googleで検索する○
自社の人事部の新人の名前を知る→人事部の友人に聞く○ Googleで検索する✗ です。

だって新人の名前なんか、ググっても出てきませんからね。

自分が悩んでいることなんて、人類誕生から今までの間においた出来事からしたらちっぽけな出来事です。
そんなことどうでもいいか、調べれば解決します。
自分が悩んでいることは今まで誰かが絶対に悩んでいます。
誰も考えたことがないものはノーベル賞並に卓越した内容かとかです。

新作映画の感想をググる理由は誰か感想書いてるだろうって思ってるからです。
もしまだ未発表で関係者だけの試写会段階の映画あったら感想はネットに出回りません。
誰かに聞く前にこれって聞くべきことかよく考えてください。
プログラミングの疑問はぐぐれば大体終わります。

金融機関の入金・出金・引き落としデータを自動記録スクリプトを書く

MoneyForwardやZaimの家計簿アプリは便利

家計簿アプリで自動連携できるので便利なのですが…

f:id:kazukichi_0914:20210921132236p:plain

1年前以上のデータを参照するには…プレミアムじゃないとできないらしいのです。
プレミアムってことは月額課金500円です。
いやー口座の残高管理で500円とられるのは嫌です。

言い方を変えれば、1年以内のデータなら見放題なので、有料のデータになる前に他の媒体に書き出してしまえば無料で使えます。

f:id:kazukichi_0914:20210904173322g:plain

お金を管理するためにお金を払うっていうのはどうなのって思っています。
そんなわけでスクリプトを書きました。

気をつけたこと

f:id:kazukichi_0914:20210904173812g:plain

無料サービスのいけないところは「無料」だけれど「PR」の広告を打ち込んでくる。

こんなデータは要らないわけですね!

こういうデータはゴミデータなので弾かないといけません。
無料だとYouTubeも広告が入るし、無料だとAmazonも送料を取ってきます。

でも良心的なので広告には、「(PR)」と書いてあります。

ウェブで広告を出すときはスポンサーリンク、広告などの表示を出して誤クリックを減らさないと広告のクリック単価が下がりますからね。
でも逆に言えば「moneyforward」かつ「PR文字」が含まれないメールは良いメールです!
さくさくっと書いていきます。

昨日から今日の間に発生したきい有取引を抽出→もしあればカレンダー転機

function moneyforward() {
  var date = new Date(); //現在日時のDateオブジェクトを作る

  var today = Utilities.formatDate(date, 'JST', 'yyyy/MM/dd');
  //Logger.log(today); //2021/9/04

  date.setDate(date.getDate() - 1);
  Logger.log(date);
  var yesterday = Utilities.formatDate(date, 'JST', 'yyyy/MM/dd');
  Logger.log(yesterday);    //createAllDayEventでカレンダーへイベントを登録

  const query = 'アラートメール label:moneyforward -PR after:'+yesterday;
  //const query = 'アラートメール カード引き落とし label:moneyforward -PR';
  Logger.log(query);

  const start = 0;
  const max = 10;
 
  const threads = GmailApp.search(query, start, max);
  const messagesForThreads = GmailApp.getMessagesForThreads(threads);
 
  for(const messages of messagesForThreads){
    Logger.log(messages[0].getDate());
    Logger.log(messages[0].getSubject());
    //Logger.log(messages[0].getPlainBody());
    Logger.log(messages[0].getBody());

    title = messages[0].getSubject();

    //登録するカレンダーIDを呼び出してeventへ格納
    var calendar = CalendarApp.getCalendarById('***************************@group.calendar.google.com');

    //createAllDayEventでカレンダーへイベントを登録
    calendar.createAllDayEvent(title,date);
  } 
}

何をやっているか解説するとJSTの現在時刻を取得して、昨日から今日までに時発生した金融取引を抜きます。
そして

const query = 'アラートメール label:moneyforward -PR after:'+yesterday;


moneyforwardのラベルが入っていて、でもPRラベルを含まず、昨日から今日に発生した金融取引を抜きます。
これで価値ある金融取引データが抜けます。
定期的に銀行に行って記帳をしなくていいので楽ですね。
強いていうと連携口座に上限があるのがネックです。

想像できることはだいたい実現できる

Admin ADK
AnalyticsReport API
Area 120 table API
BigQueut API
DriveAPI
Drive Activity API
Enterprise Lisense Manager API
Gmail API
GoogleAnalytics Data API
Google Calender API
Google Classroom API
Google Docs API
Google Sheets API
Google Slide API
Google WorkplaceReseller API
Group Migration API
Group Setting API
Mirror
PeopleAPI
TagManager API
Tasks API
YouTube Analytics API
Youtube Data API v3
YouTube Partner

Googleのほぼすべてのサービスは自動化ができますので…
もしも弱小サービスでAPI提供していないというものでもGoogleに落とし込めればほぼ自動化できます。

自動化したらスコープには気をつけたい

スコープという概念は自動化する上で理解しなければいけません。
機械にはどこまで自動化していいかを決める範囲があります。
それをスコープといいます。

f:id:kazukichi_0914:20210904181044g:plain

f:id:kazukichi_0914:20210904181055g:plain

iPhoneしかり、Googleしかり、facebookしかり…
きちんと個人情報にアクセスする際には「個人情報にアクセスするけどいい?」「通知をオンにするけどいい?」
って聞いてきます。

ソフトをインストールするときも

f:id:kazukichi_0914:20210904181316g:plain

どこのフォルダをホームにしますか?アプリケーションによる通知を許可しますか?って聞いてくれています。
なのに日本人はだいたいこの説明をかっ飛ばして全部「はい」にするので、パソコンが壊れたと言います。


引用:
docs.oracle.com

自分が会社の情シスだったりすると、社員が全部「はい」とかにするので、ここは「いいえ」にしてくださいなどと指示したりをします。

金融機関のアクセスだったり、Googleへのアクセスの情報を渡して危なくないの?

もちろん危険なので、

myaccount.google.com
引用:
https://myaccount.google.com/permissions?continue=https%3A%2F%2Fmyaccount.google.com%2Fdata-and-privacy

ときどきプライバシー設定を見直す必要があります。
時々変なアプリにGmail送信のフルアクセスを与えていたなんてこともありますかね。

せっかくなのでTwitterサードパーティーセッションも紹介しましょう

f:id:kazukichi_0914:20210904183135g:plain
引用:https://twitter.com/settings/connected_apps

Twitterにも第三者からのアカウントアクセスができます。
そしてどんなアプリにアクセス権や認証権限があるかが確認できます。

いろんなサイトでIDとパスワードを覚えるのが嫌なので、Twitter認証やLINE認証を使うわけです。
OpenIDを利用しているわけです。

qiita.com
引用:
https://qiita.com/TakahikoKawasaki/items/498ca08bbfcc341691fe

昔はパスワードがいっぱいで管理できないということもありましたが、OpenIDを使えば管理コストを抑えられます。

とにかく時短をしたい人にはおすすめ!Apple純正のショートカットアプリで時短コマンドを量産しよう

iPhoneでのコピーアンドペーストを覚えると賢くなったような気がする

f:id:kazukichi_0914:20210906135904j:plain

「こうやって文字を長押しして、コピーして貼り付けるんだよ!」

と教えています。
まーできるっちゃできるんですが…問題があります。

140文字を超える URLをコピーするとTwitterに投稿ができない

f:id:kazukichi_0914:20210906140337g:plain
引用:
https://image.itmedia.co.jp/l/im/news/articles/1302/18/l_yuo_twitter_01.jpg#_ga=2.127626382.22858492.1630904535-682982599.1630904535

長いURLって140文字を超えるんですよね。
そしてダサいんですよ。

f:id:kazukichi_0914:20210906140742g:plain

例えばこんなURL踏みたいですか?
もう少し見やすいURLを出してくれって思います。

フリーダイヤルに電話する時
0120-657-452より
0120-444-444のほうが電話しやすいですよね?

URLは短くしてから伝えましょう

ja.wikipedia.org
引用:
https://ja.wikipedia.org/wiki/%E7%9F%AD%E7%B8%AEURL

そうすれば相手も覚えやすくなりますし、スペースを節約ができます
f:id:kazukichi_0914:20210906141348g:plain
引用:
https://limia.jp/idea/182164/

100円均一にある収納ボックスみたいなものを想像してください。
多くのお片付けアイテムが売っていると思います。

同様にiPhoneでも長いURLを短く、自動で加工してしまいましょう

使用するもの

ショートカット

ショートカット

  • Apple
  • 仕事効率化
  • 無料
apps.apple.com
引用:
https://apps.apple.com/jp/app/%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88/id915249334

Apple純正のショートカットアプリです。
一度設定をすれば以後は爆速で仕事ができるようになります。

time-space.kddi.com

ショートカットギャラリーで自分にあったショートカットを探す

support.apple.com
引用:
https://support.apple.com/ja-jp/guide/shortcuts/apdd018638ca/ios

Ctrl+X Ctrl+C Ctrl+Vにショートカットは世界に数個なんてものじゃありません。
マニアな人はみなさん思い思いに便利なショートカットを作っています。
iPhoneは自分好みのショートカットを作れるんだと初めて知った人はぜひ使ってみてください。