Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

xoxe

Ajuda com Access

Mensagens Recomendadas

xoxe

Boas

Estou a trabalhar numa base dados em Access para gerir um serviço prestado.

Nesta base de dados tenho duas tabelas onde registo os dados das pessoas a quem é prestado o serviço e na outra registo a data de realização do serviço e o tempo que demorou a ser prestado.

Pretendo para esta BD escrever num campo da tabela onde é registado o serviço efectuado um número sequencial que será iniciado no começo de cada ano, o qual corresponderá ao número da requisição do serviço. Não sei como isto se faz, se me poderem ajudar agradeço.

Pretendo ainda que a base de dados de alguma forma assinale (talvez registar noutra tabela ou através de um campo do tipo Sim/Não) os serviços prestados cujo tempo decorrido entre a prestação de 2 serviços á mesma pessoa seja inferior a 60 dias. Também não sei como se faz isto.

Estou a tentar aprender VBA através de um livro, mas ainda não consigo desenvolver nada por mim próprio.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
FreiNando

Tens de introduzir os dados não nas tabelas mas em formulários para poderes implementar essas funcionalidades.

Para a primeira questão, sempre que inserires um novo registo tens de achar o o valor mais alto da requisição de serviço para esse ano, e incrementa-lo.

Convém lembrar que neste caso tens de bloquear a eliminação de registos ou então podes ficar com lacunas.

Nota: além de VBA deves aprender SQL para poderes criar base de dados convenientemente. Existe muita informação na Net.


O caminho mais curto para conseguir fazer muitas coisas é fazer uma de cada vez. Samuel Smiles

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
xoxe

Já tenho o formulário para dar entrada dos valores, no qual a edição está bloqueada e o campo com o número da requisição estará bloqueado. Só preciso mesmo de preencher esse campo.

Essa forma de incrementar o valor mais alto desse campo é interessante. Qual é a instrução que me permite fazer isso.

Para iniciar a numeração a cada ano estou a pensar utilizar uma condição If. Quando o ano actual for diferente do ano do último registo  ele inicia a numeração.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
FreiNando

Para achar o valor mais alto é preciso fazer uma consulta à base de dados:

Por isso sempre que queira adicionar mais um registo deverá ser executado o seguinte código:

    Dim rst As Recordset
    Set rst = Application.CurrentDb.OpenRecordset("SELECT MAX(campo) FROM [tabela] WHERE [campo_ano]=" & Ano)
    'Ano será a variavel ou objecto que contenha o ano a que se refere a requisição de serviço
    'se for o ano actual, substituir Ano por Year(Date)
    
    
    'se não for obtido valor, não existem registos para este Ano
    If IsNull(rst(0)) Then
        'Aqui começa a nova numeração
        Número = 1
    Else
        'Incrementa o ultimo valor    
        Numero =rst(0)+1
    End If

Que poderá ser colocado no evento de algum botão, ou no event  BeforeInsert do Form


O caminho mais curto para conseguir fazer muitas coisas é fazer uma de cada vez. Samuel Smiles

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
xoxe

Obrigado pela ajuda.

Tenho uma dúvida.

O formulário tem um botão que permite alterar dados, outro que permite inserir um novo registo e outro para guardar.

Se o código for associado ao event BeforeInsert quando efectuar a alteração de um registo esse número irá ser alterado?

E se eu associar ao event Click do botão novo registo irá evitar a alteração deste número.?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
FreiNando

O evento BeforeInsert é chamado apenas quando é inserido um novo registo, e antes de introduzir os dados. Por isso todos os campos estão com valor NULL. Até ser feito um update ao registo, este novo registo pode ser cancelado.

No Access basta carregar a tecla Escape uma vez para voltar ao valor anterior do campo e mais uma vez para cancelar toda a edição do registo e caso este registo seja um novo registo, este será cancelado. Funciona assim nas tabelas, nas consultas e, também nos formularios ligados a uma tabela ou consulta através da Origem de Registos(RowSource).

Para evitares a edição tens de bloquear o campo. Faz isso em modo de estrutura, alterando a propriedade Protegido para Sim.

Se tens um botão  para criar um novo registo então o código que te dei pode ser colocado lá, mas deves ter em atenção que se for criado um novo registo atraves da barra de navegação de registo esse código não será executado. No entanto podes bloquear a adição de registos.

Deves testar a fim de ter a certeza que funciona comodesejas.


O caminho mais curto para conseguir fazer muitas coisas é fazer uma de cada vez. Samuel Smiles

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
xoxe

Já testei e está a funcinar muito bem. Muito Obrigado.

Não querendo abusar da ajuda quanto ao outro caso que eu também referi, será que me podia ajudar?

Estou a guardar as datas em que o serviço é realizado e preciso filtrar de alguma forma os serviços realizados para a mesma pessoa em que o tempo de realização entre 2 serviços seja inferior a 60 dias.

O dados das pessoas a quem é realizado o serviço está numa tabela e o dados do serviço estão noutra, as quais estão relacionadas através da chave primária da tabela de pessoas.

Mais uma vez muito obrigado.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
FreiNando

Bom dia,

Estou a guardar as datas em que o serviço é realizado e preciso filtrar de alguma forma os serviços realizados para a mesma pessoa em que o tempo de realização entre 2 serviços seja inferior a 60 dias.

Como é que queres ver essa informação?

Se é no momento de introduzir um novo serviço, faz uma pesquisa pela data mais recente entre os serviços prestados a essa pessoa.

Se quiser visualizar de entre todos os serviços aqueles que distaram menos de 60 dias, para uma ou mais pessoas, terá de criar um a pesquisa de serviços para cada pessoa , ordenados por data e percorrê-los um a um comparando a data do anterior com a do seguinte, de forma a preencher uma lista com a informação daí resultante.

O bom seria um novo formulário, ligado à tabela Pessoas e quando fosse selecionado o registo de uma determinada pessoa, fazer a pesquisa relacionada com essa pessoa.


O caminho mais curto para conseguir fazer muitas coisas é fazer uma de cada vez. Samuel Smiles

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
xoxe

Vou precisar que cada vez que seja feita a análise sejam encontrados todos os registos que se encontram nesta situação.

Vou precisar de exibir essa informação num formulário.

Na realidade o que se passa é que se forem realizados 2 serviços à mesma pessoa dentro dum período de 60 dias um  desses serviços terá de ser pago.

Talvez registar num campo sim/não se o serviço será ou não pago.

No caso do serviço ser pago vou necessitar de saber qual foi o serviço anterior não pago. Para poder informar a pessoa.

Estou também a pensar fazer uma ligação com o Word para imprimir notificações para as pessoas que terão de pagar o serviço.

Não sei se estou a fazer-me entender.

Terei também de arranjar uma forma de não repetir os que já se encontram processados.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
FreiNando

Vou-te arranjar um exemplo de código para processares os serviços de uma determinada pessoa, e deve ser colocada num modulo.

É uma função que retorna um lista em texto para inserir no RowSource de uma listBox com 5 colunas.

Para processar todas as pessoas basta chamar esta função com o id de cada uma das pessoas e juntar o resultado num unico texto a inserir na listBox.

Public Function ProcessarServicos(PessoaID As Long, Optional Dias As Integer = 60) As String
    Dim rstPess As Recordset 'Registo Pessoa
     Dim rstServ As Recordset 'Tabela Serviços
     Dim Lista As String ' | PessoaID  | Nome Pessoa | Data Serv Anterior | Data Serv Seguinte | Número Dias |
     Dim D As Date
    Dim NumDias As Long
    
    Lista = ""
    
    'verificar a existencia do registo pessoa
     Set rstPess = Application.CurrentDb.OpenRecordset( _
        "SELECT * FROM Pessoas WHERE ID=" & PessoaID)
    If rstPess.EOF Then Exit Function
    
    'pesquizar todos os serviços da pessoa e com data válida
     Set rstServ = Application.CurrentDb.OpenRecordset( _
        "SELECT * FROM Servicos WHERE Data IS NOT NULL AND PessoaID=" _
        & PessoaID & " AND Factura IS NULL ORDER BY Data")
    
    'sem serviços sair
     If rstServ.EOF Then Exit Function
    
    'Data do primeiro serviço
     D = rstServ!Data
    rstServ.MoveNext
    
    'verificar todos os serviços seguintes
     Do Until rstServ.EOF
        NumDias = CInt(rstServ!Data - D)
        If NumDias <= Dias Then
            s = s & PessoaID & ";"
            s = s & rstPess!Nome & ";"
            s = s & Format(D, "dd-mm-yyyy") & ";"
            s = s & Format(rstServ!Data, "dd-mm-yyyy") & ";"
            s = s & NumDias & ";"
        End If
        'Continuar na Data
         D = rstServ!Data
        rstServ.MoveNext    
    Loop
    
    'devolver o resultado
     ProcessarServicos = s
    
End Function


O caminho mais curto para conseguir fazer muitas coisas é fazer uma de cada vez. Samuel Smiles

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
xoxe

Mais uma vez obrigado por todo este seu trabalho.

Pelo que eu entendi deste código acho que vai funcionar muito bem. Vou testar.

Seria possível colocar mais um loop para correr todas as pessoas e depois guardar estes dados numa tabela em vez de exibir uma listagem. A lista de exibição fasso através de um formulário.

É que a minha tabela de pessoas tem mais de mil pessoas a quem o serviço é prestado.

Já li um livro de 450 paginas sobre VBA para Access e não consigo criar nada parecido com isto que você faz. Faço apenas algumas coisas muito mais simples.

Bem pelo menos já consigo entender +/- o código quando o vejo. Só comecei a aprender há umas 2 ou 3 semanas

.

Agradecido por toda a ajuda até agora.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
FreiNando

A Programação é em muitos aspectos identico ao Desporto, há que praticar muito e começar pelos exercicios mais básicos. É preciso conhecer as regras muito bem e não tentar aldrabar, até porque como em qualquer desporto, na hora de demonstrar o que sabe, a verdade aparece.

É muito util ter um bom manual, que pode ser complementado com toda a ajuda encontrada na internet.


O caminho mais curto para conseguir fazer muitas coisas é fazer uma de cada vez. Samuel Smiles

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
xoxe

Escrevi esta função baseada na função que o FreiNando postou mas está a dar-me um erro na condição If rstServico!DataServicoAnterior Is Null Then.

Public Function ProcessarServicos(lngEntidade As Long) As String
    Dim rstServico, rstDataServico, rstDataServicoAnterior As Recordset 'Tabela Serviços
    Dim lngNumServEntid As Long 'Para guardar o número de serviços por entidade
    Dim D As Date
                                   
    'pesquizar todos os serviços da entidade com data de serviço
    Set rstServico = Application.CurrentDb.OpenRecordset("SELECT * FROM Servicos WHERE DataServico IS NOT NULL AND CodEntid =" & lngEntidade & " ORDER BY NumServico")

    'Contar numero de serviços para a entidade
    lngNumServEntid = rstServico.RecordCount
    
    'sem serviços sair
    If rstServico.EOF Then Exit Function
    
    'Se existe apenas um serviço a data do serviço anterior
    'é igual à data do serviço actual menos 65 dias
    If lngNumServEntid = 1 Then
        D = rstServico!DataServico - 65
        With rstServico
        .Edit
        !DataServicoAnterior = D
        .Update
        End With
    End If
                
    'Guarda na tabela as datas do serviço anterior
    Do Until rstServico.EOF
        If rstServico!DataServicoAnterior Is Null Then
            With rstServico
            .Edit
            !DataServicoAnterior = D
            .Update
            End With
            D = rstServico!DataServico
        Else
            D = rstServico!DataServico
        End If
        rstServico.MoveNext
    Loop
    
End Function

Alguma coisa está mas ainda não descobri o quê. Alguém me pode ajudar?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
FreiNando

Em Bases de Dados se um campo comtém valor NULL significa que não possui valor.

Um texto vazio ("") não é NULL e zero(0) também não é NULL.

Em VB quando copiamos valores de uma base de dados temos de verificar se esse valor é NULL, porque caso o seja não vai ter valor para copiar e dá erro.

As comparações em VB são efectuadas entre valores, daí que se NULL não tem valor não pode ser comparado. 

Temos de utilizar a função IsNull(expressão) que nos devolve um valor Boolean(Verdadeiro ou Falso).

Assim sendo, a tua expressão correcta será: If IsNull(rstServico!DataServicoAnterior) Then

No entanto em SQL devemos sempre utilizar a expressão "IS NULL" ou "IS NOT NULL". O SQL é uma linguagem declarativa estruturada, e não de programação, apesar de nessas declarações podermos utilizar algumas funções, na realidade apenas estamos usando os valores devolvidos por essas funções.


O caminho mais curto para conseguir fazer muitas coisas é fazer uma de cada vez. Samuel Smiles

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.