Accessdatenbank benutzen

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
mike41
Beiträge: 13
Registriert: 20.06.2006 09:00
Wohnort: Wassenberg
Kontaktdaten:

Accessdatenbank benutzen

Beitrag von mike41 »

Hi alle zusammen!

Hab mich seit langer Zeit mal wieder mit PB beschäftigt und festgestellt, dass es immer noch viele fragen zur Datenbankprogrammierung mit PB gibt.

Hier mal ein Code zum ausprobieren. Ist mit PB 4.0 getestet und funktioniert bei mir einwandfrei. :-)

Code: Alles auswählen

#ODBC_ADD_DSN = 1 
#ODBC_REMOVE_DSN = 3


  If InitDatabase() = 0 
    MessageRequester("ODBC Error", "Can't initialize the database drivers", #PB_MessageRequester_Ok) 

  EndIf 


Procedure db_Connect(num.l, dbFile.s, dbUser.s, dbPass.s) ;dbFile = vollständiger Datenbankpfad incl. name der Accessdatei


     
  dbName.s = GetFilePart(dbFile.s) 
  dbPath.s = GetPathPart(dbFile.s) 

  strAtt.s = "Server=MyOwnServer" + ";" 
  strAtt.s + "DSN="           + dbName.s + ";" 
  strAtt.s + "Description="   + dbName.s + ";" 
  strAtt.s + "DefaultDir=" + dbPath.s + ";" 
  strAtt.s + "DBQ="           + dbName.s + ";" 
  strAtt.s + "UID="           + dbUser.s + ";" 
  strAtt.s + "PWD="           + dbPass.s + ";" 
   
  MyMemory = AllocateMemory(Len(strAtt)) 
   
  CopyMemory(@strAtt, MyMemory, Len(strAtt)) 
   
  For L = 1 To Len(strAtt) 
    If PeekB(MyMemory + l - 1) = Asc(";") 
      PokeB(MyMemory  + l - 1, 0) 
    EndIf 
  Next L 
   
  Result = SQLConfigDataSource_(num, #ODBC_ADD_DSN, "Microsoft Access Driver (*.mdb)", MyMemory) 
   
  FreeMemory(MyMemory) 
     
  If Result 
   
     
    If OpenDatabase(num,  dbName.s,  dbUser.s,  dbPass.s) <> 0 
     
       
      ProcedureReturn 1 
    Else 
     
       
      MessageRequester("ODBC Error", "Can't open the database connection", #PB_MessageRequester_Ok) 
      ProcedureReturn 0 
    EndIf 
  Else 
    MessageRequester("ODBC Error", "Can't configure sql data source", #PB_MessageRequester_Ok) 
  ProcedureReturn -1 
  EndIf 
EndProcedure


Procedure db_Disconnect(num.l,dbName.s) ; dbName = Name des erstellten DSN


  strAtt.s + "DSN="           + dbName.s + ";" 
   
  MyMemory = AllocateMemory(Len(strAtt)) 
   
  CopyMemory(@strAtt, MyMemory, Len(strAtt)) 
   
  For L = 1 To Len(strAtt) 
    If PeekB(MyMemory + l - 1) = Asc(";") 
      PokeB(MyMemory  + l - 1, 0) 
    EndIf 
  Next L 
   
  Result = SQLConfigDataSource_(num, #ODBC_REMOVE_DSN, "Microsoft Access Driver (*.mdb)", MyMemory) 
   
  FreeMemory(MyMemory) 
     


EndProcedure
Dazu noch ein Beispiel zur Benutzung z.B. mit einem ListIconGadget

Code: Alles auswählen

Procedure Open_Window_1()
  If OpenWindow(#Window_1, 216, 50, 800, 600, "Kunden",  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
    
    DatabaseQuery(0,"select * from kunden")
    
    If CreateMenu(#MenuBar_1, WindowID(#Window_1))
      MenuTitle("Kunde")
      MenuItem(#MENU_9, "...anlegen")
      MenuItem(#MENU_10, "...bearbeiten")
      MenuItem(#MENU_11, "...löschen")
      MenuBar()
      MenuItem(#MENU_12, "Beenden")
      EndIf

      If CreateGadgetList(WindowID(#Window_1))
        ButtonGadget(#Button_0, 655, 95, 120, 25, "Rechnungsdaten")
        ButtonGadget(#Button_1, 655, 126, 120, 25, "Zusatzdaten")
        ButtonGadget(#Button_3, 655, 157, 120, 25, "Pkw")
        
        ;-
        ListIconGadget(#ListIcon_0, 35, 95, 600, 400, "KundenNr", 100, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
        AddGadgetColumn(#ListIcon_0, 1, "Vorname", 100)
        AddGadgetColumn(#ListIcon_0, 2, "Nachname", 100)
        AddGadgetColumn(#ListIcon_0, 3, "Telefon", 100)
        While NextDatabaseRow(0)
          KundenNr.s=GetDatabaseString(0,0)
          Vorname.s=GetDatabaseString(0,1)
          Nachname.s=GetDatabaseString(0,2)
          Telefon.s=GetDatabaseString(0,6)
          AddGadgetItem(#ListIcon_0,-1,KundenNr.s+Chr(10)+Vorname+Chr(10)+Nachname+Chr(10)+Telefon)
        Wend
        SetGadgetItemState(#ListIcon_0,0,#PB_ListIcon_Selected)
        
      EndIf
    EndIf
EndProcedure
StringGadgets füllen geht dann so:

Code: Alles auswählen

      DatabaseQuery(0,"select * from kunden where kundennr = '"+dbSelect+"'")
      NextDatabaseRow(0)
              
              KundenNr.s=GetDatabaseString(0,0)
              Vorname.s=GetDatabaseString(0,1)
              Nachname.s=GetDatabaseString(0,2)
              Adresse.s=GetDatabaseString(0,3)
              Ort.s=GetDatabaseString(0,4)
              Plz.s=GetDatabaseString(0,5)
              Telefon.s=GetDatabaseString(0,6)
              Mobil.s=GetDatabaseString(0,7)
              
              SetGadgetText(#String_0,KundenNr)
              SetGadgetText(#String_1,Vorname)
              SetGadgetText(#String_2,Nachname)
              SetGadgetText(#String_3,Adresse)
              SetGadgetText(#String_4,Ort)
              SetGadgetText(#String_5,Plz)
              SetGadgetText(#String_6,Telefon)
              SetGadgetText(#String_7,Mobil)
...und bearbeiten

Code: Alles auswählen

      KundenNr.s=GetGadgetText(#String_0)
      Vorname.s=GetGadgetText(#String_1)
      Nachname.s=GetGadgetText(#String_2)
      Adresse.s=GetGadgetText(#String_3)
      Ort.s=GetGadgetText(#String_4)
      Plz.s=GetGadgetText(#String_5)
      Telefon.s=GetGadgetText(#String_6)
      Mobil.s=GetGadgetText(#String_7)
      DatabaseUpdate(0,"update kunden set vorname='"+vorname+"',nachname='"+nachname+"',adresse='"+adresse+"',ort='"+ort+"',plz='"+plz+"',telefon='"+telefon+"',mobil='"+mobil+"' where kundennr='"+kundennr+"'")
     
      CloseWindow(#Window_2)
      DisableWindow(#Window_1,0)
      SetActiveWindow(#Window_1)
      DatabaseQuery(0,"select * from kunden")
      ClearGadgetItemList(#ListIcon_0)
      While NextDatabaseRow(0)
        KundenNr.s=GetDatabaseString(0,0)
        Vorname.s=GetDatabaseString(0,1)
        Nachname.s=GetDatabaseString(0,2)
        Telefon.s=GetDatabaseString(0,6)
        AddGadgetItem(#ListIcon_0,-1,KundenNr.s+Chr(10)+Vorname+Chr(10)+Nachname+Chr(10)+Telefon)
      Wend
      SetGadgetItemState(#ListIcon_0,0,#PB_ListIcon_Selected)
Ich hoffe es hilft ein wenig weiter :-)

Mfg Mike
Benutzeravatar
winduff
Beiträge: 879
Registriert: 10.02.2006 21:05
Wohnort: Gießen
Kontaktdaten:

Beitrag von winduff »

schaut cool aus, thanks!

Werds bei gelegenheit testen :allright:
Bild
AND51 hat geschrieben:...und ich würde dein Programm aus Wut zwei mal installieren, um eines genüsslicher löschen zu können, als das andere...
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Accessdatenbank benutzen

Beitrag von Kiffi »

Hallo mike41,

finde ich klasse, dass Du sofort mit Deinem ersten Beitrag einen nützlichen
Code hier der Allgemeinheit zur Verfügung stellst. :D

Allerdings gibt's die Funktionalitäten zum Erstellen und Entfernen einer DSN
bereits in den PBOSL (Userlib ExDatabase) ;-)

Dennoch: Mach weiter so! :allright:

Grüße ... Kiffi
Benutzeravatar
mike41
Beiträge: 13
Registriert: 20.06.2006 09:00
Wohnort: Wassenberg
Kontaktdaten:

Beitrag von mike41 »

Hi Kiffi,

hab ich mir auch gedacht. Leider funktionierte die ExDatabase bei mir nicht. Zeigte immer "external" Fehler an. Hängt wahrscheinlich mit der Version zusammen. Unter 3.94 funktionierte sie einwandfrei. Nur nicht unter 4.0.
In der neuesten PBOSL ist sie auch nicht mehr vorhanden.

Hab mir also kurzerhand eine eigene Include gebastelt unter Mithilfe von SQL Tutorial 4 von Paul Leischow.

Ausserdem ist es auch möglich durch einige Veränderungen sämtliche Treiber der ODBC über die ODBC-Api anzusprechen.

Leider weiss ich noch nicht wie man eigene Gadgets unter PB bastelt. Sonst würde ich mich mal daran machen, ein Datensteuerelement
wie in VB zu basteln.

Mfg Mike
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

PBOSL CreateGadget koennte dir sicherlich weiter helfen.

Wie du eine neue Fensterklasse registrierst steht hier im Forum
sicherlich auch irgendwo.
Benutzeravatar
mike41
Beiträge: 13
Registriert: 20.06.2006 09:00
Wohnort: Wassenberg
Kontaktdaten:

Beitrag von mike41 »

Danke dir Edel, werd mich mal umschauen :allright:
Benutzeravatar
mike41
Beiträge: 13
Registriert: 20.06.2006 09:00
Wohnort: Wassenberg
Kontaktdaten:

Beitrag von mike41 »

Hallo Zusammen,

nach einigen Überlegungen bin ich zu dem Schluß gekommen, dass ein Datensteuerelement unter PB nicht sinnvoll wäre. PB ist keine Form-basierte Entwicklungsumgebung wie z.B. VB. Man kann genauso gut den Code schreiben, da ein Gadget ja auch erst angesprochen werden muß, was in VB automatisch verläuft.

Als Arbeitserleichterung werde ich also eine DLL schreiben, die alle erforderlichen Befehle für eine Datenbank enthält.

Das hat den Vorteil, dass sie in jeder PB-Version angesprochen werden kann und die ODBC-API nach meinen Recherchen auch plattformübergreifend funktioniert.

Wie z.B. *recordset.add, *.moveNext ect.

Ich hatte mir vorgestellt sie so zu gestalten, dass auch SQL Unkungige sie leicht benutzen können.

Über den Stand der Dinge werd ich Euch natürlich informieren.

Falls ein Datensteuerelement doch erforderlich sein sollte, hängt es von der Breite der Masse ab, ob ich dennoch eines konstruiere. Das hätte den Nachteil, das die Registrierung des Gadgets wieder über die Windows-API läuft und somit auf eine Plattform beschrängt ist. (Dank an Edel für die Info von CreateGadget :allright: )

Mfg Mike
Benutzeravatar
Karl
Beiträge: 520
Registriert: 21.07.2005 13:57
Wohnort: zu Hause

Beitrag von Karl »

Es gibt ein Datensteuerelement (eigentlich ein ListIconGadget mit einer Verknüpfung zu einer Datenbank). Ist Shareware und irgendwo im Archiv gepostet.

Wieso willst du eine DLL machen? Kann ich mir so richtig nicht vorstellen. Mit SQL ist doch alles klar. Außerdem gibt es die mächtige SQLite3.dll.

Gruß Karl
The Kopyright Liberation Front also known as the justified ancients of Mumu!
PB 5.X
Benutzeravatar
mike41
Beiträge: 13
Registriert: 20.06.2006 09:00
Wohnort: Wassenberg
Kontaktdaten:

Beitrag von mike41 »

Hallo Karl,

ich weiss,dass es unorthodox ist eine Frage mit einer Gegenfrage zu beantworten.

Warum hat einer dieses ListIconGadget mit Datenanbindung gemacht? Ist doch alles klar mit Windows-API und ODBC.

Zeit ist Geld, warum soll ich mich mit ellenlangen SQL-Texten bemühen, wenn da jemand etwas einfacheres gemacht hat. Kein Fortschritt ohne Zeitgeist.

Ich möchte damit die Datenanbindung etwas vereinfachen. Es gibt auch viele Anfänger unter den Programmierern. Man kann schnell die Lust verlieren, wenn man dazu erst 1000 Seiten Bücher lesen muss.

Damit erfinde ich nicht das Rad neu! In VB sind einfache Datenanbindungen existent. Die haben sich auch die Mühe gemacht. Warum??

Sqlite3 ist sicherlich eine sehr starke Datenbank, aber eben nur Sqlite3.
Manche bevorzugen dBase oder Paradox, andere Access, weil sie nicht etliche Tabellen einzeln haben wollen. Jeder so wie er möchte. :wink:

Und ich möchte, dass andere davon profitieren. Sonst wäre ich nicht hier.

Gruß Mike
Benutzeravatar
mk-soft
Beiträge: 3845
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

Schönes Beispiel von Dir. Hatte ich auch schon mal gebraucht. Auch mit komprimmieren der Access Datenbank. Irgendwo wo gefunden und nach PB übersetzt.

Code: Alles auswählen


#ODBC_ADD_DSN = 1; // Add data source 
#ODBC_CONFIG_DSN = 2; // Configure (edit) Data source 
#ODBC_REMOVE_DSN = 3; // Remove data source
#ODBC_ADD_SYS_DSN = 4; // add a system DSN 
#ODBC_CONFIG_SYS_DSN = 5; // Configure a system DSN 
#ODBC_REMOVE_SYS_DSN = 6; // remove a system DSN 
#ODBC_REMOVE_DEFAULT_DSN = 7; // remove the default DSN


;function SQLConfigDataSource( hwndParent: HWND; fRequest: WORD; lpszDriver: LPCSTR;
;lpszAttributes: LPCSTR): BOOL; stdcall; external 'ODBCCP32.DLL';

Procedure.l AddDSN(databasename.s, user.s, pass.s) 

  name.s = GetFilePart(databasename.s) : name.s = Left(name.s, Len(name.s) - 4)
  strDriver.s = "Microsoft Access Driver (*.mdb)"
  strAttributes.s = "Server=APServer;Description=" + name
  strAttributes.s + ";DSN=" + name
  strAttributes.s + ";DBQ=" + databasename 
  strAttributes.s + ";UID=" + user 
  strAttributes.s + ";PWD=" + pass + ";"  
  
  MyMemory = AllocateMemory(Len(strAttributes))  ; Allocate the memory you need here 
  CopyMemory(@strAttributes, MyMemory, Len(strAttributes))      ; Copy the database information string into the memory space 
  
  For L = 1 To Len(strAttributes)                               ; Check the string in the memory space now 
    If PeekB(MyMemory + L - 1) = Asc(";")                       ; If you find a semicolon anywhere in the string 
      PokeB(MyMemory + L - 1, 0)                                ; Replace it with an empty character as the driver doesn't use it 
    EndIf                                                       ; End the current check 
  Next L                                                        ; Check the next byte 
  
  result = SQLConfigDataSource_(0, #ODBC_ADD_DSN, strDriver, MyMemory)   ; Call the function you need from the ODBC library with the right details 
    
  FreeMemory(MyMemory)                                     ; Free the memory now 

  ProcedureReturn result

EndProcedure
  

Procedure.l RemoveDSN(databasename.s, user.s, pass.s) 

  name.s = GetFilePart(databasename.s) : name.s = Left(name.s, Len(name.s) - 4)
  strDriver.s = "Microsoft Access Driver (*.mdb)"
  strAttributes.s = "DSN=" + name + ";"
  
  MyMemory = AllocateMemory(Len(strAttributes))  ; Allocate the memory you need here 
  CopyMemory(@strAttributes, MyMemory, Len(strAttributes))      ; Copy the database information string into the memory space 
  
  For L = 1 To Len(strAttributes)                               ; Check the string in the memory space now 
    If PeekB(MyMemory + L - 1) = Asc(";")                       ; If you find a semicolon anywhere in the string 
      PokeB(MyMemory + L - 1, 0)                                ; Replace it with an empty character as the driver doesn't use it 
    EndIf                                                       ; End the current check 
  Next L                                                        ; Check the next byte 
  
  result = SQLConfigDataSource_(0, #ODBC_REMOVE_DSN, strDriver, MyMemory)   ; Call the function you need from the ODBC library with the right details 
    
  FreeMemory(MyMemory)                                     ; Free the memory now 

  ProcedureReturn result

EndProcedure
  

Procedure.l RepairDB(databasename.s, user.s, pass.s) 

  name.s = GetFilePart(databasename.s) : name.s = Left(name.s, Len(name.s) - 4)
  strDriver.s = "Microsoft Access Driver (*.mdb)"
  strAttributes.s + "REPAIR_DB=" + databasename 
  strAttributes.s + ";UID=" + user 
  strAttributes.s + ";PWD=" + pass + ";"
  
  MyMemory = AllocateMemory(Len(strAttributes))  ; Allocate the memory you need here 
  CopyMemory(@strAttributes, MyMemory, Len(strAttributes))      ; Copy the database information string into the memory space 
  
  For L = 1 To Len(strAttributes)                               ; Check the string in the memory space now 
    If PeekB(MyMemory + L - 1) = Asc(";")                       ; If you find a semicolon anywhere in the string 
      PokeB(MyMemory + L - 1, 0)                                ; Replace it with an empty character as the driver doesn't use it 
    EndIf                                                       ; End the current check 
  Next L                                                        ; Check the next byte 
  
  result = SQLConfigDataSource_(0, #ODBC_ADD_DSN, strDriver, MyMemory)   ; Call the function you need from the ODBC library with the right details 
    
  FreeMemory(MyMemory)                                     ; Free the memory now 

  ProcedureReturn result

EndProcedure
  

Procedure.l CompactDB(databasename.s, user.s, pass.s) 

  name.s = GetFilePart(databasename.s) : name.s = Left(name.s, Len(name.s) - 4)
  strDriver.s = "Microsoft Access Driver (*.mdb)"
  strAttributes.s + "COMPACT_DB=" + databasename + " " + databasename + " General"
  strAttributes.s + ";UID=" + user 
  strAttributes.s + ";PWD=" + pass + ";"
    
  MyMemory = AllocateMemory(Len(strAttributes))  ; Allocate the memory you need here 
  CopyMemory(@strAttributes, MyMemory, Len(strAttributes))      ; Copy the database information string into the memory space 
  
  For L = 1 To Len(strAttributes)                               ; Check the string in the memory space now 
    If PeekB(MyMemory + L - 1) = Asc(";")                       ; If you find a semicolon anywhere in the string 
      PokeB(MyMemory + L - 1, 0)                                ; Replace it with an empty character as the driver doesn't use it 
    EndIf                                                       ; End the current check 
  Next L                                                        ; Check the next byte 
  
  result = SQLConfigDataSource_(0, #ODBC_ADD_DSN, strDriver, MyMemory)   ; Call the function you need from the ODBC library with the right details 
    
  FreeMemory(MyMemory)                                     ; Free the memory now 

  ProcedureReturn result

EndProcedure
  

Procedure.l CompactDB2(databasename1.s, databasename2.s, user.s, pass.s) 

  name.s = GetFilePart(databasename.s) : name.s = Left(name.s, Len(name.s) - 4)
  strDriver.s = "Microsoft Access Driver (*.mdb)"
  strAttributes.s + "COMPACT_DB=" + databasename1 + " " + databasename2 + " General"
  strAttributes.s + ";UID=" + user 
  strAttributes.s + ";PWD=" + pass + ";"
    
  MyMemory = AllocateMemory(Len(strAttributes))  ; Allocate the memory you need here 
  CopyMemory(@strAttributes, MyMemory, Len(strAttributes))      ; Copy the database information string into the memory space 
  
  For L = 1 To Len(strAttributes)                               ; Check the string in the memory space now 
    If PeekB(MyMemory + L - 1) = Asc(";")                       ; If you find a semicolon anywhere in the string 
      PokeB(MyMemory + L - 1, 0)                                ; Replace it with an empty character as the driver doesn't use it 
    EndIf                                                       ; End the current check 
  Next L                                                        ; Check the next byte 
  
  result = SQLConfigDataSource_(0, #ODBC_ADD_DSN, strDriver, MyMemory)   ; Call the function you need from the ODBC library with the right details 
    
  FreeMemory(MyMemory)                                     ; Free the memory now 

  ProcedureReturn result

EndProcedure
  

Procedure.l CreateDB(databasename.s, user.s, pass.s) 

  name.s = GetFilePart(databasename.s) : name.s = Left(name.s, Len(name.s) - 4)
  strDriver.s = "Microsoft Access Driver (*.mdb)"
  strAttributes.s + "CREATE_DB=" + databasename + " General"
  strAttributes.s + ";UID=" + user
  strAttributes.s + ";PWD=" + pass + ";"
  
  MyMemory = AllocateMemory(Len(strAttributes))  ; Allocate the memory you need here 
  CopyMemory(@strAttributes, MyMemory, Len(strAttributes))      ; Copy the database information string into the memory space 
  
  For L = 1 To Len(strAttributes)                               ; Check the string in the memory space now 
    If PeekB(MyMemory + L - 1) = Asc(";")                       ; If you find a semicolon anywhere in the string 
      PokeB(MyMemory + L - 1, 0)                                ; Replace it with an empty character as the driver doesn't use it 
    EndIf                                                       ; End the current check 
  Next L                                                        ; Check the next byte 
  
  result = SQLConfigDataSource_(0, #ODBC_ADD_DSN, strDriver, MyMemory)   ; Call the function you need from the ODBC library with the right details 
    
  FreeMemory(MyMemory)                                     ; Free the memory now 

  ProcedureReturn result

EndProcedure
  

Procedure.l CreateV2DB(databasename.s, user.s, pass.s) 

  name.s = GetFilePart(databasename.s) : name.s = Left(name.s, Len(name.s) - 4)
  strDriver.s = "Microsoft Access-Treiber (*.mdb)"
  strAttributes.s + "CREATE_V2DB=" + databasename
  strAttributes.s + ";UID=" + user
  strAttributes.s + ";PWD=" + pass + ";"
  
  MyMemory = AllocateMemory(Len(strAttributes))  ; Allocate the memory you need here 
  CopyMemory(@strAttributes, MyMemory, Len(strAttributes))      ; Copy the database information string into the memory space 
  
  For L = 1 To Len(strAttributes)                               ; Check the string in the memory space now 
    If PeekB(MyMemory + L - 1) = Asc(";")                       ; If you find a semicolon anywhere in the string 
      PokeB(MyMemory + L - 1, 0)                                ; Replace it with an empty character as the driver doesn't use it 
    EndIf                                                       ; End the current check 
  Next L                                                        ; Check the next byte 
  
  result = SQLConfigDataSource_(0, #ODBC_ADD_DSN, strDriver, MyMemory)   ; Call the function you need from the ODBC library with the right details 
    
  FreeMemory(MyMemory)                                     ; Free the memory now 

  ProcedureReturn result

EndProcedure
  
FF :wink: [/code]
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Antworten