web-dev-qa-db-fra.com

La connexion OLEDB n'a pas de date d'actualisation

Je dois vérifier par programme la date d'actualisation d'un certain nombre de connexions de données OLEDB dans Excel aux tables et vues SQL. Ils sont tous configurés de la même manière et utilisent la même chaîne de connexion, et je les vérifie dans VBA en utilisant: 

Connections.OLEDBConnection.RefreshDate

Cependant, quelques-unes de ces connexions n'ont pas de date d'actualisation et je ne veux pas dire que la propriété RefreshDate renvoie un NULL, cette propriété n'existe même pas. VBA émet une "erreur définie par l'application ou définie par l'objet" et lorsque je vérifie les propriétés de la connexion, le champ "actualisé en dernier" est vide:

 enter image description here

Il est cohérent pour les connexions à ces vues et tables SQL particulières, indépendamment de la manière dont je construis la connexion ou du nombre de fois où je l'actualise. Je suis bloqué avec OLEDB et certaines de nos machines ont des problèmes de compatibilité avec Power Query. Est-ce que quelqu'un sait ce qui causerait ceci ou ce que je dois changer, que ce soit dans Excel ou dans SQL?

8
C Dieguez

Je n'ai pas trouvé de solution satisfaisante mais cela peut vous aider si vous avez désespérément besoin de savoir que la connexion a été mise à jour. Cela peut également dépendre du type de connexion que vous avez. Clause de non-responsabilité: cette solution est plus un piratage qu'une solution professionnelle, mais semble fonctionner jusqu'à présent. Voici le plan:

1 Le mannequin

Affichez une donnée de votre connexion dans une feuille de calcul. Cette feuille de calcul Sheet1 peut être Hidden ou VeryHidden. Ca n'a pas d'importance. 

2 L'événement

Modifiez l'événement Worksheet_Change comme suit:

Private Sub Worksheet_Change(ByVal Target As Range)
RefreshDate (Now())
End Sub

3 modules

En plus de cela, vous voulez un module offrant des fonctionnalités pour stocker et accéder à la propriété RefreshDate sur une autre feuille. Vous voudrez peut-être le faire avec un objet stocké dans la propriété Thisworkbook mais ce n'est pas à l'abri de la destruction, pour autant que je sache.

Voici le code: 

Sub RefreshDate(D As Date)
Sheet2.Range("A1").Value = D
End Sub

Public Function GetRefreshDate() As Date
GetRefreshDate = Sheet2.Range("A1").Value
End Function

4 rincer et répéter pour toutes les connexions

Vous devez maintenant procéder de la sorte pour toutes les connexions qui ne fonctionnent pas avec la variable RefreshDate. Vous souhaiterez peut-être enregistrer toutes les dates dans une feuille de calcul et disposer d'une feuille de calcul pour chaque connexion. 

Cette solution est-elle laide? Oui, ça l'est. Est-ce que ça marche? Oui. 

L'idée de base est la suivante: Chaque fois que la connexion est rafraîchie, la feuille de calcul change. Cela déclenchera l'événement: Worksheet_Change. Vous pouvez maintenant enregistrer la date pour pouvoir y accéder ultérieurement.

Si vous trouvez d'autres moyens d'accéder à un événement chaque fois qu'une connexion est rafraichie, cela devrait également faire l'affaire. Si vous trouvez d'autres moyens de sauvegarder la RefreshDate, cela fera l'affaire. 

4

Si la refreshDate n'est pas remplie, vous n'avez probablement pas de chance.

En guise de solution de contournement, vous pouvez suivre vous-même l'actualisation. Le point de départ est l'événement afterRefresh- d'une table. Pour cela, vous devez ajouter le code suivant au module Workbook- (ne fonctionnera pas avec un module standard car le With Events nécessite une class.

Option Explicit
Private WithEvents table As Excel.QueryTable

Private Sub table_AfterRefresh(ByVal Success As Boolean)
    Debug.Print table.WorkbookConnection.name & " refreshed. (success: " & Success & ")"
    If Success Then
        Call trackRefreshDate(table.WorkbookConnection.name, Now)
    End If
End Sub

Vous avez maintenant besoin d'une logique pour enregistrer l'événement d'actualisation. Dans mon exemple, je l’enregistre sous un nom au niveau du classeur. Vous pouvez bien sûr également l’enregistrer dans une feuille (masquée). Mettez ceci dans un module régulier:

Sub trackRefreshDate(tableName As String)

    Dim nameObj As Name, nName As String
    Set nameObj = Nothing
    nName = "Refresh_" & tableName
    On Error Resume Next
    ' Check if name already exists
    Set nameObj = ThisWorkbook.Names(nName)
    On Error GoTo 0
    Dim v
    v = Format(Now, "dd.mm.yyyy hh:MM:ss")
    If nameObj Is Nothing Then
        ' No: Create new
        Call ThisWorkbook.Names.Add(nName, v)
    Else
        nameObj.Value = v
    End If
End Sub

Function getRefreshDate(tableName As String)
    Dim nName As String
    nName = "Refresh_" & tableName
    On Error Resume Next
    getRefreshDate = Replace(Mid(ThisWorkbook.Names(nName), 2), """", "")
    On Error GoTo 0        
End Function
2
FunThomas

Pourquoi ne pas simplement ajouter une colonne dans votre source SQL à laquelle vous vous connectez (que ce soit une vue ou une procédure)?. Ajoutez la colonne RefreshTime=GETDATE(). Chaque fois que l'utilisateur extrait les données de SQL, les résultats renvoyés sont RefreshTime

Si vous devez stocker des informations lors de l'actualisation de la source SQL par l'utilisateur, faites-le également dans la base de données SQL. Faire une procédure stockée:

create stored procedure ShareMySource as
-- part one, prepare data
select * from MySQLTable;

-- part two, get user data
insert into dbo.LogBook
select 
RefreshTime=getdate(), 
User = ORIGINAL_LOGIN()

La table LogBook doit être créée en premier. 

0
Przemyslaw Remin