消除除alpha字符以外的所有字符的公式

时间:2015-03-19 16:23:42

标签: excel excel-vba excel-formula substitution excel-udf vba

我需要在Excel中擦除一列名称以消除所有非Alpha字符,包括句点,逗号,空格,连字符和撇号。

实施例: 将O'Malley-Smith, Tom, Jr.更改为OMALLEYSMITHTOMJR

客户端要求这是一个Excel函数,否则我可以使用类似于replaceAll("[^a-zA-Z]", "").toUpperCase()的快速Java程序轻松实现。在一整套SUBSTITUTE函数之外,我似乎无法找到任何看起来像现成函数的东西 - 这似乎只有每个单元格一个。

如果这是我需要的话,我对开发自定义宏的能力不是非常流畅。

6 个答案:

答案 0 :(得分:6)

如果你想沿着VBA路线走下去 - 你不能使用用户定义函数(UDF)来改变你输入函数的单元格的值 - 但是你可以使用一个简单的宏来拍摄微软VBScript RegEx引擎的优势:

Sub SO()

Dim searchRange     As Excel.Range
Dim cell            As Variant
Dim RegEx           As Object

Set RegEx = CreateObject("VBScript.RegExp")

With RegEx
    .Pattern = "[^a-zA-Z]"
    .Global = True
    .MultiLine = True
End With

Set searchRange = ActiveSheet.Range("A1:D5") '// Change as required

    For Each cell In searchRange.Cells
        If RegEx.test(cell) Then cell.Value = RegEx.Replace(cell.Value, vbNullString)
        cell.Value = UCase(cell.Value)
    Next cell

Set searchRange = Nothing
Set RegEx = Nothing

End Sub

答案 1 :(得分:5)

确实可能在一个单元格中出现一堆SUBSTITUTE,例如:

=UPPER(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(A1," ",""),",",""),"'",""),".",""),"-",""))   

当然可能需要'扩展'以涵盖其他非字母字符。

答案 2 :(得分:5)

前段时间我有类似的需求,并发现了一些效果很好的东西。

按Alt + F11以打开Visual Basic编辑器。插入一个新模块并粘贴以下代码。

Function CleanCode(Rng As Range)
    Dim strTemp As String
    Dim n As Long

    For n = 1 To Len(Rng)
        Select Case Asc(Mid(UCase(Rng), n, 1))
            Case 48 To 57, 65 To 90
                strTemp = strTemp & Mid(UCase(Rng), n, 1)
        End Select
    Next
    CleanCode = strTemp
End Function

CleanCode现在是新功能,您可以将其用作公式。

因此,在您要操作的字符串的单元格旁边,只需复制=CleanCode(yourcell)

答案 3 :(得分:1)

另一个VBA解决方案

Sub RemoveCrap()
    Dim varRange As Range
    Dim varWorkRange As Range

    Set varWorkRange = Range("A1:A10")

    For Each varRange In varWorkRange
        varVal = ""
        For i = 1 To Len(varRange.Value)
            varTemp = Mid(varRange.Value, i, 1)
            If Not (varTemp Like "[a-z]" Or varTemp Like "[A-Z]") Then
                varStr = ""
            Else
                varStr = UCase(varTemp)
            End If
            varVal = varVal & varStr
        Next i
        varRange.Value = varVal
    Next
End Sub

答案 4 :(得分:0)

这可以在Excel 2016及更高版本中使用单个公式完成。

虽然pnuts的解决方案列出了要删除的显式字符,但此解决方案列出了明确有效的字符。

假设您的脏数据在A列中。 假设您希望B列中包含干净的数据。

在单元格B1中使用下面的最后一个公式。要将公式输入到单元格B1中,请执行以下操作:

  • 单击单元格B1
  • 点击公式栏
  • 粘贴公式
  • 按CTRL + Shift + Enter< - 重要步骤

复制单元格B1并根据需要将其粘贴到B列。

首先,这是一个简短的例子来解释发生了什么:

=TEXTJOIN("",TRUE,

IFs(
    MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1) = "t", "t",
    MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1) = "e", "e",
    MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1) = "s", "s",
    MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1) = "T", "T",
    MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1) = "E", "E",
    MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1) = "S", "S",
    MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1) = "2", "2",
    MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1) = " ", " ",
    true, ""
  )

)

在这种情况下,我将以下字符指定为有效:t,e,s,T,E,S,2和空格字符。

显然,你需要将公式扩展到完整的字母表,分别列出每个大写和小写字符。同样,如果要保留数字,请将其扩展为包含数字。请注意,数字被编码为字符串。

这是如何运作的:

简而言之,我们将源字符串拆分为单独字符的数组,然后为每个字符检查它是否在我们的有效字符集中,如果是,则将其包含在结果中,否则将其替换为空字符串,如果不是。

'IFS'函数一次一对地遍历其参数。如果第一个参数的计算结果为true,则返回第二个参数。如果没有,它继续下一对参数 - 这就是为什么你看到每行列出两次的字母。 IFS函数中的最后一对值是set'true'和空字符串。这就是说如果我们到达有效值集的末尾(即没有匹配有效值),则返回空字符串。

有关其工作原理的更多背景信息:

这是ExcelJet给出的解决方案的变体。在该解决方案中,TEXTJOIN函数(用于连接数组的值)与INDIRECT函数(将字符串拆分为数组)与数学运算符(加号)一起使用,以强制评估每个字符之间的计算在带有数值的字符串中。字符串中的数字字符将返回数值,而其他字符将返回错误。该解决方案使用函数ISERR来检查错误,以确定是否在最终输出中包含给定字符。在那里存在类似的文章以反过来的方式 - 排除数字并保留字母。

我想解决的问题是编码员决定哪些值有效,哪些值不有。我尝试将VLOOKUP和INDEX函数与INDIRECT函数结合使用,但它们只能处理字符串中的第一个字符。诀窍是并非所有函数都会以 on 对INDIRECT的输出进行操作,以便评估数组中的每个元素(即字符串中的每个字符)。秘密是ExcelJet使用了数学运算符。如果您检查Microsoft的完整function reference,则IFS被归类为“逻辑”功能。我怀疑逻辑函数可以用这种方式与INDIRECT一起使用。

(注意:我还试图在各种组合中使用AND和OR。但是,INDIRECT会评估字符串中的所有字符。例如,使用CODE函数获取每个字符的ASCII值和断言所有字符必须具有介于65 - 90(大写)或97 - 122(小写字母)之间的值,只有当字符串中的所有字符都是大写,或者全部都是小写时才有效,但如果有混合物。)

我不知道此解决方案的性能与之前使用SUBSTITUTE的建议相比如何。如果您只想删除几个字符,我建议使用SUBSTITUTE解决方案。如果要明确指定要保留的有效字符(这是原始问题),请使用此字符。

最后,这是您需要的确切答案,包括您在问题中没有注明的转换为大写,但在示例中显示。 (对于其他不想要大写转换的人,从这个示例中删除'UPPER'的实例,然后再次将字母添加到列表中,小写,并确保将'true'/空字符串对保留为最后一个条目在列表中。)

=TEXTJOIN("",TRUE,
IFs(
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "A", "A",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "B", "B",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "C", "C",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "D", "D",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "E", "E",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "F", "F",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "G", "G",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "H", "H",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "I", "I",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "J", "J",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "K", "K",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "L", "L",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "M", "M",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "N", "N",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "O", "O",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "P", "P",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "Q", "Q",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "R", "R",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "S", "S",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "T", "T",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "U", "U",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "V", "V",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "W", "W",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "X", "X",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "Y", "Y",
    upper(MID(a1,ROW(INDIRECT(CONCATENATE("1:",LEN(a1)))),1)) = "Z", "Z",
    true, ""
)
)

原始问题是“消除除字母字符以外的所有字符” - 这个答案在公式中完成,无需VBA。

答案 5 :(得分:0)

由于刚加入并且信誉不足,无法直接回应 aurezio 。我真的很喜欢这种解决方案,发现它非常有效且简短/简单,可以满足我的要求-清理文本字段以将过滤后的字符集输出到用于文件名和Web编码输出需求的列。

尽管没有直接回答问题,但此页面是我找到的与所需解决方案最接近的页面,因此我想为其他人员提供更多背景信息,并扩展aurezio的解决方案以选择更通用的字符,以防万一有人感兴趣。 >

第7行与允许的字符数或数字序列有关。使用excel函数CODE()来标识字符的代码,并使用CHAR()将字符代码发布到其中。

我的标准(如下所示)是过滤除45(破折号),48至57(数字系列),65至90(字母数字大写系列),97至122(字母数字小写系列)之外的所有内容。另外,不需要大写意味着可以删除UCase()。

'based off aurezio's solution
Function CleanCode(Rng As Range)
    Dim strTemp As String
    Dim n As Long

    For n = 1 To Len(Rng)
        Select Case Asc(Mid(Rng, n, 1))
            Case 45, 48 To 57, 65 To 90, 97 To 122
                strTemp = strTemp & Mid(Rng, n, 1)
        End Select
    Next
    CleanCode = strTemp
End Function

最终,我想对其进行改进,使其最终具有动态性,并允许所需过滤器的输入参数。 例如ClearCode(Range,“ 45”,“ 48-57”,“ 65-90”,“ 97-122”)