Problem mit Exel

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
sebsch80
Beiträge: 53
Registriert: 28.09.2006 20:28
Wohnort: Suhl
Kontaktdaten:

Problem mit Exel

Beitrag von sebsch80 »

Hallo!!!

Ich hab da ein Problem. Ich wollte eine Exel Tabelle in PureBasic verwenden.
Da ich aber ein absoluter Anfänger bin, hab ich keinen Plan wie ich das bewerkstelligen soll.

Also meine Frage:
Ist es überhaupt möglich Daten aus einer ExelTabelle einzulesen, sie dann zu berechnen und in einem Fenster auszugeben?

Wenn ja wie und mit welchen Befehlen?

Weiß jemand ob es zu diesem Thema ein Tutorial gibt?
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Siehe hier: http://www.purebasic.fr/german/viewtopi ... iptcontrol
Beispiel für Excel-Tabelle ist bei.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
mk-soft
Beiträge: 3845
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

Mit SQL -> OpenDatabase()

Code: Alles auswählen

;-TOP
; Kommentar : Excel Tabelle lesen über SQL
; Version   : v1.01
; Author    : Michael Kastner
; Datei     : FcDatabase.pb
; Erstellt  : 28.09.2006
; Geändert  : 

; ***************************************************************************************

#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

; ***************************************************************************************

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

  name.s = GetFilePart(databasename.s)
  name = Left(name.s, Len(name.s) - 4)
  name = "Pure" + name
  Select UCase(driver)
    Case "ACCESS"
      strDriver.s = "Microsoft Access Driver (*.mdb)"
    Case "EXCEL"
      strDriver.s = "Microsoft Excel Driver (*.xls)"
    Default
      strDriver.s = driver
  EndSelect
  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 
  
  If result
    ProcedureReturn name
  Else
    ProcedureReturn ""
  EndIf

EndProcedure
  
; ***************************************************************************************

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

  name.s = GetFilePart(databasename.s)
  name = Left(name.s, Len(name.s) - 4)
  name = "Pure" + name
  
  Select UCase(driver)
    Case "ACCESS"
      strDriver.s = "Microsoft Access Driver (*.mdb)"
    Case "EXCEL"
      strDriver.s = "Microsoft Excel Driver (*.xls)"
    Default
      strDriver.s = driver
  EndSelect
  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
  
; ***************************************************************************************

;- Test

#Datenbank = 0

InitDatabase()

Path.s = "D:\Daten\PureBasic4\Database\Telefon.xls"
; DSN anlegen
Base.s = AddDSN("Excel", Path,"","")
If Base
  Debug "DSN=" + Base
  If OpenDatabase(#Datenbank, Base, "", "")
    sql.s = "Select * From [Tabelle1$]"
    If DatabaseQuery(#Datenbank, sql) ; Ermittelt alle Einträge in der 'employee' Tabelle
      Spalten = DatabaseColumns(#Datenbank) - 1
      temp.s = ""
      For Spalte = 0 To Spalten
        temp + DatabaseColumnName(#Datenbank, Spalte) + ";"
      Next
      Debug temp
      While NextDatabaseRow(#Datenbank)  ; alle Einträge durchlaufen
        temp.s = ""
        For Spalte = 0 To Spalten
          temp + GetDatabaseString(#Datenbank, Spalte) + ";"
        Next
        Debug temp
      Wend

    EndIf
  EndIf
EndIf
; DSN am Ende entfernen
RemoveDSN("Excel", path, "", "")

Erst wird eine Benutzer DSN angelegt und mit SQL-Statement die Tabelle gelesen. Am Ende die Benutzer DSN wieder löschen.

Excel Tabellen Namen mit "$" erweitern im SQL-Statement


FF :wink:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Damit das ganze auch mit Dateinamen funktioniert, die Leerzeichen
beinhalten, hab ich in der AddDSN-Procedure folgende Zeile geändert:

Code: Alles auswählen

strAttributes + ";DBQ=" + Chr(34) + databasename + Chr(34)
Aber ein Problem gibt es da noch. Ich erhalte folgenden Fehler bei
OpenDatabase():
[Microsoft][ODBC Excel driver] Aktualisieren nicht möglich; Datenbank oder Objekt ist schreibgeschützt.
Was hat das zu bedeuten, wenn ich die Datei nicht geöffnet habe oder
sonstwas. Ich hab sie nicht einmal im Explorer markiert.
Benutzeravatar
Karl
Beiträge: 520
Registriert: 21.07.2005 13:57
Wohnort: zu Hause

Beitrag von Karl »

Im ODBC-Dialog gibt es speziell für Exceldateien bei Optionen so´n Haken für schreibgeschützt. Der ist eigentlich standardmäßig aktiviert. Kann sein, dass das die Quelle des Übels ist.

OK, ist eigentlich nur bei Updates interessant.

Ich habe mal den Code ausprobiert (mk-soft). Geht auch wunderbar mit Dateinamen, die Leerzeichen enthalten. Wahrscheinlich interpretiert er die Anführungsstriche zum Dateinamen und findet keinen solchen?


Gruß Karl
The Kopyright Liberation Front also known as the justified ancients of Mumu!
PB 5.X
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Das Problem ist, dass ohne die Anführungszeichen Base = "" ist.

Sorry, dass ich jetzt so blöd frage, aber ich hab mich mit dem ODBC-Zeugs
noch nie auseinandergesetzt:

Wo gibt es denn den ODBC-Dialog?
Muss ich das für jede Excel-Datei einzeln einstellen oder einfach nur global?

Wäre schön, wenn mich da jemand mal so von Grund auf aufklären könnte.
Also Danke schonmal, wenn's jemand schafft mir zu helfen. <)

sebsch80:
Hab mal die Ausrufezeichen in deinem Thread-Titel gelöscht. Sie waren zu
aufdringlich.
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »

Für jeden ODBCEintrag
Exceltabellen werden einzeln im ODBCManager eingetragen.


Mir fällt zu Excel und ODBC noch ein, das man die Exceltabellen sich
vorher gut angucken und eventuell editieren sollte. Häufig fehlen
Eindeutigkeiten wie aufnumerierte Indexnummern, so daß die
Bearbeitung per SQL dann schwierig wird.

Außerdem muss (!) man einen oder mehrere Bereiche mit Namen
versehen (Spalten auswählen (sollte nicht zu groß sein sonst wirds arschlahm) und oben links in Namenfeld einen Namen eintragen).
Das geht auch blätterübergreifend.
Dies(r)e Name(n) tauch(t)(en) dann in der ODBC-Verknüpfung als
Tabelle(n) auf.
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
Benutzeravatar
mk-soft
Beiträge: 3845
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

@NicTheQuick

Mit Anführungszeichen geht es bei mir gar nicht. Mit Leerzeichen funktioniert es bei mir auch.

Als Datenbanktreiber habe ich für Excel und Access die englischen Treiber gewählt. In der Regel sind diese bei Windows immer mit installiert.

"Microsoft Access Driver (*.mdb)"
"Microsoft Excel Driver (*.xls)"

Vielleicht mal Prüfen welche Datenbank Treiber installiert sind.

START -> Ausführen -> odbcad32

Mögliche Treiber sind noch.
"Microsoft Access-Treiber (*.mdb)"
"Microsoft Excel-Treiber (*.xls)"

Für CSV und TXT Dateien
"Microsoft Text Driver (*.txt; *.csv)"
"Microsoft Text-Treiber (*.txt; *.csv)"

Code: Alles auswählen

Driver.s = "Microsoft Excel-Treiber (*.xls)"
Base.s = AddDSN(Driver, Path,"","")
oder CSV, TXT

Code: Alles auswählen

Driver.s = "Microsoft Text Driver (*.txt; *.csv)"
Base.s = AddDSN(Driver, Path,"","")
FF :wink:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
mk-soft
Beiträge: 3845
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

Ich habe das ganze noch mal etwas umgestaltet.

Denn zu verwendeten Treiber Optional auf den letzten Parameter.
Wenn dieser nicht mit angegeben wird, wählt das Programm automatisch aus der Extension den richtigen Treiber aus.

Code: Alles auswählen

;-TOP
; Kommentar : Excel Tabelle lesen über SQL
; Version   : v1.01
; Author    : Michael Kastner
; Datei     : FcDatabase.pb
; Erstellt  : 28.09.2006
; Geändert  : 

; ***************************************************************************************

#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

; ***************************************************************************************

Procedure.s AddDSN(databasename.s, user.s, pass.s, driver.s = "") ; Result DSN

  ; Databasename erzeugen (DSN)
  name.s = GetFilePart(databasename)
  name = Left(name.s, Len(name.s) - 4)
  name = "Pure" + name
  ; Bei fehlenden driver automatisch wählen
  If driver = ""
    driver = GetExtensionPart(databasename)
  EndIf
  ; Datenbanktreiber auswählen
  Select UCase(driver)
    Case "ACCESS", "MDB"
      strDriver.s = "Microsoft Access Driver (*.mdb)"
    Case "EXCEL", "XLS"
      strDriver.s = "Microsoft Excel Driver (*.xls)"
    Case "DBASE", "DBF"
      strDriver.s = "Microsoft dBase Driver (*.dbf)"
    Case "TEXT", "TXT", "CSV"
      strDriver.s = "Microsoft Text Driver (*.txt; *.csv)"
    Default
      strDriver.s = driver
  EndSelect
  ; Attributes zustellen
  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 
  
  If result
    ProcedureReturn name
  Else
    ProcedureReturn ""
  EndIf

EndProcedure
  
; ***************************************************************************************

Procedure.l RemoveDSN(databasename.s, user.s, pass.s, driver.s = "") 

  ; Databasename erzeugen
  name.s = GetFilePart(databasename)
  name = Left(name.s, Len(name.s) - 4)
  name = "Pure" + name
  ; Bei fehlenden driver automatisch wählen
  If driver = ""
    driver = GetExtensionPart(databasename)
  EndIf
  ; Datenbanktreiber auswählen
  Select UCase(driver)
    Case "ACCESS", "MDB"
      strDriver.s = "Microsoft Access Driver (*.mdb)"
    Case "EXCEL", "XLS"
      strDriver.s = "Microsoft Excel Driver (*.xls)"
    Case "DBASE", "DBF"
      strDriver.s = "Microsoft dBase Driver (*.dbf)"
    Case "TEXT", "TXT", "CSV"
      strDriver.s = "Microsoft Text Driver (*.txt; *.csv)"
    Default
      strDriver.s = driver
  EndSelect
  ; Attributes zustellen
  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
  
; ***************************************************************************************

;- Test

#Datenbank = 0

InitDatabase()

Path.s = "D:\Daten\PureBasic4\Database\Telefon Liste.xls"
; DSN anlegen
Base.s = AddDSN(Path,"","") 

If Base
  Debug "DSN=" + Base
  If OpenDatabase(#Datenbank, Base, "", "")
    sql.s = "Select * From [Tabelle1$]"
    If DatabaseQuery(#Datenbank, sql) ; Ermittelt alle Einträge in der 'employee' Tabelle
      Spalten = DatabaseColumns(#Datenbank) - 1
      temp.s = ""
      For Spalte = 0 To Spalten
        temp + DatabaseColumnName(#Datenbank, Spalte) + ";"
      Next
      Debug temp
      While NextDatabaseRow(#Datenbank)  ; alle Einträge durchlaufen
        temp.s = ""
        For Spalte = 0 To Spalten
          temp + GetDatabaseString(#Datenbank, Spalte) + ";"
        Next
        Debug temp
      Wend

    EndIf
  EndIf
EndIf
; DSN am Ende entfernen
RemoveDSN(path, "", "")

FF :wink:

P.S. Bei TXT und CSV läuft es etwas anders. Die DSN wird zwar angelegt, aber nur auf den Path zu den Tabellen. In der SQL Abfrage muss dann die Datei mit angegeben werden.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

@mk-soft
Danke, sehr brauchbar :allright:

PS: Mit Variablendeklaration wäre es schöner

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Antworten