次の DEMO を見にいく
Excel

VBAで文字列に改行があるか簡単に調べる方法

k.w
\お買い物マラソン開催中/
スポンサーリンク

InStr関数で文字列内を検索

InStrは、文字列の中から「探したい文字」や「部分文字列」を見つける関数です。見つかった位置(1から数える)を返します。見つからない場合は0になります。戻り値が0より大きければ「含まれている」と判断できます。

VBAでは、改行を表す特別な文字があります。この記事ではCRLFCRLFという3種類の改行コードを扱います。InStrでこれらを順番に探すことで、改行が入っているかどうかを簡単に確かめられます。

InStrの主な引数は「開始位置」「検索対象(文字列)」「検索する文字」「比較方法」です。比較方法はvbBinaryCompare(バイナリ比較)とvbTextCompare(テキスト比較)があります。改行コードの検出では、大文字小文字の違いは関係しないため、どちらでも結果は同じになります。

InStr関数による改行コードの検索

最短での判定は、InStrでvbCrLfvbCrvbLfの順に探す方法です。vbCrLf(2文字)を先に探すと、CRLFCR/LFの区別がしやすくなります。

  • 例(概念):
    • 1行目:pos = InStr(1, s, vbCrLf)
    • 2行目:If pos = 0 Then pos = InStr(1, s, vbCr)
    • 3行目:If pos = 0 Then pos = InStr(1, s, vbLf)
    • 4行目:含まれていれば pos > 0

InStrは先頭からの位置を返すため、最初の改行の場所も同時に分かります。必要に応じて、2回目以降の改行を探したい場合は、見つかった位置の次から再度InStrを呼び出します。

ミニQA:InStrで大文字小文字やバイナリ比較は?

  • Q. 比較方法はどちらを使えばよいですか?
  • A. 改行コードは制御文字なので、vbBinaryCompareでもvbTextCompareでも結果は同じです。既定値のままでも問題になりにくいです。
  • Q. 先頭や末尾の改行も見つかりますか?
  • A. 見つかります。InStrは文字列全体を対象にします。
  • Q. 改行が複数ある場合は?
  • A. 最初の位置が返ります。次を探すときは、その位置+1から再検索します。

3種類の改行コード(CR/LF/CRLF)

改行コードには大きく3種類あります。歴史的な経緯でOSごとに慣習が異なります。VBAでは定数が用意されているため、記号やエスケープ表現を覚えなくても扱えます。

  • CR(キャリッジリターン):復帰。タイプライターで行頭に戻る動きに相当
  • LF(ラインフィード):改行。次の行に送る動きに相当
  • CRLFCRLFを続けた2文字の改行

以下の表に、代表OSやVBA定数、エスケープ記法をまとめます。

コード名称代表OS/慣習VBA定数文字列表現例
CR復帰旧Mac OSなどVbCr\r
LFラインフィードUnix/Linux、現行の多くのツールVbLf\n
CRLFCR+LFWindows系の多くのツールVbCrLf\r\n

混在データも珍しくありません。ファイルを別ツールで編集した、コピー&貼り付けで持ち込んだ、などの理由で、1つの文字列に複数の改行コードが入ることがあります。

ミニQA:改行コードは混在する?対処は?

  • Q. 1つの文字列にCRとLFが混在することはありますか?
  • A. あります。異なる環境から持ち込まれたデータで起こります。
  • Q. どう扱えばよいですか?
  • A. まず種類を把握してから、必要に応じて1種類にそろえます(正規化)。そろえる際は後述の順序に注意します。

改行コードの判定

目的に応じて、次の2段階に分けると整理しやすくなります。

1. 「改行があるか」を判定(有無)
2. 「どの種類か」を判定(種類)

ここではどちらも、コピーしてすぐ使える最小の関数として示します。

改行コードの有無を判定する関数

以下は、文字列sに1つでも改行があればTrueを返す関数の例です。CRLF→CR→LFの順で探します。

  • 関数の全体(行ごと):
    • Function HasNewline(ByVal s As String) As Boolean
    • HasNewline = (InStr(1, s, vbCrLf) > 0) Or _
    • (InStr(1, s, vbCr) > 0) Or _
    • (InStr(1, s, vbLf) > 0)
    • End Function

使い方は、If HasNewline(text) Then ...のように呼び出します。戻り値がTrueなら改行を含みます。

改行コードの種類を判定する関数

最初にCRLFを探し、次にCR、最後にLFを探すと、2文字の改行を正しく見分けられます。戻り値は文字列にすると扱いやすいです。

  • 関数の全体(行ごと):
    • Function NewlineKind(ByVal s As String) As String
    • If InStr(1, s, vbCrLf) > 0 Then
    • NewlineKind = "CRLF"
    • ElseIf InStr(1, s, vbCr) > 0 Then
    • NewlineKind = "CR"
    • ElseIf InStr(1, s, vbLf) > 0 Then
    • NewlineKind = "LF"
    • Else
    • NewlineKind = "None"
    • End If
    • End Function

種類が分かれば、後続の処理(正規化や分割)に使えます。複数の種類が混在する場合は、先にCRLFを検知してから、残りを追加で検査します。

ミニQA:長文・大量データでのパフォーマンスは?

  • Q. 何万文字もの長文でも大丈夫ですか?
  • A. InStrは軽量です。数回の呼び出しなら多くのケースで問題になりにくいです。大量のループ処理では、1回の走査で複数条件を判定する方法も検討してください。
  • Q. 複数行を分割する最短の方法は?
  • A. 種類を問わず分割したい場合は、いったんCRLFLFの順に統一(正規化)してからSplitを使うと実装が簡単です。
  • Q. 文字コードの違いは影響しますか?
  • A. 影響することがあります。テキストの読み込み時に文字化けがあると、改行が期待どおりに入らない場合があります。

使用例

ここでは、実務でありがちな3つの場面を例に、関数の使い方を示します。

1. シート入力の検証:セル内に改行が含まれるかチェックして、含まれていれば注意表示

2. CSV取込前の確認:取り込み対象の行に改行が混在していないかを事前に検査

3. ログ整形:外部ログを1種類の改行にそろえてから行単位に分割

  • 例1:セル内の改行を検出してフラグを立てる(概念)
    • Dim s As String: s = Range("A2").Value
    • If HasNewline(s) Then Range("B2").Value = "改行あり"
  • 例2:CSV文字列の改行を統一してから分割する(概念)
    • Dim s As String: s = ReadAllText(path)
    • s = Replace(s, vbCrLf, vbLf)
    • s = Replace(s, vbCr, vbLf)
    • Dim lines() As String: lines = Split(s, vbLf)
  • 例3:種類に応じて処理を変える(概念)
    • Select Case NewlineKind(s)
    • Case "CRLF": ' Windows系の扱い
    • Case "CR": ' 旧Mac系の扱い
    • Case "LF": ' Unix系の扱い
    • Case Else: ' 改行なし
    • End Select

フォーム入力やユーザーファイルの取り込みでは、改行を禁止したい項目もあります。その場合は、最初にHasNewlineで弾くのが簡単です。許可する場合でも、改行が複数の種類で混ざると後工程が複雑になります。早い段階で正規化する方針が管理しやすくなります。

ミニQA:Worksheet関数やフォーム入力と組み合わせできる?

  • Q. データ検証の入力規則だけで防げますか?
  • A. セル内改行はAlt+Enterで入力できるため、完全には防げません。VBA側のチェックと併用すると確実です。
  • Q. ユーザーフォームのTextBoxで改行を禁止できますか?
  • A. EnterKeyBehaviorMultiLineの設定で制御できます。禁止したい場合は単一行にします。
  • Q. 既存データの改行を一括で整える方法は?
  • A. 読み込み時にReplacevbCrLfvbLfの順に置換し、最後にSplitで分割するのが分かりやすいです。

LFだけのチェックは危険

LFだけを探すコードは、一見シンプルですが、CRLFを見落とす可能性があります。例えば、InStr(s, vbLf) > 0だけを条件にすると、CRLFのケースでもTrueになります。CR単独の改行は見落としになります。安全に判定するには、2文字のCRLFを先に検出し、その後にCRLFを個別に見る順序が大切です。

また、改行の正規化で順序を誤ると、CRLFが二重に置換されることがあります。次の順番であれば安全です。

1. 先にCRLFLFへ置換

2. 次にCRLFへ置換

この順序なら、CRLFの中のCRだけが先に置換される、といった中途半端な状態を避けられます。

ミニQA:混在検知や正規化の安全な順番は?

  • Q. 混在を検知するには?
  • A. まずCRLFの位置を探し、見つかったらフラグを立てます。次にCR、最後にLFを探します。複数の種類が見つかったら「混在あり」と判断できます。
  • Q. 正規化はどの順番が安全?
  • A. CRLFLFの順に置換し、その後CRLFに置換します。これで二重置換のリスクを避けられます。
  • Q. 置換後に空行が増えることはありますか?
  • A. あります。空行の扱いは要件に合わせて別途調整してください。

まとめ

InStrを使えば、短いコードで改行の有無を判定できます。さらに、CRLF→CR→LFの順に探せば、種類の判定も安全に行えます。実務では、読み込み直後や入力直後の段階で、関数を使ってチェックするのが管理しやすいです。混在がある場合は、順序を守って正規化してから分割や解析を行うと、後工程の不具合を減らせます。

最小の持ち物としては、HasNewlineNewlineKindの2つの関数を用意しておくと便利です。どちらもInStrだけで完結し、依存がありません。必要に応じて、正規化用のReplace処理を組み合わせて使ってください。

ミニQA:よくある誤判定と確認手順は?

  • Q. LFのみを探してCRLFを見落としていました。どう直す?
  • A. 先にCRLFを探し、その後でCRLFを探す手順に変えます。
  • Q. 文字化けで改行が消えたように見えます。
  • A. 文字コードの違いが原因の可能性があります。読み込み方法と保存形式を確認します。
  • Q. vbCrvbLfの直書きはできますか?
  • A. Chr$(13)Chr$(10)でも表現できますが、読みやすさの面でVBA定数の使用が無難です。
スポンサーリンク
記事URLをコピーしました