2009-03-26 8 views
5

Sto cercando di creare un QueryTable in un foglio di calcolo Excel utilizzando Python comtypes biblioteca, ma ottenere un errore piuttosto uninformative ...problema usando la libreria Python comtypes per aggiungere un QueryTable per Excel

in VBA (in un modulo all'interno della cartella di lavoro), il seguente codice funziona bene:

Sub CreateQuery() 
    Dim con As ADODB.Connection 
    Dim rs As ADODB.Recordset 
    Dim ws As Worksheet 
    Dim qt As QueryTable 

    Set ws = ActiveWorkbook.Sheets(1) 

    Set con = New ADODB.Connection 
    con.Open ("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Path\to\Db.mdb;") 

    Set rs = New ADODB.Recordset 
    rs.Open "Select * from [tbl Base Data];", con 

    Set qt = ws.QueryTables.Add(rs, ws.Range("A1")) 
    qt.Refresh 
End Sub 

Ma il seguente codice Python:

import sys 
import comtypes.client as client 

def create_querytable(): 
    constring = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Path\\to\\Db.mdb" 
    conn = client.CreateObject("ADODB.Connection", dynamic = True) 
    rs = client.CreateObject("ADODB.Recordset", dynamic = True) 

    SQL = "Select * from [tbl Base Data];" 

    conn.Open(constring) 
    rs.Open(SQL, conn) 
    excel = client.CreateObject("Excel.Application", dynamic = True) 
    excel.Visible = True 
    ws = excel.Workbooks.Add().Sheets(1) 
    qt = ws.QueryTables.Add(rs, ws.Range["A1"]) 
    qt.Refresh() 
    rs.Close() 
    conn.Close() 

lancia il messaggio di errore inutile:

Traceback (most recent call last): 
    File "<pyshell#34>", line 1, in <module> 
    create_querytable() 
    File "C:/Documents and Settings/cvmne250/Desktop/temp.py", line 17, in create_querytable 
    qt = ws.QueryTables.Add(rs, ws.Range["A1"]) 
    File "G:\ISA\SPSS\comtypes\lib\comtypes\client\lazybind.py", line 160, in caller 
    File "G:\ISA\SPSS\comtypes\lib\comtypes\automation.py", line 628, in _invoke 
COMError: (-2147352567, 'Exception occurred.', (None, None, None, 0, None)) 

Qualche idea su cosa sta succedendo qui?

Grazie!

+0

Eli, lo spazio in più è stato rimosso era lì per far apparire le cose corrette sull'anteprima. Ora sono curioso: sono bloccato, ma la politica aziendale utilizza IE6, che richiede lo spazio per sembrare giusto - era proprio su altri browser senza di esso? – mavnn

+0

Mi sembra ancora buono in Firefox 3.0.7 – tgray

+0

Si potrebbe anche voler aggiungere un tag Visual Basic o VBA alla domanda ... – tgray

risposta

2

ho semplificato il codice e questo dovrebbe funzionare bene (spiegherò le modifiche di seguito):

def create_querytable2(): 
    constring = "OLEDB;Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\path\to\db.mdb;" 
    SQL = "Select * from tblName;" 
    excel = client.CreateObject("Excel.Application", dynamic=True) 
    excel.Visible = True 
    ws = excel.Workbooks.Add().Worksheets(1) 
    ws.QueryTables.Add(constring, ws.Range["A1"], SQL).Refresh() 

La funzione QueryTables.Add() può creare la connessione e Recordset oggetti per voi, in modo che semplifica un sacco di cose ... devi solo aggiungere il tipo di connessione nella stringa di connessione (la parte "OLEDB").

Lasciando Excel fare la maggior parte del lavoro sembra risolvere il problema :)

+0

Perfetto! Avevo provato la versione (constring, range, sql) ma avevo perso il fatto che avevo bisogno dell'OLEDB aggiunto all'inizio del constring. Ancora curioso di sapere perché l'originale non ha funzionato, ma tale è la vita. Bonus point per .Refresh() sulla stessa linea - molto Pythonic ... – mavnn

1

Sembra che l'errore è su questa linea:

qt = ws.QueryTables.Add(rs, ws.Range["A1"]) 

Credo che il problema è che si sta utilizzando la sintassi Python per cercare un valore in una raccolta di VBA. Prova a cambiare le parentesi quadre tra parentesi.

cioè

qt = ws.QueryTables.Add(rs, ws.Range("A1")) 

Il motivo è che in VBA quando si richiama una collezione come questa, Range("A1"), in realtà si sta chiamando è il metodo di default, Range.Item("A1"). Fondamentalmente, le raccolte VBA non si traducono in dizionari Python.

Sto ottenendo questo da questo forum thread e la mia esperienza con VBA.


Modifica dovuta al commento:

Purtroppo, ho provato entrambe le cose: come notato nel tuo link, a volte non fanno la stessa cosa, ma il mio istinto sensazione qui è che il '[' è più probabilmente quello che voglio. - mavnn

Sai se comtypes.client.CreateObject funziona allo stesso modo win32com.client.Dispatch? Potresti provare a creare il tuo oggetto com con il pacchetto win32com e vedere se questo fa la differenza.

+0

Purtroppo, ho provato entrambi: come indicato nel link, a volte donano Faccio la stessa cosa, ma il mio istinto qui è che il "[" è più probabile che sia ciò che voglio. – mavnn

+0

Mi piacerebbe. Sfortunatamente, non ho diritti di amministratore sulla macchina in questione e quindi non posso installare il pacchetto win32com. Sì, sì, lo so: se ti fidi di qualcuno abbastanza da dargli accesso a Python e le sue librerie standard non hanno molto senso, ma questa è la vita ... – mavnn

Problemi correlati