OLEDB Connection не имеет даты обновления - PullRequest
0 голосов
/ 11 декабря 2018

Мне нужно программно проверить дату обновления для ряда соединений данных OLEDB в Excel с таблицами и представлениями SQL.Все они настроены одинаково и используют одну и ту же строку подключения, и я проверяю их в VBA с помощью:

Connections.OLEDBConnection.RefreshDate

Однако у некоторых из этих подключений нет даты обновления, и яне означает, что свойство RefreshDate возвращает NULL, это свойство даже не существует.Выдает VBA и «ошибка приложения или объекта», и когда я проверяю свойства соединения, поле «последнее обновление» остается пустым:

enter image description here

Это согласованно для соединений с этими конкретными таблицами и представлениями SQL, независимо от того, как я создаю соединение или сколько раз я его обновляю.Я застрял с помощью OLEDB, и некоторые из наших машин имеют проблемы совместимости с Power Query.Кто-нибудь знает, что может вызвать это или что мне нужно изменить, либо в Excel, либо в SQL?

Ответы [ 3 ]

0 голосов
/ 17 декабря 2018

Если refreshDate не заполнено, возможно, вам не повезло.

В качестве обходного пути вы можете самостоятельно следить за обновлением.Отправной точкой является afterRefresh -Событие таблицы.Для этого вам нужно добавить следующий код в Workbook -Модуль (не будет работать с обычным модулем, так как 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

Теперь вам просто нужна логикачтобы сохранить событие обновления. В моем примере я сохраняю его как имя на уровне рабочей книги, конечно, вы также можете сохранить его в (скрытом) листе. Поместите это в обычный модуль:

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
0 голосов
/ 01 февраля 2019

Почему бы просто не добавить столбец в ваш источник 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()

Таблица LogBook должна быть создана первой.

0 голосов
/ 17 декабря 2018

Я не нашел удовлетворительного решения, но это может помочь вам, если вам крайне необходимо знать, что соединение было обновлено.Это также может зависеть от типа вашей связи.Отказ от ответственности это решение скорее взломать, чем профессиональное решение, но, кажется, работает до сих пор.Вот план:

1 Дисплей-пустышка

Отображение части данных о вашем соединении в рабочем листе.Этот лист Sheet1 может быть Hidden или VeryHidden.Не имеет значения

2 Событие

Измените событие Worksheet_Change следующим образом:

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

3 Модуль

Кроме того, вы хотите модуль, которыйпредоставляет функциональные возможности для хранения и доступа к свойству 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.Вы можете сохранить все даты на одном листе и иметь один лист для каждого соединения.

Уродливо ли это решение?Да, это.Это работает?Да, это так.

Основная идея заключается в следующем: Каждый раз, когда обновляется соединение, рабочий лист будет меняться, это вызовет событие: Worksheet_Change теперь вы можете сохранить дату, чтобы получить к ней доступ позже.

Если вы найдете другие способы доступа к событию при каждом обновлении соединения, это тоже поможет.Если вы найдете другие способы сохранить RefreshDate, это поможет.

...