OLEDB 连接没有刷新日期

OLEDB Connection has no refresh date

我需要以编程方式检查 Excel 到 SQL 表和视图中许多 OLEDB 数据连接的刷新日期。它们都以相同的方式配置并使用相同的连接字符串,我在 VBA 中检查它们使用:

Connections.OLEDBConnection.RefreshDate

但是,其中一些连接没有刷新日期,我并不是说 RefreshDate 属性 returns 是 NULL,属性 甚至没有存在。 VBA 抛出 "application-defined or object-defined error,",当我检查连接属性时,"last refreshed" 字段为空:

与那些特定 SQL 表和视图的连接是一致的,无论我如何建立连接或刷新它多少次。我坚持使用 OLEDB,我们的一些机器与 Power Query 存在兼容性问题。有谁知道在 Excel 或 SQL 中会导致什么或我需要更改什么?

我还没有找到令人满意的解决方案,但如果您迫切需要知道连接是否已更新,这可能会对您有所帮助。这也可能取决于您拥有的连接类型。免责声明这个解决方案与其说是一个专业的解决方案,不如说是一个黑客,但似乎直到现在都有效。这是计划:

1 虚拟显示器

在作品中显示来自您的连接的一段数据sheet。本作品sheetSheet1可能是HiddenVeryHidden。没关系。

2 事件

修改Worksheet_Change事件如下:

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

3 模块

最重要的是,您需要一个模块来提供存储和访问另一个 sheet 上的 RefreshDate 属性 的功能。您可能想使用存储在 Thisworkbook 属性 中的对象来执行此操作,但据我所知,这并不能免于破坏。

这里是代码:

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 冲洗并重复所有连接

您现在需要对所有不适用于 RefreshDate 的连接执行此操作。您可能希望将所有日期保存在一个作品中sheet,并且每个连接都有一个作品sheet。

这个解决方案丑陋吗?是的。它有效吗?是的,它确实。

基本思路如下:每次连接刷新时工作sheet都会改变,这会触发事件:Worksheet_Change现在你可以保存日期了以便以后访问。

如果您找到其他方法在刷新连接时访问事件,这也应该可以解决问题。如果您找到其他方法来保存 RefreshDate,它就可以解决问题。

如果refreshDate没有填写,可能是你运气不好。

作为解决方法,您可以自行跟踪刷新。起点是 table 的 afterRefresh-事件。为此,您必须将以下代码添加到 Workbook-Module(不适用于常规模块,因为 With Events 需要 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

现在你只需要一个逻辑来保存刷新事件。在我的示例中,我将其保存为工作簿级别的名称,当然您也可以将其保存在(隐藏)sheet 中。将其放入常规模块中:

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

为什么不简单地在您连接到的 SQL 源中添加一列(无论是视图还是过程)?在此处添加列 RefreshTime=GETDATE()。每次用户从 SQL 中提取数据时,他们都会在返回结果中得到 RefreshTime

如果您需要在用户刷新 SQL 源时存储信息,也可以在 SQL 数据库中进行。制作存储过程:

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()

必须首先创建 table 日志。