Wie lese ich einen Tabellennamen einer Datenbank (Excel)aus?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
mpz
Beiträge: 505
Registriert: 14.06.2005 15:53
Computerausstattung: Win 11 Pro, 48 GB Ram, Intel I7 CPU und RX4070 Grafikkarte, PB (4/5) 6.12LT
Wohnort: Berlin, Tempelhof

Wie lese ich einen Tabellennamen einer Datenbank (Excel)aus?

Beitrag von mpz »

Hallo Leute,

ich muss arbeitstechnisch mit zwei Exceltabellen arbeiten, die ich vergleiche um eine Ergebnissdatei zu erzeugen. Bisher habe ich die XLTable.dll verwendet, was nicht schön ist, aber leidlich funktioniert.

Die aber wesendlichen Nachteile:
Das Einlesen einer großen Datenbank dauert laaaannnge.
Das Auslesen von "Double" und anderen Variablen ist unmöglich, alleine eine Datumsangabe wird zu eine interessanten Zifferfolge, von Umlauten ganz zu schweigen!

Kurzum etwas anderes muss her.

Ich habe mich daher einmal etwas mit dem ODBC Dateisystem beschäftigt und mir fehlt nur noch die Möglichkeit den Namen der "Tabelle" einer Exceldatei auszulesen. Natürlich kann ich die Exceldatei mit Excel öffnen und den Tabellennamen "lesen". Es muss doch aber eine einfache andere Möglichkeit geben...

In der Beispieldatei heißt meine Tabelle "German users 030406", aber woher nehmen wenn man diesen Namen nicht kennt?

Mein Beispielcode:

Code: Alles auswählen

; English forum: 
; Author: Rings (updated for PB3.92+ by Lars)
; Date: 05. May 2003

; Notes: This example works fine for Access, if you want to make a DSN connection to a MsSQL 2000 Server
; then create your dsn by hand or read the docu about M$-sql-server carefully. 

; Enhanced Database example 
;by Siegfried Rings (CodeGuru) 

; little changes from Michael Paulwitz works with PB4.00
; Date: 19.7.2006


File$ = "C:\TestDB.mdb" 
#ODBC_ADD_DSN = 1 ; Add Data source 
#ODBC_CONFIG_DSN = 2 ; Configure (edit) Data source 
#ODBC_REMOVE_DSN = 3 ; Remove Data source 
Procedure Makeconnection(Driver.s,strAttributes.s) 

  Result=OpenLibrary(1,"ODBCCP32.DLL") 
  If Result 
    lpszDriver.s=Driver 
    MyMemory=AllocateMemory(Len(strAttributes)) 
    CopyMemory(@strAttributes,MyMemory,Len(strAttributes)) 
    For l=1 To Len(strAttributes ) 
      If PeekB(MyMemory +l-1)=Asc(";"):PokeB(MyMemory +l-1,0):  EndIf 
    Next l 
    Result = CallFunction(1, "SQLConfigDataSource", 0,#ODBC_ADD_DSN,lpszDriver.s,MyMemory ) 
    NewResult=SQLConfigDataSource_(0,#ODBC_ADD_DSN,lpszDriver.s,MyMemory ) 
    
    FreeMemory(MyMemory) 
    CloseLibrary(1) 
    If Result 
      ProcedureReturn 1 
    EndIf 
  EndIf 
EndProcedure
 
Procedure DeleteConnection(Driver.s,DSN.s) 
  Result=OpenLibrary(1,"ODBCCP32.DLL") 
  If Result 
    lpszDriver.s=Driver 
    strAttributes.s = "DSN="+DSN 
    Result = CallFunction(1, "SQLConfigDataSource", 0,#ODBC_REMOVE_DSN,lpszDriver.s,strAttributes ) 
    CloseLibrary(1) 
    If Result 
      ProcedureReturn 1;MessageRequester("Info","DSN Delete",0) 
    EndIf 
  EndIf 
EndProcedure 

MeinPointer.l 
Procedure GetDBHandle() 
  Shared MeinPointer.l 
  !EXTRN _PB_DataBase_CurrentObject;_PB_DataBase_CurrentObject 
  !MOV dword Eax,[_PB_DataBase_CurrentObject] 
  !MOV dword [v_MeinPointer], Eax 
  ProcedureReturn MeinPointer 
EndProcedure 

File$ = OpenFileRequester("PureBasic - Open", GetCurrentDirectory()+"*.xls", "Microsoft Access (*.mdb)|*.mdb;*.bat|Microsoft Excel (*.xls)|*.xls", 1) 
; File$ = "C:\TestDB.mdb" 
If File$<>"" 
  ;MessageRequester("Information", "Selected File: "+File$, 0); 
Else 
  End 
EndIf 

EXT.s=UCase(GetExtensionPart(File$)) 
Select EXT 
  Case "MDB" 
    Result=Makeconnection("Microsoft Access Driver (*.mdb)","Server=SomeServer; Description=Description For Purebasic MDB-ODBC;DSN=PureBasic_DSN;DBQ="+File$+";UID=Rings;PWD=Siggi;") 
  Case "XLS" 
    Result=Makeconnection("Microsoft Excel Driver (*.xls)","DSN=PureBasic_DSN;Description=Description For Purebasic Excel;FileType=Excel97;DBQ="+File$+";") 
EndSelect 

If InitDatabase() = 0 
  MessageRequester("Error", "Can't initialize Database (ODBC v3 or better) environment", 0) 
  End 
EndIf 

OpenConsole() 

Dim DatabaseType.s(5) 
DatabaseType(0) = "Unknown" ; Unbekannt
DatabaseType(1) = "Numeric" ; Numerisches Format: Long (.l) in PureBasic
DatabaseType(2) = "String"  ; String-Format:  String (.s) in PureBasic
DatabaseType(3) = "Float"   ; Numerisches Fließkomma-Format:  Float (.f) in PureBasic
DatabaseType(4) = "Double"  ; Numerisches Double-Format:  Double (.d) in PureBasic
DatabaseType(5) = "Quad"    ; Numerisches Quad-Format:  Quad (.q) in PureBasic


; First, let's see which drivers are attached to the system.. 
; 
PrintN("Available drivers:") 
PrintN("") 

If ExamineDatabaseDrivers() 
  While NextDatabaseDriver() 
    PrintN(DatabaseDriverName()+" - "+DatabaseDriverDescription()) 
  Wend 
EndIf 

; Open an ODBC database 
; 
;'If OpenDatabaseRequester(0) 
User$="" 
Password$="" 

#Database=1 
Result = OpenDatabase(#Database, "PureBasic_DSN", User$, Password$) 

If Result 
  Browse$="Select * from [German users 030406$]" 

; [German users 030406$] wie bekomme ich diesen Tabellennamen automatisch raus wenn ich Ihn nicht kenne?!?

  PrintN("") 
  PrintN("Database successfully opened !") 
  
  
  PrintN("Type EXIT to quit.") 
  PrintN("or anything else to browse database") 
  
  Repeat 
    Command$ = Input() 
    Select UCase(Command$) 
      Case "EXIT" 
        Quit = 1 
        
      Default 
        
        If DatabaseQuery(#Database,Browse$) 
          
          NbColumns = DatabaseColumns(#Database) 
          PrintN("NbColums: " + Str(NbColumns)) 
          
          ; only for information
          For k=0 To NbColumns-1 
            PrintN(DatabaseColumnName(#Database,k) + " - " + DatabaseType(DatabaseColumnType(#Database,k))) 
          Next 
         
          ; Read all database informations 
          While NextDatabaseRow(#Database)
           For k=0 To NbColumns-1
             Select DatabaseColumnType(#Database,k)
                 Case 1
                    Print ( Str(GetDatabaseLong(#Database,k))+"/")
                 Case 2 
                    Print ( GetDatabaseString(#Database,k)+"/")
                 Case 3
                    Print ( Str(GetDatabaseFloat(#Database,k))+"/")
                 Case 4
                    Print ( Str(GetDatabaseDouble(#Database,k))+"/")
                 Case 5
                    Print ( Str(GetDatabaseQuad(#Database,k))+"/")
                 Default
                    Print ("unknown information/")
                 EndSelect
           Next
           PrintN("")
           Command$ = Input() ; The next database entry please
           
          Wend 
          
          PrintN("") 
          Print ("Press return to continue") : Input() 
          PrintN("") 
          PrintN("Query Result -------------------------------------") 
         
         
          PrintN("--------------------------------------------------") 
        Else 
          PrintN("Bad Query !") 
        EndIf 
    EndSelect 
  Until Quit = 1 
Else 
  MessageRequester("Info", "Operation canceled", 0) 
EndIf 

;and delete: 
DeleteConnection("Microsoft Access Driver (*.mdb)","PureBasic_DSN") 

; ExecutableFormat=Windows
; FirstLine=1
; EOF
Working on :lol: - LibSGD - MP3D Engine - 8)
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Wie lese ich einen Tabellennamen einer Datenbank (Excel)

Beitrag von Kiffi »

> In der Beispieldatei heißt meine Tabelle "German users 030406", aber
> woher nehmen wenn man diesen Namen nicht kennt?

eine Möglichkeit, den Namen aller Blätter in einer Excel-Datei zu ermitteln,
ist der, diese mit VBS auszulesen. Mit dem Scriptcontrol von ts-soft ist das
ein leichtes Unterfangen.

Code: Alles auswählen

Procedure.s GetWorksheetNamesVbs(ExcelFile.s)
  
	Protected VBS$
  
	VBS$ + #CRLF$
	VBS$ + "Set xlApp = CreateObject(" + Chr(34) + "Excel.Application" + Chr(34) + ")" + #CRLF$
	VBS$ + "xlApp.Visible = False" + #CRLF$
	VBS$ + "xlApp.Workbooks.Open " + Chr(34) + ExcelFile.s + Chr(34) + #CRLF$
	VBS$ + #CRLF$
	VBS$ + "For Each wS In xlApp.Worksheets" + #CRLF$
	VBS$ + "	strWorksheets = strWorksheets & wS.Name & " + Chr(34) + ";" + Chr(34) + #CRLF$
	VBS$ + "Next" + #CRLF$
	VBS$ + "If Right(strWorksheets, 1) = " + Chr(34) + ";" + Chr(34) + " Then " + #CRLF$
	VBS$ + "  strWorkSheets = Left(strWorkSheets, Len(strWorkSheets) - 1)" + #CRLF$
	VBS$ + "End If" + #CRLF$
	VBS$ + #CRLF$
	VBS$ + "xlApp.Workbooks.Close" + #CRLF$
  
	ProcedureReturn VBS$
  
EndProcedure

SCtr_AddCode(GetWorksheetNamesVbs([DeineExcelMappe]))

Debug SCtr_EvalStr("strWorksheets")
Du musst halt nur darauf achten, dass Du die Blattnamen ausliest, bevor
Du die Excel-Datei mit dem Datenbanktreiber öffnest.

Zugegebenermaßen ist das nicht besonders elegant, aber es funktioniert ;-)

Grüße ... Kiffi
a²+b²=mc²
Benutzeravatar
mpz
Beiträge: 505
Registriert: 14.06.2005 15:53
Computerausstattung: Win 11 Pro, 48 GB Ram, Intel I7 CPU und RX4070 Grafikkarte, PB (4/5) 6.12LT
Wohnort: Berlin, Tempelhof

Beitrag von mpz »

Danke für die Antwort.

Ist auf jedemfall eine Möglichkeit. Was mich aber verwundert ist, dass es keine Abfragemöglichkeit mit dem ODBS bzw. SQL Befehlssprache gibt. Wenn man die Tabelle nicht kennt, kann man nichts abfragen. Von der Logic her ziemlicher Blödsinn, da nur eine nichts erklärende Fehlermeldung entsteht, die nicht weiterhilft. Besonders fortschrittlich ist damit SQL meiner Meinung nach nicht... :(

Gruß Michael
Working on :lol: - LibSGD - MP3D Engine - 8)
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

> Besonders fortschrittlich ist damit SQL meiner Meinung nach nicht...

das problem liegt meines erachtens bei der Proprietät des Excel-Formats...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

> Wenn man die Tabelle nicht kennt, kann man nichts abfragen.

das, was Du da mit dem Code machst, decken die Standardfunktionalitäten
von PB (und ODBC) in zweierlei Hinsicht nicht ab:

1. Du greifst auf eine Excel-Datei zu, welche nicht im eigentlichen Sinne als
Datenbank zu bezeichnen ist

2. Du kennst die Tabellennamen nicht.

In diesem Fall wärst Du besser mit ADO bzw. ADOX beraten.

Grüße ... Kiffi
a²+b²=mc²
schic
Beiträge: 68
Registriert: 25.12.2004 19:04

Beitrag von schic »

eine weitere Möglichkeit (nicht nur) die Blattnamen auszulesen:

Code: Alles auswählen

#CRLF = Chr(13)+Chr(10)

;- COM Stuff
;{- COM Constants
#CLSCTX_INPROC_SERVER  = $1
#CLSCTX_INPROC_HANDLER = $2
#CLSCTX_LOCAL_SERVER   = $4
#CLSCTX_REMOTE_SERVER  = $10
#CLSCTX_ALL = (#CLSCTX_INPROC_SERVER|#CLSCTX_INPROC_HANDLER|#CLSCTX_LOCAL_SERVER|#CLSCTX_REMOTE_SERVER)

#DISPID_PROPERTYPUT = -3

#DISPATCH_METHOD          = 1
#DISPATCH_PROPERTYGET     = 2
#DISPATCH_PROPERTYPUT     = 4
#DISPATCH_PROPERTYPUTREF  = 8
;}

Structure EXCEPINFO 
  wCode.w;
  wReserved.w;
  bstrSource.s;
  bstrDescription.s;
  bstrHelpFile.s;
  dwHelpContext.l;
  pvReserved.l ;
  pfnDeferredFillIn.l
  scode.l ;
EndStructure

Structure SAFEARRAYBOUND
  cElements.l ;ULONG
  lLbound.l ;LONG
EndStructure

Structure ObjType
  lpObj.l
  strObjNam.s
EndStructure

;{- COM Globals
;Global pApp.IDispatch
Global pvResult.VARIANT
Global IID_NULL.GUID
Global LastError.l
Global LastMessage.s 
;}

;{- COM Arrays Linked Lists
Global Dim varArr.VARIANT(0)
Global NewList ObjectList.ObjType()
;}

Procedure.l Ansi2Uni(ansistr) ; Converts normal (Ansi) string to Unicode
  ;lenA.l = Len(ansistr)
  lenA.l = MemoryStringLength(ansistr, #PB_Ascii)
  
  lenW = MultiByteToWideChar_(#CP_ACP, 0, ansistr, lenA, 0, 0);#CP_ACP
  If (lenW > 0) ; Check whether conversion was successful
    unicodestr = SysAllocStringLen_(0, lenW)
    result = MultiByteToWideChar_(#CP_ACP, 0, ansistr, lenA, unicodestr, lenW);#CP_ACP
    If result = 0
      Debug "Ansi2Uni(ansistr): " + Hex(result)
      ProcedureReturn 0
    EndIf
    ProcedureReturn unicodestr
  Else
    ProcedureReturn 0
  EndIf
EndProcedure 

Procedure.s Uni2Ansi(unicodestr.l) ; Converts Unicode to normal (Ansi) string
  lenA = WideCharToMultiByte_(#CP_ACP, 0, unicodestr, -1, 0, 0, 0, 0);
  ansistr.s = Space(lenA)
  If (lenA > 0)
    WideCharToMultiByte_(#CP_ACP, 0, unicodestr, -1, @ansistr, lenA, 0, 0);
  EndIf
  ProcedureReturn ansistr
EndProcedure 

Procedure.l AutoWrap(autoTyp.l, *pDisp.IDispatch, name.s, nArgs.l)
  dispID.l
  Exception.EXCEPINFO
  
  dp.DISPPARAMS
  dispidNamed = #DISPID_PROPERTYPUT
  
  ;Convert to Uni
  ptUniName = Ansi2Uni(@name)
  ;Get DISPID for name passed...
  ;Debug "trying name: " + name
  hr = *pDisp\GetIDsOfNames(IID_NULL, @ptUniName, 1, #LOCALE_USER_DEFAULT, @dispID) 
  
  ;Build DISPPARAMS
  dp\cArgs  = nArgs
  dp\rgvarg = @varArr(0) ;ArgsArr;pArgs;*var;
  
  ;Handle special-case for property-puts!
  If autoTyp & #DISPATCH_PROPERTYPUT
    dp\cNamedArgs = 1
    dp\rgdispidNamedArgs = @dispidNamed
  EndIf
  
  ;Make the call!
  hr = *pDisp\Invoke(dispID, IID_NULL, #LOCALE_USER_DEFAULT, autoTyp, @dp, @pvResult, @Exception, #Null);#LOCALE_SYSTEM_DEFAULT
  If hr <> #S_OK
    Debug "error " + Str(hr) + " with name: " +  name
    LastError = hr
  EndIf
  Select hr
    Case #DISP_E_EXCEPTION
      MessageRequester(Uni2Ansi(@Exception\bstrSource), Uni2Ansi(@Exception\bstrDescription) + #CRLF + "Fehler Nr. " + Hex(hr) + " mit Objekt/Eigenschaft " + name, #MB_ICONERROR)
      Debug Uni2Ansi(@Exception\bstrSource)
      Debug "an Error occured in Excel " + Uni2Ansi(@Exception\bstrDescription)
    Case #S_OK
      
    Default
      MessageRequester("Excel Fehlermeldung", "Fehler Nr. " + Hex(hr) + " mit Objekt/Eigenschaft " + name, #MB_ICONERROR)
      Debug "Fehler Nr. " + Hex(hr) + " mit Objekt/Eigenschaft " + name
  EndSelect
  FreeMemory(ArgsArr)
  ProcedureReturn hr
EndProcedure

Procedure.l SetAppObj(app.s)
  
  LastError = 0
  LastMessage = ""
  
  hr = CoInitialize_(0)
  If  hr <> #S_OK And hr <> #S_FALSE
    LastError = hr
    LastMessage = "Error CoInitialize: ErrorCode " + Hex(hr)
    End
  EndIf
  
  clsid.GUID
  hr = CLSIDFromProgID_(Ansi2Uni(@app), @clsid)
  If hr <> #S_OK
    LastError = hr
    LastMessage = "Error CLSIDFromProgID: ErrorCode " + Hex(hr)
    ProcedureReturn 0
  EndIf
  
  pCf.IClassFactory
  
  IID_IClassFactory.GUID
  IID_IClassFactory\Data1 = $1
  IID_IClassFactory\Data4[0] = $C0
  IID_IClassFactory\Data4[7] = $46
  
  hr = CoGetClassObject_(@clsid, #CLSCTX_LOCAL_SERVER | #CLSCTX_INPROC_SERVER, #Null, @IID_IClassFactory, @pCf)
  If hr <> #S_OK
    LastError = hr
    LastMessage = "Error CoGetClassObject: ErrorCode " + Hex(hr)
    ProcedureReturn 0
  EndIf
  
  
  riid.GUID
  riid\Data1 = $20400
  riid\Data4[0] = $C0
  riid\Data4[7] = $46
  
  hr = pCf\CreateInstance(#Null, @riid, @*pApp.IDispatch)
  pCf\Release()
  If hr <> #S_OK
    LastError = hr
    LastMessage = "Error CreateInstance: ErrorCode " + Hex(hr)
    ProcedureReturn 0
  Else
    AddElement(ObjectList())
    ObjectList()\lpObj = *pApp
    ObjectList()\strObjNam = app
    ProcedureReturn *pApp
  EndIf
  
EndProcedure

Procedure.l SetComObj(lpParentObj, strObjectNam.s, lArgs.l)
  
  pvResult.VARIANT
  VariantInit_(@pvResult);
  hr = AutoWrap(#DISPATCH_PROPERTYGET, lpParentObj, strObjectNam, lArgs)
  If hr = #S_OK
    ; Debug strObjectNam + " o.k."
    AddElement(ObjectList())
    ObjectList()\lpObj = pvResult\pdispVal
    ObjectList()\strObjNam = strObjectNam
    ProcedureReturn pvResult\pdispVal
  Else
    ; Debug strObjectNam + " NOT o.k."
    LastError = hr
    LastMessage = "Error Get Object: ErrorCode " + Hex(hr)
    ProcedureReturn 0
  EndIf
  
EndProcedure

Procedure SetObjNothing(*Object.IDispatch)
  If *Object
    *Object\Release()
  EndIf
EndProcedure

Procedure ReleaseAllObjects()
  i = CountList(ObjectList())
  While i >= 0 ;ObjectList()
    SelectElement(ObjectList(), i)
    ; Debug "releasing " + ObjectList()\strObjNam
    ; Debug ObjectList()\lpObj
    If ObjectList()\lpObj
      *tmpObj.IDispatch = ObjectList()\lpObj
      *tmpObj\Release()
    EndIf
    i-1
  Wend
  ClearList(ObjectList())
EndProcedure

;{-Main
  
  File$ = "E:\test\Mappe1.xls"
  
  pXlApp.IDispatch = SetAppObj("Excel.Application") ;Excel.Application.10
  If pXlApp = 0
    End
  EndIf
  
  pXlBooks.IDispatch = SetComObj(pXlApp, "Workbooks", 0)
  
  varArr(0)\vt = #VT_BSTR
  varArr(0)\lVal = Ansi2Uni(@File$)
  AutoWrap(#DISPATCH_METHOD, pXlBooks, "Open", 1)
  VariantClear_(varArr(0))
  
  pXlBook.IDispatch = SetComObj(pXlApp, "ActiveWorkbook", 0)
  
  pXlSheets.IDispatch = SetComObj(pXlBook, "Worksheets", 0)
  
  VariantInit_(pvResult.VARIANT)
  AutoWrap(#DISPATCH_PROPERTYGET,  pXlSheets, "Count", 0)
  NumOfXlSheets = pvResult\lVal
  
  Dim pXlSheet.IDispatch(NumOfXlSheets)
  For i = 1 To NumOfXlSheets
    Dim varArr.VARIANT(1)
    varArr(0)\vt = #VT_I4
    varArr(0)\lVal = i
    pXlSheet(i) = SetComObj(pXlApp, "Worksheets", 1)
    VariantClear_(varArr(0))
    
    VariantInit_(pvResult.VARIANT) 
    AutoWrap(#DISPATCH_PROPERTYGET,  pXlSheet(i), "Name", 0)
    Nam$ = Uni2Ansi(pvResult\bstrVal)
    Debug Nam$
  Next
  
  AutoWrap(#DISPATCH_METHOD, pXlApp, "Quit", 0)
  ReleaseAllObjects()
  CoUninitialize_()
  LastError = 0
  ;}
Gruß
schic
schic
Beiträge: 68
Registriert: 25.12.2004 19:04

Beitrag von schic »

mit

Code: Alles auswählen

Procedure.l XLGetCellsValue(*sheet.IDispatch, Row, Column)
  Shared tmpText$, qtmp.d
  
  Dim varArr.VARIANT(2)
  varArr(0)\vt = #VT_I4
  varArr(0)\lVal = Column
  varArr(1)\vt = #VT_I4
  varArr(1)\lVal = Row
  pXlCells_x_y.IDispatch
  pvResult.VARIANT
  VariantInit_(@pvResult);
  AutoWrap(#DISPATCH_PROPERTYGET, *sheet, "Cells", 2)
  pXlCells_x_y = pvResult\pdispVal
  
  VariantInit_(pvResult.VARIANT)
  AutoWrap(#DISPATCH_PROPERTYGET,  pXlCells_x_y, "Value", 0)
  Select pvResult\vt
    Case #VT_BSTR
      tmpText$ = Uni2Ansi(pvResult\bstrVal)
      result = @tmpText$
      
    Case #VT_R8
      qtmp = pvResult\dblVal
      result = @qtmp
      
  EndSelect
  
  VariantClear_(varArr(0))
  VariantClear_(varArr(1))
  VariantClear_(pvResult)
  
  SetObjNothing(pXlCells_x_y)
  
  ProcedureReturn result;tmpText$
EndProcedure



*tmp = XLGetCellsValue(pXlSheet(i), Zeile, Spalte)
Txt$ = PeekS(*tmp)

*tmp = XLGetCellsValue(pXlSheet(i), Zeile, Spalte)
dVal.d = PeekD(*tmp)
bekommst Du Zellenwerte aus Deinen Excel-Tabellen.
Ist schneller als mit ODBC

schic
Benutzeravatar
mpz
Beiträge: 505
Registriert: 14.06.2005 15:53
Computerausstattung: Win 11 Pro, 48 GB Ram, Intel I7 CPU und RX4070 Grafikkarte, PB (4/5) 6.12LT
Wohnort: Berlin, Tempelhof

Beitrag von mpz »

Danke schic,

mit dem Code kann wirklich was anfangen. Gibt es noch eine Möglichkeit die Anzahl der Spalten und Anzahl der Datensätz zu ermitteln? Ich habe eine einfache Möglichkeit gefunden, die aber sicherlich nicht optimal funktioniert und mit dem COM Parametern besser gehen wird:


Code: Alles auswählen

    a.l = 1
    Repeat
    *tmp = XLGetCellsValue(pXlSheet(i), 1, a)
    If *tmp
      ;Debug = PeekS(*tmp)
    Else
      Break
    EndIf 
       
    a=a+1
    ForEver  
    Debug "Spalten="+Str(a-1)


    a.l = 1
    Repeat
    *tmp = XLGetCellsValue(pXlSheet(i), a, 1)
    If *tmp
      ;Debug = PeekS(*tmp)
    Else
      Break
    EndIf 
       
    a=a+1
    ForEver     
    Debug "Datensätze="+Str(a-1)
    

Gruß Michael
Working on :lol: - LibSGD - MP3D Engine - 8)
schic
Beiträge: 68
Registriert: 25.12.2004 19:04

Beitrag von schic »

VBA-Code für Anzahl der benutzten Zeilen:

Code: Alles auswählen

objSheet.UsedRange.Rows.Count
->
PB-Code

Code: Alles auswählen

pXlUsedRange.IDispatch = SetComObj(pXlSheet(2), "UsedRange", 0)
pxlRows.IDispatch = SetComObj(pXlUsedRange, "Rows", 0)
VariantInit_(pvResult.VARIANT)
AutoWrap(#DISPATCH_PROPERTYGET,  pxlRows, "Count", 0)
NumOfUsedRows = pvResult\lVal
Debug "NumOfUsedRows: " + Str(NumOfUsedRows)
siehe auch VBA-Hilfe -> UsedRange
Eine weitere Möglichkeit für letzte Zeile bzw. Spalte und auch sonst gute
Tipps gibt´s unter
http://www.schmittis-page.de/index.html ... ba/t17.htm

Gruß
schic
Benutzeravatar
mpz
Beiträge: 505
Registriert: 14.06.2005 15:53
Computerausstattung: Win 11 Pro, 48 GB Ram, Intel I7 CPU und RX4070 Grafikkarte, PB (4/5) 6.12LT
Wohnort: Berlin, Tempelhof

Beitrag von mpz »

Vielen herzlichen Dank,

jetzt habe ich alles was ich benötige und kann eine beliebige Exceldatei auslesen. Das es so viele Ansätze gibt, hätte ich nicht gedacht...

:allright:
Gruß Michael


VBA-Code für Anzahl der benutzten Spalten:

Code: Alles auswählen


    pXlUsedRange.IDispatch = SetComObj(pXlSheet(i), "UsedRange", 0) 
    pxlRows.IDispatch = SetComObj(pXlUsedRange, "Columns", 0) 
    VariantInit_(pvResult.VARIANT) 
    AutoWrap(#DISPATCH_PROPERTYGET,  pxlRows, "Count", 0) 
    NumOfUsedColumns = pvResult\lVal 
    Debug "NumOfUsedColumns: " + Str(NumOfUsedColumns) 


Wer noch einen Tabellennamen einer Accessdatenbank über ODBC auslesen möchte (siehe meinen ersten Sourcecode) kann diese Funktion benutzen. Leider funktionierte Sie nur mit einer Accessdatei und nicht mit einer Exceldatei...

Code: Alles auswählen



#SQL_DRIVER_NOPROMPT = 0 
#sqlNoDataFound  = 100 

Global hEnv.l, Alloc.l, hDbc.l, hStmt.l,Ret.b,intCols.l 
Ergebnis.l = OpenLibrary(0,"ODBC32.dll") 


   strDataSource.s = "DBQ="+File$+";DRIVER={Microsoft Access Driver (*.mdb)}";*********************** 
   retcode=CallFunction(0,"SQLAllocEnv",@hEnv); 
   retcode=CallFunction(0,"SQLAllocConnect",hEnv,@hDbc); 
   retcode=CallFunction(0,"SQLDriverConnect",hDbc,#Null,strDataSource,Len(strDataSource),szConnStr,1024,@cbConnStr,#SQL_DRIVER_NOPROMPT) 
   retcode=CallFunction(0,"SQLAllocStmt",hDbc,@hStmt) 
   retcode=CallFunction(0,"SQLTables",hStmt,0,-3,0,-3,0,-3,"TABLE",Len("TABLE")); 
    
   Ret = CallFunction(0,"SQLFetch",hStmt)
   PrintN ("Ret = "+Str(ret))
    
    While Ret <> #sqlNoDataFound 
           Owner.s = Space(254) 
           Name.s = Space(254) 
           Ret = SQLGetData_(hStmt, 4, 1, Owner, 254, 0) 
           Ret = SQLGetData_(hStmt, 3, 1, Name, 254, 0) 
           If Owner = "TABLE" 
              Liste.s = Liste+Name+";" 
           EndIf 
      Ret = CallFunction(0,"SQLFetch",hStmt) 
    Wend
  PrintN ("Tabellennamen = "+liste)

Working on :lol: - LibSGD - MP3D Engine - 8)
Antworten