格式化电话号码只留下字母数字字符,然后按照格式

时间:2018-02-16 08:19:27

标签: excel vba excel-vba

这是我第一次在这里发帖。我目前正在探索VBA,我想制作一个格式化电话号码并将其转换为标准格式的宏。应删除除数字和字母之外的所有特殊字符。我很抱歉我的英语不太好。这是一个例子。

场景必须如下所示,我选择一个范围,

8009228080

(900) (CAT) BABA

(+1) (900) (289) (9000)

900.900.9000

然后我点击分配宏的按钮然后它就像这样

800-922-8080

900-228-2222

900-289-9000

900-900-9000

输出必须只有### - ### - ####(3个数字' - '3个数字' - '4个数字) 信必须翻译成以下内容 ABC = 2,DEF = 3,GHI = 4,JKL = 5,MNO = 6,PQRS = 7,TUV = 8,WXYZ = 9 我试着查找它,这是我的尝试:

    Sub PhoneFormat()

    Dim StSel As Range
    Dim EndSel As Range
    On Error Resume Next
    xTitleId = "Format Phone Numbers"
    Set EndSel = Application.Selection
    Set EndSel = Application.InputBox("Range", xTitleId, EndSel.Address, Type:=8)

我想更改此部分,因为我想首先选择范围,然后单击按钮然后应用宏

    For Each StSel In EndSel

        StSel.Value = Application.WorksheetFunction.Substitute(StSel.Value, "+", "")
        StSel.Value = Application.WorksheetFunction.Substitute(StSel.Value, "+1", "")
        StSel.Value = Application.WorksheetFunction.Substitute(StSel.Value, "-", "")
        StSel.Value = Application.WorksheetFunction.Substitute(StSel.Value, ".", "")
        StSel.Value = Application.WorksheetFunction.Substitute(StSel.Value, "(", "")
        StSel.Value = Application.WorksheetFunction.Substitute(StSel.Value, ")", "")
        StSel.Value = Application.WorksheetFunction.Substitute(StSel.Value, " ", "")

        If (Len(StSel) > 10) Then
            StSel = Right(StSel, 10)
        End If


    StSel = Left(StSel, 3) & "-" & Mid(StSel, 4, 3) & "-" & Right(StSel, 4)


    Next
    End Sub

我认为这可以优化为更简单的代码,但我不能这样做。此代码也无法将字母替换为数字。在此先感谢,我希望有人能回答这个问题。

4 个答案:

答案 0 :(得分:2)

以下是使用正则表达式执行此操作的示例:

Option Explicit

Public Sub test()
    Debug.Print FormatWithRegEx("(900) (CAT) BABA")
    Debug.Print FormatWithRegEx("(+1) (900) (289) (9000)")
    Debug.Print FormatWithRegEx("900.900.9000")

    Debug.Print ReplaceCharactersWithRegEx(FormatWithRegEx("(900) (CAT) BABA")) 
    'or dircetly implement ReplaceCharactersWithRegEx in FormatWithRegEx
End Sub

Public Function FormatWithRegEx(InputString As String) As String
    Dim objRegEx As Object
    Set objRegEx = CreateObject("vbscript.regexp")

    Dim arrPatterns() As Variant
    arrPatterns = Array( _
        "([A-Z0-9]{10})", _
        "\(?([A-Z0-9]{3})\)? \(?([A-Z0-9]{3})\)? \(?([A-Z0-9]{4})\)?", _
        "([A-Z0-9]{3})\.([A-Z0-9]{3})\.([A-Z0-9]{4})" _
    )

    Dim Pattern As Variant
    For Each Pattern In arrPatterns
        With objRegEx
            .Global = True
            .IgnoreCase = True
            .MultiLine = False
            .Pattern = Pattern

            Dim objMatches As Object
            Set objMatches = .Execute(InputString)
        End With

        If objMatches.Count = 1 Then
            With objMatches(0)
                If .SubMatches.Count = 3 Then
                    FormatWithRegEx= .SubMatches(0) & "-" & .SubMatches(1) & "-" & .SubMatches(2)
                End If
            End With
        End If
        If FormatWithRegEx <> vbNullString Then Exit For
    Next Pattern
    'to implement ReplaceCharactersWithRegEx uncomment …
    'FormatWithRegEx = ReplaceCharactersWithRegEx(FormatWithRegEx)
End Function

它识别测试中的3种给定模式。从字符到数字的翻译仍然需要完成。

这是一个纯RegEx替换示例

Public Function ReplaceCharactersWithRegEx(InputString As String) As String
    InputString = RegExReplace(InputString, "[ABC]{1}", "2")
    InputString = RegExReplace(InputString, "[DEF]{1}", "3")
    InputString = RegExReplace(InputString, "[GHI]{1}", "4")
    InputString = RegExReplace(InputString, "[JKL]{1}", "5")
    InputString = RegExReplace(InputString, "[MNO]{1}", "6")
    InputString = RegExReplace(InputString, "[PQRS]{1}", "7")
    InputString = RegExReplace(InputString, "[TUV]{1}", "8")
    InputString = RegExReplace(InputString, "[WXYZ]{1}", "9")

    ReplaceCharactersWithRegEx = InputString
End Function

Private Function RegExReplace(InputString, Pattern, Replace) As String
    Dim objRegEx As Object
    Set objRegEx = CreateObject("vbscript.regexp")

    With objRegEx
        .Global = True
        .IgnoreCase = True
        .MultiLine = False
        .Pattern = Pattern

        Dim objMatches As Object
        Set objMatches = .Execute(InputString)
    End With

    RegExReplace = objRegEx.Replace(InputString, Replace)
End Function

//编辑
使其对.IgnoreCase = True

不区分大小写

// EDIT2
选择循环示例

Dim cl As Range
For Each cl In Selection 'instead of Selection you can also use a defined Range("A1:A50")
    Dim FormattedValue As String
    FormattedValue = FormatWithRegEx(cl.value)
    If FormattedValue <> vbNullString Then 'don't delete if formatting wasn't successful
        cl.value = FormatWithRegEx(cl.value)
    End If
Next cl

答案 1 :(得分:1)

采取PEH的回答并添加字母转换为数字:

Option Explicit

Public Sub test()
Dim ws As Worksheet: Set ws = Sheets("Sheet1")
Dim rng As Range
Dim cell As Range
Set rng = Selection
For Each cell In rng
    cell.Value = ConvertLetters(FormatWithRegEx(cell.Value))
Next
End Sub

Public Function ConvertLetters(FormattedString As String) As String
    Dim J As Long, Digit As Variant
    For J = 1 To Len(FormattedString)
        Digit = UCase(Mid(FormattedString, J, 1))
        Select Case Digit
            Case "A" To "P"
                Digit = Chr((Asc(Digit) + 1) \ 3 + 28)
            Case "Q"
                Digit = "7"
            Case "R" To "Y"
                Digit = Chr(Asc(Digit) \ 3 + 28)
            Case "Z"
                Digit = "9"
        End Select
        Mid(FormattedString, J, 1) = Digit
    Next J
ConvertLetters = FormattedString
End Function


Public Function FormatWithRegEx(InputString As String) As String
    Dim objRegEx As Object
    Set objRegEx = CreateObject("vbscript.regexp")

    Dim arrPatterns() As Variant
    arrPatterns = Array( _
        "\(([a-zA-Z0-9]{3})\) \(([a-zA-Z0-9]{3})\) ([a-zA-Z0-9]{4})", _
        "\(([a-zA-Z0-9]{3})\) \(([a-zA-Z0-9]{3})\) \(([a-zA-Z0-9]{4})\)", _
        "([a-zA-Z0-9]{3})\.([a-zA-Z0-9]{3})\.([a-zA-Z0-9]{4})" _
    )

    Dim Pattern As Variant
    For Each Pattern In arrPatterns
        With objRegEx
            .Global = True
            .IgnoreCase = True
            .MultiLine = False
            .Pattern = Pattern

            Dim objMatches As Object
            Set objMatches = .Execute(InputString)
        End With

        If objMatches.Count = 1 Then
            With objMatches(0)
                If .SubMatches.Count = 3 Then
                    FormatWithRegEx = .SubMatches(0) & "-" & .SubMatches(1) & "-" & .SubMatches(2)
                End If
            End With
        End If
        If FormatWithRegEx <> vbNullString Then Exit For
    Next Pattern

End Function

<强>更新

以下内容将格式化您在评论中表达的电话号码(选择Thom的回答并添加选择):

Sub PhoneFormat()
Dim myLen As Long
Dim i As Long
Dim myNum As String
Dim newNum
Dim ws As Worksheet: Set ws = Sheets("Sheet1")
Dim rng As Range
Dim cell As Range
Set rng = Selection
For Each cell In rng
    '   Loop through characters, converting values
        If Len(cell.Value) > 0 Then
            For i = 1 To Len(cell.Value)
                Select Case Mid(cell.Value, i, 1)
                    Case "0"
                        myNum = "0"
                    Case "1"
                        myNum = "1"
                    Case "2"
                        myNum = "2"
                    Case "3"
                        myNum = "3"
                    Case "4"
                        myNum = "4"
                    Case "5"
                        myNum = "5"
                    Case "6"
                        myNum = "6"
                    Case "7"
                        myNum = "7"
                    Case "8"
                        myNum = "8"
                    Case "9"
                        myNum = "9"

                    Case "A", "B", "C", "a", "b", "c"
                        myNum = "2"
                    Case "D", "E", "F", "d", "e", "f"
                        myNum = "3"
                    Case "G", "H", "I", "g", "h", "i"
                        myNum = "4"
                    Case "J", "K", "L", "j", "k", "l"
                        myNum = "5"
                    Case "M", "N", "O", "m", "n", "o"
                        myNum = "6"
                    Case "P", "Q", "R", "S", "p", "q", "r", "s"
                        myNum = "7"
                    Case "T", "U", "V", "t", "u", "v"
                        myNum = "8"
                    Case "W", "X", "Y", "Z", "w", "x", "y", "z"
                        myNum = "9"

                    Case " ", "-", "."
                        myNum = "-"

                    Case Else
                        myNum = ""
                End Select
                newNum = newNum & myNum
            Next i
        End If
    cell.Value = Right(newNum, 12)
Next
End Sub

答案 2 :(得分:0)

我现在已经修改了脚本以使用选定的范围,它也将转换所有给定的示例。

对于其他可能对某些人有用的目的,阅读和修改很简单,这就是我发布它的原因。

该脚本使用Case Else删除未定义的字符,转换所需的字符。

Sub PhoneFormatRange()

        Dim myLen As Long
        Dim i As Long

        Dim myNum As String
        Dim newNum As String

        Dim selectedRng As Range
        Dim celRng As Range

        Dim strLeft As String
        Dim strMid As String
        Dim strRight As String


    ' Find the Selected Range and for each cell in the selected range run the cade and repeat.
    Set selectedRng = Application.Selection
    For Each celRng In selectedRng.Cells


    ' Convert Cell value to an array
    myLen = Len(celRng.Value)

    ReDim Carray(Len(celRng.Value))

    For i = 0 To myLen
        Carray(i) = Mid(celRng.Value, i + 1, 1)
    Next

    '   Loop through array, converting values
        If myLen > 0 Then
            For i = 0 To myLen
                Select Case Carray(i)
                     Case "0"
                        myNum = "0"
                    Case "1"
                        myNum = "1"
                    Case "2"
                        myNum = "2"
                    Case "3"
                        myNum = "3"
                    Case "4"
                        myNum = "4"
                    Case "5"
                        myNum = "5"
                    Case "6"
                        myNum = "6"
                    Case "7"
                        myNum = "7"
                    Case "8"
                        myNum = "8"
                    Case "9"
                        myNum = "9"

                    Case "A", "B", "C", "a", "b", "c"
                        myNum = "2"
                    Case "D", "E", "F", "d", "e", "f"
                        myNum = "3"
                    Case "G", "H", "I", "g", "h", "i"
                        myNum = "4"
                    Case "J", "K", "L", "j", "k", "l"
                        myNum = "5"
                    Case "M", "N", "O", "m", "n", "o"
                        myNum = "6"
                    Case "P", "Q", "R", "S", "p", "q", "r", "s"
                        myNum = "7"
                    Case "T", "U", "V", "t", "u", "v"
                        myNum = "8"
                    Case "W", "X", "Y", "Z", "w", "x", "y", "z"
                        myNum = "9"

                    Case " ", "-", "."
                        myNum = "-"

                    Case Else
                        myNum = ""

                End Select

                newNum = newNum & myNum
            Next i
        End If


    ' Check the length of the string and if it requals 10 then add the hypens
    If Len(newNum) = 10 Then

        strLeft = Left(newNum, 3)
        strMid = Mid(newNum, 4, 3)
        strRight = Right(newNum, 4)

        newNum = strLeft & "-" & strMid & "-" & strRight

    End If

    ' Set the cell value within the range to 12 right most characters of the string
    celRng.Value = Right(newNum, 12)


    ' Clear newNum before repeating
    newNum = ""

    ' Go back to celRng and repeat until all the cells within the selection is complete
    Next celRng

End Sub

答案 3 :(得分:0)

我也正在写PEH的正则表达式。但我的方法有点不同。只发布它,因为编写这篇文章很有趣,它可能会有所帮助。 我还使用了Xabiers ConvertLetters函数,因为它做得很好而且代码是一个非常好的方法。

我对正则表达式的处理方法是在一个表达式中匹配所有标准。所以我定义的模式找到了你所有定义的可能性。这迫使我做了一些额外的替换,但我稍微扩展了Xabiers代码。

Sub correctNumbers()
Dim i As Long, J As Long
Dim sEXP As String
Dim rng As Range
Dim oRegEx As Object, oMatch As Object
  ' create object for regular expressions
  Set oRegEx = CreateObject("vbscript.regexp")
  ' supposed you have a sheet called "Sheet1" - change sheetname and range according to your needs
  Set rng = ThisWorkbook.Sheets("Sheet1").Range("A2:A4")

  ' run through every entry in range
  For i = 1 To rng.Rows.Count
    With oRegEx
      .Global = True
      .IgnoreCase = False
      ' define pattern as desribed by you needs
      .Pattern = "([\(]?[0-9]{3}[\)]?[\s\.]?[\(]?[A-Z0-9]{3}[\)]?[\s\.]?[\(]?[A-Z0-9]{4}[\)]?)"
      Set oMatch = .Execute(rng(i, 1).Value)
      If oMatch.Count <> 0 Then
        sEXP = oMatch(0)
        If Len(sEXP) = 10 Then
          sEXP = Left(sEXP, 3) & "-" & Right(Left(sEXP, 6), 3) & "-" & Right(sEXP, 4)
        Else
          sEXP = ConvertLetters(oMatch(0))
        End If
      Else
        sEXP = ""
      End If
    End With
    ' write result in column B
    ThisWorkbook.Sheets("Sheet1").Range("B" & i + 1).Value = sEXP
  Next i
End Sub

 Public Function ConvertLetters(FormattedString As String) As String
 Dim J As Long, Digit As Variant
 For J = 1 To Len(FormattedString)
   Digit = UCase(Mid(FormattedString, J, 1))
   Select Case Digit
     Case "A" To "P"
       Digit = Chr((Asc(Digit) + 1) \ 3 + 28)
     Case "Q"
       Digit = "7"     'May want to change
     Case "R" To "Y"
       Digit = Chr(Asc(Digit) \ 3 + 28)
     Case "Z"
       Digit = "9"     'May want to change
       ' added as my regular expression finds complete number including dots, spaces and braces
     Case ".", " "
       Digit = "-"
     End Select
     Mid(FormattedString, J, 1) = Digit
   Next J
   ' added repalce as my regular expression finds complete number including dots, spaces and braces
   ConvertLetters = Replace(Replace(FormattedString, "(", ""), ")", "")
End Function