Connecting to SQL Server



  • Connecting to SQL Server
    di lucippo (utente non iscritto) data: 18/10/2012 10:09:40

    Salve,
    con il seguente codice intendo connettermi a SQL Server aziendale (const), far girare una query sul DB e inserire i dati in in foglio excel "RawData". Il foglio-progamma dovrà essere utilizzato da diversi utenti aziendali e funziona solo quando si è connessi nella intranet aziendale. Quando invece si è in modalità "off-line" vorrei che venga mostrato un semplice messaggio all'utente avvertendolo che è "off-line" e pertanto i dati non possono essere estratti dal server aziendale.
    Vorrei che questo messaggio comparisse anche quando ci sia un qualsiasi errore di collegamento al server.
    In sostanza, come faccio a far apparire il messaggio all'utente in tutti quei casi in cui ci sia un errore di connessione al server?
     
    Const cCNN = "ODBC; DRIVER=SQL Server;Server=server name;Database= Training;Integrated security=SSPI;"
    
    Sub RefreshData(Report As String, cSQL As String)
         ' Report name
        Sheets(Report).Select
        Cells.ClearContents    
        With ActiveSheet.QueryTables.add(Connection:=cCNN, Destination:=Range("A1"), SQL:=cSQL)
            .Name = "table"
            .FieldNames = True
            .RowNumbers = False
            .FillAdjacentFormulas = False
            .PreserveFormatting = False
            .RefreshOnFileOpen = False
            .BackgroundQuery = False
            .RefreshStyle = xlOverwriteCells
            .SavePassword = False
            .SaveData = True
            .AdjustColumnWidth = False
            .RefreshPeriod = 0
            .PreserveColumnInfo = False
            .Refresh
        End With
        'Selection.QueryTable.Delete    
    End Sub
    Sub RefreshALLData()
    RefreshData “RawData”, “select * from tbluser”
    End sub
    



  • di Vecchio Frac data: 18/10/2012 11:41:08

    Sto facendo diversi tentativi per simulare lo scenario.
    Ho lievemente modificato la tua stringa di connessione, ma il concetto è valido.

    Credo che il problema si risolva così:
    - utilizzo DisplayAlerts e On Error per disabilitare i messaggi di sistema e intercettare gli errori
    - gestisco gli errori in una routine separata
    - intercetto gli errori di ODBC e di OLEDB

    In rete ho trovato esempi per intercettare i diversi tipi di errore che si possono verificare.
    Ti allego un codice spartano ma che (mi) sembra funzionare.
    Certo ci mette un po' di tempo, ma dipende dalla risposta di Windows al tentativo di connessione, soprattutto se deve verificare una connessione di rete.
     
    Sub RefreshData()
    Const cCNN = "ODBC; DRIVER=SQL Server;Server=server name;Database= Training;Integrated security=SSPI;"
        
        Application.DisplayAlerts = False
        On Error GoTo gest_err
        ActiveSheet.QueryTables.Add Connection:=cCNN, Destination:=Range("A1"), Sql:="SELECT * FROM MYTABLE"
        ActiveSheet.QueryTables(1).Refresh BackgroundQuery:=True
    
        On Error Resume Next
        Application.DisplayAlerts = True
        Exit Sub
    
    
    gest_err:
        msg = "Module Error #=" & Str(Err.Number) & " was generated by " & Err.Source & Chr(13) & "Module Error Description=" & Err.Description & Chr(13)
        
        'ODBC
        For i = 1 To Application.ODBCErrors.Count
        msg = msg & "ODBC ERROR=" & Application.ODBCErrors(1).ErrorString & Chr(13)
        Next
        
        'OLEDB
        For i = 1 To Application.OLEDBErrors.Count
        msg = msg & "OLEDB ERROR=" & Application.OLEDBErrors.Item(1).ErrorString & Chr(13) & "OLEDB SQL STATE=" & Application.OLEDBErrors.Item(1).SqlState & Chr(13)
        Next
        
        MsgBox msg, , "Error", Err.HelpFile, Err.HelpContext
    
    
    End Sub






  • di lucippo (utente non iscritto) data: 18/10/2012 13:59:02

    Ci siamo quasi, il tuo codice va bene però c'è un problema...
    Il messaggio di errore viene mostrato anche quando non ci sono errori, sembra che la routine entri sempre in "gest_err" anche quando non ci sono errori di connessioni. Ho per esempio testato senza errori ma ottengo la Msgbox con valori:
    Module Error#=0 was generated by
    Module Error Description=

    C'è un modo per mostrare la MsgBox solo quando ci sono errori nella connessione al Server SQL?



  • di Vecchio Frac data: 18/10/2012 14:31:02

    Sì, viene gestito ogni errore.
    C'è evidentemente qualche altro problema, di tipo diverso da un errore di connessione.
    Togli On Error Resume Next e dimmi che succede.
    Male che vada, metteremo un If Err.Number = 0 per la situazione che riporti, nella gestione degli errori, però non mi sembra una bella soluzione.
    Comunque è un passo avanti :)





  • di lucippo (utente non iscritto) data: 19/10/2012 10:18:47

    Ciao VecchioFrac,
    ho tolto On erorr Resume Next ma non cambia nulla.
    Ho inserito if Err.Number <>0 e sembra che funzioni
    Vedo se riesco a ottimizzare il tutto e ti faccio sapere
    grazie



  • di Vecchio Frac data: 19/10/2012 10:48:22

    Sì, fai sapere, questo thread è interessante :)





  • di lucippo (utente non iscritto) data: 22/10/2012 15:29:49

    hi there,
    allora lo soluzione di cui sopra seppur funzionante non va bene per end user perché quando si è off-line il check richiede circa un paio di minuti per completarsi....correttamente come avevo dichiarato tu VecchioFrac all'inizio del thread è una procedura lunga.
    Ci vorrebbe qualcosa che va a verificare lo stato della connessione del server. Io pensavo ad un comando del tipo "ping" per vedere se un sever è raggiungibile e poi impostare un timeout di risposta ad es. entro 5 sec così da dare un messaggio di errore se il server non risponde entro 5 secs.
    Adesso bisogno passare dall'idea alla soluzione



  • di Vecchio Frac data: 22/10/2012 16:15:40

    Qualcosa posso proporre, è relativamente veloce e serve a pingare verso "your_site_here" per verificare la connessione (internet). Presumo che puoi utilizzare questa routine per testare se un certo sito è raggiungibile.
    Metti tutto in un modulo, testalo con l'URL che ti interessa e fai sapere :)
     
    Option Explicit
    
    'Declares for direct ping
    Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" (ByVal lpszAgent As String, ByVal dwAccessType As Long, ByVal lpszProxyName As String, ByVal lpszProxyBypass As String, ByVal dwFlags As Long) As Long
    Private Declare Function InternetOpenUrl Lib "wininet.dll" Alias "InternetOpenUrlA" (ByVal hInet As Long, ByVal lpszUrl As String, ByVal lpszHeaders As String, ByVal dwHeadersLength As Long, ByVal dwFlags As Long, ByVal dwContext As Long) As Long
    Private Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As Long) As Long
    
    Private Const INTERNET_OPEN_TYPE_PRECONFIG = 0
    Private Const INTERNET_FLAG_RELOAD = &H80000000
    Private Const INTERNET_FLAG_KEEP_CONNECTION = &H400000
    Private Const INTERNET_FLAG_NO_CACHE_WRITE = &H4000000
    
    
    Private Sub CheckConnection()
        Dim hInet As Long
        Dim hUrl As Long
        Dim Flags As Long
        
        hInet = InternetOpen("aaaa", INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0&)
        If hInet Then
            Flags = INTERNET_FLAG_KEEP_CONNECTION Or INTERNET_FLAG_NO_CACHE_WRITE Or INTERNET_FLAG_RELOAD
            hUrl = InternetOpenUrl(hInet, "your_site_here", vbNullString, 0, Flags, 0)
            If hUrl Then
                MsgBox "Your computer is connected to Internet", vbInformation, "Checing connection"
                Call InternetCloseHandle(hUrl)
                Else
                MsgBox "Your computer is not connected to Internet", vbInformation, "Checing connection"
            End If
        End If
        Call InternetCloseHandle(hInet)
    End Sub






  • di lucippo (utente non iscritto) data: 25/10/2012 12:26:34

    Ciao,

    ho provato il tuo codice ma richiede ancora troppo tempo per fare il check della connessione.
    Ho visto un pò di roba si internet e ho trovato qualcosa....ADODB connection timeout farebbe al caso mio.
    Il codice di cui sotto funziona bene però c'è qualcosa che non capisco...
    Io ho settato ConnectionTimeout = 5 secondi, quindo mi aspetterei che dopo 5 secondi se la connessione non viene stabilita allora viene mostrato il messaggio di errore.
    Purtroppo invece di 5 secs ne passano 25!!!! sembra che il valore settato venga ignorato!! strano...
     
    Function ChkCnxn() As Boolean
        On Error GoTo ErrorHandler
        
        ChkCnxn = False
        
        Dim Cnxn As ADODB.Connection
        
        Set Cnxn = New ADODB.Connection
        Cnxn.ConnectionTimeout = 5 'by default is set to 15 secs
        Cnxn.ConnectionString = "XXXXXX"
        Cnxn.Open
           
        ' clean up
        Cnxn.Close
    
        Set Cnxn = Nothing
    
        Exit Function
        
    ErrorHandler:
    
        If Err <> 0 Then        
            
            MsgBox "Connection not available & _
            vbNewLine & _
            vbNewLine & "Error Details:" & vbNewLine & Err.Source & "-->" & Err.Description, vbOKOnly, "Connection Error"        
    	
    	ChkCnxn = True
    
        End If
    End Function



  • di Vecchio Frac data: 25/10/2012 13:32:10

    Il codice è molto buono.
    Strano però che attendi così tanto, alla primissima esecuzione ho atteso circa un secondo e mezzo, le successive prove danno un risultato immediato.





  • di lucippo (utente non iscritto) data: 25/10/2012 13:41:23

    grazie per il feed-back sul codice!
    anche io ho notato che il tempo di esecuzione del secondo test è più veloce del primo. nel mio caso ho atteso 70 secs nel primo caso a 23 secs nel secondo test. io sto testando una connessione ad un server aziendale con connessione da casa in VPN sotto Telecom. Immagino che ci siano degli aspetti tecnici che ignoro che riguardano l'instradamento, connessioni varie etc etc
    Comunque adesso mi accontento ed implemento questo soluziono
    flaggo risolta
    grazie mille per il supporto!



  • di lucippo (utente non iscritto) data: 25/10/2012 13:42:04

    risolta



  • di Vecchio Frac data: 25/10/2012 15:00:38

    Grazie a te.
    Hai guardato le potenzialità di TeamViewer? io lo uso regolarmente per connettermi da casa al pc dell'ufficio (come un desktop remoto) e non ho grossi problemi di rallentamento. Ho studiato questa soluzione perchè a differenza tua io non ho i permessi per collegarmi alle rete aziendale dall'esterno :)