No primeiro artigo sobre a personalização do friso (ribbon) foi mostrado como criar um novo separador e um novo grupo com dois controlos, neste caso, dois botões.
Mas podemos utilizar inúmeros controlos de modo a tornar as opções mais simples para o utilizador. Como referido também no artigo anterior, este é o esquema base para construção do friso:
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<ribbon startFromScratch="false">
<tabs>
<tab id="customTab1" label="Extra Options">
<!-- Grupos, Controlos, etc -->
</tab>
</tabs>
</ribbon>
</customUI>
O próximo código XML apresentado irá ser colocado dentro da tab com o ID “customTab1”
Vamos ver então alguns controlos, alguns eventos, designados por callbacks, e algumas opções mais avançadas!
Para criar um grupo com caixas de selecção (checkboxes), no primeiro grupo (myCheckBox Group), podemos o fazer da seguinte forma:
<group id="Group1" label="myCheckBox Group">
<checkBox id="cb1" label="Opção A" onAction="cbGetDescription" />
<checkBox id="cb2" label="Opção B" onAction="cbGetDescription" />
<checkBox id="cb3" label="Opção C" onAction="cbGetDescription" />
<checkBox id="cb4" label="Opção D" onAction="cbGetDescription" />
<checkBox id="cb5" label="Opção E" enabled="false" />
<checkBox id="cb6" label="Opção F" enabled="false" />
</group>
Neste caso estamos a criar um grupo, onde vamos ter várias checkboxes (6). As primeiras quatro estão a chamar o callback cbGetDescription, onde irmos depois verificar qual a opção selecionada, e as duas últimas estão desabilitadas para efeitos de demonstração.
No callback (evento) cbGetDescription podemos usar o seguinte código:
Sub cbGetDescription(control As IRibbonControl, pressed As Boolean)
Select Case control.id
Case "cb1"
MsgBox "Opção A - Seleccionada: " & pressed
Case "cb2"
MsgBox "Opção B - Seleccionada: " & pressed
Case "cb3"
MsgBox "Opção C - Seleccionada: " & pressed
Case "cb4"
MsgBox "Opção D - Seleccionada: " & pressed
End Select
End Sub
No segundo grupo (MyDrops Group) estão dois controlos de selecção: Combobox e DropDown. A diferença entre ambos é que na Combobox é possível alterar o texto enquanto na DropDown não. Neste exemplo, e para mostrar diferentes formas de carregamento de dados, na Combobox estão já definidos alguns itens e a DropDown será preenchida dinamicamente com dados de um Array definido no código.
O XML para a sua criação será então o seguinte:
<group id="Group2" label="myDrops Group">
<comboBox id="cboItems" label="ComboBox:" onChange="cboOnChange">
<item id="item1" label="Item 1" />
<item id="item2" label="Item 2" />
<item id="item3" label="Item 3" />
</comboBox>
<dropDown id="dropDynamic" label="Dropdown:"
onAction="ddOnAction"
getItemLabel="ddGetItemLabel"
getItemCount ="ddGetItemCount" >
</dropDown>
</group>
Como código para a Combobox podemos definir então:
Sub cboOnChange(control As IRibbonControl, text As String)
MsgBox "Texto seleccionado: " & text
End Sub
Isto irá mostrar uma mensagem com o texto seleccionado ou inserido.
Para a DropDown o código é ligeiramente mais complexo!
Para começar vamos adicionar na primeira linha do XML o atributo onLoad definindo desta forma que quando o friso é iniciado iremos executar determinado código (poderia ser feito também no evento Workbook_Open).
<customUI xmlns=http://schemas.microsoft.com/office/2009/07/customui
onLoad="RibbonLoad">
Desta forma vamos executar o callback RibbonLoad() na inicialização do friso, onde iremos carregar alguns valores no array. Estes valores vão ser utilizados pelos métodos GetItemLabel() e GetItemCount() como é possível ver no seguinte código/comentários.
Private paises(4) As String
Private x As Integer
Sub RibbonLoad(ribbon As IRibbonUI)
paises(0) = "Portugal"
paises(1) = "Espanha"
paises(2) = "França"
paises(3) = "Alemanha"
paises(4) = "Inglaterra"
End Sub
' Mostra a determinada posição do array de acordo com o índex recebido
Sub ddOnAction(control As IRibbonControl, id As String, index As Integer)
MsgBox paises(index), vbInformation
End Sub
' Este evento é chamado uma vez por cada posição na lista, definido no
' evento ddGetItemCount(). Desta forma, quando o evento é executado, colocamos
' um valor de cada posição do array e incrementamos o contador de posição
Sub ddGetItemLabel(control As IRibbonControl, index As Integer, ByRef returnedVal)
returnedVal = paises(x)
x = x + 1
End Sub
' Define o número de itens a aparecer na lista
Sub ddGetItemCount(control As IRibbonControl, ByRef returnedVal)
returnedVal = UBound(paises) + 1
End Sub
O terceiro e último grupo (myMisc Group) tem diferentes controlos para mostrar mais algumas das possibilidades disponíveis (não todas, obviamente). O XML é um pouco extenso mas será explicado de seguida:
<group id="Group3" label="myMisc Group">
<gallery id="MonthGallery" label="Escolher mês usando uma Gallery:"
columns="3" rows="4" onAction="SetMonth" >
<item id="m01" label="Janeiro"/>
<item id="m02" label="Fevereiro"/>
<item id="m03" label="Março"/>
<item id="m04" label="Abril"/>
<item id="m05" label="Maio"/>
<item id="m06" label="Junho"/>
<item id="m07" label="Julho"/>
<item id="m08" label="Agosto"/>
<item id="m09" label="Setembro"/>
<item id="m10" label="Outubro"/>
<item id="m11" label="Novembro"/>
<item id="m12" label="Dezembro"/>
<button id="mActual" imageMso="CalendarToolSelectDate"
label="Mês Actual" onAction="SetCurrentMonth" />
</gallery>
<editBox id="EditBox1" label="Texto a pesquisar:" onChange="EditBoxOnChange"
imageMso="FindAllDownloadedDocuments" />
<separator id="separator1"/>
<toggleButton id="toggleActivar" label="Activar/Desactivar"
imageMso="AcceptTask" getPressed="toggleGetPressed"
onAction="toggleOnAction" />
<menu id="Menu1" label="Menu Opções Sistema" itemSize="normal">
<button idMso="Cut"/>
<button idMso="Copy"/>
<button idMso="Paste"/>
<menuSeparator id="menuSeparator1" title="Mais opções ..."/>
<menu id="SubMenu1" label="Ficheiro">
<button idMso="FileSave"/>
<button idMso="FileSaveAs"/>
<button idMso="FileOpen"/>
<button idMso="FileClose"/>
</menu>
<menu id="SubMenu2" label="Diversos">
<button idMso="FileExit"/>
</menu>
</menu>
<dialogBoxLauncher>
<button id="Launcher1" screentip="My Launcher"
onAction="ThisWorkbook.LauncherCode" />
</dialogBoxLauncher>
</group>
Para começar uma galeria (Gallery) onde estamos a definir os diferentes meses do ano. Aqui podemos indicar quantas linhas e colunas queremos, assim como utilizar outros controlos. No código XML está definido no final um botão que irá escolher o mês actual.
O código associado é muito simples:
' Mostra o mês de acordo com o index recebido
Sub SetMonth(control As IRibbonControl, id As String, index As Integer)
MsgBox MonthName(index + 1)
End Sub
' Mostra o mês por extenso do mês actual
Sub SetCurrentMonth(control As IRibbonControl)
MsgBox MonthName(Month(Now))
End Sub
De seguida temos uma EditBox que permite o utilizador escrever algum texto. No código basta simplesmente mostrar o resultado no callback EditBoxOnChange():
Sub EditBoxOnChange(control As IRibbonControl, text As String)
MsgBox "O texto indicado foi: " & text, vbInformation
End Sub
Depois um separador e um botão retentivo (toggle button), ou seja, quando pressionado fica seleccionado e quando pressionado novamente perde a selecção.
No código do toggle button mostramos apenas o estado no callback onAction() e definimos também, no callback getPressed(), o estado inicial quando o friso é inicializado.
' Quando o botão (toggle) é pressionado mostra o estado
Sub toggleOnAction(control As IRibbonControl, pressed As Boolean)
MsgBox "Controlo: " & control.id & " - Pressionado: " & pressed
End Sub
' Define o estado inicial do botão
Sub toggleGetPressed(control As IRibbonControl, ByRef returnedVal)
returnedVal = True
End Sub
Depois, no próximo controlo utilizado, não existe qualquer código associado pois estamos a definir funções de sistema através da atribuição de um idMso. Isto significa que cada opção que colocarmos no menu, que poderá ser colocado em outro controlo, irá executar a função que o sistema está preparado para o fazer (save, save as, copy, cut, etc).
Desta forma, podemos colocar no nosso friso algumas opções já existentes no Excel e que podem ser úteis. A lista dos ID’s (idMso) que podemos utilizar pode ser descarregada aqui:
- 2007 Office System Document: Lists of Control IDs
- Office 2010 Help Files: Office Fluent User Interface Control Identifiers
O último controlo, embora meio escondido e disponível no canto inferior direito do grupo, é um DialogBox Launcher que permite simplesmente lançar uma janela com opções relaccionadas com o respectivo grupo.
O código pode então mostrar uma mensagem, chamar um userform, etc. Neste exemplo irá mostrar apenas uma mensagem, mas tem uma particularidade, que se aplica a todos os controlos. No XML está definido para o callback onAction() o método ThisWorkbook.LauncherCode. Isto significa que o seguinte código tem de estar localizado no ThisWorkbook para funcionar, pois está a ser apontado para tal.
Sub LauncherCode(control As IRibbonControl)
MsgBox "Mais opções ..."
End Sub
Podemos apontar para módulos específicos, worksheets, etc.
NOTA IMPORTANTE: Caso o XML não esta correcto (tags inválidas, tags não fechadas, etc) o separador não ficará visível.
E são alguns exemplos que mostram como personalizar o friso e como utilizar o código para cada controlo. Existem muito mais opções para cada controlo e muito mais controlos. Para complementar estes dois pequenos artigos podem ver os seguintes links, que além de um PDF que podem descarregar gratuitamente, podem consultar online:
- Custom UI XML Markup Version 2 Specification (especificação completa com exemplos de callbacks e XML)
- Custom UI XML Markup Specification (definição do markup XML)
Podem ainda descarregar o ficheiro de exemplo utilizado neste artigo: download
1 comentários:
Olá,
Muito bom seu artigo, me ajudou bastante!
Eu gostaria de saber se é possível fazer referência a um determinado controle (botão) na minha ribbon personalizada dentro do código VBA de outro controle?
Por exemplo:
Tenho alguns ToggleButtons que ocultam algumas ferramentas, e gostaria de habilitar uma CheckBox que quando marcada desativasse os ToggleButtons.
Sub Exibir_Tudo(control As IRibbonControl, pressed As Boolean)
End Sub
Obrigado
Enviar um comentário