看一下这个属性(假设你在第一张工作表上有一个表):
Application.Sheets(1).ListObjects(1).name
此属性包含多少个字符?好吧,在测试了几个字符串后,我得出的结论是255,任何超过255个字符的字符串都会导致错误:
运行时错误5 - 无效的过程调用或争论
看看这个属性:
Application.Sheets(1).ListObjects(1).Summary
此属性包含多少个字符?再次,测试几个字符串,你会得到一个大约50,000的数字,你设置得更高并得到相同的错误,除非在这种情况下excel有时会崩溃或吐出不同的错误(多次尝试后):
Dim i As Integer
Dim a As String
For i = 1 To 5001
a = a & "abcdefghih"
Next i
Application.Sheets(1).ListObjects(1).Summary = a
方法"摘要"对象' ListObject'失败
这种"隐藏"角色限制在所有地方出现(here,here,less specifically here,and so classically here),并且它们似乎无法在任何地方记录,例如,看看ListObject.Name的页面,没有注意到你可以在该变量中存储多少个字符......
那么有更好的方法来确定这个吗?您在属性中设置的字符串是否存储在某个固定长度的字符串中,可以访问它以确定它们的最大长度,或者是否可以使用其他形式的文档来获取此信息?
在标准VBA对象中的大多数字符串上设置的这些字符限制很奇怪,我想知道他们的目的是什么,为什么设计师选择限制" ListObjects.name"到255个字符,这是否是一个任意的默认限制或是否是一个有意识的决定。我相信标准的字符串长度是this,我想知道为什么偏离这个标准。
总结我在上面提出的观点,并将这个问题浓缩成一句话:
是否有一种通用的方法来确定可以在对象属性中设置的字符串的最大长度,而无需首先通过为其提供另一个值并忽略错误/检查来测试该字符串的属性字符截断?
答案 0 :(得分:1)
首先,如果您打算存储关于对象的元信息,您可以使用CustomDocumentProperties
。你可以找到关于它们的使用here和here以及Chip Pearson here的一些不错包装的例子。
由于它们的长度仍然非常有限(255个字符)(感谢指出!),最好的解决方案可能是使用CustomXMLParts
ActiveWorkbook.Sheets(1).Name
。然而,困难的部分是使用VBA构建正确的XML,但如果添加对 Microsoft XML 的引用,则可能并非不可能。
但是,为了提供有关字符串属性最大长度的问题的一些帮助,这里有一个测试设置,您可以使用(相对)快速找到任意属性的这些限制。
只需将第19行的TestMaxStringLengthOfProperty()
替换为您要测试的媒体资源,然后运行 Option Explicit
Const PRINT_STEPS = True ' If True, calculation steps will be written to Debug.Print
Private Function LengthWorks(ByVal iLengthToTest As Long) As Boolean
Dim testString As String
testString = String(iLengthToTest, "#") ' Build string with desired length
' Note: The String() method failed for different maximum string lengths possibly
' depending on available memory or other factors. You can test the current
' limit for your setup by putting the string assignment in the test space.
' In my tests I found maximum values around 1073311725 to still work.
On Error Resume Next
' ---------------------------------------------------------------------------------
' Start of the Test Space - put the method/property you want to test below here
ActiveWorkbook.Sheets(1).Name = testString
' End of the Test Space - put the method/property you want to test above here
' ---------------------------------------------------------------------------------
LengthWorks = Err.Number = 0
On Error GoTo 0
End Function
Private Sub TestMaxStringLengthOfProperty()
Const MAX_LENGTH As Long = 1000000000 ' Default: 1000000000
Const MAXIMUM_STEPS = 100 ' Exit loop after this many tries, at most
' Initialize variables for check loop
Dim currentLength As Long
Dim lowerBoundary As Long: lowerBoundary = 0
Dim upperBoundary As Long: upperBoundary = MAX_LENGTH
Dim currentStep As Long: currentStep = 0
While True ' Infinite loop, will exit sub directly
currentStep = currentStep + 1
If currentStep > MAXIMUM_STEPS Then
Debug.Print "Exiting because maximum number of steps (" & _
CStr(MAXIMUM_STEPS) & _
") was reached. Last working length was: " & _
CStr(lowerBoundary)
Exit Sub
End If
' Test the upper boundary first, if this succeeds we don't need to continue search
If LengthWorks(upperBoundary) Then
' We have a winner! :)
Debug.Print "Method/property works with the following maximum length: " & _
upperBoundary & vbCrLf & _
"(If this matches MAX_LENGTH (" & _
MAX_LENGTH & "), " & _
"consider increasing it to find the actual limit.)" & _
vbCrLf & vbCrLf & _
"Computation took " & currentStep & " steps"
Exit Sub
Else
' Upper boundary must be at least one less
upperBoundary = upperBoundary - 1
PrintStep upperBoundary + 1, "failed", lowerBoundary, upperBoundary, MAX_LENGTH
End If
' Approximately halve test length
currentLength = lowerBoundary + ((upperBoundary - lowerBoundary) \ 2)
' "\" is integer division (http://mathworld.wolfram.com/IntegerDivision.html)
' Using `left + ((right - left) \ 2)` is the default way to avoid overflows
' when calculating the midpoint for our binary search
' (see: https://en.wikipedia.org/w/index.php?title=Binary_search_algorithm&
' oldid=809435933#Implementation_issues)
If LengthWorks(currentLength) Then
' If test was successful, increase lower boundary for next step
lowerBoundary = currentLength + 1
PrintStep currentLength, "worked", lowerBoundary, upperBoundary, MAX_LENGTH
Else
' If not, set new upper boundary
upperBoundary = currentLength - 1
PrintStep currentLength, "failed", lowerBoundary, upperBoundary, MAX_LENGTH
End If
Wend
End Sub
Private Sub PrintStep(ByVal iCurrentValue As Long, _
ByVal iWorkedFailed As String, _
ByVal iNewLowerBoundary As Long, _
ByVal iNewUpperBoundary As Long, _
ByVal iMaximumTestValue As Long)
If PRINT_STEPS Then
Debug.Print Format(iCurrentValue, String(Len(CStr(iMaximumTestValue)), "0")) & _
" " & iWorkedFailed & " - New boundaries: l: " & _
iNewLowerBoundary & " u: " & iNewUpperBoundary
End If
End Sub
:
10.0.2.2
答案 1 :(得分:-3)
简短的回答是否定的。
此致,Zack Barresse