manuel5
Goto Top

SQL Verbindung beim Formular laden herstellen

Damit die Übersicht gewahrt bleibt eröffne ich hier ne neue Anfrage.

Hallo zusammen,

also ich hab (immernoch face-wink ) ein Excel-Formular das mit wenn ich auf nen Button klicke eine Verbindung zu einer SQL-Datenbank herstellt.

Private Sub CommandButton5_Click()
Set condb = New ADODB.Connection
condb.Open "DRIVER=MySQL ODBC 3.51 Driver; SERVER=localhost; DATABASE=datenbank;USER=xxxx;PASSWORD=xxxx;"
Dim rec As ADODB.Recordset
Set rec = New ADODB.Recordset
rec.CursorLocation = adUseClient
rec.Open "SELECT * FROM `table`ORDER BY `feld1`.`feld2` ", condb, adOpenForwardOnly, adLockReadOnly

rec.MoveFirst
While Not rec.EOF
ComboBox6.AddItem (rec.Fields(3))
ComboBox8.AddItem (rec.Fields(3))
rec.MoveNext
Wend

condb.Close

End Sub

Nun versuche ich aber das die Verbindung schon hergestellt wird wenn ich die Form öffne.

Hab ein Modul

Sub Start ()

UserForm5.Show

End Sub

Habe hier denn o. g. Code (für die SQL-Verbindung) eingefügt - hier meldet er mir aber - Objekt fehlt
Wahrscheinlich wegen der Combobox......

Wie bringe ich es fertig das er mir beim Laden/Öffnen der Form die SQL-Verbindung herstellt und die Combobox6 und 8 mit Daten fuellt.

Danke und Gruß
Manuel

Content-ID: 80433

Url: https://administrator.de/contentid/80433

Ausgedruckt am: 20.11.2024 um 13:11 Uhr

56153
56153 11.02.2008 um 12:01:08 Uhr
Goto Top
hi,

du kannst mal versuchen, einfach den formularnamen vor die comboboxen zu packen, damit er weiß wo er diese findet:

also komplett dann so ->

Sub Start ()

UserForm5.Show

Set condb = New ADODB.Connection
condb.Open "DRIVER=MySQL ODBC 3.51 Driver; SERVER=localhost; DATABASE=datenbank;USER=xxxx;PASSWORD=xxxx;"
Dim rec As ADODB.Recordset
Set rec = New ADODB.Recordset
rec.CursorLocation = adUseClient
rec.Open "SELECT * FROM `table`ORDER BY `feld1`.`feld2` ", condb, adOpenForwardOnly, adLockReadOnly

rec.MoveFirst
While Not rec.EOF
UserForm5.ComboBox6.AddItem (rec.Fields(3))
UserForm5.ComboBox8.AddItem (rec.Fields(3))
rec.MoveNext
Wend

condb.Close

End Sub
manuel5
manuel5 11.02.2008 um 12:35:14 Uhr
Goto Top
Sehr fein - das wars! face-smile

Super - Danke

Hätt ich auch draufkommen können .......

Gruß Manuel
manuel5
manuel5 12.02.2008 um 08:54:01 Uhr
Goto Top
Hallo nochmals,

eine Sache waere da noch - und zwar versuche ich - also wenn ich in der Combobox6 einen Wert stehen hab - hier is es der Firmennamen - soll er mir in Textfeld39 die dazugehoerige Telefonnummer schreiben.

Muss ich hier in der Wend-Schleife dies schon deklarieren?

rec.MoveFirst
While Not rec.EOF
UserForm5.ComboBox6.AddItem (rec.Fields(3))
UserForm5.ComboBox8.AddItem (rec.Fields(2))
UserForm5.Textfeld39.AddItem(rec.Fields(4))
rec.MoveNext
Wend

Oder wie geh ich da vor?

Gruß Manuel
misterdemeanor
misterdemeanor 12.02.2008 um 10:57:51 Uhr
Goto Top
Hallo Manuel,

eine Sache waere da noch - und zwar versuche
ich - also wenn ich in der Combobox6 einen
Wert stehen hab - hier is es der Firmennamen
- soll er mir in Textfeld39 die dazugehoerige
Telefonnummer schreiben.

Muss ich hier in der Wend-Schleife dies
schon deklarieren?

Jein. Momentan ist Dein Recordset ja lokal in der Sub() Start. Sprich nach verlassen der Sub nicht mehr existent.

Und wenn ich das richtig verstehe soll die richtige Telefonnummer nach Auswahl des Firmennamens (ComboBox6_AfterUpdate) eingeblendet werden. Eine TextBox hat nur die Eigenschaft Text für einen Wert (nicht wie die Items Auflistung bei der ComboBox ).

Aslo könntest Du entweder das RecordSet global machen und nach Auswahl in der ComboBox6 die Find-methode des RecordSets aufrufen.
Andererseits könntest Du in der Sub-Start Wend-Schleife auch ein Array mit den Telefonnummern füllen

BG, Felix -misterdemeanor-
manuel5
manuel5 12.02.2008 um 11:26:36 Uhr
Goto Top
Hallo,

muesste dann also in etwa so funzen-->

Private Sub ComboBox6_AfterUpdate()
Set condb = New ADODB.Connection
condb.Open "DRIVER=MySQL ODBC 3.51 Driver; SERVER=localhost; DATABASE=database;USER=XXX;PASSWORD=XXXX;"
Dim rec As ADODB.Recordset
Dim Combobox As Boolean

Set rec = New ADODB.Recordset
rec.CursorLocation = adUseClient
rec.Open SELECT PhoneNO FROM tabelle WHERE CompName1 = "& combobox" condb, adOpenForwardOnly, adLockReadOnly
rec.MoveFirst
While Not rec.EOF
'TextBox37.Value = rec.Fields(0)
rec.MoveNext
Wend
condb.Close


End Sub


Oder verstéh ichs ned?
Gruß Manuel
misterdemeanor
misterdemeanor 12.02.2008 um 12:26:22 Uhr
Goto Top
nein...bloß nicht! *g

So baust Du ja jedes mal eine Verbindung auf nachdem man etwas aus der ComboBox gewählt hat.
Außerdem wäre in Deinem Textfeld dann einfach die Telefonnummer(und nur die eine) des letzten Datensatzes.

Wenn ich das richtig vermute hast Du in Deiner Tabelle "table" 3 Felder aud die Du zugreifen willst--->Firmenname, Telefonnummer und ein drittes. ich würde Dir jetzt einfach raten das Recordset welches Du in der Sub-Start mit Daten füllst global verügbar zu machen. Ist nicht sehr fein aber für Dich die beste Lösung. Um das zu bewerkstelligen deklarierst Du die Recordset-Variable nicht in der Sub-Start sondern auf Modulebene mit Public rec As ADODB.Recordset.

In Deiner Sub ComboBox6_AfterUpdate() kannst Du nun auch auf das Recordset zugreifen. Um den entsprechenden Datensatz, respektive die zu der ComboBox Auswahl zugehörige Telefonnummer zu erhalten tippst Du folgendes ein:

rec.MoveFirst
rec.Find "Firmenname='" & UserForm5.ComboBox6.Text & "'"  
If (Not rec.EOF) Or (Not rec.BOF) Then
  UserForm5.TextBox37.Text = rec.Fields("PhoneNumber")  
Else
  UserForm5.TextBox37.Text = "Keine Tel-nummer vorhanden"  
End If

Da ich nicht wusste und Du es immer verschieden gepostet hat must Du noch das entsprechende Feld anpassen. Hier exemplarisch PhoneNumber. Eventuell musst Du in der Sub-Start noch die Recordset.Open-Function anpassen. Du hast einen Vorwärtscursor, um die Find Methode richtig anzuwenden ist glaube ich ein Dynamischer Cursor nötig.
manuel5
manuel5 12.02.2008 um 14:17:36 Uhr
Goto Top
Hmmmmm - versteh ich das jetzt richtig?

Ich soll in dem Sub Start()
nur die SQLDB-Verbindung herstellen und die Form5.Show

das waere ja das hier praktisch

Sub Start() 'Dies im Modul
Set condb = New ADODB.Connection
condb.Open "DRIVER=MySQL ODBC 3.51 Driver; SERVER=localhost; DATABASE=database;USER=XXX;PASSWORD=XXXX;"
Dim rec As ADODB.Recordset
Dim Combobox As Boolean

UserForm5.Show
End Sub

<---- Richtig soweit?

Und dann ne neues Modul mit

Sub ComboBox6_AfterUpdate()
rec.MoveFirst
rec.Find "PhoneNo='" & UserForm5.ComboBox6.Text & "'"
If (Not rec.EOF) Or (Not rec.BOF) Then
UserForm5.TextBox39.Text = rec.Fields("PhoneNo")
Else
UserForm5.TextBox39.Text = "Keine Tel-nummer vorhanden"
End If
End Sub

<---- immer noch richtig?

Aba wo isn dann da Fehler?

Des so klappts leider nicht

Gruß Manuel
manuel5
manuel5 14.02.2008 um 08:25:57 Uhr
Goto Top
Guten Morgen,

so etndlich mal wieder dazugekommen

Also wenn ich das so eingeb bringt er Fehlermeldung -->

Entweder BOF oder EOF ist True, oder der aktuelle Datnsatz wurde gelöscht. Der angeforderte Vorgang benötigt einen aktuellen Datensatz.

Im Form5 hab ich bei Combobox6 aktualiseren diesen Code -->

Private Sub ComboBox6_AfterUpdate()
Dim strBandNr As String, Zähler As Long, strSenderID As String


If VarVorhanden("EigenerMerker") = False Then
With Application.ActiveWorkbook.CustomDocumentProperties
.Add Name:="EigenerMerker", _
LinkToContent:=False, _
Type:=msoPropertyTypeNumber, _
Value:=0
End With
End If
Zähler = CLng(Application.ActiveWorkbook.CustomDocumentProperties("EigenerMerker").Value)
Zähler = Zähler + 1
strBandNr = Left([ComboBox6], 3) & Year(Date) & CStr(Format(Zähler, "0000"))
TextBox28 = strBandNr
Testbox37 = strSenderID

' Datenbankanbindung
Set condb = New ADODB.Connection

condb.Open "DRIVER=MySQL ODBC 3.51 Driver; SERVER=localhost; DATABASE=datenbank;USER=XXXX;PASSWORD=XXXX;"

Set rec = New ADODB.Recordset
rec.CursorLocation = adUseClient
rec.Open "SELECT * FROM `table ` ORDER BY `CompName1` ", condb, adOpenForwardOnly, adLockReadOnly

rec.MoveFirst
While Not rec.BOF
rec.Find "PhoneNo='" & ComboBox6.Text & "'"
If (Not rec.EOF) Or (Not rec.BOF) Then
TextBox39.Text = rec.Fields("PhoneNo")


Else
TextBox39.Text = "Keine Tel-nummer vorhanden"
rec.MoveNext
End If
Wend

End Sub

Im Form5 Start diesen -->

Sub Start()


Set condb = New ADODB.Connection
condb.Open "DRIVER=MySQL ODBC 3.51 Driver; SERVER=localhost; DATABASE=1stbp_sender;USER=root;PASSWORD=root;"
Dim rec As ADODB.Recordset
Set rec = New ADODB.Recordset
rec.CursorLocation = adUseClient
rec.Open "SELECT * FROM `table` ORDER BY `sender`.`CompName1` ", condb, adOpenForwardOnly, adLockReadOnly
rec.MoveFirst
While Not rec.EOF
UserForm5.ComboBox6.AddItem (rec.Fields(3))
UserForm5.ComboBox8.AddItem (rec.Fields(2))
rec.MoveNext
Wend
UserForm5.Show


End Sub


Hmmmmm - der Datensatz sollte aber doch da sein oder?

Gruß Manuel
misterdemeanor
misterdemeanor 14.02.2008 um 13:19:51 Uhr
Goto Top
Hallo manuel,

also auf ein Neues *g Hatte nach dem letzten Post von Dir eigentlich schon resigniert.
Um direkt einen zweiten Hieb auszuteilen: Zwei Dinge gefallen mir an Deinem Programmierstil ganz und gar nicht. Du benennst die Steuerelemente nicht. Wenn Du (oder jemand anderes) diesen Code liest blickt man nicht durch. Benenne sie einfach! ComboBox6 z.B. cboFirma oder TextBox37 txtPhone. Zweitens habe ich einige andere Threads von Dir gelesen. Für jeden Pfirlefanz baust Du immer eine neue Verbindung zu ein DB auf. Das ist sehr unfein. Eigentlich noch ein dritter Punkt: RTFM! Selbst die lokale Hilfe von Office/VBA/Excel/ADO beinhaltet viel wissenswertes. Nimm es mir bitte nicht übel. Will wirklich nicht klug###ern nur die Welt verbessern face-wink

Nun aber zu Deinem Problem...


Fehlermeldung -->

Entweder BOF oder EOF ist True, oder der
aktuelle Datnsatz wurde gelöscht. Der
angeforderte Vorgang benötigt einen
aktuellen Datensatz.

Kein Wunder wenn Du das eintippst:


Im Form5 hab ich bei Combobox6 aktualiseren
diesen Code -->

Private Sub ComboBox6_AfterUpdate()
...
Hier das erwähnte aufbauen einer Verbindung. Jedes mal wenn in der ComboBox etwas ausgewählt wird. Wie gesagtsehr unfein.
' Datenbankanbindung
Set condb = New ADODB.Connection

condb.Open "DRIVER=MySQL ODBC 3.51
Driver; SERVER=localhost;
DATABASE=datenbank;USER=XXXX;PASSWORD=XXXX;"

Set rec = New ADODB.Recordset
rec.CursorLocation = adUseClient
rec.Open "SELECT * FROM `table ` ORDER
BY `CompName1` ", condb,
adOpenForwardOnly, adLockReadOnly

rec.MoveFirst
Wenn ich das richtig verstehe ist Deine Sub Start im Klassenmodul von UserForm5, richtig? In einem vorigen Post gab ich Dir den Rat ein globales Recordset zu verwenden.
While Not rec.BOF
rec.Find "PhoneNo='"
& ComboBox6.Text &
"'"
Wenn in der ComboBox6 der Firmenname steht, in der Tabelle respektive dem RecordSet ein Feld mit Name PhoneNo existiert welches die Telefonnummern hält, macht es kein Sinn im Feld PhoneNo nach einem Firmennamen zu suchen...richtig?
rec.Find "firmenname='" & ComboBox6.Text & "'"  
Desweiteren würdest Du keine Schleife schreiben hättest Du mal nachgeschaut was die [RecordSet].Find Function anstellt! Was Du hier getipselt hast ist eine Endlosschleife die nur wegen einem Fehler nicht weitergeht.
If (Not rec.EOF) Or (Not rec.BOF)
Then
TextBox39.Text =
rec.Fields("PhoneNo")


Else
TextBox39.Text = "Keine
Tel-nummer vorhanden"
rec.MoveNext
End If
Wend

End Sub
Um dem Spuk mal ein Ende zu setzen poste ich Dir einfach mal folgenden Code (Klassenmodul UserForm5 mit ComboBox und Start Code). ComboBox_AfterUpdate war von mir schlecht gewählt, daher jetzt imChange-Event.

Private ConDB As ADODB.Connection 'im Klassenmodul verfügbare Connection  


Sub Start()
  Dim rec As ADODB.Recordset
  Set rec = New ADODB.Recordset
      'Einmaliges herstellen der Verbindung.  
    Set ConDB = New ADODB.Connection
    ConDB.Open "DRIVER=MySQL ODBC 3.51 Driver; SERVER=localhost; DATABASE=1stbp_sender;USER=root;PASSWORD=root;"  
    rec.CursorLocation = adUseClient
    rec.Open "SELECT * FROM `table` ORDER BY `sender`.`CompName1` ", ConDB, adOpenForwardOnly, adLockReadOnly  
    rec.MoveFirst
    While Not rec.EOF
      UserForm5.ComboBox6.AddItem (rec.Fields(3))
      UserForm5.ComboBox8.AddItem (rec.Fields(2))
      rec.MoveNext
    Wend
    rec.Close
    Set rec = Nothing
    UserForm5.Show
End Sub

Private Sub ComboBox6_Change()
  Dim strBandNr As String, Zähler As Long, strSenderID As String
  Dim rec As ADODB.Recordset
  
    If VarVorhanden("EigenerMerker") = False Then  
      With Application.ActiveWorkbook.CustomDocumentProperties
        .Add Name:="EigenerMerker", _  
        LinkToContent:=False, _
        Type:=msoPropertyTypeNumber, _
        Value:=0
      End With
    End If
    Zähler = CLng(Application.ActiveWorkbook.CustomDocumentProperties("EigenerMerker").Value)  
    Zähler = Zähler + 1
    strBandNr = Left([ComboBox6], 3) & Year(Date) & CStr(Format(Zähler, "0000"))  
    TextBox28 = strBandNr
    Testbox37 = strSenderID
    
    Set rec = New ADODB.Recordset
    rec.CursorLocation = adUseClient
        'Bitte noch die WHERE Klausel anpassen-->Firmenname  
    rec.Open "SELECT * FROM `table ` WHERE Firmenname='" & ComboBox6 & "'", ConDB, adOpenForwardOnly, adLockReadOnly  
      
      'Wenn das Recordset nun ein (oder mehrere) Firmennamen beinhaltet Telefonnummer in die TextBox  
      'Ggfls. reagieren wenn mehrere identische Firmennamen, bleibt Dir überlassen  
    If rec.RecordCount >= 1 Then
          'Prüfen ob im Feld PhoneNo Daten vorhanden  
      If (rec.Fields("PhoneNo") <> "") And Not IsNull(rec.Fields("PhoneNo")) Then  
        TextBox39.Text = rec.Fields("PhoneNo")  
      End If
    Else  'Dürfte nicht eintreten da Firmenname(Combobox) ja aus gleicher Tabelle  
      TextBox39.Text = "Keine Tel-nummer vorhanden"  
    End If
    rec.Close
    Set rec = Nothing
End Sub

Code ist nicht getestet, hoffe er geht.

BG, Felix -misterdemeanor-
manuel5
manuel5 15.02.2008 um 09:06:09 Uhr
Goto Top
Hallo Felix,

das mit den Benenungen der Steuerelemente - da haste auf alle Fälle recht! Das muss ich mir noch angewöhnen - find ich ja selber ne so optimal!

Das andere - Ich hab schon n "Start"-Modul mit der DB-Connection aufgebaut und dann den ComboBox6-Code aber im UserForm5 gelassen.
Die Verbindung dachte dich baut sich im Start-Modul auf und im Form tätigt er eben die entsprechenden Aktionen. Ok - ich hab jetzt mal deinen Code genommen.....Der is einleuchtend und auch verständlich - Danke dafür.

NUR!!! - Wenn ichs richtig verstanden habe - ich soll den ganzen Code in ein Klassenmodul eingeben? Was irgendwie ned haut da er nun das Start-Modul nimma findet.
Ehrlich gesagt mit Klassenmodulen hab ich mich noch NIE beschaeftigt - und wie du in meine Code siehst - noch nie angewandt! face-wink

Seis drum - Habe eben nun ein Klassenmodul welches ich clsUserForm5 genannt hab - ab wie gesagt - er findet das Makro fuer den Start nicht mehr.

Habe auch versucht den Connection-Code im Modul zu lassen - dann öffnet er mir zwar die Form aber er führt nichts mehr aus - auch nicht meine Merker. face-sad

Achja - die Hilfe vom VBA- und vom Office ansich - nehm ich grundsaetzlich immer erst her und frag dann in Foren nach - evetnl les ich aber auch diese Hilfen nie richtig durch? ..... face-wink

Also wenn du mir nun noch erkaleren magst wie ich die Klassenmodul ansorech - waere echt klasse

Gruß Manuel
misterdemeanor
misterdemeanor 15.02.2008 um 17:20:10 Uhr
Goto Top
Hi Manuel,

wir reden wohl irgendwie aneinander vorbei. Liegt aber an mir da ich schlicht und einfach das was Du schreibst falsch interpretiere. Hätten wir einmal 10 Minuten an einem Tisch gesessen wäre das sich nicht passiert.
Lass uns jetzt mal zusammenfassen. Wir haben im Grunde 3 Elemente die wir unterbringen wollen:

  1. Die Sub Start()
  2. Eine globale ADODB.Connection
  3. Der Ereignishandler für das Change Event der ComboBox6 (ComboBox6_Change)

1. und 2. kommen in ein Modul --> Standardmodul. Dann musst Du die Connection aber Public deklarieren (Public ConDB As ADODB.Connection). Hatte im letzten Post von Dir mal wieder etwas missverstanden. (Das Modul heißt wohl "Form5 Start"...?

3. Kommt dann in Dein UserForm-Code. Was ja dann wohl "Form 5" heißt. Das ist nebenbei gesagt ein Klassenmodul. Hast also doch schon desöfteren damit gearbeitet. face-wink

Alright, so sollte es jetzt eigentlicch funktionieren.

OK. Fand ich übrigens super das Du meine Kritik so "sportlich" genommen hast. Aber glaube mir: Vor allem üersichtlich geschriebener Code (u.a. eben Benennung der Controls) und Kommentare erleichtern das warten und erweitern mittelgroßer Applikationen ungemein. Nicht zuletzt hilft es auch Leuten in Foren wie hier z.B. den Durchblick zu bekommen.

UserForm5.ComboBox6.AddItem (rec.Fields(3))
z.B. ist nicht sehr Aussagekräftig. Es ist wirklich nur ein gut gemeinter Rat.

Schönes Wochenende

BG, Felix -misterdemeanor-
manuel5
manuel5 16.02.2008 um 12:18:03 Uhr
Goto Top
Servus Felix,

da haste recht - Wir haben sehr wohl an einigen Stellen aneinander vorbei geredet! face-smile
Nach deinem letzten Post - welchen ich mal "langsam" gelesen hab und auch das geschriebene mir verinnerlicht habe wurde mir einiges klar.
Verwirrt hat mich dieses Klassenmodul - das es das is was ich die ganze Zeit mache war mir nicht wirklich klar. Aber dein Satz --> Was ja dann wohl "Form 5" heißt. Das ist nebenbei gesagt ein Klassenmodul. --> da wars mir dann klar was du meinst.

Auf alle Fälle tuts jetzt! face-smile
Die cmds txts usw hab ich alle richtig bezeichnet - das is ne Sache die ich mir echt angewöhnen muß, aber das Excel-Sheet is nun ca 5 Jahre oder so alt und war zu Beginn mal nur n Form wo man Daten eingeben kann - ohne Schnickschnack und MySql und so. Is in laufe de Zeit eben gewachsen und jedesmal dachte ich mir "ach passt schon so" Der/die Leue konnten damit arbeiten und von daher.......

Nun gut - es gibt noch ein bis drei Dinge die noch gemacht werden müssen - welche aber nun dank deiner Hilfe eher von einfacher Natur sein dürften.


Ansonsten weiss ich ja wo ich dich finde! face-smile

Dann erstmal super Danke dafür
Und bis dann

Gruß Manuel