Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

String builder question 2

Status
Not open for further replies.

PeteG

Programmer
Feb 23, 2001
144
0
0
GB
Hi,
Does VBA have an object or function similar to StringBuilder in java or StringBuffer in c#? Basically, some way, in code, to append to a String rather than multiple "stringa = stringa + stringb" statements? Come to think of it, does anybody know if VBA has the same memory behaviour which makes these java/c# objects worthwhile, if not then I guess there would not be much point in having a StringBuilder-style object?
Thanks
Pete
 
What's wrong with "stringa = stringa & stringb" ?

Hope This Helps, PH.
FAQ219-2884
FAQ181-2886
 
In java/c#, using StringBuilder/Buffer is a more efficient use of memory; one object created as opposed to creating multiple new String objects. I was wondering if the same memory behaviour exists with VBA and, if so, whether there is a ready-made solution to deal with it.
Thanks.
 
not as far as I know

Rgds, Geoff

We could learn a lot from crayons. Some are sharp, some are pretty and some are dull. Some have weird names and all are different colours but they all live in the same box.

Please read FAQ222-2244 before you ask a question
 
OK, many thanks for the replies
 

you could just use one variable

string a = "whatever"
stringa = stringa & " Whatever else"

etc

just a thought....
 
one object created as opposed to creating multiple new String objects."

But appending actual strings does not create new objects. Appending different objects means there ARE differnt objects.

stringA = atringA & "yadda" still is one object

stringA = stringA & stringB yes is two objects, but that is because there are two objects.

I do not know StringBuilder. How does it append using one object?



faq219-2884

Gerry
My paintings and sculpture
 
Typically, like this:
Code:
StringBuilder sb = new Stringbuilder()
sb.append("This text")
sb.append("and then this")

There are other methods available for further manipulation and the string value could then be returned using sb.toString()

In java, if you coded:
Code:
stringa = stringa + "This text"
stringa = stringa + "and then this"
you would be creating a new String object on each line, albeit the superfluous ones would be garbage-collected at some point. It's just not very efficient when there is something better.

I've been away from VBA for quite some time - just getting back into it now. However, I think it's safe to say that VBA String and java String are two very different things and there is simply no need for a StringBuilder-type object in VBA.
 
>But appending actual strings does not create new objects

I'm afraid that it does. VB and VBA allocate a new area of memory big enough for the concatenated string, perform the concatenation into this area of memory, and then changes the pointer (that a VB string variable represents) to point to it.

In fact, whenever you modify a string a new block of memory is allocated and the modified string is created in that new block, and the pointer then changed. It is one of the reasons that VB(A) string operations are relatively slow.

(Note that the String object in .NET does essentially the same thing)

This could should help illustrate:
Code:
[blue]

    Dim string1 As String
      
    ' Demonstrate with append
    string1 = "Hello"
    Debug.Print VarPtr(ByVal string1)
    string1 = string1 + " there"
    Debug.Print VarPtr(ByVal string1)
    
    Debug.Print
    
    ' Demonstrate with an operation that doesn't even modify the source string
    string1 = "Hello"
    Debug.Print VarPtr(ByVal string1)
    string1 = Left$(string1, Len(string1)) ' we won't even modify it ...
    Debug.Print VarPtr(ByVal string1)[/blue]

Java's (and .NET's) StringBuilder class work differently. They have a capacity, which is simply extended if the string held in them grows larger than that capacity. In general (but not always), this makes the StringNuilder more efficient that traditional string operations.
 
Love this place. I like to learn things.

If you could, could you explain what the numbers mean?
Code:
    string1 = "Hello"
    Debug.Print VarPtr(ByVal string1)
    string1 = Left$(string1, Len(string1))
    Debug.Print VarPtr(ByVal string1)

produced:

2271980 (first Debug.Print)
54763292 (second debug.Print)

On a second go-round:

55377620 (first debug.Print)
2271980 (second Debug.Print)

Why are the numbers so different? One 8 digits, one 7 digits. Also, if I remove the ByVal:
Code:
[code]    string1 = "Hello"
    Debug.Print VarPtr(string1)
    string1 = Left$(string1, Len(string1))
    Debug.Print VarPtr(ByVal string1)

I get:

1241716
1922340

all 7 digits. Further, if I execute the Sub four times in a row, I get:

1241464
1901148

1241464
54749204

1241464
54595348

1241464
1922340

The Sub is executed and terminated. I would think the address of that variable is cleared. Yet notice that the 1241464 persists. What IS it? What is VarPtr(string1) - without the ByVal?

faq219-2884

Gerry
My paintings and sculpture
 
Ok.

Step 1.

All variables in VB(A) are really just pointers to the memory location where the actual value is held.

So if we

Dim l as long
l = 15

then what actually happens is that VB(A) allocates 4 bytes of memory to store a long, and l is actually a pointer to that memory location. Of course, normally in VB(A) we never get to see the pointer. What VarPtr does is allow us to see the value of that pointer:
Code:
[blue]Public Sub Example3()
    Dim l As Long
    l = 15
    MsgBox "The 4 bytes starting at memory location " & VarPtr(l) & " contain the long value " & l
End Sub[/blue]

I could go to the trouble of using the API to peek into that memory location top prove they contain what I say, but just trust me on this. In fact:
Code:
[blue]Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Public Sub Example3()
    Dim l As Long
    Dim lcontents As Long
    
    l = 15
    CopyMemory lresult, ByVal VarPtr(l), 4
    MsgBox "The 4 bytes starting at memory location " & VarPtr(l) & " contain the long value " & lcontents
End Sub[/blue]

Right, Step 2

Strings are a bit different because (and I'm simplifying slightly) a VB string is a actually a pointer to a string (this is known as a BSTR). So a VB string variable is a pointer to a pointer. And it is that second pointer that we need access to - which is why we need ByVal; without it we simply get the memory address of where the second pointer is stored. I could have used [blue]StrPtr(string1)[/blue] instead to achieve the same result, which might have saved some initiali complication but then made it difficult to do a comparative illustration against other variables.

You might also find some more details of VB strings in thread222-558844
 
Thank you. That was very educational and (hopefully) useful for something at some point. I like to understand things (even if somewhat marginally), and that helped to expand some awareness. I appreciate that. That, and your patience in explaining, AND the link to the other thread.

Have a star.

faq219-2884

Gerry
My paintings and sculpture
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top