Excel VBA セル内の文字列のチェックと変換
WordPressのプラグインで、WP-Syntaxっていうソースコードを整形して表示するものがあります。 これならいちいちHTMLタグやエスケープシーケンスを入れずに済むのでサンプルを公開しやすくなるかな。
このコードは実際に動きます。
Excelのマクロでコード編集を表示して貼り付けてください。 後はシートにボタンを貼り付けて、先頭の2つのプロシージャーを呼び出せばOKです。 中に"N2S"という関数がありますが、Nullチェックをしています。 何か作って置き換えてください。
Option Explicit
'定数
Public Const COMMAND_CHECKCELL_WIDEALPHABET = 1
Public Const COMMAND_CHECKCELL_WIDENUMBERS = 2
Public Const COMMAND_CHECKCELL_WIDEMARKS = 3
Public Const COMMAND_CHECKCELL_WIDECOMMA = 4
Public Const COMMAND_CHECKCELL_WITHOUTINCLUDEDCHAR = 5
Public Const COMMAND_CONVERT_WIDEALPHABET = 1
Public Const COMMAND_CONVERT_WIDENUMBERS = 2
Public Const COMMAND_CONVERT_WIDEMARKS = 3
Public Const COMMAND_CONVERT_WIDECOMMA = 4
'色
Public Const COLOR_PINK = 16711935
Public Const COLOR_BLUE = 16776960
'セルのフォント情報の保存
'メンバーは何が入ってくるかわからないのでとりあえず「Variant」
Type tyFontInfo
vBold As Variant
vColor As Variant
vColorIndex As Variant
vFontStyle As Variant
vItalic As Variant
vName As Variant
vShadow As Variant
vSize As Variant
vStrikethrough As Variant
vSubscript As Variant
vSuperscript As Variant
vUnderline As Variant
End Type
'イベント共通処理
'チェック
Public Function gExecCellCheck(ByVal lCommand As Long) As Boolean
On Error GoTo ErrProc
Dim lRow As Long
Dim lCol As Long
Dim objWs As Excel.Worksheet
Set objWs = Application.ThisWorkbook.ActiveSheet
lRow = Application.ActiveCell.Row
lCol = Application.ActiveCell.Column
Application.ScreenUpdating = False
Select Case lCommand
Case COMMAND_CHECKCELL_WIDEALPHABET, _
COMMAND_CHECKCELL_WIDENUMBERS, _
COMMAND_CHECKCELL_WIDEMARKS, _
COMMAND_CHECKCELL_WIDECOMMA
If CheckCell_WideThin(objWs, lRow, lCol, lCommand) Then
Else
'チェック対象が見つからなかった
End If
Case COMMAND_CHECKCELL_WITHOUTINCLUDEDCHAR
If CheckCell_WithOutIncludedChar(objWs, lRow, lCol) Then
End If
Case Else
End Select
Application.ScreenUpdating = True
MsgBox "チェック終了", vbOKOnly + vbInformation
ExitProc:
Exit Function
ErrProc:
Call ErrFunc(Err, "gExecCellCheck")
Resume ExitProc
End Function
'イベント共通処理
'変換
Public Function gExecCellConvert(ByVal lCommand As Long) As Boolean
On Error GoTo ErrProc
Dim lRow As Long
Dim lCol As Long
Dim objWs As Excel.Worksheet
If vbYes = MsgBox("変換処理をすると元に戻すことができません。" & vbCrLf & _
"事前にバックアップを作ることを推奨します。" & vbCrLf & vbCrLf & _
"変換処理を行いますか?", vbYesNo + vbQuestion) Then
Else
GoTo ExitProc
End If
Application.ScreenUpdating = False
Set objWs = Application.ThisWorkbook.ActiveSheet
lRow = Application.ActiveCell.Row
lCol = Application.ActiveCell.Column
If Convert_Letter(objWs, lRow, lCol, lCommand) Then
MsgBox "変換終了", vbOKOnly + vbInformation
Else
'変換の失敗
MsgBox "変換できませんでした。", vbOKOnly + vbExclamation
End If
ExitProc:
Application.ScreenUpdating = True
Exit Function
ErrProc:
Call ErrFunc(Err, "gExecCellConvert")
Resume ExitProc
End Function
'選択中のセルの書式を保存した後、変更
Private Function CheckCell_WithOutIncludedChar(ByVal objWs As Excel.Worksheet, _
ByVal lRow As Long, _
ByVal lCol As Long) As Boolean
CheckCell_WithOutIncludedChar = False
On Error GoTo ErrProc
Dim strCellValue As String
Dim lCnt As Long
Dim arrErrStringIdx() As Long
ReDim arrErrStringIdx(0)
strCellValue = objWs.Cells(lRow, lCol).value
If CheckLetter_WithOut_OSIncluded(strCellValue, arrErrStringIdx) Then
Else
For lCnt = 0 To UBound(arrErrStringIdx)
If objWs.Cells(lRow, lCol).Characters(arrErrStringIdx(lCnt), 1).Font.Color = COLOR_PINK Then
objWs.Cells(lRow, lCol).Characters(arrErrStringIdx(lCnt), 1).Font.Color = 0
ElseIf objWs.Cells(lRow, lCol).Characters(arrErrStringIdx(lCnt), 1).Font.Color = 0 Then
objWs.Cells(lRow, lCol).Characters(arrErrStringIdx(lCnt), 1).Font.Color = COLOR_PINK
Else
End If
CheckCell_WithOutIncludedChar = True
Next
End If
ExitProc:
Exit Function
ErrProc:
Call ErrFunc(Err, "CheckCell_WithOutIncludedChar")
Resume ExitProc
End Function
'機種依存文字以外のチェック
Private Function CheckCell_WideThin(ByVal objWs As Excel.Worksheet, _
ByVal lRow As Long, _
ByVal lCol As Long, _
ByVal lMode As Long) As Boolean
CheckCell_WideThin = False
On Error GoTo ErrProc
Dim strCellValue As String
Dim lCnt As Long
Dim arrWideStringIdx() As Long
Dim arrThinStringIdx() As Long
Dim flgCheckOK As Boolean
strCellValue = objWs.Cells(lRow, lCol).value
Select Case lMode
Case COMMAND_CHECKCELL_WIDEALPHABET
flgCheckOK = Check_WideToThin_Alphabet(strCellValue, arrWideStringIdx, arrThinStringIdx)
Case COMMAND_CHECKCELL_WIDENUMBERS
flgCheckOK = Check_WideToThin_Numeric(strCellValue, arrWideStringIdx, arrThinStringIdx)
Case COMMAND_CHECKCELL_WIDEMARKS
flgCheckOK = Check_WideToThin_Mark(strCellValue, arrWideStringIdx, arrThinStringIdx)
Case COMMAND_CHECKCELL_WIDECOMMA
flgCheckOK = Check_WideToThin_Comma(strCellValue, arrWideStringIdx, arrThinStringIdx)
Case Else
End Select
If flgCheckOK Then
Else
GoTo ExitProc
End If
'全角チェック
For lCnt = 0 To UBound(arrWideStringIdx)
If objWs.Cells(lRow, lCol).Characters(arrWideStringIdx(lCnt), 1).Font.Color = COLOR_PINK Then
objWs.Cells(lRow, lCol).Characters(arrWideStringIdx(lCnt), 1).Font.Color = 0
ElseIf objWs.Cells(lRow, lCol).Characters(arrWideStringIdx(lCnt), 1).Font.Color = 0 Then
objWs.Cells(lRow, lCol).Characters(arrWideStringIdx(lCnt), 1).Font.Color = COLOR_PINK
Else
End If
Next
'半角チェック
For lCnt = 0 To UBound(arrThinStringIdx)
If objWs.Cells(lRow, lCol).Characters(arrThinStringIdx(lCnt), 1).Font.Color = COLOR_BLUE Then
objWs.Cells(lRow, lCol).Characters(arrThinStringIdx(lCnt), 1).Font.Color = 0
ElseIf objWs.Cells(lRow, lCol).Characters(arrThinStringIdx(lCnt), 1).Font.Color = 0 Then
objWs.Cells(lRow, lCol).Characters(arrThinStringIdx(lCnt), 1).Font.Color = COLOR_BLUE
Else
End If
Next
CheckCell_WideThin = True
ExitProc:
Exit Function
ErrProc:
Call ErrFunc(Err, "CheckCell_WideThin")
Resume ExitProc
End Function
'機種依存文字の判別
'機種依存文字のインデックスを返す。
Private Function CheckLetter_WithOut_OSIncluded(ByVal strCheck As String, _
ByRef arrErrStringIdx() As Long) As Boolean
CheckLetter_WithOut_OSIncluded = False
Dim lCheckLength As Long
Dim lCharacter As Long
Dim lIdx As Long
Dim lCnt As Long
On Error GoTo ErrProc
lCheckLength = Len(strCheck)
lCnt = 0 'カウンターをリセット
lIdx = 0 '配列のインデックスをリセット
ReDim arrErrStringIdx(lIdx) '配列をリセット
' Excelの"Asc"はSignedで正負を含む10進数を返します。
' 1:NEC選定特殊文字 -30823 ~ -30912
' 2:IBM選定特殊文字 -1472 ~ -949
For lCnt = 1 To lCheckLength
lCharacter = Asc(Mid(strCheck, lCnt, 1))
If (lCharacter <= -30823 And lCharacter >= -30912) Or (lCharacter <= -949 And lCharacter >= -1472) Then
ReDim Preserve arrErrStringIdx(lIdx) '配列をリセット
arrErrStringIdx(lIdx) = lCnt '配列に機種依存文字のインデックスをセット[~文字目]
lIdx = lIdx + 1
End If
Next
If lIdx > 0 Then
CheckLetter_WithOut_OSIncluded = False
Else
CheckLetter_WithOut_OSIncluded = True
End If
ExitProc:
Exit Function
ErrProc:
Call ErrFunc(Err, "CheckLetter_WithOut_OSIncluded")
Resume ExitProc
End Function
'アルファベットチェック
Private Function Check_WideToThin_Alphabet(ByVal strCheck As String, _
ByRef arrWideStringIdx() As Long, _
ByRef arrThinStringIdx() As Long) As Boolean
Check_WideToThin_Alphabet = False
On Error GoTo ErrProc
Dim lCheckLength As Long
Dim lCharacter As Long
Dim lWideIdx As Long
Dim lThinIdx As Long
Dim lCnt As Long
lCheckLength = Len(strCheck)
lCnt = 0
lWideIdx = 0
lThinIdx = 0
ReDim arrWideStringIdx(lWideIdx)
ReDim arrThinStringIdx(lThinIdx)
'A:65~Z:90/a:97~z:122
'A:-32160~Z:-32135/a:-32127~z:-32102
For lCnt = 1 To lCheckLength
lCharacter = Asc(Mid(strCheck, lCnt, 1))
If (lCharacter <= 90 And lCharacter >= 65) Or (lCharacter <= 122 And lCharacter >= 97) Then
ReDim Preserve arrThinStringIdx(lThinIdx) '配列をリセット
arrThinStringIdx(lThinIdx) = lCnt '配列に半角英字のインデックスをセット[~文字目]
lThinIdx = lThinIdx + 1
Check_WideToThin_Alphabet = True
End If
If (lCharacter <= -32135 And lCharacter >= -32160) Or (lCharacter <= -32102 And lCharacter >= -32127) Then
ReDim Preserve arrWideStringIdx(lWideIdx) '配列をリセット
arrWideStringIdx(lWideIdx) = lCnt '配列に全角英字のインデックスをセット[~文字目]
lWideIdx = lWideIdx + 1
Check_WideToThin_Alphabet = True
End If
Next
ExitProc:
Exit Function
ErrProc:
Call ErrFunc(Err, "Check_WideToThin_Alphabet")
Resume ExitProc
End Function
'数字チェック
Private Function Check_WideToThin_Numeric(ByVal strCheck As String, _
ByRef arrWideStringIdx() As Long, _
ByRef arrThinStringIdx() As Long) As Boolean
Check_WideToThin_Numeric = False
On Error GoTo ErrProc
Dim lCheckLength As Long
Dim lCharacter As Long
Dim lWideIdx As Long
Dim lThinIdx As Long
Dim lCnt As Long
lCheckLength = Len(strCheck)
lCnt = 0
lWideIdx = 0
lThinIdx = 0
ReDim arrWideStringIdx(lWideIdx)
ReDim arrThinStringIdx(lThinIdx)
'0:48~9:57
'0:-32177~9:-32168
For lCnt = 1 To lCheckLength
lCharacter = Asc(Mid(strCheck, lCnt, 1))
If lCharacter <= 57 And lCharacter >= 48 Then
ReDim Preserve arrThinStringIdx(lThinIdx) '配列をリセット
arrThinStringIdx(lThinIdx) = lCnt '配列に半角数字のインデックスをセット[~文字目]
lThinIdx = lThinIdx + 1
Check_WideToThin_Numeric = True
End If
If lCharacter <= -32168 And lCharacter >= -32177 Then
ReDim Preserve arrWideStringIdx(lWideIdx) '配列をリセット
arrWideStringIdx(lWideIdx) = lCnt '配列に全角数字のインデックスをセット[~文字目]
lWideIdx = lWideIdx + 1
Check_WideToThin_Numeric = True
End If
Next
ExitProc:
Exit Function
ErrProc:
Call ErrFunc(Err, "Check_WideToThin_Numeric")
Resume ExitProc
End Function
'記号チェック
Private Function Check_WideToThin_Mark(ByVal strCheck As String, _
ByRef arrWideStringIdx() As Long, _
ByRef arrThinStringIdx() As Long) As Boolean
Check_WideToThin_Mark = False
On Error GoTo ErrProc
Dim lCheckLength As Long
Dim lCharacter As Long
Dim lWideIdx As Long
Dim lThinIdx As Long
Dim lCnt As Long
lCheckLength = Len(strCheck)
lCnt = 0
lWideIdx = 0
lThinIdx = 0
ReDim arrWideStringIdx(lWideIdx)
ReDim arrThinStringIdx(lThinIdx)
'+,-,*,=
'+,-,*,=
For lCnt = 1 To lCheckLength
lCharacter = Asc(Mid(strCheck, lCnt, 1))
Select Case lCharacter
Case 42, 43, 45, 61
ReDim Preserve arrThinStringIdx(lThinIdx) '配列をリセット
arrThinStringIdx(lThinIdx) = lCnt '配列に半角記号のインデックスをセット[~文字目]
lThinIdx = lThinIdx + 1
Check_WideToThin_Mark = True
Case -32383, -32388, -32362, -32389
ReDim Preserve arrWideStringIdx(lWideIdx) '配列をリセット
arrWideStringIdx(lWideIdx) = lCnt '配列に全角記号のインデックスをセット[~文字目]
lWideIdx = lWideIdx + 1
Check_WideToThin_Mark = True
Case Else
End Select
Next
ExitProc:
Exit Function
ErrProc:
Call ErrFunc(Err, "Check_WideToThin_Mark")
Resume ExitProc
End Function
'カンマチェック
Private Function Check_WideToThin_Comma(ByVal strCheck As String, _
ByRef arrWideStringIdx() As Long, _
ByRef arrThinStringIdx() As Long) As Boolean
Check_WideToThin_Comma = False
On Error GoTo ErrProc
Dim lCheckLength As Long
Dim lCharacter As Long
Dim lWideIdx As Long
Dim lThinIdx As Long
Dim lCnt As Long
lCheckLength = Len(strCheck)
lCnt = 0
lWideIdx = 0
lThinIdx = 0
ReDim arrWideStringIdx(lWideIdx)
ReDim arrThinStringIdx(lThinIdx)
',
'、,
For lCnt = 1 To lCheckLength
lCharacter = Asc(Mid(strCheck, lCnt, 1))
Select Case lCharacter
Case 44
ReDim Preserve arrThinStringIdx(lThinIdx) '配列をリセット
arrThinStringIdx(lThinIdx) = lCnt '配列に半角カンマのインデックスをセット[~文字目]
lThinIdx = lThinIdx + 1
Check_WideToThin_Comma = True
Case -32445, -32447
ReDim Preserve arrWideStringIdx(lWideIdx) '配列をリセット
arrWideStringIdx(lWideIdx) = lCnt '配列に全角カンマのインデックスをセット[~文字目]
lWideIdx = lWideIdx + 1
Check_WideToThin_Comma = True
Case Else
End Select
Next
ExitProc:
Exit Function
ErrProc:
Call ErrFunc(Err, "Check_WideToThin_Comma")
Resume ExitProc
End Function
'文字列変換
Private Function Convert_Letter(ByVal objWs As Excel.Worksheet, _
ByVal lRow As Long, _
ByVal lCol As Long, _
ByVal lMode As Long) As Boolean
Convert_Letter = False
On Error GoTo ErrProc
Dim strCellValue As String
Dim lCnt As Long
Dim lIdx As Long
Dim arrWideStringIdx() As Long
Dim arrThinStringIdx() As Long
Dim strBuffer As String
Dim strConvBuffer As String
Dim lCellLength As Long
Dim flgCheckOK As Boolean
lCnt = 0
lIdx = 0
strConvBuffer = ""
flgCheckOK = False
ReDim arrErrStringIdx(0)
Dim objFont() As tyFontInfo
strCellValue = objWs.Cells(lRow, lCol).value
lCellLength = Len(strCellValue)
ReDim objFont(lCellLength - 1)
Select Case lMode
Case COMMAND_CONVERT_WIDEALPHABET
flgCheckOK = Check_WideToThin_Alphabet(strCellValue, arrWideStringIdx, arrThinStringIdx)
Case COMMAND_CONVERT_WIDENUMBERS
flgCheckOK = Check_WideToThin_Numeric(strCellValue, arrWideStringIdx, arrThinStringIdx)
Case COMMAND_CONVERT_WIDEMARKS
flgCheckOK = Check_WideToThin_Mark(strCellValue, arrWideStringIdx, arrThinStringIdx)
Case COMMAND_CONVERT_WIDECOMMA
flgCheckOK = Check_WideToThin_Comma(strCellValue, arrWideStringIdx, arrThinStringIdx)
Case Else
End Select
If flgCheckOK Then
Else
'終了する
GoTo ExitProc
End If
For lCnt = 0 To lCellLength - 1
'書式の保存
With objWs.Cells(lRow, lCol).Characters(lCnt + 1, 1).Font
objFont(lCnt).vBold = .Bold
objFont(lCnt).vColor = .Color
objFont(lCnt).vColorIndex = .ColorIndex
objFont(lCnt).vFontStyle = .FontStyle
objFont(lCnt).vItalic = .Italic
objFont(lCnt).vName = .Name
objFont(lCnt).vShadow = .Shadow
objFont(lCnt).vSize = .Size
objFont(lCnt).vStrikethrough = .Strikethrough
objFont(lCnt).vSubscript = .Subscript
objFont(lCnt).vSuperscript = .Superscript
objFont(lCnt).vUnderline = .Underline
End With
strConvBuffer = Mid(strCellValue, lCnt + 1, 1)
Select Case lMode
Case COMMAND_CONVERT_WIDEALPHABET
'アルファベットを全角から半角へ
For lIdx = 0 To UBound(arrWideStringIdx)
If arrWideStringIdx(lIdx) = lCnt + 1 Then
strConvBuffer = StrConv(strConvBuffer, vbNarrow)
End If
Next
Case COMMAND_CONVERT_WIDENUMBERS
'数字を全角から半角へ
For lIdx = 0 To UBound(arrWideStringIdx)
If arrWideStringIdx(lIdx) = lCnt + 1 Then
strConvBuffer = StrConv(strConvBuffer, vbNarrow)
End If
Next
Case COMMAND_CONVERT_WIDEMARKS
'記号を全角から半角へ
For lIdx = 0 To UBound(arrWideStringIdx)
If arrWideStringIdx(lIdx) = lCnt + 1 Then
strConvBuffer = StrConv(strConvBuffer, vbNarrow)
End If
Next
Case COMMAND_CONVERT_WIDECOMMA
'カンマをすべて全角の「,」へ
For lIdx = 0 To UBound(arrWideStringIdx)
If arrWideStringIdx(lIdx) = lCnt + 1 Then
strConvBuffer = ","
End If
Next
For lIdx = 0 To UBound(arrThinStringIdx)
If arrThinStringIdx(lIdx) = lCnt + 1 Then
strConvBuffer = ","
End If
Next
Case Else
End Select
strBuffer = strBuffer & strConvBuffer
Next
'文字列をセルに
objWs.Cells(lRow, lCol).value = strBuffer
'書式を書き戻す
For lCnt = 0 To lCellLength - 1
With objWs.Cells(lRow, lCol).Characters(lCnt + 1, 1).Font
.Bold = objFont(lCnt).vBold
.Color = objFont(lCnt).vColor
.ColorIndex = objFont(lCnt).vColorIndex
.FontStyle = objFont(lCnt).vFontStyle
.Italic = objFont(lCnt).vItalic
.Name = objFont(lCnt).vName
.Shadow = objFont(lCnt).vShadow
.Size = objFont(lCnt).vSize
.Strikethrough = objFont(lCnt).vStrikethrough
.Subscript = objFont(lCnt).vSubscript
.Superscript = objFont(lCnt).vSuperscript
.Underline = objFont(lCnt).vUnderline
End With
Next
Convert_Letter = True
ExitProc:
Exit Function
ErrProc:
Call ErrFunc(Err, "Convert_Letter")
Resume ExitProc
End Function