ZZZZ

AAA


   ' VeriationSelectorを除去する
    Dim variationSelectorRemover As variationSelectorRemover
    Set variationSelectorRemover = New variationSelectorRemover
    name = variationSelectorRemover.Remove(name, resultMap)
    For Each key In resultMap
        message = message & "「" & key & "」を「" & resultMap.Item(key) & "」に変換しました【VS】" & vbCrLf
    Next
    
    ' 異体字→常用漢字に変換する
    Dim joyoKanjiNormalizer As joyoKanjiNormalizer
    Set joyoKanjiNormalizer = New joyoKanjiNormalizer
    name = joyoKanjiNormalizer.Normalize(name, resultMap)
    For Each key In resultMap
        message = message & "「" & key & "」を「" & resultMap.Item(key) & "」に変換しました【異体字】" & vbCrLf
    Next
    
    ' 変換不可の外字を取得する
    Dim gaijiChecker As gaijiChecker
    Set gaijiChecker = New gaijiChecker
    Call gaijiChecker.HasGaiji(name, resultMap)
    For Each key In resultMap
        Dim code As Long
        code = WorksheetFunction.Unicode(resultMap.Item(key))
        message = message & key & "文字目に外字「" & resultMap.Item(key) & "/" & Hex(code) & "」がありました" & vbCrLf
    Next

 

 


'GaijiChecker
Option Explicit

' マスタのシート名および開始行
Private Const SHEET_NAME = "M_使用可能文字"
Private Const MASTER_DATA_BEGIN_ROW As Long = 2

' 利用可能文字のリスト
Private usableCharacters As Dictionary

'
' [処理] 外字を含むかどうか
' [引数] str: 入力文字列
'        gaijiMap: 外字の連想配列(文字位置, 文字)
' [戻り値] True: 外字を含む
'
Public Function HasGaiji(str As String, ByRef gaijiMap As Dictionary) As Boolean
    Dim gaiji_flag As Boolean
    gaiji_flag = False
    
    Call gaijiMap.RemoveAll
    
    ' 初めて関数が呼ばれた場合、マスタデータを取得する
    If (usableCharacters Is Nothing) Then
        Set usableCharacters = GetMasterData()
    End If

    Dim i As Long
    For i = 1 To Len(str)
        Dim c As String
        c = Mid(str, i, 1)
                
        ' 4バイト文字である場合、2文字分を取得する
        Dim is4Byte As Boolean
        is4Byte = Is4ByteCharacter(c)
        If (is4Byte) Then
            c = Mid(str, i, 2)
        End If

        ' 利用可能文字でない場合
        If Not (usableCharacters.Exists(c)) Then
            Call gaijiMap.Add(i, c)
            gaiji_flag = True
        End If
        If (is4Byte) Then
            i = i + 1
        End If
    Next
    HasGaiji = gaiji_flag
End Function

'
' マスタデータを取得する
'
Private Function GetMasterData() As Dictionary

    With ThisWorkbook.Worksheets(SHEET_NAME)
    Dim last_row As Long
    last_row = .Range("A1").End(xlDown).Row
    
    Dim dic As Dictionary
    Set dic = New Dictionary
    Dim i As Long
    For i = MASTER_DATA_BEGIN_ROW To last_row
        Dim c As String
        c = .Cells(i, 2)
        ' MapではなくSetとして利用するため、Valueには適当な値を設定する
        Call dic.Add(c, "")
    Next
    End With
    Set GetMasterData = dic
End Function

CCC


'JoyoKanjiNormalizer
Option Explicit

' マスタのシート名および開始行
Private Const SHEET_NAME = "M_新旧字体対応"
Private Const MASTER_DATA_BEGIN_ROW As Long = 3

' 新旧字体の文字を保持する連想配列
Private gaijiToJoyoMap As Dictionary

'
' [処理] 異体字を対応する常用漢字へ変換する
' [引数] str: 異体字を含む文字列
'        replacedMap:変換した文字の連想配列(変換前 -> 後)
' [戻り値] 常用漢字へ変換後の文字列
'
Public Function Normalize(str As String, ByRef replacedMap As Dictionary) As String
    Const CONVERTED_MARK = &H0
    Call replacedMap.RemoveAll

    ' 初めて関数が呼ばれた場合、マスタデータを取得する
    If (gaijiToJoyoMap Is Nothing) Then
        Set gaijiToJoyoMap = GetMasterData()
    End If

    Dim i As Long
    For i = 1 To Len(str)
        Dim c As String
        c = Mid(str, i, 1)
                
        ' 4バイト文字である場合、2文字分を取得する
        Dim is4Byte As Boolean
        is4Byte = Is4ByteCharacter(c)
        If (is4Byte) Then
            c = Mid(str, i, 2)
        End If
                
        ' 常用漢字に変換可能な場合
        If (gaijiToJoyoMap.Exists(c)) Then
            If Not replacedMap.Exists(c) Then
                Call replacedMap.Add(c, gaijiToJoyoMap.Item(c))
            End If
            Mid(str, i, 1) = gaijiToJoyoMap.Item(c)
            
            ' 4バイト文字の2文字目は削除対象にする
            If (is4Byte) Then
                Mid(str, i + 1) = Chr(CONVERTED_MARK)
                i = i + 1
            End If
        End If
    Next
    str = Replace(str, Chr(CONVERTED_MARK), "")
    Normalize = str
End Function

'
' マスタデータを取得する
'
Private Function GetMasterData() As Dictionary

    With ThisWorkbook.Worksheets(SHEET_NAME)
    Dim last_row As Long
    last_row = .Range("A1").End(xlDown).Row
    
    Dim dic As Dictionary
    Set dic = New Dictionary
    Dim i As Long
    For i = MASTER_DATA_BEGIN_ROW To last_row
        Dim before As String
        Dim after As String
        before = .Cells(i, 1)
        after = .Cells(i, 2)
        Call dic.Add(before, after)
    Next
    End With
    Set GetMasterData = dic
End Function

DDD


'ValidationSelectorRemover
Option Explicit

'
' [処理] IVS登録文字のVariation Selectorを取り除く
' [引数] str: 対象文字列
'        replacedMap: 除去前後の文字の連想配列(除去前, 除去後)
' [戻り値] Variation Selectorを除去した文字列
' [補足]
'   IVS : Ideographic Variation Sequence
'   例.にしんにょうの辻   :8FBB
'   いっしんにょうの辻 :8FBB + E0100(VS)
'  「+E01XX」の2文字を取り除く
Public Function Remove(str As String, ByRef replacedMap As Dictionary) As String
    Const REPLACED_MARK As String = &H0
    
    Call replacedMap.RemoveAll
    Dim i As Long
    For i = 1 To Len(str) - 2
        Dim c As String
        
        ' 文字に対するVariation Selectorの相対位置
        Dim vs_offset_pos As Long
        If (StringUtil.Is4ByteCharacter(Mid(str, i, 1))) Then
            c = Mid(str, i, 2)
            vs_offset_pos = 2
        Else
            c = Mid(str, i, 1)
            vs_offset_pos = 1
        End If
            
        ' 末端文字がVariation Selectorを持たず、文字長を超過する場合は処理を打ち切る
        If (i + vs_offset_pos + 1 > Len(str)) Then
            Exit For
        End If
        
        ' 2バイト文字の場合、Variation Selector含め3文字であるため,2,3文字目を取得する
        ' 4バイト文字の場合、Variation Selector含め4文字であるため,3,4文字目を取得する
        Dim n1 As String
        Dim n2 As String
        n1 = Mid(str, i + vs_offset_pos, 1)
        n2 = Mid(str, i + vs_offset_pos + 1, 1)
        
        ' Variation Selectorを持つ場合
        If (IsVariationSelector(n1, n2)) Then
            If Not replacedMap.Exists(c & n1 & n2) Then
                Call replacedMap.Add(c & n1 & n2, c)
            End If
            Mid(str, i + vs_offset_pos, 1) = Chr(REPLACED_MARK)
            Mid(str, i + vs_offset_pos + 1, 1) = Chr(REPLACED_MARK)
            i = i + 2
        End If
    Next
    
    ' Variation Selectorを全て取り除く
    str = Replace(str, Chr(REPLACED_MARK), "")
    Remove = str
End Function

' 指定文字がVariation Selectorであるか
Private Function IsVariationSelector(n1 As String, n2 As String) As Boolean
    Dim code1 As Long
    Dim code2 As Long
    code1 = AscW(n1)
    code2 = AscW(n2)
    
    ' Variation Selectorの取りうるコードポイント(U+E0100 - U+E01EF)
    IsVariationSelector = (code1 = &HDB40 And (&HDD00 <= code2 And code2 <= &HDDEF))
End Function

 



'
' [処理] サロゲートペア(4バイト)の文字であるか
' [引数] c : サロゲートペアの上位2バイト(1文字)
' [戻り値] True:サロゲートペアである
'
Public Function Is4ByteCharacter(c As String) As Boolean
    Dim code As Long
    code = AscW(c)
    Is4ByteCharacter = (&HD800 <= code And code <= &HDBFF)
 End Function