#ms-access-2010
#vba #ms-доступ
Вопрос:
У меня есть запрос под названием qryAlloc_Source, в котором два параметра соответствуют одному критерию:
gt;=[forms]![frmReportingMain]![txtAllocStart] And lt;=[forms]![frmReportingMain]![txtAllocEnd])
У меня есть отдельный запрос, который в конечном итоге ссылается на qryAlloc_Source (между ними есть пара запросов), и этот запрос работает нормально, когда я дважды щелкаю по нему в пользовательском интерфейсе, но если я попытаюсь открыть его в VBA, я получу ошибку. Мой код таков:
Dim rst As Recordset Set rst = CurrentDb.OpenRecordset("qryAlloc_Debits")
Я получаю ошибку 3061 во время выполнения, слишком мало параметров. Ожидается 2. Я читал, что мне, возможно, потребуется создать SQL в VBA с использованием параметров формы, но это будет довольно сложный SQL, учитывая, что в цепочке есть несколько запросов.
Есть какие-либо предложения по обходному пути? Я подумал о том, чтобы использовать VBA для создания таблицы из запроса, а затем просто ссылаться на эту таблицу-хотя я ненавижу делать дополнительные шаги.
Ответ №1:
Причина, по которой вы получаете ошибку, когда просто пытаетесь открыть набор записей, заключается в том, что ваша форма не открыта, и когда вы пытаетесь получить доступ [forms]![frmReportingMain]
к ней, она равна нулю, затем вы пытаетесь получить свойство по этой нулевой ссылке, и все взрывается. OpenRecordset
Функция не может открыть диалоговое окно для запроса пользовательских вводов, как это делает пользовательский интерфейс, если он получает эту ошибку.
Вы можете изменить свой запрос, чтобы использовать параметры, которые не привязаны к форме
yourTableAllocStart gt;= pAllocStart and yourTableAllocEnd lt;= pAllocEnd
Затем вы можете использовать эту функцию для получения набора записей этого запроса.
Function GetQryAllocDebits(pAllocStart As String, pAllocEnd As String) As DAO.Recordset Dim db As DAO.Database Dim qdef As DAO.QueryDef Set db = CurrentDb Set qdef = db.QueryDefs("qryAlloc_Debits") qdef.Parameters.Refresh qdef.Parameters("pAllocStart").Value = pAllocStart qdef.Parameters("pAllocEnd").Value = pAllocEnd Set GetQryAllocDebits = qdef.OpenRecordset End Function
Недостатком этого является то, что, когда вы вызываете это сейчас в привязанной к нему форме, она динамически не «заполняет пробелы» для вас.
В этом случае вы можете привязать формы qryAlloc_debts
и не иметь предложения where в сохраненном запросе, а затем использовать формы Filter
для создания предложения where. В этом случае вы можете использовать свое предложение where именно так, как вы его написали.
Затем, если вы все еще хотите открыть набор записей, вы можете сделать это следующим образом
Function GetQryAllocDebits(pAllocStart As String, pAllocEnd As String) As DAO.Recordset Dim qdef As DAO.QueryDef Set qdef = New DAO.QueryDef qdef.SQL = "Select * from qryAlloc_Debits where AllocStart gt;= pAllocStart and pAllocEnd lt;= pAllocEnd" qdef.Parameters.Refresh qdef.Parameters("pAllocStart").Value = pAllocStart qdef.Parameters("pAllocEnd").Value = pAllocEnd Set GetQryAllocDebits = qdef.OpenRecordset End Function
Комментарии:
1. Мне нужно перечитать это, чтобы полностью переварить, но я хотел отметить, что моя форма открыта и введен диапазон дат. На самом деле я инициирую код с помощью кнопки в той же форме. Вот что меня действительно смущает-я могу открыть запрос вручную, но не с помощью кода. Большое спасибо за вклад, хотя … Сейчас я еще раз рассмотрю его.
2. Поэтому моя главная проблема в том, что эти параметры не являются частью необходимого мне запроса (qryAlloc_Debits)… они являются частью запроса исходных данных, который фильтрует необработанные данные по дате. Запрос, который мне нужен, — это несколько запросов по цепочке, которые выполняют большую группировку и консолидацию. Поэтому, к сожалению, я не могу применить параметры непосредственно к этому запросу.
3. что ж, опция определения запроса все еще применима. Параметры будут продвигаться вверх по цепочке. Вы даже можете заполнить этот набор записей следующим образом при загрузке формы и установить его в набор записей формы.
4. Или, как только вы получите свой большой набор запросов, объедините его обратно в один запрос.
5. Ах, теперь я понимаю-мне не хватало того, что я мог использовать параметры qdef, даже если эти параметры не были указаны конкретно в этом запросе. Спасибо!
Ответ №2:
В то время как a [Образуется]!… ссылка по умолчанию является ссылкой на форму, когда QueryDef запускается из графического интерфейса, на самом деле это просто еще один параметр в запросе в VBA. В результате вам вообще не нужно перекодировать свой запрос/создавать новый. Кроме того, как упоминал @Brad, независимо от того, находится ли параметр в конечном запросе цепочки запросов или нет, вы можете ссылаться на параметр так, как если бы он находился в коллекции конечного запроса. В таком случае вы должны иметь возможность использовать код, аналогичный этому:
Sub GetQryAllocDebits(dteAllocStart As Date, dteAllocEnd as Date) Dim db As DAO.Database Dim qdf As DAO.QueryDef Dim rst As DAO.Recordset Set db = CurrentDb() Set qdf = db.QueryDefs("qryAlloc_Debit") If CurrentProject.AllForms("frmReportingMain").IsLoaded Then qdf.Parameters("[forms]![frmReportingMain]![txtAllocStart]") = [forms]![frmReportingMain]![txtAllocStart] qdf.Parameters("[forms]![frmReportingMain]![txtAllocEnd]") = [forms]![frmReportingMain]![txtAllocEnd] Else qdf.Parameters("[forms]![frmReportingMain]![txtAllocStart]") = CStr(dteAllocStart) qdf.Parameters("[forms]![frmReportingMain]![txtAllocEnd]") = CStr(dteAllocEnd) End If Set rst = qdf.OpenRecordset Do Until rst.EOF '...do stuff here. Loop Set rst = Nothing Set qdf = Nothing Set db = Nothing End Function
Если форма, на которую ссылается ссылка, открыта, код достаточно умен, чтобы использовать элементы управления, на которые ссылается форма. Если нет, он будет использовать даты, указанные в подпрограмме, в качестве параметров. Тут я понял, что параметры не понравились, когда я установил их в качестве типов дат (#xx/xx/xx#), даже если в поле были даты. Казалось, что это работает правильно только в том случае, если я задаю параметры в виде строк. Однако, похоже, это не было проблемой при извлечении значений прямо из элементов управления в формах.
Комментарии:
1. Спасибо @VBlades-это действительно очень помогло! Я дал правильный ответ Брэду, основываясь только на времени, но просмотр обоих ответов действительно помог прояснить ситуацию. Я ценю это.
2. Потрясающе, рад, что это помогло.
Ответ №3:
Я знаю, что прошло много времени с тех пор, как это было опубликовано, но я хотел бы добавить свою сумму в два пенса, так как я всегда ищу эту проблему:
Сохраненный запрос может быть разрешен:
Set db = CurrentDb Set qdf = db.QueryDefs(sQueryName) For Each prm In qdf.Parameters prm.Value = Eval(prm.Name) Next prm Set rst = qdf.OpenRecordset
Для SQL:
Set db = CurrentDb Set qdf = db.CreateQueryDef("", "SELECT * FROM MyTable " amp; _ "WHERE ID = " amp; Me.lstID amp; _ " AND dWeekCommencing = " amp; CDbl(Me.frm_SomeForm.Controls("txtWkCommencing")) amp; _ " AND DB_Status = 'Used'") For Each prm In qdf.Parameters prm.Value = Eval(prm.Name) Next prm Set rst = qdf.OpenRecordset
Это предполагает, что все значения параметров доступны, т. е. Формы открыты, а элементы управления имеют значения.
Ответ №4:
«У меня есть два параметра в моем наборе записей, и я получал» Слишком мало параметров. Ожидаемая ошибка 2″ при использовании набора OpenRecordset в MS Access vba, и вот как я ее обошел, и ЭТО РАБОТАЕТ! смотрите нижеприведенную подпрограмму:
‘Частный субдисплайид_клик()
‘1. Я создал переменные для своих двух полей параметров xEventID и xExID, как показано ниже:
Dim db As Database Dim rst As Recordset Dim xEventID As Integer Dim xExId As Integer
‘2. Устанавливает переменные в поля параметров, как показано ниже:
Set db = CurrentDb xEventID = Forms!frmExhibitorEntry!txtEventID xExId = Forms!frmExhibitorEntry!subExhibitors!ExID
‘3. Установите для первого значение OpenRecordset и назначьте Набор переменных предложению WHERE. Обязательно укажите все цитаты, амперсанд и пробелы точно так, как они отображаются. В противном случае код сломается!точно так, как показано ниже:
Set rst = db.OpenRecordset("SELECT tblInfo_Exhibitor.EventID,tblInfo_Display.ExID, tblMstr_DisplayItems.Display " _ amp; "FROM tblInfo_Exhibitor INNER JOIN (tblMstr_DisplayItems INNER JOIN tblInfo_Display ON tblMstr_DisplayItems.DisplayID = tblInfo_Display.DisplayID) ON tblInfo_Exhibitor.ExID = tblInfo_Display.ExID " _ amp; "WHERE (((tblInfo_Exhibitor.EventID) =" amp; xEventID amp; " ) and ((tblInfo_Exhibitor.ExID) =" amp; xExId amp; " ));") rst.Close Set rst = Nothing db.Close
‘Конец подлодки