Veja nessa dica como realizar um questionário de múltipla escolha em um UserForm (formulário de usuário) com o VBA Excel.
Essa dica ensina a alterar as propriedades de uma planilha dinamicamente (por código) e utilizar as informações localizadas na folha. O pré-requisito é a compreensão dos blocos com With e/ou End With. O banco de dados (perguntas/respostas) para múltipla escolha já foi preparado para você, nesse arquivo (em francês) a ser baixado gratuitamente.
Para começar, crie um UserForm (formulário de usuário) com uma etiqueta, um Frame (quadro) contendo um OptionButton 3 (Botão opção 3) e um CommandButton (Botão de comando). Se você não estiver familiarizado com a caixa de ferramentas, dê uma olhada nesta dica.
Não altere nenhuma das propriedades (tamanho, nome, título, etc.) desses controles.
Limite-se a colocar e alinhar os três OptionButtons, e você obterá isto:
Agora, vamos ter que alternar para o modo de código, seja clicando duas vezes na parte inferior do UserForm, seja clicando com o botão direito no Código. Duas linhas aparecerão:
Private Sub UserForm_Click() End Sub
No início do UserForm, quero obter a seguinte configuração inicial: ter um texto que indique ao usuário que, para começar, ele deverá clicar no botão, não ver os botões de opção aparecerem (já que a múltipla escolha ainda não começou) e obter um botão que diz para começar o teste.
Também será preciso ajustar para cada controle as margens esquerda e superior, a largura, a altura e o texto. Durante o 'tempo de vida' do nosso UserForm, talvez tenhamos que lembrar dessa configuração inicial dos controles. Assim, vamos criar um procedimento reservado para esse caso no nosso módulo de código do UserForm. Procedimento este que poderemos usar quando quisermos.
Copie e cole esse código no módulo de código do UserForm:
Private Sub Config_Inicial_Controles() 'Se refere ao objeto0 : UserForm1 With UserForm1 .Width = 350 'largura .Caption = "QCM" 'título 'se refere ao objeto Label1 do UserForm1 With .Label1 .Caption = "Para começar, clique no botão: COMECE O TESTE” 'texto a ser exibido .Left = 5 'margem esquerda em relação à borda esquerda do UserForm .Top = 5 'margem superior em relação à borda superior do UserForm .Width = UserForm1.Width - 15 'largura .Height = 50 'altura End With With .Frame1 .Visible = False 'deixa invisível o frame E seu conteúdo .Caption = "Possíveis respostas: " .Left = 5 'margem esquerda em relação à borda esquerda do UserForm .Top = Label1.Top + Label1.Height + 5 'margem superior em relação à borda inferior da Etiqueta .Width = UserForm1.Width - 15 'largura .Height = 90 With .OptionButton1 .Caption = "" .Left = 5 'margem esquerda em relação à borda do Frame .Top = 5 'margem superior em relação à borda superior do Frame .Width = Frame1.Width - 15 .Height = 20 End With With .OptionButton2 .Caption = "" .Left = 5 'margem esquerda em relação à borda esquerda do Frame .Top = OptionButton1.Top + OptionButton1.Height + 5 'margem superior em relação à borda inferior da OptionButton1 .Width = Frame1.Width - 15 .Height = 20 End With With .OptionButton3 .Caption = "" .Left = 5 'margem esquerda em relação à borda esquerda do Frame .Top = OptionButton2.Top + OptionButton2.Height + 5 'margem superior em relação à borda inferior da OptionButton2 .Width = Frame1.Width - 15 .Height = 20 End With End With With .CommandButton1 .Caption = "COMECE O TESTE" .Left = 5 .Top = Frame1.Top + Frame1.Height + 5 'margem superior em relação à borda inferior do Frame .Width = UserForm1.Width - 15 .Height = 30 End With .Height = .CommandButton1.Top + .CommandButton1.Height + 30 'altura do UserForm de acordo com a altura dos controles End With End Sub
Até aqui, nada de especial a ser explicado. As propriedades são indicadas nos comentários. Essa imagem mostra apenas o método de posicionamento dos controles, uns em relação aos outros:
Agora, vamos ter que usar esta Sub antes da exibição do UserForm (formulário de usuário). Para isso, podemos usar, a nosso critério, seja o evento Inicialize seja o evento Activate do UserForm. Aqui, vamos escolher o Inicialize. No menu Geral, escolha UserForm e no menu Eventos, escolha Inicialize. Você obterá estas linhas adicionais de código:
Private Sub UserForm_Click() End Sub Private Sub UserForm_Initialize() End Sub
Observação: já que o evento “Clique” não é mais necessário, você poderá remover as linhas relacionadas a ele.
Para chamar um procedimento depois de outro, eu costumo usar o Call (Chamada). Isso não é obrigatório, mas acho que é mais explícito. Portanto, no nosso evento Inicialize, chamemos a nossa Sub Config_Inicial_Controles:
Private Sub UserForm_Initialize() Call Config_Initiale_Controles End Sub
Você pode testar (F5), alterando a propriedade visível do quadro (True/False - Verdadeiro/falso) para ver o resultado.
De acordo com a nossa escolha inicial, a etiqueta vai ter a pergunta e os botões de opção, as respostas, respectivamente:
OptionButton1: respostas da coluna B,
OptionButton2: respostas da coluna C,
OptionButton3: respostas da coluna D.
Já que nós conhecemos as colunas, agora teremos que procurar a informação, os números de linha. Para isso, vamos criar uma variável nível de módulo (cujo tempo de vida = duração da exibição do UserForm). No topo (no cabeçalho e antes de qualquer declaração de Sub), escreva:
Dim Linha As Byte
Agora, teremos que criar um procedimento para procurar a informação na célula: Linha, Coluna de OptionButton e incluir esta informação (resposta) na Caption (subtítulo) do OptionButton em questão. Sob o seu procedimento Config_Inicial_Controles (depois do seu End Sub), copie e cole o seguinte código:
Private Sub Perguntas_Respostas() With Sheets("Plan1") 'Pergunta 'modificamos a propriedade Caption da etiqueta 'com o conteúdo da coluna A (Perguntas) Label1.Caption = .Range("A" & Linha).Value 'respostas 'verificamos que a opção esteja desmarcada OptionButton1.Value = False 'completamos sua propriedade Caption com o conteúdo da célula em questão OptionButton1.Caption = .Range("B" & Linha).Value 'Idem para as outras 2 OptionButton2.Value = False OptionButton2.Caption = .Range("C" & Linha).Value OptionButton3.Value = False OptionButton3.Caption = .Range("D" & Linha).Value End With End Sub
As explicações necessárias são dadas nos comentários do código. Para testar, teremos de lidar com o evento Click () no CommandButton. Para isso, selecione CommandButton1 no menu Geral. Por padrão, o VBA te coloca no evento Click() por estas linhas:
Private Sub CommandButton1_Click() End Sub
Veja abaixo, o comentário do código desse evento:
Private Sub CommandButton1_Click() 'primeiro clique, no botão, consultamos sua propriedade Caption 'se "COMECE O TESTE" então If CommandButton1.Caption = "COMECE O TESTE" Then 'modificamos a propriedade Caption do botão para os próximos cliques CommandButton1.Caption = "VALIDAR" 'a primeira pergunta sendo linha 2 na planilha: Linha = 2 'chamamos o procedimento de exibição da pergunta Call Perguntas_Respostas 'Exibição do Frame (que estava invisível até agora) Frame1.Visible = True Else 'caso dos cliques seguintes (a partir do segundo) 'passamos para a linha seguinte Linha = Linha + 1 'chamamos o procedimento da pergunta Call Perguntas_Respostas End If End Sub
Agora você pode testá-lo, o seu UserForm exibe corretamente as perguntas e respostas da sua tabela Plan1 em seus controles.
O objetivo dessa dica não é fazer uma múltipla escolha, mas entender como carregar informações da planilha para o UserForm. No entanto, o trabalho estando quase completo, seria uma pena não finalizá-lo.
A preocupação agora será a de contar os pontos, já que podemos pular uma pergunta sem responde-la. Para fazê-lo, vamos criar uma segunda variável de nível de módulo, marcando sob Dim Linha As Byte:
Dim Pontos As Byte
Em seguida, vamos criar uma Function (Função) para reenviar 1 se a resposta for correta, caso contrário, 0. Para isso, basta verificar qual opção foi escolhida e ver se a célula relativa está amarela (6) ou:
Private Function Correção() As Byte 'Valor padrão Correção = 0 With Sheets("Plan1") 'se a propriedade Value da optionbutton = true significa 'que você desmarcou esta resposta 'então verificamos, na planilha, se a célula coluna B está amarela na linha em questão If OptionButton1.Value = True And .Range("B" & Linha).Interior.ColorIndex = 6 Then Correção = 1 'se sim, correção retorna 1 'Idem ElseIf OptionButton2.Value = True And .Range("C" & Linha).Interior.ColorIndex = 6 Then Correção = 1 ElseIf OptionButton3.Value = True And .Range("D" & Linha).Interior.ColorIndex = 6 Then 'Idem Correção = 1 End If End With End Function
Para terminar, vamos alterar o código do botão assim:
Private Sub CommandButton1_Click() 'primeiro clique, no botão, consultamos sua propriedade Caption 'se "COMECE O TESTE" Então If CommandButton1.Caption = "COMECE O TESTE" Then 'modificamos a propriedade Caption do botão para os próximos cliques CommandButton1.Caption = "VALIDAR" 'a primeira pergunta sendo a linha 2 na planilha: Linha = 2 Pontos = 0 'chamamos o procedimento de exibição da pergunta Call Perguntas_Respostas 'Exibição do Frame (que estava invisível até agora) Frame1.Visible = True Else 'caso dos cliques seguintes (a partir do segundo) 'conte os pontos Pontos = Pontos + Correção 'passamos para a linha seguinte Linha = Linha + 1 'teste se última pergunta If Linha = 22 Then 'exibição do número de pontos MsgBox “você obteve: " & Pontos & " sobre 20." 'Colocar em 0 da configuração => volta ao início Call Config_Inicial_Controles 'fechamos o procedimento para não acionar o Call Perguntas_Respostas Exit Sub End If 'chamamos o procedimento de exibição da pergunta Call Perguntas_Respostas End If End Sub
.
Agora temos um código funcional. Só falta testar o seu formulário de usuário e seus conhecimentos.
Só para verificar se tudo está correto:
Option Explicit Private Linha As Byte Private Pontos As Byte Private Sub CommandButton1_Click() 'primeiro clique, no botão, consultamos a sua propriedade Caption 'se "COMENCE O TESTE" Então If CommandButton1.Caption = "COMECE O TESTE" Then 'modificamos a propriedade Caption do botão para os próximos cliques CommandButton1.Caption = "VALIDAR" 'a primeira Pergunta estando na linha 2 da planilha: Linha = 2 Pontos = 0 'chamamos o procedimento de exibição da Pergunta Call Perguntas_Respostas 'Exibição do Frame (que estava invisível até agora) Frame1.Visible = True Else 'caso dos cliques seguintes (a partir do segundo) 'conte os pontos Pontos = Pontos + Correção Passamos para a linha seguinte Linha = Linha + 1 'teste se última Pergunta If Linha = 22 Then 'Exibição do número de pontos MsgBox "Você obteve: " & Pontos & " sobre 20." 'Colocar em 0 da configuração => volta ao início Call Config_Inicial_Controles 'fechamos o procedimento para não acionar o Call Perguntas_Respostas Exit Sub End If 'chamamos o procedimento de exibição da pergunta Call Perguntas_Respostas End If End Sub Private Sub UserForm_Initialize() Call Config_Inicial_Controles End Sub Private Sub Config_Inicial_Controles() 'Refere-se ao objeto: UserForm1 With UserForm1 .Width = 350 'largura .Caption = "QME" 'título 'refere-se ao objeto Label1 do UserForm1 With .Label1 .Caption = "Para começar, clique no botão : COMECE O TESTE" 'texto a ser exibido .Left = 5 'margem esquerda em relação à borda esquerda do UserForm .Top = 5 'margem superior em relação à borda superior do UserForm .Width = UserForm1.Width - 15 'largura .Height = 50 'altura End With With .Frame1 .Visible = False torna 'invisível o frame E seu conteúdo .Caption = "Possíveis respostas: " .Left = 5 'margem esquerda em relação à borda esquerda do UserForm .Top = Label1.Top + Label1.Height + 5 'margem superior em relação à borda inferior da etiqueta .Width = UserForm1.Width - 15 'largura .Height = 90 With .OptionButton1 .Caption = "...................." .Left = 5 'margem esquerda em relação à borda esquerda do Frame .Top = 5 'margem superior em relação à borda superior do Frame .Width = Frame1.Width - 15 .Height = 20 End With With .OptionButton2 .Caption = "...................." .Left = 5 'margem esquerda em relação à borda esquerda do Frame .Top = OptionButton1.Top + OptionButton1.Height + 5 'margem superior em relação à borda inferior da OptionButton1 .Width = Frame1.Width - 15 .Height = 20 End With With .OptionButton3 .Caption = "...................." .Left = 5 'margem esquerda em relação à borda esquerda do Frame .Top = OptionButton2.Top + OptionButton2.Height + 'margem superior em relação à borda inferior da OptionButton2 .Width = Frame1.Width - 15 .Height = 20 End With End With With .CommandButton1 .Caption = "COMECE O TESTE" .Left = 5 .Top = Frame1.Top + Frame1.Height + 5 'margem superior em relação à borda inferior do Frame .Width = UserForm1.Width - 15 .Height = 30 End With .Height = .CommandButton1.Top + .CommandButton1.Height + 30 'altura do UserForm em função da altura dos controles End With End Sub Private Sub Perguntas_Respostas () With Sheets("Feuil1") 'Pergunta 'modificamos a propriedade Caption da etiqueta 'com o conteúdo da coluna A (Perguntas) Label1.Caption = .Range("A" & Linha).Value 'respostas 'verificamos se a opção está desmarcada OptionButton1.Value = False 'completamos sua propriedade Caption com o conteúdo da célula em questão OptionButton1.Caption = .Range("B" & Linha).Value 'Idem para as outras 2 OptionButton2.Value = False OptionButton2.Caption = .Range("C" & Linha).Value OptionButton3.Value = False OptionButton3.Caption = .Range("D" & Linha).Value End With End Sub Private Function Correção() As Byte 'Valor padrão Correção = 0 With Sheets("Plan1") 'se a propriedade Value do optionbutton = true significa 'que você marcou esta respostaa 'então verificamos, na folha, se a célula da coluna B está amarela na linha em questão If OptionButton1.Value = True And .Range("B" & Linha).Interior.ColorIndex = 6 Then Correção = 1 'se sim, correção retorna 1 'Idem ElseIf OptionButton2.Value = True And .Range("C" & Linha).Interior.ColorIndex = 6 Then Correção = 1 ElseIf OptionButton3.Value = True And .Range("D" & Linha).Interior.ColorIndex = 6 Then 'Idem Correção = 1 End If End With End Function
Para finalizar, você pode fazer o download do arquivo completo aqui (em francês).
Foto: © Kelly Sikkema - Unsplash.