viernes, 16 de octubre de 2015

Excel VBA - Copiar Filas en Excel con una Macro

Hace poco tuve un requerimiento en el cual debía generar un reporte con Excel a partir de una plantilla base. El core del asunto es que no podía saber de antemano cual era la cantidad de registros que iba  a tener el reporte y las filas del mismo debían contar con un formato especial.

Consideré que se veía horrible si dejaba simplemente toda la hoja de Excel con el formato preestablecido (este consistía en celdas con bordes, algunas con fondos de diversos colores, formatos de fecha y de contabilidad), así que decidí ubicar en la plantilla una única fila con dichos formato y, en tiempo de ejecución, replicar esa fila "base" tantas veces como fuera necesario.

Para ello, desde el sistema que hace las veces de modelo y control de este desarrollo, incluí una linea adicional que agregaba en una celda especifica de la hoja de Excel la cantidad de registros que debía incluir el reporte.

La macro resultante que deseo compartir es la siguiente:


Como es de suponer, en la variable cant se recoge el valor que indica la cantidad de filas en las cuales esta macro debe replicar el formato. La variable val indica la fila en la cual se comienza a replicar el formato (la fila base es la 3 y en esa fila también va información, por eso se resta 1).

Luego del bucle que replica el formato de la fila, se borra de la celda B1 el valor que indicaba la cantidad de registros del reporte.

Esta forma de replicar formatos de fila puede ser muy simple cuando no se tenga precisamente un formato fijo (en este caso, se aprovechó que el reporte siempre empezaba en la columna B y acababa en la columna V) pero se pueda extrapolar a otros escenarios.

Si alguien que lea esta lineas puede encontrar la forma de realizar la misma acción sin necesidad del bucle, le agradecería que nos compartiera su solución.

domingo, 11 de octubre de 2015

Java - Concatenar cadenas con +: Un pecado mortal

Recientemente he estado revisando los apuntes y algunos libros de programación para retomar mi trabajo en Java. Una de las primeras anotaciones importantes que encontré en dicha información es la que resalta el uso de las clases StringBuffer y StringBuilder.

Supongamos que se tiene la siguiente clase, cuyo único propósito es concatenar un conjunto de 100000 caracteres en un único objeto String:



Como se puede apreciar, la concatenación se realiza con el operador +. Luego de ejecutar dicho programa, se puede verificar que el tiempo de ejecución del mismo el de alrededor de 9000 ms (existía en algunos casos cierta variabilidad de unos 200 a 300 ms que no comprendo aún porque ocurre). Tal y como en mis libros ponía, decidí verificar el rendimiento del mismo programa pero usando las clases mencionadas en el título de esta entrada. Las versiones fueron las siguientes:


Los resultados obtenidos fueron una descomunal diferencia de tiempo entre el concatenar por medio del operador + y el uso de las clases StringBuilder y StringBuffer. Ya que en algunas veces existía diferencia entre las ejecuciones, decidí ejecutar cada programa en 5 ocasiones y después resumir los resultados en una tabla, la cual muestro a continuación:


Como es evidente, el uso del operador + aumenta dramáticamente la ejecución de una clase sencilla como la que se ha tomado de ejemplo. Las clases StringBuffer y StringBuilder son la forma más adecuada de realizar una concatenación, sobre todo en proyectos donde el trabajo con caracteres sea fundamental. De momento, el pecado de concatenar con + solo debería ser ‘permisible’ en una que otra línea de código… como para imprimir un resultado en un out.println… ¿o no?

Para una próxima entrada, diferenciaremos entre StringBuffer y StringBuilder.




Java - Finalize y Garbage Collector: Los que nos salvan de colgarnos por memoria

En mi trabajo de grado tuve un problema relacionado con el manejo de memoria. En ese proyecto, enfocado en el análisis de cadenas, era imprescindible crear montones de objetos, analizarlos y obtener información a partir de ellos. Sabía que existía el Garbage Collector y que este era el encargado de liberar la memoria que dejaban todos mis objetos desreferenciados. Este es un ejemplo del mal uso de la memoria que a veces hacemos sin darle mucha importancia:


Es decir, cada que utilizamos y reutilizamos la misma variable para crear objetos de una clase, estamos dejando muchísimo trabajo al Garbage Collector, quien se encargará de liberar toda la memoria que ocupaban, por ejemplo, las 99 instancias anteriores de ObjetoPrueba.

Lo que no sabía hasta hace muy poco es que existe un método de la clase Object (y por lo tanto, de todas las clases Java) que es invocado por el Garbage Collector justo antes de que el objeto pase a mejor vida: el método finalize.

Supongamos que tenemos la definición de la siguiente clase (ObjetoPrueba) y el main ubicado en la clase Ejecutable:



Si ejecutamos este código podemos visualizar, como pocas veces pasa, cual es la labor del recolector de basura en tiempo real. El programa comienza creando instancias del ObjetoPrueba y justo cuando el Garbage Collector decide entrar al juego, se bajan de la memoria un numero crítico de instancias (la gran mayoría de ellas, donde ninguna esta referenciada), lo cual alivia la carga de memoria del sistema.

No es muy usual que dentro de un programa se utilice directamente el método finalize, pero es algo que puede llegar a ser muy interesante de experimentar si se trata de programas donde la creación de objetos es de vital importancia. Mas aún, si se tiene un programa donde la memoria es limitada y se cuenta con algoritmos de análisis de objetos, implementar y el método finalize puede llegar a ser una gran ventaja para el desarrollador.

En el momento de escribir estas lineas se me ocurre por ejemplo el poder determinar, en tiempo de ejecución, de cuales clases estamos creando una mayor cantidad de objetos que por algún motivo se quedan desreferenciados y solo cargan el sistema. Sabiendo eso se podría determinar cuales son clases críticas. Esto puede ser muy útil para que redefinamos los algoritmos que rodean a esa clase, o se cambie la implementación de la misma para que esto no suceda. Todo esto es con el fin de perfeccionar nuestras propias técnicas de desarrollo y así podamos generar programas más rápidos y eficientes.