最近、事務処理のフォーム作成を頼まれることがありました。結果を示すなら、例えばこんなものです(詳細は伏せています)。
これを作るにあたってもちろん考えたのは、一般的な編集ソフトの利用でした。 しかし、現状で流通しているソフトの利用に私は慣れないです。 昔のMacDrawとか、ClarisImpactといったソフトなら、要素を狙うところに置くことができたのに、 最近のソフトは何でも自動でしてくれるのは良いが、それを抑えてこちらの希望を入れることが、逆にできにくくなっています。
上の例では、2種類の行間隔の違う表を左右に並べる必要があります。 実現する方法はあるのかも知れませんが、大手のソフト会社は、研修を受けてくれたら、ひょとすると解決が見つかるかも知れませんよ、という態度のように思います。
小学生にまでプログラミング教育が言われる昨今、難しくはあっても解決の道筋が見えているプログラミングとは相いれないこういう作業に対して違和感を私は感じます。 同じところから頂いたもう一つの課題は次のようなものでした。
小さいフォームですが、行の配置が絶妙です。 上の「日誌」や「連絡票」を作るためにとりあえず私が採用したのは、 「ページの自由なデザイン」でもしていたグラフィックとプリントの方法でした。
しかし、こういうことを繰り返しする内に、プログラミング言語の中の限られた範囲のものを集中して使っているので、 その機能のみを指示することができる手段を作るのも面白いかなと考えました。 なぜなら、私の信じるところ、機能を絞ることもプログラミングの立派な目標なので(そうでないなら、誰もがC言語だけを弄っていれば良いことになる)。
そこで、フォーム編集のための専用言語を作り、使ってみました。次に挙げるのは、複数ページの文書の例です。
印刷の寸法確認をしました。このテストパターンは次のものでした。
これらの文書のソース、すなわちプログラムは、主にテキストファイルです。拡張子は*.txtのままでも良いですが、*.fmmに変えておくと最初に検索できます。 それぞれの文書を作るプログラムは次のようになります。
大括弧 [] で囲った命令を「タグ」と称することにします。タグは各行に多くても1個のみです。 タグのない部分として代入文があります。代入文で扱われる数値は浮動小数点数です。 数値には定数と変数とがありますが、先頭に「#」が付いているのが変数です。 定数については、(同じページの中で)再定義ができません。
いくつかの限られた変数「#T, #R, #H, #U, #E, #W, #N, #S」には、後で述べる特別の役割があります。 タグのある文において、タグ以前に代入文を置くこともできます。 代入文には必ず等号「=」が入ります。代入文が並ぶとき、区切りにコンマ「,」が使われます。 等号の左辺は単一の変数または定数です。 等号の右辺は、変数、定数、先頭にマイナスのついた変数や定数、数値から成る列です。 それらは基本的に足し算されますが、先頭に「*」がついた場合は掛算、「/」がついた場合は割算となります。 ですので、「+」は基本的には使いません。
演算の種類によらず、必ず先頭から優先的に計算されます。 だから、「a=4 2 *2」では、aには(8でなく)12が入ります。 代入式の結果にも値があって、それは代入された式の値です。 ですので例えば、「a=1, a=(b=a 2) 1」とあれば、最終的にaには4、bには3が入ります。
タグの機能は以下の表によります。
[PSize] | 規格されている紙のサイズです。現状では、A3,A4,B4,B5,Letter,Tabloid,Legal,Executive 。 |
---|---|
[Page] | ページの区切りを表わします。最初のページ文以前の記述は、全てのページに共通します。 引数は数値ではなく、単なる名前として扱われます。 同じ名前のページがあることは、好ましくはないが、禁じてはいません。 単一ページの場合は必ずしも必要なく、「default」がページ名となります。 |
[End] | プログラム文がそこで終っていることと同じです。 デバッグのための配慮であり、なければプログラムの最後で終わります。 ページが呼び出される毎の判断ですが[Page]に優先し、選択されていないページの中でも有効です。 |
[Iter] | その後にある[IEnd]文までの間を引数回だけ繰り返します。 |
[IEnd] | [Iter]に始まるくり返し区間の終了を宣言します。 |
[LColor] | r,g,bに対応する3つの整数値(0~255)で線の色を指定します。 次回の同じ指定までは保持されます。 宣言がない場合、デフォルトの色は黒(0,0,0)です。 |
[TColor] | 文字の色を同様に指定します。 |
[LStyle] | 破線、点線のスタイルを指定します。 可能なのは、Dash,Dot,DashDot,DashDotDotの各文字列です。 |
[TFont] | フォントファミリー、フォントサイズ、またはその両方を指定できます。 |
[Text] | 文字列(グローバルに一個)を指定します。 |
[TextWild] | [Text]とほぼ同じですが、コメント指定「//」が無視されます。 |
[AText] | 文字列(グローバルに一個)に、改行後、追加します。 |
[ATextWild] | [AText]とほぼ同じですが、コメント指定「//」が無視されます。 |
[ToText] | 引数である数値を、文字列(グローバルに一個)に変換します。 |
[PageToText] | 現在のページを表わす文字列を、グローバルな文字列に変換します。 |
[Dump] | 引数である数値を、ページの先頭から上書きします。あくまでデバッグのための手段です。 |
[Dtext] | グローバルな文字列を書きだします。引数には、x位置、y位置、幅(省略可)が指定されます。 行間隔は#Hで指定されますが、これがゼロのときは、デフォルトの間隔が使われます。 書き出し以降のy位置が変数#Uに代入されます。 #Rにゼロでない値があると、角に丸みのある長方形の線で囲われます。 各行の中身が「,」で区切られてるマルチカラムの利用が可能です。 この場合、[DText]をくり返して呼び出すと、左のカラムから順に利用できます。 |
[DSingle] | 単一行を書きだします。引数には、x位置、y位置、幅(省略可)、さらに「;」の後に、文字列を直接指定します。 |
[DSingleWild] | [DSingle]とほぼ同じですが、コメント指定「//」が無視されます。 |
[ResetColumn] | マルチカラムを初期状態に戻します。 |
[DRect] | 長方形を画きます。左端、右端、上端、下端は#W,#E,#N,#Sで指定されます。 太さは#Tで、角の丸みは#Rで指定されます。 |
[DOval] | 長方形の要領で楕円を描きます。 |
[DHoriz] | 水平線を描きます。限界は、#W,#Eで決められますが、y位置は引数で指定します。複数のy位置指定が可能です。 太さは#Tによります。 |
[DVerti] | 垂直線を描きます。限界は、#N,#Sで決められますが、x位置は引数で指定します。複数のx位置指定が可能です。 太さは#Tによります。 |
[DSlant] | (#W, #N)から(#E, #S)への直線を描きます。これにより、あらゆる直線が可能です。なぜならば、 #W < #E や #N < #S は強制されていないからです。 太さは#Tによります。 |
[DImage] | 画像を描きます。x, y, w, h, 画像ファイル名 の順で指定します。 |
さて、最後のテストパターンを出してみて、発覚したことがあります。 各プリンタに付随して登録されているデータを見ると、例えばA4については、横が827、縦が1169とあります。 A4の横幅は210mmですから、このデータが言っている1は、210/827≒0.2539299 mm ということで、 1インチ25.4 mm の100分の1に極めて近い値と言えます。 このことから1ピクセルは100分の1インチに設定されているように思われ、私も過去にそのように書いていました。 ところが、これを信じてフォームを作ると、4%以上大きなものが出来上がってしまいます。
整理しましょう。横が827、縦が1169といった寸法データは、100分の1インチを単位として定義されたものに間違いないです。 ですが、この1単位が即、ピクセルかというと、そうではないようです。 プリンタの描画は、100ではなく、96ピクセルで1インチになります。 これは国産のプリンタだけでなく、Adobe Acrobat でも同じです。
A4で横が827ピクセルと思ってデザインしてしまった場合は、以下のプログラム(FormMaker.cs)の9行目にある「AdjustmentOnPrint」を true にしておくと、印刷時に補正されます。 一方、最初から4%だけ小さくデザインしておく手もあります。 その場合は同論理値を false にして下さい。その場合は、つぎのように紙サイズの限界が線引きされます。
以上のルールで書かれたプログラムをコンパイルする⦅pdf化,印刷,画像ファイル作成⦆ためのプログラムは次のものです。
FormMaker.cs