Introdução
Na matemática, podemos calcular a quantidade de combinações sem repetições possíveis através da fórmula:
n
é a quantidade total de elementos disponíveis para combinar.p
é a quantidade de elementos de cada combinação.
O Excel possui uma função nativa para fazer esse cálculo. Suponha que queremos calcular a quantidade de combinações sem repetições de 6 elementos em grupos de 3. Logo, n = 6
e p = 3
. A fórmula é:
=COMBIN(6;3)
Em VBA, você pode usar a expressão a seguir:
MsgBox WorksheetFunction.Combin(6, 3)
O resultado de ambos exemplos é 20
, em acordo com a fórmula inicial.
Esta página possui uma pasta de trabalho que lista todas as combinações de um grupo n
de valores. No exemplo abaixo, temos n = 6
(porque a coluna Valores tem 6 itens) e p = 3
, determinado pelo campo Tam. Grupo. Veja o resultado dessas combinações listado na tabela da direita:
Você pode alterar os valores da das combinações e as repetições à vontade, lembrando que deve-se ter uma quantidade de valores maior que o tamanho do grupo de combinações.
Código
Option Explicit Private aResult As ListObject 'Tabela de resultados Private aValor As ListObject 'Tabela de valores a combinar Private aListRowIndex As Long 'Linha da tabela de resultados Private aNumElements As Long 'Quantidade de valores a combinar disponíveis Private aNumCols As Long 'Quantidade de elementos em cada grupo de combinação Private aNumRows As Long 'Quantidade de resultados gerados Private Sub Main() Dim Elements As Variant 'Elementos disponíveis para combinar Dim Result As Variant 'Set de resultados de cada iteração 'Inicialização de variáveis Set aResult = Me.ListObjects("loResult") Set aValor = Me.ListObjects("loValor") Elements = WorksheetFunction.Transpose(aValor.DataBodyRange) aNumElements = UBound(Elements) aNumCols = Me.Range("TamanhoGrupo") 'Validação If aNumCols > aNumElements Then MsgBox "A quantidade de repetições deve ser menor ou igual à quantidade de valores disponíveis.", vbInformation GoTo Quit End If aNumRows = WorksheetFunction.Combin(aNumElements, aNumCols) ReDim Result(1 To aNumCols) aListRowIndex = 1 'Formatar tabela de resultados FormatTable 'Inicia a recursão para gerar as combinações Combinar Elements, aNumCols, Result, 1, 1 Quit: End Sub Sub Combinar(ByVal Elements As Variant, _ ByVal p As Long, _ ByVal Result As Variant, _ ByVal iElement As Integer, _ ByVal iIndex As Integer) Static iEvents As Long 'Para desafogar temporariamente processos pendentes do Excel Dim i As Long iEvents = iEvents + 1 If iEvents Mod 100 = 0 Then DoEvents For i = iElement To aNumElements Result(iIndex) = Elements(i) If iIndex = p Then aResult.ListColumns(1).DataBodyRange(aListRowIndex).Resize(, p) = Result aListRowIndex = aListRowIndex + 1 Else Combinar Elements, p, Result, i + 1, iIndex + 1 'Se quiser que seja calculado um Arranjo ao invés da Combinação, 'comente a expressão acima e use a expressão abaixo: 'Combinar Elements, p, Result, i, iIndex + 1 End If Next i End Sub Private Sub FormatTable() Dim iCol As Long With aResult If .ListColumns.Count > 1 Then .ListColumns(2).Range.Resize(, .ListColumns.Count - 1).Delete End If If .ListRows.Count > 0 Then .DataBodyRange.ClearContents .Resize .Range.Resize(1 + aNumRows, aNumCols) For iCol = 1 To .ListColumns.Count .HeaderRowRange(iCol) = "Col" & iCol Next iCol End With End Sub
A característica mais importante do código é a presença do subprocedimento Combinar
. É uma rotina recursiva (isto é, ela mesma faz chamadas a ela) para gerar as combinações. Analisar como ela funciona usando a tecla F8
para depurar o código passo a passo é fundamental para entender o algoritmo.
Nota que se você quiser arranjos (isto é, combinações com repetições), basta usar o trecho de código comentado acima.
Download
Para fazer download da pasta de trabalho usada neste artigo, clique aqui.