Excel 从列索引获取单元地址列字母和从列字母获取列索引的最佳方法
通常,公认的方法是执行以下操作 数字与字母 字母对数字 但是,这两种方法都不是特别理想的,因为在每种情况下,我们都要创建一个对象,然后对该对象调用属性访问器。有更快的方法吗?总结 要认识到的核心是Excel中使用的字母系统也被称为Base26Excel 从列索引获取单元地址列字母和从列字母获取列索引的最佳方法,excel,vba,indexing,letter,Excel,Vba,Indexing,Letter,通常,公认的方法是执行以下操作 数字与字母 字母对数字 但是,这两种方法都不是特别理想的,因为在每种情况下,我们都要创建一个对象,然后对该对象调用属性访问器。有更快的方法吗?总结 要认识到的核心是Excel中使用的字母系统也被称为Base26NumberToLetter从十进制编码到Base26,而letttonumber从Base26解码到十进制 基本转换可以通过简单的循环和 Function base26Encode(ByVal iDecimal As Long) As String i
NumberToLetter
从十进制编码到Base26,而letttonumber
从Base26解码到十进制
基本转换可以通过简单的循环和
Function base26Encode(ByVal iDecimal As Long) As String
if iDecimal <= 0 then Call Err.Raise(5, "base26Encode" ,"Argument cannot be less than 0")
if iDecimal >= 16384 then Call Err.Raise(5, "base26Encode" ,"There are only 16384 columns in a spreadsheet, thus this function is limited to this number.")
Dim s As String: s = ""
Do
Dim v As Long
v = (iDecimal - 1) Mod 26 + 1
iDecimal = (iDecimal - v) / 26
s = Chr(v + 64) & s
Loop Until iDecimal = 0
base26Encode = s
End Function
Function base26Decode(ByVal sBase26 As String) As Long
sBase26 = UCase(sBase26)
Dim sum As Long: sum = 0
Dim iRefLen As Long: iRefLen = Len(sBase26)
For i = iRefLen To 1 Step -1
sum = sum + (Asc((Mid(sBase26, i))) - 64) * 26 ^ (iRefLen - i)
Next
base26Decode = sum
End Function
结果如下:
Sub testPerf()
Dim cMax As Long: cMax = 16384
With stdPerformance.Measure("Encode Original")
For i = 1 To cMax
Call numberToLetter(i)
Next
End With
With stdPerformance.Measure("Encode Optimal")
For i = 1 To cMax
Call base26Encode(i)
Next
End With
With stdPerformance.Measure("Decode Original")
For i = 1 To cMax
Call letterToNumber(base26Encode(i))
Next
End With
With stdPerformance.Measure("Decode Optimal")
For i = 1 To cMax
Call base26Decode(base26Encode(i))
Next
End With
End Sub
Encode Original: 78 ms
Encode Optimal: 31 ms
Decode Original: 172 ms
Decode Optimal: 63 ms
如图所示,这是一种稍快的方法(快2-3倍)。但是,我很惊讶对象创建和属性访问的表现如此出色。您没有创建对象-在这两种情况下,单元格都已经存在。如果您确实需要在列字母和索引之间进行映射,那么这对我来说似乎很好:如果您尝试映射不存在的列,那么它将出错。@TimWilliams我非常确定
范围(…)
amd单元格(…)
将创建一个对象,或者更确切地说,我很确定,没有为您打开的每个电子表格创建一些2147483647
对象(整个电子表格中的每个单元格一个对象),因为这会非常慢。好吧,公平点…而不是v=iDecimal Mod 26
&如果v=0,那么v=26
使用v=(iDecimal-1)Mod 26+1
速度相当但代码更清晰。此外,如果您将0传递到函数中,您会得到一个奇怪的字符串,因此对此进行错误检查是很好的。
Sub testPerf()
Dim cMax As Long: cMax = 16384
With stdPerformance.Measure("Encode Original")
For i = 1 To cMax
Call numberToLetter(i)
Next
End With
With stdPerformance.Measure("Encode Optimal")
For i = 1 To cMax
Call base26Encode(i)
Next
End With
With stdPerformance.Measure("Decode Original")
For i = 1 To cMax
Call letterToNumber(base26Encode(i))
Next
End With
With stdPerformance.Measure("Decode Optimal")
For i = 1 To cMax
Call base26Decode(base26Encode(i))
Next
End With
End Sub
Encode Original: 78 ms
Encode Optimal: 31 ms
Decode Original: 172 ms
Decode Optimal: 63 ms