Macro Conglobante para produzir texto descritivo a partir de dados sólidos CALC

Olá,
Tenho o seguinte problema para resolver no CALC e cuja melhor forma de descrevê-lo é dando um exemplo. Sintéticamente, ocorre que minha planilha reúne uma série de dados que devem ser cruzados a fim de alimentar uma linha de texto descritivo que será migrada para o Write. A tabela d dados tem as seguintes características:

  • Serão concatenados cerca de 15 eventos por vêz (15 colunas)
  • Cada evento conterá o nome do cliente, e o produto que adquiriu
  • Um mesmo cliente pode efetuar mais de uma compra no mês;
  • Um mesmo cliente poderá comprar o mesmo produto mais de uma vez;
  • O texto gerado deve colocar pontuação adequada (", "; "; " ou " e ").

Esses dados precisam ser organizados de forma a produzir um texto contendo o nome do cliente e os produtos que adquiriu, de modo que a aquisição de um mesmo produto duas ou mais vezes seja indicada apenas uma vez e, entre parenteses, o número de vezes, como a seguir:

Andre comprou B, C (2x) e D;
Beto comprou C, F, E e G;
Carlos comprou G (2x) e F;

Ainda não consegui pensar em nada melhor do que a planilha em anexo. Alguém tem solução melhor?
Concatenador - usando CONCAT.ods
[NOTA]: Usei a função CONCAT( que é muito melhor do que a velha e inútil CONCATENAR(. Porém, na planilha original serei obrigado a usar esta última (na verdade, usarei &), porque versões mais antigas do LibreOffice (como a que a minha empresa usa) ainda não têm essa função.

@Jedison, tentando entender o arquivo, para poder palpitar…

Com base no arquivo postado a linha Eventos e só uma sequencia de Registro, então tenho que totalizar as linhas Clientes e Compras.

O arquivo Original seu, e lançado desta maneira, a sequencia em colunas ?

Poderia ser em Linhas como Banco de dados ?

Após olhar sua macro postada, Compras seriam os Delitos ? Esta quantidade de opções é conhecida, tem uma lista ?

Oi Schiavinatto,
Eventos é só o número sequencial dos “fatos” examinados.
Se houver menos que isso, o código excluirá automaticamente os registros em branco (usei como parâmetro o campo Nome (porque é o dado principal).
Sim, no exemplo que eu tinha dado inicialmente usei “Clientes” e “Compras” para ficar mais fácil do público entender. No meu caso, o que quero é classificar uma série de ilícitos cometidos por um ou mais indivíduos, e tenho mais dados pra incluir nesse pequeno relatório que será gerado (Data de nascimento e idade).
A sequência é dada em colunas. Porém, para mudar para linhas basta mudar as referências indicadas no código (variáveis INTERV1 e INTERV2, principalmente).
Sim, no meu arquivo costumo trabalhar com no máximo 15 eventos simultâneos.
Para trabalhar com mais dados, tem-se que alterar a dimensão das variáveis oEvent() e NCR()
Não testei, mas acho que mudando isso, o código já funcionará direito.
(*) Notei agora que a publicação excluiu algumas aspas do meu código.

Editei o texto original, e troquei o arquivo pelo (fragmento) do que será realmente usado.
Tentei disponibilizar o código para corrigir as alterações que a página fez no meu, mas não consegui por causa do formato.
Também queria mudar as TAGS, para incluir Automatização Texto Macro, mas a página não registra as alterações que faço.

Depois de muito me debruçar sobre o problema acabei desenvolvendo uma pequena SUB que fornece o resultado desejado.
Posto a solução para servir de ajuda a outros que precisem de algo semelhante.
Eis a MACRO, que denominei CONGLOB()
A minha intenção era aplicá-la como um FUNÇãO na planilha, que pudesse ser chamada de uma determinada célula mediante a fórmula =CONGLOB( I1 , I2 , I3 , Cel), onde:
i1 - seja o intervalo principal da fonte de dados (C3:Q3)
i2 - o intervalo secundário (do cruzamento dos dados) - C4:Q4
i3 - o intervalo complementar (informações secundárias do registro)
Cel - Endereço de destino para o texto resultante.

    REM    BASIC  

rem Faz o Cruzamento de dois dados interligados, associando a outras duas informações
'       referentes ao mesmo registro, e produz um texto descritivo concatenado, devidamente
'       pontuado
'       No exemplo, organiza vários réus segundo seus crimes, relacionando a data de nascimento
'       e idade da data dos fatos.
'      Autor Jédison Maidana
'
sub CONGLOB
    Para transformar em Função, substituir por: 
` ' function CONGLOB (Byval Interv1 as string, interv2 as string, interv3 as string, Dest as string) as string
   ' (Veja alterações no final do código) `
      Dim oSheet, oCelReus, oCelCrims
      Dim oCelDNs, oCelIds
      Dim oReu(), oReus(), oCrim(), oCrims() as string
      Dim oDN(), oDNs() as integer
      Dim oId(), oIds() as integer
      
  Dim Lista as String
  Dim oEvent(15) as integer
  Dim NCr(15) as integer


   Dim Col , xx, yy , Li , LS , NR As Integer
    
    'print interv1 , interv2 , Dest
    'Definição dos parâmetros de pesquisa
'   SE usada como função, retirar o bloco abaixo
       Interv1 = "C2:Q2"   ' Intervalo da primeira referência (Linha Réus)
       interv2 = "C7:Q7"   ' Intervalo da segunda referência (Linha Crimes)
       interv3 = "C3:Q3"   ' Intervalo da Terceira referência (Linha D.Nascimento)
       interv4 = "C4:Q4"   ' intervalo da quarta referência (Idade)
       Dest = "L32"           ' Célula onde o texto final será inserido

       Tx0$ =  "(Nascido em "
       Tx1$ =  "anos de idade na data do fato), foi denunciado Pelo Ministério Público por incurso nas sanções do "
       Tx2$ =  "("
       Tx3$ =  "anos), por violação do"  
    
' Define o documento ativo como fonte dos dados  
   oSheet = ThisComponent.CurrentController.ActiveSheet

' Armazena os dados de Interv1 na matriz oReu()
   oCelReus = oSheet.getCellRangeByName( Interv1 )
   oReus() = oCelReus.getDataArray()
   oReu() = oReus(0) 

' Armazena os dados de Interv2 na matriz oCrime()
   oCelCrims = oSheet.getCellRangeByName( interv2 )
   oCrims() = oCelCrims.getDataArray()
   oCrim() = oCrims(0)

' Armazena os dados de Interv3 na matriz oDNasc()
   oCelDNs = oSheet.getCellRangeByName( interv3 )
   oDNs() = oCelDNs.getDataArray()
   oDN() = oDNs(0)

' Armazena os dados de Interv4 na matriz oIdade()
   oCelIds = oSheet.getCellRangeByName( interv4 )
   oIds() = oCelIds.getDataArray()
   oId() = oIds(0)

Rem Vincula os Réus aos Eventos - Evento(x) cometido pelo mesmo réu do evento X
	For Col =  LBound(oReu()) To UBound(oReu())
	       oEvent(Col) = Col
	       For xx = 0 to Col
                    if UCase(oReu(Col)) = UCase(oReu(xx)) then
                    ' Caixa alta pra não separar iguais
                       oEvent(Col) = xx
                       exit for
                     end if
            Next
     Next

' Montagem da lista conglobante
Lista = 
Li = LBound(oReu())
LS = UBound(oReu())

' Pesquisa quantos crimes (total) cada reu cometeu
For Col = Li to LS
      For xx = Col to LS
            if Col = oEvent(xx) then
            NCR(Col) = NCR(Col) + 1
            End if
       Next
Next    

For Col = Li to LS
       Reu$ =  oReu(Col)
       if Reu$ =  Then
           Exit for
           Elseif Col = oEvent(Col) then
                   Lista = Lista & Reu$ 
                         if Col = 0 then
                               Lista = Lista & Tx0$ &  Format(oDN(Col), ddmmyyyy) & ,  & oId(Col) & Tx1$
                       Else Lista = Lista & Tx2$ &  Format(oDN(Col), ddmmyyyy) & ,  & oId(Col) & Tx3$
                   End if
                   For xx = Col to LS
                         if oEvent(xx) = Col then
                             Lista = Lista &   & oCrim(xx)
                             NR = 0 
                             For yy = xx to LS
                                   if  UCase(oCrim(xx))= UCase(oCrim(yy)) and oEvent(yy) = Col then 
                                   ' Caixa Alta pra não separar iguais
                                           NR = NR + 1
                                           oEvent(yy) = LS + 1
                                  end if
                              Next
                              if NR  1 then
                                  Lista = Lista &  ( & NR & x)
                                  end if
							 NCR(Col) = NCR(Col) - NR ' Retira da contagem os delitos duplicados
							If NCR(Col)  1 then 
						    Lista = Lista & , 
							    Else if NCR(Col) 0 then
					            Lista = Lista &  e 
				            Else Lista = Lista & ; 
							End if
							End if
                          end if
                    Next
            Lista = Lista & chr$(10)
            Else
        End if
Next

ThisComponent.Sheets(0).getCellRangebyName(Dest).string = Lista                               
'MsgBox Lista 

' Se usada como function, trocar End Sub por:
' CONGOB = "Concatenado"
' End Function
    End sub