StringBuilder anstatt Array, da viel schneller
#1
Guten Tag

Ich wollte einen Test bauen, ob Zeilen- und Spalten Einträge schneller mit dem StringBuilder ausgelesen werden könnten als via Array bei vielen Datensätzen aus einzelnen Textdokumente (.txt-Dateien) in einer Excel-Tabelle. Doch ich scheitere wieder mal kläglich. Ich bekomme nur zwei Fragezeichen (??) und habe selber ein Fragezeichen. AppendLine scheint Excel-VBA so nicht zu kennen? Also wäre nur eine Spalte auslesbar bei mehreren Zeilen? Oder geht das auch irgendwie? Ich kann später immer noch im Array mit Split (vTab) die Spaltenwerte in ein weiteres Array umschreiben. 
Ich hoffe gespannt auf Vorschläge.
Grüsse
Stefan1

Code:
' ************************************************************

' Benötigt einen Verweis auf die Microsoft Forms 2.0 Objektlibrary

' ************************************************************



Private Function StringBuilderTest() As String
Dim oData As New DataObject
Dim sb As clsStringBuilder
Dim s As Variant
Dim i As Integer, iR As Integer
    Set sb = New clsStringBuilder
    For i = 1 To 1000
        'For iR = 1 To 500
            sb.Append ("Step " & i & vbCrLf)
        'Next
        'sb.Appendline()
    Next
    With oData
        .Clear
        .SetText sb.ToString
        .PutInClipboard
        .GetFromClipboard
        s = .GetText
        '.SetText ""
        '.PutInClipboard
    End With
    Set sb = Nothing
End Function
Antworten Top
#2
Wo ist dieser  Klasse ?
Code:
clsStringBuilder

Bitte lade eine Bespieldatei hoch.
Ein Array ist immer schneller.
Zum übersetzen von Excel Formeln:

http://dolf.trieschnigg.nl/excel/index.p...gids=en+de
Antworten Top
#3
Hallöchen,

schon die Verwendung einer Schleife kann darauf hindeuten, dass der entsprechende Code langsamer ist ...
.      \\\|///      Hoffe, geholfen zu haben.
       ( ô ô )      Grüße, André aus G in T  
  ooO-(_)-Ooo    (Excel 97-2019+365)
Antworten Top
#4
Und wozu das Clipboard wenn ein Variabele (sb.tostring) schon die ganze Text enthält ?
Zum übersetzen von Excel Formeln:

http://dolf.trieschnigg.nl/excel/index.p...gids=en+de
Antworten Top
#5
(27.05.2024, 09:13)snb schrieb: Und wozu das Clipboard wenn ein Variabele (sb.tostring) schon die ganze Text enthält ?

Lieber snb
Wie meinst Du das? Ich komme z.B. mit "s = ab.ToString" nicht an den Textinhalt ran, ausser ich übersehen hier etwas? Es müsste schon ein "Print 1# ab.ToString" sein oder eben via Clipboard? Excel VBA lässt da nicht viel anderes zu? Ausser einer temporären Lösung via eines zusammenfassenden Textfiles (.txt), dass man dann wieder als ganzes einliest (hier habe ich ein Bespiel im Internet gefunden, dass sogar schneller sein soll als die vielgepriesen rasche Array-Lösungen, doch es gefällt mir nicht so recht. Im Gegensatz zu einem Array soll also der StringBuilder wesentlich schneller sein, wenn auch mit Limitation (nach etwa 1000 Datensätze sollte man von vorne beginnen, wenn es noch mehr Daten gibt) bevor er in einen Überlauffehler läuft. Ich kenne das von einer ganzen Seite als .txt abspeichern und bin dort gegenüber einem Array deutlich schneller unterwegs. Ich möchte es ja gerne testen, ob es beim Laden der letzten Zeile aus einzelnen Textdateien auch so ist. So recht will es mir nicht gelingen. Der Clou ist eigentlich auf schnellstmögliche Art einmal die Daten zu sammeln. Meine bisherige Lösung ist dazu ein Array-Daten, die dann mit Split (Delimeter: Semikolom) und Anreicherung von Attributen ergänzt in einem Ruck auf die Tabelle gespielt wird. Das hoffe ich auch mit ClipBoard (ohne Transpose) auch tun zu können?
Gruss
Stefan1

Soeben entdeckt, dass für die neue Zeile auch folgendes gehen könnte:
sb.Append(Environment.NewLine);
Doch in Excel gibt es nur Environ(), dann doch eher:

- vbNewLine
- vbCrLf
- vbLf
Antworten Top
#6
Man sollte keinen Code 'finden' doch erstellen.
So liest man .txt:

Code:
With createobject("scripting.filesystemobject")
   msgbox .opentextfile("G:\OF\beispiel.txt").readall
end with

So integriert man .txt Dateien in directory G:\OF\
Code:
shell "cmd copy G:\OF\*.txt G:\alles.txt",0
und liest man das Ergebnis:
Code:
msgbox createobject("scripting.filesystemobject").opentextfile("G:\alles.txt").readall
Zum übersetzen von Excel Formeln:

http://dolf.trieschnigg.nl/excel/index.p...gids=en+de
Antworten Top
#7
Keine Ahnung, wozu man zum Auslesen einer Textdatei eine StringBuilder-Klasse benötigt.

Hier findet man zwei Versionen (CopyMemory bzw. Array) einer StringBuilder-Klasse
strings - A lightning-fast StringBuilder - Code Review Stack Exchange

Hier etwas zum Thema, auch wenn es um .Net geht
Verwenden der StringBuilder-Klasse in .NET - .NET | Microsoft Learn
Antworten Top
#8
Hallöchen Stefan,

irgendwie ist das etwas durcheinander, mal wird was (aus)gelesen, mal was geschrieben (print), wo ist da der rote Faden?

Also, wie snb schon schrieb, Du kannst den kompletten Text in einem Rutsch einlesen, gerne auch aus Smile und einer Variable zuweisen.
Da wären wir z.B. bei String.
Wenn Du den Text zeilenweise willst, sofern denn auch Zeilenvorschübe oder andere entsprechend bedeutungsvolle Trenner drin sind, dann tust Du den mit split in ein Array bringen
Nun hätten wir die Zeilen
Wenn Du auch noch die Spalten getrennt benötigst, dann splittest Du die Zeilen in "Zellen". Anhand der Zeilen kannst Du ein Array dimensionieren und dahinein packst Du die gesplitteten Zeilen.
Oder, Du nutzt hier mal ein Blatt und verwendest Text in Spalten.
Kommt auch darauf an, was Du mit den Daten machen willst.
.      \\\|///      Hoffe, geholfen zu haben.
       ( ô ô )      Grüße, André aus G in T  
  ooO-(_)-Ooo    (Excel 97-2019+365)
Antworten Top
#9
Oder
Tab Data, from Text


Code:
Workbooks.opentext
Zum übersetzen von Excel Formeln:

http://dolf.trieschnigg.nl/excel/index.p...gids=en+de
Antworten Top
#10
Guten Tag zusammen

Nun, es macht den Eindruck, dass ich mich verrannt habe. Doch was ich eigentlich möchte, ist möglichst schnell von >500 Textdateien (.txt) die letzte Zeile mit mehreren Spalten (Delimeter: Semikolom) auslesen und dann in eine Exceltabelle via Array hineinfügen. Heute werden mit FindFiles alle Dateinamen und Laufwerk ausgelesen (das geschieht sehr schnell, selbst wenn das 1000 Dateien wären), doch dann braucht es ewig bis bei jeder Textdatei die letzte Zeile ausgelesen und mit Split() in Spalten aufgetreten und in ein Array eingelesen ist. Ich habe gehofft eine schnellere Möglichkeit zu finden für diesen Vorgang. Doch ich wollte zum Verständnis quasi zuerst ein Prototyp bauen um die Funktion zu verstehen. Beim untenstehenden Code verstehe ich nach CopyMemory (wieder nicht die MS 64-bit Variante!) nicht, wie das "Memory" (Inhalt) wieder ausgelesen und in ein Tabellenblatt geschrieben werden kann.

Gruss
Stefan1

https://www.clever-excel-forum.de/Thread...-schneller

Code:
Option Compare Text
Option Explicit

Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByVal dst As Long, ByVal src As Long, ByVal Length As Long)

Private Const InitialCharCount As Long = 16
' Define members
Private mUBound As Long
Private mString() As Byte

Private Sub Class_Initialize()
    Clear
End Sub

Public Sub Clear()
    mUBound = -1
    ReDim mString(0 To InitialCharCount * 2 - 1) 'Each unicode character is 2 bytes
End Sub

Public Function Append(value As String) As StringBuilder
Dim NewUBound As Long
Dim CapacityUBound As Long
On Error GoTo Failed
    NewUBound = mUBound + LenB(value)

    If NewUBound > UBound(mString) Then
        CapacityUBound = UBound(mString) * 2 + 1
        If NewUBound > CapacityUBound Then CapacityUBound = NewUBound * 2 + 1
        ReDim Preserve mString(0 To CapacityUBound)
    End If
    CopyMemory VarPtr(mString(mUBound + 1)), StrPtr(value), LenB(value)

    mUBound = NewUBound
    Set Append = Me
    Exit Function

Failed:
    Stop
    Resume
End Function

Public Property Get Length() As Long
    Length = (mUBound + 1) / 2
End Property

Public Function ToString() As String
    ToString = Mid(mString, 1, Length)
End Function
Share
Follow
Antworten Top


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste