Discussion:
25.000 Datensätze aus einer Textdatei lesen VB .net 2005
(zu alt für eine Antwort)
Jörn Janz
2007-08-03 05:20:21 UTC
Permalink
Hallo NG,

ich muss beim Programmstart 25.000 Datensätze aus einer Textdatei
lesen.
Die Textdatei enthält 22 "Felder" und ca. 144 Zeichen pro Zeile.
Ich habe mit Array und ArrayList herumprobiert und die Datei ist
in unter einer Sekunde eingelesen und in die entsprechende Felder
aufgeteilt.

Jetzt zu meiner Frage. In den ersten 7 Zeichen der Zeile finde ich die
Artikelnummer. Die Artikelnummer möchte ich an ein Suchfeld binden.
Nett wäre eine "Autovervollständigung" wie z.B. in einer Combobox.
Wenn ich die Artikelnummer mit .Add hinzufüge benötigt das Programm
ca. 6 Sekunden für den Vorgang. Ich habe auch schon versucht mit
einer
ArrayList zu arbeiten und die ArrayList dann an die ComboBox zu binden
- dann dauert es noch länger.
Sind 6 Sekunden OK? Habt Ihr noch einen
Beschleunigungstip oder eine Idee für eine komfortable Suchmaske die
sich schneller
aufbauen lässt für mich?

Gruß - Jörn

'===================

Dim sr As System.IO.StreamReader = _
New System.IO.StreamReader("c:\Artikel.txt", _
System.Text.Encoding.GetEncoding("iso-8859-1"))


' Streamreader 1 um die Anzahl der Zeilen zu bestimmen und
' um auf ReDim und Preserve verzichten zu können
Dim row As String
' Zeilenweise lesen


Dim i As Integer = 0

Do
row = sr.ReadLine()
If IsNothing(row) Then Exit Do
i = i + 1
Loop
sr.Close()


Dim sr2 As System.IO.StreamReader = _
New System.IO.StreamReader("c:\Artikel.txt", _
System.Text.Encoding.GetEncoding("iso-8859-1"))


' Ich habe das Beispiel verkürzt - b hat später 22 Felder
Dim b(i, 2) As String
Dim x As Integer
Do
row = sr2.ReadLine()
If row <> Nothing Then
'Me.lbxAnzeige.Items.Add(row)

x = x + 1
b(x, 0) = i.ToString
b(x, 1) = Strings.Left(row.ToString, 7)
Me.cmbSuchen.Items.Add(b(x, 1))
b(x, 2) = Strings.Mid(row.ToString, 8, 3)

End If

Loop While row <> Nothing

sr2.Close()
'========
Alfred M.
2007-08-03 05:36:26 UTC
Permalink
Hallo Jörn,

hat sie ca. 144 Zeichen oder genau 144 Zeichen pro Zeile?
Also feste Satzlänge oder mit CRLF begrenzt?

Grüße Alfred M.


"J�rn Janz" <***@jrdrucksysteme.de> schrieb im Newsbeitrag news:***@w3g2000hsg.googlegroups.com...
Hallo NG,

ich muss beim Programmstart 25.000 Datensätze aus einer Textdatei
lesen.
Die Textdatei enthält 22 "Felder" und ca. 144 Zeichen pro Zeile.
Ich habe mit Array und ArrayList herumprobiert und die Datei ist
in unter einer Sekunde eingelesen und in die entsprechende Felder
aufgeteilt.

Jetzt zu meiner Frage. In den ersten 7 Zeichen der Zeile finde ich die
Artikelnummer. Die Artikelnummer möchte ich an ein Suchfeld binden.
Nett wäre eine "Autovervollständigung" wie z.B. in einer Combobox.
Wenn ich die Artikelnummer mit .Add hinzufüge benötigt das Programm
ca. 6 Sekunden für den Vorgang. Ich habe auch schon versucht mit
einer
ArrayList zu arbeiten und die ArrayList dann an die ComboBox zu binden
- dann dauert es noch länger.
Sind 6 Sekunden OK? Habt Ihr noch einen
Beschleunigungstip oder eine Idee für eine komfortable Suchmaske die
sich schneller
aufbauen lässt für mich?

Gruß - Jörn

'===================

Dim sr As System.IO.StreamReader = _
New System.IO.StreamReader("c:\Artikel.txt", _
System.Text.Encoding.GetEncoding("iso-8859-1"))


' Streamreader 1 um die Anzahl der Zeilen zu bestimmen und
' um auf ReDim und Preserve verzichten zu können
Dim row As String
' Zeilenweise lesen


Dim i As Integer = 0

Do
row = sr.ReadLine()
If IsNothing(row) Then Exit Do
i = i + 1
Loop
sr.Close()


Dim sr2 As System.IO.StreamReader = _
New System.IO.StreamReader("c:\Artikel.txt", _
System.Text.Encoding.GetEncoding("iso-8859-1"))


' Ich habe das Beispiel verkürzt - b hat später 22 Felder
Dim b(i, 2) As String
Dim x As Integer
Do
row = sr2.ReadLine()
If row <> Nothing Then
'Me.lbxAnzeige.Items.Add(row)

x = x + 1
b(x, 0) = i.ToString
b(x, 1) = Strings.Left(row.ToString, 7)
Me.cmbSuchen.Items.Add(b(x, 1))
b(x, 2) = Strings.Mid(row.ToString, 8, 3)

End If

Loop While row <> Nothing

sr2.Close()
'========
Jörn Janz
2007-08-03 07:56:53 UTC
Permalink
Hallo Alfred,

es sind genau 144 Zeichen pro Zeile mit einer festen Satzlänge. Die
Zeilen werden mit ";CRLF" abgeschlossen.
Beispiel:
1234567Schraube 47,90 ..... ;CRLF
Feld 1 = 7 Zeichen
Feld 2 = 12 Zeichen
Feld 3 = 5 Zeichen

Ich habe die Aktualisierung der ComboBox shon mit
"me.cmbSuchen.BeginUpdate()" abgeschaltet.
Bringt leider auch nix.

Eine Datenbank ist mir zu aufwendig. Die Datensätze werden nicht
bearbeitet bzw. geändert oder ergänzt. Es soll nur nach
der Artikelnummer gesucht werden können. Der Datensatz soll dann
angezeigt werden und dann füge ich manuell die
Auftragsnummer ein und drucke dann den Datenstaz + Auftragsnummer aus.
Alle 2 Wochen wird von einer anderen Anwendung
die TXT erneuert.

Gruß - Jörn
Steffan Schramm
2007-08-03 08:17:38 UTC
Permalink
Post by Jörn Janz
Eine Datenbank ist mir zu aufwendig. Die Datensätze werden nicht
bearbeitet bzw. geändert oder ergänzt. Es soll nur nach
der Artikelnummer gesucht werden können.
Ohne Index lässt sich nix beschleunigen und Indexe kennen nur
SortedList, Hashtable und Datenbanken.

OK, Du kannst einen schnelleren Rechner kaufen mit schnellere Platte
und schnelleren Controller und schnelleren Bus-Chipsatz!
;-)

Bei einer SortedList, Hashtable nimmt man die Artikelnummer als Key
und legt für den Value ein Klasse an, die man auch gleich an die
Textboxen binden kann - Stichwort Databindung.

Eigentlich eine nette kleine Aufgabe, überweise mir einen Betrag und
ich mache Dir das ;-)
Jörn Janz
2007-08-03 08:22:34 UTC
Permalink
Hallo,

noch ein paar Anmerkungen zu meinem Problem:
Ich habe leider keinen Einfluss auf die Datenhaltung. Die Artikeldaten
werden aus einer alten Anwendung alle 2 Wochen
in eine Textdatei geschrieben. Beim Start des VB .net Programm sollen
die Daten nur einmal eingelesen werden.
Dann wird einfach nur gesucht und angezeigt. Die Anwendung läuft dann
den ganzen Tag schnell. Auch die Textdatei ist schnell eingelesen und
steht in unter einer Sekunde bereit zur Verarbeitung.
Mein Problem ist der Aufbau eines "netten" Suchdialogs. Wenn ich in
das Suchfeld "123" eingebe dann würde ich gerne alle Datensätze die
mit "123" beginnen angezeigt bekommen. So wie z.B. in einer ComboBox.

Vielen Dank für Eure Antworten.

Gruß - Jörn
Jörn Janz
2007-08-03 08:22:42 UTC
Permalink
Hallo,

noch ein paar Anmerkungen zu meinem Problem:
Ich habe leider keinen Einfluss auf die Datenhaltung. Die Artikeldaten
werden aus einer alten Anwendung alle 2 Wochen
in eine Textdatei geschrieben. Beim Start des VB .net Programm sollen
die Daten nur einmal eingelesen werden.
Dann wird einfach nur gesucht und angezeigt. Die Anwendung läuft dann
den ganzen Tag schnell. Auch die Textdatei ist schnell eingelesen und
steht in unter einer Sekunde bereit zur Verarbeitung.
Mein Problem ist der Aufbau eines "netten" Suchdialogs. Wenn ich in
das Suchfeld "123" eingebe dann würde ich gerne alle Datensätze die
mit "123" beginnen angezeigt bekommen. So wie z.B. in einer ComboBox.

Vielen Dank für Eure Antworten.

Gruß - Jörn
Peter Götz
2007-08-03 09:00:40 UTC
Permalink
Hallo Jörn,
Post by Jörn Janz
Ich habe leider keinen Einfluss auf die Datenhaltung.
Die Artikeldaten werden aus einer alten Anwendung
alle 2 Wochen in eine Textdatei geschrieben. Beim
Start des VB .net Programm sollen die Daten nur
einmal eingelesen werden.
Es spricht nichts dagegen, diese Daten in eine mit
entsprechenden Feldern ausgestattete DataTable
einzulesen und eine DataView zu dieser DataTable
zu erstellen.
Damit stehen Dir dann alle Such- und Filterfunktionen
von DataTable und DataView zur Verfügung. Die Suche
nach einem oder mehreren bestimmten Datensätzen ist
dann äusserst simpel.
Post by Jörn Janz
Dann wird einfach nur gesucht und angezeigt.
Die Anwendung läuft dann den ganzen Tag schnell.
Auch die Textdatei ist schnell eingelesen und
steht in unter einer Sekunde bereit zur Verarbeitung.
Mein Problem ist der Aufbau eines "netten" Suchdialogs.
Wenn ich in das Suchfeld "123" eingebe dann würde
ich gerne alle Datensätze die mit "123" beginnen
angezeigt bekommen.
Genau das leistet z.B. DataView.RowFilter

Mit DataTable und DataView hast Du u.a. diese
Methoden zur Verfügung

Datatable.Rows.Find(Key)
Datatable.Rows.IndexOf(DataRow)
DataView.Find(Key)
DataView.FindRows(Key)
DataView.RowFilter = "Filterkriterium"
DataView.Sort

Wie DataTable, DataView und CurrencyManager
erstellt und verwendet werden kannst Du Dir unter

www.gssg.de -> Visual Basic -> VB.net

u.a. bei den vielen DataGridView-Beispielen ansehen.

Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
Michael Roth
2007-08-03 09:40:23 UTC
Permalink
Hallo Jörn,
Post by Jörn Janz
Hallo,
Ich habe leider keinen Einfluss auf die Datenhaltung. Die Artikeldaten
werden aus einer alten Anwendung alle 2 Wochen
in eine Textdatei geschrieben. Beim Start des VB .net Programm sollen
die Daten nur einmal eingelesen werden.
Dann wird einfach nur gesucht und angezeigt. Die Anwendung läuft dann
den ganzen Tag schnell. Auch die Textdatei ist schnell eingelesen und
steht in unter einer Sekunde bereit zur Verarbeitung.
Mein Problem ist der Aufbau eines "netten" Suchdialogs. Wenn ich in
das Suchfeld "123" eingebe dann würde ich gerne alle Datensätze die
mit "123" beginnen angezeigt bekommen. So wie z.B. in einer ComboBox.
Die Textbox hat seit .Net 2.0 auch eine AutoComplete Eigenschaft.
Vielleicht ist diese schneller als bei der Combobox.
Gibt sogar extra eine Collection (AutoCompleteStringCollection - siehe
Hilfe), in der die Vorschläge gepackt werden sollen.
Das machst ja nur einmal beim Programmstart. Deswegen sollte es ja egal
sein, wie lange das Einlesen der Textdatei dauert? Dein Problem ist die
Darstellungsgeschwindigkeit in der Combobox. Richtig?

Weitere Stichwörter für die Hilfe sind AutoCompleteMode und
AutoCompleteSource

Gruß

Michael
Jörn Janz
2007-08-03 10:10:20 UTC
Permalink
Hallo Michael,

wenn die Datensätz erstmal der ComboBox zugefügt wurden ist alles
super schnell.
Das 25.000 mal "Me.cmbSuchen.Items.Add(b(x, 1)) " kostet mich 6
Sekunden.

Gruß - Jörn
Post by Alfred M.
Hallo Jörn,
Post by Jörn Janz
Hallo,
Ich habe leider keinen Einfluss auf die Datenhaltung. Die Artikeldaten
werden aus einer alten Anwendung alle 2 Wochen
in eine Textdatei geschrieben. Beim Start des VB .net Programm sollen
die Daten nur einmal eingelesen werden.
Dann wird einfach nur gesucht und angezeigt. Die Anwendung läuft dann
den ganzen Tag schnell. Auch die Textdatei ist schnell eingelesen und
steht in unter einer Sekunde bereit zur Verarbeitung.
Mein Problem ist der Aufbau eines "netten" Suchdialogs. Wenn ich in
das Suchfeld "123" eingebe dann würde ich gerne alle Datensätze die
mit "123" beginnen angezeigt bekommen. So wie z.B. in einer ComboBox.
Die Textbox hat seit .Net 2.0 auch eine AutoComplete Eigenschaft.
Vielleicht ist diese schneller als bei der Combobox.
Gibt sogar extra eine Collection (AutoCompleteStringCollection - siehe
Hilfe), in der die Vorschläge gepackt werden sollen.
Das machst ja nur einmal beim Programmstart. Deswegen sollte es ja egal
sein, wie lange das Einlesen der Textdatei dauert? Dein Problem ist die
Darstellungsgeschwindigkeit in der Combobox. Richtig?
Weitere Stichwörter für die Hilfe sind AutoCompleteMode und
AutoCompleteSource
Gruß
Michael
Stefan Falz [MVP]
2007-08-03 10:35:33 UTC
Permalink
Hallo Jörn,
Post by Jörn Janz
wenn die Datensätz erstmal der ComboBox zugefügt wurden ist alles
super schnell.
Das 25.000 mal "Me.cmbSuchen.Items.Add(b(x, 1)) " kostet mich 6
Sekunden.
Naja, 25k Datensätze in einer Combobox zu halten finde ich nicht gerade
sinnvoll. Hier würde sich eher die RowFilter Eigenschaft einer DataView
(die du als DataSource der Combobox angeben kannst) anbieten.

Was spricht eigentlich dagegen, die Daten in eine kleine Access Datenbank
zu importieren und diese dann zu durchsuchen? Abgesehen davon, dass das
natürlich noch andere Vorteile hat, würde ich meinen, dass der Import um
einiges schneller gehen dürfte (zumindest, wenn sich der Import direkt über
SQL lösen lässt, was bei CSV problemlos geht, bei festen Formaten ohne Trenn-
zeichen hab ichs noch nicht probiert).
--
Tschau, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
Jörn Janz
2007-08-03 11:44:48 UTC
Permalink
Post by Alfred M.
Hallo Jörn,
Hallo Stefan,
Post by Alfred M.
Naja, 25k Datensätze in einer Combobox zu halten finde ich nicht gerade
sinnvoll.
Du / Ihr (wurde ja auch schon mehrfach angedeutet) habt ja recht.
Ich werde mich dann auf den "DataTable / DataView" Weg begeben.
Ist auf jeden Fall eleganter. Ich habe schon ein Beispiel von Peters
Homepage auf meinem Rechner.
Vielen Dank an Peter!
Post by Alfred M.
Hier würde sich eher die RowFilter Eigenschaft einer DataView
(die du als DataSource der Combobox angeben kannst) anbieten.
Was spricht eigentlich dagegen, die Daten in eine kleine Access Datenbank
zu importieren und diese dann zu durchsuchen? Abgesehen davon, dass das
natürlich noch andere Vorteile hat, würde ich meinen, dass der Import um
einiges schneller gehen dürfte (zumindest, wenn sich der Import direkt über
SQL lösen lässt, was bei CSV problemlos geht, bei festen Formaten ohne Trenn-
zeichen hab ichs noch nicht probiert).
Werde ich auch nochmal überdenken. Wird - glaube ich - aber noch
aufwendiger. Neuere .txt da? > wenn ja Access DB aktualisieren.
Post by Alfred M.
Access DB noch da? Tabelle anlegen usw....
Vielen Dank für die vielen Tips! Jörn
Stefan Falz [MVP]
2007-08-03 11:54:23 UTC
Permalink
Hallo Jörn,
Post by Jörn Janz
Du / Ihr (wurde ja auch schon mehrfach angedeutet) habt ja recht.
Ich werde mich dann auf den "DataTable / DataView" Weg begeben.
Gut so^^
Post by Jörn Janz
Werde ich auch nochmal überdenken. Wird - glaube ich - aber noch
aufwendiger. Neuere .txt da? > wenn ja Access DB aktualisieren.
Nö, du mussts ja nur einmal schreiben. Und der Import (wenn er denn
direkt über Jet SQL machbar wäre) ist nebenbei bemerkt, auch noch
ziemlich schnell.
--
Tschau, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
Peter Götz
2007-08-03 13:05:30 UTC
Permalink
Hallo Jörn,

schau Dir mal das nachfolgende Beispiel an.
Es zeigt Dir eine mögliche Verwendung von
DataView.RowFilter.

' /// Code in einer leeren Form1
Public Class Form1
Private WithEvents DGV As DataGridView
Private WithEvents TB As TextBox

Private mDT As DataTable
Private mDV As DataView
Private WithEvents mCM As CurrencyManager

Private Sub Form1_Load _
(ByVal sender As System.Object, _
ByVal e As System.EventArgs _
) Handles MyBase.Load

CreateControls()
CreateData()
DGV.DataSource = mDV

DGV.Columns(0).DefaultCellStyle.Alignment = _
DataGridViewContentAlignment.MiddleRight

DGV.AutoResizeColumns()
End Sub

Private Sub CreateControls()
TB = New TextBox
With TB
.Name = "TB"
.Font = New Font("Arial", 12)
.SetBounds(10, 10, _
Me.ClientSize.Width - 20, _
.Height)

.Anchor = AnchorStyles.Left Or _
AnchorStyles.Top Or _
AnchorStyles.Right
End With
Me.Controls.Add(TB)

DGV = New DataGridView
With DGV
.Name = "DGV"

.DefaultCellStyle.Font = _
New Font("Arial", 10)

.ColumnHeadersDefaultCellStyle.Font = _
New Font("Arial", 8, FontStyle.Bold)

.SetBounds _
(10, _
TB.Bottom + 10, _
TB.Width, _
Me.ClientSize.Height - (TB.Bottom + 20))

.Anchor = AnchorStyles.Left Or _
AnchorStyles.Top Or _
AnchorStyles.Right Or _
AnchorStyles.Bottom
End With
Me.Controls.Add(DGV)
End Sub

Private Sub CreateData()
Dim i As Integer
Dim dr As DataRow

mDT = New DataTable
With mDT
.Columns.Add("ID", GetType(Integer))
.Columns.Add("Bezeichnung", GetType(String))
For i = 1 To 12
dr = .NewRow
dr.Item(0) = i
dr.Item(1) = MonthName(i)
.Rows.Add(dr)
Next
.AcceptChanges()
End With
mDV = New DataView(mDT)

mCM = DirectCast _
(Me.BindingContext(mDV), _
CurrencyManager)

End Sub

Private Sub mCM_PositionChanged _
(ByVal sender As Object, _
ByVal e As System.EventArgs _
) Handles mCM.PositionChanged

If mCM.Position > -1 Then
Dim DR As DataRow
DR = DirectCast(mCM.Current, DataRowView).Row
Me.Text = DR.Item(0).ToString & " : " & _
DR.Item(1).ToString
End If
End Sub

Private Sub TB_TextChanged _
(ByVal sender As Object, _
ByVal e As System.EventArgs _
) Handles TB.TextChanged

mDV.RowFilter = "Bezeichnung like '" & TB.Text & "*'"
End Sub

End Class
' \\\ E N T E

Nach dem Programmstart in der Textbox irgendwelche
Monatsnamen eingeben.
Schon während der Eingabe wird die Auswahl im
DataGridView immer kleiner, bis letztlich nur noch
ein einziger Datensatz übrig bleibt.

Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
Westfal Osten
2007-08-03 14:04:23 UTC
Permalink
Post by Peter Götz
Schon während der Eingabe wird die Auswahl im
DataGridView immer kleiner, bis letztlich nur noch
ein einziger Datensatz übrig bleibt.
...macht das bei 25.000 eindeutigen Artikelnummern überhaupt Sinn?

Da sollte man doch wenigstens nach was anderem suchen bzw alternativ
im Artikelnamen und das spricht wieder für einen DB.





-
Peter Götz
2007-08-03 15:39:17 UTC
Permalink
Hallo Westfal Osten,
Post by Westfal Osten
Post by Peter Götz
Schon während der Eingabe wird die Auswahl im
DataGridView immer kleiner, bis letztlich nur noch
ein einziger Datensatz übrig bleibt.
...macht das bei 25.000 eindeutigen Artikelnummern
überhaupt Sinn?
Da Jörn bisher nicht genauer beschrieben hat
wie seine "Artikelnummern" tatsächlich aussehen
("die ersten sieben Zeichen) und in welchem Datentyp
sie verwaltet werden, kann man die Frage kaum
beantworten.
Post by Westfal Osten
Da sollte man doch wenigstens nach was anderem
suchen bzw alternativ im Artikelnamen und das spricht
wieder für einen DB.
Na ja, wenn man sich mein Beispiel mal genauer ansiehst,
sollte auffallen, dass darin eben nicht nach der Nummer,
sondern nach der Bezeichnung gesucht wird.
Es geht wohl auch weniger darum, wonach gesucht wird,
sondern Jörn einfach mal zu zeigen, was er mit DataTable
und DataView und deren Eigenschaften und Methoden
machen kann.

Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
Jörn Janz
2007-08-03 14:18:12 UTC
Permalink
Hallo Peter,

vielen Dank für das wahnsinnig gute Beispiel! Ich bin begeistert.
Der Code ist bereits eingebaut und getestet. Mehr als eine tolle Hilfe
für den Einstieg in DataTable & Co!!

Ich habe die 25.000 IDs & Artikel Nummern in die DataTable geschossen
und das Ergebnis: so um die 6 Sekunden bis das Formular gefüllt auf
dem Schirm erscheint
Die Suche ist dann schnell.

Ich probiere in den nächsten Tagen mal den "Access" Weg aus und
berichte dann hier.

Gruß - Jörn
Stefan Falz [MVP]
2007-08-03 14:48:25 UTC
Permalink
Hallo Jörn,
Post by Jörn Janz
Ich probiere in den nächsten Tagen mal den "Access" Weg aus und
berichte dann hier.
Import von Dateien mit fester Spaltenbreite klappt übrigens problemlos.
Einfach eine schema.ini Datei erstellen [1], dort als Format Fixed Length
angeben, die Spalten definieren und schon kanns losgehen. (Das muss man
natürlich nur einmal machen, das Format bleibt ja immer gleich)

siehe u.a.: http://msdn2.microsoft.com/de-de/library/ms709353.aspx
--
Tschau, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
Martin H.
2007-08-03 15:21:10 UTC
Permalink
Hallo Jörn,
Post by Jörn Janz
Ich probiere in den nächsten Tagen mal den "Access" Weg aus und
berichte dann hier.
Wenn ich mich nicht irre, kann JET auch Text-Dateien als "Datenbank"
öffnen. Dadurch würdest Du Dir den Import in eine Access-Datenbank sparen.

Beste Grüße,

Martin
Peter Götz
2007-08-03 15:49:13 UTC
Permalink
Hallo Jörn,
Post by Jörn Janz
vielen Dank für das wahnsinnig gute Beispiel!
Ich bin begeistert.
Möchtest Du meine Kontonummer haben? ;-))
Post by Jörn Janz
Der Code ist bereits eingebaut und getestet.
Mehr als eine tolle Hilfe für den Einstieg in
DataTable & Co!!
Ich habe die 25.000 IDs & Artikel Nummern in
so um die 6 Sekunden bis das Formular gefüllt
auf dem Schirm erscheint
Wie hast Du denn Deine Daten in die DataTable
"geschossen" (Code)?
6 Sekunden scheint mir nicht wirklich schnell zu
sein.

Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
Peter Fleischer
2007-08-03 16:14:16 UTC
Permalink
Post by Jörn Janz
Hallo Peter,
vielen Dank für das wahnsinnig gute Beispiel! Ich bin begeistert.
Der Code ist bereits eingebaut und getestet. Mehr als eine tolle Hilfe
für den Einstieg in DataTable & Co!!
Ich habe die 25.000 IDs & Artikel Nummern in die DataTable geschossen
und das Ergebnis: so um die 6 Sekunden bis das Formular gefüllt auf
dem Schirm erscheint
Die Suche ist dann schnell.
Ich probiere in den nächsten Tagen mal den "Access" Weg aus und
berichte dann hier.
Hi Jörn,
Access ist nicht unbedingt nötig, wenn du die Daten immer als Textdatei
bekommst und wirklich nur anzeigen lassen bzw. suchen willst. Hier mal ein
Beispiel; einfach in eine leere Form in ein Windows Projekt kopieren. Da
kannst du mal testen und spürst auch den Einfluss der RowFilter-Eigenschaft
bei 25000 Datensätzen auf die Geschwindigkeit.

Public Class Form1

Dim dv As DataView

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
' Create Testdata
Dim i, k As Integer
Using sr As New IO.StreamWriter("c:\temp\x.txt")
For i = 1 To 25000
For k = 1 To 22
sr.Write("Item" & i.ToString("00000") & k.ToString("00"))
Next
sr.WriteLine()
Next
End Using
' Load Testdata
Dim da As New OleDb.OleDbDataAdapter("SELECT * FROM [x.txt]", _
"provider=microsoft.jet.oledb.4.0;data source=c:\temp\;Extended
Properties=""text;""")
Dim dt As New DataTable
Dim t1 As Date = Now
da.Fill(dt)
Dim t2 As Date = Now
dv = dt.DefaultView
' Create and Bind Controls
'
Dim dg As New DataGrid
Me.Controls.Add(dg)
dg.Dock = DockStyle.Fill
dg.DataSource = dv
'
Dim cb As New ComboBox
Me.Controls.Add(cb)
cb.Dock = DockStyle.Top
cb.DisplayMember = "F1"
Dim t3 As Date = Now
cb.DataSource = dv
Dim t4 As Date = Now
'
Dim tb As New TextBox
Me.Controls.Add(tb)
tb.Dock = DockStyle.Top
AddHandler tb.TextChanged, AddressOf cbTextChanged
'
MsgBox(String.Format("{0} Datensätze gelesen in {1}, gebunden in {2}", _
dt.Rows.Count, t2.Subtract(t1), t4.Subtract(t3)))
'
End Sub

Private Sub cbTextChanged(ByVal sender As Object, ByVal e As EventArgs)
dv.RowFilter = "F1 LIKE '" & CType(sender, TextBox).Text & "*'"
End Sub

End Class

Dazu die c:\temp\schema.ini

; Import von Textdatei

[x.txt]
ColNameHeader=False
CharacterSet=1252
Format=FixedLength
Col1=F1 Text Width 11
Col2=F2 Text Width 11
Col3=F3 Text Width 11
Col4=F4 Text Width 11
Col5=F5 Text Width 11
Col6=F6 Text Width 11
Col7=F7 Text Width 11
Col8=F8 Text Width 11
Col9=F9 Text Width 11
Col10=F10 Text Width 11
Col11=F11 Text Width 11
Col12=F12 Text Width 11
Col13=F13 Text Width 11
Col14=F14 Text Width 11
Col15=F15 Text Width 11
Col16=F16 Text Width 11
Col17=F17 Text Width 11
Col18=F18 Text Width 11
Col19=F19 Text Width 11
Col20=F20 Text Width 11
Col21=F21 Text Width 11
Col22=F22 Text Width 11
--
Viele Grüße

Peter
Jörn Janz
2007-08-03 22:10:14 UTC
Permalink
Hallo Peter,

das wird ja ein echter Lerntag für mich. Dein eingebauter Zeitmesser
sagt mir folgendes 24999 Datensätze gelesen in 00:00:42.798750,
gebunden in 00:00:04.0937500.
Ihr habt bestimmt alle schnellere Rechner, oder? Ich habe noch keine
Zeit gefunden mir den Code etwas genauer zu anzuschauen. Ich melde
mich in den nächsten Tagen
mal. Genug Futter habe ich jetzt ja.

Vielen Dank! Jörn
Peter Fleischer
2007-08-04 07:10:00 UTC
Permalink
Post by Jörn Janz
das wird ja ein echter Lerntag für mich. Dein eingebauter Zeitmesser
sagt mir folgendes 24999 Datensätze gelesen in 00:00:42.798750,
gebunden in 00:00:04.0937500.
Ihr habt bestimmt alle schnellere Rechner, oder?
HI Jörn,
obige Angabe von dir zeigt, dass du die schema.ini vergessen hast anzulegen.

Ohne schema.ini kommen bei mir 1,01 und 1,41 Sekunden. Mein PC hat 1,5 GHz
und 1,5 GB.

Mit schema.ini ergibt es 2,03 und 0,53.

Beide Prüfungen mit der Release-Version (ohne IDE) ausgeführt.
--
Viele Grüße

Peter
Jörn Janz
2007-08-04 13:15:57 UTC
Permalink
Hallo Peter,
Post by Peter Fleischer
obige Angabe von dir zeigt, dass du die schema.ini vergessen hast anzulegen.
Dann habe ich was falsch gemacht. Ich habe die Datei mit dem Namen
"schema.ini" in das
Verzeichnis "c:\Temp" gelegt.

Der Inhalt der Schema.ini Datei sieht so aus:
[x.txt]
ColNameHeader=False
CharacterSet=1252
Format=FixedLength
Col1=F1 Text Width 11
Col2=F2 Text Width 11
Col3=F3 Text Width 11
Col4=F4 Text Width 11
Col5=F5 Text Width 11
Col6=F6 Text Width 11
Col7=F7 Text Width 11
Col8=F8 Text Width 11
Col9=F9 Text Width 11
Col10=F10 Text Width 11
Col11=F11 Text Width 11
Col12=F12 Text Width 11
Col13=F13 Text Width 11
Col14=F14 Text Width 11
Col15=F15 Text Width 11
Col16=F16 Text Width 11
Col17=F17 Text Width 11
Col18=F18 Text Width 11
Col19=F19 Text Width 11
Col20=F20 Text Width 11
Col21=F21 Text Width 11
Col22=F22 Text Width 11

An Deinem Programmcode habe ich nix verändert. Was mache ich falsch?

Viele Grüße und besten Dank. Jörn
Peter Fleischer
2007-08-04 14:20:17 UTC
Permalink
Post by Jörn Janz
Post by Peter Fleischer
obige Angabe von dir zeigt, dass du die schema.ini vergessen hast anzulegen.
Dann habe ich was falsch gemacht. Ich habe die Datei mit dem Namen
"schema.ini" in das
Verzeichnis "c:\Temp" gelegt.
Hi Jörn,
es muss alles passen.

1. Dateiname und Pfad der txt-Datei muss passen zu schema.ini.
2. txt-Datei und schema.ini müssen im gleichen Verzeichnis liegen
3. Sektion in der schema.ini muss genau den Dateinamen der txt-Datei haben

Also:

Using sr As New IO.StreamWriter("c:\temp\x.txt")
...
Dim da As New OleDb.OleDbDataAdapter("SELECT * FROM [x.txt]", _
"provider=microsoft.jet.oledb.4.0;data source=c:\temp\;Extended
Properties=""text;""")
...

Dazu die c:\temp\schema.ini

[x.txt]
...
--
Viele Grüße

Peter
Jörn Janz
2007-08-04 22:47:22 UTC
Permalink
Hallo Peter,
Post by Peter Fleischer
es muss alles passen.
1. Dateiname und Pfad der txt-Datei muss passen zu schema.ini.
2. txt-Datei und schema.ini müssen im gleichen Verzeichnis liegen
3. Sektion in der schema.ini muss genau den Dateinamen der txt-Datei haben
Using sr As New IO.StreamWriter("c:\temp\x.txt")
...
Dim da As New OleDb.OleDbDataAdapter("SELECT * FROM [x.txt]", _
"provider=microsoft.jet.oledb.4.0;data source=c:\temp\;Extended
Properties=""text;""")
...
Dazu die c:\temp\schema.ini
[x.txt]
...
Ich habe Dein Beispiel immer im VS im über den DebugModus / F5. Die
Werte: 00:00:41 und 00:00:02.
Wenn ich im Verzeichnis ...\bin\debug\ die Exe starte dann bekomme ich
auch Deine Traumwerte.
So einen Unterschied hätte ich nicht erwartet.
Nochmal vielen Dank für Deine Mühe!

Viele Grüße - Jörn

Armin Zingler
2007-08-03 11:16:56 UTC
Permalink
"Jörn Janz" <***@jrdrucksysteme.de> schrieb
Hallo Michael,

wenn die Datensätz erstmal der ComboBox zugefügt wurden ist alles
super schnell.
Das 25.000 mal "Me.cmbSuchen.Items.Add(b(x, 1)) " kostet mich 6
Sekunden.


======

Evtl Daten (Artikel-Nr) "umschaufeln" in ein eindimensioales Array und dann
cmbSuchen.Items.AddRange verwenden. Letzteres dauert hier bei bei einem
String-Array mit 25.000 Items 0,6 Sekunden. Ersteres dürfte "kaum messbar"
sein.


Armin
Peter Götz
2007-08-03 12:06:19 UTC
Permalink
Hallo Jörn,
Post by Jörn Janz
wenn die Datensätz erstmal der ComboBox zugefügt wurden
ist alles super schnell.
Das 25.000 mal "Me.cmbSuchen.Items.Add(b(x, 1)) "
kostet mich 6 Sekunden.
Willst Du wirklich in die DropDown-Liste einer Combobox
25.000 Items packen?

Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
Alfred M.
2007-08-03 08:20:32 UTC
Permalink
"J�rn Janz" <***@jrdrucksysteme.de> schrieb im Newsbeitrag news:***@r34g2000hsd.googlegroups.com...
Hallo Alfred,

es sind genau 144 Zeichen pro Zeile mit einer festen Satzlänge. Die
Zeilen werden mit ";CRLF" abgeschlossen.
Beispiel:
1234567Schraube 47,90 ..... ;CRLF
Feld 1 = 7 Zeichen
Feld 2 = 12 Zeichen
Feld 3 = 5 Zeichen

Ich habe die Aktualisierung der ComboBox shon mit
"me.cmbSuchen.BeginUpdate()" abgeschaltet.
Bringt leider auch nix.

Eine Datenbank ist mir zu aufwendig. Die Datensätze werden nicht
bearbeitet bzw. geändert oder ergänzt. Es soll nur nach
der Artikelnummer gesucht werden können. Der Datensatz soll dann
angezeigt werden und dann füge ich manuell die
Auftragsnummer ein und drucke dann den Datenstaz + Auftragsnummer aus.
Alle 2 Wochen wird von einer anderen Anwendung
die TXT erneuert.

Gruß - Jörn


Hallo Jörn,

ich würde vesuchen die Datei in einem Schub in einen String einzulesen und
dann in einer Schleife die Records und Felder mit den Stringfunktionen
herausholen. Diese dann in eine DataTable im Speicher packen. Falls du
keinen spezifischen Datenbankprovider verwendest, musst du nichts
zusätzliches für ADO.NET installieren und hast alle wichtigen
Datenbank-Objekte verfügbar. Wenn die Daten erst mal im DataSet sind, steht
dir die ganze Welt offen.

Grüße Alfred M.
Westfal Osten
2007-08-03 06:18:51 UTC
Permalink
Post by Jörn Janz
ich muss beim Programmstart 25.000 Datensätze aus einer Textdatei
lesen.
Die Textdatei enthält 22 "Felder" und ca. 144 Zeichen pro Zeile.
Ich habe mit Array und ArrayList herumprobiert und die Datei ist
in unter einer Sekunde eingelesen und in die entsprechende Felder
aufgeteilt.
Jetzt zu meiner Frage. In den ersten 7 Zeichen der Zeile finde ich die
Artikelnummer. Die Artikelnummer möchte ich an ein Suchfeld binden.
Also, wenn schon Liste, dann SortedList oder Hashtable, da kann man
die Artikelnummer als Key nutzen und das alles schneller finden.

Aber Du könntest das auch gleich in ein Dataset einlesen und die
Filterfunktion des dataviews nutzen.

Besser wäre aber eine Datenbank zu verwenden wie
http://www.advantagedatabase.com , die braucht keine Installation für
den Local-Server und ist als Local-Server kostenlos. Dafür hatst Du
die Flexibilität einer SQL-Datenbank. Bei Bedarf kann man auch einen
richtigen Server draus machen und mehrer Leute übers Netz zugreifen
lassen.
Peter Götz
2007-08-03 07:32:00 UTC
Permalink
Hallo Jörn,
Post by Jörn Janz
ich muss beim Programmstart 25.000 Datensätze
aus einer Textdatei lesen.
25.000 Datensätze und Textdatei, das pass irgendwie
nicht so recht zusammen. Gibt es denn besondere
Gründe, diese Daten nicht in einer Datenbank zu halten?
Post by Jörn Janz
Die Textdatei enthält 22 "Felder" und ca. 144 Zeichen
pro Zeile.
Wie definierst Du "Felder" in Deiner Textdatei?
Wie definierst Du "Zeile"? Einfach durch die Länge
von 144 Zeichen oder durch Abschluss mit einem CrLF?
Post by Jörn Janz
Ich habe mit Array und ArrayList herumprobiert und die
Datei ist in unter einer Sekunde eingelesen und in die
entsprechende Felder aufgeteilt.
Jetzt zu meiner Frage. In den ersten 7 Zeichen der Zeile
finde ich die Artikelnummer. Die Artikelnummer möchte
ich an ein Suchfeld binden. Nett wäre eine "
Autovervollständigung" wie z.B. in einer Combobox.
Kommt diese Artikelnummer innerhalb Deiner 25.000
Datensätze nur einmal vor oder mehrfach?
Post by Jörn Janz
Wenn ich die Artikelnummer mit .Add hinzufüge benötigt
das Programm ca. 6 Sekunden für den Vorgang. Ich habe
auch schon versucht mit einer ArrayList zu arbeiten und
die ArrayList dann an die ComboBox zu binden
- dann dauert es noch länger.
Sind 6 Sekunden OK?
6 Sekunden Wartezeit sind für einen Benutzer sicher
nicht angenehm und bei Datenhaltung in einer Datenbank
liesse sich das ganz sicher auf deutlich unter 1 Sekunde
verkürzen.
Post by Jörn Janz
Habt Ihr noch einen Beschleunigungstip oder eine Idee
für eine komfortable Suchmaske die sich schneller
aufbauen lässt für mich?
Dein Hauptproblem ist wohl die Datenhaltung in einer
Textdatei. Eine Datenbank würde vieles ganz wesentlich
vereinfachen und beschleunigen. Bei Deiner vergleichsweise
geringen Datenmenge wäre eine simple Access.mdb
vollkommen ausreichend. Die ist kostenlos und kann
mit ADO.net via Jet-Provider problemlos ver- und bearbeitet
werden.

Ob Array() oder ArrayList() nun gerade günstig sind, lässt
sich ohne genauere Kenntnis Deiner Programmanforderungen
nicht beurteilen. Zusammen mit einer Datenbank wäre
möglicherweise eine DataTable mit zugehöriger DataView
wesentlich komfortabler. Wobei Du natürlich auch Deine
Daten aus der Textdatei in einer DataTable halten könntest
und so zusammen mit DataView und CurrencyManager
eben auch wesentlich komfortabler arbeiten könntest.


Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
Loading...