文字列のスペースを削除・集結するTrim関数
文字列にくっついているスペースを削除するには、通常Trim関数を使用します。セル上の数式として使用するワークシート関数の「TRIM」もありますし、VBAとしては「Trim」関数の他にも、WorksheetFunctionオブジェクトの「WorksheetFunction.
今回はその違いと、削除できるスペース・出来ないスペース、および集結されるスペースについて、整理します。
1.Trim関数の概要
ワークシート関数・VBA関数のTrimについては、多くのサイトで解説されています。機能をまとめると図1のようになります。ワークシート | VBA | ||
---|---|---|---|
TRIM | Trim | Worksheet | |
両端のスペース | 削除 | 削除 | 削除 |
文字列間スペース | 1つに集結 | そのまま | 1つに集結 |
使い方をVBAのTrim関数を代表にして示すと「 Trim( 文字列 ) 」のように、引数に処理する文字列を指定します。戻り値は図1のように、「両端」及び「文字列間」について「スペースを削除・集結」した文字列となります。
2.ヌルが含まれる場合
Trimについて、他のサイト等では「指定した文字列内にヌル値が含まれていた場合は、ヌル値を返す」とあります。Excelの中でヌル値と呼ばれるものは、図2に示す「Null」「vbNullChar」「vbNullString」の3種だと思います。
内容 | |
---|---|
Null | VarTypeではvbNullを示す「未定義値」 |
vbNullChar | Asciiコード=0の1文字を表す定数。 「Dim S As String * 20」のように固定長文字列として宣言した変数の1文字1文字に相当。 データを入れた後でも、データで埋まらない部分はvbNullCharのまま。 |
vbNullString | String型の初期値で可変長文字列型。 「Dim S As String」のように宣言した直後の変数に相当。 一旦データが入るとvbNullStringでは無くなる |
この3種のヌルを使って「"abc" & Null & "def"」のような文字列を作り、ワークシート上のセル、及びVBA上の変数に書き込んだ時の値が図3です。なお表中の「+」は、文字列がつながっている事を示します。
作った文字列 | セル上 | VBA上 |
---|---|---|
"abc" & Null & "def" | "abcdef" | "abcdef" |
"abc" & vbNullChar & "def" | "abc" | "abc"+vbNullChar+"def" |
"abc" & vbNullString & "def" | "abcdef" | "abcdef" |
vbNullChar & "abc" | ""(長さゼロの文字列) | vbNullChar+"abc" |
図3はTrim関数で処理する前の値ですが、「Null」と「vbNullString」では、既にヌルが無くなった状態になっています。
一方「vbNullChar」は、VBAではそのままの形ですが、セル上では「vbNullChar 以降が削除」された値として表示されます。
そして図3の一番下は「vbNullCharが先頭」に来た時で、セル上では「""(長さゼロの文字列)」となります。
Trim関数でのヌル値の処理内容を調べるのに際し、まずNullとvbNullStringは「Trim関数で処理する前にNullが無くなる」ので除外しておきます。残ったvbNullCharについて、Trim関数処理をした結果を図4にまとめました。
引数 | ワークシート | VBA | |
---|---|---|---|
TRIM | Trim | Worksheet | |
"abc" | "abc" | "abc" | "abc" |
vbNullChar | "" | vbNullChar | "" |
ワークシートのTRIM関数は、処理前で既にvbNullChar以降は存在しませんので、vbNullCharより前の文字列のみとなります。
またWorksheetFunction.TrimもワークシートTRIM関数と同じ処理内容となるようで、同じく「vbNullCharより前の文字列のみ」となります。
一方VBAのTrim関数では、引数で指定した文字列が(今回は普通のスペースが無いので)そのまま出力されます。
但しその値をMsgBox等で確認しようとしても、図5のようにvbNullChar(NULと表示されている文字列)以降を表示することは出来ませんし、またVBE(ExcelのVBAコードを編集するツール)のウォッチウインドウやローカルウィンドウでも値の列にも、vbNullChar以降の値は示されません。
図5
vbNullChar以降を確認するには、コード内の「Debug.Print [変数]」によりイミディエイトウィンドウに出力したり、イミディエイトウィンドウで「? [変数] 」と指定し出力させる事で可能です。
以上の事から「ヌル値が含まれていると、ヌル値を返す」という特性は、何を指しているのか分かりませんでした。
しかしヌル(特にvbNullChar)が含まれる場合には、上記で説明したように充分注意が必要です。
3.スペースの種類
「Trim関数の概要」では、Trimで処理するものを単に「スペース」としていました。スペースの代表格は、キーボードを使って入力できる「半角スペース」と「全角スペース」だと思いますが、ヌルの項でも説明した「vbNullChar」も見かけはスペースに見えますし、HTMLで使用できるスペースも含めると図6の様に多くの種類があります。「HTMLは無関係だ」と思うかもしれませんが、「サイトの文字列をコピペでワークシート等に貼り付けた後、その文字列をExcelで処理」する場合には考慮する必要が出てきます。
なお、これ以外にもスペースは多く存在します。詳細は「Unicode のスペースは色々あるし、半角スペースと は同じでもない」のサイトなどを参照下さい。
種類 | コード(10進) | 備考 | ||
---|---|---|---|---|
Shift-JIS | UniCode | |||
1 | ヌル | 0 | 0 | String型固定長文字列。VBAでは「vbNullChar」 |
2 | 半角スペース | 32 | 32 | 幅=1/4 em |
3 | No-Break Space | 160 | 160 | スペースの箇所では自動的改行せず。幅=1/4 em。HTMLでは「 」 |
4 | En Space | (63) | 8194 | 幅=1/2 em。HTMLでは「 」 |
5 | Em Space | (63) | 8195 | 幅=1 em。HTMLでは「 」 |
6 | Thin Space | (63) | 8201 | 幅=1/5 em。HTMLでは「 」 |
7 | 全角スペース | 8481 | 12288 |
図6 No.1の「ヌル」は、ヌルの項で説明した「vbNullChar」です。「ヌル」と表現するのは適切で無いのかもしれませんが、Asciiコード表などを見ると「NUL」や「Null文字」と記されていますので、ここでは「ヌル」とします。
「vbNullChar」は、例えば固定長の文字列で「データが入らなかった部分」です。
図7のような「固定長ファイルからデータを取得」するプログラムで説明すると、02行目「Adata As String * 20」のように「20文字のデータ/1データ」として宣言すると、宣言された変数(ここでは変数Adata)は「20個のヌル文字」となります。そして実際に変数に取り込んだデータが20文字未満の場合は「データで埋まらなかった変数の末尾」にはヌル文字(vbNullChar)が残ります。この残されたスペース(=ヌル)を削除する際にはTrim関数などを使用することになります。
- '========== ⇩(1) 固定長データの構造宣言 ============
- Type Record
- Adata As String * 20 '←Adata項目の長さを指定
- End Type
- '========== ⇩(2) 固定長データの取得 ============
- Sub ReadData()
- Dim RD As Record '←ユーザー定義型変数を設定
- fileNo = FreeFile '←空いているファイル番号取得
- Open [固定長ファイルのパス+ファイル名] For Random As #fileNo Len = Len(RD)
- Get #fileNo, [取り出すデータ位置], RD
- [取得データ] = RD.Adata
- Close #fileNo '←ファイルを閉じる
- End Sub
図6のNo.2「半角スペース」とNo.7「全角スペース」は、キーボードから入力できるスペースなので、説明は省きます。
なお図6の備考列に記した「幅=1/4 em」等の「em」というのは、文字の高さに対する割合を示す単位です。HTMLに於いての半角スペース(1/4 em)は、文字サイズが12ポイントであれば、幅は基本的には「3ポイント」となるようです。
このem値について、HTML上で使用する上での説明はいくつかのサイトで見かけたのですが、ExcelやWordでの言及は見当たりませんでした。 恐らくフォントにより幅が異なってくる為では?と推測しているのですが、Excel等のMs-Officeでは 上部リボンの「挿入」タブ→「記号と特殊文字」→「記号と特殊文字」ダイアログ→「特殊文字」タブを選択 から、「全角スペース」「半角スペース」「1/4スペース」「改行をしないスペース」を選択することが可能です。 但しExcelで試してみましたが、全角スペースの幅(≒文字の高さ)は半角スペース2つ分、半角スペースと1/4スペースの幅は同じであり、em単位とは違う考え方の様です。 |
No.3「ノーブレークスペース(No-Break Space)」は、HTMLでは「 」と表現されます。通常、ページの右端では「文字列と文字列の間の(通常の)スペース」で自動的に文章が折り返されますが、ノーブレークスペースをスペースとして使用すると「自動的には改行しない」ことになります。
No.4~No.6の「En Space」「Em Space」「Thin Space」もHTMLで使用されるスペースですが、ノーブレークスペースとは幅も異なりますし、また自動的改行を防止する機能もありません(通常スペースと同様、ページの右端にあれば改行する)。
なお、Shift-JISのコード番号は「63」と記しましたが、このコード番号は「?」を表します。しかし、この特殊文字を使ったHTMLサイトからコピペでワークシートに貼り付けても、特に「?」という表示にはなりませんので、カッコ付きにしています。
4.処理可能なスペース
ExcelのTrim関数等に「スペースを削除・集結する機能」がある と言っても、図6の全てのスペースに対応できる訳ではありません。関数ごとに、どのスペースが処理できるかをまとめたのが図8です。種類 | ワークシート | VBA | ||
---|---|---|---|---|
TRIM | Trim | Worksheet | ||
1 | ヌル(vbNullChar) | (〇) | × | (〇) |
2 | 半角スペース | 〇 | 〇 | 〇 |
3 | No-Break Space | × | × | × |
4 | En Space | × | × | × |
5 | Em Space | × | × | × |
6 | Thin Space | × | × | × |
7 | 全角スペース | 〇 | 〇 | 〇 |
まず、通常の「半角スペース(図8のNo.2)」「全角スペース(No.7)」は、当然ながら「全てのTrim関数」で図1のルールに従って処理されます。
次にNo.1のヌルに対するワークシートTRIM関数についてですが、図3で説明したように、セルに「ヌル文字(vbNullChar)を含めた文字列」を入力すると「ヌル以降の文字列は無視」されます。例えば「"abc" & vbNullChar & "def"」のような文字列は「"abc"」のみになります。
但し、上記図7のプログラムのような固定長文字列には、目に見える文字列は先頭側から入り「ヌル文字は末尾側に集中」しているため、格納された文字列が削除されるような事は無いはずです。そのため、見かけは「後方のスペース(=ヌル)を削除」してからTRIM関数の処理(先頭部のスペース削除、文字間のスペース集結)を行いますので、図8上では「(〇)」としました。
またNo.1のヌルに対する「VBAのWorksheetFunction.Trim」でも、WorksheetFunctionの名前の通り、ワークシートのTRIM関数と同様の動きとなるようです。つまり、一旦引数に指定した変数値(メモリ上の値)をワークシート上に書き込むような処理(この段階でヌル以降が削除か?)の後で、ワークシートのTRIM関数の処理(半角・全角スペースの処理)をするようです。
このように処理内容はワークシートのTRIM関数に準ずるようなので、TRIM関数と同様に「(〇)」としました。
一方、ヌルに対する「VBAのTrim関数」では、vbNullCharが残ってしまいます。Len関数で文字列の長さを確かめても「vbNullCharの個数」も含めた長さが戻ってきますので、両端(特に右端)のスペースを削除したとは言えないため、「×」としました。
以上ヌルに対し、ワークシートTRIM関数とWorksheetFunction.Trim関数では、処理前にヌルが取れてしまう現象を使っているのでTrim関数の本来の能力では無い感じがします。他の手段として「Replace関数」などを使い、一旦ヌルを「本当のスペース」や「""(長さゼロの文字列)」に変換した後、改めてTrim関数を使用する という方が正しい処理方法かもしれません。
No.3~No.6のHTMLの特殊文字(nbsp、ensp、emsp、thinsp)は、どのTrim関数でも処理対象とはならず、削除や文字間の集結はされません。と言うよりExcelからすると、これらの特殊文字は「普通の文字列」に見えているようです。特殊文字と普通の文字列の間に複数のスペース(半角または全角)が存在すると、1つのスペースに集結する事からも分かります。
ですので、もしサイトからコピペで貼り付けた文字列に対して「特殊文字も含めたスペース」を処理したい場合は、それらの特殊文字を「Replace関数」などで一旦「本当のスペース」や「""(長さゼロの文字列)」に変換した後、Trim関数を使用すると良いと思います。
5.文字間のスペース
文字列間にヌル(vbNullChar)が存在すると「ヌル以降は無視」されますし、また図8のNo.3~No.6のHTMLの特殊文字(nbsp、ensp、emsp、thinsp)は普通の文字列の扱いになりますので、ここでは「半角スペース」と「全角スペース」が文字列の間に存在した場合に絞って説明します。また図1でも説明したように、VBAのTrim関数の機能は「文字間のスペースについては、そのまま」ですので、ワークシートの「TRIM関数」と、VBAの「WorksheetFunction.Trim関数」についてのみが、文字列間のスペース処理となります。
文字間に「半角スペース」と「全角スペース」が混在する組み合わせは、図9の上側のように4種類です(ここではスペースの数を2個としています)。
図9
「TRIM関数」と「WorksheetFunction.Trim関数」には、文字列間のスペースを「1つに集結」する機能があります。
文字列間に「半角スペースが複数」ある場合は、集結して「半角スペースが1つ」になりますし、「全角スペースが複数」ある場合は、集結して「全角スペースが1つ」になります。
問題は、半角スペースと全角スペースが混在していた時ですが、結論としては「文字列間のスペースの内、先頭のスペース1つだけを残して、その後ろ側のスペース(半角スペース、全角スペース)は全て削除」しているようです。絵で表すと図9の下側のようになります。
ですので、文字列間のスペースとして半角・全角が混在している場合には、一旦「Replace関数」などでスペースを統一させてから処理する方が良いと思います。
アプリ実例
「セルの文字を検出して、セル色を自動で変更する」「備品の予約・貸出・記録ができる貸出管理表」
「DVD等の内容・保管場所等管理システム」
「先行予約可能な備品予約・貸出システム」
「共有コメント付きカレンダー(固定長ファイルを使用)」
「固定長ファイルのテキストデータ呼び込み時処理」