我需要在Excel中擦除一列名称以消除所有非Alpha字符,包括句点,逗号,空格,连字符和撇号。
实施例:
将O'Malley-Smith, Tom, Jr.
更改为OMALLEYSMITHTOMJR
客户端要求这是一个Excel函数,否则我可以使用类似于replaceAll("[^a-zA-Z]", "").toUpperCase()
的快速Java程序轻松实现。在一整套SUBSTITUTE
函数之外,我似乎无法找到任何看起来像现成函数的东西 - 这似乎只有每个单元格一个。
如果这是我需要的话,我对开发自定义宏的能力不是非常流畅。
答案 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并根据需要将其粘贴到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”)