Access 2007 VBA & SQL - обновление подчиненной формы, указывающей на динамически создаваемый запрос - PullRequest
1 голос
/ 26 мая 2010

Аннотация: Я использую VB для воссоздания запроса каждый раз, когда пользователь выбирает один из 3 вариантов из выпадающего меню, в которое добавляется предложение WHERE, если они выбирают что-либо из комбинированных окон. Затем я пытаюсь получить информацию, отображаемую в форме, чтобы обновить ее, фильтруя тем самым то, что отображается в таблице, на основе пользовательского ввода.

1) Динамически создаваемый запрос с использованием VB.

Private Sub BuildQuery()
' This sub routine will redefine the subQryAllJobsQuery based on input from
' the user on the Management tab.

Dim strQryName As String
Dim strSql As String            ' Main SQL SELECT statement
Dim strWhere As String          ' Optional WHERE clause
Dim qryDef As DAO.QueryDef
Dim dbs As DAO.Database

strQryName = "qryAllOpenJobs"
strSql = "SELECT * FROM tblOpenJobs"
Set dbs = CurrentDb

' In case the query already exists we should deleted it
' so that we can rebuild it.  The ObjectExists() function
' calls a public function in GlobalVariables module.
If ObjectExists("Query", strQryName) Then
    DoCmd.DeleteObject acQuery, strQryName
End If

' Check to see if anything was selected from the Shift
' Drop down menu.  If so, begin the where clause.
If Not IsNull(Me.cboShift.Value) Then
    strWhere = "WHERE tblOpenJobs.[Shift] = '" & Me.cboShift.Value & "'"
End If

' Check to see if anything was selected from the Department
' drop down menu.  If so, append or begin the where clause.
If Not IsNull(Me.cboDepartment.Value) Then
    If IsNull(strWhere) Then
        strWhere = strWhere & " AND tblOpenJobs.[Department] = '" & Me.cboDepartment.Value & "'"
    Else
        strWhere = "WHERE tblOpenJobs.[Department] = '" & Me.cboDepartment.Value & "'"
    End If
End If

' Check to see if anything was selected from the Date
' field.  If so, append or begin the Where clause.
If Not IsNull(Me.txtDate.Value) Then
    If Not IsNull(strWhere) Then
        strWhere = strWhere & " AND tblOpenJobs.[Date] = '" & Me.txtDate.Value & "'"
    Else
        strWhere = "WHERE tblOpenJobs.[Date] = '" & Me.txtDate.Value & "'"
    End If
End If

' Concatenate the Select and the Where clause together
' unless all three parameters are null, in which case return
' just the plain select statement.
If IsNull(Me.cboShift.Value) And IsNull(Me.cboDepartment.Value) And IsNull(Me.txtDate.Value) Then
    Set qryDef = dbs.CreateQueryDef(strQryName, strSql)
Else
    strSql = strSql & " " & strWhere
    Set qryDef = dbs.CreateQueryDef(strQryName, strSql)
End If

End Sub

2) Основная форма, в которой пользователь выбирает элементы из полей со списком.

изображение основной формы и подформы http://i48.tinypic.com/25pjw2a.png

3) Подформа указывает на запрос, созданный на шаге 1.

Цепочка событий: 1) Пользователь выбирает элемент из выпадающего списка на главной форме. 2) Старый запрос удален, новый запрос сгенерирован (то же имя). 3) Подформа, на которую указывает запрос, не обновляется, но если вы откроете запрос самостоятельно, отобразятся правильные результаты.

Имя запроса: qryAllOpenJobs имя подчиненной формы: subQryAllOpenJobs Кроме того, источник строки subQryAllOpenJobs = qryAllOpenJobs Название основной формы: frmManagement

Ответы [ 3 ]

2 голосов
/ 27 мая 2010

Пустая строка - это не то же самое, что Null. Когда вы объявляете строковую переменную, такую ​​как эта:

Dim strWhere As String

strWhere инициализируется как пустая строка (или «строка нулевой длины»). Это значение иногда называют пустой строкой, и существует даже константа VBA vbNullString , которая представляет пустую строку. Однако независимо от того, какое имя вы используете, переменная пустой строки не равна Null. Кроме того, строковая переменная VBA может никогда быть нулевой. Например, этот код вызовет ошибку 94 «Недопустимое использование Null»:

Dim strWhere As String
strWhere = Null

Причина, по которой я подчеркиваю этот момент, заключается в том, что ваш код проверяет, является ли strWhere нулевым. Это логический недостаток, потому что strWhere никогда не будет нулевым. Например, я не верю, что это условие когда-либо может быть истинным:

If IsNull(strWhere) Then

Если вы хотите, чтобы тест определял, когда strWhere не было присвоено значение (это все еще пустая строка), используйте функцию Len:

If Len(strWhere) = 0 Then

Вот другой подход для BuildQuery. Предполагается, что тип данных для вашего поля [Date] - String (как предполагает ваш оригинальный код). Если [Дата] фактически является типом данных Дата / Время, этот код не будет работать. Также обратите внимание, что Дата является зарезервированным словом (см. Имена проблем и зарезервированные слова в Access ). Я заключил имя поля в квадратные скобки, чтобы избежать двусмысленности. Если бы это была моя собственная база данных, я бы изменил имя поля.

Private Sub BuildQuery()
'* Update subform RecordSource based on input from *'
'* the user on the Management tab. *'

Dim strSql As String        ' Main SQL SELECT statement '
Dim strWhere As String      ' Optional WHERE clause '
Dim i As Integer
Dim strControl As String
Dim strField As String

strSql = "SELECT * FROM tblOpenJobs AS oj"

strWhere = vbNullString
For i = 1 To 3
    Select Case i
    Case 1
        strControl = "cboShift"
        strField = "Shift"
    Case 2
        strControl = "cboDepartment"
        strField = "Department"
    Case 3
        strControl = "txtDate"
        strField = "[Date]"
    End Select
    If Not IsNull(Me.Controls(strControl).Value) Then
        strWhere = strWhere & _
            IIf(Len(strWhere) > 0, " AND ", "") & _
            "oj." & strField & " = '" & _
            Me.Controls(strControl).Value & "'"
    End If
Next i

If Len(strWhere) > 0 Then
    strSql = strSql & " WHERE " & strWhere
End If
'* use the name of the subform CONTROL for sfrmJobs *'
'* (may not be the name of the subform) *'
Me.sfrmJobs.Form.RecordSource = strSql

End Sub
2 голосов
/ 27 мая 2010

Я думаю, у вас есть логика в выпадающем чеке Департамента задом наперед.

У вас есть проверка, является ли strWhere нулевым, тогда, если это так, вы объединяете strWhere со значением cboDepartment.

Вы должны делать то, что вы для даты.

' Check to see if anything was selected from the Department
' drop down menu.  If so, append or begin the where clause.
If Not IsNull(Me.cboDepartment.Value) Then
    If Not IsNull(strWhere) Then
        strWhere = strWhere & " AND tblOpenJobs.[Department] = '" & Me.cboDepartment.Value & "'"
    Else
        strWhere = "WHERE tblOpenJobs.[Department] = '" & Me.cboDepartment.Value & "'"
    End If
End If

Вы также можете сделать:

If Nz(strWhere,"") = "" then

Вместо того, чтобы просто делать IsNull, чтобы вы ловили строку нулевой длины в дополнение к нулевой переменной.

Что касается настройки источника записей, используйте что-то вроде

Me.sfrmJobs.Form.RecordSource = strSQL

где sfrmJobs - имя вашей подчиненной формы.

1 голос
/ 29 мая 2010

Мое решение ниже в трех частях. (1) Build Query, (2) Основная форма, (3) Subform. `Private Sub OpenJobsQuery () Эта подпрограмма создаст запрос на первой странице для пользователя в зависимости от того, кто они и что они выбирают из списка выше таблица для фильтрации путем переопределения источника строк подчиненной формы 'subQryOpenJobs

Dim strSql As String            ' Main SQL SELECT statement
Dim strWhere As String          ' Where clause containing user specified parameters.

strSql = "SELECT * FROM tblOpenJobs"
strWhere = ""

' Check to see if anything was selected from the Shift
' combo box.  If so, begin the Where clause.
If Not IsNull(Me.cboOpenJobShift.Value) Then
    strWhere = "WHERE tblOpenJobs.[Shift] = '" & Me.cboOpenJobShift.Value & "'"
End If

' Check to see if anything was selected from the Department
' combo box.  If so, append or begin the where clause.
If Not IsNull(Me.cboOpenJobDepartment.Value) Then
    If strWhere = "" Then
        strWhere = "WHERE tblOpenJobs.[Department] = '" & Me.cboOpenJobDepartment.Value & "'"
    Else
        strWhere = strWhere & " AND tblOpenJobs.[Department] = '" & Me.cboOpenJobDepartment.Value & "'"
    End If
End If

' Check to see if anything was selected from the Date
' field.  If so, append or begin the Where clause.
If Not IsNull(Me.cboOpenJobDate.Value) Then
    If strWhere = "" Then
        strWhere = "WHERE tblOpenJobs.[JobDate] = #" & Me.cboOpenJobDate.Value & "#"
    Else
        strWhere = strWhere & " AND tblOpenJobs.[JobDate] = #" & Me.cboOpenJobDate.Value & "#"
    End If
Else
    ' If nothing was entered in the date field, make sure the user
    ' only sees future jobs.
    If strWhere = "" Then
        strWhere = "WHERE tblOpenJobs.[JobDate] > #" & FormatDateTime(Date, vbShortDate) & "#"
    Else
        strWhere = strWhere & " AND tblOpenJobs.[JobDate] > #" & FormatDateTime(Date, vbShortDate) & "#"
    End If
End If

' Always include as part of the where clause, a section that
' will narrow the results based on who the user is
If strWhere = "" Then
    strWhere = "WHERE tblOpenJobs.[OpenJobID] Not In " & _
               "(SELECT tblSignUps.[OpenJobID] FROM tblSignUps WHERE tblSignUps.[EUID] = '" & strEUID & "');"

Else
    strWhere = strWhere & " AND tblOpenJobs.[OpenJobID] Not In " & _
               "(SELECT tblSignUps.[OpenJobID] FROM tblSignUps WHERE tblSignUps.[EUID] = '" & strEUID & "');"
End If

' Concatenate the Select and the Where clause together
strSql = strSql & " " & strWhere

' Set the recordsource of the subform to the SQL query generated
' and refresh the form.
Me.subQryOpenJobs.Form.RecordSource = strSql

' In addition, synchronize the JobID's in the Edit Job box to match those
' filtered by this Build Query.
Me.cboSelectJOBID.RowSource = "SELECT tblOpenJobs.[OpenJobID] FROM tblOpenJobs" & " " & strWhere

Me.Refresh

End Sub`

(2) Основная форма. http://j.imagehost.org/view/0385/Form. и (3) подформа заполняется, как показано в подпункте BuildQuery (), для построения запроса на основе того, что пользователь выбирает из выпадающих фильтров и полей ввода справа от формы. Данные в самой таблице недоступны для пользователя, это просто для справки.

...