Упрощение условного кода VBA Microsoft Access

#vba #forms #ms-access #button #mailmerge

Вопрос:

Я новичок в MS Access и коде VBA, но я хорошо справляюсь со своими потребностями. Код, опубликованный ниже, — это единственный способ заставить мое событие Click работать. Для распечатки текущей записи из нескольких таблиц (слияние почты) требуется, чтобы некоторые поля были заполнены. Поэтому перед фактическим кодом распечатки я вставил следующий код. Есть ли лучший способ сделать это? Мне просто кажется неправильным то, как я это сделал.

 If IsNull(Screen.ActiveForm![Nome]) Then
MsgBox "Preencher o Nome do Cliente."
Screen.ActiveForm![Nome].SetFocus
Else

  If IsNull(Screen.ActiveForm![Gênero]) Then
  MsgBox "Preencher o Gênero do Cliente."
  Screen.ActiveForm![Gênero].SetFocus
  Else

    If IsNull(Screen.ActiveForm![Estado Civíl]) Then
    MsgBox "Preencher o Estado Civíl do Cliente."
    Screen.ActiveForm![cboecivil].SetFocus
    Else

        If IsNull(Screen.ActiveForm![Profissão]) Then
        MsgBox "Preencher a Profissão do Cliente."
        Screen.ActiveForm![Profissão].SetFocus
        Else

            If IsNull(Screen.ActiveForm![CEP]) Then
            MsgBox "Preencher o CEP do Cliente."
            Screen.ActiveForm![CEP].SetFocus
            Else

                If IsNull(Screen.ActiveForm![Endereço]) Then
                MsgBox "Preencher o nome da Rua do Cliente."
                Screen.ActiveForm![Endereço].SetFocus
                Else

                    If IsNull(Screen.ActiveForm![Número]) Then
                    MsgBox "Preencher o Número da Rua do Cliente."
                    Screen.ActiveForm![Número].SetFocus
                    Else

                        If IsNull(Screen.ActiveForm![Cidade]) Then
                        MsgBox "Preencher a Cidade do Cliente."
                        Screen.ActiveForm![Cidade].SetFocus
                        Else

                            If IsNull(Screen.ActiveForm![UF]) Then
                            MsgBox "Preencher o Estado do Cliente."
                            Screen.ActiveForm![UF].SetFocus
                            Else
                        
                                If IsNull(Screen.ActiveForm![Bairro]) Then
                                MsgBox "Preencher o Bairro do Cliente."
                                Screen.ActiveForm![Bairro].SetFocus
                                Else
                                
                                    If IsNull(Screen.ActiveForm![Complemento]) Then
                                    MsgBox "Preencher o Complemento do Endereço do Cliente."
                                    Screen.ActiveForm![Complemento].SetFocus
                                    Else
                                    
                                        If IsNull(Forms("Painel de Controle").sftblCPF.Form.CPF) Then
                                        MsgBox "Preencher o CPF do Cliente."
                                        Forms("Painel de Controle").sftblCPF.Form.CPF.SetFocus
                                        Else
                                        
                                            If IsNull(Forms("Painel de Controle").sftblRG.Form.Número) Then
                                            MsgBox "Preencher o Número do RG do Cliente."
                                            Forms("Painel de Controle").sftblRG.Form.Número.SetFocus
                                            Else
                                        
                                                If IsNull(Forms("Painel de Controle").sftblRG.Form.Série) Then
                                                MsgBox "Preencher a Série do RG do Cliente."
                                                Forms("Painel de Controle").sftblRG.Form.Série.SetFocus
                                                Else
                                        
                                                    If IsNull(Forms("Painel de Controle").sftblRG.Form.[Orgão Emissor]) Then
                                                    MsgBox "Preencher o Orgão Emissor do RG do Cliente."
                                                    Forms("Painel de Controle").sftblRG.Form.[Orgão Emissor].SetFocus
                                                    Else
                                        
                                                        If Forms("Painel de Controle").sftblCPF.Form.[Principal?] = False Then
                                                        MsgBox "Marcar o CPF Principal do Cliente."
                                                        Forms("Painel de Controle").sftblCPF.Form.[Principal?].SetFocus
                                                        Else
                                                        
                                                            If Forms("Painel de Controle").sftblRG.Form.[Principal?] = False Then
                                                            MsgBox "Marcar o RG Principal do Cliente."
                                                            Forms("Painel de Controle").sftblRG.Form.[Principal?].SetFocus
                                                            Else
 
'MailMerge code inserted Here.

End If
    End If
        End If
            End If
                End If
                    End If
                        End If
                            End If
                                End If
                                    End If
                                        End If
                                            End If
                                                End If
                                                    End If
                                                        End If
                                                            End If
                                                                End If
 

Комментарии:

1. Взгляните на функции И и или VBA.

2. Кроме того, подумайте о «Раннем выходе». Это означает, что когда одно из ваших условий истинно, вы можете просто вернуться из метода или функции вместо использования всех этих предложений ELSE.

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

Ответ №1:

Поместите все имена полей в массив

 Dim fieldNames As Variant

Private Sub Form_Load()
    fieldNames = Array("Nome", "Gênero", "Estado Civíl", "Profissão", ...)
End Sub
 

затем используйте цикл для выполнения проверок

 Dim fieldName As String
Dim i As Long

For i = LBound(fieldNames) To UBound(fieldNames)
    fieldName = fieldNames(i)
    If IsNull(Screen.ActiveForm(fieldName).Value) Then
        MsgBox "Preencher o " amp; fieldName amp; " do Cliente."
        Screen.ActiveForm(fieldName).SetFocus
        Exit Sub
    End If
Next i
 

Если вам нужны индивидуально составленные сообщения, вы можете использовать второй массив с сообщениями:

 Dim fieldNames As Variant
Dim messages As Variant

Private Sub Form_Load()
    fieldNames = Array("Nome", "Gênero", "Estado Civíl", "Profissão", ...)
    messages = Array("Preencher o Nome do Cliente.", "Preencher o Gênero ...", ...)
End Sub
 

затем снова используйте цикл для выполнения проверок

 Dim fieldName As String
Dim i As Long

For i = LBound(fieldNames) To UBound(fieldNames)
    fieldName = fieldNames(i)
    If IsNull(Screen.ActiveForm(fieldName).Value) Then
        MsgBox messages(i)
        Screen.ActiveForm(fieldName).SetFocus
        Exit Sub
    End If
Next i
 

Кстати, вы можете использовать ElseIf вместо ан Else , за которым следует ан If . Это приведет к цепочке условий, а не к их вложению

 If IsNull(Screen.ActiveForm![Nome]) Then
    MsgBox "Preencher o Nome do Cliente."
    Screen.ActiveForm![Nome].SetFocus
ElseIf IsNull(Screen.ActiveForm![Gênero]) Then
    MsgBox "Preencher o Gênero do Cliente."
    Screen.ActiveForm![Gênero].SetFocus
ElseIf IsNull(Screen.ActiveForm![Estado Civíl]) Then
    MsgBox "Preencher o Estado Civíl do Cliente."
    Screen.ActiveForm![cboecivil].SetFocus
ElseIf IsNull(Screen.ActiveForm![Profissão]) Then
    MsgBox "Preencher a Profissão do Cliente."
    Screen.ActiveForm![Profissão].SetFocus
...
End If
 

Смотри: Если…Тогда…Оператор Else (Visual Basic)

Ответ №2:

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

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

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

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

Ответ №3:

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

Поля по сути не являются необходимыми для базы данных, но они обязательны для некоторых событий кнопок, которые я создал для экспорта данных в документ MailMerge. Что, кстати, было действительно трудно сделать, так как у меня есть данные из нескольких таблиц (в виде подформ) в этой форме, и мне нужно было объединить только текущую запись. Чтобы это сработало, я создал запрос параметров, индексированный по текущему идентификатору клиента формы, а не код VBA, чтобы вставить эти данные в предварительно созданную таблицу с одной записью, из которой мои почтовые документы извлекают информацию. Я также использовал код для создания имени папки клиента, если она еще не создана. Я не знаю, безопасна ли эта процедура для базы данных, но я действительно не мог найти другого способа сделать это. Я опубликую полный код ниже, чтобы другие люди могли проверить и использовать его.

Хакслэш, я много боролся с этой формой, потому что каждый раз, когда я пытался использовать запрос в качестве источника, я не мог его отредактировать. При этом я использовал таблицу, в которой содержалась наиболее необходимая информация, и множество подформ (по двум причинам). Во-первых, некоторые поля, которые мне нужны в форме, имеют отношение «один ко многим» (например, комментарии клиентов, номера телефонов клиентов,…), во-вторых, поскольку я не знал, что могу редактировать источник запроса, мне пришлось использовать подформы в качестве текстового поля для размещения соответствующей информации в форме. Я обязательно проверю статью, которую вы опубликовали, и попробую заполнить эту форму с запросом. Еще раз большое вам спасибо!

 Private Sub cmdProcuração_Click()

If IsNull(Screen.ActiveForm![Nome]) Then
MsgBox "Preencher o Nome do Cliente."
Screen.ActiveForm![Nome].SetFocus
 ElseIf IsNull(Screen.ActiveForm![Gênero]) Then
 MsgBox "Preencher o Gênero do Cliente."
 Screen.ActiveForm![Gênero].SetFocus
    ElseIf IsNull(Screen.ActiveForm![Estado Civíl]) Then
    MsgBox "Preencher o Estado Civíl do Cliente."
    Screen.ActiveForm![cboecivil].SetFocus
        ElseIf IsNull(Screen.ActiveForm![Profissão]) Then
        MsgBox "Preencher a Profissão do Cliente."
        Screen.ActiveForm![Profissão].SetFocus
            ElseIf IsNull(Screen.ActiveForm![CEP]) Then
            MsgBox "Preencher o CEP do Cliente."
            Screen.ActiveForm![CEP].SetFocus
                ElseIf IsNull(Screen.ActiveForm![Endereço]) Then
                MsgBox "Preencher o nome da Rua do Cliente."
                Screen.ActiveForm![Endereço].SetFocus
                    ElseIf IsNull(Screen.ActiveForm![Número]) Then
                    MsgBox "Preencher o Número da Rua do Cliente."
                    Screen.ActiveForm![Número].SetFocus
                        ElseIf IsNull(Screen.ActiveForm![Cidade]) Then
                        MsgBox "Preencher a Cidade do Cliente."
                        Screen.ActiveForm![Cidade].SetFocus
                            ElseIf IsNull(Screen.ActiveForm![UF]) Then
                            MsgBox "Preencher o Estado do Cliente."
                            Screen.ActiveForm![UF].SetFocus
                                ElseIf IsNull(Screen.ActiveForm![Bairro]) Then
                                MsgBox "Preencher o Bairro do Cliente."
                                Screen.ActiveForm![Bairro].SetFocus
                                    ElseIf IsNull(Screen.ActiveForm![Complemento]) Then
                                    MsgBox "Preencher o Complemento do Endereço do Cliente."
                                    Screen.ActiveForm![Complemento].SetFocus
                                        ElseIf IsNull(Forms("Painel de Controle").sftblCPF.Form.CPF) Then
                                        MsgBox "Preencher o CPF do Cliente."
                                        Forms("Painel de Controle").sftblCPF.Form.CPF.SetFocus
                                            ElseIf IsNull(Forms("Painel de Controle").sftblRG.Form.Número) Then
                                            MsgBox "Preencher o Número do RG do Cliente."
                                            Forms("Painel de Controle").sftblRG.Form.Número.SetFocus
                                                ElseIf IsNull(Forms("Painel de Controle").sftblRG.Form.Série) Then
                                                MsgBox "Preencher a Série do RG do Cliente."
                                                Forms("Painel de Controle").sftblRG.Form.Série.SetFocus
                                                    ElseIf IsNull(Forms("Painel de Controle").sftblRG.Form.[Orgão Emissor]) Then
                                                    MsgBox "Preencher o Orgão Emissor do RG do Cliente."
                                                    Forms("Painel de Controle").sftblRG.Form.[Orgão Emissor].SetFocus
                                                        ElseIf Forms("Painel de Controle").sftblCPF.Form.[Principal?] = False Then
                                                        MsgBox "Marcar o CPF Principal do Cliente."
                                                        Forms("Painel de Controle").sftblCPF.Form.[Principal?].SetFocus
                                                            ElseIf Forms("Painel de Controle").sftblRG.Form.[Principal?] = False Then
                                                            MsgBox "Marcar o RG Principal do Cliente."
                                                            Forms("Painel de Controle").sftblRG.Form.[Principal?].SetFocus
                                                            Else

On Error GoTo ErrorHandler
'A seguir comandos para modificar a tabela existente com os dados atuais do formulário (Organizados em uma Consulta)
DoCmd.SetWarnings False
DoCmd.RunSQL "SELECT * INTO [tblExportarDocumentos] FROM [Exportar Contatos]" '(FROM QUERY)
DoCmd.SetWarnings True

Dim strSql As String

'Instrução SQL direto da tabela criada
strSql = "SELECT * FROM [tblExportarDocumentos]"

Dim strDocumentName As String  'Nome do Documento Template com a subpasta
strDocumentName = "DocumentosProcuração RCT.docx"

Dim strNewName As String  'Nome usado para Salvar o Documento
strNewName = "Procuração - " amp; Nome.Value

Call OpenMergedDoc(strDocumentName, strSql, strNewName)
Exit Sub
ErrorHandler:
MsgBox "Error #" amp; Err.Number amp; " occurred. " amp; Err.Description, 
vbOKOnly, "Error"
Exit Sub
End If
    
End Sub

Private Sub OpenMergedDoc(strDocName As String, strSql As String, s 
trMergedDocName As String)
On Error GoTo WordError

Const strDir As String = "C:UsersJcnraDocumentsBanco de Dados RCT" 
'Localização da pasta com o Banco de Dados


  Dim objWord As New Word.Application
  Dim objDoc As Word.Document
  objWord.Application.Visible = True
  Set objDoc = objWord.Documents.Open(strDir amp; strDocName)
  objWord.Application.Visible = True

'A seguir, a função do Mail Merge. Em Name: Colocar o endereço exato do arquivo do Banco de Dados
'Em SQLStatement: Colocar a mesma função sql acima
objDoc.MailMerge.OpenDataSource _
    Name:="C:UsersJcnraDocumentsBanco de Dados RCTBackup Banco de 
Dados RCT.accdb", _
    LinkToSource:=True, AddToRecentFiles:=False, _
    Connection:="", _
    SQLStatement:="SELECT * FROM [tblExportarDocumentos]"

'A seguir, condição para criar pastas no diretório, caso já não existam
If Dir(strDir amp; "Clientes" amp; Nome.Value, vbDirectory) = "" Then
    MkDir (strDir amp; "Clientes" amp; Nome.Value)
    Else
    End If

objDoc.MailMerge.Destination = wdSendToNewDocument
objDoc.MailMerge.Execute

'Comando para salvar o Documento criado
objWord.Application.Documents(1).SaveAs (strDir amp; "Clientes" amp; 
Nome.Value amp; "" amp; strMergedDocName amp; ".docx")

objWord.Application.Documents(2).Close wdDoNotSaveChanges
objWord.Visible = True
objWord.Activate
objWord.WindowState = wdWindowStateMaximize

'Liberar as variáveis
Set objWord = Nothing
Set objDoc = Nothing
   
Exit Sub
WordError:
    MsgBox "Err #" amp; Err.Number amp; "  occurred." amp; Err.Description, 
vbOKOnly, "Word Error"
    objWord.Quit

End Sub
 

Комментарии:

1. Чтобы получить отдельное сообщение об ошибке для каждого поля, вы должны создать второй массив с текстами сообщений.

2. Я обновил свой ответ, включив решение цикла с отдельными сообщениями.

3. Теперь в этом есть большой смысл! Очень хороший и полезный инструмент. Спасибо!