简体   繁体   中英

Excel VBA Append to TextBox is Slow

I've got a user-form that generates a large amount of text and puts it into a Textbox.

I have the following function to append the next line of text to the textbox:

Sub AddLineToSQL(sLine As String)

    frmSQL.txtSQL.Value = frmSQL.txtSQL.Value & sLine & vbCr

End Sub

When adding several hundred lines of text it takes a while to process (up to 20 seconds).

The problem with this is that there is the possibility of adding more than a thousand lines of text.

We have an old form that does basically the same thing, but I'm trying to create a cleaner user experience. the old form wrote the text to a worksheet, and it seems to work much quicker than appending to the textbox.

Is there a More efficient way to append text to a textbox than what I have above?

should I just do what the old form did and write lines to a worksheet?

Thanks,

Mark

Do not appending line by line to the TextBox. Instead do concatenating a String with all lines and then set that String as the TextBox value.

Sub test()
 Dim sTxtSQL As String

 For i = 1 To 5000
  sTxtSQL = sTxtSQL & "This is row " & i & vbCrLf
 Next

 frmSQL.txtSQL.Value = sTxtSQL
 frmSQL.Show
End Sub

should your amount of text be veeery large then you could use this class:

' Class: StringBuilder
' from http://stackoverflow.com/questions/1070863/hidden-features-of-vba
Option Explicit

Private Const initialLength As Long = 32

Private totalLength As Long  ' Length of the buffer
Private curLength As Long    ' Length of the string value within the buffer
Private buffer As String     ' The buffer

Private Sub Class_Initialize()
  ' We set the buffer up to it's initial size and the string value ""
  totalLength = initialLength
  buffer = Space(totalLength)
  curLength = 0
End Sub

Public Sub Append(Text As String)

  Dim incLen As Long ' The length that the value will be increased by
  Dim newLen As Long ' The length of the value after being appended
  incLen = Len(Text)
  newLen = curLength + incLen

  ' Will the new value fit in the remaining free space within the current buffer
  If newLen <= totalLength Then
    ' Buffer has room so just insert the new value
    Mid(buffer, curLength + 1, incLen) = Text
  Else
    ' Buffer does not have enough room so
    ' first calculate the new buffer size by doubling until its big enough
    ' then build the new buffer
    While totalLength < newLen
      totalLength = totalLength + totalLength
    Wend
    buffer = Left(buffer, curLength) & Text & Space(totalLength - newLen)
  End If
  curLength = newLen
End Sub

Public Property Get Length() As Integer
  Length = curLength
End Property

Public Property Get Text() As String
  Text = Left(buffer, curLength)
End Property

Public Sub Clear()
  totalLength = initialLength
  buffer = Space(totalLength)
  curLength = 0
End Sub

just place it in any Class Module and name it after "StringBuilder"

then you can test it similarly as per Axel answer:

Sub test()

Dim i As Long
Dim sb As StringBuilder
Dim sTxtSQL As String

Dim timeCount As Long

timeCount = Timer

Set sb = New StringBuilder
For i = 1 To 50000
  sb.Append "This is row " & CStr(i) & vbCrLf
Next i
sTxtSQL = sb.Text

MsgBox Timer - timeCount

frmSQL.txtSQL.Value = sTxtSQL
frmSQL.Show

End Sub

My test showed significant time reduction for "i" loops over 50k

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM