As macros do LibreOffice Calc costumam ficar lentas em planilhas grandes por um motivo simples: a macro gasta mais tempo atravessando o limite do objeto UNO do que realizando o cálculo em si. Ler uma célula, modificá-la e gravá-la de volta milhares de vezes pode ser muito mais custoso do que mover os mesmos dados em blocos maiores.
O objetivo não é tornar todas as macros "rápidas" em abstrato. Uma otimização útil deve produzir o mesmo resultado, concluir em menos tempo com o mesmo conjunto de dados, manter o Calc responsivo o suficiente para o fluxo de trabalho e evitar a criação de novos problemas de correção ou memória. As técnicas abaixo se concentram nesses resultados mensuráveis.
Em outubro de 2026, a documentação atual do SDK do LibreOffice identifica as interfaces de planilha usadas aqui na referência da API do LibreOffice 26.8. Os métodos principais são interfaces UNO já consolidadas, e não um recurso de desempenho recém-introduzido.
1. Meça a macro antes de alterá-la.
Comece com uma linha de base repetível. O LibreOffice Basic oferece GetSystemTicks()o recurso `system_time`, que a Ajuda oficial descreve como uma forma de medir os ciclos do sistema e otimizar processos. Envolva a parte da macro que você realmente deseja aprimorar, em vez de medir o tempo de abertura da pasta de trabalho, solicitações ao usuário ou configurações irrelevantes.
Dim t0 As Long, elapsed As Long
t0 = GetSystemTicks()
' Run the work you want to measure here.
elapsed = GetSystemTicks() - t0
MsgBox "Elapsed ticks: " & elapsed
Execute a mesma operação várias vezes na mesma cópia do arquivo. A primeira execução pode ser diferente devido a caches do sistema de arquivos, estado da fórmula ou outras operações realizadas apenas uma vez. Registre o tamanho do conjunto de dados, o intervalo processado e se o cálculo automático estava ativado para que suas comparações continuem relevantes.
Um bom resultado não se resume apenas a um número de tempo menor. Confirme se a contagem de linhas, os totais, as fórmulas, os valores de texto, as datas e quaisquer intervalos de saída ainda correspondem à linha de base.
Referência oficial: Ajuda do LibreOffice: Função GetSystemTicks .
2. Remova primeiro as leituras e gravações célula por célula.
Se uma macro percorre um intervalo grande e chama repetidamente métodos como `map` getCellByPosition(), esse padrão geralmente é o primeiro lugar a ser investigado. A API UNO expõe os métodos `map` XCellRangeData.getDataArray()e ` filter` setDataArray()especificamente para mover um intervalo de células completo como uma matriz.
A API oficial afirma que getDataArray()retorna uma sequência de linhas, com cada linha contendo colunas. Os valores são retornados como strings ou números de ponto flutuante de dupla precisão (doubles). setDataArray()Escreve um array de volta para um intervalo, e as dimensões do array devem corresponder a esse intervalo.
Por exemplo, suponha que as colunas A a E contenham a entrada que sua macro transforma. Em vez de ler cada célula individualmente, selecione o intervalo exato de uma só vez:
Dim doc As Object
Dim sheet As Object
Dim sourceRange As Object
Dim data As Variant
doc = ThisComponent
sheet = doc.Sheets.getByName("Data")
' Example only: A2:E50001.
sourceRange = sheet.getCellRangeByPosition(0, 1, 4, 50000)
data = sourceRange.getDataArray()
O processo é executado datana memória BASIC e, em seguida, um array de resultados é gravado em um intervalo de destino correspondente em uma única operação. Isso reduz drasticamente o número de chamadas UNO em comparação com milhares de leituras e gravações individuais.
Referências oficiais: SDK do LibreOffice: XCellRangeData e SDK do LibreOffice: XCellRange .
3. Processe apenas o intervalo que você realmente precisa.
O acesso em massa a matrizes é útil, mas transformar uma planilha desnecessariamente grande em uma matriz pode simplesmente transferir o gargalo para a memória. Evite codificar colunas inteiras ou toda a grade do Calc quando a tarefa afetar apenas uma tabela definida.
Determine a última linha relevante usando informações que sua planilha já possui: a contagem de linhas importadas, o tamanho do resultado do banco de dados, uma coluna-chave designada ou um intervalo criado pelo aplicativo. Em seguida, solicite apenas as linhas e colunas necessárias para a macro.
Isso é especialmente importante quando a planilha contém formatação muito abaixo dos dados reais ou quando conteúdo antigo expandiu a área aparentemente utilizada. Grandes matrizes na memória consomem RAM, e uma alocação excessiva pode ser pior do que processar blocos de tamanho moderado.
Quando mudar para o agrupamento (chunking)
Se uma única matriz causar um aumento repentino no uso de memória, longas pausas antes do início do processamento ou se aproximar dos limites práticos da máquina, processe os dados em blocos. Por exemplo, processe vários milhares de linhas, escreva os resultados e, em seguida, continue com o próximo bloco. Não existe um tamanho de bloco ideal universal; teste com a planilha e o hardware reais.
4. Suspender as notificações de atualização de tela durante tarefas intensas.
Um documento do Calc implementa XModela interface do LibreOffice. Seu lockControllers()método suspende algumas notificações do controlador usadas para atualizações de exibição e unlockControllers()as retoma. Isso pode reduzir o trabalho visual desnecessário enquanto uma macro realiza muitas alterações.
Dim doc As Object
doc = ThisComponent
doc.lockControllers()
' Perform bulk changes here.
doc.unlockControllers()
A API oficial é explícita ao afirmar que os bloqueios e desbloqueios do controlador devem ser pareados. Isso significa que as macros de produção devem incluir tratamento de erros que garanta que o processo unlockControllers()seja concluído mesmo se o processamento falhar. Deixar o documento bloqueado não é uma otimização de desempenho; é um caminho de limpeza inadequado.
Referência oficial: SDK do LibreOffice: XModel .
5. Controle o recálculo automático quando as fórmulas dominam o tempo de execução.
Se a macro alterar repetidamente células que alimentam muitas fórmulas, o Calc poderá gastar um tempo considerável recalculando enquanto a macro ainda estiver atualizando os valores intermediários. O documento da planilha expõe a XCalculatableinterface, incluindo isAutomaticCalculationEnabled(), enableAutomaticCalculation(), calculate(), e calculateAll().
Uma estratégia mais segura é memorizar o modo de cálculo atual do usuário, desativar o cálculo automático apenas durante a atualização e restaurar o estado original posteriormente:
Dim doc As Object
Dim wasAutoCalc As Boolean
doc = ThisComponent
wasAutoCalc = doc.isAutomaticCalculationEnabled()
doc.enableAutomaticCalculation(False)
' Perform bulk updates.
doc.enableAutomaticCalculation(wasAutoCalc)
If wasAutoCalc Then
doc.calculate()
End If
calculate()Recalcula células com problemas. calculateAll()Recalcula cada célula, o que pode ser custoso, portanto, não execute esse processo automaticamente apenas porque uma macro terminou. Use o recálculo completo somente quando a lógica da planilha realmente o exigir.
Assim como no bloqueio do controlador, restaure o estado de cálculo em um caminho de limpeza de erros. Uma macro não deve deixar silenciosamente a planilha do usuário no modo de cálculo manual.
Referência oficial: SDK do LibreOffice: XCalculatable .
6. Combine as otimizações com segurança.
A estrutura mais eficaz geralmente é: determinar um intervalo preciso, lê-lo uma única vez, processar os valores na memória, gravar os resultados em lote e suprimir a interface do usuário desnecessária ou o recálculo apenas durante a duração dessa operação.
Um padrão prático de limpeza no LibreOffice Basic se parece com isto:
Sub ProcessLargeData
Dim doc As Object
Dim sheet As Object
Dim dataRange As Object
Dim data As Variant
Dim wasAutoCalc As Boolean
On Error GoTo CleanUp
doc = ThisComponent
sheet = doc.Sheets.getByName("Data")
dataRange = sheet.getCellRangeByPosition(0, 1, 4, 50000)
wasAutoCalc = doc.isAutomaticCalculationEnabled()
doc.lockControllers()
doc.enableAutomaticCalculation(False)
data = dataRange.getDataArray()
' Transform data in memory here.
' Build an output array with dimensions matching its target range.
CleanUp:
doc.enableAutomaticCalculation(wasAutoCalc)
If doc.hasControllersLocked() Then
doc.unlockControllers()
End If
If wasAutoCalc Then
doc.calculate()
End If
End Sub
O exemplo deixa intencionalmente a lógica de transformação não especificada, pois essa parte depende da sua planilha. A otimização importante é o formato do fluxo de trabalho, não um cálculo comercial hipotético.
7. Considere as funções integradas do Calc antes de reimplementá-las.
O LibreOffice Basic pode chamar funções do Calc por meio do com.sun.star.sheet.FunctionAccessserviço. Se sua macro estiver implementando manualmente uma pesquisa, agregação ou outra operação que o Calc já oferece, usar a função integrada pode simplificar o código e reduzir a necessidade de loops personalizados.
Isso não garante que todas as funções integradas terão um desempenho melhor do que todos os algoritmos personalizados. Faça testes de desempenho com uma carga de trabalho real. A Ajuda oficial mostra como chamar funções do Calc a partir do Basic e observa que os nomes das funções são fornecidos em inglês.
Referência oficial: Ajuda do LibreOffice: Usando funções do Calc em macros .
Como avaliar se a otimização é suficientemente boa?
| Verificar | Bom sinal | Quando mudar de abordagem |
| Tempo de execução | As corridas repetidas são consistentemente mais curtas do que a linha de base. | A maior parte do tempo ainda é gasta em uma única seção; faça um perfil dessa seção separadamente. |
| Correção | Os totais, a contagem de linhas, as fórmulas e os registros representativos correspondem à macro original. | A conversão de arrays altera os tipos de dados ou as dimensões de saída. |
| Memória | A gama de produtos a granel encaixa-se perfeitamente, sem necessidade de trocas ou longas pausas na alocação. | Use blocos menores quando uma matriz de intervalo completo ficar muito grande. |
| Recálculo | O processamento da fórmula ocorre uma única vez após a atualização principal, em vez de após cada gravação. | As dependências de fórmulas exigem valores calculados intermediários. |
| comportamento da interface do usuário | O documento retorna ao estado normal de exibição e cálculo após a conclusão ou falha. | Adicione mecanismos de limpeza/tratamento de erros mais robustos caso o estado possa permanecer alterado. |
Erros comuns que anulam o benefício
- Ler uma planilha inteira para a memória quando apenas algumas colunas são necessárias.
- Utilizando o método
getDataArray(), mas ainda escrevendo cada resultado de volta, célula por célula.
- Desativar o cálculo automático e esquecer de restaurar a configuração anterior.
- Controladores de bloqueio sem um caminho de limpeza confiável.
- Chamar o sistema
calculateAll()após cada pequeno lote, mesmo quando apenas as células com problemas precisam ser recalculadas.
- Avaliar a velocidade a partir de uma única execução, em vez de medições repetidas com os mesmos dados.
- Otimizar o desempenho sem verificar se a saída permanece idêntica.
Onde essas técnicas deixam de ajudar
As transferências de arrays reduzem principalmente a sobrecarga de acesso a objetos em planilhas. Elas não corrigem um algoritmo intrinsecamente custoso. Uma comparação aninhada de cada linha com todas as outras, por exemplo, pode continuar lenta mesmo quando todos os valores estão na memória. Nesse caso, altere o algoritmo: use dicionários ou índices, classifique os dados uma única vez em vez de repetidamente, reduza o trabalho duplicado ou mova a carga de trabalho para uma ferramenta de processamento de dados mais adequada quando a planilha deixar de ser o ambiente de execução correto.
O mesmo se aplica a macros dominadas por chamadas de rede, consultas a bancos de dados, entrada/saída de arquivos ou serviços externos. Meça primeiro para otimizar o gargalo real, em vez do loop visível na planilha.
Ordem de otimização recomendada
- Meça a macro atual com um conjunto de dados repetível.
- Substitua as leituras e gravações repetidas de células por matrizes de intervalo.
- Restrinja o processamento às linhas e colunas exatas necessárias.
- Use o recurso de fragmentação (chunking) se o array principal for muito grande para um uso confortável da memória.
- Controladores de bloqueio durante grandes lotes, com limpeza garantida.
- Suspenda temporariamente o cálculo automático quando o recálculo repetido da fórmula se mostrar um gargalo.
- Recalcule apenas o necessário, restaure o estado da aplicação e verifique o resultado.
- Reavalie. Se o tempo de execução ainda for dominado pelo processamento computacional em vez do acesso à lista UNO, melhore o algoritmo.
Para grandes conjuntos de dados do Calc, reduzir o número de chamadas entre objetos Basic e da planilha geralmente é a melhoria estrutural mais importante. Considere cada otimização adicional como algo a ser medido, não como um ritual. Uma macro mais rápida só é útil quando permanece correta, previsível e de fácil manutenção.