Таблицы запросов (QueryTables) в Excel 2010 с VBA с VBA, создающей много соединений - PullRequest
5 голосов
/ 07 февраля 2011

Я следую коду, найденному на другом сайте. Вот основы моего кода:

Dim SQL As String
Dim connString As String

connString = "ODBC;DSN=DB01;UID=;PWD=;Database=MyDatabase"
SQL = "Select * from SomeTable"

With Worksheets("Received").QueryTables.Add(Connection:=connString, Destination:=Worksheets("Received").Range("A5"), SQL:=SQL)
.Refresh

End With

End Sub

Проблема с этим заключается в том, что каждый раз, когда они нажимают на назначенную кнопку, это создает новое соединение и, кажется, никогда не прерывает его. После тестирования я открываю электронную таблицу, и в разделе «Подключения» перечислены многие версии подключения. соединение Connection1 Connection2

Кажется, я не могу найти способ закрыть или удалить соединения. Если я добавлю «.delete» после «.Refresh», я получу ошибку 1004. Эта операция не может быть выполнена, потому что данные обновляются в фоновом режиме.

Есть идеи, как закрыть или удалить соединение?

Ответы [ 8 ]

9 голосов
/ 08 февраля 2011

Вы можете спросить себя, почему вы каждый раз создаете QueryTable в своем коде. Есть причины сделать это, но обычно это не нужно.

QueryTables - более типичные объекты времени разработки. То есть вы создаете QueryTable один раз (с помощью кода или пользовательского интерфейса) и обновляете QueryTable для получения обновленных данных.

Если вам нужно изменить базовый оператор SQL, у вас есть несколько вариантов. Вы можете настроить параметры, которые запрашивают значение или получать его из ячейки. Другой вариант изменения SQL - это изменение его в коде для существующего QueryTable.

Sheet1.QueryTables(1).CommandText = "Select * FROM ...."
Sheet1.QueryTables(1).Refresh

Вы можете выбрать разные столбцы или даже разные таблицы, изменив CommandText. Если это другая база данных, вам понадобится новое соединение, но это довольно редко.

Я знаю, что это не дает прямого ответа на ваш вопрос, но я думаю, что определение того, действительно ли вам нужно добавлять QueryTable каждый раз, является первым шагом.

Подробнее о параметрах см. http://dailydoseofexcel.com/archives/2004/12/13/parameters-in-excel-external-data-queries/ Это для 2003 года, поэтому есть несколько несоответствий с более поздними версиями. Основы одинаковы, вам просто может понадобиться узнать об объекте ListObject, если вы используете 2007 или более позднюю версию.

7 голосов
/ 04 августа 2011

У меня была такая же проблема. Предыдущий ответ, в то время как определенный шаг в правильном направлении - это PITA.

Это, однако, позволило мне уточнить мой поиск, и победитель ...

http://msdn.microsoft.com/en-us/library/bb213491(v=office.12).aspx

т.е. для вашего существующего объекта QueryTable просто сделайте это:

.MaintainConnection = False

Работает очень хорошо. Больше нет файла блокировки доступа к БД после обновления данных.

1 голос
/ 25 июня 2015

Вместо добавления другой таблицы запросов методом add, вы можете просто обновить свойство CommandText соединения.Однако вы должны знать, что при обновлении свойства CommandText соединения ODBC существует ошибка.Если вы временно переключаетесь на соединение OLEDB, обновите свойство CommandText, а затем переключитесь обратно на ODBC, чтобы новое соединение не создавалось.Не спрашивайте меня, почему ... это просто работает для меня.

Создайте новый модуль и вставьте следующий код:

Option Explicit

Sub UpdateWorkbookConnection(WorkbookConnectionObject As WorkbookConnection, Optional ByVal CommandText As String = "", Optional ByVal ConnectionString As String = "")

With WorkbookConnectionObject
    If .Type = xlConnectionTypeODBC Then
        If CommandText = "" Then CommandText = .ODBCConnection.CommandText
        If ConnectionString = "" Then ConnectionString = .ODBCConnection.Connection
        .ODBCConnection.Connection = Replace(.ODBCConnection.Connection, "ODBC;", "OLEDB;", 1, 1, vbTextCompare)
    ElseIf .Type = xlConnectionTypeOLEDB Then
        If CommandText = "" Then CommandText = .OLEDBConnection.CommandText
        If ConnectionString = "" Then ConnectionString = .OLEDBConnection.Connection
    Else
        MsgBox "Invalid connection object sent to UpdateWorkbookConnection function!", vbCritical, "Update Error"
        Exit Sub
    End If
    If StrComp(.OLEDBConnection.CommandText, CommandText, vbTextCompare) <> 0 Then
        .OLEDBConnection.CommandText = CommandText
    End If
    If StrComp(.OLEDBConnection.Connection, ConnectionString, vbTextCompare) <> 0 Then
        .OLEDBConnection.Connection = ConnectionString
    End If
    .Refresh
End With

End Sub

Эта подпрограмма UpdateWorkbookConnection работает только при обновлении OLEDBили соединения ODBC.Соединение не обязательно должно быть связано с сводной таблицей.Это также устраняет другую проблему и позволяет обновлять соединение, даже если существует несколько сводных таблиц, основанных на одном и том же соединении.

Чтобы инициировать обновление, просто вызовите функцию с объектом соединения и текстовыми параметрами команды, например так:

UpdateWorkbookConnection ActiveWorkbook.Connections("Connection"), "exec sp_MyAwesomeProcedure"

Также можно обновить строку подключения.

1 голос
/ 19 июня 2012

Я обнаружил, что по умолчанию новые соединения, созданные таким образом, называются «Соединение».Я использую этот фрагмент кода, чтобы удалить соединение, но сохранить список объектов.

Application.DisplayAlerts = False
ActiveWorkbook.Connections("Connection").Delete
Application.DisplayAlerts = True

Его можно легко изменить, чтобы удалить последнее добавленное соединение (или если вы отслеживаете соединения по их индексу).

Application.DisplayAlerts = False
ActiveWorkbook.Connections(ActiveWorkbook.Connections.Count).Delete
Application.DisplayAlerts = True
1 голос
/ 08 февраля 2011

Вы должны объявить соединение как отдельный объект, затем вы можете закрыть его после завершения запроса к базе данных.

У меня нет VBA IDE передо мной, поэтому извините, если есть какие-либонеточности, но это должно указывать вам в правильном направлении.

Например

Dim SQL As String
Dim con As connection

Set con = New connection
con.ConnectionString = "ODBC;DSN=DB01;UID=;PWD=;Database=MyDatabase"

Worksheets("Received").QueryTables.Add(Connection:=con, Destination:=Worksheets("Received").Range("A5"), SQL:=SQL).Refresh

con.close
set con = nothing
0 голосов
/ 01 мая 2015

Все еще актуальны годы спустя ... борются с той же проблемой, и это самая полезная тема.Моя ситуация - вариант вышеупомянутого, и я добавлю свое решение, когда найду его.

Я использую базу данных Access для своего источника данных и создаю таблицу запросов на новом листе.Затем я добавляю еще два новых листа и пытаюсь создать таблицу запросов, используя одно и то же соединение для каждого из них, но в другой таблице доступа.Первая таблица запросов работает очень хорошо, и я использую .QueryTables (1). Удалите и установите для объекта таблицы запросов значение Ничего, чтобы отключить его.

Однако на следующем листе не удается установить новую таблицу запросов с использованием того же соединения,который не был закрыт.Я подозреваю (и добавлю решение ниже), что мне нужно сбросить соединение перед удалением таблицы запросов.Вышеприведенный код Расмуса выглядит как вероятное решение.

0 голосов
/ 20 февраля 2014

Попробуйте установить для свойства QueryTable.MaintainConnection значение False ...

"Установите для MaintainConnection значение True, если подключение к указанному источнику данных необходимо поддерживать после обновления и до закрытия книги. По умолчаниюзначение равно True! И, похоже, для этого нет флажка UI (логическое чтение / чтение) "

0 голосов
/ 20 августа 2012

Если вы хотите удалить, если сразу после обновления вы должны выполнить обновление не в фоновом режиме (используя первый параметр -> Refresh False), чтобы иметь правильную последовательность действий

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...