#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
Ответ №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. Теперь в этом есть большой смысл! Очень хороший и полезный инструмент. Спасибо!