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:
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?
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:
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.
Modifiez l'événement Worksheet_Change
comme suit:
Private Sub Worksheet_Change(ByVal Target As Range)
RefreshDate (Now())
End Sub
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
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.
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
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.