Gerando Todas as Combinações Possíveis de um Grupo de Células

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.