11

Take a look at this property(Given you have a table on the first worksheet):

Application.Sheets(1).ListObjects(1).name

How many characters can this property contain? Well, after testing out a few strings I've come to the conclusion that its 255, any string with more than 255 characters causes an error to be thrown:

Run-Time Error 5 - Invalid procedure call or arguement

Take a look at this property:

Application.Sheets(1).ListObjects(1).Summary

How many characters can this property contain? Again, test several strings and you'll come out with a number that's around 50,000, You set it any higher and you get the same error, except in this case excel will sometimes crash or spit out a different error(after multiple attempts):

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

Method "Summary" of object 'ListObject' failed

This sort of "hidden" character limit comes up all over the place(here, here, less specifically here, and so classically here), and it doesn't seem like they're documented anywhere, for example take a look at the page for ListObject.Name, its not noted how many characters you can store in that variable...

So is there a better way to determine this? Are the strings you are setting in properties being stored in a fixed length string somewhere that can be accessed to determine what their maximum length is, or is there some other form of documentation that can be leveraged in order to obtain this information?

It strikes me as odd these character limits that are set on most strings within standard VBA objects, I wonder what their purpose is, why the designers choose to limit "ListObjects.name" to 255 characters and whether that was an arbitrary default limit or whether that was a conscious decision that was made. I believe that the standard string length is this, I wonder why the deviation from this standard.

To summarize the points I've made above and to condense this question into one sentence:

Is there a generic way to determine the maximum length of a string that can be set within an object's property, without first testing that string's property by giving it another value and ignoring errors/checking for character truncation?

David Rogers
  • 2,284
  • 2
  • 30
  • 68
  • I doubt there is such method. The general consensus is that if you need to ask this question, you are doing something wrong, because during normal operation you do not come anywhere close the limits. A proper source of Excel limits would be https://support.office.com/en-us/article/Excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3, but it does not specify the particular ones you mention. The `Name` limit is not surprising though because there is a limit of 255 characters for VBA variable names. – GSerg Apr 12 '16 at 22:22
  • I also doubt this is possible through code (other than checking for exceptions like you're basically doing). The workaround solution would be to [suggest changes to the documentation](https://github.com/OfficeDev/VBA-content) to add the method and property limits when you run across them. – Comintern Apr 12 '16 at 22:26
  • @GSerg, Yeah, your probably right there no way to do this, but I think there's certainly value in being able to hijack properties of objects such as tables/charts/embedded objects/etc to store related data in which ever format you choose(XML/JSON/CSV), probably just have to go about that another way :( I'm sure this is not what the designers thought the properties would be used for, though it still makes me wonder why they would enforce such limits(as they differ for each string), anyways its always good to dream... – David Rogers Apr 12 '16 at 22:34
  • Would looking up the methods online be an answer? https://msdn.microsoft.com/en-us/library/aa445183(v=vs.60).aspx says "An object's Name property must start with a letter and can be a maximum of 40 characters"? Or are you wanting a way to do this in the coding environment, not Google? – BruceWayne Apr 12 '16 at 22:39
  • 1
    @Comintern This really strikes me as a systematic issue with VBA as a language and office as a platform, Designers add limits and then don't document them and provide no way, other than by hand, to find those limits they've imposed. The real systematic solution to this issue is that I suggest updates to every MSDN VBA page for every string in every object(because I'm pretty sure most of them have a limit, though that could be contested), and that's only after testing each property by hand... That will never happen – David Rogers Apr 12 '16 at 22:41
  • @BruceWayne For that specific example you have provided a very good answer, unfortunately documentation providing the maximum string length for a object's string is rarely available(though that my be a matter of opinion) I'm looking for a way this can be determined if documentation is not available(like for the first example I provide) – David Rogers Apr 12 '16 at 22:45
  • @Dave13s - Well, the only real alternative I can think of is to start disassembling the Excel executables and libraries, run some code analysis tools on them, and see if you can find the buffer overrun checks in there. This really isn't something that is exposed to COM - an object doesn't have a "schema" you can examine. It seems much more reasonable to check the documentation, if it isn't there, test it, then pass it forward to the next person by improving the documentation. – Comintern Apr 12 '16 at 22:51
  • Good question but I wonder why you might want a name above 255 characters? – Absinthe Sep 09 '16 at 19:40
  • @Absinthe For example, putting XML or JSON data in a field, there are other ways to go about this, but it may be convenient to store data attached to an object by hijacking that objects built-in properties and using them to store data/information about that object. – David Rogers Sep 09 '16 at 20:19

2 Answers2

1

First of all, if your intention is to store meta information about objects, you could maybe make use of CustomDocumentProperties. You can find examples on their usage here and here and some nice wrappers by Chip Pearson here.
Since they are still very limited (255 chars) in length (thanks for pointing that out!), the best solution might be to use CustomXMLParts like described here. The hard part would then be building correct XML using VBA, but maybe not impossible, if you add a reference to Microsoft XML.

But to provide some help with your question concerning maximum lengths for string properties, too, here is a test setup you can use to (relatively) quickly find these limits for arbitrary properties. Just replace the ActiveWorkbook.Sheets(1).Name on line 19 with the property you want to test and run 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
Community
  • 1
  • 1
Marcus Mangelsdorf
  • 2,198
  • 1
  • 27
  • 35
  • CustomDocumentProperties are [very limited in length](https://stackoverflow.com/questions/42120915/how-to-overcome-custom-document-property-size-limit), or course you can get around that by [splitting your data into pieces](https://social.msdn.microsoft.com/Forums/office/en-US/49f2b496-ed25-4c91-946e-3b1c3684f677/custom-document-properties-is-there-a-limit-to-how-many-can-be-created?forum=exceldev) but again that is a very inelegant solution. Of course I long ago came up with a different workaround. The point of my question is that no matter the workaround, it always a sub-optimal solution :( – David Rogers Nov 10 '17 at 15:27
  • Of course I think your answer is the best attempt at solving this so far, I'll have to do some testing with it but as far as I can tell this is probably the best method we're every going to get(I would love if someone proved me wrong). – David Rogers Nov 10 '17 at 15:30
  • Oh, I didn't know about the 255 chars length limit for custom document properties. But the [suggested solution using `Custom XML Parts`](https://stackoverflow.com/a/42121489/2822719) seems perfect to store meta information alongside the document, albeit handling XML with VBA code might be a bit hard... - still gonna update my answer with a reference to this possibility :) – Marcus Mangelsdorf Nov 12 '17 at 14:42
-3

The short answer is no.

Regards, Zack Barresse

Zack Barresse
  • 219
  • 1
  • 8
  • 4
    How about the long answer? A simple "no" is not very helpful. – elixenide Sep 29 '16 at 20:11
  • I gave a longer answer. A Mr. Ed Cottrell (http://stackoverflow.com/users/2057919/ed-cottrell) deleted it for some reason, and didn't give any explanation. Suffice to say there's no way to get that because it wasn't put in the application. The "why", of course, is a different story. For everyone giving down votes to my answer above, I understand you think it's not helpful, but the moderator has tied my hands. Apologies for brevity. – Zack Barresse Sep 30 '16 at 23:42
  • 2
    Actually, your first "answer" was merely an insulting rant. It didn't offer any real guidance to OP, so I deleted it. This one is better, but only because it's not as rude. It's not very helpful, but it at least doesn't violate the site's ["Be Nice"](http://stackoverflow.com/help/be-nice) policy. I would suggest you read about [answer] questions here. – elixenide Sep 30 '16 at 23:47