Las macros de LibreOffice Calc suelen ralentizarse en hojas de cálculo grandes por una razón sencilla: la macro dedica más tiempo a cruzar el límite del objeto UNO que a realizar el cálculo propiamente dicho. Leer una celda, modificarla y volver a escribirla miles de veces puede resultar mucho más costoso que mover los mismos datos en bloques más grandes.
El objetivo no es lograr que cada macro sea "rápida" en abstracto. Una optimización útil debería producir el mismo resultado, completarse en menos tiempo con el mismo conjunto de datos, mantener la capacidad de respuesta de Calc para el flujo de trabajo y evitar generar nuevos problemas de corrección o memoria. Las técnicas que se describen a continuación se centran en esos resultados medibles.
A fecha de octubre de 2026, la documentación actual del SDK de LibreOffice identifica las interfaces de hoja de cálculo utilizadas aquí en la referencia de la API de LibreOffice 26.8. Los métodos principales son interfaces UNO de larga trayectoria, en lugar de una nueva función de rendimiento.
1. Mide la macro antes de cambiarla.
Comience con una línea base reproducible. LibreOffice Basic proporciona GetSystemTicks(), que la Ayuda oficial describe como una forma de medir los ciclos del sistema y optimizar los procesos. Envuelva la parte de la macro que realmente desea mejorar en lugar de medir el tiempo de apertura del libro de trabajo, las indicaciones del usuario o la configuración no relacionada.
Dim t0 As Long, elapsed As Long
t0 = GetSystemTicks()
' Run the work you want to measure here.
elapsed = GetSystemTicks() - t0
MsgBox "Elapsed ticks: " & elapsed
Ejecute la misma operación varias veces en la misma copia del archivo. La primera ejecución puede diferir debido a la caché del sistema de archivos, el estado de la fórmula u otras operaciones puntuales. Registre el tamaño del conjunto de datos, el rango procesado y si se habilitó el cálculo automático para que sus comparaciones sigan siendo relevantes.
Un buen resultado no se limita a un tiempo de ejecución menor. Confirme que el número de filas, los totales, las fórmulas, los valores de texto, las fechas y cualquier rango de salida sigan coincidiendo con el valor de referencia.
Referencia oficial: Ayuda de LibreOffice: Función GetSystemTicks .
2. Elimine primero las lecturas y escrituras celda por celda.
Si una macro recorre un rango grande y llama repetidamente a métodos como getCellByPosition(), ese patrón suele ser el primer lugar donde buscar. La API de UNO expone XCellRangeData.getDataArray()y setDataArray()específicamente para mover un rango completo de celdas como una matriz.
La API oficial indica que getDataArray()devuelve una secuencia de filas, donde cada fila contiene columnas. Los valores se devuelven como cadenas o números decimales. setDataArray()Escribe una matriz en un rango, y las dimensiones de la matriz deben coincidir con dicho rango.
Por ejemplo, supongamos que las columnas A a E contienen los datos de entrada que su macro transforma. En lugar de leer cada celda individualmente, seleccione el rango exacto una sola 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()
El programa se procesa dataen la memoria básica y, a continuación, se escribe una matriz de resultados en un rango de destino coincidente en una sola operación. Esto reduce drásticamente el número de llamadas a UNO en comparación con miles de lecturas y escrituras individuales.
Referencias oficiales: LibreOffice SDK: XCellRangeData y LibreOffice SDK: XCellRange .
3. Procese solo el rango que realmente necesita.
El acceso masivo a matrices es útil, pero convertir una hoja de cálculo excesivamente grande en una matriz puede simplemente trasladar el cuello de botella a la memoria. Evite codificar columnas completas o la cuadrícula completa de Calc cuando la tarea solo acceda a una tabla definida.
Determina la última fila relevante utilizando la información que tu libro de trabajo ya conoce: el número de filas importadas, el tamaño del resultado de la base de datos, una columna clave designada o un rango creado por la aplicación. Luego, solicita solo las filas y columnas que requiere la macro.
Esto es especialmente importante cuando la hoja de cálculo contiene formato muy por debajo de los datos reales o cuando el contenido antiguo ha aumentado el área utilizada aparente. Las matrices grandes en memoria consumen RAM, y una asignación excesiva puede ser peor que procesar bloques de tamaño moderado.
Cuándo cambiar a la segmentación
Si un solo array provoca un aumento brusco en el uso de memoria, genera largas pausas antes de que comience el procesamiento o se acerca a los límites prácticos de la máquina, procese los datos en bloques. Por ejemplo, procese varios miles de filas, escriba los resultados y luego continúe con el siguiente bloque. No existe un tamaño de bloque ideal universal; realice pruebas con el libro de trabajo y el hardware reales.
4. Suspender las notificaciones de actualización de pantalla durante tareas pesadas.
Un documento de Calc implementa XModella interfaz de LibreOffice. Su lockControllers()método suspende algunas notificaciones del controlador utilizadas para las actualizaciones de visualización, mientras que unlockControllers()las reanuda. Esto puede reducir el trabajo visual innecesario mientras una macro realiza muchos cambios.
Dim doc As Object
doc = ThisComponent
doc.lockControllers()
' Perform bulk changes here.
doc.unlockControllers()
La API oficial especifica que los bloqueos y desbloqueos del controlador deben ir emparejados. Esto significa que las macros de producción deben incluir un manejo de errores que garantice que unlockControllers()se alcance el objetivo incluso si el procesamiento falla. Dejar el documento bloqueado no optimiza el rendimiento; simplemente provoca una interrupción en el proceso de limpieza.
Referencia oficial: LibreOffice SDK: XModel .
5. Controlar el recálculo automático cuando las fórmulas dominan el tiempo de ejecución.
Si la macro cambia repetidamente las celdas que alimentan muchas fórmulas, Calc puede dedicar mucho tiempo a recalcular mientras la macro sigue actualizando los valores intermedios. El documento de hoja de cálculo expone la XCalculatableinterfaz, incluyendo isAutomaticCalculationEnabled(), enableAutomaticCalculation(), calculate(), y calculateAll().
Un método más seguro consiste en recordar el modo de cálculo actual del usuario, deshabilitar el cálculo automático solo durante la actualización y restaurar el 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 las celdas modificadas. calculateAll()Recalcula todas las celdas, lo cual puede resultar costoso, así que no lo llames automáticamente solo porque una macro haya terminado. Usa el recálculo completo solo cuando la lógica del libro de trabajo lo requiera.
Al igual que con el bloqueo del controlador, restaure el estado de cálculo en una ruta de limpieza de errores. Una macro no debe dejar silenciosamente el libro de trabajo del usuario en modo de cálculo manual.
Referencia oficial: LibreOffice SDK: XCalculable .
6. Combine las optimizaciones de forma segura.
La estructura más eficaz suele ser la siguiente: determinar un rango preciso, leerlo una sola vez, procesar los valores en memoria, escribir los resultados en bloque y suprimir el trabajo innecesario de interfaz de usuario o recálculo solo durante la duración de esa operación.
Un patrón de limpieza práctico en LibreOffice Basic tiene este aspecto:
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
El ejemplo deja intencionadamente sin especificar la lógica de transformación, ya que esa parte depende de su libro de trabajo. La optimización importante reside en la estructura del flujo de trabajo, no en un cálculo empresarial inventado.
7. Considere las funciones integradas de Calc antes de reimplementarlas.
LibreOffice Basic puede llamar a funciones de Calc a través de este com.sun.star.sheet.FunctionAccessservicio. Si su macro implementa manualmente una búsqueda, agregación u otra operación que Calc ya proporciona, usar la función integrada puede simplificar el código y reducir la necesidad de bucles personalizados.
Esto no garantiza que todas las funciones integradas superen el rendimiento de todos los algoritmos personalizados. Realice pruebas de rendimiento con la carga de trabajo real. La ayuda oficial muestra cómo llamar a las funciones de Calc desde Basic e indica que los nombres de las funciones se proporcionan en inglés.
Referencia oficial: Ayuda de LibreOffice: Uso de funciones de Calc en macros .
Cómo juzgar si la optimización es suficientemente buena
| Controlar | Buena señal | Cuándo cambiar de enfoque |
| Tiempo de ejecución | Las carreras repetidas son sistemáticamente más cortas que la línea base. | La mayor parte del tiempo se sigue dedicando a una sola sección; describa esa sección por separado. |
| Exactitud | Los totales, el recuento de filas, las fórmulas y los registros representativos coinciden con la macro original. | La conversión de matrices modifica los tipos de datos o las dimensiones de salida. |
| Memoria | La amplia gama de productos se adapta cómodamente sin necesidad de intercambios ni largas pausas en la asignación. | Utilice fragmentos más pequeños cuando una matriz de rango completo se vuelva demasiado grande. |
| Recálculo | El procesamiento de fórmulas se realiza una sola vez después de la actualización principal, en lugar de después de cada escritura. | Las dependencias de las fórmulas requieren valores calculados intermedios. |
| comportamiento de la interfaz de usuario | El documento vuelve a su estado normal de visualización y cálculo tras su finalización o fallo. | Si el estado puede permanecer alterado, es necesario implementar medidas de limpieza/manejo de errores más rigurosas. |
Errores comunes que anulan el beneficio
- Cargar en la memoria una hoja de cálculo completa cuando solo se necesitan unas pocas columnas.
- Utilizando
getDataArray()pero aún así escribiendo cada resultado celda por celda.
- Desactivar el cálculo automático y olvidar restaurar la configuración anterior.
- Bloqueo de controladores sin una ruta de limpieza fiable.
- Llamar
calculateAll()después de cada lote pequeño, incluso cuando solo las celdas sucias necesitan ser recálculo.
- Evaluar la velocidad a partir de una sola prueba en lugar de realizar mediciones repetidas con los mismos datos.
- Optimizar el rendimiento sin comprobar que el resultado siga siendo idéntico.
Dónde dejan de ayudar estas técnicas
Las transferencias de matrices reducen principalmente la sobrecarga de acceso a los objetos de la hoja de cálculo. No solucionan un algoritmo intrínsecamente costoso. Por ejemplo, una comparación anidada de cada fila con todas las demás puede seguir siendo lenta incluso cuando todos los valores están en memoria. En ese caso, cambie el algoritmo: utilice diccionarios o índices, ordene una sola vez en lugar de repetidamente, reduzca el trabajo duplicado o traslade la carga de trabajo a una herramienta de procesamiento de datos más adecuada cuando la hoja de cálculo ya no sea el entorno de ejecución apropiado.
Lo mismo se aplica a las macros que dependen en gran medida de llamadas de red, consultas a bases de datos, operaciones de entrada/salida de archivos o servicios externos. Mida primero para optimizar el cuello de botella real en lugar del bucle visible de la hoja de cálculo.
Orden de optimización recomendada
- Mida la macro actual con un conjunto de datos repetible.
- Reemplace las lecturas y escrituras repetidas de celdas con matrices de rangos.
- Limite el procesamiento a las filas y columnas exactas necesarias.
- Utilice la segmentación si el array principal es demasiado grande para un uso cómodo de la memoria.
- Bloquee los controladores durante el procesamiento de grandes lotes, con limpieza garantizada.
- Suspenda temporalmente el cálculo automático cuando se demuestre que el recálculo repetido de la fórmula constituye un cuello de botella.
- Recalcula solo lo necesario, restaura el estado de la aplicación y verifica el resultado.
- Reevaluar. Si el tiempo de ejecución sigue estando dominado por el cálculo en lugar del acceso a UNO, mejore el algoritmo.
Para conjuntos de datos grandes de Calc, reducir el número de llamadas entre objetos Basic y de hoja de cálculo suele ser la mejora estructural más importante. Cada optimización adicional debe medirse, no implementarse de forma rutinaria. Una macro más rápida solo es útil si sigue siendo correcta, predecible y fácil de mantener.