Как добавить фильтр в форму на основе столбцов объединенной таблицы, которые не отображаются в предложении Select? - PullRequest
2 голосов
/ 17 августа 2011

У меня есть форма, отображающая компании, и подчиненная форма, отображающая контакты. В каждой компании несколько контактов.

У меня есть фильтр, который работает вне поля со списком, который выбирает компании только в тех случаях, когда у них есть контакты с выбранной ответственностью;

Sub SetFilter()    
    Dim ASQL As String        
    If IsNull(Me.cboshowcat) Then
    ' If the combo and all check boxes are Null, use the whole table as the 
    ' RecordSource.
        Me.RecordSource = "SELECT company.* FROM company"        
    Else        
        ASQL = "SELECT DISTINCTROW company.* " & _
                "FROM company INNER JOIN Contacts " & _
                    "ON company.company_id = Contacts.company_id " & _
                "WHERE Contacts.responsibility= '" & cboshowcat & "' " & _
                "ORDER BY Company.company_id"
        Me.RecordSource = ASQL        
    End If        
End Sub

У меня также есть 3 флажка, которые дополнительно уточняют записи, которые можно использовать только после того, как была выбрана ответственность за работу. Фильтр и флажки запускаются после нажатия кнопки;

Private Sub Command201_Click()

If Nz(Me.cboshowcat) = "" _
        And Me.Check194 = True _
    Or Nz(Me.cboshowcat) = "" _
        And Me.Check199 = True _
    Or Nz(Me.cboshowcat) = "" _
        And Me.Check205 = True _
    Then
        MsgBox "Please Select a Job Responsibility"
        Cancel = True
    Else    
        SetFilter
        If Me.Check194 = True _
            And Me.Check199 = True _
            And Me.Check205 = True _
            Then
            Me.Filter = "[contacts].[edit] <=Date()-90 " & _
                "and [contact].[opt out]='No' " & _
                "and [company].[exclude site] is null"
            Me.FilterOn = True
        Else
            If Me.Check194 = True _
                And Me.Check199 = True _
                And Me.Check205 = False _
                Then
                Me.Filter = "[contacts].[edit] <=Date()-90 " & _
                    "and [contact].[opt out]='No'"
                Me.FilterOn = True
            Else
'................(repeated for each combination)
                                    Me.Filter = ""
                                    Me.FilterOn = False
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        End If
    End If
    Me.Repaint
End Sub

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

Мне нужно отфильтровать компании на основе информации в контактной таблице без дублирования информации о компании.

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

1 Ответ

1 голос
/ 17 августа 2011

Сначала некоторые вещи стиля:

1) Вероятно, у вас меньше вложенности, если вы используете ElseIf вместо

Else
    If '...

2) Было бы неплохо переименовать флажки в нечто более значимое, чем Check194 (по крайней мере, для следующего разработчика, который коснется этого кода - даже если это 4 года спустя). То есть, конечно, если предположить, что это не надуманный пример, чтобы немного анонимизировать код.

3) Точно так же наличие пробела в именах столбцов и таблиц может быть проблемой в заднице. Аналогично «Редактировать» выглядит как зарезервированное слово (оно может не быть) и может привести к остановке сердца.

4) Я не уверен в логике вашего первого IF заявления. Вы можете не иметь порядок работы, может не соответствовать вашим ожиданиям. Это в основном эквивалент

If Nz(Me.cboshowcat) = "" _
    And (Me.Check194 = True _
        Or Me.Check199 = True _
        Or Me.Check205 = True) _
    then

Если это то, что вы хотели, тогда все в порядке.

5) Если вы построите строку фильтра на лету, вам не придется проходить все восемь комбинаций (и, возможно, пропустить одну). Представьте, если у вас есть 4, 5 или 10 флажков. Как правило, я бы сделал что-то вроде этого

dim strFilter as string

strFilter = "(1 = 1) " ' so we don't have to decide whether to put `and` or not.
If Nz(Me.cboshowcat) = "" then
    if Me.Check194 = then
        strFilter = strFilter & "and [contacts].[edit] <=Date()-90 "
    end if
    if Me.Check199 = then
        strFilter = strFilter & "and [contacts].[opt out]='No' "
    end if
    if Me.Check199 = then
        strFilter = strFilter & "and [company].[exclude site] is null "
    end if
    me.filter = strFilter
    me.filteron = true
else
    me.filter = ""
    me.filteron = false
end if

Второе решение вашей проблемы:

Несколько строк для каждой компании обусловлены объединением, и теперь запрос вынужден показывать строку для каждого контакта с различной комбинацией значений для «Изменить» или «Отказаться».

Поскольку вы уже обновляете источник записи на лету, я просто вставил фильтр в предложение where источника записи и покончим с этим. Это эффективно, что фильтр делает в любом случае (только на результат запроса, поэтому он не может видеть в таблице контактов).

Опять же, создайте предложение where на лету, вместо того, чтобы делать 8 различных комбинаций.

...