テキストからある文字列を検索し、それより左側を取得するコードを解説します。
捉え方が違うだけで同じことなので、ある文字列から右側を削除するとも言えますね。
基本の書き方
ある文字列より左側の部分 = Left(元の文字列, InStr(元の文字列, 検索文字列) - 1)
実行サンプル
商品名 = "愛媛産みかん" 産地 = Left(商品名, InStr(商品名, "産") - 1) MsgBox 産地 ' ← 「愛媛」が表示されます。
解説
「左から文字列が見つかるまで」という日本語そのままに、
Instr関数で文字列の位置を調べてその1文字手前までを取得しています。
ただし、このコードのままではもし文字列が含まれなかった場合にLeft関数に「-1」が渡ってエラーで止まってしまいますので、
If InStr(商品名, "産") > 0 Then 産地 = Left(商品名, InStr(商品名, "産") - 1) Else 産地 = "" End If
このように、Instr関数の結果が0でないかをIf文で分岐して回避します。
If文を使うとコード中に同じInstr関数が2回出てきてしまいますが、
2回出てくるのが読みづらいと感じる場合は、
Dim 産の位置 As Long 産の位置 = InStr(商品名, "産") If 産の位置 >= 0 Then 産地 = Left(商品名, 産の位置 - 1) Else 産地 = "" End If
と、変数に格納すると読みやすくなります。
検索する文字列も結果に含めたい場合
検索文字列を結果に含める場合は、まずそれが1文字の場合は
ある文字含めた左側部分 = Left(元の文字列, InStr(元の文字列, 検索文字))
と、「最後の-1を消す」だけでOKです。
検索文字列が2文字以上の場合は、
ある文字含めた左側部分 = Left(元の文字列 _ , InStr(元の文字列, 検索文字列) - 1 +Len(検索文字列))
と、Left関数で取ってくる文字数に「検索文字列の長さ」を足します。
ただ、こういった計算はわかりにくく計算間違いが怖いので、
ある文字含めた左側部分 = Left(元の文字列 _ , InStr(元の文字列, 検索文字列) - 1) & 検索文字列
と、検索文字列を&を使って後ろにくっつけた方が楽かもしれません。
お好きな方をお使いください。
Split関数を使う
ここまでは「ある文字列を検索して、その位置をもとに文字列を加工する」という、
文字列操作の基本に忠実なコードを解説しました。
Left・Right・Mid + Instrの書き方は必修項目ですので、
まずはこれをマスターしましょう。
さてマスターしたうえで、実はこの処理はもっと簡単なコードで書けます。
それがこれ↓
ある文字列より左側の部分 = Split(元の文字列, 検索文字列)(0) MsgBox Split("愛媛産みかん","産")(0) ' ← 「愛媛」が表示されます。
Split関数で元の文字列を検索する文字で分割し、その初項をとってくることでも、
目的の処理は果たせます。
Split関数は配列を返す関数ですので、丁寧にコードを書いた場合は
商品名 = "愛媛産みかん" Dim 配列 配列 = Split(商品名, "産") ' この時点で「配列」は、第0項に「愛媛」、第1項に「みかん」が入っている 産地 = 配列(0)
こうなるのですが、Splitが返す配列を変数に入れずに直接参照すれば、
産地 = Split(商品名,"産")(0)
と、Split(~~)(0)のように書いてしまえるということです。
Split関数を「カンマとかコロンとかの区切り記号に使うもの」と考えていた人は、
「普通の文字列の検索にも使えるもの」と視野を広げてみましょう。
Split関数は「包丁でぶつ切り」するイメージが強いかもしれませんが、
「刀で真っ二つ」にするのにも非常に便利な関数です。
ただし、区切り文字がなかったときには元の文字列が全部返ってきてしまいます。
それを配列の状態で判定しようとすると、
If Ubound(Split(商品名, "産")) > 0 Then 産地 = Split(商品名,"産")(0)
と、作られた配列の要素数が1個かどうか(=配列の添字の上限UBoundが0かどうか)で判定する必要がありますが、
こんな判定するくらいなら、
If InStr(商品名, "産") > 0 Then 産地 = Split(商品名,"産")(0)
と、Splitを使うかどうかの判定は結局Instrでやる方が読みやすくて綺麗です。
ということで、文字列操作の基本はやっぱりInstr関数だと思いますので、
基本の型としてInstrをマスターし、実践技としてSplitを身につけ、
どちらもしっかり扱えるようになっておきましょう。
おまけ:文字列処理は関数化しておくと便利
文字列を操作するコード全般に言えることなのですが、
式中に「元の文字列」が何度も登場するため、コードが汚くなりやすいです。
例えば「Cells(R + i, C)」セルの"("より右を消したいときは、
Cells(R + i, C) = Left(Cells(R + i, C), InStr(Cells(R + i, C), "(") - 1)
みたいになって、ぱっと見なにやってるか分からないコードになりますし、
さらには"("がなかったとき用のIf文まで書くとなると面倒ですよね。
ということで、文字列処理を多くやる人は、↓のように汎用関数を作ってみましょう。
' 目的:汎用関数を作って↑のコードをこう書けるようにしたい Cells(R + i, C) = 左から文字列まで(Cells(R + i, C), "(") ' 用意する汎用関数 Function 左から文字列まで(ByVal 元の文字列 As String, 検索文字列 As String) As String Dim instr位置 As Long instr位置 = InStr(元の文字列, 検索文字列) If instr位置 > 0 Then 左から文字列まで = Left(元の文字列, instr位置 - 1) Else 左から文字列まで = "" End If End Function ' 使用例 MsgBox 左から文字列まで("和歌山産みかん", "産") ' ←和歌山が表示されます。
劇的に読みやすくなっていますよね?
一度作ってしまえばあとは使いまわすことができますし、
何なら自分で作らなくても、これをコピペしても動きます。
私と共同開発したつもりになって、持って帰って使ってみてください。
関数と聞くと難しく感じるかもしれませんが、コードを見ればわかる通り、
中身は上で紹介したコードそのままです。
文字列操作は関数化が楽ちんで、その割に関数化の効果が大きいので、
関数づくりの練習にぴったりだと思います。
Functionプロシージャ勉強してみたいけど難しそうだな~って思っている方は、
ちょうどいいのでこの機会に始めて見るといいかもしれません。
今回の「指定文字列より左側を取り出す」や、
他には「文字から文字までを取ってくる(例えばカッコの中身)」など、
私が作成した文字列操作の汎用関数集が下記のページにあります。
関数作成の参考にするなり、中身を見ないでコピーして使うなり、
ご自由にお持ち帰りください。