2023/08/16

ノーツで QR コード:#15)自由研究まとめ

今回のシリーズでは、QR コードについて、1. 仕組みを理解すること、2.ノーツで作成できることを目的に調査した結果をレポートしました。

仕組みの理解は残念ながら断念しましたが、ノーツで作成については何とか作成できました。ただ、人の手を借りた関係で、多くの内容が、QR コードではなく、VBA から LotusScript の移植話となってしまいました。VBA からの移植がどれほど必要なのかは不明ですが、何かの参考になれば幸いです。

”QR コードの仕組み” に期待された方、申し訳ありません。私の力不足です。ご容赦ください...


Excel VBA →  LotusScript 移植 まとめ

シリーズ後半で、Excel VBA のライブラリを LotusScript に移植する作業を紹介しました。LotusScript は VBA 互換とは言いますが実際に移植しようとすると様々な作業が発生しました。長くなったので最後に整理しておきます。


まず、移植直後の文法エラーです。

VBA のコードを LotusScript のライブラリに貼り付け、コンパイルが通るようになるまでに実施した対応です。Sheet や Range など、Excel 固有のオブジェクトが直接使えないのは当然として、次のような対応が必要でした。

  • 引数の Optional が使えない
  • 引数の ByRef が使えない
  • 予約語と変数名と衝突
  • Debug オブジェクトがない
  • IsMissing、IIf、Array 関数がない
  • 名称の違う関数がある(AscW )
  • 配列の次元変更できない
  • 定数がない(vbNewLine)


続いて、組み込み時にもいくつか問題が発生しました。

  • TypeName の戻り値に差がある
  • VBA のソースコードをコピペするとデバッガの挙動がおかしい(確証なし)


今回、移植元とした VBA のライブラリだけでこれだけの対応が必要でした。非互換な部分はほかにもあるかと思います。類似の作業を行う際には、ご注意ください。


少しだけ脱線

今回は、VBA のライブラリを LotusScript に移植しました。移植という前提上、既存のコードを残しつつ必要な改造を加える作業をしました。

ただ、途中、QR コードしか使用しないことから不要なコードを掃除したり、大規模な改造を加えました。そこまで修正するならということで、途中で気になっていた点を再検討しました。それは、#12#13 で触れた、エンコードした文字列を QR コードを表す Boolean 型の2次元配列に変換した部分です(ソースコードは #13 を参照)。

もともとの仕様のように Shape オブジェクトで作画しないので、隣のマスと連結して2マス同時に処理する必要がありません。それに伴い、Select Case 文を使い 16 通りの作画パターンを用意しているのも、移植後はコードが複雑に見えます。

そこで、この部分のプログラムを書き直してみました。

Public Sub bc_2Dms_New(xBC As String, rabBC() As Boolean)
   Dim vTmp As Variant
   Dim x As Integer, y As Integer    'QR コード配列の座標
   Dim xx As Integer, yy As Integer    'エンコード文字列の座標
   Dim b As Integer
   Dim sBin As String
  
   'QR コードのサイズ
   vTmp = Split(Trim(xBC), Chr(13) & Chr(10))
   x = Len(vTmp(0))*2 - 1
   y = UBound(vTmp)*2 - 1
   ReDim rabBC(y, x)
  
   'QR コード生成
   For yy = 0 To UBound(vTmp)-1
      y = yy * 2
      For xx = 1 To Len(vTmp(yy))
         x = (xx - 1) * 2
         sBin = Mid(vTmp(yy), xx, 1)
         sBin = Bin(Asc(sBin) - 97)
         sBin = Right("000" & sBin, 4)
         For b = 0 To 3
            If Mid(sBin, 4 - b, 1) = "1" Then
               rabBC(x + (b Mod 2), y - (b >= 2)) = True
            End If
         Next
      Next
   Next
End Sub

基本的な処理の流れは、元のコードと同じなのですが、次のような点を意識して処理をわかりやすくしたつもりです。

  • エンコード文字列を区切り文字で分離し、その数を行(YY)、文字数を列(XX)として、二次元のループで1文字ずつ処理
  • QR コード配列の基準座標(X,Y)はエンコードの文字列の座標(XX, YY)から算出
  • 演算処理や 2 進数を活用し処理を効率化
  • 処理の分岐(Select Case 文)を排除
  • drw 関数を削除(メインルーチンに統合)


ポイントは、QR コード配列を更新する個所です。

4 桁の 2 進数を右から順に処理するためループ(b)を使用していますが、この値を使用して処理する桁(ビット)と配列の座標を決定しています。

rabBC(x + (b Mod 2), y - (b >= 2)) = True

"mod" は剰余を求める演算子で、">=" は比較演算子です。比較演算子は結果を Ture か False で返しますが、True = -1、False = 0 と定義されています。

よって、このループ b においてこれらの値は次のようになります。

b + (b mod 2) - (b >= 2)
0 0 0
1 1 0
2 0 1
3 1 1

これを利用して、処理している桁(ビット)を座標に変換しています。


少々特殊な表現にはなりますが、このような演算を利用すると、プログラムがシンプルに記述できます。


最後に

今回事例で紹介した、QR コードをフォームに文字列で表示する方法なのですが、認識率が少し悪いようです(QR コードリーダによるのかもしれませんが...)。

たぶん、文字間隔が広いため、1マス分のピッチが正しく判定されないのではないかと想定しています。実際に運用する際には、簡易的な方法ではなく、しっかり作画したほうがよさそうです。

前回 ノーツで QR コード

0 件のコメント:

コメントを投稿