図1●Chr関数を使って,コード番号が0から255までの文字をセルに入力したワークシート
図1●Chr関数を使って,コード番号が0から255までの文字をセルに入力したワークシート
[画像のクリックで拡大表示]
リスト1●制御コードを含むセルに色を付けるプロシジャ
リスト1●制御コードを含むセルに色を付けるプロシジャ
[画像のクリックで拡大表示]
リスト2●制御コードを削除するプロシジャ
リスト2●制御コードを削除するプロシジャ
[画像のクリックで拡大表示]
リスト3●特殊な意味を持つ文字を削除するプロシジャ
リスト3●特殊な意味を持つ文字を削除するプロシジャ
[画像のクリックで拡大表示]

 良い季節になりました。皆さん,よく遊び,よく学んでますか? 真面目なだけでは,いい仕事はできませんよ。そこの青年,顔色がよくないなぁ。

今月の相談

「データが書かれたテキスト・ファイルをExcelに取り込んで,思い通りの集計を終えた後で印刷したら,集計表の後に真っ白なページが何枚も…,何枚も。誰かに恨まれる覚えはないのですが,おはらいが必要でしょうか?」

 私はドクターなので恨みや呪いのたぐいは専門外。しかし,印刷時の怪現象にはちゃんと原因があるものです。予想される原因は二つ,それは制御コードと見えないオートシェイプ(線や図形などのオブジェクト)です。

セルに表示されない文字がある

 作成した表以外にワークシート上には何もないのに,白紙のページが印刷される場合は,どこかのセルに制御コードが入力されているか,見えないオートシェイプが存在する可能性があります。まずは,制御コードから説明しましょう。

 コンピュータは文字の処理に文字コード・セットを使います。最初に登場した文字コード・セットは,英語のアルファベットと記号だけのASCIIコードです。当初のASCIIコードは7ビット*1で128種類を表しました。ただし,すべてのコード番号に文字や記号が割り当てられているわけではなく,0~31(16進数では0x00~0x1f)には制御コードが割り当てられました。制御コードは,ディスプレイやプリンタを制御する特別な文字コードです。例えば,10(0x0a)はラインフィード(LF)でプリンタ(元々はタイプライタ)の紙を1行分送るというコマンドです。13(0x0d)はキャリッジ・リターンでプリンタのヘッド(タイプライタのロール)を元の位置に戻すコマンドとして働きます。Excelのセルでは,10(LF)は改行コード,8はBS(バックスペース),9はTAB(タブ)です。

 図1[拡大表示]は,文字コードに対応する文字を返すChr関数を使って,コード番号が0から255までの文字をセルに入力したものです。これを見ると,1~8,11,12,14~27は「・」が表示されますので,何かが入力されていることがわかります。しかし,0,9,10,13,28~31は見ることができません。また,制御コードではありませんが,32のスペースや39のシングルクォートも白紙が印刷される原因となります。

 「シングルクォートが空白ページの原因になるの?」と思う方がいるかもしれませんね。Excelでは,セルの先頭にシングルクォートを入力すると,続いて入力される数字を文字列に変換するという機能があります。したがって,セルにシングルクォートだけを入力した場合,セルには何も表示されません(入力バーには表示されます)*2。そのほか,[ツール]-[オプション]-[移行]-[Lotus 1-2-3 形式のキー操作]を選択してLotusライクにしているExcelでは,「"」は右寄せ,「^」はセンタリング,「\」は文字列フィル(セルの幅いっぱいに文字列を表示する)の記号として使われますので,やはりそれだけを入力すると何も表示されません。

 しかし,印刷時には何かが入力されていると判断され,結果的に空白ページを出力します。

特殊な文字を削除する方法

 「制御コードが白紙のページのどこかにあることがわかったとしても,そのページのセルを一つずつ調べていたら日が暮れてしまう!」---ごもっとも。こういう地道な処理はマクロでやるのが一番です。リスト1[拡大表示]は,選択されている各セルの値を調べて,制御コードを含む場合は,そのセルの背景色を黄色に変更するマクロです。

リスト1●制御コードを含むセルに色を付けるプロシジャ

Sub ControlCodeMarking()
    Dim R As Range
    Dim i As Integer
    Dim myFlag As Boolean

    For Each R In Selection
        If Not R.Value = "" Then
            For i = 1 To Len(R.Value)
                Select Case Asc(Mid(R.Value, i, 1))
                    Case 0 To 32
                        myFlag = True
                        Exit For
                End Select
            Next i
            DoEvents
        End If
        If myFlag = True Then
            R.Interior.ColorIndex = 6
            myFlag = False
        End If
    Next R
End Sub

 指定した文字の文字コードを返すAsc関数を使ってセルの値を調べます(1)。セルの値に制御コードまたはスペースが含まれる場合は,ブール型変数myFlagにTrueを代入します。myFlagがTrueの場合は,そのセルの背景色を黄色に変更します(2)。これで一目瞭然。

 「セルに色なんか付けなくていいから,制御コードを消しちゃって!」---はいはい,せっかちな人ですね,あなた。それならリスト2[拡大表示]のようにしてください。このマクロではAsc関数を使いません。Replace関数とChr関数を組み合わせて,制御コードを削除します(2)。Replace関数は,本来文字列の置換(入れ替え)を目的とした関数ですが,置換する文字列に””(文字数0の文字列)を指定することで,結果的に任意の文字列を削除できます。ここで注目してほしいのは,Chr(32)=スペースを置換していないことです。このコードでスペースを置換すると,文字列中の単語と単語の間にある本来必要なスペースまで削除してしまいます。そこで,スペースだけは(3)で,Trim関数を使って文字列の前後にあるスペースだけを削除します。Trim関数は,半角/全角両方のスペースを削除してくれるのでとても便利です。

リスト2●制御コードを削除するプロシジャ

Sub CutControlCode1()
    Dim R As Range
    Dim i As Integer
    Dim T1 As Single

    For Each R In Selection
        If Not R.Value = "" Then
            For i = 0 To 31
                R.Value = Replace(R.Value, Chr(i), "")
            Next i
            R.Value = Trim(R.Value)
            DoEvents
        End If
    Next R
    Set R = Nothing
End Sub

 表示しているワークシートのすべてのセルを対象にする場合は,(1)を次のように,

For Each R In
ActiveSheet.Cells

と変更してください。ただし,このマクロを実行すると非常に時間がかかりますので,その点は覚悟してください。

 シングルクォートなどのようにExcelで特殊な意味を持つ文字を削除するコードも紹介します(リスト3[拡大表示])。これらの文字が一つだけセルに入力されている場合,やっかいなことにセルのValueプロパティやTextプロパティでは取得できません。しかし,セルが空白かどうかを調べるIsEmpty関数ではFalse(空白ではない)が返されます。リスト3[拡大表示]では,IsEmpty関数を使って文字数ゼロの文字列でかつ空白でないセルを調べています(1)。対象となるセルが見つかると,Empty関数でセルをクリアします(2)。なお,説明のためにリスト2[拡大表示]とリスト3[拡大表示]を分けていますが,実際に使う場合,一つのプロシジャにしたほうが便利でしょう。

リスト3●特殊な意味を持つ文字を削除するプロシジャ

Sub CutControlCode2()
    Dim R As Range

    For Each R In Selection
        If R.Value = "" And IsEmpty(R.Value) = False Then
            R.Value = Empty
        End If
    Next R
    Set R = Nothing
End Sub

 おや,今回は“見えない文字”の説明だけで誌面がつきてしまいました。“見えないシェイプ”については次号で説明します。

古庄 潤