IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VBA Access Discussion :

Lenteur d'exécution aléatoire de VBA avec Access


Sujet :

VBA Access

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développement d'une BD maison
    Inscrit en
    Octobre 2014
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Développement d'une BD maison

    Informations forums :
    Inscription : Octobre 2014
    Messages : 7
    Points : 5
    Points
    5
    Par défaut Lenteur d'exécution aléatoire de VBA avec Access
    J'utilise une application Access 2013 pour accéder à une base de donnée dans SQL Server express 2012.

    Dans plusieurs procédures, j'exécute en mode transactionnel une commande ADODB dans une boucle While- Wend pour chaque enregistrement trouvé et stoqué dans un recordset et tout fonctionne normalement. Or, pour une de ces procédures, l'exécution du code VBA devient très lent au point qu' il y a génération de l'erreur :

    "ODBC -- l'appel a échoué.

    [Microsoft][SQL Server Native Client 11.0]Query timeout expired (#0) "


    Ce qui m'intrigue, c'est que parfois l'exécution du code fonctionne normalement et que plus souvent qu'autrement, il ralentit, principalement lors de la première exécution de l'objet ADODB.Command.

    Je soupçonne que c'est le ralentissement d'exécution qui empêche la connexion à la BD mais je ne sais comment identifier la cause de ce ralentissement et encore moins comment le régler. Merci d'avance pour l'aide!!

    Voici le code problématique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    Sub MAJHDepTrav(strNomForm As String, numIdFTemps As Long)
        On Error GoTo Trappe
     
        Dim cn As ADODB.Connection
        Dim cmd As ADODB.Command
        Dim rs As ADODB.Recordset
        Dim strSQL As String
        Dim numIdEmpl, numHTotEmpl, curDepTotEmpl
        Dim numIdProjet As Long
        Dim strSource As String
     
        strSource = "modProjets.MAJHDepTrav"
        LogEvt strSource, strSource, TYPE_EVT_INFO
     
        Set cn = CurrentProject.Connection
        cn.BeginTrans
     
       numIdEmpl = CLng(DLookup("[FK_Empl]", "tblFTemps", "Id = " & numIdFTemps))
     
       'Récup dela liste des projets de la feuille de temps à mettre à jour
        Select Case strNomForm
     
            Case "frmFTemps"
                strSQL = "SELECT distinct tblFTempsLignes.FK_Projet" & _
                        " FROM  tblFTempsLignes LEFT JOIN tblProjets ON tblFTempsLignes.FK_Projet = tblProjets.ID" & _
                        " WHERE tblFTempsLignes.FK_FTemps = " & numIdFTemps & " AND tblProjets.FK_Statut=9" & _
                                " Or tblFTempsLignes.FK_FTemps = " & numIdFTemps & " AND tblProjets.FK_Statut=65"
            Case Else
                strSQL = "SELECT [ID] FROM tblProjets WHERE FK_Statut = 9 or FK_Statut = 65"
        End Select
     
        Set rs = New ADODB.Recordset
        rs.Open strSQL, cn, adOpenForwardOnly, adLockReadOnly
     
        'Mise-à-jour de [tblAFacturer]![HTotTrav] et [tblAFacturer]![DepTotTrav] ou ajout d'un enregistrement dans tblAFacturer pour les projets sélectionnés.
        While Not rs.BOF And Not rs.EOF
     
            'Récup des données à transférer
            Select Case strNomForm
                Case "frmFTemps"
                    numIdProjet = rs.Fields![FK_Projet].Value
                Case Else
                    numIdProjet = rs.Fields![Id].Value
            End Select
     
            numHTotEmpl = DLookup("[HTrav]", "qryTotTrav", "FK_Projet = " & numIdProjet & " and FK_Empl = " & numIdEmpl)
            curDepTotEmpl = DLookup("[DepTrav]", "qryTotTrav", "FK_Projet = " & numIdProjet & " and FK_Empl = " & numIdEmpl)
     
            'MAJ ou ajout dans tblAFacturer selon qu'il s'agit ou non d'un nouvel employé à facturer
            If NouvelEmplAFacturer(ByVal numIdEmpl, ByVal numIdProjet) Then
     
                Set cmd = New ADODB.Command
                With cmd
                    .ActiveConnection = cn
                    .CommandType = adCmdText
                    strSQL = ""
                    strSQL = strSQL & "INSERT INTO tblAFacturer"
                    strSQL = strSQL & " (FK_Projet, FK_Empl, HTotTrav, DepTotTrav, HTotFact, DepTotFact)"
                    strSQL = strSQL & " VALUES(" & numIdProjet & ", " _
                                                 & numIdEmpl & ", " _
                                                 & Replace(numHTotEmpl, ",", ".") & ", " _
                                                 & Replace(curDepTotEmpl, ",", ".") & ", 0, 0)"
                    .CommandText = strSQL
                    .Execute
                End With
            Else
                Set cmd = New ADODB.Command
                With cmd
                    .ActiveConnection = cn
                    .CommandType = adCmdText
                    strSQL = ""
                    strSQL = strSQL & "UPDATE tblAFacturer"
                    strSQL = strSQL & " SET [HTotTrav] = " & Replace(numHTotEmpl, ",", ".")
                    strSQL = strSQL & ", [DepTotTrav] = " & Replace(curDepTotEmpl, ",", ".")
                    strSQL = strSQL & " WHERE FK_Projet = " & numIdProjet & " and FK_Empl = " & numIdEmpl
                    .CommandText = strSQL
                    .Execute
                End With
            End If
            rs.MoveNext
        Wend
     
        'On sauvegarde TOUTES les modifications
        cn.CommitTrans
     
    Sortie:
        'Ménage
        On Error Resume Next
        pnumErrNum = 0
        pstrErrDescr = ""
        rs.Close
        Set rs = Nothing
        Set cmd = Nothing
        cn.Close
        Set cn = Nothing
        Exit Sub
    Trappe:
        pnumErrNum = Err.Number
        pstrErrDescr = Err.Description
        LogErr pnumErrNum & ": " & pstrErrDescr, strSource
        Select Case pnumErrNum
     
            Case Else
                On Error Resume Next
                pnumErrNum = 0
                pstrErrDescr = ""
                Err.Clear
                cn.RollbackTrans
                If Err.Number <> 0 Then LogErr ERR1093_DESCR, strSource
                rs.Close
                Set rs = Nothing
                Set cmd = Nothing
                cn.Close
                Set cn = Nothing
                Err.Raise ERR1160, strSource, ERR1160_DESCR
        End Select
    End Sub 'MAJHDepTrav
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    Function NouvelEmplAFacturer(ByVal numIdEmpl As Long, ByVal numIdProjet As Long) As Boolean
        On Error GoTo Trappe
        'Vérifie si on doit ajouter une ligne à tblAFacturer qui correspond à la ligne de tblFTempsLignes
        'Ex: MsgBox NouvelEmplAFacturer(4, 1255)
     
        Dim numResult As Integer
        Dim strSource As String
     
        strSource = "modProjets.NouvelEmplAFacturer"
        LogEvt strSource, strSource, TYPE_EVT_INFO
     
        numResult = DCount("[Id]", "tblAFacturer", "FK_Projet = " & numIdProjet & " and FK_Empl = " & numIdEmpl)
     
        If numResult = 0 Then
            NouvelEmplAFacturer = True
        Else
            NouvelEmplAFacturer = False
        End If
    Sortie:
        On Error Resume Next
        pnumErrNum = 0
        pstrErrDescr = ""
        Exit Function
    Trappe:
        pnumErrNum = Err.Number
        pstrErrDescr = Err.Description
        LogErr pnumErrNum & ": " & pstrErrDescr, strSource
        Select Case pnumErrNum
     
            Case Else
                Err.Raise ERR1159, strSource, ERR1159_DESCR
        End Select
        Resume Sortie
    End Function 'NouvelEmplAFacturer

  2. #2
    Membre émérite Avatar de Zekraoui_Jakani
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    1 670
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1 670
    Points : 2 489
    Points
    2 489
    Par défaut
    Je n'ai pas le temps de lire le code mnt; mais avez-vous essayer de compacter la db de temps en temps ?

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Développement d'une BD maison
    Inscrit en
    Octobre 2014
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Développement d'une BD maison

    Informations forums :
    Inscription : Octobre 2014
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Je compacte la db régulièrement.

    De mon côté, j'ai créé une fonction scalaire dans la db sur SQL Server pour remplacer la requête qryTotTrav qui semble ralentir le code.

    Je pense être sur la bonne voie mais je continue à faire des tests.

    Merci!

  4. #4
    Futur Membre du Club
    Homme Profil pro
    Développement d'une BD maison
    Inscrit en
    Octobre 2014
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Développement d'une BD maison

    Informations forums :
    Inscription : Octobre 2014
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Se pourrait-il qu'en mode transactionnel, il y ait une limite du nombre de modifications que la mémoire peut emmagasiner avant un CommitTrans ou encore un nombre limite d'itérations de la boucle While-Wend (178 dans mon cas) ? Après des tests, je remarque que le code plante toujours au traitement du même enregistrement (174 sur 178).

    De plus, lorsque j'utilise le code avec un nombre plus restreint d'enregistrements à traiter, cela fonctionne.

    Merci d'avance!

  5. #5
    Membre émérite Avatar de Zekraoui_Jakani
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    1 670
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1 670
    Points : 2 489
    Points
    2 489
    Par défaut
    Je suppose qu'il n'y a pas de problème de saturation de mémoire!
    Le code me paraît correct; mes suggestions: le "commit trans" est inutile dans ce cas précis, et ça prend de la mémoire pour rien.
    Autre amélioration possible (à tester le temps de voir si ça tourne mieux): remplacer l'UPDATE par une simple query de mise à jour à appeler dans le code; ça peut jouer, mais pour l'instant je n'ai pas de meilleure pistes que celles énumérées ci-dessus.

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Développement d'une BD maison
    Inscrit en
    Octobre 2014
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Développement d'une BD maison

    Informations forums :
    Inscription : Octobre 2014
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Après réflexion, je suis réticent à enlever le CommitTrans/RollbackTrans de ma procédure justement au cas où la boucle plante, je veux éviter que les données soient modifiées partiellement.

    Je vais plutôt essayer de contourner le problème en utilisant le code seulement avec le formulaire qui commande l'exécution sur un nombre plus restreint d'enregistrements. Je vous reviendrai pour vous dire si tout fonctionne.

    Merci!

Discussions similaires

  1. comment exécuter ma fonction VBA dans Access
    Par kapotocho dans le forum VBA Access
    Réponses: 23
    Dernier message: 18/01/2008, 16h43
  2. menu vba avec access
    Par habib2006 dans le forum VBA Access
    Réponses: 10
    Dernier message: 27/10/2006, 19h06
  3. Comment lire un fichier de 2go en VBA avec Access
    Par Fablondon dans le forum Access
    Réponses: 8
    Dernier message: 31/08/2006, 09h36
  4. Réponses: 5
    Dernier message: 13/07/2006, 09h39
  5. Ajouter un enregitrement a une table vide en VBA avec access
    Par Mateache dans le forum VBA Access
    Réponses: 4
    Dernier message: 03/01/2006, 15h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo