Como saber se o cliente já foi cadastrado ?
Nota importante: para ter acesso aos vídeos e arquivos exemplos deste site, adquira um dos planos apresentados abaixo. Você pode comprar em até 5x no Cartão de Crédito.
Veja como comprar e saiba mais sobre o material oferecido, clicando aqui.
Criar uma rotina para identificar se o cliente já se encontra cadastrado é relativamente simples! Usamos para este objetivo a função DCount() que informa a quantidade de registros existentes na tabela, de acordo com o tipo de filtragem aplicada. Queremos aqui, que a função DCount() informe apenas a quantidade de registros do cliente, supostamente cadastrado.
A função DCount() tem a seguinte estrutura:
DCount("NomeDoCampo","NomeDatabela", Filtro)
Vamos supor que eu tenha uma tabela de nome tblClientes e que irei solicitar a contagem de registros, utilizando o campo número exclusivo do cliente (idCliente).
TotalDeRegistros = DCount("idCliente","tblClientes")
Como não utilizei o filtro, a função irá contar todos os registros existentes na tabela.
Agora, vamos supor que eu queira contar apenas os registros do cliente cadastrado "Avelino Sampaio"
TotalDeRegistros = DCount("idCliente","tblClientes","cli_nome ='Avelino Sampaio'")
Se existir o nome Avelino Sampaio no campo cli_nome da tabela, a função irá retornar a contagem de 1 registro e se o nome pesquisado não existir no cadastro, a função irá retornar com o valor 0(zero).
Fica fácil, então, usarmos esta função para saber se o cliente foi ou não, previamente cadastrado!
Usamos o evento Antes de Atualizar, do campo que recebe o nome do cliente. Observe que o evento tem o argumento Cancel, que usamos para manter o foco no campo.
Exemplo do usos da função DCount() no evento:
Private Sub cli_Nome_BeforeUpdate(Cancel As Integer) If DCount("idCliente","tblClientes","cli_Nome =""" & Me!cli_Nome & """") > 0 Then 'A função DCount() contou um ou mais registros existentes MsgBox "O Cliente " & Me!cli_Nome & " já existe..." Me.Undo 'Limpa o campo Cancel = True 'mantém o foco no campo. End If End Sub
Só que esta função nos traz uma pegadinha bem sutil, da qual já fui vítima! Meu cliente, um dia me ligou, bem irritado, comunicando que havia encontrado no cadastro, o sobrenome de uma empresa, iniciando com letra minúscula e quando foi corrigir a letra para maiúscula, o programa não permitiu, acusando que o cliente já se encontrava cadastrado. Huumm!!! De fato, neste caso, não houve mudança alguma no nome para a função acima, que detectou a presença do cliente, no cadastro! A saída, para este caso em particular, foi a de armazenar o nome do cliente atual, na memória, usando uma variável, e então comparar se o nome alterado difere do nome original, armazenado na variável.
O primeiro passo é armazenar o nome do cliente, no instante em que é acessado o registro. Isso é feito pelo evento No atual do formulário:
Option Compare Database 'Variável criada para armazenar o nome do cliente original Dim NomeOriginal As String Private Sub Form_Current() 'Capturando o nome do cliente ao entrar no registro. NomeOriginal = Nz(Me!cli_Nome, "") End Sub
Agora, acrescentamos no evento Antes de Atualizar, do campo cliente, o código que analisa se de fato o nome sofreu alteração. Caso não tenha sofrido alteração, não permitimos que a função DCount() seja executada.
Observe abaixo, o acréscimo do código no evento:
Private Sub cli_Nome_BeforeUpdate(Cancel As Integer) '--------------------------------------------------------------------- 'Se não houver alteração do nome, sair do procedimento, impedindo assim 'que a função DCount() seja disparada. If NomeOriginal = Me!cli_Nome Then Exit Sub '--------------------------------------------------------------------- If DCount("idCliente","tblClientes","cli_Nome =""" & Me!cli_Nome & """") > 0 Then 'A função DCount() contou um ou mais registros existentes MsgBox "O Cliente " & Me!cli_Nome & " já existe..." Me.Undo Cancel = True End If End Sub
Uma outra questão, resolvida na prática: certa ocasião fui chamado por um dos meus clientes para investigar o que estava acontecendo de errado em relação ao Cadastro de Clientes. Alegou que alguns dos clientes cadastrados possuíam mais de um registro. Após algumas observações, percebi que as funcionárias da empresa ao cadastrarem novos clientes, cometiam erros de digitação, o que contribuía para os vários registros referentes ao mesmo cliente. Isto era recorrente na empresa, envolvendo mais de um cliente cadastrado, porque as sutis alterações do nome do cliente ao ser digitado, passavam despercebidas. Exemplo:
Celula Serviços Tecnologicos
Celula Servicos Tecnológicos
Celula Serviços Tecnológicos Ltda
Ora, considerei que isso não era um problema pertinente à programação, mas sim à falta de atenção das funcionárias, durante a digitação! Para resolver o problema, fiz uma reunião para orientar que antes de iniciar o cadastro era necessário investigar, através de uma combobox, se o cliente já havia sido registrado!
Em pouco tempo, o problema voltou a se repetir. Quem disse que as funcionárias, antes de prosseguir com o cadastro, investigavam se determinado cliente já havia sido registrado?! O meu cliente ficou muito irritado com a situação e sobrou bronca para todos, inclusive para mim, é claro!
Após o ocorrido, fiquei pensando de que forma poderia resolver a questão! Surgiu, então, uma idéia fantástica para o caso: criei uma tela para que na medida em que o novo cliente for registrado, a lista de cadastros existentes seja filtrada e exibida numa listbox.
Observe, na imagem abaixo, a tela usada para registrar o novo cliente:
Veja que ao começar a digitar o novo cliente (Ce), a lista dos clientes já cadastrados, na listbox, começa a se reduzir.
Peguei elas! (risos).
O fato é que tive sim, minha parcela de culpa no caso, por não ter avaliado corretamente o comportamento humano! Recomendo muito que você leia este artigo sobre usabilidade.
Se quiser aprender como se filtra uma listbox, a medida que se digita em campo texto, leia o artigo e assista a vídeo-aula sobre filtragens, clicando aqui.
O emprego, das técnicas aqui apresentadas, está à sua disposição no aplicativo Maestro, que forneço aqui no site. Clicando no botão novo, do formulário de Cadastro de Clientes, você terá acesso à tela apresentada acima, para realizar testes.
Arquivo exemplo
Para entrar na estrutura do Maestro (Maestro_v5.accdb), basta manter pressionada a tecla SHIFT , na inicialização.
Senha do usuário admin > admin
Senha do usuário Avelino > 1234
Senha do Maestro_v3_be.accdb (tabelas) > a1234
Bom estudo!
Os dez artigos mais visitados
MontaRibbons v.7.0 - Assistente completo para criar ribbons no Access
Vídeo - Controle personalizado de Acesso de Usuários
Vídeo - Aprenda sobre filtragens
Vídeo - Segurança máxima, usando o OPEN
Uma ajuda para quem está começando um negócio ou um projeto
Integrando o Access com Servidor MySQL - Introdução
Desabilitando a faixa(ribbon) superior do Access
Vídeo - Programação de relatórios - Parte 1
Como carregar o seu menu sem que ele vá para lista de suplementos
Adquira o kit UsandoAccess e aprenda em alta velocidade
40 comentário(s) Nilton Oliveira 30/12/2023 18:06:23 Avelino, preciso de uma ajuda. Quero mostrar o total de registros de uma tabela com a condição data de hoje e status ativo. Me.LabelTotal.Caption = DCount("[customers_id]", "[customers_table]", "[customers_entrada] = now() And [customers_status] = 'A'") Do jeito que fiz causa erro. Pode me ajudar, desde já agradeço. Camilo Sousa 01/12/2022 12:43:58 Bom dia! Avelino Sampaio, amigão muito obrigado por compartilha seus conhecimentos com nos, estou tentando adapta sua formula a um projeto meu, mais estou com um problema, esta dando o seguinte erro: Erro em tempo de execução '13': Tipos incompatíveis Segue abaixo meu código, onde tem os seguintes critérios, verifica se minha nota existe, verifica se minha nota e do estado do CE se for do estado CE ele abri mensagem "Nota estadual, não emitir GNRE, caso os criterios acima forem falso, ele abri o formulario com o calculo da minha GNRE. O erro esta acontecendo nesta parte verifica se minha nota e do estado do CE se for do estado CE ele abri mensagem "Nota estadual, não emitir GNRE Private Sub btm_atualiza_Click() Dim nota As String nota = "num_nota = " & Me.txt_num_nota & "" Dim ESTADO As String ESTADO = "ESTADO = " & Me.Texto19 & "" If IsNull(txt_num_nota) Then MsgBox "Digite o numero da nota.", vbOKOnly, "Atenção!" Me.txt_num_nota.SetFocus ElseIf DCount("num_nota", "NFSCB", nota) < 1 Then MsgBox "Nota inexistente, digite novamente.", vbOKOnly, "Atenção!" Me.txt_num_nota.SetFocus ElseIf DCount("NUM_NOTA", "NFSCB", nota And ESTADO) > 0 Then O ERRO OCORE NESTE LOCAL MsgBox "Nota estadual, não emitir GNRE." ElseIf DCount("num_nota", "NFSCB", nota) > 0 Then DoCmd.OpenForm "frm_calculo_gnre" Else MsgBox "Nota inexistente, digite novamente.", vbOKOnly, "Atenção!" Me.txt_num_nota.SetFocus End If End Sub Desde ja agradeço pela atenção e ajuda. Dora 11/11/2022 11:27:09 Bom dia ! To com um sistema em access, to querendo saber como faço para não deixa o usuario digita na venda o mesmo codigo do produto duas vezes. como posso fazer isso ? Raimundinho 07/11/2022 11:36:48 Obrigado Avelino já consegui veja meu código: rst.FindFirst "codbarra='" & Me.codbarra & "'" If Not rst.NoMatch Then Me.Undo Me.Bookmark = rst.Bookmark Else Me.Undo End If no caso o campo é codbarra Raimundinho 07/11/2022 10:58:38 Olá Avelino, estou com dificuldades. Meu caso é parecido com esse. porém eu não quero uma mensagem de registro existente e sim que o formulário focalize automaticamente o registro que já existe. Abraços. felizardo zua 22/09/2022 10:36:35 muito fix,mais eu quero saber como armazenar dados do mesmo cliente no formulario e dpois fazer o total Paulo Gomes da Rosa 12/07/2022 16:34:49 e ótimo era assim que eu queria Avelino Sampaio 03/07/2022 05:54:47 James, leve o seu caso lá para o nosso fórum, que tem um espaço melhor para debatermos o assunto. http://www.redeaccess.com.br Aguardo Avelino Sampaio 03/07/2022 05:52:33 Nelson, neste seu caso eu acrescentaria um botão de Opção para o usuário setar, caso necessite da duplicidade de nomes. Ao setar o botão de Opção, projete o código para ignorar a verificação. Sucesso! James Pontes 02/07/2022 21:09:17 Olá Avelino E se caso fosse num subformulário, como ficaria esse exemplo acima, considerando que campo esta no subform e quando digitar algo na txt tem que procurar no subform e não na tabela. Private Sub cli_Nome_BeforeUpdate(Cancel As Integer) If DCount("idCliente","tblClientes","cli_Nome =""" & Me!cli_Nome & """") > 0 Then 'A função DCount() contou um ou mais registros existentes MsgBox "O Cliente " & Me!cli_Nome & " já existe..." Me.Undo 'Limpa o campo Cancel = True 'mantém o foco no campo. End If End Sub Nelson Santos 01/07/2022 17:48:17 Mestre Guru Avelino. Entendi perfeitamente o raciocínio, agora vejamos um exemplo claro de não duplicidade e sim homônimo; Exemplo:(cliente já cadastrado) Nome: LUIZ ANTONIO GARCIA SANTOS DT_NASC: 20/01/1975 Mãe: MARIA FRANCISCA GARCIA (cliente a cadastrar) Nome: LUIZ ANTONIO GARCIA SANTOS DT_NASC: 25/08/2001 Mãe: TEREZINHA GARCIA SANTOS. Repare que o Campo Nome houve a duplicidade mas ao analisarmos os restantes dos campos veremos que a data de Nascimento e a Filiação são diferentes, Neste caso qual seria o procedimento para efetuar o cadastro do 2º cliente, não contrariando o argumento do campo nome onde não pode haver duplicidade? Grato pela atenção. Abilio 20/03/2022 09:45:21 Bom dia, gostando muito das suas dicas. Por gentileza, voce teria como me dizer qual codigo seria ideal para que num formulario que tenho, identifique ao digitar o CPF do Cliente, se o CPF já foi cadastrado ? Valmir Palhares de Matos Junior 03/03/2022 19:59:07 PQP!!! Tive que comentar!!! Muito bom!! Parabéns!!! Isso sim que é excelencia e gosto pelo que faz!!!! Avelino Sampaio 26/11/2021 05:54:34 Alessandro, Observe que no formulário de cadastrar o novo cliente, basta dar dois cliques sobre o cliente existente na listbox que o cadastro será aberto. Se estiver usando o evento "antes de atualizar" do campo para isso, acrescente a proprieadade FILTER. Exemplo: Private Sub cli_nome_BeforeUpdate(Cancel As Integer) Dim filtro As String If NomeOriginal = Me!cli_Nome Then Exit Sub filtro = "cli_Nome =""" & Me!cli_Nome & """" If DCount("idCliente", "tblClientes", filtro) > 0 Then MsgBox "O Cliente " & Me!cli_Nome & " já existe..." Me.Undo Cancel = True Me.Filter = filtro Me.FilterOn = True End If End Sub Sucesso! Alessandro 25/11/2021 23:33:37 Pessoal eu estava precisando de um codigo que procurasse se o registro existe e retornar a mensagem. Ótima dica, esse codigo funcionou certinho. Acontece que eu gostaria, que ao aparecer a mensagem avisando que o codigo já existe, abrisse o registro para que pudesse ser editado. Osmar 29/10/2021 15:21:08 Eu tenho uma dúvida e gostaria de como solucionar, caso alguém possa ajudar-me, pois meus conhecimentos em access são precários: Eu tenho uma tabela com o campos cd_Posto, Ano_Posto, num_caixa, status e gostaria de saber como posso fazer um VBA onde ao atualizar o registro ele verifique se já existe um registro onde cd_Posto = Ano_Posto = num_caixa e não permita o cadastramento. JGaspar 26/09/2021 18:02:20 Amigo, faça igual ao um blog para podermos assinar o post e tudo mais! Abraços JGaspar 26/09/2021 18:01:08 Usei parte do seu código e me ajudou. Valeu e obrigado!!! Pedro Trindade 19/09/2021 00:47:29 Olá, Avelino Como eu completo o código para que eu escolha entre desistir da duplicação ou continuar com a edição do registro duplicado? Eu quero que a caixa de msg me pergunte se desejo ou não continuar. No meu caso, a mensagem será só um alerta para eu não cadastrar um aluno duas vezes no mesmo curso. Obrigado luis otavio da silva 16/07/2021 13:20:57 gostaria de saber se a recado Formiga10x 13/07/2021 15:57:04 Grande mestre Avelino suas aulas são incríveis. Através das experiências por vc já vivida nos faz aprimorar mais e mais a nossa. Muito obrigado. Abraço. Gilvane 24/06/2021 17:34:12 Muito bom! Era justamente o que eu estava precisando. Alisson 20/05/2021 07:55:46 Avelino Agora funcionou, muito obrigado! Avelino Sampaio 20/05/2021 05:30:16 Alison, tente assim: If DCount("codControle", "tblControleContratos", "CodFundo=" & Me.cboFundo & " And CodCorretora = '" & Me.cboCorretora & "' And CodGestor='" & Me.cboGestor & "'") > 0 Then Sucesso! Alisson 20/05/2021 00:26:45 Caro Avelino, Podemos usar a função Dcount para mais de um criterio? Gostaria que o fosse comparado tres campos da tabela e tentei esse codigo, mas aparece o erro 13 Tipos incompativeis. Os campos sao selecionados em combos e o CodFundo é numero. 'verifica se o cadastro esta duplicado If DCount("codControle", "tblControleContratos", "CodFundo=" & Me.cboFundo & "" _ And "CodCorretora = '" & Me.cboCorretora & "'" And "CodGestor='" & Me.cboGestor & "'") > 0 Then 'A função DCount() contou um ou mais registros existentes MsgBox "Este Fundo já esta cadastrado nesta Corretora", vbExclamation, NomeApp End If O que esta errado? Avelino Sampaio 05/03/2021 06:39:09 Denilson, Sem dúvida é uma ótima opção usar o CNPJ ou o CPF mas existem muitos casos na prática em que esses dados só são obtidos em um segundo momento. Pre cadastros são muito comuns na prática. Obrigado pela sua contribuição pois assim temos mais uma opção para o programador decidir o que cabe melhor ao projeto dele. Denilson 04/03/2021 21:30:41 Para não acontecer esse tipo de cadastro duplicado basta incluir um campo CNPJ e deixar ele como chave primária, aposto que os operadores não conseguirão duplicar registros nunca mais...muito simples...abraços. Ricardo 15/02/2021 20:25:45 Fiz algumas alterações e já consigo carregar o formulário com os dados se o utilizador clicar em Sim (Editar) no entanto estou com outro problema. Neste formulário eu tenho um subformulário que recebe os dados de uma tabela que está relacionada com a tabela de onde provêm os dados que são carregados no formulário principal e quando introduzo um registo existente e o utilizador clica em sim este subformulário é carregado com os dados (não fiz qualquer código para isso) no entanto não consigo editar nem adicionar novos dados a esse subformulário aparece a seguinte mensagem "As alterações pedidas para a tabela não foram bem sucedidas pois iriam criar valores duplicados no índice ou no relacionamento, altere o índice ou remova o índice para que as entradas possam ser duplicadas" Eu entendo que tem algo a ver com a chave primária que relaciona as duas tabelas e pla qual eu faço a pesquisa, no entanto eu queria que ele entendesse que eu não quero duplicar o registo mas sim editar / adicionar informação. :) O meu código do evento antes de actualizar da caixa de texto está assim, Os meus conhecimentos são básicos, eu pesquiso vou lendo, tentando e adaptando o meu código, não sei se está feito da forma mais correcta. Private Sub instalação_BeforeUpdate(Cancel As Integer) Dim rst As Recordset Dim banco As Database Dim instal, StrSQL As String Dim response As VbMsgBoxResult 'Set rst = CurrentDb.OpenRecordset("Clientes", dbOpenTable) Set banco = CurrentDb Set rst = banco.OpenRecordset("Clientes") instal = Me.instalação With rst 'Informa o nome do índice na tabela. .Index = "PrimaryKey" 'Pesquisa o campo na tabela. .Seek "=", instal 'Se encontrar, então... If Not .NoMatch Then response = MsgBox("A instalação '" & (instal) & "' já existe!" + Chr$(13) & "Deseja editar o registo existente ou inserir um novo? " + Chr$(13) & "Para editar clique Sim" + Chr$(13) & "Para inserir novo clique Não", vbYesNo, "Instalação Existente") If response = vbYes Then StrSQL = "SELECT cNOme, cMorada, cContacto, Concelho" & _ " FROM clientes" & _ " WHERE instalação = '" & instalação.Text & "';" Set banco = CurrentDb Set rst = banco.OpenRecordset(StrSQL) Me.AllowEdits = True Me.CortesBTN2.Form.AllowEdits = True Me.CortesBTN2.Form.AllowAdditions = True rst.Edit Me.cNome = rst.Fields("cNome").Value Me.cMorada = rst.Fields("cMorada").Value Me.cContacto = rst.Fields("cContacto").Value Me.CConcelho = rst.Fields("Concelho").Value rst.Update Else instalação.Undo 'limpa a caixa de texto Cancel = True 'Cancela o evento. End If End If End With Set rst = Nothing 'Libera memória. End Sub Ricardo 15/02/2021 14:38:08 Olá Avelino, eu tenho uma situação idêntica mas o meu código está um pouco diferente, no evento antes de actualizar de uma caixa de texto do formulário eu tenho o seguinte, Eu consigo ver se existe o registo que o utilizador está a introduzir, se existir aparece uma mensagem onde o utilizador pode escolher editar esse mesmo registo ou inserir um novo (diferente claro). Eu não estou a conseguir é preencher o formulário com os dados correspondentes se o utilizador escolher editar. Private Sub instalação_BeforeUpdate(Cancel As Integer) 'Verifica antes de ir a frente se ja foi digitado um código de instalação 'Dim rst As Recordset, instal As String Dim response As VbMsgBoxResult Dim StrSQL As String 'Abre o recordset do tipo Table. Set rst = CurrentDb.OpenRecordset("Clientes", dbOpenTable) instal = Me.instalação With rst 'Informa o nome do índice na tabela. .Index = "PrimaryKey" 'Pesquisa o campo na tabela. .Seek "=", instal 'Se encontrar, então... If Not .NoMatch Then response = MsgBox("A instalação '" & (instal) & "' já existe!" + Chr$(13) & "Deseja editar o registo existente ou inserir um novo? " + Chr$(13) & "Para editar clique Sim" + Chr$(13) & "Para inserir novo clique Não", vbYesNo, "Instalação Existente") If response = vbYes Then StrSQL = "SELECT * FROM [clientes] WHERE [instalação] = " & instalação & "" DoCmd.RunSQL StrSQL Else instalação.Undo 'limpa a caixa de texto Cancel = True 'Cancela o evento. End If End If End With Set rst = Nothing 'Libera memória. End Sub Marcelo David 08/02/2021 20:01:11 Nossa Avelino, realmente cada vez mais você nos surpreende e mostra o quanto é profissional a programação Access/VBA.... Simplesmente fantástico!! MARCIO MELO - RJ 08/02/2021 18:19:58 Gostei muito desse artigo, e cada vez mais tenho o seu site como meu manual online. Aos poucos você vem abordando assuntos conhecidos mas de maneira diferente e com uma ótima didática. No meu caso as vezes descubro um procedimento e não tenho a certeza do funcionamento e aqui você nos mostra o passo a passo. Continue assim, é muito bom ler, entender e acompanhar o seu raciocinio lógico... Parabéns... Ahhh adorei a sua vídeo aula de setup e os arquivos pré definidos, uma mão na roda... Sou mais Brasil! Avelino Sampaio 08/02/2021 17:20:37 Gilberto, Eduardo e Welson muito obrigado pela participação de vcs. Sucesso! Avelino Sampaio 08/02/2021 17:19:09 Edson, já lhe enviei o arquivo exemplo modificado. Bom estudo! Welson Zeferino de Oliveira Junior 08/02/2021 16:42:05 Avelino, meus parabéns. Mais uma vez, mostra de forma simples coisas que para aprendizes demoram muito para encontrar a solução. Edson Junho 08/02/2021 13:01:36 Avelino, poderia colocar um exemplo banco do nº 01, como verificar se o cliente já está cadastrado. Tentei fazer e não consegui. edjunhoscj@gmail.com Eduardo Sousa 08/02/2021 10:05:55 Muito útil. Obrigado por mais esta ajuda. Gilberto Mendes 08/02/2021 08:40:10 Já tive esse problema. Eu resolvi verificando se é registro novor ( If Me.NewRecord then... ). Se a quantidade é 1 eu dou um aviso que já existe. Se não é registro novo, eu vejo se o DCount retorna 2. Boa dica! Parabéns pelo trabalho Gilberto Mendes www.accesspro.com.br Anibal 17/01/2021 10:02:29 funcionou perfeitamente, Obrigado Avelino. Avelino Sampaio 17/01/2021 08:09:53 Anibal, SERIAL é do tipo String ou Numérico ? Se for do tipo String estaria faltando os apóstrofes. Exemplo: If DCount("SERIAL", "ALMOX", "SERIAL='" & Me.Texto0 & "' And STATUS_EQUIP = 'INICIALIZADO'") > 0 Then ... Se for do tipo númerico, experimente: If DCount("SERIAL", "ALMOX", "SERIAL=" & val(Me.Texto0) & " And STATUS_EQUIP = 'INICIALIZADO'") > 0 Then ... No aguardo Anibal 16/01/2021 18:05:26 estou com uma dificuldade semelhante, esta dando erro 3464, segue o código: If DCount("SERIAL", "ALMOX", "SERIAL=" & Me.Texto0 & " And STATUS_EQUIP = 'INICIALIZADO'") > 0 Then MsgBox "O Serial " & Me!Texto0 & " já esta cadastrado no Sistema!", vbExclamation, "INFORMAÇÃO" Me.Undo Cancel = True Texto12.SetFocus End If |