none
Obter variáveis dentro de variáveis RRS feed

  • Pergunta

  • Amigos boa tarde.

    Preciso obter as variáveis e sua contagem, que se encontram incluídas noutras variáveis.

    Para as variáveis principais, utilizo um código, gentilmente cedido por Felipe Benzadeus a quem muito tenho a agradecer e que transcrevo.

    ListBox14.Clear
    CheckBox29.Locked = True: CheckBox30.Locked = False
    Label283.Caption = "TIPO DIABETES"
    Label305.Caption = "SEXO"
    Label293.Caption = "PACIENTES COM DIABETES"
    Label295.Caption = ""
    
        Const cstrColDIAB As String = "T"
        Const cstrColDIABSX As String = "D"
        
    Dim ttvarD As Integer, ttvarM As Integer, ttvarF As Integer
    Dim TpDIABRow, TpDIABlast As Long, TpDIABlastSX As Long
    Dim wks As Excel.Worksheet
    Dim dicD As Object, SXdic As Object ' Scripting.Dictionary
    Dim varD As Variant, varM As Variant, varF As Variant
    Dim strD As String, astrD() As String
    Dim strM As String, strF As String, astrM() As String, astrF() As String
      
      Set dicD = CreateObject("Scripting.Dictionary")
      Set SXdic = CreateObject("Scripting.Dictionary")
      Set wks = ThisWorkbook.Worksheets("REGISTOS")
      
    With wks
      TpDIABlast = .Cells(.Rows.Count, cstrColDIAB).End(xlUp).Row
      TpDIABlastSX = .Cells(.Rows.Count, cstrColDIABSX).End(xlUp).Row
      
    For TpDIABRow = 2 To TpDIABlast
        strD = .Cells(TpDIABRow, cstrColDIAB).Value
    
    '==============================================================================INSERIR CONDIÇÃO DE BUSCA
    If wks.Range("T" & TpDIABRow) <> "--" And wks.Range("T" & TpDIABRow) <> "" Then
        If VBA.Len(strD) > 0 Then
        strD = VBA.Mid(strD, 1) '=====O NUMERO INDICA O CARATER ONDE INICIA A BUSCA
        astrD = VBA.Split(strD, "-")
            For Each varD In astrD
            strD = VBA.CStr(varD)
                If dicD.Exists(strD) Then
                    dicD(strD) = dicD(strD) + 1
                Else
                    dicD.Add strD, 1
                End If
                    ttvarD = ttvarD + 1
            Next varD
        End If
    End If
    Next TpDIABRow
    
      With Me.ListBox14
        .ColumnCount = 4
        For Each varD In dicD.Keys
          .AddItem
            ListBox14.ColumnWidths = "120;105;90;10"
          .List(.ListCount - 1, 0) = varD
          .List(.ListCount - 1, 1) = dicD(varD)
          .List(.ListCount - 1, 2) = Format((dicD(varD) * 100) / ttvarD, "0.00")
          .List(.ListCount - 1, 3) = " %"
        Next varD
      End With
    

    Tentando adaptar o código, ele fornece os valores das segundas variáveis, mas apenas no total e não por variáveis separadas.

    Traduzindo isto para Português que se entenda, tenho uma coluna com o registo de doentes com Diabetes:

    ----Tipo I, Tipo II, Pré-Diabetes e Diab. Gestacional. "Estas são as varáveis principais", cujos valores consigo com a rotina acima.

    Preciso pois de um código que, me descrimine em cada uma destas variáveis o numero de doentes do sexo Masc. e do sexo Fem.

    Grato pela ajuda que puderem dar...

    Cumprimentos

    M_A_L


    sábado, 10 de maio de 2014 13:02

Respostas

  • Acredito que seu problema possa ser resolvido com bastante facilidade, por esse caminho:

    Private Sub CommandButton32_Click()
      Dim wks As Excel.Worksheet
      
      Set wks = ThisWorkbook.Worksheets("REGISTOS")
      With wks
        'Tipo 1, Feminino
        MsgBox WorksheetFunction.CountIfs(.Columns("T"), "I", .Columns("D"), "F")
      
        'Tipo 1, Masculino
        MsgBox WorksheetFunction.CountIfs(.Columns("T"), "I", .Columns("D"), "M")
      
        'Tipo 2, Feminino
        MsgBox WorksheetFunction.CountIfs(.Columns("T"), "II", .Columns("D"), "F")
      
        'Tipo 2, Masculino
        MsgBox WorksheetFunction.CountIfs(.Columns("T"), "II", .Columns("D"), "M")
      End With
    End Sub

    Entendeu como funciona a função CountIfs?

    Valor = CountIf([coluna1],[critério1],[coluna2],[critério2],(...),[colunaN],[critérioN])


    Felipe Costa Gualberto - http://www.ambienteoffice.com.br

    • Marcado como Resposta M_A_S_L domingo, 8 de junho de 2014 00:42
    quarta-feira, 4 de junho de 2014 00:46
    Moderador
  • Private Sub CommandButton32_Click()
      Dim wks As Excel.Worksheet
      Dim dblFem1 As Double
      Dim dblMas1 As Double
      Dim dblFem2 As Double
      Dim dblMas2 As Double
      
      Set wks = ThisWorkbook.Worksheets("REGISTOS")
      With wks
        dblFem1 = WorksheetFunction.CountIfs(.Columns("T"), "I", .Columns("D"), "F")
        dblFem2 = WorksheetFunction.CountIfs(.Columns("T"), "II", .Columns("D"), "M")
        dblMas1 = WorksheetFunction.CountIfs(.Columns("T"), "I", .Columns("D"), "F")
        dblMas2 = WorksheetFunction.CountIfs(.Columns("T"), "II", .Columns("D"), "M")
      End With
      
      With ListBox14
        .AddItem
        .List(0, 0) = "F"
        .List(0, 1) = "I"
        .List(0, 2) = dblFem1
      
        .AddItem
        .List(1, 0) = "M"
        .List(1, 1) = "I"
        .List(1, 2) = dblMas1
      
        .AddItem
        .List(2, 0) = "F"
        .List(2, 1) = "II"
        .List(2, 2) = dblFem2
      
        .AddItem
        .List(3, 0) = "M"
        .List(3, 1) = "II"
        .List(3, 2) = dblMas2
      End With
    End Sub


    Felipe Costa Gualberto - http://www.ambienteoffice.com.br

    • Marcado como Resposta M_A_S_L domingo, 8 de junho de 2014 00:40
    sexta-feira, 6 de junho de 2014 01:04
    Moderador

Todas as Respostas

  • Caro Manuel Antonio, bom dia.

    Quando você faz o registro de pacientes deve selecionar o sexo para evitar a aplicação de exames impróprios. Por exemplo: imagine um homen receber um pedido de exame do tipo PAPA NICOLAU e uma senhora um exame do tipo ESPERMOGRAMA!

    É no mínimo hilariante! Mas o que tem isso a ver com teu programa?

    Se você cuidou de selecionar os exames de acordo com o sexo, faça uma listagem dos pacientes a partir desse ponto, pois já foram previamente identificados.

    Edison

    domingo, 11 de maio de 2014 13:11
  • Bom dia, Edsudani.

    Não estão em causa, marcações de exames, mas sim estatísticas de dados previamente gravados.

    É claro que no caso concreto, quando se trata de classificar a diabetes gestacional, o sexo que corresponde é sempre feminino, no entanto na rotina que preciso, os dados deverão ser apresentados desta forma: Fem. - 10,   Masc.  - 0.
    Estas situações são pois óbvias e nada têm de hilariantes, pois a rotina que dá um resultado em diabetes do tipo II, sendo a mesma que apresenta os dados da Diabetes Gestacional, tem obrigatóriamente que ter o mesmo comportamento.

    Caso se tratasse de marcação de exames, como o doente tem um registo com o seu nome, seria nesse registo individual que seria registado e o sexo, já lá estaria definido. Portanto ao gravar o Papa Nicolau, seria na ficha da Genoveva e não na do Gervasio. Na apresentação das estatísticas por Papa Nicolau, se fosse utilizar a mesma rotina que utilizo para Obesidade, era pois óbvio que no Papa Nicolau me apareceriam "0" em masculinos, pois as label de apresentação dos resultados são as mesmas.

    O problema no meio disto tudo, são os meus magros conhecimentos de VBA, pois se percebesse alguma coisa seria fácil por certo resolver a questão.

    Neste caso concreto, a rotina que aplicar para a Diabetes, seria aplicada para o exame citado, para os hábitos tabágicos, para o consumo de drogas, para os registos de Tensão Arterial, pois há homens  e Mulheres com todos estes problemas. Apenas a apresentação dos dados seria diferente.
    Da mesma forma, quando acedo às estatísticas da Saúde Materna, óbviamente no Masculino aparece-me o resultado "0".

    Como os meus conhecimentos de VBA são muito pequenos, é mais fácil para mim utilizar a mesma rotina.

    Os valores globais, como disse no post que coloquei, são-me apresentados, sinal que o sexo do doente está registado.

    Com a rotina apresentada, selecionando o tipo de diabetes, a aplicação diz-me:
    tipo 2 ---20
    tipo 1 ---  6

    Masc. --- 18
    Fem.  ---   8

    Mas o que pretendia era:

    Tipo 2  ---  20
    Tipo 1  ---   6

    Masc.  -  12
    Fem.   -   8
    Masc.  -   1
    Fem.   -   5

    Penso ter sido claro na explicação e exposição da minha dúvida.

    Cumprimentos

    M_A_L


    • Editado M_A_S_L quarta-feira, 14 de maio de 2014 11:28
    quarta-feira, 14 de maio de 2014 10:54
  • Olá, Manuel.

    Estou começando a achar que você deveria utilizar uma tabela dinâmica. Como você armazena os dados?


    Felipe Costa Gualberto - http://www.ambienteoffice.com.br

    sábado, 17 de maio de 2014 20:14
    Moderador
  • Bom dia Felipe.

    Bons ventos o tragam a este tópico e espero que esteja de saúde.

    Os dados são armazenados numa folha de cálculo, mais ou menos desta forma:

    coluna A-nome do paciente

    coluna B-data nascimento

    coluna C-idade

    Coluna D-sexo

    ...

    coluna N-tensão Arterial

    ...

    coluna T-tipo de diabetes

    etc.

    Os dados de um doente encontram-se todos na mesma linha.

    Os dados são fornecidos à folha de calculo através de vários userform's encadeados, que no primeiro registo de um doente, através do botão gravar abre automaticamente o próximo userform.

    No entanto a gravação de dados pode ser interrompida e reiniciada mais tarde nesse mesmo userform.

    Através do botão "alterar registos", os mesmos userforms podem ser usados individualmente, corrigindo apenas os dados constantes nesse userform, sendo os dados gravados na folha, visualizados ao clicar no botão "ver registos".

    Grande parte dos dados são introduzidos marcando ou desmarcando Checkbox's e OptionButtons. de forma que ao clicar em "gravar" ou  em "alterar registos", o valor gravado na folha será a Caption do objeto, pois desta forma esse valor não sofre erros de digitação. A visualização é feita de forma inversa de modo que clicando em "ver registos" as checkbox e OptionButton ficam marcadas.

    Finalmente no form "estatísticas", os dados são projetados em listbox's que passam depois para outra folha para elaboração de gráficos.

    Os dados que preciso e que não consigo apurar, são, digamos um parcial dos valores apurado com a rotina acima e que me facultou anteriormente. Falta-me conhecimento da sintaxe, mas penso que criando uma coleção dentro do dicionário, isso seja possível com a sua rotina. Penso que podem ser criadas varias coleções dentro de um dicionário, mas não sei nem encontrei nada que me ajudasse a fazê-lo.

    Com a sua rotina, consigo obter os valores totais M ou F, dentro do range selecionado, mas por mais voltas que tenha dado, com If's e mais If's a condicionar as escolhas, não consegui que me fossem apresentados os valores que pretendo, conforme coloquei no tópico. 

    Pegando no seu código, digamos que preciso de partir em dois a variável "varD" e consequentemente obter os seus valores em "dicD(srtD)".

    Penso que respondi às suas dúvidas.

    Um grande abraço

    M_A_L

    domingo, 18 de maio de 2014 02:42
  • Obrigado pela resposta.

    Pela forma que está estruturando os dados, desconfio que uma tabela dinâmica cairá muito bem para o seu caso. Você conhece tabelas dinâmicas? Sugiro que você experimente-as.

    De vez em quando, gastamos muita energia tentando resolver um problema de Excel utilizando objetos avançados de VBA, como dicionários, sendo que o que desejamos pode ser alcançado através das ferramentas nativas do Excel.

    Veja um exemplo:


    Felipe Costa Gualberto - http://www.ambienteoffice.com.br

    domingo, 18 de maio de 2014 19:49
    Moderador
  • Boa tarde, Felipe.

    Não conheço o funcionamento das Tabelas Dinâmicas, mas estive a pesquisar e tentar inserir uma numa cópia do meu ficheiro e não me deu qualquer resultado, provavelmente por desconhecer o seu funcionamento.

    A verdade é que, na tabela que introduzi na folha, não me foram apresentados resultados satisfatórios, pois não efetuou qualquer contagem.

    Como disse, nunca tentei utilizar as tabelas dinâmicas e provavelmente não terei inserido a tabela da forma correta.

    Sei-lhe dizer no entanto que a coluna "D" contem as letras F e M, consoante o sexo e a coluna "T" contem as strings "I", "II", "Pre-Diabetes" e "Diab.Gestacional". Nenhuma contem números. Aliás, se ainda não eliminou o E-Mail, tem um exemplo que lhe mandei da outra vez.

    Tentei na tabela dinamica, selecionar apenas estas duas colunas e não me apresentou totais.

    De qualquer forma, seria também dificil para mim, (talvez até mais difícil), fazer a tabela dinâmica interagir com o userform para apresentação de resultados, percentagens e gráficos.

    A forma de apresentar os resultados no userform, parece-me que não resultaria em percentagens reais, pois o numero total de doentes, com ou sem doenças fazem parte de um todo, valor que nos permite obter determinadas percentagens.

    Eu sei que a imagem que apresenta é apenas um exemplo e provavelmente pode apresentar todos os resultados, mas será que dá para o fazer?

    Os dados estão escalonados desta forma:

    coluna D ..... COLUNA T

           F..................... --           

          M......................--

          M......................I

          F  ...........Pre-Diabetes

          F .................... II

          F.......................II

          F................Diab.Gestacional

    ETC.

    Há no entanto outro fator a considerar. No caso das doenças crónicas, a mesma célula

    pode apresentar o valor "DM-TA" e a tabela não faz o "split" das duas doenças contando

    um para cada, "D.Mellitus" e "T. Arterial", criando ao inves disso uma nova unidade de contagem.

    Estou correto no meu raciocinio?

    Dá para fazer isso na tabela Dinâmica?

    De qualquer forma eu continuo a pensar que a rotina que escreveu e que se encontra em cima, embora alterada na tentativa de me apresentar outros resultados, continua a ser o ideal.

    Afinal, foi escrita por FELIPE GUALBERTO, que, citando as palavras de um outro utilizador deste forum perante uma resposta que postou, "Ganhou um fã incondicional".

    Cumprimentos

    M_A_L





    • Editado M_A_S_L segunda-feira, 19 de maio de 2014 17:06
    segunda-feira, 19 de maio de 2014 16:39
  • Acho que está correto sim. Vamos fazer assim: disponibilize uma pasta de trabalho de exemplo (com dados fictícios) para download para sugerirmos uma solução.

    Felipe Costa Gualberto - http://www.ambienteoffice.com.br

    segunda-feira, 19 de maio de 2014 21:42
    Moderador
  • Boa noite Felipe.

    Peço desculpa pela demora.

    Ficheiro disponível em:

    https://onedrive.live.com/redir?resid=alterado-alterado-alterado=!AIMQ4hyO5nYn4kc&ithint=file%2c.xlsm

    Depois de abrir a aplicação, clique em "Registos Estatísticos". No separador da recolha de informação, clique em "estatísticas" e as rotinas que precisam de ajuste, encontram-se nos "CommandButton" das varias páginas do multipage.

    Bastará no entanto a correção de 1, o resto é só copiar de uns para os outros.

    Se não fôr pedir muito, no form da recolha de informação, se selecionar o botão de Opção "Diabetes" e clicar em inserir, abre-lhe um novo form em que existem dois botões a negro, chamando-se um deles "lista de medicamentos".

    Ao clicar, se reparar, demora imenso tempo a abrir. Será que consegue disponibilizar-me um código mais eficiente do que o que tenho associado ao botão. De notar no entanto que todas os itens têm que ser listados, quer tenham o mesmo nome ou não, pois embora tenham a mesma designação, têm depois dosagens diferentes ou embalagens diferentes, ou até fabricantes diferentes. Todas as linhas devem ser listadas conforme lista da folha "MEDICAM".

    Um enorme agradecimento por tudo o que puder ou não puder fazer.

    Um grande abraço.

    M_A_L



    • Editado M_A_S_L quarta-feira, 4 de junho de 2014 22:18
    terça-feira, 20 de maio de 2014 22:12
  • Manuel, estou um pouco perdido na pasta de trabalho. Há muita informação. No fim de semana vou olhar com mais calma.

    Felipe Costa Gualberto - http://www.ambienteoffice.com.br


    sexta-feira, 23 de maio de 2014 01:41
    Moderador
  • Bom dia, Felipe.

    Sem problema. Um agradecimento enorme pela sua paciência. Se necessitar de algum esclarecimento, disponha.

    Cumprimentos

    M_A_L


    M_A_L

    sexta-feira, 23 de maio de 2014 11:17
  • Boa tarde, Felipe.

    Estava aqui a pensar com os meus botões, sobre a rotina que preciso e julgo que o problema se poderá resolver, se pegarmos no código do post inicial e colocarmos as condições da seguinte forma:

    If wks.Range("T" & TpDIABRow) <> "--" And wks.Range("T" & TpDIABRow) <> "" Then

    If VBA.Len(strD) > 0 Then .........Aqui é criada uma variável para os totais de "Diabéticos"

    '---inserindo nova condição...

    If wks.Range("T" & TpDIABRow)="I" then

    ............criar nova variável para Tipo I

    else

    ............criar nova variável para Tipo II

    end if

    Apenas não sei depois como colocar em linhas diferentes da Listbox as diferentes variáveis.

    Será possível colocar o código desta forma?

      ListBox14.ColumnWidths = "120;105;90;10"
          .List(.ListCount 0, 0) = varD
          .List(.ListCount 0, 1) = dicD(varD)

    Isto é, em vêz de Listcount -1,0, colocar Listcount 0,0 ?

    Cumprimentos.

    M_A_L


    M_A_L

    sexta-feira, 30 de maio de 2014 17:11
  • Olá Manuel,

    Esta postagem tomou uma proporção muito grande. Para resolver esse problema, gastarei boa parte do tempo entendendo a postagem e o que se passa pela pasta de trabalho/código até, finalmente, eu entender a dúvida de Excel.

    Já não estou mais conseguindo acompanhar a sua necessidade. Não seria possível você fazer uma pasta de trabalho pequena com um exemplo minimalista que explica resumidamente o que deseja que o algoritmo faça?


    Felipe Costa Gualberto - http://www.ambienteoffice.com.br

    sábado, 31 de maio de 2014 01:18
    Moderador
  • Boa noite, Felipe.

    Vou tentar fazer um arquivo pequeno eliminando códigos desnecessários.

    Mas, em jeito de explicação ...

    Todos os valores são registados na folha de cálculo, através de Userforms.

    Tal como digo no primeiro post, com a rotina que me facultou e que incluí na primeira postagem, consigo obter os valores previamente gravados na folha de cálculo. Estes valores são depois exibidos numa Listbox e apresentados sob a forma de gráficos.

    As variáveis de cada coluna da folha de cálculo podem ser várias e com a rotina do 1º post, ao clicar no botão "TIPO DE DIABETES" do userform, cujos valores se encontram na coluna "T" da folha de cálculo, consigo obter os seguintes dados:

    ---Listbox1:

    tipo I---90

    tipo II--10

    ---Listbox2:

    Fem---60

    Masc--40

    O pretendido seria:

    ---Listbox1:

    tipo I---90

    tipo II--10

    ---Listbox2:

    »»Tipo I

    ----------Fem---70

    ----------Masc--20

    »»Tipo II

    ----------Fem---3

    ----------Masc--7

    Daí a colocação do último post, pois se a rotina faz a separação por "M" ou "F", se na rotina se inserir uma filtragem diferente dos dados penso que podem obter-se os dados pretendidos.

    Neste momento, essa filtragem está a ser feita da seguinte forma:

    If wks.Range("T" & TpDIABRow) <> "--" And wks.Range("T" & TpDIABRow) <> "" Then
        If VBA.Len(strD) > 0 and wks.Range("D" & TpDIABRow) = "M" Then

    Se a filtragem passar a ser feita assim:

    If wks.Range("T" & TpDIABRow) <> "--" And wks.Range("T" & TpDIABRow) <> "" Then If VBA.Len(strD) > 0 and wks.Range("T" & TpDIABRow)="I" and wks.Range("D" & TpDIABRow)="M" then

    -------- linhas de código para a variável tipoI-M

    elseif VBA.Len(strD) > 0 and wks.Range("T" & TpDIABRow)="I" and wks.Range("D" & TpDIABRow)="F" then

    -------- linhas de código para a variável tipoI-F

    As instruções elseif, repetir-se-iam para as oito variáveis.

    Penso que irá funcionar, apenas vai ficar um código muito extenso.

    Cumprimentos

    M_A_L


    M_A_L


    • Editado M_A_S_L domingo, 1 de junho de 2014 02:39
    domingo, 1 de junho de 2014 02:25
  • Como faço para acessar essa parte do formulário "Tipo de Diabetes"? Não estou conseguindo chegar a esse botão.

    Felipe Costa Gualberto - http://www.ambienteoffice.com.br

    domingo, 1 de junho de 2014 14:44
    Moderador
  • Bom dia, Felipe.

    Desculpe a demora, mas estive ausente de casa e sem acesso ao computador.

    Para acessar esse botão, no formulário inicial, tem um botão cujo nome é "DADOS ESTATÍSTICOS". Ao clicar, abre um novo formulário, com vários botões decorados com Bitmaps. Na fila inferior, tem um botão com o nome "DIABETES". Clicando, abre o separador do multipage que contém Diabetes incluindo esse botão no lado superior ligeiramente à esquerda.

    No programador de VBA, é o Userform1_ESTATISTICAS, Pag. 9 do multipage.

    Estou a tentar preparar uma pasta mais leve, retirando o que não é importante para a verificação do código, mas não está fácil, pois como tem muita coisa encadeada, há sempre um erro por falta de um objeto ou uma variável que não se encontra declarada por eliminação de certas partes de códigos.

    Mas...estou a tentar.

    Um abraço.

    M_A_L


    M_A_L

    terça-feira, 3 de junho de 2014 08:15
  • Comentarei vários aspectos que me vieram em mente em minha resposta.

    Você já deve saber disso, mas tome cuidado ao compartilhar informação na internet. Muitas vezes pessoas enviam pastas de trabalho com dados reais, e, dependendo do tipo de atividade ou da empresa em que se trabalha, isso pode causar um problema de segurança da informação já que no momento em que se faz isso, o mundo inteiro pode abrir suas planilhas, ler o nome e exames de seus pacientes.

    Além disso, ele poderá copiar todo seu sistema e ideias para a empresa dele, o qual imagino que você tenha gastado incontáveis horas para fazer.

    É por isso que normalmente peço para pessoas enviarem exemplos "minimalistas".

    ---

    Realmente é ruim/difícil de se fazer testes quando tem muita coisa encadeada.

    Nesse caso, eu adaptei temporariamente a inicialização do formulário para algo como mostrado abaixo e testar com eficiência:

    Private Sub UserForm_Initialize()
    Dim CHK As Integer
    CheckBox1.Locked = True
    CheckBox23.Locked = True
    
    For CHK = 3 To 8
      Me.Controls("CheckBox" & CHK).Locked = True
    Next CHK
    'MultiPage1.Value = 0
    
        ListBox6.Visible = False: ListBox7.Visible = False: ListBox8.Visible = False
        Label205.Visible = False: Label206.Visible = False
        Label207.Visible = False: Label208.Visible = False
    
      'Para testes
      CommandButton32_Click
    End Sub

    Ou seja: contornei a obrigatoriedade de se iniciar na primeira página do controle multipágina e simulei um clique no botão 'Neurovasculares'.

    Obviamente, eu voltaria o código ao normal após concluir os testes.

    ---

    A sua pasta de trabalho está muito grande, mas isso você já sabe. Só o formulário que estamos discutindo em questão possui 3000 linhas! Você está usando formulários demais e Excel de menos.

    Falar é muito fácil, mas pode ser que já esteja na hora de você dar uma estudada em Access e migrar tudo para o Access. Mas tudo bem, vale a pena, depois de tudo, fazer esse sistema rodar 100% no Excel. E claro, parabéns, porque não é qualquer um que chega nesse nível de complexidade em VBA.

    ---

    Indente seu código. Verá que assim, consegue melhorar a leitura: http://www.ambienteoffice.com.br/officevba/indentacao/

    Obviamente, você não vai parar agora para indentar todo seu código, já que ele está muito extenso (3000 linhas). Existem programas que indetam código automaticamente. Fiz um que lançarei em breve, mas, para agilizar, indentei o código do seu formulário e salvei aqui: https://onedrive.live.com/redir?resid=FB206A2D510E0661!22181&authkey=!AJZP5jIg1rKAleI&ithint=file%2c.txt

    Substitua o código do seu formulário pelo que está nesse link.

    ---

    Não use chamadas de função como VBA.Mid e VBA.Split ou VBA.Left, etc. Dificulta a leitura do código. Use simplesmente Mid, Split ou Left. Para acertar seu projeto, substituei o termo VBA. (inclua o ponto) por nada. A substituição tem que se dá no nível de todo o seu projeto.

    ---

    A seguir, responderei sua questão, para que esta postagem não fique muito grande.


    Felipe Costa Gualberto - http://www.ambienteoffice.com.br




    terça-feira, 3 de junho de 2014 23:58
    Moderador
  • Acredito que seu problema possa ser resolvido com bastante facilidade, por esse caminho:

    Private Sub CommandButton32_Click()
      Dim wks As Excel.Worksheet
      
      Set wks = ThisWorkbook.Worksheets("REGISTOS")
      With wks
        'Tipo 1, Feminino
        MsgBox WorksheetFunction.CountIfs(.Columns("T"), "I", .Columns("D"), "F")
      
        'Tipo 1, Masculino
        MsgBox WorksheetFunction.CountIfs(.Columns("T"), "I", .Columns("D"), "M")
      
        'Tipo 2, Feminino
        MsgBox WorksheetFunction.CountIfs(.Columns("T"), "II", .Columns("D"), "F")
      
        'Tipo 2, Masculino
        MsgBox WorksheetFunction.CountIfs(.Columns("T"), "II", .Columns("D"), "M")
      End With
    End Sub

    Entendeu como funciona a função CountIfs?

    Valor = CountIf([coluna1],[critério1],[coluna2],[critério2],(...),[colunaN],[critérioN])


    Felipe Costa Gualberto - http://www.ambienteoffice.com.br

    • Marcado como Resposta M_A_S_L domingo, 8 de junho de 2014 00:42
    quarta-feira, 4 de junho de 2014 00:46
    Moderador
  • Boa tarde Felipe.

    Obrigado pela resposta. Vou tentar inserir essas linhas de código e ver como funciona.

    Logo que possa, dou um feedback. Caso necessite da pasta de trabalho bastante mais leve, está disponível no link:

    https://onedrive.live.com/redir?resid=EEE3B7A606CED5BF!496&authkey=!AMyLR4AWH2twvUg&ithint=folder%2c.xlsm

    Vou pesquisar um pouco sobre essa função pois nunca a utilizei em nenhum código.

    Até para saber mais ou menos do que a função é capaz.

    Um grande obrigado pelo seu interesse.

    Assim que tiver novidades, posto o resultado, mas acredito que funcione a 100%, à semelhança de todas as ajudas que me tem dado.

    Mais uma vez, um enorme agradecimento de um incondicional Fã.

    Abraços

    M_A_L


    M_A_L

    • Marcado como Resposta M_A_S_L domingo, 8 de junho de 2014 00:42
    • Não Marcado como Resposta M_A_S_L domingo, 8 de junho de 2014 00:42
    quarta-feira, 4 de junho de 2014 17:09
  • Felipe.

    Na resposta anterior, reportei-me apenas ao seu último post, porque quando vi a sua resposta fui direto ao último post e não percebi que havia outro comentário antes. Pelo facto peço desculpas.

    Agradeço todos os seus avisos e agradeço o elogio, no entanto, relativamente a este último cabe-me dizer que, os códigos utilizados com maior complexidade, têm a sua assinatura. Embora haja outros que resultaram de pesquisa sobre o assunto. Também tem códigos de outros amigos que gentilmente me deram a sua ajuda num forum português e para uma outra aplicação anterior a esta, mas que encaixam na perfeição aqui. Em VBA, nunca tive qualquer formação de forma que se torna uma tarefa complicada sem ajuda. 

    Nunca pretendi no entanto que fizessem o trabalho todo para mim como vi em vários foruns de discussão e esclarecimento de dúvidas. Apenas me sentia impossibilitado de contornar certas situações devido à ausência de formação no assunto pelo que apenas pedia ajuda depois de esgotar as possibilidades de resolução pelos meus próprios meios.

    Posto este esclarecimento e face aos seus avisos, quando disponibilizei a pasta coloquei especificamente o seu endereço de e-mail de forma a permitir apenas a visualização e edição por si. Claro que um entendido na matéria pode chegar lá, mas confiei na maior sabedoria da Microsoft.

    De qualquer forma quando disponibilizei a pasta, retirei cerca de 850 nomes e os nomes disponibilizados foram truncados de forma que não são nomes completos nem corretos.

    Dados de empresa, também não tem mas a ideia, essa sim, pode ser utilizada por outros.

    A indentação, desde o seu anterior aviso sobre esta matéria e que me levou ao seu site, mais ou menos tem sido feita, salvo quando são códigos não indentados transpostos de um ponto para o outro, no entanto, tal com diz no seu post, é já uma fase demasiado avançada para rever todo o código. Mas será feita a seu tempo e as vantagens da indentação são óbvias e mais óbvias se tornam quando existem sucessivos ciclos For-Next ou If-Elseif-End If.

    Transferi o código Indentado que cedeu, no entanto vou ter que ter cuidado, pois o código já possui outras linhas de código intercaladas e que não podem ser eliminadas, caso contrário vai haver objectos que deixarão de funcionar.

    Quanto à utilização do prefixo VBA nas funções Mid, Split ou Left, como sabe, não tenho formação para as utilizar por livre iniciativa. Apenas utilizei o código que me cedeu num post anterior e para mim, como funciona na perfeição, é suficiente. Mas no futuro, vou considerar a sua observação.

    Um enorme agradecimento.

    M_A_L


    M_A_L

    quarta-feira, 4 de junho de 2014 22:16
  • Manuel,

    Parabéns, você está usando os fóruns e se desenvolvendo em VBA corretamente. Logo, estará dominando o Excel e o VBA muito bem.

    Aguardo retorno de seus testes com o código que sugeri.


    Felipe Costa Gualberto - http://www.ambienteoffice.com.br

    quinta-feira, 5 de junho de 2014 00:37
    Moderador
  • Felipe.

    Inserindo o código, como o apresentou, os resultados são apresentados como era de esperar numa Caixa de Mensagens.

    No entanto, mesmo atribuindo variáveis à instrução COUNTIFS e tentando carregar os valores na listbox, não consigo que os valores me sejam apresentados na listbox14 ou listbox16, para que possam ser transpostos para a folha, de forma a poder elaborar o gráfico.

    Existe alguma sintaxe especial para este caso?

    É que não consigo encontrar códigos que se encaixem porque o gráfico deverá apresentar os dados desta forma:

    tipo de diabetes (I, II, Pré ou Gest.).....14.....20,5.....%

    --- M..........7..........50,00..........%

    --- F..........7...........50,00..........%

    Em que os 20,5 % serão a percentagem de diabéticos, por exemplo do tipo I, no total de diabéticos e os 50% serão a percentagem de Masc ou Fem dentro do Tipo I.

    Quando chegar a casa, ainda vou fazer novas tentativas, mas ponho dúvidas que os meus conhecimentos me deixem chegar lá.

    Cumprimentos

    M_A_L


    M_A_L

    quinta-feira, 5 de junho de 2014 15:52
  • Private Sub CommandButton32_Click()
      Dim wks As Excel.Worksheet
      Dim dblFem1 As Double
      Dim dblMas1 As Double
      Dim dblFem2 As Double
      Dim dblMas2 As Double
      
      Set wks = ThisWorkbook.Worksheets("REGISTOS")
      With wks
        dblFem1 = WorksheetFunction.CountIfs(.Columns("T"), "I", .Columns("D"), "F")
        dblFem2 = WorksheetFunction.CountIfs(.Columns("T"), "II", .Columns("D"), "M")
        dblMas1 = WorksheetFunction.CountIfs(.Columns("T"), "I", .Columns("D"), "F")
        dblMas2 = WorksheetFunction.CountIfs(.Columns("T"), "II", .Columns("D"), "M")
      End With
      
      With ListBox14
        .AddItem
        .List(0, 0) = "F"
        .List(0, 1) = "I"
        .List(0, 2) = dblFem1
      
        .AddItem
        .List(1, 0) = "M"
        .List(1, 1) = "I"
        .List(1, 2) = dblMas1
      
        .AddItem
        .List(2, 0) = "F"
        .List(2, 1) = "II"
        .List(2, 2) = dblFem2
      
        .AddItem
        .List(3, 0) = "M"
        .List(3, 1) = "II"
        .List(3, 2) = dblMas2
      End With
    End Sub


    Felipe Costa Gualberto - http://www.ambienteoffice.com.br

    • Marcado como Resposta M_A_S_L domingo, 8 de junho de 2014 00:40
    sexta-feira, 6 de junho de 2014 01:04
    Moderador
  • Boa tarde, Felipe.

    Não tenho palavras para agradecer sua atenção e empenho.

    Logo à noite, quando chegar a casa vou tentar inserir as linhas de código e testar o seu funcionamento.

    Por antecipação no entanto, Mil e Um agradecimentos.

    Um abraço.

    M_A_L


    M_A_L


    • Editado M_A_S_L sábado, 7 de junho de 2014 23:58
    sexta-feira, 6 de junho de 2014 13:04
  • Olá Felipe, boa noite.

    Depois de ter dados muitas voltas com o seu código, no sentido de apresentar os dados da forma que mais me convinha, acabei por obter a solução possível.

    Como sabe, tenho duas listbox a fazer a apresentação dos dados. Listbox14 e Listbox16.

    Continuo a usar o código que me facultou e com o qual abri este tópico, para obtenção das varáveis "Tipo de Diabetes" e sua apresentação na Listbox14. Acrescentei depois o código que me facultou no seu último post, ligeiramente alterado e de forma a serem exibidos na Listbox16, acrescentando também uma linha para obtenção de percentagens.

    Tentei fazer aparecer os dados na Listbox16, apenas da variável clicada na listbox14, criando o evento Listbox_click, mas não consegui a correta referência ao item selecionado na listbox, na coluna 1. Saberia como fazê-lo se a listbox tivesse apenas uma coluna. Neste caso com Quatro colunas não consegui.

    Para todos os efeitos, nos casos em que necessito de gráficos, esta foi a solução possível. 

    Então o código ficou assim:

    Private Sub CommandButton32_Click()
    
    ListBox14.Clear: ListBox16.Clear
    Label298.Caption = ""
    Label299.Caption = ""
    Label283.Caption = "TIPO DIABETES"
    Label305.Caption = "SEXO"
    Label293.Caption = "PACIENTES COM DIABETES"
    Label295.Caption = ""
    
        Const cstrColDIAB As String = "T"
        Const cstrColDIABSX As String = "D"
        
    Dim ttvarD As Integer, ttvarM As Integer, ttvarF As Integer
    Dim TpDIABRow, TpDIABlast As Long, TpDIABlastSX As Long
    Dim wks As Excel.Worksheet
    Dim dicD As Object, SXdic As Object ' Scripting.Dictionary
    Dim varD, varM As Variant, varF As Variant
    Dim strD As String, astrD() As String
    Dim strM As String, strF As String, astrM() As String, astrF() As String
    Dim FEM1 As Variant, FEM2 As Variant
    Dim MAS1 As Variant, MAS2 As Variant
    Dim PREM As Variant, PREF As Variant, GEST As Variant
      
      Set dicD = CreateObject("Scripting.Dictionary")
      Set SXdic = CreateObject("Scripting.Dictionary")
      Set wks = ThisWorkbook.Worksheets("REGISTOS")
      
    With wks
      TpDIABlast = .Cells(.Rows.Count, cstrColDIAB).End(xlUp).Row
      TpDIABlastSX = .Cells(.Rows.Count, cstrColDIABSX).End(xlUp).Row
      
    For TpDIABRow = 2 To TpDIABlast
        strD = .Cells(TpDIABRow, cstrColDIAB).Value
    
    '===========================================================INSERIR CONDIÇÃO DE BUSCA
    
    If wks.Range("T" & TpDIABRow) <> "--" And wks.Range("T" & TpDIABRow) <> "" Then
    
        If VBA.Len(strD) > 0 Then
        strD = VBA.Mid(strD, 1)
        astrD = VBA.Split(strD, "-")
            For Each varD In astrD
            strD = VBA.CStr(varD)
                If dicD.Exists(strD) Then
                    dicD(strD) = dicD(strD) + 1
                Else
                    dicD.Add strD, 1
                End If
                    ttvarD = ttvarD + 1
    
            Next varD
        End If
    End If
    Next TpDIABRow
    
      With Me.ListBox14
        .ColumnCount = 4
        For Each varD In dicD.Keys
          .AddItem
          ListBox14.ColumnWidths = "120;105;90;10"
          .List(.ListCount - 1, 0) = varD
          .List(.ListCount - 1, 1) = dicD(varD)
          .List(.ListCount - 1, 2) = Format((dicD(varD) * 100) / ttvarD, "0.00")
          .List(.ListCount - 1, 3) = " %"
        Next varD
        
      End With
    '============================================================ BUSCA POR SEXO.
    
    FEM1 = WorksheetFunction.CountIfs(.Columns("T"), "I", .Columns("D"), "F")
    FEM2 = WorksheetFunction.CountIfs(.Columns("T"), "II", .Columns("D"), "F")
    MAS1 = WorksheetFunction.CountIfs(.Columns("T"), "I", .Columns("D"), "M")
    MAS2 = WorksheetFunction.CountIfs(.Columns("T"), "II", .Columns("D"), "M")
    PREM = WorksheetFunction.CountIfs(.Columns("T"), "Pré-Diabetes", .Columns("D"), "M")
    PREF = WorksheetFunction.CountIfs(.Columns("T"), "Pré-Diabetes", .Columns("D"), "F")
    GEST = WorksheetFunction.CountIfs(.Columns("T"), "Gestacional", .Columns("D"), "F")
    
    
    ListBox16.Clear
      With Me.ListBox16
        .ColumnCount = 4
        ListBox16.ColumnWidths = "120;105;90;10"
              .AddItem
          .List(0, 0) = "Tipo  I -----------------"
          .List(0, 1) = "-----"
          .List(0, 2) = "-----"
          .List(0, 3) = "-----"
              .AddItem
          .List(1, 0) = "M"
          .List(1, 1) = MAS1
          .List(1, 2) = Format((MAS1 * 100) / (FEM1 + MAS1), "0.00")
          .List(1, 3) = " %"
              .AddItem
          .List(2, 0) = "F"
          .List(2, 1) = FEM1
          .List(2, 2) = Format((FEM1 * 100) / (FEM1 + MAS1), "0.00")
          .List(2, 3) = " %"
    
              .AddItem
          .List(3, 0) = "Tipo  II ---------------"
          .List(3, 1) = "-----"
          .List(3, 2) = "-----"
          .List(3, 3) = "-----"
              .AddItem
          .List(4, 0) = "M"
          .List(4, 1) = MAS2
          .List(4, 2) = Format((MAS2 * 100) / (FEM2 + MAS2), "0.00")
          .List(4, 3) = " %"
              .AddItem
          .List(5, 0) = "F"
          .List(5, 1) = FEM2
          .List(5, 2) = Format((FEM2 * 100) / (FEM2 + MAS2), "0.00")
          .List(5, 3) = " %"
    On Error Resume Next
              .AddItem
          .List(6, 0) = "Pré-Dabetes -----------"
          .List(6, 1) = "-----"
          .List(6, 2) = "-----"
          .List(6, 3) = "-----"
              .AddItem
          .List(7, 0) = "M"
          .List(7, 1) = PREM
          .List(7, 2) = Format((PREM * 100) / (PREF + PREM), "0.00")
          .List(7, 3) = " %"
              .AddItem
          .List(8, 0) = "F"
          .List(8, 1) = PREF
          .List(8, 2) = Format((PREF * 100) / (PREF + PREM), "0.00")
          .List(8, 3) = " %"
      
     On Error Resume Next
              .AddItem
          .List(9, 0) = "Gestacional -----------"
          .List(9, 1) = "-----"
          .List(9, 2) = "-----"
          .List(9, 3) = "-----"
              .AddItem
          .List(10, 0) = "F"
          .List(10, 1) = GEST
          .List(10, 2) = Format((GEST * 100) / (GEST), "0.00")
          .List(10, 3) = " %"
      
     
    End With
    Label294.Caption = ttvarD
    Label297.Caption = TpDIABlast - 1
    'Label298.Caption = SXdic(strM)
    'Label299.Caption = ttvarM - SXdic(strM)
    Label295.Caption = Format((Label294.Caption * 100) / Label297.Caption, "0.00")
    End With
    End Sub
    

    Felipe, um agradecimento do tamanho do continente Sul-Americano.

    Desejo-lhe a melhor sorte do mundo.

    M_A_L


    M_A_L

    domingo, 8 de junho de 2014 00:39
  • Parabéns pelo código, Manuel! Grande abraço e muita luz no seu desenvolvimento no Excel/VBA.

    Quando tiver mais dúvidas, volte a postar.


    Felipe Costa Gualberto - http://www.ambienteoffice.com.br

    domingo, 8 de junho de 2014 01:52
    Moderador
  • Os parabéns, tem que ir inteirinhos para si e para este forum.

    Um obrigado muito especial pela ajuda e ensinamentos que de forma altroísta me facultou.

    Obrigado

    M_A_L


    M_A_L

    domingo, 8 de junho de 2014 21:21