query vba



  • query vba
    di gugluca (utente non iscritto) data: 17/02/2014 09:39:19

    Ciao a tutti,
    ho creato alcune tabelle (oggetti ADODB.Recordset) a seguito di una connessione via ODBC (sempre adodb)..

    le tabelle create hanno tutte la stessa struttura.
    Vorrei metterle in join creando una nuova tabella (questa volta in locale sul file excel e quindi non mi occorrono connessioni)..

    come posso fare?

    Grazie in anticipo

    ciao

    Luca



  • di Vecchio Frac data: 17/02/2014 15:56:03

    Come la crei la nuova tabella? Con una query SELECT, immagino, sulla connessione ADO aperta.
    Una volta che hai il recordset in memoria del tipo Set rs = conn.Execute("SELECT ... FROM ...") (eventualmente anche con una serie di schifezze JOIN annidate), lo puoi scorrere con While not rs.eof e assegni alle celle Excel il risultato di ogni rs.MoveNext.
    Chiaro no? ^_^
    ...un pochino almeno :)





  • di gugluca (utente non iscritto) data: 17/02/2014 16:29:54

    Ciao!
    La nuova tabella la creo con una query di select che mette in join i vari recordset in memoria.
    Ogni recordset è creato su una connessione diversa via ODBC..
    La nuova tabella la voglio creare su una connessione in locale (attualmente non esiste credo..)

    Per quanto riguarda il tuo consiglio, 'rs' immagino sia il nome della tabella, 'conn' il nome della connessione (impostata come ADODB.Connection immagino)...
    Come posso settare quel 'conn'?

    Grazie ancora per l'aiuto!



  • di Vecchio Frac data: 17/02/2014 20:37:47

    Sì, di solito con "rs" chiamo il recordset, e "conn" la connessione che creo quando istanzio l'oggetto ADODB.
    Mostra un po' di codice, anzi meglio sarebbe un pezzo di file funzionante (senza dati riservati).
    Magari anche con una descrizione del risultato atteso... altrimenti brancolo nel buio :)






  • di gugluca (utente non iscritto) data: 18/02/2014 08:58:03

    Ciao!
    Riporto qui di seguito il codice utilizzato.
    Ho creato 6 Function (una per ogni connessione ODBC)

    Poi una macro che Genera 6 recordset (ognuno utilizzando una connessione diversa, DB1, DB2, ecc..).

    Alla fine della macro vorrei generare un'ulteriore recordset che metta in join alcuni dei 6 recordset...
    Solo che non so come procedere (non so se devo creare un'ulteriore connessione, ma in questo caso vorrei che rimanesse semplicemente in memoria per poi riportare i risultati su excel)..

    Come posso risolvere?

    Grazie ancora

    Ciao

    Luca

     
    'Ho 6 function di questo tipo che mi creano le 6 connessioni
    
    Function ExecQuery1(strsql) As ADODB.Recordset
      Const adOpenStatic = 3
      Const adUseClient = 3
      Const adLockBatchOptimistic = 4
      Dim oRS As ADODB.Recordset
      Dim conn1 As ADODB.Connection
    
    
    Set conn1 = New ADODB.Connection
    conn1.Open DSN, UID, PWD ..
    
    'Creo la tabella
      Set oRS = New ADODB.Recordset
      oRS.CursorLocation = adUseClient
    
    'Popolo la tabella
      oRS.Open strsql, conn1, adOpenStatic, adLockBatchOptimistic
    
    'Disconnetto il recordset
      Set oRS.ActiveConnection = Nothing
    
    'Ritorno al Recordset
      Set ExecQuery1 = oRS
    
      conn1.Close
      Set conn1 = Nothing
    
    End Function
    
    
    
    Sub prova
    
    Dim DB1, DB2, DB3, DB4, DB5, DB6 As ADODB.Recordset
    Dim sql As String
    
    sql = "......."
    
    Set DB1 = ExecQuery1(sql)
    
    sql = "......."
    
    Set DB2 = ExecQuery2(sql)
    
    sql = "......."
    
    Set DB3 = ExecQuery3(sql)
    
    sql = "......."
    
    Set DB4 = ExecQuery4(sql)
    
    sql = "......."
    
    Set DB5 = ExecQuery5(sql)
    
    sql = "......."
    
    Set DB6 = ExecQuery6(sql)
    
    
    
    'A questo punto ho creato i 6 recordset. Come posso creare ora un recordset che mi metta in join i recordset?
    
    
     



  • di Vecchio Frac data: 18/02/2014 20:41:43

    Ma hai sei tabelle distinte?
    Visto che tutte le tabelle hanno la stessa struttura, forse ti basta solo una query di unione, senza ricorrere a sei recordset separati:

    Sub prova
    Dim DB1 As ADODB.Recordset
    Dim sql As String

    sql = "SELECT ... FROM t1 UNION SELECT ... FROM t2 UNION SELECT ... FROM t3"
    Set DB1 = ExecQuery1(sql)
    End Sub

    p.s. quel Dim DB1, DB2, ... attenzione: solo l'ultimo è dichiarato As ADODB.Recordset, gli altri sono Variant; devi specificare il tipo As per tutte le variabili.
    Le istruzioni sql sono tutte dello stesso tipo? Se ne può vedere una?







  • di gugluca (utente non iscritto) data: 19/02/2014 17:32:15

    Ciao,
    innanzitutto grazie per quell'osservazione... non sapevo che mettendo: Dim DB1, DB2, ... As ADODB.Recordset, il sistema mi prendesse solo l'ultima come variabile dichiarata..
    Ho scoperto una cosa nuova

    Per quanto riguarda il tuo suggerimento, non ho ben capito..
    Io ho 6 tabelle distinte che stanno su 6 collegamenti ODBC distinti (sulle conn1, conn2, conn3, conn4, conn5, conn6) che ho settato in 6 function distinte (prima te ne avevo riportato solo 1 per esempio).
    Poi ho una macro che esegue la query (riportata sulla variabile 'sql' string, ogni volta cambia di qualcosa ma estrae con una select 3 campi uguali per ciascuna connessione) sulle 6 connessioni (col comando Set DB1=ExecQuery1(sql)...).

    Provo a riportarti meglio il codice contenuto nella macro..

    Quello che non capisco è come posso mettere in join il risultato delle 6 query che girano su 6 connessioni diverse e riportare il risultato in excel..
    In particolare, nel mio caso, vorrei creare una query che mi metta in union le 6 query e mi gruppi il risultato, del tipo:
    SELECT NOME, GRUPPO, SUM(VALORE) AS VALORE
    FROM (SELECT NOME, GRUPPO, VALORE FROM DB1
    UNION
    SELECT NOME, GRUPPO, VALORE FROM DB2
    UNION
    SELECT NOME, GRUPPO, VALORE FROM DB3
    UNION
    SELECT NOME, GRUPPO, VALORE FROM DB4
    UNION
    SELECT NOME, GRUPPO, VALORE FROM DB5
    UNION
    SELECT NOME, GRUPPO, VALORE FROM DB6)
    GROUP BY NOME, GRUPPO

    Dove DB1, DB2, DB3, DB4, DB5, DB6 sono i risultati di query di select girate su 6 connessioni ODBC diverse..

    Grazie ancora dell'aiuto

    Ciao
    Luca
     
    Sub prova
    Dim DB1 As ADODB.Recordset
    Dim DB2 As ADODB.Recordset
    Dim DB3 As ADODB.Recordset
    Dim DB4 As ADODB.Recordset
    Dim DB5 As ADODB.Recordset
    Dim DB6 As ADODB.Recordset
    Dim sql As String
    
    sql = "SELECT NOME, GRUPPO, VALORE FROM TABELLA1 "
    Set DB1 = ExecQuery1(sql)   --> Eseguo il codice 'sql' sulla conn1
    
    sql = "SELECT NOME, GRUPPO, VALORE FROM TABELLA2 "
    Set DB2 = ExecQuery2(sql)   --> Eseguo il codice 'sql' sulla conn2
    
    sql = "SELECT NOME, GRUPPO, VALORE FROM TABELLA3 "
    Set DB3 = ExecQuery3(sql)   --> Eseguo il codice 'sql' sulla conn3
    
    sql = "SELECT NOME, GRUPPO, VALORE FROM TABELLA4 "
    Set DB4 = ExecQuery4(sql)   --> Eseguo il codice 'sql' sulla conn4
    
    sql = "SELECT NOME, GRUPPO, VALORE FROM TABELLA5 "
    Set DB1 = ExecQuery5(sql)   --> Eseguo il codice 'sql' sulla conn5
    
    sql = "SELECT NOME, GRUPPO, VALORE FROM TABELLA6 "
    Set DB1 = ExecQuery6(sql)   --> Eseguo il codice 'sql' sulla conn6
    
    
    
    
    
    
    



  • di Vecchio Frac data: 19/02/2014 18:07:36

    cit. "Quello che non capisco è come posso mettere in join il risultato delle 6 query che girano su 6 connessioni diverse"
    ---> E' quello che cerco di comunicarti: non ti servono affatto sei connessioni diverse, te ne basta una e passare all'apertura del recordset una sola query di unione: una query cioè composta da più istruzioni SELECT UNION.
    Le SELECT leggono dalle tabelle desiderate i dati necessari.
    E' richiesto che le tabelle abbiano tutte la stessa struttura (tu hai già confermato che è così).
    Il risultato è assegnato alla variabile recordset che poi può essere letta (cioè scorsa col cursore in avanti); i dati del recordset ad ogni loop di lettura vengono infilati nelle celle di Excel desiderate.
    E' un'operazione comune, sempre se ho capito la problematica :)
    Appena ho un attimo provo a simulare la tua situazione (prendo Access, creo sei tabelle con dati fittizi e costruisco la query di unione in modo che possa girare nel tuo caso).





  • di gugluca (utente non iscritto) data: 19/02/2014 18:42:26

    Ciao
    con access lo saprei fare (con le tabelle collegate)
    il problema è che sto utilizzando excel

    non riesco a capire come tu riesca a fare tutto con una connessione sola...

    grazie ancora per il tuo aiuto!!



  • di Vecchio Frac data: 19/02/2014 18:55:05

    cit. "il problema è che sto utilizzando excel"
    ---> Ma lo stai usando solo per contenere i dati finali, risultanti dal raggruppamento finale.
    La modalità di accesso ai dati (ODBC) è indipendente dall'applicativo che usi per rappresentarli.
    Per dire, potresti usare benissimo Access anche in lettura delle sei diverse tabelle e potresti anche esportare la tabella risultante in formato Excel.
    Perchè forse non ti è chiaro che quando apri sei connessioni stai di fatto creando sei tabelle diverse (i recordset sono tabelle). La mia scorciatoia è solo quella di pensare: invece di sei connessioni distinte ne apro una sola, l'origine della tabella è una query di unione (UNION SELECT), il risultato finale è un grosso recordset che posso scorrere per recuperasre le righe di dati.
    Sarebbe interessante vedere come in concreto apri la connessione (cioè come hai costruito la variabile DSN in conn1.Open DSN) per sapere se punti a un file csv o di che altro formato.
    Comunque ci provo, l'unica perplessità è sul group (ma solo perchè non ne scrivo da un po', basta un attimo di attenzione).





  • di Vecchio Frac data: 19/02/2014 19:11:59

    Ho ottenuto un certo risultato che credo sia quello che vuoi tu...
    La query di unione è come quella che riporto sotto.
    Occhio che la "somma di valore" deve avere un alias diverso da "valore" perchè questo è già un nome di campo.
    Quindi in pratica adesso dai in pasto alla connessione questa stringa sql e dovresti ottenere un recordset compilato contenente a somma dei valori dei campi "valore" raggruppati per nome e gruppo.
    Occhio ovviamente allo spezzettamento della stringa sql per motivi editoriali e di... fretta (è tutta una riga) :)
     
    Sub prova 
    Dim rs As ADODB.Recordset 
    Dim sql As String 
    
    sql = "SELECT mytable.NOME, mytable.GRUPPO, Sum(mytable.VALORE) AS SOMMA_VALORE
    FROM [SELECT NOME, GRUPPO, VALORE FROM DB1 
    UNION SELECT NOME, GRUPPO, VALORE FROM DB2 
    UNION SELECT NOME, GRUPPO, VALORE FROM DB3 
    UNION SELECT NOME, GRUPPO, VALORE FROM DB4
    UNION SELECT NOME, GRUPPO, VALORE FROM DB5
    UNION SELECT NOME, GRUPPO, VALORE FROM DB6]. AS mytable
    GROUP BY mytable.NOME, mytable.GRUPPO; "
    
    Set rs = ExecQuery1(sql) 
    
    rs.movefirst
    'ora scorri il recordset!
    while not rs.eof
    msgbox rs("nome")
    rs.movenext
    wend
    End Sub 






  • di Vecchio Frac data: 19/02/2014 21:02:59

    Forse non ho riprodotto correttamente il tuo scenario, e probabilmente ho inteso solo adesso che hai sei origini dati da riunire in una.
    Sono file di testo? li potresti importare in Excel direttamente.
    Adesso sto smanettando con file di testo creati al volo.





  • di Vecchio Frac data: 19/02/2014 21:38:31

    Eppure dai miei tentativi lo sforzo ha successo... basta una connessione sola, e la sub "prova" che ho postato poco fa funziona bene.
    Con l'avvertenza che se si tratta di file di testo si deve specificare l'estensione; e mi sono accorto che specificare i nomi dei campi provoca errore perciò ho utilizzato l'asterisco per il test e tutto è andato bene:
    sql = "SELECT * FROM db1.txt UNION SELECT * FROM db2.txt"
    Set DB1 = ExecQuery1(sql)

    Però ripeto, mi piacerebbe sapere che tipo di origine dati hai in mano.
    Significa che dovresti mostrare il DNS di conn1.





  • di gugluca (utente non iscritto) data: 20/02/2014 18:41:04

    Ciao!
    Ho sei origini dati da riunire in una.....
    Non sono file di testo, ma sono connessioni su DB su 6 server diversi della mia azienda..

    Mi sa che non si riesce a fare.. Speravo di creare 6 tabelle (chiamiamole DB1, DB2, DB3, ecc..) e lasciarle in memoria di VBA come Recordset... A quel punto puntavo a fare una union di quelle tabelle e generare un output..
    Non so se mi sono spiegato bene (capisco che è un casino, ma sinceramente non so che fare)

    In alternativa, ho accodato l'estrazione delle 6 tabelle in un foglio excel e con 2 cicli ho creato un raggruppamento dei valori... Puntavo a saltare il passaggio di estrarre i risultati delle 6 tabelle su un foglio..




  • di Vecchio Frac data: 21/02/2014 21:20:07

    La sub prova() del mio ultimo post ha prodotto qualche risultato?





  • di gugluca (utente non iscritto) data: 26/02/2014 17:11:11

    Ciao
    la tua sub non mi funziona, perchè le 6 tabelle generate DB1, DB2, DB3, DB4, DB5, DB6 (ora in memoria in locale di VBA), le sto eseguendo con una connessione diversa (il Set rs = ExecQuery1(sql) esegue il codice sulla connessione 1 e non in locale)...

    Secondo me per quello non va...