2011-02-24 4 views
1

У меня есть книга, в которой некоторые из моих данных передают параметр обратно в запрос SQL в зависимости от некоторых выпадающих меню/действий пользователя. Это позволяет убирать книгу, улучшать вычисления и т. Д. - сохранение всей детали на уровне деталя локально в книге просто нецелесообразно.excel vba: приостанавливается выполнение параметризованных SQL-запросов?

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

Мне любопытно, есть ли у кого-нибудь какие-либо мысли или советы о лучших практиках для программного «приостановки» исполнения VBA до обновления фида. Сейчас моя работа заключается в том, чтобы разбить мой VBA на две части, выбросить все, что зависит от измененных данных, в отдельную функцию и использовать application.ontime для паузы в течение X секунд.

Application.OnTime Now + TimeSerial(0, 0, 10), "Restart" 

Это 90% -ное решение, но оно меньше, чем идеальное. Продолжительность времени произвольная - при очень медленном соединении она недостаточно длинная, а на быстрой - излишне медленная.

В идеале был бы какой-то способ подождать, пока Excel не будет готов, а затем продолжить. Подобно тому, как при использовании MS Internet Controls библиотеки можно использовать

Do Until .document.ReadyState = "complete" 

, чтобы приостановить выполнение, пока IE не возвращает состояние готовности. Какие-либо стратегии для более элегантного решения?

редактировать: на Джоне ниже, добавив код и объяснить, как SQL-запрос работает:

select sts1.studentid, sts1.alphascore as testcycle, 
sts2.numscore as lexile, sts3.alphascore as gleq, sts4.numscore as nce 

from ps.studenttestscore sts1 
join ps.students stu on (sts1.studentid = stu.id) 
join ps.studenttestscore sts2 on (sts1.studenttestid = sts2.studenttestid) 
join ps.studenttestscore sts3 on (sts1.studenttestid = sts3.studenttestid) 
join ps.studenttestscore sts4 on (sts1.studenttestid = sts4.studenttestid) 

where (stu.id = ?) and (sts1.testscoreid = 578) and (sts2.testscoreid = 575) 
and (sts3.testscoreid = 577) and (sts4.testscoreid = 576) 

в? - это параметр, который передает соответствующий идентификатор студента - запрос MS использует значение ячейки для этого параметра. клетка, что она выглядит просто имеет поиск основанный на том, что студент был выбран:

=IFERROR(INDEX(Stu!$B:$F,MATCH(Student!B2,Stu!$F:$F,0),1),999999) 

(ЕСЛИОШИБКА просто проходит произвольное число, чтобы предотвратить неприятные диалоговые окна от выскакивают, если неправильное значение каким-то образом получает выбранный) ,

+0

Пожалуйста, вы можете дать более длинный пример вызова SQL и окружающего кода - я не знаю, почему он будет ждать исполнения. Cheers –

+0

Непонятно, как вы выполняете этот SQL - можете ли вы показать свой код VBA? Что именно вы используете для своих «фидов данных»? –

ответ

2

Ваша ошибка в использовании MS-Query. Кодируйте вызовы базы данных с помощью ADODB и дожидайтесь метода Execute объекта ADODB.Command.

... Если это то, что вы на самом деле делаете. Здесь есть определенное количество догадок, но похоже, что статус запроса, а не лист, в который он встроен, - это информация, которая вам нужна.

Этот код вызывает асинхронный SQL-запрос - он концептуально похож на объект команды, который (я думаю), что вы на самом деле делаете, и цикл сырой «сна» можно заменить индикатором выполнения или кодом для опроса флагов и расчетов в другом месте.

FYI, состояние и свойства объектов ADO могут сбивать с толку. В общем случае нуль означает «закрыть», а 1 означает «открыть» (для объектов, которые возвращают открытое соединение или набор данных), а значения, превышающие 1, соответствуют ожиданию или выполнению.

Вы могли бы, конечно, просто вызвать запрос синхронно.

Я мог бы дать вам код для «DataConnection», но для этого вам гораздо лучше пойти на ConnectionStrings.com.

 

Public Function FetchRecordSet(SQL As String, Optional CursorType As CursorTypeEnum = adOpenForwardOnly) As ADODB.Recordset 
On Error Resume Next 

Set FetchRecordSet = New ADODB.Recordset 

With FetchRecordSet 

    .CacheSize = 8 
    Set .ActiveConnection = DataConnection 
    .Open SQL, , CursorType, adLockReadOnly, adCmdText + adAsyncFetch 

    Do While .State > 1 
     Application.StatusBar = "Retrieving data... " 
     Sleep 250 
    Loop 

End With 

Application.StatusBar = False 

End Function 





[Update]

Я узнал кое-что, так как я отправил этот ответ:

Если вы знаете имя команды, rowset- возвращающей функции или именованного запроса в базе данных MS-Access, не вызывайте этого:

 

    SQL = "SELECT * FROM MyQuery" 
    .Open SQL, , CursorType, adLockReadOnly, adCmdText + adAsyncFetch 

Вызов команды по имени, и сказать, ядро ​​базы данных это именованная команда, используя константу adCmdStoredProc:

 

    SQL = "MyQuery" 
    .Open SQL, , CursorType, adLockReadOnly, adCmdStoredProc + adAsyncFetch 

Он работает намного быстрее.

Посмотрите на CommandTypeEnum на MSDN, и использовать любые наиболее подходящий для вас:

https://msdn.microsoft.com/en-us/library/ms675946(v=vs.85).aspx

Использование adCmdTable для именованных таблиц и посмотреть, работает ли это лучше, чем adCmdStoredProc для «просмотра» объектов - я ve обнаружил, что это зависит от двигателей баз данных.

[/ Update]

Смежные вопросы