2025年02月28日
_ [computer] pythonでエクセル納品書
PC98+informix3.3を、会計処理及び事務処理のプラットフォームとして長らく(30年以上!)使用していますが、98に繋げてあるプリンタの継続使用がどうやらもう無理そうで、その要請にかられて一部の処理の移行を余儀なくされています。かといって基本Cで書かれているこのデータベースと処理は、やろうと思えばかなり細かい事まで出来るので、過去に何度も新しい環境への移行を考えながらもその都度断念し、現在では既にもう諦めています。(この先は98エミュかなと思っています)
とりあえずその98で作成した印字データは、Windows環境に移してWordにて、PC接続のドットプリンタで印字させる事で凌いでいますが、よく考えてみれば、伝票のドットインパクトプリンタでの印字発行は、既に一般的では無くなっています。複写も無い、プリンタによる単票印字が殆どです。印刷屋さんに作ってもらった、ドットプリンタ用の専用納品書も残り少なくなっている事も有り、まず納品書からwindowsからのレーザプリンタでの単票印刷にすることにしました。
具体的には、98で作った納品書データをエクセルに移して、そこから印字させればそれで良さそうです。やり方として、一つは、現在納品書発行の印字データを出力しているinformixとMS-Cのプログラム(informixレポートライターのACEは使わず、Cで直接書いている)を書き直して、CSV形式とかの処理しやすい出力にして、それをエクセルで読み込んで後は必要があればVBとかで整形する方法です。
もう一つは、現状のプリンタ出力用のデータを直接読み込んで、整形しつつエクセルのデータとするやり方です。
スマートなのは、当然元の出力プログラムから書き換える事ですが、今更元のCのプログラムを書き換えるのが面倒だったので、現状のデータをpythonを使って加工して、エクセルのデータにすることにしました。
今回pythonを使うにあたり、今まではCMDと普通のエディタでしたが、暫く前にVSCodeの解説本も買っている事も有り、VSCodeを使う事にしました(当方も、流行の方式に慣れなければ、です)。
常時使っている訳で無いので、すぐ仕様や文法を忘れてしまいます。pythonの本とかも買ってはあるのですが、書物の目次をひくより、最近は"python (調べたい事)"で検索した方が、ずっと早いです。
それに簡単な雛形は、ChatGPTに教えてもらった方が、より簡単です。細かい仕様まで全部AIに伝えれば、プログラムを全部書いてくれる様ですが、でもそれでは、まぁ、仕様の完備性を求めるだけで、何のプログラムを書いているのか分かりませんし、何よりおもしろくはありません。
で、書いていて、すんなりプログラムが書ける訳はなく、、
まず「確かpythonにはcase文が無かった筈なので、代わりの構文は、、」と検索してみますと、何と、最近のpythonはcase文が有るらしい。ヴァージョンによって通らないプログラムは面倒なので、ヴァージョンアップによる仕様変更は通常はあまり歓迎しないのですが、これは結構有難い変更です。私も、早速使わせて戴きます。
最初は、読み込んだ文字列をsplit()で分けて処理すればそれで楽勝、と思っていましたがそう甘くは無く(空白が不定期に入る場合が有るので)、「そんな場合は、文字列のこの部分をそのまま転記する事にして、それなら文字列のスライスで」と思ったのですが、全角と半角が混じっているのでpythonでは適切に処理できませんでした。
Shift-JISのPC98のMS-DOS環境では、半角は1バイト全角は2バイトと決まっていて、印字のカラム数も半角は1カラム全角は2カラムとなっています。それが普通だと思っていましたが、pythonは文字処理が優秀で、s="あaいb"でも、s[0]は"あ"、s[1]は"a"となります。元データに半角と全角の入り方の明確な規則が無い為、文字列のスライスでは、元の印刷データの決まったエリアを正確に選択できません。
色々調べた所、文字列を一度Shift-JISでエンコードしてバイト列に変更し、そこでスライスしてから、またShift-JISでデコードする事にしました。こんな感じです。
s_sjis=s.encode('shift_jis', errors='ignore')
ws.cell(row=i,column=3,value=s_sjis[0:24].decode('shift_jis'))
まぁ、元の出力のプログラムから書き換えればこんな事考えなくても良かった訳で、結局どっちが楽だったか微妙な所です。
その他、pythonで書いていて、この度新たに気がついた事は、print(*)の出力は、特に何も指定をせずに列記すると、出力はスペースで区切られる事。つまり、
>>> print("123","456") は、
>>> 123 456 になってしまう事に、少々びっくりした。
print()は、データ確認の為に書きかけのプログラムにはよく挿入するけど、今まで気がつかなかった(本当はVSCodeのデバック機能を使えばよいのだろうけど、私には旧来の方法で充分)。今回文字の位置を確認する為だったので、何故かスペースが多めに入っているので確認したら、
【objects を sep で区切りながらテキストストリーム file に表示し、最後に end を表示します。】
となっていました。print関数の引数にsep=''と入れておけば、スペース無しになるようです。