とりあえずUnicodeのことは忘れて、次の例を考えます。
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|
あ | イ | う | エ | お |
この場合、たとえばMidh(str, a, b)
のような関数を作ったとしてMidh("あイうエお", 5, 3)
としたとき、「う」はどう扱ったらいいでしょうか?
半角を1、全角を2とカウントするようなMidのような関数は現実的ではないでしょう
このようなことをする場合は、すべての文字をひとくくりに考える必要があります
半角を含む文字列を処理する関数「splith()」
Function splith(str As String, n As Long) As String()
'//ANSI(半角1バイト、全角2バイト)を利用してnカウント以内で分割した文字列の配列を返す関数
Dim strBase As String, strAnsi As String, str1 As String, str2 As String, strLeft As String
Dim sCount As Long
Dim strSplit() As String
strBase = str
Do Until strBase = ""
ReDim Preserve strSplit(sCount)
strAnsi = strConv(strBase, vbFromUnicode)
'//合計nカウント以内だったらそのまま取り出して終わり
If LenB(strAnsi) <= n Then
strSplit(sCount) = strBase
Exit Do
End If
'//nカウント目の文字をチェックして2バイト文字なら切り捨てる
str1 = strConv(LeftB(strAnsi, n), vbUnicode)
str2 = strConv(LeftB(strAnsi, n + 1), vbUnicode)
If Len(str1) = Len(str2) Then
'//2バイト文字から1バイト取り出したら文字数は1(文字は化けるが文字数は1)
'//余分に1バイト取り出しても正常な文字として文字数は1で、全体の文字数は変わらない
'//nカウント目の文字が2バイト文字の前半1バイトだったので1バイト減らす
strLeft = strConv(LeftB(strAnsi, n - 1), vbUnicode)
Else
'//余分に1バイト取り出して文字数が変わったらnカウントでちょうど文字の区切りだった
strLeft = str1
End If
'//取り出した文字を配列に保存
strSplit(sCount) = strLeft
'//取り出した文字分だけ元の文字を取り除く
strBase = Mid(strBase, Len(strLeft) + 1)
'//配列の次の要素の準備
sCount = sCount + 1
Loop
splith = strSplit()
End Function
テストコード
Private Sub コマンド0_Click()
Dim strBase As String
Dim strSplit() As String
Dim sCount As Long
strBase = Me!テキスト
If strBase = "" Then Exit Sub
If strBase <> strConv(strConv(strBase, vbFromUnicode), vbUnicode) Then
MsgBox "非対応の文字が見つかりました。処理を中断します"
Exit Sub
End If
strBase = strConv(strBase, vbNarrow)
strSplit() = splith(strBase, 20)
For sCount = 0 To UBound(strSplit)
Debug.Print strSplit(sCount)
Next
End Sub
出力結果
このページの下の「新し
いトピックを作る」ボタンを
クリックして質問を入力し
てください。あるいは
下記のリンクをクリックして
ください。
通報 ...
大変悩んでいたので本当に助かります。
じっくり内容を確認し、勉強させていただきます!!本当にうれしいです。
ありがとうございます。