我已经阅读了一些主题,解释了其中一个可行的方法,但效果会非常慢。解释如下:
https://www.extendoffice.com/documents/excel/651-excel-remove-non-numeric-characters.html
它涉及遍历范围中的每个单元格,然后遍历字段中的字符,如果它们与[0-9]
不匹配则删除它们。我想知道是否还有其他任何更有效的建议。
我想到的是将单元格内容加载到数组中,迭代它,并将每个条目拆分成自己的数组以进行迭代。
答案 0 :(得分:2)
无需 VBA 或循环。 excel 公式可以达到您想要的效果。
=NPV(-0.9,,IFERROR(MID(A1,1+LEN(A1)-ROW(OFFSET(A$1,,,LEN(A1))),1)%,""))
这是一个数组公式。您必须按 Ctrl + Shift + Enter
解释:
每个字词乘以(1+rate)^n
的倒数,其中n
是系列中的nth
字词。
通过使用不同的费率值,我们可以得到不同的结果。在这种情况下,使用-0.9
会向我们提供1 + rate = 1 + -0.9 = 0.1
。
Result: {0.1;0.01;0.001;0.0001;0.00001}
Inverse of above: {10;100;1000;10000;100000}
Also NPV skips text values which contributes to the above
免责声明:我没有想出这个公式。我很久以前就看过这个公式,只是爱上了它。从那以后它就成了我数据库的一部分。
答案 1 :(得分:2)
对于VBA方面(注意循环),我决定满足自己对几种不同方法的性能的好奇心。所有这些都将范围拉入阵列并在其中进行处理。由于读取和写入单个单元格值的开销,链接的文章将被任何中的速度所扼杀。
对于第一种方法,我优化了linked article" a bit"中的代码:
Private Sub MidMethod(values() As Variant)
Dim r As Long, c As Long, i As Long
Dim temp As String, output As String
For r = LBound(values, 1) To UBound(values, 1)
For c = LBound(values, 2) To UBound(values, 2)
output = vbNullString
For i = 1 To Len(values(r, c))
temp = Mid$(values(r, c), i, 1)
If temp Like "[0-9]" Then
output = output & temp
End If
Next
values(r, c) = output
Next
Next
End Sub
对于我使用RegExp.Replace
的第二种方法:
Private Sub RegexMethod(values() As Variant)
Dim r As Long, c As Long, i As Long
With New RegExp
.Pattern = "[^0-9]"
.MultiLine = True
.Global = True
For r = LBound(values, 1) To UBound(values, 1)
For c = LBound(values, 2) To UBound(values, 2)
values(r, c) = .Replace(values(r, c), vbNullString)
Next
Next
End With
End Sub
最后,对于最后一种方法,我使用了Byte
数组:
Private Sub ByteArrayMethod(values() As Variant)
Dim r As Long, c As Long, i As Long
Dim chars() As Byte
For r = LBound(values, 1) To UBound(values, 1)
For c = LBound(values, 2) To UBound(values, 2)
chars = values(r, c)
values(r, c) = vbNullString
For i = LBound(chars) To UBound(chars) Step 2
If chars(i) > 47 And chars(i) < 58 Then
values(r, c) = values(r, c) & Chr$(chars(i))
End If
Next
Next
Next
End Sub
然后我使用此代码对1000个单元格进行基准测试,每个单元格包含25个字母和数字的随机混合:
Private Sub Benchmark()
Dim data() As Variant, start As Double, i As Long
start = Timer
For i = 1 To 5000
data = ActiveSheet.Range("A1:J100").Value
MidMethod data
Next
Debug.Print "Mid: " & Timer - start
start = Timer
For i = 1 To 5000
data = ActiveSheet.Range("A1:J100").Value
RegexMethod data
Next
Debug.Print "Regex: " & Timer - start
start = Timer
For i = 1 To 5000
data = ActiveSheet.Range("A1:J100").Value
ByteArrayMethod data
Next
Debug.Print "Byte(): " & Timer - start
End Sub
结果并非令人惊讶 - Regex方法 到目前为止 最快(但它们都不是我所称的&# 34;快速&#34):
Mid: 24.3359375
Regex: 8.31640625
Byte(): 22.5625
请注意,我不知道这与@ SiddharthRout的酷公式方法相比如何,因为我无法通过我的测试工具运行它。 www.extendoffice.com代码也可能仍在运行,所以我没有测试它。
答案 2 :(得分:0)
使用正则表达式(您需要在工具参考下的Microsoft VBScript正则表达式库5.5):
Public Function GetNumericValue(range)
Set myRegExp = New RegExp
myRegExp.IgnoreCase = True
myRegExp.Global = True
myRegExp.Pattern = "[\D]"
GetNumericValue = myRegExp.Replace(range.value, "")
End Function