2015年7月14日火曜日

第3話:プリンタ印刷時にフッタにバーコードをつける

バーコードに夢見ての第3話「プリンタ印刷時にフッタにバーコードをつける」です。

目次
  • バーコードに夢見て (リンク
  • 第1話:無料のバーコードリーダーを使えるようにする (リンク
  • 第2話:JANバーコードを作る (リンク
  • 第3話:プリンタ印刷時にフッタにバーコードをつける (リンク)
  • 第4話:実験Iがバーコードで管理される (リンク
  • 第5話:学籍番号がバーコードになったシールを配る (リンク
  • 第6話:学籍番号と課題番号をバーコードを短冊状に印刷して配る (リンク
  • 第7話:表紙作成マクロ (リンク
  • 第8話:QRコードの作り方を書いた解答用紙を配る (リンク
  • 第9話:QRコード自動埋め込みレポート用紙 (リンク
  • 第10話:ラベル屋さん9 web版を使う(研究) (リンク
  • 第11話:ラベル屋さん9 web版を使う(バーコード付き学籍番号シール) (リンク) 
  • 第12話:無償のバーコードフォントを見つける (リンク)

■プリンタ印刷時にフッタにバーコードをつける

 2003年まで、情報工学科では Sun製のWorkstationを使ってコンピュータの演習をしていました。この環境で印刷するときは、lprcというコマンドを使って印刷します。lprcは、 助手の先生が作られたコマンドで、このコマンドを使うとテキストファイルがPostscriptファイルに変換され、フッターに印刷日時と学籍番号(アカウント名)を添えて、印刷されます。ここに、学籍番号をバーコードとして印刷しておけば良いんじゃないかと思いました。

 幸いにもlprcコマンドはシェルスクリプトでしたので解析可能です。またlprcからはa2psという「テキストファイルをPostscriptファイルに変換する」コマンドが呼び出されていました。そしてa2psはPerlスクリプトでしたので、こちらも、変更可能です。

 以前にExcel(VBA)でバーコードを生成するプログラムは書いています。これをPerl用に書きなおして、a2psコマンドに組み込みます。そして試したところ成功しました。
フッターに学籍番号のバーコードを入れた実行例
(テスト用環境で作成したため、実際の出力とは異なります。実環境では学籍番号(アカウント名)も表示されます)

■インストールする

 当時下っ端の助手だった私は、偉い助手の先生に、「lprcコマンドを改造して、フッタの隙間にバーコードを印刷するようにしたのですが、これを全ユーザーが使えるようにしてもよいですか?」と聞いたところ快諾いただきました。

 学生さんたちは気づいていなかったようですが、こっそりフッターにバーコードが印刷されるようになっていました。

 他の先生は、レポートの表紙を見て学籍番号をチェックしていましたが、私は表紙をちらっとめくって2枚目(以降)のページのフッターに印字されたバーコードをスキャンして、学生のレポートの提出状況を管理していました。


■Postscriptのコード

 a2ps内に以下の記述を追加しています。

 if ( $pattern ne "(null)" ) {
     print "gsave\n";
     print "430 25 translate\n";
     print "16 16 scale\n";
     printf "67 5 4 [8 0 0 8 0 0] {<%s>} image\n", $pattern;
     print "grestore\n";
 }

$patternは、バーコードのパターンが格納されています(黒と白の並び)。これを表示しているわけですが、これで動く仕組みが全く思い出せません。バーコードの白黒の並びをPostscriptを生成しているのですが、このPostscriptの意味が全く分かりません。当時、Postscript言語の必要なところだけ、勉強して対応したのだと思います。 これぞHack(やっつけ仕事)です (^_^)。

■付録:JAN8のバーコードパターン作成プログラム

 JAN8のバーコード作成部分、つまり黒と白の並びのパターンを生成するPerlプログラムは以下の通りです。上記のプログラムとあわせて、80行程度(空行含む)でバーコードを作っています。

sub get_pattern {
    local($username) = `whoami`;
    chomp($username);

    if (!( $username =~ m/[a-z][0-9][0-9][0-9][0-9][0-9][0-9]/ )) {
    return "(null)";
    }

    $username =~ s/^.(.*)/$1/;
    local($ret) = &barcode_pattern($username);
    $ret =~ s/0/E/g;
    $ret =~ s/1/0/g;
    $ret =~ s/E/F/g;
    return $ret;
}

sub barcode_pattern {
    local($num) = (@_);
    local(@LeftBar, @RightBar, $LeftGardBar, $RightGardBar, $CenterBar);
    $LeftBar[0]  = "0001101"; $LeftBar[1]  = "0011001";
    $LeftBar[2]  = "0010011"; $LeftBar[3]  = "0111101";
    $LeftBar[4]  = "0100011"; $LeftBar[5]  = "0110001";
    $LeftBar[6]  = "0101111"; $LeftBar[7]  = "0111011";
    $LeftBar[8]  = "0110111"; $LeftBar[9]  = "0001011";

    $RightBar[0] = "1110010"; $RightBar[1] = "1100110";
    $RightBar[2] = "1101100"; $RightBar[3] = "1000010";
    $RightBar[4] = "1011100"; $RightBar[5] = "1001110";
    $RightBar[6] = "1010000"; $RightBar[7] = "1000100";
    $RightBar[8] = "1001000"; $RightBar[9] = "1110100";
    $LeftGardBar  = "101";
    $RightGardBar = "101";
    $CenterBar = "01010";

    local(@bar)=unpack('C6', $num);
    for ($i = 0; $i < 6; $i++) {
    $bar[$i] -= 48;
    }
    $bar[6] = 0;

    local($c) = 0;
    for ($i = 0; $i < 7; $i++) {
        if ($i % 2 == 0) {
        $c += $bar[$i] * 3;
        } else {
        $c += $bar[$i];
        }
    }
    $bar[7] = 10 - ($c % 10);
    if ($bar[7] == 10) {
    $bar[7] = 0;
    }
    
    local($pattern) = $LeftGardBar;
    for ($i = 0; $i < 4; $i++) {
        $pattern .= $LeftBar[$bar[$i]];
    }
    $pattern .= $CenterBar;
    for ($i = 4; $i < 8; $i++) {
        $pattern .= $RightBar[$bar[$i]];
    }
    $pattern .= $RightGardBar;
    return $pattern;
}

0 件のコメント:

コメントを投稿