kikimiki
Goto Top

SQL-Count Ergebnis als Variable speichern

Hallo könnt ihr mir vielleicht helfen
dieses vbs script zieht Daten aus unserer MySQL DB in xls:

Option Explicit

'---- CursorTypeEnum Values ----  
Const adOpenForwardOnly = 0
' Const adOpenKeyset = 1  
' Const adOpenDynamic = 2  
' Const adOpenStatic = 3  

'---- LockTypeEnum Values ----  
Const adLockReadOnly = 1
' Const adLockPessimistic = 2  
' Const adLockOptimistic = 3  
' Const adLockBatchOptimistic = 4  

'---- CursorLocationEnum Values ----  
' Const adUseServer = 2  
Const adUseClient = 3

'---- ConnectModeEnum Values ----  
' Const adModeUnknown = 0  
Const adModeRead = 1
' Const adModeWrite = 2  
' Const adModeReadWrite = 3  
' Const adModeShareDenyRead = 4  
' Const adModeShareDenyWrite = 8  
' Const adModeShareExclusive = &Hc  
' Const adModeShareDenyNone = &H10  
' Const adModeRecursive = &H400000  
Dim objExcel, objWb, SkriptPfad
Dim objSheet
Dim Conn, RS
Dim rowCount, i, headerSet
Dim x 'Zähler für Statusbar  
Dim Gesamtanzahl 
Dim Ergebnis



x = 0 'Anfangswert für Zähler  
Gesamtanzahl  =1443

rowCount = 1

SkriptPfad = WScript.ScriptFullName 'Pfadermittlung  
SkriptPfad = Left(SkriptPfad, Len(SkriptPfad) - Len(WScript.ScriptName))  'Pfadermittlung  


Set objExcel = CreateObject("Excel.Application")   
Set objWb = objExcel.Workbooks.Open(SkriptPfad & "../test.xls")'öffnet die angegebene xls  



objExcel.Visible = True
objExcel.Sheets("Datenbasis").Select 'wählt die angegebene Mappe der zuvor geöffneten xls  
objExcel.Range("Datenbasis!$1:$65536").ClearContents 'löscht alle Inhalte von angegebener Mappe  


'Angabe des Tabellenblattes  
Set objSheet = objExcel.ActiveWorkbook.WorkSheets("Datenbasis") 'Import in angegebenes Tabellenblatt  

Set Conn = CreateObject("ADODB.Connection")  
Conn.Provider = "MSDASQL"  
Conn.Mode = adModeRead
Conn.CursorLocation = adUseClient
Conn.Open "DRIVER={MySQL ODBC 5.1 Driver};" & _  
          "DATABASE=db;" & _  
          "SERVER=server;", _  
          "user", "pw"  

Set RS = CreateObject("ADODB.Recordset")  
RS.CursorLocation = adUseClient
'verwendete SQL-Anweisung  
RS.Source = "Select * From Kundentab;"  
Set RS.ActiveConnection = Conn
RS.CursorType = adOpenForwardOnly
RS.LockType = adLockReadOnly
RS.Open          

Do While Not RS.EOF
objExcel.StatusBar = Ergebnis & " % "&"der Datensätze aus DB importiert" 'Text für Statusbar  
'Die Spalenüberschriften einfügen Bezug aus dem SQL-Statement  
	If( headerSet = 0 ) Then
		For i = 0 to RS.Fields.Count - 1
		  objSheet.Cells(rowCount, i+1).Value = RS.Fields.Item(i).Name
		Next
		headerSet = 1
    End If
'Die dazugehörigen Werte einfügen  
	For i = 0 to RS.Fields.Count -1 
	  objSheet.Cells(rowCount+1, i+1).Value = RS.Fields.Item(i).Value
	Next
    rowCount = rowCount + 1
	RS.MoveNext
	
x = x + 1
'Ergebnis = Round((x/Gesamtanzahl) * 100, 0)  
Ergebnis = Int((x/Gesamtanzahl) * 100)


Loop
objExcel.Statusbar = False 'Statusbar bereinigen  


objExcel.Sheets("Pivot1").Select 'wählt die angegebene Mappe der zuvor geöffneten xls  


RS.Close
Set RS = Nothing

Conn.Close
Set Conn = Nothing


MsgBox "Datenimport aus DB abgeschlossen! Die Datenbasis zeigt den Stand vom " &  Date  & " bis " & Time & "!" & vbCrLf & "Aktualisieren Sie die Pivottabellen über die Schaltfläche!" & vbCrLf & "Es wurden " & x & " Datensätze aus DB importiert",64, "Info"  


In diesem Code ist die Gesamtanzahl fest vergeben, kann man die Gesamtaanzahl als Ergebnis dieses Sql Statements übernehmen?

SELECT COUNT(*) AS Anzahl FROM Kunden where kndnr.= 1020;

Das ist nämlich die Anzahl die ich in meinem "alten" Code als festen Wert drin habe

Jemand eine Idee??

Content-Key: 110694

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

Printed on: April 16, 2024 at 18:04 o'clock

Member: Logan000
Logan000 Mar 06, 2009 at 08:52:36 (UTC)
Goto Top
Moin Moin

Genau so wie du es die ganze Zeit machst:
Recordset füllen. Daten aus RS lesen.

So in etwa:
...
RS.Source = "SELECT COUNT(*) AS Anzahl FROM Kunden where kndnr.= 1020;"   
Set RS.ActiveConnection = Conn 
RS.CursorType = adOpenForwardOnly 
RS.LockType = adLockReadOnly 
RS.Open           
Gesamtanzahl  = RS.Fields("Anzahl").Value  
...

Gruß L.
Member: KikiMiki
KikiMiki Mar 06, 2009 at 08:55:59 (UTC)
Goto Top
Hi Logan000

und an welcher Stelle in meinem Code muss ich diese Passage einfügen?
Member: Logan000
Logan000 Mar 06, 2009 at 10:10:03 (UTC)
Goto Top
Moin

Ich würde es ziwschen Zeile 71 und 72 setzen.

Gruß L.
Member: KikiMiki
KikiMiki Mar 06, 2009 at 10:41:22 (UTC)
Goto Top
Hat leider nicht geklappt

Es wird gar nichts importiert mehr

Hier der ganze Code

Option Explicit

'---- CursorTypeEnum Values ----  
Const adOpenForwardOnly = 0
' Const adOpenKeyset = 1  
' Const adOpenDynamic = 2  
' Const adOpenStatic = 3  

'---- LockTypeEnum Values ----  
Const adLockReadOnly = 1
' Const adLockPessimistic = 2  
' Const adLockOptimistic = 3  
' Const adLockBatchOptimistic = 4  

'---- CursorLocationEnum Values ----  
' Const adUseServer = 2  
Const adUseClient = 3

'---- ConnectModeEnum Values ----  
' Const adModeUnknown = 0  
Const adModeRead = 1
' Const adModeWrite = 2  
' Const adModeReadWrite = 3  
' Const adModeShareDenyRead = 4  
' Const adModeShareDenyWrite = 8  
' Const adModeShareExclusive = &Hc  
' Const adModeShareDenyNone = &H10  
' Const adModeRecursive = &H400000  
Dim objExcel, objWb, SkriptPfad
Dim objSheet
Dim Conn, RS
Dim rowCount, i, headerSet
Dim x 'Zähler für Statusbar  
Dim Gesamtanzahl 
Dim Ergebnis



x = 0 'Anfangswert für Zähler  


rowCount = 1

SkriptPfad = WScript.ScriptFullName 'Pfadermittlung  
SkriptPfad = Left(SkriptPfad, Len(SkriptPfad) - Len(WScript.ScriptName))  'Pfadermittlung  


Set objExcel = CreateObject("Excel.Application")   
Set objWb = objExcel.Workbooks.Open(SkriptPfad & "../test.xls")'öffnet die angegebene xls  



objExcel.Visible = True
objExcel.Sheets("Datenbasis").Select 'wählt die angegebene Mappe der zuvor geöffneten xls  
objExcel.Range("Datenbasis!$1:$65536").ClearContents 'löscht alle Inhalte von angegebener Mappe  


'Angabe des Tabellenblattes  
Set objSheet = objExcel.ActiveWorkbook.WorkSheets("Datenbasis") 'Import in angegebenes Tabellenblatt  

Set Conn = CreateObject("ADODB.Connection")  
Conn.Provider = "MSDASQL"  
Conn.Mode = adModeRead
Conn.CursorLocation = adUseClient
Conn.Open "DRIVER={MySQL ODBC 5.1 Driver};" & _  
          "DATABASE=db;" & _  
          "SERVER=local;", _  
          "user", "pw"  

Set RS = CreateObject("ADODB.Recordset")  
RS.CursorLocation = adUseClient

RS.Source = "SELECT COUNT(*) AS Anzahl FROM Kunden where Kunde=10200;"   
Set RS.ActiveConnection = Conn 
RS.CursorType = adOpenForwardOnly 
RS.LockType = adLockReadOnly 
RS.Open           
Gesamtanzahl  = RS.Fields("Anzahl").Value  

'verwendete SQL-Anweisung  
RS.Source = "SELECT * From Kunden;"  
Set RS.ActiveConnection = Conn
RS.CursorType = adOpenForwardOnly
RS.LockType = adLockReadOnly
RS.Open          

Do While Not RS.EOF
objExcel.StatusBar = Ergebnis & " % "&"der Datensätze aus DB importiert" 'Text für Statusbar  
'Die Spalenüberschriften einfügen Bezug aus dem SQL-Statement  
	If( headerSet = 0 ) Then
		For i = 0 to RS.Fields.Count - 1
		  objSheet.Cells(rowCount, i+1).Value = RS.Fields.Item(i).Name
		Next
		headerSet = 1
    End If
'Die dazugehörigen Werte einfügen  
	For i = 0 to RS.Fields.Count -1 
	  objSheet.Cells(rowCount+1, i+1).Value = RS.Fields.Item(i).Value
	Next
    rowCount = rowCount + 1
	RS.MoveNext
	
x = x + 1

Ergebnis = Int((x/Gesamtanzahl) * 100)


Loop
objExcel.Statusbar = False 'Statusbar bereinigen  


objExcel.Sheets("Pivot1").Select 'wählt die angegebene Mappe der zuvor geöffneten xls  


RS.Close
Set RS = Nothing

Conn.Close
Set Conn = Nothing


MsgBox "Datenimport aus DB abgeschlossen! Die Datenbasis zeigt den Stand vom " &  Date  & " bis " & Time & "!" & vbCrLf & "Aktualisieren Sie die Pivottabellen über die Schaltfläche!" & vbCrLf & "Insgesamt wurden " & x & " Datensätze aus DB importiert",64, "Info"  
Member: Logan000
Logan000 Mar 06, 2009 at 11:04:58 (UTC)
Goto Top
Moin

Kommte eine Fehlermeldung? Wenn ja welche?
Hast Du mein Codefragment vorher in einem eigenen Skript mal gestestet?

Warum wisst Du eigentlich nur die Kunden mit kndnr.= 1020 zählen, während alle nach Excel kopiert werden?

Gruß L.
Member: KikiMiki
KikiMiki Mar 06, 2009 at 11:08:12 (UTC)
Goto Top
Es kommt keine Fehlermeldung
das xls wird geöffnet und es tut sich nichts

Mit dem Count zähl ich nur die Zeilen der Tabelle, der Inhalt interessiert mich gar nicht
Ich brauch diesen Wert für die prozentuale Gegenüberstellung mit dem 2. SQL

Habe die SQL in diesem Post abgeändert, sie sind doch sehr lang

Aber sie erfüllen ihren Zweck

Ich habe bischen rumgespielt, den Wert scheint er zu bekommen, aber meine 2. SQL wird nicht ausgeführt
Member: Logan000
Logan000 Mar 06, 2009 at 13:03:31 (UTC)
Goto Top
Moin

Läuft das Skript bei Dir mit einem on Error resume next?
Wie dem auch sein ich habe wohl das Close fürs Recordset vergessen.
...
RS.Open            
Gesamtanzahl  = RS.Fields("Anzahl").Value   
RS.Close                                                             
...

Gruß L.
Member: KikiMiki
KikiMiki Mar 06, 2009 at 13:31:28 (UTC)
Goto Top
Klappt leider nich, es wird nur eine Zeiel importiert und fertig

So sieht mein Codeabschnitt jetzt aus:

Set Conn = CreateObject("ADODB.Connection")  
Conn.Provider = "MSDASQL"  
Conn.Mode = adModeRead
Conn.CursorLocation = adUseClient
Conn.Open "DRIVER={MySQL ODBC 5.1 Driver};" & _  
          "DATABASE=db;" & _  
          "SERVER=local;", _  
          "user", "pw"  

Set RS = CreateObject("ADODB.Recordset")  
RS.CursorLocation = adUseClient

RS.Source = "SELECT COUNT(*) AS Anzahl FROM Kunden;"   
Set RS.ActiveConnection = Conn 
RS.CursorType = adOpenForwardOnly 
RS.LockType = adLockReadOnly 
RS.Open           
Gesamtanzahl  = RS.Fields("Anzahl").Value  
RS.Close

'verwendete SQL-Anweisung  
RS.Source = "SELECT * FROM Kunden"  
Set RS.ActiveConnection = Conn
RS.CursorType = adOpenForwardOnly
RS.LockType = adLockReadOnly
RS.Open          

Do While Not RS.EOF
objExcel.StatusBar = Ergebnis & " % der angefragten Datensätze sind importiert!" 'Text für Statusbar  
'Die Spalenüberschriften einfügen Bezug aus dem SQL-Statement  
	If( headerSet = 0 ) Then
		For i = 0 to RS.Fields.Count - 1
		  objSheet.Cells(rowCount, i+1).Value = RS.Fields.Item(i).Name
		Next
		headerSet = 1
    End If
'Die dazugehörigen Werte einfügen  
	For i = 0 to RS.Fields.Count -1 
	  objSheet.Cells(rowCount+1, i+1).Value = RS.Fields.Item(i).Value
	Next
    rowCount = rowCount + 1
	RS.MoveNext
	
x = x + 1

Ergebnis = Int((x/Gesamtanzahl) * 100) 'optional Ergebnis = Round((x/Gesamtanzahl) * 100, 0)  


Loop

Eine Frage: Kann ich bei beiden Abfragen die Variable RS. nehmen???
Muss ich auch nach der Count Abfrage das Conn schließen

Ich hab echt keinen Plan wie ich vorzugehen habe

Die 2. SQL Anweisung soll komplett durchgeführt werden
Die 1. SQL Anweisung brauch ich nur um der Variable gesamtzahl den Wert aus der Count Abfrage zu geben

Eine Idee??
Member: Biber
Biber Mar 07, 2009 at 13:50:47 (UTC)
Goto Top
Moin KikiMiki,

Eine Frage: Kann ich bei beiden Abfragen die Variable RS. nehmen???
Warum soltest Du so etwas tun? Ist das umweltschonender, performanter oder macht den Code wartbarer?
Solltest Du niemals tun - Recycling von Variablen kommt auf der DONOT-Liste der Programmierung dierkt nach dem Copy-und-Pasten von Code-Blöcken und dem Löschen von Kommentaren vor Sourcecode-Übergabe an den Kunden.

Muss ich auch nach der Count Abfrage das Conn schließen
Warum soltest Du so etwas NICHT tun? Ist das umweltschonender, performanter oder macht den Code wartbarer, wenn Du es weglässt?
Ist wie im richtigen Leben - wenn Du aus Spaß irgendwelche Objekte, Nachkommen, Einladungen zu Partys oder Gerüchte in die Welt setzt, dann bist Du der Erzeuger und bist dafür verantwortlich, bis es wieder aus der Welt ist.
Selbst in "richtigen" Datenbanken ist die Gesamtzahl auf dem Client "offener" Cursor und vergessener Connections durchaus eine begrenzte Ressouce.
Wenn auf einer DB2 oder einer Oracle-DB 500 Clients lang vergessene Cursor "nicht gesclossen" haben und immer noch die Connection halten, dann bekommt der 501ste Client bei irgendeiner Abfrage, die IMMER funktioniert bisher einen "Unavailable Ressource"-Error.

Anyhow, wenn Du es für eleganter hältst mit nur EINEM Recordset-Object auskommen zu wollen, dann nimm nur eines und hole Dir die Gesamtanzahl aus dem
RS.RecordCount -Property des (jetzigen) zweiten Recordset-Objects und lass die komplette erste Abfrage wech.

Grüße
Biber
Member: KikiMiki
KikiMiki Mar 07, 2009 at 17:05:16 (UTC)
Goto Top
Hallo Biner,

zunächst einmal vielen Dank für deine lange Antwort

Doch erhlich gesagt bin ich nicht der DB Fachmann. Um überhaupt den Code zum Laufen zu brigen wurde mir hier so viel geholfen.

Es wäre halt net die Count Abfrage zu nutzen um den User über den Fortschritts des Imports zu informieren
Sonst sehe ich keinen Weg da ich mit Fortschrittsbalken mich gar nicht auskenne.

Am liebsten wäre mir das Excel während dem Import gar nicht sichtbar ist. Der Import über einen Fortschrittsbalken angezeigt wird. Und wenn der Import fertig ist sich die xls öffnet. Aber kein Plan wie ich das umsetzten kann
Member: Biber
Biber Mar 07, 2009 at 20:12:27 (UTC)
Goto Top
Moin KikiMiki,

zunächst einmal vielen Dank für deine lange Antwort
Dafür nich'.
Doch erhlich gesagt bin ich nicht der DB Fachmann.
Meine Antworten haben auch nichts DB-spezifisches an sich - ging ganz allgemein um Codequalität.
Es wäre halt net die Count Abfrage zu nutzen um den User über den Fortschritts des Imports zu informieren
Ich habe Deine Frage verstanden - hast Du auch meine Antwort auf Relevanz für Dein Problem gescannt?
Am liebsten wäre mir das Excel während dem Import gar nicht sichtbar ist.
Okay. Warum sagst Du dann oben "objExcel.Visible = True "?
[OT] Und warum nicht "während des Imports"? Rheinländer? [/OT]
Der Import über einen Fortschrittsbalken angezeigt wird.
Dafür allerdings brauchst Du zwar kein Excel-Sheet, aber ein Fenster wäre hilfreich.

--> wenn Du Excel NICHT öffnen willst, dann solltest Du den Schnipsel oben komplett als VBScript (nicht als VBA) laufen lassen.
Außer den ad-Konstanten, die Du halt in VBS selbst definieren musst kaum Unterschiede.

Aber dennoch können wir doch erstmal das VBA-Fragment zum Fliegen bringen.
Hast Du mal versucht, mit EINEM RecordSet und dem RecordCount-Property zum Ziel zu kommen?

Grüße
Biber
Member: KikiMiki
KikiMiki Mar 08, 2009 at 11:32:29 (UTC)
Goto Top
Hi Biber wenn ich visible auf false setzte macht er den Import aber der User hat keine Infos das was läuft
erst ide msg box am Ende
Die jetztige vbs Lösung läuft super
Mir fehlt ledoglich der fortschrittsbalken

Wenn das xls offen ist klappt der Import, doch sobald ich während dem Import in das xls reinklicke bricht er ab
Member: Logan000
Logan000 Mar 13, 2009 at 07:43:22 (UTC)
Goto Top
Moin Moin

Mir fehlt ledoglich der fortschrittsbalken
Leider hast du bei VBS keine Möglichkeit gescheite GUIs zu bauen.
Als Plan B könntest du höchstens eine html Seite erzeugen und diese in einem kleinen IE fenster anzeigen.

Gruß L.