web-dev-qa-db-fra.com

Erreurs de connexion de données Excel lors de l'actualisation

Résolu! Voir ci-dessous pour la solution!

Je suis dans Excel 2010 en me connectant à plusieurs, séparés db Access 2010 à partir d'Excel via des connexions de données de tableau croisé dynamique.

L'actualisation de toutes mes connexions entraîne l'échec de l'actualisation finale. L'ordre n'a pas d'importance, j'ai rafraîchi manuellement dans différents ordres, même erreur.

Cependant, si je sauvegarde et ferme après en avoir rafraîchi quelques-uns, puis revenez et actualisez le dernier, il n’ya aucun problème.

Cela me porte à croire que je suis en train de mettre en place une sorte de limite de mémoire qui est réinitialisée lorsque je sauvegarde et ferme.

Puis-je recréer cet effet via VBA sans enregistrer/fermer réellement? Existe-t-il une meilleure solution à ce problème?

Messages d'erreur - Ces trois fenêtres apparaissent dans cet ordre:

  • La requête n'a pas été exécutée ou la table de base de données n'a pas pu être ouverte.
  • Problèmes d'obtention de données.
  • Un tableau croisé dynamique, une fonction de cube ou un segment utilisant une connexion n'a pas pu être actualisé.

Code actuel

Private Sub CommandButton1_Click()
On Error GoTo ErrHndlr

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.StatusBar = "Refreshing Data - Please Be Patient"

ActiveWorkbook.Connections("Connection_1").Refresh
ActiveWorkbook.Connections("Connection_2").Refresh
ActiveWorkbook.Connections("Connection_3").Refresh

Application.Calculation = xlCalculationAutomatic
Application.StatusBar = "Ready"
[LastUpdated].Value = FormatDateTime(Now, vbGeneralDate)
Application.ScreenUpdating = True
Exit Sub

ErrHndlr:
  Application.StatusBar = "Ready"
  Application.Calculation = xlCalculationAutomatic
  Application.ScreenUpdating = True
  [LastUpdated].Value = "Update Error"
  Exit Sub

End Sub

Chaîne de connexion

Provider=Microsoft.ACE.OLEDB.12.0
;User ID=Admin
;Data Source=C:\Folders\Database_1.accdb
;Mode=Share Deny None
;Extended Properties=""
;Jet OLEDB:System database=""
;Jet OLEDB:Registry Path=""
;Jet OLEDB:Engine Type=6
;Jet OLEDB:Database Locking Mode=0
;Jet OLEDB:Global Partial Bulk Ops=2
;Jet OLEDB:Global Bulk Transactions=1
;Jet OLEDB:New Database Password=""
;Jet OLEDB:Create System Database=False
;Jet OLEDB:Encrypt Database=False
;Jet OLEDB:Don't Copy Locale on Compact=False
;Jet OLEDB:Compact Without Replica Repair=False
;Jet OLEDB:SFP=False
;Jet OLEDB:Support Complex Data=False
;Jet OLEDB:Bypass UserInfo Validation=False

Solutions tentées

  • Désactiver l'actualisation en arrière-plan - Déjà désactivé
  • Désactiver la récupération automatique (pour économiser de la mémoire)
  • Effacer "Annuler pile" (pour économiser de la mémoire)
  • 'DoEvents' pour retarder l'exécution du code jusqu'à la fin de chaque actualisation, en modifiant:

ce

ActiveWorkbook.Connections("Connection_1").Refresh

à

With ActiveWorkbook.Connections("Connection_1")
  Select Case .Type
    Case xlConnectionTypeODBC
      With .ODBCConnection
        .Refresh
        Do While .Refreshing
          DoEvents
        Loop
      End With
    Case xlConnectionTypeOLEDB
      With .OLEDBConnection
        .Refresh
        Do While .Refreshing
          DoEvents
        Loop
      End With
    Case Else
      .Refresh
  End Select
End With

SOLUTION!

Remarque secondaire, j'ai quelques connexions supplémentaires que je ne voulais pas mettre à jour via ce code et j'ai ajouté une logique simple supplémentaire pour spécifier les connexions que je voulais mettre à jour. Ce code fonctionne ici pour actualiser chaque connexion de votre classeur:

Dim i As Integer
Dim awc As WorkbookConnection
Dim c As OLEDBConnection

Set awc = ActiveWorkbook.Connections.Item(i)
Set c = awc.OLEDBConnection
c.EnableRefresh = True
c.BackgroundQuery = False
c.Reconnect
c.Refresh
awc.Refresh
c.MaintainConnection = False
Next i

Je ne connais pas les spécificités de pourquoi cela fonctionne. Cette partie de cette opération permet à Excel de dépasser sa propre limitation. J'aimerais entendre davantage si quelqu'un est plus familier!

9
Aaron Contreras

Ce n'est pas une réponse complète, mais une tentative d'aide au débogage, afin que nous puissions trouver une solution.

Je crois que vous pouvez résoudre ce problème en déboguant Connections. Essayez de remplacer votre code de rafraîchissement ci-dessus (et le remplacement par DoEvents) par le sous-sous suivant. Tout d'abord, il est possible que l'affichage du dialogue entre les actualisations corrige le problème (s'il s'agit d'actualisations simultanées, etc.). Deuxièmement, chaque fois que cela fonctionne, vérifiez attentivement que rien n'a changé. S'il vous plaît rapporter avec des découvertes ou des informations. Si les erreurs persistent, parcourez le code et signalez la ligne qui génère l'erreur.

Sub ShowDebugDialog()

   Dim x As Integer
   Dim i As Integer, j As Integer
   Dim awc As WorkbookConnection
   Dim c As OLEDBConnection

   For i = 1 To ActiveWorkbook.Connections.Count
   'For i = ActiveWorkbook.Connections.Count To 1 Step -1

      For j = 1 To ActiveWorkbook.Connections.Count
         Set awc = ActiveWorkbook.Connections.Item(j)
         Set c = awc.OLEDBConnection
         x = MsgBox("ConnectionName: " & awc.Name & vbCrLf & _
              "IsConnected: " & c.IsConnected & vbCrLf & _
              "BackgroundQuery: " & c.BackgroundQuery & vbCrLf & _
              "MaintainConnection: " & c.MaintainConnection & vbCrLf & _
              "RobustConnect: " & c.RobustConnect & vbCrLf & _
              "RefreshPeriod: " & c.RefreshPeriod & vbCrLf & _
              "Refreshing: " & c.Refreshing & vbCrLf & _
              "EnableRefresh: " & c.EnableRefresh & vbCrLf & _
              "Application: " & c.Application & vbCrLf & _
              "UseLocalConnection: " & c.UseLocalConnection _
              , vbOKOnly, "Debugging")
      Next j

      Set awc = ActiveWorkbook.Connections.Item(i)
      Set c = awc.OLEDBConnection
      c.EnableRefresh = True
      c.BackgroundQuery = False
      c.Reconnect
      c.Refresh
      awc.Refresh
      c.MaintainConnection = False
   Next i

End Sub

Questions supplémentaires auxquelles vous pouvez répondre si vous recevez toujours des erreurs: 

  • BackgroundQuery était-il toujours faux? 
  • Y a-t-il eu un délai perceptible entre chaque jeu de dialogues (indiquant qu'Excel attend la fin d'un rafraîchissement) ou est-ce qu'ils sont tous apparus immédiatement après le dernier? 
  • Quelle ligne de code soulève l'erreur initiale? Si vous actualisez les connexions dans l'ordre inverse (en supprimant la mise en commentaire de la ligne "Étape -1"), vous obtenez l'erreur à la même connexion? 
  • Lorsque vous dites que vous pouvez mettre à jour les connexions manuellement, est-ce via une macro différente ou via Data >> Connections >> Refresh? 
  • Des erreurs si vous sélectionnez manuellement "RefreshAll"?

Désolé pour toutes les questions, mais vous devez penser à tout lors du débogage de mauvaises erreurs de connexion comme celle-ci.

2
ExactaBox

J'avais donc une erreur similaire lorsque j'essayais de créer un script VBA pour actualiser automatiquement un classeur Excel à un moment donné, et certaines choses que j'ai effectuées dans mon script VBA pour que cela fonctionne. L'un d'eux est désactive l'actualisation en arrière-plan . Cela pourrait être votre problème et vous pouvez facilement le désactiver en accédant à vos propriétés de connexion et en désactivant l'actualisation en arrière-plan.

Voici ce que j'ai fait dans VBA lorsque j'ai eu cette erreur, bien que je dirais que je ne l'utilisais pas avec une base de données MS Access. J'avais un classeur Excel que je utilisais comme «coureur» et il ouvrait les autres livres un par un et rafraîchissait leurs liens. Fondamentalement, j'avais une variable pour les variables path et extension et plaçais les noms de chaque classeur dans un tableau et le parcourait en boucle.

J'ai combiné le chemin et l'extension pour me donner le nom de fichier complet du fichier, vous le verrez dans la boucle.

Voici à quoi ressemblait ma boucle:

For i = LBound(testArray) To UBound(testArray)
    Dim wb As Workbook
    Set wb = Workbooks.Open(path & testArray(i) & ext, 0, False)

    'Next I checked to see if the workbook was in protected view and allowed for editing.
    If Application.ProtectedViewWindows.Count > 0 Then
        Application.ActiveProtectedViewWindow.Edit
    End If

    'Now comes the part that I believe should help for your case
    wb.Connections(testArray(i) & "This is your connection name").OLEDBConnection.BackgroundQuery = False
    wb.RefreshAll
    wb.Connections(testArray(i) & "This is your connection name").OLEDBConnection.BackgroundQuery = True

    wb.SaveAs fileName:= "Thisbook.xlsx"
    wb.Close
Next i

Pour obtenir le nom de la connexion, vous pouvez procéder de plusieurs manières, notamment en cherchant simplement à voir ce que c'est manuellement. Pour moi, parce que je voulais faire en sorte que je n’aie pas besoin de mettre manuellement chaque nom de connexion, j’ai utilisé le modèle inhérent que j’ai vu avec les noms de connexions.

Dans mon cas, c'était le baseNameOfWorkbook & " POS Report"

Je pense que les erreurs dues au rafraîchissement de l’arrière-plan risquent de vous causer des erreurs. Donc, si vous n'avez pas besoin de faire cela dans VBA, je vous suggère simplement d'aller dans les propriétés de connexion et de le désactiver.

Laissez-moi savoir si cela fonctionne.

3
Adjit

Pour effacer la mémoire système, vous pouvez toujours exécuter quelque chose comme ceci:

Sub ClearUndo()
Range("A1").Copy Range("A1")
End Sub

Cela effacera la pile d'annulation contenant toutes les mises à jour de vos tableaux croisés dynamiques, ce qui vous permettra de les annuler. Si vous faites cette référence entre les deux, cela peut vous aider à garder l'utilisation de la mémoire sous contrôle.

Ne tenez pas compte de ma suggestion précédente, car je pensais à une solution qui m'a aidé dans Access.

0
pegicity

Vous pouvez utiliser VBA pour appeler vos actualisations individuellement via l'objet activeworkbook . Connections. Voir cet article Stack Overflow pour quelques indices sur cette méthode. Une approche plus atomistique peut permettre une meilleure compréhension et un meilleur contrôle. Par exemple, une fois que toutes les étapes sont en place, vous pouvez essayer d'insérer DoEvents dans résoudre le problème.

0
Smandoli