MontaRibbons 4.0 Vetores e Matrizes Manipulação de Strings (Contagem de Caracteres) Funções e Sub-rotinas Login no Sistema Segurança de Dados Mala Direta (Access X Word) com VBA Alterando a Fonte de Registro a Cada Novo Ano Automaticamente Brincando com o Looping For... Next Brincando com Comboboxes Manipulando Strings no VBA (Contagem de Caracteres) Em caixa de textos do tipo Memorando e formatação Rich Text você pode com o seguinte código no evento Change contar os caracteres que são digitados a partir de uma caixa de texto não acoplada e sem formatação: Private Sub Corpo_Change() Call AtualizaContagem DoCmd.RunCommand accmdsave Public Sub AtualizaContagem() Dim ncar As Integer Dim strmsg As String Dim strtitle As String Dim intretval As Integer If Not IsNull(Corpo) Or Corpo <> "" Then ncar = Len(Corpo) Define o comprimento ou número de caracteres existentes na caixa de texto do tipo Memorando e formatação Rich Text ncar = 0 ncar = ncar + 1 Contador de caracteres Me.txtCar = ncar txtcar é o nome da caixa de texto não acoplada sem formatação. Coloque na fonte de controle a seguinte sintaxe: =Len(Corpo) que vai virar =Compr([corpo]) DoCmd.RunCommand accmdsave Este commando atualizará a contagem a partir de ncar ******************************************************************************** ***
Código complementar para dar um refino em detalhes para limitar o número de caracteres digitado If txtcar = 800 Then MsgBox "Atingido o limite máximo de caracteres permitido!!!", vbcritical, "Máximo de Caracteres" Corpo.Locked = True strtitle = "Liberação" strmsg = "Deseja liberar para digitar mais ou deletar informação extra? No primeiro caso, lembre-se que o corpo sairá da estética padrão. Continuar?" intretval = MsgBox(strMsg, vbquestion + vbyesno, strtitle) Select Case intretval Case vbyes Corpo.Locked = False Case vbno Corpo.Locked = True End Select Else Corpo.Locked = False Para implementar ainda mais a análise do texto digitado incluí mais uma subrotina para limitar o texto digitado e realizar uma análise crítica do documento. Public Sub LimitarCaracteres() Me.Refresh Dim scar As Long Const nmax = 800 Corpo.Locked = False scar = Len(Corpo) MsgBox "Você já digitou " & scar & " caracteres. Máximo é de 800 caracteres!!!", vbinformation, "Limite de Caracteres" If scar >= nmax Then Corpo.Locked = True MsgBox "Você chegou ao limite de caracteres para integrar o corpo do memorando!!!", vbcritical, "Limite de Caracteres" Beep
MsgBox "Digitados " & scar & " caracteres!!!", vbinformation, "Máximo de Caracteres Digitados" FUNÇÕES X SUB-ROTINAS Qual é a diferença entre uma Função e uma Sub-Rotina? A diferença entre uma função e uma sub-rotina é que a primeira retorna um valor, enquanto a segunda executa uma tarefa. Vamos primeiramente dar uma olhada em funções e como elas podem ser úteis para resolver inúmeros problemas em VBA. Vou destacar algumas que já criei para que você programador possa ir já aprendendo a desenvolvê-las e utilizá-las em seus aplicativos. Vamos ver então primeiramente funções sem parâmetros. FUNÇÕES PRÁTICAS (1) Private Function Tabuada() Dim i As Integer Bloco For...Next ******************************************************************************** For i = 1 To 10 Tabuada = Valor * i MsgBox "O valor " & Valor & " vezes " & i & " é " & Tabuada, vbinformation, "Tabuada" Next i ************************************************************************************** End Function (2) Public Function Substituir() As String Dim srua As String Dim savn As String Dim setr As String If Not IsNull(Endereco) Then Endereco é o nome do campo em sua tabela presente no formulário srua = Replace(Endereco, "Rua", "R") 'Expression(ou nome do campo), Find(procura a string antiga), Replace(Substitui por esta nova string) Endereco = srua setr = Replace(Endereco, "Estrada", "Etr") 'Expression(ou nome do campo),
Find(procura a string antiga), Replace(Substitui por esta nova string) Endereco = setr savn = Replace(Endereco, "Avenida", "Avn") 'Expression(ou nome do campo), Find(procura a string antiga), Replace(Substitui por esta nova string) Endereco = savn Substituir = Endereco Aqui a função recebe o valor Resultante Else Exit Function End Function Na saída do campo Endereco chame a função. Private Sub Endereco _Exit(Cancel As Integer) Call Substituir() 'Chama a função na saída do campo endereço (3) Public Function CalculaTaxa() Dim ntaxa As Double Dim jurocredito As Double Dim jurodebito As Double Dim jurovoucher As Double Dim parc As Integer parc = Nz(Parcela) ' Atualizando a caixa taxa com valor da taxa de credito If Me!Descricao = "Credito" Then jurocredito = DLookup("CpJuros", "tbljuros", "CpTipo = 'Crédito' And CodParcelaCred = " & parc) Me.valortaxa = jurocredito ntaxa = valortaxa CalculaTaxa = ntaxa ' Atualizando a caixa taxa com valor da taxa de debito If Me!Descricao = "Debito" Then jurodebito = DLookup("CpJuros", "tbljuros", "CpTipo = 'Débito' And CodParcelaDeb = " & parc) Me.valortaxa = jurodebito ntaxa = valortaxa CalculaTaxa = ntaxa Atualizando a caixa taxa com valor da taxa de voucher If Me!Descricao = "Voucher" Then
' atualizando a caixa taxa com valor da taxa de voucher jurovoucher = DLookup("CpJuros", "tbljuros", "CpTipo = 'Voucher' And CodParcelaVou = " & parc) Me.valortaxa = jurovoucher ntaxa = valortaxa CalculaTaxa = ntaxa Me.Datavenda.SetFocus End Function Como é que fica a tabela de juros (tbljuros)? Nome do campo Tipo de dados Id_Tipo CpTipo CpJuros CodParcelaCred ParcelaCred CodParcelaDeb ParcelaDeb CodParcelaVou ParcelaVou Numeração Automática Texto Número Número Número Número Número Número Número ID_Ti po CpTipo CpJur os CodParcela Cred ParcelaC red 1 Crédito 3,8 1 1 tbljuros CodParcela Deb Parcela Deb 2 Débito 2,2 1 1 3 Vouch er 4 Parcela do CodParcela Vou Parcela Vou 7,5 1 1 7,5 5 Crédito 6,5 2 2 6 Débito 6,5 2 2 7 Vouch er 6,5 2 2
Agora vamos aprender a criar funções parametrizadas ou com parâmetros. (1) Com um parâmetro Public Function EncontreErrosOrtográficos(nTexto As String) ntexto = CInt(InputBox("Você pretende fazer uma correção ortográfica?" & vbcrlf & _ "1 - Yes " & vbcrlf & _ "2 - No ", "Erros Ortográficos")) Select Case ntexto Case Is = 1 DoCmd.RunCommand accmdspelling Case Is = 2 Exit Function End Select ntexto = Resposta 'Resposta é o nome da caixa de texto do tipo Texto ou do tipo Memorando EncontreErrosOrtográficos = ntexto End function Código da saída da caixa de texto Resposta. Private Sub Resposta_Exit(Cancel As Integer) Dim ntexto As String Call EncontreErrosOrtográficos(nTexto) (2) Função para identificar o usuário com dois parâmetros Public Function VerificaLogin(sLogin As String, ssenha As String) Dim nlogin As String Dim nsenha As String nlogin = login 'login é o nome da caixa de texto do formulário de Login nsenha = senha 'senha é o nome da caixa de texto do formulário de Login slogin = Nz(DLookup("login", "tblcadastro", "login = '" & nlogin & "'")) A função Nz ssenha = Nz(DLookup("senha", "tblcadastro", "login = '" & slogin & "'")) If slogin <> "" Then MsgBox "Nome OK", vbinformation, "Testa Login"
If ssenha = nsenha Then MsgBox "Senha válida!!!", vbinformation, "Testa Login" DoCmd.OpenForm "frmteste", acnormal 'Se a senha for válida abre o formulário principal Else MsgBox "Senha inválida!!!", vbinformation, "Testa Login" End Function Código do botão OK (cmdentrar) Private Sub cmdentrar_click() If Not IsNull(login) And Not IsNull(senha) Then If VerificaLogin(login, senha) = True Then DoCmd.Close acform, "frmtestelogin", acsaveyes SUB-ROTINAS PRÁTICAS (1) Public Sub RemoveTexto() Dim nendereco As String Dim strtexto As String Dim intpos As String nendereco = ENDERECO intpos = InStr(1, nendereco, ",") 'Localiza a vírgula na string de endereço a partir do primeiro caracter strtexto = Trim(Left(nENDERECO, intpos)) 'Remove a string à esquerda da vírgula para inclusão de uma nova numeração pela consulta da minha combo cuja fonte de dados é uma consulta dos endereços pelo campo ENDERECO de minha tabela ENDERECO = strtexto No evento duplo-clique do campo ENDEREÇO: Private Sub ENDERECO_DblClick(Cancel As Integer) If Not IsNull(ENDERECO) Then Call RemoveTexto 'Chama a sub-rotina que remove os caracteres à esquerda da vírgula
MsgBox "Atualize o campo ENDERECO com a nova numeração agora!!!", vbinformation, "CONTROLE DE ORDEM DE SERVIÇO" Else MsgBox "O campo ENDERECO está em branco!!!", vbquestion, "CONTROLE DE ORDEM DE SERVIÇO" (2) Um trecho de código do aplicativo Gerador de Relatórios Public Sub AcrescentarNivel() Dim strregistro As String Dim strassunto As String Dim strstatus As String Dim n As Integer Dim strmsg As String Dim strtitle As String Dim intretval As Integer strtitle = "Criar Relatório" strmsg = "Deseja acrescentar um Nível?" intretval = MsgBox(strMsg, vbquestion + vbyesno, strtitle) Select Case intretval Case vbyes If Nível = Format(Nível, "0.0") Then 'Se o formato do código for com ponto acrescenta o próximo Nível n = Mid(Forms!CriarRelatorioII!Nível, 3, 3) 'Pega o último dígito do último código n = n + 1 strregistro = Mid(Forms!CriarRelatorioII!Nível, 1, 1) & "." & n 'Formata o código e acrescenta uma unidade ao valor depois do ponto strregistro = Replace(strRegistro, ",", ".") 'Corrige e reformata o código strassunto = Assunto DoCmd.SetWarnings False strregistro = "INSERT INTO Pai(Nível,Assunto) VALUES('" & strregistro & "', '" & strassunto & "')" DoCmd.RunSQL strregistro DoCmd.RunCommand accmdrefresh DoCmd.SetWarnings True MsgBox "Dados Alterados com sucesso!!!", vbexclamation, "Criar Relatorio" Else 'Caso o contrário n = Mid(Forms!CriarRelatorioII!Nível, 3, 3) 'Pega o último dígito do último código n = n + 1
strregistro = Mid(Forms!CriarRelatorioII!Nível, 1, 1) & "." & n 'Formata o código e acrescenta uma unidade ao valor depois do ponto strregistro = Replace(strRegistro, ",", ".") strassunto = Assunto DoCmd.SetWarnings False strregistro = "INSERT INTO Pai(Nível,Assunto) VALUES('" & strregistro & "', '" & strassunto & "')" DoCmd.RunSQL strregistro DoCmd.RunCommand accmdrefresh DoCmd.SetWarnings True MsgBox "Dados Alterados com sucesso!!!", vbexclamation, "CriarRelatorio" Case vbno Exit Sub End Select LOGIN NO SISTEMA Public Function VerificaLogin(sLogin As String, ssenha As String) Dim nlogin As String Dim nsenha As String nlogin = login 'login é o nome da caixa de texto do formulário de Login nsenha = senha 'senha é o nome da caixa de texto do formulário de Login slogin = Nz(DLookup("login", "tblcadastro", "login = '" & nlogin & "'")) A função Nz ssenha = Nz(DLookup("senha", "tblcadastro", "login = '" & slogin & "'")) If slogin <> "" Then MsgBox "Nome OK", vbinformation, "Testa Login" If ssenha = nsenha Then MsgBox "Senha válida!!!", vbinformation, "Testa Login" DoCmd.OpenForm "frmteste", acnormal 'Se a senha for válida abre o formulário principal Else MsgBox "Senha inválida!!!", vbinformation, "Testa Login" End Function Código do botão OK (cmdentrar) Private Sub cmdentrar_click()
If Not IsNull(login) And Not IsNull(senha) Then If VerificaLogin(login, senha) = True Then DoCmd.Close acform, "frmtestelogin", acsaveyes SEGURANÇA DE DADOS Public Function verificalogin(slogin As String, ssenha As String) Dim nlogin As String Dim nsenha As String Dim xlogin As String Dim ylogin As String Dim zlogin As String Dim ncodigo As Integer Dim x As String Dim y As String Dim z As String nlogin = login nsenha = senha x = Nz(DLookup("Nivel", "tblniveis", "Codigo = 1")) y = Nz(DLookup("Nivel", "tblniveis", "Codigo = 2")) z = Nz(DLookup("Nivel", "tblniveis", "Codigo = 3")) ncodigo = Nz(DLookup("Codigo", "tblcadastro", "login = '" & nlogin & "'")) slogin = CStr(Nz(DLookup("login", "tblcadastro", "login = '" & nlogin & "'"))) ssenha = CStr(Nz(DLookup("senha", "tblcadastro", "login = '" & slogin & "'"))) xlogin = CStr(Nz(DLookup("login", "tblcadastro", "Nivel = '" & x & "' And Codigo = " & ncodigo))) ylogin = CStr(Nz(DLookup("login", "tblcadastro", "Nivel = '" & y & "' And Codigo = " & ncodigo))) zlogin = CStr(Nz(DLookup("login", "tblcadastro", "Nivel = '" & z & "' And Codigo = " & ncodigo))) If slogin <> "" Then 'Valida usuário MsgBox "Login válido!!! ", vbinformation, "Testa Login" If ssenha = nsenha Then 'Valida senha do usuário MsgBox "Senha válida!!!", vbinformation, "Testa Login" If xlogin = slogin Then MsgBox "O nivel é de " & x & "", vbexclamation, "Testa Login" DoCmd.OpenForm "frmteste", acnormal,,, acformedit DoCmd.Close acform, "frmtestelogin", acsaveyes ElseIf ylogin = slogin Then MsgBox "O nivel é de " & y & "", vbexclamation, "Testa Login"
DoCmd.OpenForm "frmteste", acnormal,,, acformadd DoCmd.Close acform, "frmtestelogin", acsaveyes ElseIf zlogin = slogin Then MsgBox "O nivel é de " & z & "", vbexclamation, "Testa Login" DoCmd.OpenForm "frmteste", acnormal,,, acformreadonly DoCmd.Close acform, "frmtestelogin", acsaveyes Else Exit Function Else MsgBox "Senha inválida!!!", vbinformation, "Testa Login" Else MsgBox "Login inválido!!!", vbinformation, "Testa Login" End Function CALCULANDO TEMPO EM ANOS, MESES E DIAS ENTRE DUAS DATAS Vamos supor que você queira a partir do número de meses calcular o tempo em ano, meses e dias. Desenvolvi uma técnica de primeiro, calcular entre duas datas o número de meses e só a partir do resultado extrair o tempo em anos, meses e dias. Vamos ver, então, a função que calcula o tempo decorrido entre duas datas chama-se DateDiff ou DifData: Public Function CalculaTempoServico(nData1 As Date, ndata2 As Date) Dim nts As Long ndata1 = Nz([DataInicial]) ndata2 = Nz([DataFinal]) nts = Nz(DateDiff("m", ndata1, ndata2)) diferença entre as datas 'Calcula o total de meses pela TempoServico = Nz(nts) End Function Private Sub Atualizar_Click()
Dim nano As Long Dim sano As Long Dim nmes As Integer Dim ntempototal As Long Dim TempAno As Long Dim TempMes As Long Dim CalcAno As Long Dim ndia As Long Dim ndatainicial As Date Dim ndatafinal As Date Dim smes As Long Dim smes2 As Long smes = Month(DataInicial) smes2 = Month(DataFinal) ntempototal = TempoTotal sano = txtano ndatainicial = left(format(datainicial, "dd/mm/yyyy"), 2) ndatafinal = left(format(datafinal, "dd/mm/yyyy"), 2) nano = Nz(IIf(nTempoTotal <= 12, 0, Replace(left(([TempoTotal] / 12), 2), ",", ""))) 'Calcula o total 'de anos. Se o total em meses for menor que 12, o total de anos é zero. Caso contrário pega os 'dois primeiros dígitos do quociente como total de anos. nmes = Nz(CInt(Abs(nTempoTotal - (sano * 12)))) 'Calcula o que sobra de meses. Uma vez calculado o número de anos, capturo o valor em uma variável sano, multiplico por 12 para dar o número em meses e subtraio do total de meses. ndia = IIf(sMes = smes2, Abs(DateDiff("d", ndatainicial, ndatafinal)), 0) Calcula a diferença em dias entre duas datas txtano = Nz(nAno) txtmes = Nz(CInt(nMes)) txtdia = Nz(nDia) DoCmd.RunCommand accmdrefresh MALA DIRETA (ACCESS X WORD) COM VBA No documento Word, com este código, você não precisa procurar pelo registro que você acabou de implantar lá no Access, isto no arquivo gerado
.mdb ou.accdb de seu projeto Mala Direta. Quando você abrir o documento, criticará qualquer tentativa do usuário de digitar dentro do formulário e já irá para o último registro que é o que você acabou de preencher no bd em Access. Private Sub Document_Open() Dim Texto As String Texto = "POR FAVOR, NÃO PREENCHA NESTE FORMULÁRIO!!!" MsgBox Texto, vbinformation, "MEU FORMULÁRIO" Call IrParaUltimo Sub IrParaUltimo() ' IrParaUltimo Macro ' ' ActiveDocument.MailMerge.DataSource.ActiveRecord = wdlastrecord ALTERANDO A FONTE DE REGISTRO A CADA NOVO ANO AUTOMATICAMENTE Se você usa uma mesma fonte de dados para o seu formulário de um aplicativo de sua empresa, um cadastro de funcionários por exemplo, não é necessário criar uma cópia, zera(r) a(s) tabela(s), isto é, ter todo esse trabalho na virada do ano. Com um simples código você pode alterar somente o ano e trocar a fonte de registro, sua tabela por outra tabela. Mas para isso você precisa criar tantas tabelas anuais quanto desejar antes de tudo. Um único trabalho, mas vai deixar você tranquilo nos próximos anos e você nem precisa estar presente para atender o seu cliente. Exemplo: Minha tabela atual chama-se ListadeFR2013. Crio então várias tabelas para os anos seguintes: ListadeFR2014, ListadeFR2015, etc Private Sub Form_Open(Cancel As Integer) Dim nano As Long Dim cal As String cal = UCase(MonthName(Month(Date), True)) 'Variável que pega o mês atual Select Case cal Case Is = "JAN" nano = InputBox("Digite o novo ano OU, o ano de pesquisa OU mantenha o ano atual: ", "FR",
Case Is = "FEV" Case Is = "MAR" Case Is = "ABR" Case Is = "MAI" Case Is = "JUN" Case Is = "JUL" Case Is = "AGO" Case Is = "SET" Case Is = "OUT" Case Is = "NOV"
Case Is = "DEZ" MsgBox "Aguarde a entrada do novo ano para zerar o controle...", vbexclamation, "FICHA DE REVISÃO" End Select BRINCANDO COM O LOOPING For... Next: 1- Crie um formulário com uma caixa de texto e dê um nome a ela. 2- No ambiente de código coloque esta função: Public Function Analise() Dim s As Integer Dim scripto As String For s = 1 To Len(txtPalavra) scripto = Nz(Mid(txtPalavra, s, 1)) MsgBox scripto Em seguida, Next s 'txtpalavra seria o nome de sua caixa de texto 'Repare o que será exibido na variável scripto. troque a variável scripto pela variável s. End Function Código do botão Testar: Private Sub cmdtestar_click() Call Analise BRINCANDO COM COMBOBOXES Acho que este exemplo será muito prático para quem quer aprender a filtrar com as comboboxes. Aprenda a identificar quantas ruas existem em determinado bairro e qual o bairro correspondente a determinada rua. ATENÇÃO: Coloque o código bairro da tabela tblbairros correspondente a cada rua da tabela tblruas na tabela tblruas. Coloque três comboboxes e uma caixa de texto em seu formulário. Crie duas tabelas, uma para Ruas e outra para Bairros:
tblbairros: CodBairro - Numeração Automática - com chave primária Bairro - Texto tblruas: CodRua - Número Rua - Texto CodBairro - Número Bairro - Texto NOTA: Insira ruas à vontade com o seu bairro respectivo na tabela tblruas e código de Bairro correto. 'Filtra as ruas para o bairro selecionado Private Sub cbobairros_afterupdate() 'Código de Eduardo Machado (Good Guy) Dim strmsg As Integer Dim sbairro As String sbairro = Nz(cboBairros.Column(1)) strmsg = Nz(DLookup("CodBairro", "tblbairros", "Bairro = '" & sbairro & "'")) Me.cboRuas.RowSource = "SELECT tblruas.codrua, tblruas.rua FROM tblruas WHERE tblruas.codbairro = " & strmsg 'Propriedades desta combobox: 'Origem da linha : SELECT tblbairros.[codbairro], tblbairros.[bairro] FROM tblbairros ORDER BY tblbairros.bairro; 'Número de colunas: 2 'Largura das colunas: 0cm;4cm; 'Filtra o bairro para a rua selecionada Private Sub cboruas_afterupdate() 'Código de Eduardo Machado (Good Guy) Dim strmsg As Integer Dim srua As String srua = Nz(cboRuas.Column(1)) strmsg = Nz(DLookup("CodBairro", "tblruas", "Rua = '" & srua & "'"))
Me.cboBairros.RowSource = "SELECT tblbairros.codbairro, tblbairros.bairro FROM tblbairros WHERE tblbairros.codbairro = " & strmsg 'Propriedades desta combobox: 'Origem da linha : SELECT tblruas.codrua, tblruas.rua FROM tblruas ORDER BY tblruas.rua; 'Número de colunas: 2 'Largura das colunas: 0cm;4cm; 'Filtra o bairro para a rua selecionada, numa caixa de texto Private Sub cboruas2_beforeupdate(cancel As Integer) 'Código de Eduardo Machado (Good Guy) Dim srua As String srua = cboruas2.column(1) Me.txtBairros = DLookup("Bairro", "tblruas", "Rua = '" & srua & "'") 'Caixa de texto que informará o bairro correspondente a esta rua 'Propriedades desta combobox: 'Origem da linha : SELECT tblruas.codrua, tblruas.rua FROM tblruas ORDER BY tblruas.rua; 'Número de colunas: 2 'Largura das colunas: 0cm;4cm; End