Proyecto: Beam Maximum Axial Forces
Cliente: Diservel S.R.L.
Problema: El cliente necesita generar planillas de calculo Excel en base a los reportes de "Beam Maximum Axial Forces" generados por STAAD Pro. Para esto, un usuario debe generar el reporte en Word, para cada caso de carga, dentro del STAAD Pro, y luego copiar la información a un archivo Excel. Dependiendo de la complejidad de la estructura, y la cantidad de casos de carga, este proceso puede tomar desde 3 hasta 7 horas, entre tiempo de procesamiento y trabajo manual del usuario. El cliente nos pide encontrar una alternativa para agilizar este proceso.
Solución: Una utilidad que genera un archivo Excel, con una hoja por cada caso de carga, utilizando los datos "crudos" generados por STAAD Pro. El tiempo de procesamiento, aun en estructuras complejas, no supera los 60 segundos, y el trabajo manual del usuario se reduce a menos de una hora.
Tecnologías: Java, Swing, ANTLR, Apache POI.
Primeros intentos
Nuestra primer idea fue tratar de solucionar el problema usando el sistema de macros (VBA) provisto por STAAD, pero rápidamente descubrimos que esto no era una autentica solución. STAAD no "genera" archivos de Microsoft Office, si no que envía pedidos a la aplicación, la cual debe estar instalada, para que ejecute comandos dentro de la instancia de la aplicación; por ejemplo, puede enviar un comando que le diga "crea una nueva linea de texto, con el siguiente contenido". Esta es precisamente la razón de la enorme cantidad de tiempo requerido aun para generar reportes relativamente cortos. Además de la cuestión de tiempo de ejecución, presenta un problema de flexibilidad: como se dijo, es preciso tener instalado un Microsoft Office (y solo este, es decir, no se puede utilizar alguna alternativa equivalente como OpenOffice).
Habiendo descartado esta opción, y decidiendo que la solución debía ser una aplicación standalone, se opto por desarrollarla utilizando Java, con Swing para la interfaz gráfica.
El primer paso entonces era obtener la información de Beam Maximum Axial Forces de STAAD (información a la que se puede acceder muy fácilmente a través de la interfaz propia de la aplicación). Para esto se investigo OpenSTAAD, una librería que expone funciones y motores internos de STAAD, y prometía solucionar todos nuestros problemas. Su utilización requiere una instancia corriendo de STAAD, lo que le quita flexibilidad, pero era un precio que estábamos dispuestos a pagar. Lamentablemente, la librería para Java no esta bien documentada, y nuestros intentos de acceder a la información necesaria (principalmente, a la información de fuerzas axiales), terminaron en fracasos: la información que se obtenía era incorrecta o nula.
A veces reinventar la rueda es una buena idea...
Los proyectos de STAAD Pro contienen un archivo, con extensión ANL, que cumple una doble función: contiene una buena parte de las definiciones del proyecto (nodos, barras, casos de carga, grupos, etc), y también contiene, en modo texto, resultados de comandos de análisis (de ahí la extensión) que un usuario haya solicitado. Viendo las posibilidades que ofrecía la aplicación en cuanto a estos reportes, no se encontró el necesitado "Beam Maximum Axial Forces", pero sospechando que el nombre era bastante literal, y luego de confirmarlo con el cliente, decidimos que la mejor solución era rearmar el reporte, esto es, calcular la máxima fuerza axial para cada barra, es decir, la máxima fuerza sobre el eje X, relativo a la misma barra. Se confirmo la simple formula (que solo tenia una particularidad con respecto al signo de estas fuerzas) con los ingenieros que trabajan para el cliente, y se decidió obtener la información de fuerzas de este archivo ANL (las fuerzas ejercidas, para cada caso de carga y para todos los ejes, se podía obtener del análisis de "Member Forces"). Este mismo archivo nos proveía, como se dijo, de cuales eran los casos de carga, los grupos y sus miembros, y mediante otro "análisis", el largo de las barras, y esa es toda la información que se necesitaba. Ahora debíamos sacarla del archivo ANL e introducirle en nuestra aplicación de alguna manera.
.. y otras veces es mejor usar las ruedas que ya existen.
El archivo ANL, como se dijo, contiene toda la información que necesitábamos. Afortunadamente la forma de presentar esta información sigue reglas bastante estrictas, con formatos y ubicaciones, en general, previsibles. Es decir, este archivo respeta una "Gramática", y por lo tanto aprovechamos herramientas existentes, en esta caso ANTLR, para "parsear" el archivo y obtener la información. Por otra parte, el archivo también contiene mucha otra información que no nos interesaba en absoluto, y para la cual no valía la pena el esfuerzo de interpolar la gramática (el hecho de que STAAD use una, no significa que este documentada en algún lado, y si acaso lo esta, no parece ser simple encontrar dicha documentación), y por esta razón se opto finalmente por utilizar un parseo híbrido, utilizando en primer nivel una simple búsqueda de palabras clave que nos indicaran donde comenzaban y terminabas "sectores" o tablas de información, y al encontrarlos se pasaba la responsabilidad a un nivel inferior, mas especifico, el cual, dependiendo el caso, podía hacer un parseo utilizando un "parser" y un "lexer" generados por ANTLR, como en el caso de los grupos, donde se debían interpretar no solo barras sueltas si no rangos de barras, por ejemplo "322 TO 329"; o podía ser un "parser" ad hoc que aprovechara tamaños de campos en tablas, y en efecto solo parsea la información que nos interesaba, como en el caso de la tabla de "member forces", donde sabíamos que los primeros 8 caracteres corresponden a la barra, los siguientes 4 al caso de carga, los siguientes 6 al numero de nodo inicial (dato que no nos interesa), los siguientes 10 a la fuerza en X, es decir, la axial, y el resto de la linea al resto de las fuerzas, que tampoco nos interesan y por lo tanto no perdemos tiempo en leer.
Al mismo tiempo que se lee la información del archivo, se guarda internamente siguiendo la estructura del reporte que nos interesaba generar, y calculando el tan necesitado valor de "beam maximum axial force" utilizando la formula (esto lo podemos realizar a medida que leemos el archivo precisamente porque se trata de un máximo).
Generando el Excel.
Teniendo ya toda la información, solo nos resta volcarla al archivo excel, siguiendo el formato requerido por el cliente. Para realizar esto utilizamos la librería Apache POI, mas precisamente el componente SXSSF que permite crear archivos según el standard OOXML, y requiere muy poca memoria (a cambio de limitaciones, que a nosotros no nos afectan, como el hecho de no poder leer archivos, solo escribirlos, y solo dentro de una "ventana" de filas que siempre debe moverse hacia adelante). Decidimos crear un solo archivo de salida, donde cada hoja es un grupo, y dentro de estos se genera la tabla correspondiente que el cliente requería.
Finalmente se creo una muy simple interfaz, donde el usuario elige el archivo de entrada (ANL) y la ubicación y nombre del archivo de salida (XLSX), que puede verse en la imagen.