'******************************************************
' 全角を半角に変換
'******************************************************
Function ZenToHan(str As String) As String
Dim i As Integer
Dim result As String
result = ""
For i = 1 To Len(str)
Dim charCode As Integer
charCode = AscW(Mid(str, i, 1)) ' [AscW] : Unicode数値をわかる関数
' 全角文字の範囲 : [&HFF01] ‐ [&HFF5E]
If charCode >= &HFF01 And charCode <= &HFF5E Then
' <全角の範囲にあったら、半角に変える処理をする>
result = result & ChrW(charCode - &HFF00 + &H20)
' [charCode - &HFF00] :
' 全角文字のUnicodeコード値から[&HFF00]を引いた値。半角文字のUnicodeコード値との差。
' → [&H20]を加える : 差を補正し、半角文字のUnicodeコード値を得ます。
' → [ChrW] : Unicodeコード値を文字に変換し、結果文字列に追加します。
Else
' <全角の範囲にないと、何の処理もしない。>
result = result & Mid(str, i, 1)
End If
Next i
ZenToHan = result
End Function
If charCode >= &HFF01 And charCode <= &HFF5E Then
' 로직 작성 (전각의 범위)
Else
' 로직작성 (전각 범위 이외)
End If
If currentChar Like "[0-9A-Za-zア-ンヲ-ン゙゚]" Then
' 로직 작성 (반각의 범위)
Else
' 로직작성 (반각 범위 이외)
End If
[&HFF01] ‐ [&HFF5E]
와 같은 로직으로는 비쥬얼 베이직의 텍스트 박스에서 전각과 반각을 구분해서 카운팅하고 몇 가지 조건에 따른 스크롤바를 추가, 혹은 버튼의 활성화 등의 기능을 구현할 수 없었다.만약 문자열이 UTF-8 또는 다른 인코딩으로 인코딩되어 있다면, 직접적인 유니코드 코드 포인트 비교로는 제대로 작동하지 않을 수도 있다.
Function countChars(text As String) As Integer()
Dim zenkakuCnt As Integer
Dim hankakuCnt As Integer
zenkakuCnt = 0
hankakuCnt = 0
'''' 작동하지 않음 (전체적으로 문제)
For i As Integer = 1 To Len(text)
'If AscW(Mid(text, i, 1)) >= &HFF01 And AscW(Mid(text, i, 1)) <= &HFF5E Then
' zenkakuCnt += 1
'Else
' hankakuCnt += 1
'End If
Next
'''' 작동하지 않음 (잘 되는 줄 알았는데 가타카나를 반각으로 인식)
For i As Integer = 1 To Len(text)
'Dim currChar As String
'currChar = Mid(text, i, 1)
'''If currChar Like "[0-9A-Za-zア-ンヲ-ン゙゚]" Then
'If currChar Like "[0-9A-Za-zア-ン¥HFF65-\HFF9F]" Then
' hankakuCnt += 1
'Else
' zenkakuCnt += 1
'End If
Next
'''' 작동함 (IsZenkaku 불린 함수를 이용)
For i As Integer = 1 To Len(text)
Dim currChar As String
Dim isZen As Boolean
currChar = Mid(text, i, 1)
isZen = IsZenkaku(currChar)
If isZen Then
zenkakuCnt += 1
Else
hankakuCnt += 1
End If
Next
Dim result(0 To 1) As Integer
result(0) = zenkakuCnt
result(1) = hankakuCnt
countChars = result
End Function
''' 작동하는 로직
Function IsZenkaku(oneChar As String) As Boolean
Dim charCode As Integer
oneChar = Mid(oneChar, 1, 1)
charCode = AscW(oneChar)
If (charCode >= &HFF61 And charCode <= &HFF9F) Or
(charCode >= &H3040 And charCode <= &H309F) Or
(charCode >= &H30A0 And charCode <= &H30FF) Or
(charCode >= &HFF00 And charCode <= &HFFEF) Then
IsZenkaku = True ' 전각
Else
IsZenkaku = False ' 반각
End If
End Function
- (charCode >= &HFF61 And charCode <= &HFF9F): 전각 가타카나의 유니코드 범위
- (charCode >= &H3040 And charCode <= &H309F): 히라가나의 유니코드 범위
- (charCode >= &H30A0 And charCode <= &H30FF): 가타카나의 유니코드 범위
- (charCode >= &HFF00 And charCode <= &HFFEF): 특수문자의 유니코드 범위
- 그냥 바이트 수가 1보다 크면 전각이라고 계산하면 안 됨? 이라는 생각에 다다름. 너무 귀찮다.
- 그렇다면 내장함수의 힘을 빌려 구현 가능.
- 결국 지금 전각 반각을 구분하는 이유는 데이터 베이스에 자료가 어떻게 들어갈지 체크하기 위해서니까.
![]()
- 개행을 두 개의 반각이라고 인식했다는 가정 하에, 지금까지 중 가장 완벽하게 작동하는 코드였다.
Sub Button7_Click(sender As Object, E As EventArgs) Handles Button7.Click
Dim dialogPopupStr As String = ""
Dim result(0 To 1) As Integer
Dim totalLen As Long = 0
Dim zenLen As Integer = 0
Dim hanLen As Integer = 0
result = countChars(Me.txtBox.Text)
MessageBox.Show("全角:" & result(0) & " / 半角 : " & result(1) & vbCrLf & "bytes : " & Me.getByteCnt(Me.txtBox.Text))
zenLen = result(0)
hanLen = result(1)
'totalLen = (zenLen * 2) + hanLen
totalLen = Me.getByteCnt(Me.txtBox.Text)
'dialogPopupStr += "300字以内で作成してください。" & vbCrLf & "全角:" & zenLen & " 字" & vbCrLf & "半角:" & hanLen & " 字
'
dialogPopupStr += "600バイト以内で作成してください。(現在:" & totalLen & " bytes)" & vbCrLf & "【全角(2バイト)/半角)(1バイト)】" & vbCrLf & "全角:" & result(0) & " 字" & vbCrLf & "半角:" & result(1) & " 字"
If totalLen > 599 Then
Dim dialogPopup As DialogResult = MessageBox.Show(dialogPopupStr,
"確認",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Exclamation,
MessageBoxDefaultButton.Button2)
End If
End Sub
Sub textBox_Change() Handles txtBox.TextChanged
'文字が599字以上になるとスクロールバー
makeScrollBar()
End Sub
Sub makeScrollBar()
Dim textLen As Long
Me.txtBox.MaxLength = 0 ’무한입력
textLen = getBytesCnt(txtBox.Text)
If textLen >= 599 Then
'Me.txtBox.Multiline = True
txtBox.ScrollBars = ScrollBars.Vertical
Else
txtBox.ScrollBars = ScrollBars.None
End If
End Sub
Function countChars(text As String) As Integer()
Dim zenkakuCnt As Integer
Dim hankakuCnt As Integer
zenkakuCnt = 0
hankakuCnt = 0
For i As Integer = 1 To Len(text)
Dim currChar As String
Dim isZen As Long
currChar = Mid(text, i, 1)
isZen = getByteCnt(currChar)
' 일괄적으로 1바이트를 초과하면 전각처리
If isZen > 1 Then
zenkakuCnt += 1
Else
hankakuCnt += 1
End If
Next
Dim result(0 To 1) As Integer
result(0) = zenkakuCnt
result(1) = hankakuCnt
countChars = result
End Function
' 바로 이 함수 !
Function getByteCnt(text As String, Optional encoding As String = "Shift_JIS") As Long
Dim bytes() As Byte
Select Case LCase(encoding)
Case "utf-8"
bytes = System.Text.Encoding.UTF8.GetBytes(text)
Case "shift-jis"
bytes = System.Text.Encoding.GetEncoding("Shift_JIS").GetBytes(text)
Case Else
bytes = System.Text.Encoding.GetEncoding("Shift_JIS").GetBytes(text)
End Select
getByteCnt = UBound(bytes) - LBound(bytes) + 1
End Function
&HFF61
: Visual Basic에서 16진수로 표기된 값. &H는 16진수를 나타내는 접두사이며, 그 이후의 숫자들은 해당 코드 포인트의 16진수 표현.\uFF61
: 유니코드에서는 코드 포인트를 \u 뒤에 16진수로 표기. 이 표기법은 유니코드 문자의 문자열 리터럴에서 주로 사용.&HFF61
과 \uFF61
은 모두 전각 가타카나의 첫 번째 문자인 。