Inicio
» Consejos PC
»
Acelere las macros de Calc leyendo y escribiendo datos en lotes.
Acelere las macros de Calc leyendo y escribiendo datos en lotes.
La primera mejora de velocidad más fiable para una macro lenta de Calc consiste en reemplazar las lecturas y escrituras repetidas celda por celda con una lectura de rango, un bucle en memoria y una escritura de rango. Esto reduce las llamadas entre Basic y Calc; sin embargo, no garantiza una mejora de velocidad fija, ya que las fórmulas, el formato, el tamaño del archivo y la lógica de la macro también pueden influir considerablemente en el tiempo de ejecución. El siguiente ejemplo modifica una columna de estado y muestra cómo medir tanto la velocidad como la precisión. Los detalles de la API se verificaron con la documentación de LibreOffice 26.8 el 9 de octubre de 2026.
¿Qué aspectos deberían mejorar y cómo se medirá ese cambio?
Ejecute la macro actual en una copia del libro de trabajo y registre el tiempo transcurrido. Utilice una copia nueva con los mismos datos iniciales para las macros antigua y revisada, o restaure la entrada entre ejecuciones; de lo contrario, la segunda ejecución podría realizar menos trabajo. Mantenga el número de filas, la configuración de cálculo y las condiciones de salida sin cambios. Repita cada ejecución y compare el tiempo típico en lugar de basarse en una ejecución excepcionalmente rápida. Compruebe que el resultado coincida con la regla esperada. Una macro que finaliza antes pero modifica las filas incorrectas no representa una mejora.
La función de LibreOffice Basic Timerinforma los segundos transcurridos desde la medianoche; asígnela a Longvariables para obtener segundos numéricos. Para una ejecución corta, registre un valor inicial y final y réstelos. Si el valor final es menor, la ejecución pasó la medianoche, así que sume 86 400 segundos a la diferencia. El temporizador informa segundos enteros; utilice el ScriptForgeservicio de temporizador para obtener precisión de milisegundos. Consulte la documentación del temporizador de LibreOffice Basic y la documentación del servicio de temporizador de ScriptForge . Mantenga la apertura, el guardado y la inspección manual del libro de trabajo fuera del intervalo medido, a menos que formen parte de la tarea principal.
Comience con el mismo rango de datos contiguos y las mismas condiciones del libro de trabajo para cada ejecución de medición de tiempo.
¿Por qué se ralentizan las macros grandes de Calc?
Un bucle que llama getCellByPosition(), lee y escribe repetidamente las propiedades de celdas individuales requiere que Calc acceda a la interfaz Basic-to-Calc para cada operación. Con muchas filas y columnas, estas llamadas pueden acumularse incluso cuando la transformación en sí es sencilla. Un bucle sobre una matriz en memoria sigue accediendo a cada fila, pero evita una llamada independiente a la API de celda para cada valor.
Primero, elimina las operaciones que no afectan el resultado: evita seleccionar o activar celdas dentro del bucle, no recalcules ni formateas una celda repetidamente cuando una operación de rango final sea suficiente, y no proceses columnas completas si solo se necesita un bloque de datos delimitado. Estos cambios ayudan a identificar el cuello de botella real antes de agregar más controles.
¿Cómo se procesa un rango como si fuera una matriz?
Utilice un rango rectangular que contenga únicamente los valores que su macro pretende modificar. El ejemplo asume una hoja llamada Data, una fila de encabezado en la fila 1 y valores de estado en la columna C. Modifique el nombre de la hoja y el rango para que coincidan con su libro de trabajo. La API getDataArray()devuelve el rango como filas que contienen valores; setDataArray()escribe una matriz del mismo tamaño en ese rango.
Lea el rango rectangular necesario una vez antes del bucle en memoria.
Sub UpdateStatuses
Dim oSheet As Object
Dim oRange As Object
Dim aData As Variant
Dim i As Long
oSheet = ThisComponent.Sheets.getByName("Data")
oRange = oSheet.getCellRangeByName("A2:C10001")
aData = oRange.getDataArray()
For i = LBound(aData) To UBound(aData)
If aData(i)(2) = "pending" Then
aData(i)(2) = "review"
End If
Next i
oRange.setDataArray(aData)
End Sub
La matriz de filas tiene índice base cero: aData(i)(2)se refiere a la tercera columna de cada fila. En este caso, es la columna C, ya que el rango seleccionado comienza en A. La secuencia externa de la matriz representa las filas y cada secuencia interna representa las columnas. El rango que se pasa setDataArray()debe tener las mismas dimensiones que la matriz; una discrepancia genera un error. Consulte la referencia de la API XCellRangeData de LibreOffice y la documentación de matrices de LibreOffice ScriptForge .
Aplica la regla en memoria y, a continuación, escribe la matriz completa en Calc en una sola llamada.
Mantenga las celdas de fórmula fuera de una actualización de solo valor.
getDataArray()Devuelve los valores de las celdas como números o cadenas, no el texto de la fórmula original. Si lee un rango que contiene fórmulas y escribe esa matriz de nuevo con setDataArray(), esas fórmulas pueden ser reemplazadas por sus resultados actuales. Limite el método de matriz de valores a las celdas de entrada/salida que deben contener valores. Cuando una macro debe conservar o modificar fórmulas, utilice los métodos de matriz de fórmulas getFormulaArray()y setFormulaArray(), o trabaje solo en el rango que no contiene fórmulas. Los documentos de referencia de la API XCellRangeFormula que separan esa interfaz.
¿Cuándo debería cambiar la configuración de cálculo o de visualización?
Pruebe estas opciones solo después de medir la versión de la matriz. Si el recálculo de fórmulas representa gran parte de la ejecución, puede consultar isAutomaticCalculationEnabled(), deshabilitar temporalmente el cálculo automático con enableAutomaticCalculation(False), luego restaurar la configuración original y recalcular las celdas modificadas cuando sea necesario. Coloque la restauración en una ruta de limpieza para que un error no deje el libro de trabajo en modo de cálculo manual. No deshabilite el cálculo si la macro necesita resultados de fórmulas nuevos entre pasos. LibreOffice documenta calculate()como recalcular celdas modificadas; calculateAll()fuerza un recálculo completo y puede ser costoso. Consulte la referencia de la API de XCalculable .
lockControllers()Puede suspender algunas notificaciones utilizadas para actualizaciones de visualización mientras una macro modifica muchas celdas. Combine cada bloqueo con unlockControllers(), incluso cuando la macro finaliza a través de un controlador de errores. Esto reduce el trabajo de actualización de la visualización; no desactiva el cálculo de fórmulas ni convierte la lógica por celda en una operación masiva. Úselo para un cuello de botella medido en la actualización de la pantalla, no como sustituto de las matrices de rangos. Consulte la referencia de la API de XModel .
¿Cómo se verifica el cambio y se sabe cuándo cambiar de método?
Ejecute la macro revisada en una copia del libro de trabajo y registre el tiempo de ejecución en las mismas condiciones que la versión de referencia. Compare las filas afectadas, las filas no afectadas, las fórmulas y los totales clave. Guarde, cierre y vuelva a abrir la copia si el flujo de trabajo de producción incluye el guardado; esto puede revelar problemas que una revisión visual rápida no detecta. Debería observarse una mejora constante en ejecuciones repetidas mientras las comprobaciones de salida sigan siendo satisfactorias.
Confirme los valores transformados y registre los tiempos medidos sin asumir de antemano una mejora en la velocidad.
Si la macro aún dedica la mayor parte de su tiempo a fórmulas complejas, formato, E/S de archivos o clasificación, analice esa etapa por separado; las matrices de rangos solo reducen el acceso repetido a las celdas. Para hojas muy grandes, una matriz completa en memoria también puede consumir una cantidad considerable de memoria. Procese algunas columnas a la vez o divida las filas en bloques medidos si aumenta la presión de memoria, verificando que cada bloque comience y termine en las filas previstas. Si los datos ya se encuentran en una base de datos y la tarea consiste en filtrar, agrupar o actualizar registros, trasladar ese trabajo a una consulta de base de datos puede ser más adecuado que cargar cada registro en Calc.