🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA の Trim — 空白が消えない理由と Chr(160) の対処法

|

Excel VBA の Trim — 空白が消えない理由と Chr(160) の対処法

検証環境: Excel 365 v2509 · Excel 2021 · Excel 2019 · 最終確認 2026-06-10

要点 — VBA の Trim は文字列の両端の空白を取り除くだけで、それ以外は何もしません。テキストの内側にある連続スペースをまとめることはなく、Web ページや PDF が貼り付ける非改行スペース(Chr(160))も取り除きません。この 2 つ目の事実こそ、「Trim が効かない」が VBA の検索上位の悩みであり続ける理由です。

Sub TrimDemo()
    Dim s As String
    s = "   山田  太郎   "                   ' 両端 + 真ん中に二重スペース

    Debug.Print "[" & Trim(s) & "]"        ' [山田  太郎]  <- 両端は消えるが、内側の二重スペースは残る
    Debug.Print "[" & LTrim(s) & "]"       ' [山田  太郎   ]  左端だけ
    Debug.Print "[" & RTrim(s) & "]"       ' [   山田  太郎]  右端だけ
End Sub

内側の連続スペースも 1 つにまとめたいときは、VBA のキーワードではなくワークシート関数を使います。

Debug.Print Application.WorksheetFunction.Trim("   山田  太郎   ")   ' "山田 太郎"

考え方の軸:Trim は「両端をそろえる」だけ、洗うわけではない

Trim は端をきれいにします。左から非空白に当たるまで進み、右から非空白に当たるまで進み、その間を返す。真ん中はそっくりそのまま残ります。これが動作のすべてで、すべての「想定外」を説明します。

このイメージを持てば、ファミリーは一目で読めます。LTrim は左端だけ、RTrim は右端だけ、Trim は両端。どれも内側には関心がありません。だから問題が「ユーザーが姓名の間に空白を 2 つ打った」なら、Trim は端的に道具ちがいです。内側の連続もまとめてくれる、同名の別関数 WorksheetFunction.Trim を使いましょう。

唯一のルール:VBA の Trim が消すのは ASCII スペース Chr(32) だけ

これが、不可解なバグを 1 行の修正に変えるルールです。

Trim が「消すべき空白」と認識する文字はただ 1 つ、ふつうの ASCII スペース Chr(32) だけです。それ以外の空白に見える文字 — タブ、改行、そして何より非改行スペース Chr(160) — は、Trim にとっては残すべき普通の文字です。

この罠が自然に潜む場所はこうです。Web ページ、HTML メール、PDF から値を Excel にコピーする。見た目は末尾がスペースで終わっている。Trim を実行しても、セルは相変わらず検索に一致せず、1 時間を溶かす。

Dim raw As String
raw = "山田太郎" & Chr(160)               ' 末尾に非改行スペース、Web 貼り付け由来
Debug.Print Len(Trim(raw))               ' 5(4 ではない)— Trim は何も消していない
Debug.Print (Trim(raw) = "山田太郎")       ' False! 値は同じに見えるが一致しない

直し方は「賢い Trim」ではありません。まず Chr(160) を本物のスペースに変えてから Trim することです。

Function CleanText(ByVal s As String) As String
    s = Replace(s, Chr(160), " ")                          ' 非改行スペース -> 通常スペース
    s = Application.WorksheetFunction.Clean(s)             ' 制御文字 Chr(0)-Chr(31) を除去
    CleanText = Application.WorksheetFunction.Trim(s)      ' 内側の連続をまとめ、両端を Trim
End Function

ここで Clean にも触れておきます。エクスポートから紛れ込む印字不能な制御文字(復帰・改行・タブなど 0〜31 の範囲)を取り除きます — ただし Chr(160)取り除きません。160 はその範囲の外だからです。だから実務の整形は、単独の関数ではなく、上の 3 つをこの順で重ねるのが正解です。

第 2 の罠:TrimTrim$

Trim は 2 つあります。素の Trim は Variant 版、Trim$ は String 型の双子です。実務上の違いは 2 つ。

  • Trim$ はわずかに速く、直接 String を返します。数千セルを回すきついループでは効いてきます。
  • Trim$Null でエラーになり、TrimNull を黙ってそのまま通します。Null になりうる Variant(データベースの項目、空の Range.Value)を読むときは、素の Trim が寛容な方です。

私の習慣は、型を自分で握っているループでは Trim$、値が Null になりうる境界では素の Trim。どちらを握っているか分かっていれば、不意の「Null の使い方が不正です」を避けられます。

どれをいつ使うか

やりたいこと 使うもの
先頭末尾の空白を消す Trim(s)
片側だけ LTrim(s) / RTrim(s)
内側の二重スペースもまとめる Application.WorksheetFunction.Trim(s)
印字不能な制御文字を消す Application.WorksheetFunction.Clean(s)
Web/PDF 由来の非改行スペースを潰す Replace(s, Chr(160), " ") の後に Trim
列まるごとを速く整える CleanText 関数 1 つを、セルごとに 1 回

意見:Trim を連ねるな — 境界で一度だけ正規化せよ

いちばんよく見るアンチパターンは、マクロのあちこちに守りで Trim を撒くこと — ここで Trim(rng.Value)、あそこで Trim(parts(i)) — どれかが比較をやっと通してくれるのを期待して。Chr(160) に対しては決して通りません。どの Trim もそれに触れないからです。

テキストの整形は境界の仕事で、行ごとの仕事ではありません。データが汚れて入ってくるのはただ 1 か所 — 取り込み、貼り付け、読み取り — なので、そこで一度だけ、上のような単一の CleanText 関数で整え、以降はそれを信頼します。境界で正規化するマクロは読みやすく正しい。Trim が 40 か所に散ったマクロは、作者が当てずっぽうをしていたマクロです。本物の整形をしても比較がまだ落ちるなら、その差はそもそも空白ではありません — Chr(160)、大文字小文字の不一致(CStr / 型変換 を参照)、あるいは文字列として保存された数値です。

よくある Trim のミス(と直し方)

症状 原因 直し方
値は「Trim 済みに見える」のに一致しない Web/PDF 貼り付け由来の末尾 Chr(160) Trim の前に Replace(s, Chr(160), " ")
内側の二重スペースが残る 端しか処理しない Trim を使った WorksheetFunction.Trim(s)
改行・タブが生き残る それらは空白ではなく制御文字 まず WorksheetFunction.Clean(s)
ループで「Null の使い方が不正です」 Trim$Null の Variant に当たった 素の Trim、または先に IsNull を判定
セルに対し Trim が何もしないように見える その空白は実は Chr(160)Chr(9) Asc(Right(s,1)) で実際のコードを確認
Trim 後も列全体が不一致のまま 整形が散在し、取り込み時に行われていない 読み取り境界で CleanText を 1 回呼ぶ

整形が目的を上回ったら — 代わりに「やりたいこと」を伝える

あなたは空白を研究したかったわけではありません。今週のエクスポートをマスター一覧と突き合わせたかっただけなのに、半分が Chr(160) に包まれて届いたせいで名前がそろわない。整形関数を書き、列を回し、それでも一致しない 1 行を追ううちに、配管仕事が午後を食い尽くす。ExcelMaster Agent なら、自然な日本語で目的をそのまま言えます — 「B 列の空白と隠れ文字をきれいにして、マスターシートと突き合わせて」 — すると Chr(160)・制御文字・大文字小文字まで面倒を見る Python を、ブックを先にバックアップしたうえで書き出します。無料で試す →

関連ガイド

よくある質問

VBA の Trim が効かないのはなぜ? ほとんどの場合、その「スペース」がスペースではないからです。Trim が消すのは ASCII スペース Chr(32) だけ。Web ページ・HTML メール・PDF から貼ったテキストは、末尾が非改行スペース Chr(160) で終わっていることが多く、Trim はそれを残します。先に置き換えましょう:Trim(Replace(s, Chr(160), " "))

VBA Trim は文字列内側の二重スペースを消す? いいえ。VBA のキーワード Trim は両端の空白しか消しません。内側の連続を 1 つのスペースにまとめるには、ワークシート関数 Application.WorksheetFunction.Trim(s) を使います。

VBA の Trim と Trim$ の違いは? TrimVariant を返し Null をそのまま通します。Trim$ は直接 String を返し、わずかに速く、Null でエラーになります。型が分かっているきついループでは Trim$、値が Null になりうる場所では素の Trim を使いましょう。

VBA で非改行スペース(Chr 160)を消すには? 通常のスペースに置き換えてから Trim します:Application.WorksheetFunction.Trim(Replace(s, Chr(160), " "))。同じパスで改行やタブなどの制御文字も消すなら WorksheetFunction.Clean(s) を足します。

VBA Clean は何をする? Trim と同じ? いいえ。Clean は印字不能な制御文字(0〜31、改行やタブなど)を消し、Trim は空白を消します。別々の問題を解くもので、よく併用します。なお CleanChr(160) を消しません。160 は制御文字の範囲外だからです。