にっきダイアリー

はてなダイアリーからはてなblogに移動してみました。

センチメートル単位で Excel のセル幅を指定する - 2006/04/12

追記(2016/12/27)

Excel2016あたりから、新規でブックを作ると標準スタイルのフォントが游ゴシックになってまして、案の定、下記マクロ&関数で算出した数値が食い違うようになりました。

それに気がついたのが9月頃の話なんですが……ていうか、これまで私はページレイアウトをほとんど使ったことがなかったので全然気がついてなかったんですが、表示をページレイアウトにすればセル幅をcm単位で確認しながら変えられるので、いちいちマクロだの何だので計算しなくてもいいんじゃないかなあって。

てことで、以下のマクロはもはや必要ないと思われますが、昔イライラしながらやってたよなーっていう思い出日記として残しておきます。

こっから本文

Excel を使っていて、一番悩み且つ作成に時間がかかるのが、枠が印刷された用紙にあわせて文字を印刷しなきゃならないようなシロモノであります。

Excel って、印刷用紙の余白サイズ指定こそセンチメートル単位で出来るけれど、主役たるシートの中のセルのサイズは、縦がポイント、横が文字の数、という悩ましい単位で指定しなきゃならない。まぁ、高さを指定するほうはまだ楽。ポイントは 1 / 72 吋 = 25.4 / 72 mm = 約 0.35mm ということを覚えていれば暗算できるレベルだし、VBA には InchesToPoints とか CentimetersToPoints とかいうステキメソッドがあるので、暗算できなくてもマクロで計算すればいい。問題は幅のほう。Excel のヘルプ読みますと、「"列幅の単位は、標準スタイルの 1 文字分の幅に相当します。プロポーショナル フォントでは、数字の 0 の幅が列幅の単位になります"」とか書いてある。そして、その標準スタイルの数字の 0 の幅なんてものはマクロで計算できないにもかかわらず、文字幅でしか指定できないのであります。

しょうがないので、ある程度目測(18ptの高さとで正方形に見えるセルの幅はきっと18pt)とか、憶測(漢字は縦横同じサイズだから11ptの漢字が10個表示できるならたぶん110pt)とかでセルの高さや位置を合わせておいてから、実際に用紙に印刷し、印刷結果のずれを見ながら調整していくという、本来どうでもいいような作業をちまちまやるしかないと。

手動で調整するなら文字数で幅指定できたほうがいい場合もある。確かにそう思う。けど、VBA の仕様が馬鹿すぎる。ポイント単位の Range.Width は読み取り専用プロパティで、指定するのは文字数単位の Range.ColumnWidth を使えとか、なんでこんなアホタレなつくりのままなんだ。

つくづく枠線文化な日本にそぐわねぇ仕様だこと。だいたい基本が 72dpi とか、10進法で綺麗に割り切れないうえに世界共通単位系じゃない数を使うんだ、あっちの国の人間は。日本の文字サイズ単位を見ろ、文字の1級=0.25mmだぞ。なんて美しいんだ。

とはいえ、メリケン文化にけちをつけたからといって、Excel2003 が級数使ってセル幅を指定できる世界に変わるはずもない。何かいい方法はないかとググって見ると、自作マクロとか公開しているサイトがあった。Excel のセル上に「ものさし」を表示するマクロや、そのものずばりミリメートルやインチでセルサイズを指定するマクロなどを公開している。ただまあ、これはどうも手動でセルのサイズを変更する際の手助けにはなるようだけど、自作マクロに組み込むような形ではないようだ。実際にダウンロードしてないのでそこらへんわからないけれども、改造して使うのは面倒くさそうだ。

というわけで、よそさまの成果を使わずに、結局自分で adhoc に車輪を作ってみるテスト。 Excel を立ち上げて新しいワークブックを作ると、標準のスタイルのフォントがMS Pゴシックの 11pt になっている。普段標準スタイルをいじった文書などつくらないので、この状態で出てくる固定の数値を使って変換しちまおうと。

でまぁ、ちょっと試行錯誤した結果、うちの環境だと Excel が幅 41 ピクセルだというセルを印刷すると幅1センチになることが判明している。さらに、MS Pゴシック 11pt な Excel 上では1文字以上の文字幅のセルの横幅が、文字数×8+5ピクセルになる。そこで、セル幅=(41×センチ−5)÷8 という式(幅が1以上の場合)が導き出される。だんだん自分で書いててMMRに並にうさんくさい文章な気がしてきたが、マクロで書くと

Sub CentimetersToColumnWidth()
    Dim cm ' センチ
    Dim mh ' 文字数
    
    cm = 5
    mh = (cm * 41 - 5) / 8
    Selection.ColumnWidth = mh
End Sub

こんな感じ。で、マクロを実行すると、選択したセルの幅が25(205ピクセル)になり、これを印刷するとだいたい5センチくらいになる。ただまあこのままだとあんまり小さい値の場合誤差が出てくる。セル幅が1以下の時はピクセル数の計算が変わってくるのだな。そこで、その部分の処理を付け加えると、

Sub CentimetersToColumnWidth()
    Dim cm ' センチ
    Dim mh ' 文字数
    
    cm = 0.3
    mh = (cm * 41 - 5) / 8
    If mh < 1 Then mh = cm * 41 * 0.075
    Selection.ColumnWidth = mh
End Sub

実行するとちゃんと、0.3センチの幅のセルになる。

ということで。とりあえず、まとめとして、InputBox で入力した数値で選択されたセル幅を変更するマクロ。

Sub CentimetersToColumnWidth()
    Dim cm ' センチ
    Dim mh ' 文字数
    cm = InputBox("幅をcmで入力してください", "選択しているセルの幅を変更する")
    cm = Val(cm)
    If cm <= 0 Then Exit Sub
    mh = (cm * 41 - 5) / 8
    If mh < 1 Then mh = cm * 41 * 0.075
    Selection.ColumnWidth = mh
End Sub

マクロの中に 41 とか、8 とか 5 とか 0.075 とか魔法の数字(とくに 41 は印刷して1センチになる幅のピクセルを数えただけなので、どうしてそうなのかは私も知らない)がいっぱい出てくるので、環境によってはうまく動かないと思うが、うちの会社のパソコンの環境でうまく出来りゃいいんだ。たぶん、でも、画面のプロパティが 96dpi で Excel の標準スタイルが MS Pゴシック 11pt な環境の人なら期待したとおりのセル幅になるかもしれない。うん。たぶんだけど。

追記(2016/05/27)

ちょっと調べたい時にいちいちマクロの入ったファイルを開くのも面倒くさくなり、上記のVBAマクロをワークシート関数で書きなおしてみた。
A1の部分はセンチメートルの数値を入力するセルの番号に書き換えてください。

=IF((A1*41)<13,A1*3.075,((A1*41)-5)/8)

マクロも関数も、指定した長さによってはセル幅として正確に指定できない数値が出てきます。10.3445とかね。だけど、文字幅って小数点以下は .0、.25、.38、.50、.63、.75、.88しか指定できないでしょ。
なので、どうしても誤差は出ます。(マクロにしても多分指定した瞬間、ピクセル換算できる数値に丸められちゃってると思うんだな)
すでに枠線が印刷されてる用紙にピッタリ合わせて印刷したいとかいう場合は印刷>微調整の繰り返しでよろしくお願いします。