GoogleフォームでQR在庫管理

2019年10月28日

K0001をパラメタで渡す

QRコードリーダーはいまやみんなのスマホで使えます。
ほんの数年前には、生産ラインでは重装備のバーコードリーダーが必要でしたが、今どきのシステムのデータ収集では、かなり軽い装備でできそうです。スマホでQRコードを読ませて、Googleフォームのサイトに飛ばして、Googleスプレッドシートに格納したらそれで済みます。
SAPとかERPとかの巨大システムはもはや必要なく、GoogleさんとExcelだけでそこそこできます。
Googleフォーム内の 管理コード の値をURLのパラメタで渡せるので、 管理コード を含むURLのQRコードを作成しておけば、スマホから コストのかからない在庫管理システムができます。 ↓QRコードのURLの例
https://docs.google.com/forms/XX/XX/XXXXXXXXXX/viewform?entry.XXXXXX=K0001

スマホのQRコードリーダーでQRコードを読ませ フォームにK0001というパラメタを表示して 入出庫を入力してもらえばよい
Googleフォームからの入力をスプレッドシートに格納する際に K0001で過去データを検索し在庫数を計算する

スマホ上のフォームでは入出庫の数量入力だけで、残数の表示はできません。結果のダイアログでも表示できないかと調べましたが、Googleフォームからは起動できないようです。在庫数量はスプレッドシートのスクリプトで計算し、必要な場面でスプレッドシートをEXCELにダウンロードして管理するマクロを起動するのが使いやすそうです。

↓スプレッドシートのコンテナバインドスクリプトのGoogle Apps Scriptはこんな感じ。

 function myFunction(e) {
   //用紙在庫スプレッドシートをシートから入力された用紙コードで検索し、初期在庫と入出庫後の在庫を入力レコードに追加する
   //LockServiceオブジェクトを生成
   var lock = LockService.getPublicLock();  
   try{
     //10秒間のロックを取得する
     lock.waitLock(10000);
     SpreadsheetApp.flush(); //(1)他のユーザが更新した内容があっても取得
     //現在のuidの値を取得する
     var Properties = PropertiesService.getScriptProperties();
     var uid = Properties.getProperty("uid");
     var usr = Session.getActiveUser();
     var sheet = SpreadsheetApp.getActiveSheet();
     var keycds = Array.prototype.concat.apply([],sheet.getRange(1, 2, sheet.getLastRow()-1).getValues());//セルを直接操作は時間がかかりすぎるので、用紙コード列を1行目から最終行の一つ前まで取得し、indexOfメソッドを使えるように1次元配列化
     var row = e.range.getRow();//回答の行番号を取得 単独で動かすと「EypeError:undefined からプロパティ「range」を読み取れません」が出る しかしフォームから起動するといいらしい
     //★フォームの最終行と、スプレッドシート自体の最終行の2種類は独立しているらしい。したがって、手削除すると間が空いてしまう
     var newkey = sheet.getRange(row, 2).getValue() ;//入力された新規用紙コード
     var row2 = keycds.lastIndexOf(newkey);//過去データの用紙コードを検索
     if (row2 == -1){
       var zaiko = 0;//過去に用紙コードが無ければ在庫は0
     }else{
       var zaiko = sheet.getRange(row2+1, 6).getValue();//過去に有れば用紙コードが一致した最下行の在庫を取得する(配列加工時に見出しを削除しているので1を加算)
     };
     //スプレッドシートの新規行を補完
     sheet.getRange(row, 3).setValue(zaiko);//過去の同一用紙コードの在庫からこのレコードの初期在庫を設定
     sheet.getRange(row, 6).setFormulaR1C1('=RC[-3]+RC[-2]-RC[-1]');//数式代入
     sheet.getRange(row, 7).setValue(usr);//ユーザー名格納
     var array = e.values;
     var msg = "";
     msg= msg + "タイムスタンプ(要9時間+):" + array[0] + "\n" +  "用紙コード:" + array[1] + "\n" +"入庫:" +  array[3] + "\n" + "出庫:" + array[4] + "ユーザー名:" + array[6];
   }catch(e){
     //時間内にロックが解除されなかったら、実行する
     //エラー内容をsys-devと入力者にメールで通知
     var array = e.values;
     var msg = "";
     msg= msg + "タイムスタンプ(要9時間+):" + array[0] + "\n" +  "用紙コード:" + array[1] + "\n" +"入庫:" +  array[3] + "\n" + "出庫:" + array[4] + "ユーザー名:" + array[6];
     MailApp.sendEmail({
        to: "xxxx@xxxxxx.co.jp",
        subject: "システムエラー通知",
        cc: usr,
        title:"★排他制御でロックされているので処理していません",
        body: msg,
     });    
   }finally{
     //処理が終わったらロックを解除する
     SpreadsheetApp.flush(); //(2)自身が更新した内容でスプレッドシートを更新
     lock.releaseLock();
   }
 }