文字列の特定位置から数文字を取得する【Mid関数】
説明
Mid関数とは?
Mid関数は、文字列の途中もしくは1文字目から指定した数の文字列を返します。
例えば「1234567」を(左から)3文字目から4文字取得して「3456」を取り出す処理をします。
抽出する文字列の開始位置が、文字列の長さを超えている時は、ブランクが返ります。
(例:「1234567」の10文字目から3文字を抽出 → 「」(ブランク)を抽出)
抽出する文字数が、取得開始位置以降の文字数以上の時、文字列全てが返ります。
(例:「1234567」の4文字目から10文字を抽出 → 「4567」を抽出)
特殊なケースですが、「Null」の場合は、Nullが返ります。
Mid関数の構文と引数一覧
Mid関数の構文と引数一覧です。
Mid関数の構文
Mid(string, start, [length])
Mid関数の引数一覧
引数 | 省略 | 説明 |
---|---|---|
string | 不可 | 文字列を返す元となる文字列。 |
start | 不可 | string 内で抽出する文字列の先頭の位置を指定。 |
length | 可能 | 返す文字数を入力。 省略した場合、start以降の文字列を全て返す。 |
一部、Microsoft社のリファレンス【Mid関数】を参照しています。
【Microsoft公式】
キーワード (Visual Basic for Applications) | Microsoft Learn
使用サンプル
文字列の2番目から1文字を抽出する
本ページの主役「Mid関数」を使用します。
Sub SampleMid1()
'B と表示される
MsgBox Mid("ABCDEF", 2, 1)
End Sub
文字列の3番目以降の全ての文字を抽出する
第三引数を省略すると開始位置以降の全ての文字列をすべて返す仕様を使います。
なお、第三引数を第一引数の文字数で指定しても同様になります。
Sub SampleMid2()
Dim str As String
Dim startPos As Long '取得開始位置
str = "ABCDEF"
startPos = 3
'CDEF と表示される。「Mid(str, startPos, Len(str)) 」でも可
MsgBox Mid(str, startPos)
End Sub
電話番号の市外局番、市内局番、加入者番号を分けて取得する
"-"の位置を取得するため、InStr関数を使用します。
電話番号は「市外局番-市内局番-加入者番号」で構成されており、市外局番は2桁~5桁、加入者番号は『原則』4文字らしいです。
Sub SampleMid3()
Dim telNumber As String '電話番号
Dim areaCode As String '市外局番
Dim localCode As String '市内局番
Dim userCode As String '加入者番号
Dim sepPos1 As Long '1回目の"-"の位置
Dim sepPos2 As Long '2回目の"-"の位置
telNumber = "00-1122-3344"
'市外局番と市内局番を分ける"-"の位置の取得
sepPos1 = InStr(telNumber, "-")
'市内局番と加入者番号を分ける"-"の位置の取得
sepPos2 = InStr(sepPos1 + 1, telNumber, "-")
'市外局番を抽出
areaCode = Mid(telNumber, 1, sepPos1 - 1)
'市内局番を抽出
localCode = Mid(telNumber, sepPos1 + 1, sepPos2 - sepPos1 - 1)
'加入者番号を抽出(第3引数は「100」でも可能)
userCode = Mid(telNumber, sepPos2 + 1, Len(telNumber))
MsgBox "市外局番:" & areaCode & vbNewLine & _
"市内局番:" & localCode & vbNewLine & _
"加入者番号:" & userCode
End Sub
ファイルパスからパスとファイル名を別に抽出する
ディレクトリ区切りの文字は"¥"と"/"の2種類あるため、Replace関数を使用して"¥"で統一します。
ファイル名とパスを区切る"\"(最後の"\")の位置を取得するため、InStrRev関数を使用しています。
Sub SampleMid4()
Dim fullPath As String
Dim filePath As String
Dim fileName As String
Dim sepPos As Long
fullPath = "C:\Users\Yamada\Desktop\abc.txt"
'"/" でもディレクトリ指定ができるため、"\"で統一
fullPath = Replace(fullPath, "/", "\")
'パスとファイル名の区切りの"\"の位置を取得
sepPos = InStrRev(fullPath, "\")
'パスのみを抽出する
filePath = Mid(fullPath, 1, sepPos - 1)
'ファイル名のみを抽出する
fileName = Mid(fullPath, sepPos + 1)
MsgBox "ファイルパス:" & fullPath & vbNewLine & _
"パスのみ:" & filePath & vbNewLine & _
"ファイル名のみ:" & fileName
End Sub
【リンク】
ファイルパスから拡張子名を除いたファイル名を抽出する
ディレクトリ区切りの文字は"¥"と"/"の2種類あるため、Replace関数を使用して"¥"で統一します。
ファイル名とパスを区切る"\"(最後の"\")の位置を取得するため、InStrRev関数を使用しています。
Sub SampleMid5()
Dim fullPath As String 'フルパス
Dim fileName As String 'ファイル名
Dim sepPos1 As Long 'ファイル名の"\"の位置
Dim sepPos2 As Long '拡張子の"."の位置
'筆者はヤマダではありません。
fullPath = "C:\Users\Yamada\Desktop\abc.txt"
' "/" でもディレクトリ指定ができるため、"\"で統一
fullPath = Replace(fullPath, "/", "\")
'ファイル名の"\"の位置を取得する
sepPos1 = InStrRev(fullPath, "\")
'ファイル名の"."の位置を取得する
sepPos2 = InStrRev(fullPath, ".")
'拡張子を除いたファイル名が抽出される
fileName = Mid(fullPath, sepPos1 + 1, sepPos2 - sepPos1 - 1)
'abc と表示される
MsgBox fileName
End Sub
【リンク】
処理速度を早くする方法
Mid関数はバリアント型 (内部処理形式 String の Variant)を返します。
関数名 Mid に $ を付けることで、戻り値の型がString型になり、処理速度がわずかに速くなります。
主に大量のデータ処理で違いが出ます。
Mid$(string, start, length)
使用サンプルです。
Sub SampleMidOther1()
MsgBox Mid$("ABCDEF", 2, 4)
End Sub
第一引数がNullの場合
第一引数がNullの場合はNullを返します。
Variant型以外は、Nullを格納できず「実行時エラー94」が発生します。
Nullになりえる場合は受け取る変数の型をVariantにして、Nullが返ってきていないかチェックを行いましょう。
Sub SampleMidNull()
Dim val As Variant
val = "abc"
If Not IsNull(val) Then
MsgBox Mid(val, 2, 2)
Else
MsgBox "valがNullです"
End If
End Sub
【エラー】Mid関数を使用した時の「実行時エラー5」について
第二引数が0以下の時や、第三引数が0未満の時にエラーとなります。
このエラーは次のように表示されます。
実行時エラー '5'
プロシージャの呼び出し、または引数が不正です。
Instr関数は、検索した文字が文字列に無かった場合に「0」が返ってきます。
先の「SampleMid3」では、電話番号の市内局番を抽出するために "-" の位置を検出しました。これは "-" が必ずある前提でのプログラムです。もし "-" が無かった場合、次のプログラムのようにエラーが発生します。
Sub SampleMidError1()
Dim telNumber As String '電話番号
Dim areaCode As String '市外局番
Dim localCode As String '市内局番
Dim userCode As String '加入者番号
Dim sepPos1 As Long '1回目の"-"の位置
Dim sepPos2 As Long '2回目の"-"の位置
telNumber = "0011223344" '← 検索文字 "-" が無い
' "-" がないので、Instr関数の仕様により「0」が返ってきている
sepPos1 = InStr(telNumber, "-") '←エラーの原因①
' "-" がないので、Instr関数の仕様により「0」が返ってきている
sepPos2 = InStr(sepPos1 + 1, telNumber, "-") '←エラーの原因②
'第三引数が、"-1" のため、エラーが発生する
areaCode = Mid(telNumber, 1, sepPos1 - 1) '← ここでエラーが発生する
localCode = Mid(telNumber, sepPos1 + 1, sepPos2 - sepPos1 - 1)
userCode = Mid(telNumber, sepPos2 + 1, Len(telNumber))
MsgBox "市外局番:" & areaCode & vbNewLine & _
"市内局番:" & localCode & vbNewLine & _
"加入者番号:" & userCode
End Sub
改善案です。
Mid関数を安全に使用する場合は、Istr関数の戻り値が 0 でないかを確認しましょう。
Sub SampleMidError1_2()
Dim telNumber As String '電話番号
Dim areaCode As String '市外局番
Dim localCode As String '市内局番
Dim userCode As String '加入者番号
Dim sepPos1 As Long '1回目の"-"の位置
Dim sepPos2 As Long '2回目の"-"の位置
Dim existbl1 As Boolean '1回目の"-"の有無
Dim existbl2 As Boolean '2回目の"-"の有無
telNumber = "0011223344" '← 検索文字 "-" が無い
' "-" がないと、「0」が返る
sepPos1 = InStr(telNumber, "-")
' "-" がないと、「0」が返る
sepPos2 = InStr(sepPos1 + 1, telNumber, "-")
existbl1 = Not (sepPos1 = 0) '"-" があるとき、True
existbl2 = Not (sepPos2 = 0) '"-" があるとき、True
' "-" が2つあるときにTrueとなる
If (existbl1 And existbl2) Then
areaCode = Mid(telNumber, 1, sepPos1 - 1)
localCode = Mid(telNumber, sepPos1 + 1, sepPos2 - sepPos1 - 1)
userCode = Mid(telNumber, sepPos2 + 1, Len(telNumber))
MsgBox "市外局番:" & areaCode & vbNewLine & _
"市内局番:" & localCode & vbNewLine & _
"加入者番号:" & userCode
ElseIf existbl1 Then
MsgBox """-""" & " が1つしか無いため、市内局番が分かりません。"
Else
MsgBox """-""" & " が1つも無いため、市内局番が分かりません。"
End If
End Sub