成績処理の印刷出力 その1

目次

公開日 2023-05-24 更新日 -

成績処理の結果を印刷

1981年からの話です。多くの書類が印刷された枠に点数や出欠を手書きで記入するものでした。生徒名だけは薄い紙に印刷された表を貼り付けるか、一人ずつのゴム印を使いました。

成績処理のプログラムを作成した話 その1でも書いたように何回かの移植が必要になりましたが、プリンタも更新になります。困ったことに、PC本体だけ更新とか、プリンタだけ買替えるとかが起こります。プリンタの方式も、16×16ドットのワイヤードットから、22×22ドットのワイヤードット、24×24ドットのワイヤードット、レーザープリンタと変わっていきました。プログラムの書き換えもこの条件に複雑にからんでいて、書いているうちに思い出すという厄介な状態になるかと思います。ざっくりと書いておきます。

数字だけを書く時代

最初は16×16ドットのワイヤードットプリンタを買いましたが、オプションの漢字ROMの値段と印字品質とから導入を見送りました。数字だけなら満足に印刷できます。実は漢字が印刷できても、生徒名を漢字データで用意するのはまだ難しい状態です。まだ個人が買えるようなワープロはなく、学校には和文タイプとそれを使いこなすただ一人の事務員がいるという状態でした。

数字だけの印刷でも、問題がありました。

改行幅が合わない
印刷業者に外注する用紙の罫線はミリ単位で、プリンタはインチ単位です。合わせたつもりでもずれてきます。何行かに一回少なめの改行を入れることで合わせます。
スタート位置を合わせるのが難しい
用紙は一枚ずつローラーに挟んで位置合わせをする必要がありました。1ドットを印字して1ドット分進めたり戻したりという操作をプログラムから行って合わせることにしました。
プリンタはA4用で、B4は縦長にしか入らない
当時の用紙はB5かB4でした。B4の場合はドット分解して90度回転させた数字を出力するプログラムを作って対応しました。
実は正確に言えばパイカピッチで80桁のプリンタと136桁のプリンタがあって、一般人に買えるものは80桁だったのです。印字幅は80桁ですが、用紙の幅には余裕があってB4が縦に入ったということです。確か22万円強の値段だったと思います。本体ともに私費での購入でした。

この時代のプログラムリストはきちんと残っていない。動かせるハードが無傷で残っていないということと、記録媒体がFDDであることが大きい。HDDだと残そうという意図がなくても残っていたということがままある。

それでも、改行幅を合わせる工夫は見つけることができた。この時代のプリンタはNEC製で制御コードはPC-PR201系のものである。

改行幅を調整する
初期設定
3880  F=0 : VV!=0 : V!=.35
3890  EC$=CHR$(27)
3962  LF19$=EC$+"T19":LFAA$=EC$+"A":LF29$=EC$+"T29"
サブルーチン
9310 *VLF
9320  VV!=VV!+V!
9330  IF F<>INT(VV!) THEN F=INT(VV!):LPRINT LF19$ ELSE LPRINT LFAA$
9350  RETURN
呼び出し方
9900 GOSUB *VLF

プリンタに ESC+"T19" を出力すると19/20改行をし、ESC+"A" を出力すると20/20(普通の)改行をする。V!(!は不動小数の変数を意味する)に定数を入れておき、座ルーチンが呼ばれるたびに加算して、整数部分が増えたときだけ少なめの改行をするという仕組み。V!の値を増減することで微調整が可能となる。

1/20なのはこのプリンタコントロールコード体系が16×16ドットの文字のときに20ドット分の改行を標準としていたことによるらしい。

この頃のプリンタにはコントロールコードと文字コードを説明した冊子が付属していて、改行幅の変更や下線の設定、ドットを制御してビットマップで図を描くこともできた。

ドットプリンタでの罫線の描画

シートフィーダが導入されて、位置合わせが格段に楽になったが、印刷に失敗すると係まで用紙を貰いに行かなければならなくなる。

数字だけでなく、罫線も一緒に描けばズレることを心配する必要もないし、白紙から書類を作ることができる。印刷業者に印刷してもらうコストを軽減することができる。ということで、罫線の描画に挑戦することにした。印刷業者の書類と同等なものを作って、コンピュータ処理をしたくない人には、空欄の書類を印刷して従来どおり手書きをしてもらうというシステムを目指します。

学校の運営者側からは、コンピュータ化はお金もかかるし、仕事のやり方が変わる教員からの抵抗も大きいので一切指示は出なかった。仕事分担にがからむ作業手順にはいっさい触らずに、参加したい人だけ参加するというやり方を貫いた。それでも、広げたかったのは、3学年になってからの調査書の作成や、いろいろな統計処理に全学年の成績や出欠のデータが揃っていることが必要だったからです。

さて、ドットマトリクスプリンタでの罫線です。いまではページプリンタと比べて大変さがわかりますが、当時はそれしか方法がありませんでした。

具体例を再現してみます。用紙の左上を想定して、下図のような罫線を引くものとします。

当時のプリンタは縦24ドットでグラフィックの印字ができました。下図は縦24ドットで横が72ドットにしてあります。文字は24ドット×24ドットでしたから、図の欄の横幅ではせいぜい漢字2文字分です。高さは足りませんが、次の行と合わせて記入欄を作っていきます。グラフィクで線を描きながら、普通の印字で文字も入れていくという作業をします。ここでは罫線の印字部分だけを説明します。

これを描画するプログラムを過去のものに倣って書いてみます。この時代はEPSON製のプリンタがメインでしたので、ESC/Pの制御コードでを使っています。

ESC/Pを使用した罫線印刷の例(N88-BASIC(86))
8010 S$=CHR$(0)+CHR$(0)+CHR$(0)
8020 REP = 2
8030 GOSUB *IMGREP
8110 S$=CHR$(&H3F)+CHR$(&HFF)+CHR$(&HFF)
8120 REP = 1
8130 GOSUB *IMGREP
8210 S$=CHR$(&H20)+CHR$(0)+CHR$(0)
8220 REP = 63
8230 GOSUB *IMGREP
8310 S$=CHR$(&H3F)+CHR$(&HFF)+CHR$(&HFF)
8320 REP = 1
8330 GOSUB *IMGREP
8210 S$=CHR$(&H20)+CHR$(0)+CHR$(0)
8220 REP = 5
8230 GOSUB *IMGREP
 ・・・ 
9000 *IMGREP '(REP,S$)
9010  CONSOLE,,,,1
9020  LPRINT CHR$(27);"*";CHR$(39);CHR$(REP MOD 256);CHR$(REP \ 256);
9030  FOR R=1 TO REP:LPRINT S$;:NEXT
9040  CONSOLE,,,,0
9050  RETURN

グラフィックデータをプリンタに送るコマンドはこれです。コマンドリファレンスには同じことをASCIIコードと10進法と16進法で書いているのが普通です。便利だからです。

ESC * ビットイメージ選択
ASCII: ESC * m nL nH d1 ・・・ dk
10 進: 27 42 m nL nH d1 ・・・ dk
16 進: 1B 2A m nL nH d1 ・・・ dk

mが解像度などを決める数値で、今回は39を使っています。これば縦横共に180dpiで、縦一列のドット数が24ビット、つまり3バイトということです。

nL nH はデータが何列分であるかという数値で、nLが2バイトで表した数値の下位で、nHが上位です。63なら 16進で n=&H003F なので nL=&H3F nH=0 です。

d1 ・・・ dk はバイト列で、その数 k= n*3 です。

図で左から3列目の縦線の部分を決めるのは、行番号8110の S$=CHR$(&H3F)+CHR$(&HFF)+CHR$(&HFF) ですが、

d1 &H3F ○○●● ●●●●
d2 &HFF ●●●● ●●●●
d3 &HFF ●●●● ●●●●

なので、続けて

○○●●●●●●●●●●●●●●●●●●●●●●

これを縦に並べて

○  - d1 最高位ビット
○
●
●
●
●
●
●  - d1 最低位ビット 
●  - d2 最高位ビット
●
●
●
●
●
●
●  - d2 最低位ビット
●  - d3 最高位ビット
●
●
●
●
●
●
●  - d3 最低位ビット

の24ドットが、左を上にして縦に並ぶわけです。

CONSOLE,,,,1 はCHR$()を使ってビットデータを送る際の漢字の処理をしないようにする命令です。今回のプログラムでは当然漢字も使いますから、CONSOLE,,,,0 でもとに戻して置きます。

プリンタの機種で異なる

このプログラムの中に、プリンタの選択部分がありました。4つの選択肢が有ります。

(1) PC-PR201系 カラー印刷
(2) PC-PR201系 白黒印刷
(3) EPSON HG-4000 (ESC/P 167が使える) 
(4) EPSON LP-8000 (ESC/P 39を使う)

制御コードが違うので、それぞれにプログラムを書いて切り替えて使っていました。

上で紹介したプログラムは(4)のLP-8000用のものです。LP-8000はHG-4000の後に導入されたページプリンタでしたがページプリンタの制御コードは別物なので、とりあえずESC/Pモードで使用していましたが、その時のものです。

HG-4000のESC/Pでの罫線

HG-4000はA3が入るインクジェットプリンタで文字が美しく印字も早い機種でした。罫線を印字するプログラムはこのプリンタに合わせて開発しました。上記のプログラムではデータを繰り返すのに FOR-NEXT ループを使っていますが、HG-4000では(おそらくはHG-400までは)次のように書くことができました。

HG-4000のESC/Pを使用した罫線印刷の例(N88-BASIC(86))
9000 *IMGS '(REP,S$)
9010  CONSOLE,,,,1
9020  LPRINT CHR$(27);"*";CHR$(167);CHR$(REP MOD 256);CHR$(REP \ 256);
9030  LPRINT CHR$(1);CHR$(0);S$;
9040  CONSOLE,,,,0
9050  RETURN

ポイントはLPRINT CHR$(27);"*";CHR$(167)です。39の代わりに167を使うと指定したパターンをプリンタ内部で繰り返してくれます。

プログラム上の記述量は大して変わらないですが、プリンタに送られるデータ量はかなり少なくなります。180dpiですから、1インチ(25.4mm)の線を引くには S$ を180回送信しなければなりません。S$は3バイトですから、180×3=540バイトです。これが167が使えることで CHR$(1);CHR$(0);S$の 5バイトで済んでいます(その前の5バイトは共通)。たとえもっと長く30cmの線を引いても 5バイトはそのままです。

LP-8000の追加導入のときに、なぜか167が使えなくなっていました。プログラムは突然止まります。なぜ動かなくなったのかなかなかわかりませんでした。ESC/P のリファレンスマニュアルは別売りになってましたし、どこにもそんなアナウンスはありませんでした。

しばらく試行錯誤して ESC * 167 の代わりに ESC * 39 を使って、描画データは FOR-NEXT を使えばよいことが判明します。プログラムの改変をして動くようになったのですが、送信するデータ量が多くなったためにものすごく遅くなってしまいました。まだパラレルインターフェースの時代ですから無理もありません。画面に印刷の進捗状況を表示する部分を作ったほどでした。

今回これを書くにあたってESC/Pのレファレンスをウェブでも検索しましたが、 ESC * はあるものの、m=167 に触れられていないものが多くあります。当時はLP-8000だけの不具合と想像していたのですが、どうやらESC/Pの仕様変更だったようです。ドットインパクトプリンタのマニュアルの付録に一覧表として簡単に載っているものが若干見つかりました。しかも不正確なものもあり、この改変に触れているものはありませんでした。困ったのは私ぐらいのものなのでしょうか。

間違っていると思われる(EPSONの正式の印刷物がpdfで公開されているものですが)ので、正解を書いておきます。

ESC * ビットイメージリピート選択
ASCII: ESC * m rL rH nL nH d1 ・・・ dk
10 進: 27 42 m rL rH nL nH d1 ・・・ dk
16 進: 1B 2A m rL rH nL nH d1 ・・・ dk
m = 167
0 ≦ rL ≦ 255
0 ≦ rH ≦ 19
0 ≦ nL ≦ 180
nH = 0
k = (nL + nH × 256) × 3

解説: nL nH d1 ・・・ dk の部分は mが167でない場合と同じで、複数の列のデータを指定できます。ただしnHは0に制限されています。上の例ではただの線なので、CHR$(1);CHR$(0);S$ で良いわけです。

それに、r 回繰り返す指示が付きます。rH ≦ 19 ですが、19×256+255 = 5119 で 5119÷180 ≒ 28.43インチ ですから、実用上十分でしょう。マニュアルによってはrH ≦ 14 というのも有りましたがどちらにしても十分です。リピートのパラメータは167しかないようです。つまり、縦横共に180dpiで、縦一列のドット数が24ビット、つまり3バイトというのが固定です。

ここの解説で、こちらをメインに扱わなかったのは説明が複雑だと思ったからです。縦24ビットの長方形に描いた図形を繰り返し印字するという作業が必要な場面が思い浮かばないからだと思います。なので、ESC/Pの機能からこれが外されたのではないでしょうか。でもここで解説したように幅1ビットのデータを繰り返したいという需要ならありがちだと思いませんか。

PR201系での罫線

使うのは1列3バイトのデータを繰り返すだけの専用コマンドなので、わかりやすい。

ESC U 24ビットドット列 リピートモード
ASCII: ESC U n1 n2 n3 n4 d1 d2 d3
10 進: 27 85 m n1 n2 n3 n4 d1 d2 d3
16 進: 1B 55 m n1 n2 n3 n4 d1 d2 d3
"0" ≦ n1 ≦ "9" 繰り返し回数の10進1000の位を表す文字
"0" ≦ n2 ≦ "9" 繰り返し回数の10進100の位を表す文字
"0" ≦ n3 ≦ "9" 繰り返し回数の10進10の位を表す文字
"0" ≦ n4 ≦ "9" 繰り返し回数の10進1の位を表す文字
d1 データの1バイト目
d2 データの2バイト目
d3 データの3バイト目

繰り返し回数の表し方は、123回ならば、CHR$(27);"U0123"; とすればよいので見てすぐにわかります。

PR201の制御コードはすべて「半角の文字」なので漢字と干渉せず、ESC/Pで必要だった console,,,,1 の指定が不要です。

PR201を使用した罫線印刷の例(N88-BASIC(86))
8010 LPRINT CHR$(27);"U0002";CHR$(0);CHR$(0);CHR$(0);
8020 LPRINT CHR$(27);"U0001";CHR$(&HFC);CHR$(&HFF);CHR$(&HFF);
8030 LPRINT CHR$(27);"U0063";CHR$(&H04);CHR$(0);CHR$(0);
8040 LPRINT CHR$(27);"U0001";CHR$(&HFC);CHR$(&HFF);CHR$(&HFF);
8050 LPRINT CHR$(27);"U0005";CHR$(&H04);CHR$(0);CHR$(0);

とても簡単になります。

ただし、ビットの並び方が異なります。まず、d1が高位のビットを下にして並び、その下に d2が高位のビットを下にして並び、さらにその下に、d3が高位のビットを下にして並びます。

図で左から3列目の縦線の部分を決めるのは、行番号8020の CHR$(&HFC);CHR$(&HFF);CHR$(&HFF) ですが、

d1 &HFC ●●●● ●●○○
d2 &HFF ●●●● ●●●●
d3 &HFF ●●●● ●●●●

なので、1バイトずつ縦に並べて

○  - d1 最低位ビット
○
●
●
●
●
●
●  - d1 最高位ビット 
●  - d2 最低位ビット
●
●
●
●
●
●
●  - d2 最高位ビット
●  - d3 最低位ビット
●
●
●
●
●
●
●  - d3 最高位ビット

この後の予定

この後、さらに変化してゆきます。

(1) ページプリンタ(ESC/Page)での罫線付き印刷

(2) f-BASIC導入に伴うf-BASICの印刷機能を使った罫線付き印刷

(3) Javaの印刷機能を使った罫線付き印刷

長くなってきたので、以下次号とします。