NUNCA MAIS PASSE RAIVA POR NÃO CONSEGUIR RESOLVER UM PROBLEMA COM O EXCEL - GARANTIDO!

UNIVERSIDADE DO VBA - Domine o VBA no Excel Criando Sistemas Completos - Passo a Passo - CLIQUE AQUI

Você está em: PrincipalArtigosLivroexc2007ribbon › Capítulo 1 : 11
Quer receber novidades e e-books gratuitos?
« Anterior Δ Página principal ¤ Índice Próxima »
Programando o RibbonX no Excel 2007
Autor: Robert Friedrick Martim
Lição 11 - Exemplos Avançados - Parte 2

Botões especiais: splitButton, toggleButton e checkBox

Um splitButton funciona de forma similar ao menus do tipo popup na versão 2003. Ao acionarmos um splitButton ele nos dará mais opções de comandos o que pode facilitar em muito nossa vida no momento de agruparmos comandos, evitando, assim, o uso excessivo do espaço disponível na Faixa de Opções.

Um toggleButton refere-se ao botão de alternância, isto é dependendo do seu estado (pressionado ou não) um comando é executado.

Um checkBox é uma caixa de checagem a qual podemos clicar para determinar se algo ficará visível ou não, por exemplo.

Crie um novo arquivo nos moldes já definidos e insira o seguinte XML no arquivo (os comentários estão no código):

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
  <ribbon startFromScratch="false">
    <tabs>
      <tab
        id="meuTab"
        label="Minha Guia">

        <group
          id="meuGrupo"
          label="Meu Grupo">

          <!-- Adiciona o boto de alternncia - toggleButton -->

          <toggleButton
            id="btnToggle"
            label="toggleButton"
            image="rob"
            size="large"
            screentip="Autor: Robert Martim"
            onAction="alternado"
            supertip="Clique neste botão para acionar o autor..."/>

          <!-- Adiciona caixa de checagem - checkBox -->
          <checkBox
            id="chkOcultar"
            label="Ocultar grupo Fonte"
            onAction="ocultarGrupoFonte"
            screentip="Ocultar grupo Fonte"
            supertip="Clique nesta caixa para ocultar o grupo Fonte"
            getPressed="reexibirGrupoFonte"/>

          <!-- Adiciona caixa de checagem - checkBox -->
          <checkBox
            id="chkOcultar2"
            label="Ocultar grupo Shapes"
            onAction="ocultarGrupoShapes"
            screentip="Ocultar grupo Shapes"
            supertip="Clique nesta caixa para ocultar o grupo Shapes"
            getPressed="reexibirGrupoShapes"/>
        </group>

        <!-- Adiciona um grupo para adicionarmos o splitButton e respectivos botões -->
        <group
          id="meuGrupo2"
          label="SplitButton">

          <splitButton
            id="splitBtn"
            size="large">

            <button
              id="btn1"
              imageMso="HappyFace"
              label="Sr. HappyFace"
              supertip="Splibutton do Sr. HappyFace"/>

            <menu
              id="splitMenu"
              itemSize="large">
         
              <button
                id="btn2"
                image="rob"
                label="Robert Martim"
                screentip="Foto do autor."
                supertip="Foto do autor narcisista ou falta de uma foto melhor??"/>

              <button
                id="btn3"
                imageMso="InkToolsClose"
                label="Fechar"
                onAction="fechar"
                screentip="Fechar."
                supertip="Utilize este botão para fechar o documento ativo."/>
         
              <button
                id="btn4"
                imageMso="FileStartWorkflow"
                label="Checar compatibilidade"
                onAction="chkCompatbilidade"
                screentip="Checar compatibilidade."
               supertip="Utilize este botão para checar a compatibilidade do documento ativo."/>
             </menu>
           
          </splitButton>
        </group>

      </tab>
    </tabs>
  </ribbon>
</customUI>

Se desejar crie os callbacks e adicione algum código para visualizar o funcionamento:

'Callback for btnToggle onAction
Sub alternado(control As IRibbonControl, pressed As Boolean)
    If Not pressed Then
        MsgBox "O toggleButton não está pressionado...", vbInformation
    Else:
        MsgBox "O toggleButton está pressionado...", vbInformation
    End If
End Sub

'Callback for chkOcultar onAction
Sub ocultarGrupoFonte(control As IRibbonControl, pressed As Boolean)
    If Not pressed Then
        MsgBox "Você acaba de reexibir o grupo Fonte...", vbInformation
    Else:
        MsgBox "Você acaba de ocultar o grupo Fonte...", vbInformation
    End If
End Sub

'Callback for chkOcultar getPressed
Sub reexibirGrupoFonte(control As IRibbonControl, ByRef returnedVal)
End Sub

'Callback for chkOcultar2 onAction
Sub ocultarGrupoShapes(control As IRibbonControl, pressed As Boolean)
    If Not pressed Then
        MsgBox "Você acaba de reexibir o grupo Shapes...", vbInformation
    Else:
        MsgBox "Você acaba de ocultar o grupo Shapes...", vbInformation
    End If
End Sub

'Callback for chkOcultar2 getPressed
Sub reexibirGrupoShapes(control As IRibbonControl, ByRef returnedVal)
End Sub

'Callback for btn3 onAction
Sub fechar(control As IRibbonControl)
End Sub

'Callback for btn4 onAction
Sub chkCompatbilidade(control As IRibbonControl)
    MsgBox "Não sei o que você está checando, mas é completamente incompatível!", vbInformation
End Sub

Finalmente, a sua nova guia será composta conforme mostra a figura abaixo:


Figura 5‑7 Alguns dos botões especiais

Ocultando grupos

Pode haver cenários onde desejamos ocultar grupos, botões ou tabulações, por exemplo. Aqui discutirei a questão da visibilidade de grupos a qual aparece no tópico anterior, mas não possui código algum para execução.

Caso o leitor tenha adquirido o módulo feito a partir da versão Beta 2, praticamente tudo mudou. Embora a estrutura seja basicamente a mesma, existem novos elementos que precisam ser levados em conta para que possamos implementar a solução.

Iniciaremos pela análise o evento onLoad (que é um procedimento - callback) o qual é carregado quando o documento é aberto e que anteriormente não era crítico a solução do problema.

Determinando o callback para o evento “onLoad”

No atributo onLoad, o qual representa um evento durante o carregamento do documento, recebe como valor um determinado procedimento escrito diretamente no XML da interface gráfica.

Logo na abertura do tag para a interface gráfica ficaria como segue:

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="setarRibbon">

O nome do procedimento (callback) pode ser o que o leitor desejar. Note que como tal procedimento é carregado na abertura do documento, ele funciona como um Auto_Open ou Workbook_Open (ou até mesmo uma inicialização de classe).

Antes mesmo de escrevemos o nosso XML, precisaremos adicionar um módulo comum onde o codigo abaixo deve ser entrado (caso o leitor não acompanhe o significado, não se preocupe, pois todo o processo será amalgamado mais adiante e todo o processo fará mais sentido):

'Declaracao do objeto "IRibbonUI" global
Dim ribPersonalizado    As IRibbonUI

Sub setarRibbon(ribbon As IRibbonUI)
'    MsgBox "debug para break"
    Set ribPersonalizado = ribbon
End Sub

Primeiramente, declaramos globalmente o objeto que representará a nossa Faixa de Opções (Ribbon). Dentro do procedimento declarado no atributo onLoad, nós setamos o objeto declarado globalmente no módulo como sendo o ribbon.

A segunda parte importante diz respeito a invalidação do ribbon. Isso será necessário para forçarmos a chamada do procedimento que ocultará/reexibirá o grupo em questão.

Invalidando a chamada do callback (ribbonX.Invalidate)

Na versão Beta 2 era desnecessário invalidar o ribbon, pois o callback era constantemente chamado. Este comportamente era, na verdade, um bug o qual tinha conseqüências relevantes a outras partes de seu código.

Agora, para que o procedimento específico seja chamado precisamos invalidar o ribbon para que o procedimento seja executado. Aqui, o procedimento será executado de acordo com a guia. Como teremos duas guias, quando uma guia for selecionada ela executará o código referente a ela.

Para melhor explicar isso, vejamos o seguinte cenário:

  • Desabilitaremos um grupo sob a guia “Início” e outro sob a guia “Inserir”;
  • Ao invalidarmos o ribbon a primeira guia selecionada executará o seu callback;
  • O problema começa quando clicamos no botão para desabilitar um grupo na guia “Início”, mas selecionamos a guia “Inserir” primeiro;
  • Neste caso, o callback da guia “Inserir” é executado antes do callback para a guia “Início” causando um problema na ordem “ocultar/exibir”;
  • Outro problema diz respeito a qual guia está ativa no momento da abertura de tal documento;
  • A guia ativa determina qual callback será executado. Podemos considerar isso como um bug, pois o callback deveria estar atrelado a guia em questão e não qualquer guia.

Para invalidar o ribbon usamos o método Invalidate:

ribPersonalizado.Invalidate

Este tópico é somente para explicar o que ocorre no processo de invalidação do ribbon, pois o mesmo terá conseqüências na escrita de nosso VBA.

No próximo tópico veremos o código XML para criação de nossa interface.

Determinando o XML

Como as explicações dadas, vejamos como ficará o nosso código XML. Comentários são adicionados nos pontos discutidos.

O leitor deve estudar atendamente o código abaixo em relação ao que foi explicado e será apresentado adiante no código VBA:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Adicionar o atributo onLoad e determinar um callback -->
<!-- para ser carregada na abertura do documento -->

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="setarRibbon">
  <ribbon startFromScratch="false">
    <tabs>
      <tab
      id="meuTab"
      label="Minha Guia">

        <group
            id="meuGrupo"
            label="Meu Grupo">

          <!-- Adiciona o boto de alternncia - toggleButton -->
          <toggleButton
            id="btnToggle"
            label="toggleButton"
            image="rob"
            size="large"
            screentip="Autor: Robert Martim"
            onAction="alternado"
            supertip="Clique neste botão para acionar o autor..."/>

          <!-- Adiciona caixa de checagem - checkBox -->
          <checkBox
            id="chkOcultar"
            label="Ocultar grupo Fonte"
            onAction="ocultarGrupoFonte"
            screentip="Ocultar grupo Fonte"
            supertip="Clique nesta caixa para ocultar o grupo Fonte"/>

          <!-- Adiciona caixa de checagem - checkBox -->
          <checkBox
            id="chkOcultar2"
            label="Ocultar grupo Tabelas"
            onAction="ocultarGrupoTabelas"
            screentip="Ocultar grupo Tabelas"
            supertip="Clique nesta caixa para ocultar o grupo Shapes"/>
        </group>

        <!-- Adiciona um grupo para adicionarmos o splitButton e respectivos botões -->
        <group
            id="meuGrupo2"
            label="SplitButton">

          <splitButton
            id="splitBtn"
            size="large">

              <button
                  id="btn1"
                  imageMso="HappyFace"
                  label="Sr. HappyFace"
                  supertip="Splibutton do Sr. HappyFace"/>

              <menu
                  id="splitMenu"
                  itemSize="large">

              <button
                  id="btn2"
                  image="rob"
                  label="Robert Martim"
                  screentip="Foto do autor."
                  supertip="Foto do autor narcisista ou falta de uma foto melhor??"/>

              <button
                  id="btn3"
                  imageMso="PrintPreviewClose"
                  label="Fechar"
                  onAction="fechar"
                  screentip="Fechar."
                  supertip="Utilize este botão para fechar o documento ativo."/>

              <button
                  id="btn4"
                  imageMso="FileStartWorkflow"
                  label="Checar compatibilidade"
                  onAction="chkCompatbilidade"
                  screentip="Checar compatibilidade."
                  supertip="Utilize este botão para checar a compatibilidade do documento ativo."/>
            </menu>
           
          </splitButton>
        </group>

      </tab>

      <tab idMso="TabHome">

<!-- Adicionar um callback para o atributo "getVisible" -->
<!-- tais callbacks serao executados quando o ribbon -->
<!-- for invalidado utilizando o método "invalidate" -->
      <group
            idMso="GroupFont"
            getVisible="altGrpFonte"/>
      </tab>

      <tab idMso="TabInsert">
      <group
            idMso="GroupInsertTablesExcel"
            getVisible="altGrpTbl"/>
      </tab>

    </tabs>
  </ribbon>
</customUI>

Determinando o VBA

O leitor deve notar que o atributo getVisible gera um callback, portanto quando a guia que contiver o grupo que desejamos ocultar/exibir estiver ativa, haverá uma chamada no VBA. Isso quer dizer que não será possível colocar o código em “break” para debug.

Como o callback terminará a chamada assim que tenha sido executado, precisamos invalidar o Ribbon para que o callback seja chamado. Vejamos, portanto, como ficará o nosso código VBA. Primeiramente adicione o código abaixo no VBE da pasta de trabalho:

Option Explicit

'Determina se a primeira chamada no callback de ocultar/exibir
'foi causada pela abertura do documento
Private Sub Workbook_Open()
    blnCarregado = True
End Sub
Agora, adicione um módulo onde acrescentaremos os callbacks abaixo:
'Variáveis globais para determinar se oculta/exibe
'o grupo "Font" na guia "Início".
Dim blnGrpFontVísivel       As Boolean

'Veja explicação acima. O mesmo se aplica
Dim blnGrpTabelasVisível    As Boolean

'Variável booleana para determinar se o callback ocorreu
'na abertura do documento.
Public blnCarregado     As Boolean

'Variável global representando o nosso riboon a ser setado
'na abertura do documento
Dim ribPersonalizado    As IRibbonUI

Sub setarRibbon(ribbon As IRibbonUI)

'    MsgBox "ola"           'Debug apenas

'   Setar o objeto
    Set ribPersonalizado = ribbon
End Sub

Sub alternado(control As IRibbonControl, pressed As Boolean)
'   Se o botao de alternância nao estiver ativo, mostrar esta mensagem...
    If Not pressed Then
        MsgBox "O toggleButton não está pressionado...", vbInformation
    Else:

'       Caso contrário, mostrar esta mensagem:
        MsgBox "O toggleButton está pressionado...", vbInformation
    End If
End Sub

Sub ocultarGrupoFonte(control As IRibbonControl, pressed As Boolean)

'   Determina o valor da variável para ocultar/exibir o grupo
    blnGrpFontVísivel = pressed
   
'   Invalida o ribbon para execução do callback durante a seleção de uma guia
    ribPersonalizado.Invalidate
   
'   Define o estado atual da caixa de checagem (se está selecionada ou nao)
'   e passa o valor para a variável global "blnGrpFontVísivel"
    If Not pressed Then
        MsgBox "Você acabou de reexibir o grupo Fonte...", vbExclamation
    Else:
        MsgBox "Você acabou de ocultar o grupo Fonte...", vbExclamation
    End If
End Sub

Sub ocultarGrupoTabelas(control As IRibbonControl, pressed As Boolean)

'   Determina o valor da variável para ocultar/exibir o grupo
    blnGrpTabelasVisível = pressed

'   Invalida o ribbon para execução do callback durante a seleção de uma guia
    ribPersonalizado.Invalidate
   
'   Define o estado atual da caixa de checagem (se está selecionada ou nao)
'   e passa o valor para a variável global "blnGrpTabelasVisível"
    If Not pressed Then
        MsgBox "Você acabou de reexibir o grupo Tabelas...", vbExclamation
    Else:
        MsgBox "Você acabou de ocultar o grupo Tabelas...", vbExclamation
    End If
End Sub

Sub fechar(control As IRibbonControl)
End Sub

Sub altGrpFonte(control As IRibbonControl, ByRef returnedVal)

'   Alterna entre oculto e visível. Se o valor para a variável global
'   blnGrpFontVísivel for "FALSE" (oculto) entao, "not" altera para "TRUE"
'   (visível). O inverso é verdadeiro para TRUE.
    returnedVal = True
    If blnCarregado Then
        blnCarregado = False
        Exit Sub
    End If
   
    If control.ID = "GroupFont" Then
        returnedVal = Not blnGrpFontVísivel
    Else:
        ribPersonalizado.Invalidate
    End If
End Sub

Sub altGrpTbl(control As IRibbonControl, ByRef returnedVal)

'   Alterna entre oculto e visível. Se o valor para a variável global
'   blnGrpTabelasVisível for "FALSE" (oculto) entao, "not" altera para "TRUE"
'   (visível). O inverso é verdadeiro para TRUE.
   
    returnedVal = True
    If blnCarregado Then
        blnCarregado = False
        Exit Sub
    End If
   
    If control.ID = "GroupInsertTablesExcel" Then
        returnedVal = Not blnGrpTabelasVisível
    Else:
        ribPersonalizado.Invalidate
    End If
End Sub

Sub chkCompatbilidade(control As IRibbonControl)
    MsgBox "Não sei o que você está checando, " _
       mas é completamente incompatível!", vbInformation
End Sub

Redefinindo/desabilitando a função de um comando interno (“repurpose” e “enable”)

Neste tópico discutirei um assunto muito comum no fórum de Excel: como desabilitar determinado comando?

Muitas vezes o leitor deseja desabilitar um determinando comando no Excel (como “Imprimir”, por exemplo) para que o usuário final não possa imprimir o documento. A partir da versão 97 é possível efetuar tal redefinição/desabilitação de comandos, contudo, o trabalho era por demais exagerado, pois tínhamos que desabilitar cada comando individualmente.

Por exemplo, podemos imprimir atráves do menu “Arquivo” ou através de um botão na barra de ferramentas. Precisaríamos desabilitar ambos. Não obstante, se houvesse outra instância deste botão o usuário ainda assim poderia imprimir. Além disso, teríamos o problema óbvio de diferentes índices para determinado comando em versões diferentes o que dificulta ainda mais o trabalho em termos de compatibilidade.

Agora, podemos pular esta trabalheira toda redefinindo o comando diretamente no XML do CustomUI. Aqui, temos duas opções:

  • Enable à Habilita ou não um determinado comando
  • Repurpose à Modifica o propósito original do comando por um outro determinado pelo atributo “OnAction”.

Vejamos a seguir cada um separadamente.

Desabilitando um comando globalmente

Nossa primeira parada será desabilitar um comando qualquer globalmente. Observe a figura abaixo:


Figura 5‑8 Comando “Paste” (colar) habilitado

O nosso objetivo é desabilitar a possibilidade de colagem desabilitando o camando “paste” (colar) através do código XML.

Crie um novo documento onde adicionaremos o seguinte código XML:

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
      <commands>
            <command
                  idMso="Paste"
                  enabled="false"/>
      </commands>
</customUI>

Primeiramente abrimos o bloco referente aos comandos determinado por commands e em seguida especificamos qual comando deve ser desabilitado utilizando o atributo enabled e setando o seu valor para false (falso, isto é, desabilitado).
Quando o arquivo é aberto o comando é desabilitado:


Figura 5‑9 Comando “Paste” (colar) desabilitado

O leitor deve estar atento que tal modificação tem efeito global e não será aplicado somente no arquivo que contém o XML, mas na sessão aberta do Excel.

Finalmente, ao desabilitarmos o comando o atalho de teclado associado a ele não é desabilitado. Isso implica que o usuário final poderá colar mesmo com o botão desabilitado como mostrado acima.

Uma solução é utilizarmos o método “OnKey” do aplicativo para determinar o conjunto de atalho a ser desabilitado.

Podemos fazer isso da seguinte maneira:

Sub desabilitarAtalhoColar()
    Application.OnKey "^{v}", "desabilitado"
End Sub

Sub desabilitado()
    MsgBox "Não é possível colar utilizando o atalho de teclado. " _
        & "Colar não é permitido nesta sessão!", vbExclamation
End Sub

Sub habilitarAtalhoColar()
    Application.OnKey "^{v}"
End Sub

Para terminar, adicione os seguintes procedimentos ao VBE da pasta de trabalho:

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Call habilitarAtalhoColar
End Sub

Private Sub Workbook_Open()
    Call desabilitarAtalhoColar
End Sub

Ao tentar utilizar a tecla de atalho o usuário será informado da impossibilidade:


Figura 5‑10 Informando o usuário da impossibilidade de colagem

Vejamos agora como modificar o propósito original de um comando.

Redefinindo o propósito de um comando (repurpose)

Quando clicamos em um botão como o de colar, nós esperamos que algo seja colado. Da mesma forma, quando clicamos em “Imprimir” esperamos que a janela de impressão seja aberta para definirmos as propriedades de impressão.

A redefinição de um comando funciona de forma similar ao que fizemos antes utilizando o método “OnKey”. No exemplo, redefinimos o propósito original para outro onde ao invés de ocorrer a colagem de dados o usuário recebe uma mensagem.
Para modificarmos o propósito original devemos adicionar o atributo onAction e definir um callback para o mesmo.

Suponhamos que o objetivo seja trocar o comando “Paste” (Colar) pelo comando “Copy” (copiar) quando ocorrer o clique no botão. Primeiramente, definimos o nosso XML como segue:

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
      <commands>
            <command
                  idMso="Paste"
                  onAction="copiar"/>
      </commands>
</customUI>

O nome da macro pode ser qualquer coisa que o leitor queira. Neste caso, a chamo de “copiar”. Salve o arquivo e gere o callback para o atributo onAction. Agora, abra o arquivo Excel onde iremos colar e programar o callback como segue:

Sub copiar(control As IRibbonControl, ByRef cancelDefault)
    Dim resposta    As Integer
    If Not (MsgBox("Este comando irá copiar ao invés de colar. " _
        & "Deseja continuar?", vbQuestion + vbYesNo)) = vbYes Then Exit Sub
    Selection.Copy
End Sub

Ao utilizar o botão de colagem a seguinte mensagem é mostrada ao usuário:


Figura 5‑11 Confirmando a ação do usuário em um “repurpose”

« Anterior Δ Página principal ¤ Índice Próxima »

Quer Aprender VBA no Excel, Sem Dificuldades, com Exemplos
Práticos Passo a Passo e com Explicações Detalhadas?

Aprenda com Júlio Battisti: "Macros e Programação VBA no Excel 2010 Através de Exemplos Práticos e Úteis - Passo a Passos

Junto com o livro você Recebe 11 Bônus Incluindo 50 horas de Vídeo Aulas.

Mesmo que Você não Saiba Nada de Programação VBA ou já Tenha Tentado
Aprender VBA e Desistiu ou Achou Difícil, com Este Livro EU GARANTO que Você Aprenderá, SEM DIFICULDADES. APRENDIZADO GARANTIDO.

Clique Aqui Para Todos os Detalhes sobre Esta Oferta

- É com alegria que Comunico o lançamento do meu 42º Livro.

 

- Perfeito para Iniciantes em Programação VBA.

 

- Abordo desde o Básico até Comandos Avançados.

 

- Códigos detalhadamente explicados, linha por linha.

 

- Criação de Funções e Procedimentos com VBA.

 

- O Modelo de Objetos do Excel - Exemplos Práticos.

 

- Criação de Formulários - UseForms.

 

- Criação de um Sistema de Cadastro Completo, com Foto.

 

- Como trabalhar com Tabelas Dinâmicas na Programação VBA.

 

- Como trabalhar com Gráficos na Programação VBA.

 

- Rotina que Escreve um número por Extenso usando VBA.

 

- E muito, muito mais mesmo...

 

- Junto com o livro você recebe 50 horas de Vídeo Aulas sobre Macros, Programação VBA, Fórmulas e Funções Avançadas, Dashboards e Muito mais.

 

[Bônus]: 60 horas de Vídeo Aulas sobre Macros, Programação VBA, Fórmulas e Funções Avançadas no Excel, Recursos Avançados, Dashboards e Muito mais.

 

Aprenda com Júlio Battisti: "Macros e Programação VBA no Excel 2010 Através de Exemplos Práticos e Uteis - Passo a Passos

Aprenda com Júlio Battisti: "Macros e Programação VBA no Excel 2010 Através de Exemplos Práticos e Uteis - Passo a Passos

A BÍBLIA DA
PROGRAMAÇÃO
VBA NO EXCEL

 

Quer receber novidades e e-books gratuitos?

Contato: Telefone: (51) 3717-3796 | E-mail: webmaster@juliobattisti.com.br | Whatsapp: (51) 99627-3434

Júlio Battisti Livros e Cursos Ltda | CNPJ: 08.916.484/0001-25 | Rua Vereador Ivo Cláudio Weigel, 537 - Universitário, Santa Cruz do Sul/RS, CEP: 96816-208

Todos os direitos reservados, Júlio Battisti 2001-2021 ®

[LIVRO]: MACROS E PROGRAMAÇÃO VBA NO EXCEL 2010 - PASSO-A-PASSO

APRENDA COM JULIO BATTISTI - 1124 PÁGINAS: CLIQUE AQUI