Arquivo da categoria: VBA

Aprenda tudo ou quase tudo sobre VBA.

Administre sua Empresa – Parte II


Vamos falar sobre outros tipos de categorias. São as categorias de despesas. Lembrando que na semana passada iniciamos a série de matérias nas quais passarei algumas dicas de como se administrar uma empresa e como projetar uma aplicação em cima desta necessidade. Usando o melhor da instrução reduzida e o melhor em termos de componentes do VB.

Conforme citei: para que tenhamos um bom formulário de Contas a Pagar é necessário que o mesmo seja amarrado a um fornecedor, uma conta bancária para despesa e sobretudo categorias e subcategorias de despesa. Atualmente quanto menos você permitir o usuário digitar melhor. E isso não significa encher o seu projeto de Combos. Nem muito menos validar até a alma do programa. Lembrem-se da ilustrissíma relação Performance x Segurança.
Já pensaram se o caixa automático dos bancos perguntassem além da senha, o nome do pai e da mãe. A fila daquela joça iria dobrar. Imagine se você sobre um suave acidente e na hora de lhe internarem os caras querem saber o seu C.P.F., R.G, quantas meninas beijou no Verão e ou para as garotas, quantos rapazes foram para o diário. Sendo a sim, quanto maior a segurança, menor a performance.

>Na verdade quando resolvi planejar a idéia da Categorias e SubCategorias para Despesas usada oficialmente pela Microsoft no Money, foi pelo simples fato de que o usuário poderá cadastrar novas categorias e não precisará preencher um campo específico para a Descrição da conta a pagar. É um campo do tipo CHAR a menos na base e dois índices a mais: CDCATEGORIA, CDSUBCATEGORIA. Funcionando da seguinte maneira:

Na Categoria mulheres estão cadastradas todas as SubCategorias referentes aos gastos feitos com as mulheres. É claro, de uma forma hedionda e bem machista.

Você deve tá se perguntando: _ Legal, eu entendi, mas como codificar essa tranquerada toda no VB ?

Primeiramente o desenho da estrutura de dados é impressindível. Vincule a cada SubCategoria o código da Categoria. Veja só:

Fazer isso funcionar é bem fácil. Monte o formulário abaixo e codifique uma função espeficifa para carregar o Combo de Categorias. E em seguida, no evento Lost_Focus deste Combo (CMBCD_CATEGORIA). Carregue o outro Combo (CMBCD_SUBCATEGORIA). Aplicando um Filtro (WHERE) na montagem do RecordSet com o código da Categoria.

ModFunções

   'Módulo Básico com que conterá
   'as funções mais básicas usadas
   Option Explicit
   Dim cConn As ADODB.Connection
   Dim cStrConn As Variant
   Public cMensagem As String
   Public Const cTitulo = "FINANCEIRO"

   Public Function ConectaBanco() As Boolean

        ConectaBanco = False

        'Protegendo em memória na função
        'os objetos a serem usados
        Set cConn = New ADODB.Connection

        'Não se esqueça de direcionar o path com o banco 
        'para o diretório em que o mesmo estive em sua
        'máquina. Ou ultilize um arquivo .INI para informar
        'o path de conexão com a máquina.
         cStrConn = "Provider=Microsoft.Jet.OLEDB.4.0;"
         cStrConn = cStrConn & "Data Source=D:Imasters41ª Materiafinanceiro.mdb;"
         cStrConn = cStrConn & "Persist Security Info=False" 'Abrindo conexão    com a base

         cConn.Open cStrConn 
         Set cStrConn = Nothing

         ConectaBanco = True
End Function
   Public Function DesconectaBanco() As Boolean 
         DesconectaBanco = False

            cConn.Close
            Set cConn = Nothing

         DesconectaBanco = True

   End Function

   Public Function HabilitaCampo(NomeForm As Form, _
                                 NomeCampo As TextBox, _
                                 Habilita As Boolean)

         'Instrução Reduzida para Habilitar
         'ou desabilitar Campos

         NomeForm.NomeCampo.Enable = Habilita

   End Function
   Public Function DisparaComandos(cInstrucao As String) As Boolean

         'Esta função fará as conexões com o banco e dispará    os
         'comandos direto ao objeto de conexão
         'sem o uso de command's e ou recordset's

         DisparaComandos = False

         If ConectaBanco = True Then

            If IsNull(cInstrucao) = True Then
               cMensagem = MsgBox("ERRO INTERNO: O Banco 
Recebeu uma instrução    nula.", vbCritical, cTitulo)
               Exit Function
            End If

            cConn.Execute cInstrucao
          End If

          Call DesconectaBanco

          DisparaComandos = True

   End Function 
 

frmPCOMPRA

   Function CarregaCategoria() As Boolean

   CarregaCategoria = False
   On Error Resume Next

       Set cConn = New ADODB.Connection
       Set RS = New ADODB.Recordset

       If ConectaBanco = True Then

          cSQL = " SELECT CATEGORIASUB.CD_CATEGORIA,"
          cSQL = cSQL & " CATEGORIASUB.DS_CATEGORIA"
          cSQL = cSQL & " FROM CATEGORIASUB"

          Set RS = cConn.Execute(cSQL)
          If Err.Number <> 0 Then
             cMensagem = MsgBox("ERRO INTERNO: Não foi possível carregar as 
Categorias", vbCritical & " " & Err.Description, cTitulo)
             Exit Function
          End If

          While Not RS.EOF
             cmbcd_categoria.AddItem RS("CD_CATEGORIA") & " " & RS("DS_CATEGORIA")
             cmbcd_categoria.Refresh
             RS.MoveNext
          Wend

       End If

        Call DesconectaBanco

   CarregaCategoria = True
   End Function
Function CarregaSubCategoria() As Boolean

   CarregaSubCategoria = False
   On Error Resume Next

   Set cConn = New ADODB.Connection
   Set RS = New ADODB.Recordset

   If ConectaBanco = True Then

      cSQL = " SELECT CATEGORIASUB.CD_SUBCATEGORIA,"
      cSQL = cSQL & " CATEGORIASUB.DS_SUBCATEGORIA"
      cSQL = cSQL & " FROM CATEGORIASUB"
      cSQL = cSQL & " WHERE CATEGORIASUB.CD_CATEGORIAPAI = " 
& cmbcd_categoria.Text    & ""

      Set RS = cConn.Execute(cSQL)
      If Err.Number <> 0 Then
         cMensagem = MsgBox("ERRO INTERNO: Não foi possível 
carregar as Categorias", vbCritical & " " & Err.Description, cTitulo)
         Exit Function
      End If

      While Not RS.EOF
         cmbcd_subcategoria.AddItem RS("CD_SUBCATEGORIA") & " "    
& RS("DS_SUBCATEGORIA")
         cmbcd_subcategoria.Refresh
         RS.MoveNext
      Wend

   End If

   Call DesconectaBanco

   CarregaSubCategoria = True

End Function

Agora não se esqueça de declarar as variáveis globais e fazer a chamada da Function CarregaCategoria( ) ao carregar o formulário:

   'Exigindo que as variáveis sejam
   'declaradas e no código
   Option Explicit
   Dim cSQL As Variant
   Dim RS As ADODB.Recordset
   Dim cNovo As Boolean
Private Sub Form_Load()
   If CarregaCategoria = False Then
      cMensagem = MsgBox("Não foi possível carregar CATEGORIAS.", 
vbCritical & " " & Err.Description, cTitulo)
      Exit Sub
   End If
End Sub

Um outro assunto que quero abordar é a questão das Validações. Nem sempre encher o Form de eventos Validate é uma boa opção. Quanto mais você prende o usuário. Mais você o irrita.

Adote na programação Cliente/Servidor a mesma estética do projeto WEB. Valide tudo o que você tem que validar quando o usuário enviar os dados ao banco. O que chamamos na WEB de: “Dar o Submit”. E isso não é boiolagem !!!

Para seguir esta estética criei uma única função chamada de VALIDACAMPOS( ). Nela validarei tudo o que preciso à acionando no instante em que o feinho do usuário gravar ou atualizar algum dado. Veja só:

Function ValidaCampos() As Boolean

   ValidaCampos = False

   Dim cData As Date

   If cmbcd_categoria.Text = "(Nenhuma Categoria)" Then
      cMensagem = MsgBox("Categoria de Despesa não informada.", vbCritical, cTitulo)
      Exit Function
   End If

   If cmbcd_subcategoria.Text = "(Nenhuma SubCategoria)" Then
      cMensagem = MsgBox("SubCategoria de Desepasa não informada.", vbCritical, cTitulo)
      Exit Function
   End If

   cData = txtdt_emissao.Text
   If IsNull(cData) = True Then
      cMensagem = MsgBox("Data de Emissão não informada.", vbCritical, cTitulo)
      Exit Function
   End If

   cData = txtdt_vencimento.Text
   If IsNull(cData) = True Then
      cMensagem = MsgBox("Data de Vencimento não informada.", vbCritical, cTitulo)
      Exit Function
   End If

   cData = txtdt_pagamento.Text
   If IsNull(cData) = True Then
       txtdt_pagamento.Text = cData
       Exit Function
   End If

   If cmbds_formapg.Text = (Nenhum) Then
      cMensagem = MsgBox("Forma de Pagamento não informada.", vbCritical, cTitulo)
      Exit Function
   End If

   If txtds_juros.Text = vbNullString Then
      txtds_juros.Text = "0"
   End If

   If txtds_multa.Text = vbNullString Then
      txtds_multa.Text = ""
   End If

   If txtcd_fornecedor.Text = vbNullString Then
      cMensagem = MsgBox("Fornecedor não informado.", vbCritical, cTitulo)
      Exit Function
   End If

   If txtcd_contamemo.Text = vbNullString Then
      cMensagem = MsgBox("ContaMemo não informada.", vbCritical, cTitulo)
      Exit Function
   End If

   'Cheque
   If cmbds_formapg.ListIndex = 1 Or _
      txtcd_cheque.Text = vbNullString Then
      cMensagem = MsgBox("Pagamento em Cheque com 
número do cheque não informado.", vbCritical, cTitulo)
      Exit Function
   End If

   If txtvl_conta.Text = vbNullString Then
      cMensagem = MsgBox("Valor não informado.", vbCritical, cTitulo)
      Exit Function
   End If

   If txtvl_contapago.Text = vbNullString Then
      txtvl_contapago.Text = txtvl_conta.Text
   End If

   If txtds_obs.Text = vbNullString Then
      txtds_obs.Text = "Nenhum"
   End If

   ValidaCampos = True

   End Function




Um último assunto a ser abordado no Formulário de Contas a Pagar é a questão do Button Hit.

Trata-se de um componente construído, para vinculação de Chaves Estrangeiras. Ao invés montar um combo com todos os fornecedores cadastrados. O que com um tempo poderá levar a um Combo enorme com mais de 999 registros e conseguentemente o seu combo deixaria de funcionar ou o seu formulário demoraria uma década para carregar os dados.

Com o Button Hit o mentecapto do usuário digita o código do fornecedor ou da conta memo e o sistema pesquisa e exibe a descrição no campo ao lado. Caso não encontre, exibirá que o registro não foi encontrado. Daí se o usuário não souber o código, basta clicar no botão e chamar o cadastro de fornecedores por exemplo, para fazer a pesquisa.

Segue o código para que o Button Hit funcione. Se caso queira maiores detalhes, consulte a matéria sobre Button Hit.

Function ButtonHit(nCodigo As Integer, _
                   cTabela As String) As Boolean

   ButtonHit = False
   On Error Resume Next

   If ConectaBanco = True Then

   If IsNull(nCodigo) = True Then
      cMensagem = MsgBox("Código não Informado.", vbCritical, cTitulo)
      Exit Function
   End If

   If IsNull(cTabela) = True Then
      cMensagem = MsgBox("Tabela não encontrada.", vbCritical, cTitulo)
      Exit Function
   End If

   If Trim(cTabela) = "FORNECEDOR" Then
      cSQL = " SELECT FORNECEDOR.CD_FORNECEDOR,"
      cSQL = cSQL & " FORNECEDOR.NM_FANTASIA"
      cSQL = cSQL & " FROM FORNECEDOR"
      cSQL = cSQL & " WHERE FORNECEDOR.CD_FORNECEDOR = " & nCodigo    & ""
   Else
      cSQL = " SELECT CONTAMEMO.CD_CONTAMEMO,"
      cSQL = cSQL & " CONTAMEMO.NM_TITULAR"
      cSQL = cSQL & " FROM CONTAMEMO"
      cSQL = cSQL & " WHERE CONTAMEMO.CD_CONTAMEMO = " & nCodigo    & ""
   End If

   Set RS = cConn.Execute(cSQL)
   If Err.Number <> 0 Then
         cMensagem = MsgBox("Não foi possível carregar os dados."    _
                            , vbCritical & " " & Err.Description, cTitulo)
         Exit Function
   End If

   If IsNull(RS) = True Then
      If Trim(cTabela) = "FORNECEDOR" Then
         txtcd_fornecedor.Text = ""
         txtnm_fantasia.Text = "Fornecedor não encontrado"
         Exit Function
      Else
         txtcd_contamemo.Text = ""
         txtno_contamemo.Text = "Conta Memo não cadastrada"
         Exit Function
      End If
    End If

   If Trim(cTabela) = "FORNECEDOR" Then
      txtcd_fornecedor.Text = RS("CD_FORNECEDOR")
      txtnm_fantasia.Text = RS("NM_FANTASIA")
      Exit Function
   Else
      txtcd_contamemo.Text = RS("CD_CONTAMEMO")
      txtno_contamemo.Text = RS("NM_TITULAR")
      Exit Function
   End If

   Call DesconectaBanco
   
   End If

   ButtonHit = True

End Function

Por fim, o restante do código. Note a única rotina para Salvar e Atualizar dados. As rotinas para Exclusão e movimentação dos dados no formulário fica prá semana que vem.

Private Sub cmdContaMemo_Click()
   frmCONTAMEMO.Show
End Sub

Private Sub cmdFornecedor_Click()
   frmFORNECEDORES.Show
End Sub

Private Sub cmdNova_Click()
   cNovo = True
End Sub

Private Sub cmdSair_Click()
   End
End Sub

Private Sub cmdSalvar_Click()
   If ValidaCampos = False Then
      Exit Sub
   End If

   If cNovo = True Then
      cSQL = " INSERT INTO PCOMPRA"
      cSQL = cSQL & " (PCOMPRA.CD_CATEGORIA,"
      cSQL = cSQL & " PCOMPRA.CD_SUBCATEGORIA,"
      cSQL = cSQL & " PCOMPRA.CD_FORNECEDOR,"
      cSQL = cSQL & " PCOMPRA.CD_CONTAMEMO,"
      cSQL = cSQL & " PCOMPRA.DT_PAGAMENTO,"
      cSQL = cSQL & " PCOMPRA.DT_VENCIMENTO,"
      cSQL = cSQL & " PCOMPRA.DT_EMISSAO,"
      cSQL = cSQL & " PCOMPRA.DS_OBS,"
      cSQL = cSQL & " PCOMPRA.DS_FORMAPG,"
      cSQL = cSQL & " PCOMPRA.CD_CHEQUE,"
      cSQL = cSQL & " PCOMPRA.VL_CONTA,"
      cSQL = cSQL & " PCOMPRA.VL_CONTAPAGO,"
      cSQL = cSQL & " PCOMPRA.DS_JUROS,"
      cSQL = cSQL & " PCOMPRA.DS_MULTA)"
      cSQL = cSQL & " VALUES(" & cmbcd_categoria.Text & ","
      cSQL = cSQL & " " & cmbcd_subcategoria.Text & ","
      cSQL = cSQL & " " & txtcd_contamemo.Text & ","
      cSQL = cSQL & " '" & txtdt_pagamento.Text & "',"
      cSQL = cSQL & " '" & txtdt_vencimento.Text & "',"
      cSQL = cSQL & " '" & txtdt_emissao.Text & "',"
      cSQL = cSQL & " '" & txtds_obs.Text & "',"
      cSQL = cSQL & " '" & cmbds_formapg.Text & "',"
      cSQL = cSQL & " " & txtcd_cheque.Text & ","
      cSQL = cSQL & " " & txtvl_conta.Text & ","
      cSQL = cSQL & " " & txtvl_contapago.Text & ","
      cSQL = cSQL & " " & txtds_juros.Text & ","
      cSQL = cSQL & " " & txtds_multa.Text & ")"
      cMensagem = "Dados Gravados com Sucesso."
   Else
      cSQL = " UPDATE PCOMPRA SET"
      cSQL = cSQL & " PCOMPRA.CD_CATEGORIA = " & cmbcd_categoria.Text    & ","
      cSQL = cSQL & " PCOMPRA.CD_SUBCATEGORIA = " & cmbcd_subcategoria.Text    & ","
      cSQL = cSQL & " PCOMPRA.CD_FORNECEDOR = " & txtcd_fornecedor.Text    & ","
      cSQL = cSQL & " PCOMPRA.CD_CONTAMEMO = " & txtcd_contamemo.Text    & ","
      cSQL = cSQL & " PCOMPRA.DT_PAGAMENTO = '" & txtdt_pagamento.Text    & "',"
      cSQL = cSQL & " PCOMPRA.DT_VENCIMENTO = '" & txtdt_vencimento.Text    & "',"
      cSQL = cSQL & " PCOMPRA.DT_EMISSAO = '" & txtdt_emissao.Text    & ","
      cSQL = cSQL & " PCOMPRA.DS_OBS = '" & txtds_obs.Text &    "',"
      cSQL = cSQL & " PCOMPRA.DS_FORMAPG = '" & cmbds_formapg.Text    & "',"
      cSQL = cSQL & " PCOMPRA.CD_CHEQUE = " & txtcd_cheque.Text    & ","
      cSQL = cSQL & " PCOMPRA.VL_CONTA = " & txtvl_conta.Text &    ","
      cSQL = cSQL & " PCOMPRA.VL_CONTAPAGO = " & txtvl_contapago.Text    & ","
      cSQL = cSQL & " PCOMPRA.DS_JUROS = " & txtds_juros.Text &    ","
      cSQL = cSQL & " PCOMPRA.DS_MULTA = " & txtds_multa.Text &    ""
      cSQL = cSQL & " WHERE PCOMPRA.CD_PCOMPRA = " & txtcd_conta.Text    & ""
      cMensagem = "Dados Atuallizados com Sucesso."
   End if

     If DisparaComandos(cSQL) = True Then
        cMensagem = MsgBox(cMensagem, vbInformation, cTitulo)
     Else
        cMensagem = MsgBox("ERRO INTERNO: Não foi possível executar    
a operação" & " " & Err.Description, vbCritical,    cTitulo)
        Exit Sub
      End If
   End If

End Sub
 

Agora parem tudo !!! Largem o copo de leite, desliguem a TV, tranquem as portas . . .

Quase todo iniciante em VB tem dúvidas na hora de aplicar um filtro e gerar uma SPREAD, um GRID em cima destes dados filtrados. Exemplo: Selecionar todas as contas a pagar em um determinado período de vencimento. Observe:

frmGRIDPCOMPRA

   Option Explicit
   Dim cSQL As Variant
   Dim cMensagem As String
   Dim RS As New ADODB.Recordset

Private Sub Form_Load()
   If CarregaGrid = False Then
      cMensagem = MsgBox("ERRO INTERNO: Não foi possível carregar os dados.", 
vbCritical & " " & Err.Description, cTitulo)
      Exit Sub
   End If
End Sub

Function CarregaGrid() As Boolean
   CarregaGrid = False

   Set cConn = New ADODB.Connection
   Set RS = New ADODB.Recordset
   Dim cDataInicial As Date
   Dim cDataFinal As Date

   cDataIncial = InputBox("Digite a Data Inicial", cTitulo, cDataInicial)
   cDataFinal = InputBox("Digite a Data Final", cTitulo, cDataFinal)
   cSQL = " SELECT PCOMPRA.CD_PCOMPRA ""Código"""
   cSQL = cSQL & " PCOMPRA.CD_CATEGORIA ""Categoria"""
   cSQL = cSQL & " PCOMPRA.CD_SUBCATEGORIA ""SubaCategoria"""
   cSQL = cSQL & " PCOMPRA.VL_CONTA ""Valor"""
   cSQL = cSQL & " PCOMPRA.DT_VENCIMENTO ""Vencimento"""
   cSQL = cSQL & " WHERE PCOMPRA.DT_VENCIMENTO >= '" & Format(cDataInicial,
    "dd/mm/yyyy") & "',"
   cSQL = cSQL & " AND PCOMPRA.DT_VENCIMENTO <= '" & Format(cDataFinal,
    "dd/mm/yyyy") & ""
  Set RS = cConn.Execute(cSQL)

   Set grdPCONTA.DataSource = RS

   CarregaGrid = True

End Function

>O segredo está em deixar o formulário solto e gerar uma instrução SQL passando como parâmetros as datas imputadas e em seguida carregando um objeto Recordset e passando o mesmo como propriedade DataSource para o GRID. Fazendo isso, o seu Grid, será carregado em tempo de execução com os dados filtrados. E quantas e quantas vezes você disparar esta função, o seu Grid será atualizado.

Legenda do código:

Comentários
Destaque
Códigos

Finalmente concluimos o Form de Contas a Pagar e na semana que vem. Eu volto com os formulários restantes.

Abraços a todos!

Anúncios

Administre sua Empresa – Parte I


Tenho juntado um punhado de dúvidas de diversos leitores ao longo de algum tempo; dúvidas com GRID, SPREAD, em suma; Todas estão relacionadas com o grupo de Componentes do Visual Basic.

Afinal, é indispensável para o bom programador VB, saber carregar um SPREAD, um MSFLEX GRID, um DBGRID e até mesmo uma PROGRESS BAR. E o melhor, de forma higiência. Criando funções específicas e separadas.

Juntei este ao qual chamarei de catalógo de dúvidas e resolvi destinar o meu espaço no Imasters para comentar sobre o uso dos componentes mais sensacionais do Front End Visual Basic, em cima de alguma lógica plausível e bem postada.

Acompanhando uma série de estatíticas sobre a administração das empresas nacionais, sofri uma catalepsia momentânea !

O resultado me assustou tanto, foi pior do que tomar um fora de uma baranga em festa de formatura.
É justo, mas 90% dos microempresários brasileiros não sabem realmente quanto ganham e quanto gastam. Vou ainda mais longe, pois 88% das microempresas paulistas não possuem um Prolabore estimado. Têm o capital dos sócios administrado concomitantemente em paralelo à receita da empresa. Isso é como você montar uma barraquinha de Hot Dog e administrar os seus gastos pessoais em cima da renda bruta obtida com as vendas do seu negócio.

E não é necessário ser pós graduado em Administração de Empresas para saber que o correto é: estimar o capital bruto, retirar a despesa líquida ou o caixa para rêpor a mercadoria, no caso da barraquinha de Hot Dog. E por fim, a sobra é aplicada a um fundo de caixa e o restante é o que chamamos de Prolabore. A renda que deve ser destinada aos respectivos sócios e submetida a um processo semelhante.

O problema é que nem tudo mundo detém essa forma de administrar como uma regra básica, como uma lei!

É é ai que mora o perigo. E onde morre esta série de colunas; pois tentarei ao máximo simplificar resumindo todo o processo de Contas a Pagar/Contas a Receber e Livro Caixa. Em um único projeto. Usando em matéria de componentes, o que o Visual Basic tem de melhor.

Meu amigo, antes que você saia como um pedreiro codificando o que vê pela frente.
Faremos um breve estudo e em cima deste construiremos a base de dados.
Parte por parte. Nada de construir a base toda e depois ir desenvolvendo os formulários no decorrer das outras matérias.

Tentarei ao máximo adicionar um fechamento a cada coluna.

1.1 Contas a Pagar

Para que se obtenha sucesso no ato de fazer um fechamento de gastos mensal e tirar o seu Prolabore.
Ter todas as contas a pagar em dia é fundamental. E mais fundamental ainda é construir um projeto que atenda as espectativas financeiras e proceda uma amarração contábil eficiente.
Sendo assim, para o formulário de Contas a Pagar funcione corretamente vincularemos o mesmo a três chaves estrangeiras:
Fornecedores, Contas Memo (Contas Bancárias) e Categorias/Sub Categorias de Despesa.

Já com a questão das CONSTRAINTS após a criação das tabelas. É bem simples!
Todos os relacionamentos deste pequeno módulo, estão concentrados da tabela PCOMPRA. Afinal, uma conta a pagar provém de um Fornecedor, é paga a partir de uma conta bancária e possui uma Categoria / Sub Categoria para despesa, exemplo Categoria – Despesas Domésticas, Sub Categoria – Conta de Luz, assim como o Microsoft Money.
Foi uma idéia oficializada neste software e que eu particularmente adorei.

O Relacionamento Categoria com SubCategoria, ocorrerá numa mesma tabela; de forma sintética e analítica.
E com essa base devidamente preenchida você já terá um controle simples das suas despesas podendo até fazer um fechamento mensal de gastos.
Mas é claro, vamos dar uma cara a essa lógica. Usando o nosso bom e velho Visual Basic, portando algumas técnicas de programação modernas, generalizando o código em Funções Globais ao invés de ficar copiando e colando código.

Dentre as funções genéricas, separei algumas neste módulo:

ModFunções

 'Módulo Básico com que conterá
 'as funções mais básicas usadas
 Option Explicit
 Dim cConn As ADODB.Connection
 Dim cStrConn As Variant
 Public cMensagem As String
 Public Const cTitulo = "FINANCEIRO"

 Public Function ConectaBanco() As  Boolean

 	ConectaBanco = False

 	'Protegendo em memória na função
 	'os objetos a serem usados
 	Set cConn = New ADODB.Connection

    'Não se esqueça de direcionar o path com o banco	
    'para o diretório em que o mesmo estive em sua
    'máquina. Ou ultilize um arquivo .INI para informar
    'o path de conexão com a máquina.
    cStrConn = "Provider=Microsoft.Jet.OLEDB.4.0;"
 	cStrConn = cStrConn & "Data Source=D:Imasters40ª Materiafinanceiro.mdb;"
 	cStrConn = cStrConn & "Persist Security Info=False" 'Abrindo conexão  com a base

    cConn.Open cStrConn 
    Set cStrConn = Nothing

    ConectaBanco = True

 End Function

 Public Function DesconectaBanco() As Boolean 

      DesconectaBanco  = False

      cConn.Close
      Set cConn = Nothing

      DesconectaBanco = True

 End Function

 Public Function HabilitaCampo(NomeForm As Form, _
                               NomeCampo As TextBox, _
                               Habilita As Boolean)

      'Instrução Reduzida para Habilitar
      'ou desabilitar Campos

       NomeForm.NomeCampo.Enable = Habilita

  End Function

 Public Function DisparaComandos(cInstrucao As String) As Boolean

      'Esta função fará as conexões com o banco e dispará  os
      'comandos direto ao objeto de conexão
      'sem o uso de command's e ou recordset's

      DisparaComandos = False

      If ConectaBanco = True Then

        If IsNull(cInstrucao) = True Then
          cMensagem = MsgBox("ERRO INTERNO: O Banco 
Recebeu uma instrução  nula.", vbCritical, cTitulo)
          Exit Function
        End If

        cConn.Execute cInstrucao

      End If

      Call DesconectaBanco

      DisparaComandos = True

 End Function

Notem que generalizei ao máximo. Tudo o que for usado em um ou mais formulários recomenda-se aplicar em funções globais com retorno Booleano ou seja, sempre vamos ter a certeza de que aquela função foi executada com sucesso.

frmContaMemo

Este é o cadastro simples de contas bancárias, que mandará um código Chave Estrangeira para o formulário frmPCompra.
Este será codificado passo a passo na semana que vem. Notem o encaixe dos componentes:

Atualmente ando abolindo o uso do DataControl para cordenação de registros em um Cadastro.

Seu método de acesso ao banco é arcaíco e mau estruturado. Seus procedimentos são meio desengonçados.
Ele protege além do objeto de conexão, outro objeto em memória de forma preemptiva.
Imagine um passageiro no ônibus sem o número da passagem.

O ideal na hora de programar qualquer tipo de cadastro, é deixar o formulário o mais solto possível.
Fazendo as rotinas de alteração/inclusão e exclusão via instrução SQL direto no objeto de conexão; sem a necessidade de
um ponteiro recordset.Que a propósito só deve ser aberto, quando os botões de navegação forem acionados.
No caso do exemplo da figura abaixo são os botões Próximo e Anterior.

Não se esqueça ainda de aplicar validações rigorosas e de preferência na hora de disparar as rotinas dentro do banco,
como uma página em ASP quando faz o Submit. Note na figura que o Combo com o Nome do Banco é carregado em
tempo de execução. Não há nenhuma tabela de cadastros de bancos na nossa base de dados.
Talvez até houvesse a necessidade em sistemas de escrita contábil. Então todos sabemos que existem menos de 20
bancos economicamente participantes em nosso país. Por que não carregar em tempo de execução o Combo.
E se caso o meliante do usuário desejar optar por um que não tenha sido carregado.
Basta clicar no botão ao lado e incluir um novo banco ao cadastro, naquela execução.
Pois não há o mínimo interesse em aumentar o volume de dados do Combo.

frmFornecedores

Já neste Form. A auto numeração foi deixada por conta do banco. É só será exibida no quando as rotinas de navegação entre os
registros for disparada. Neste formulário foi codificado as rotinas essenciais e não se esqueça de inserir a mascára no campo
referente a Data de Entrega. Observe:

Clique  aqui para abrir a janela pop up com o código

frmCATEGORIASUB

Com este aqui, coloque a mão na massa. E obtenha assim uma idéia básica de como iniciar um simples plano de despesas para
administrar a sua microempresa. É claro que empresas como a Votorantim,
possuem um plano de contas muito mas muito mais complexo. Qualquer dúvida, eu tô na área . . .

Legenda do código:

destaque
comentários
códigos

Na semana que vem. Volto com a continuação enquanto vocês se recuperam dos estragos causados pelo Carnaval. Ainda por fim, preciso comunicar-lhes sobre os problemas que estive com minha conta de email do Imasters e acabei por não receber nenhum email enviado no período de 26/02/2003 a 05/03/2003. Porém quero comunicar-lhes que já está tudo certo e o meu email continua o mesmo: fernando.andrade@imasters.com.br.

Abraços a todos. Beijos para as meninas. E quando chegar o final de semana:

Esse negócio de se trajar de mulher no Carnaval e sobretudo afirmar que isso é só por que é Carnaval. Não é digno. Eu particularmente acho que isso é uma perobagem adquirida e um processo de encapsulamento que mais cedo ou mais tarde poderá expandir-se e lhe tornar uma mulher presa no corpo de um homem.