Artículo
· 19 hr atrás Lectura de 8 min

Creación de documentos Word avanzados con IRIS

Los documentos de Word se utilizan ampliamente en el mercado. Los usuarios crean con frecuencia contratos, memorandos, currículums, informes, análisis y otros documentos que pueden requerir datos de InterSystems IRIS o que este los capture. Sin embargo, IRIS no dispone de una API, SDK, biblioteca ni adaptador para ello. Esta limitación ya no existe.

La nueva biblioteca de Open Exchange, iris4word (https://openexchange.intersystems.com/package/iris4word), ofrece un SDK de ObjectScript donde el desarrollador pasa cualquier %DynamicObject como parámetro, una plantilla de archivo de Word y recibe un documento listo para usar, con la estructura y el formato definidos en su plantilla.


Para utilizar iris4word

Este artículo utilizará una API REST para obtener el contenido, pero también es posible consultar la base de datos. Para instalar iris4word y el ejemplo que lo utiliza, siga estos pasos:

  1. Si utiliza IPM/ZPM: zpm:USER>install iris4word
  2. Si usas Docker: 
    1. git clone https://github.com/yurimarx/iris4word.git
    2. docker-compose up -d --build
  3. Abra el Postman (para ejecutar el ejemplo de API REST)
  4. Importar la colección de muestras desde (https://raw.githubusercontent.com/yurimarx/iris4word/refs/heads/master/iris4word.postman_collection.json): 
  5. Sube la plantilla de archivo template.docx (en la ruta sample/template.docx de este repositorio o desde https://raw.githubusercontent.com/yurimarx/iris4word/refs/heads/master/sample/template.docx). Para cargar, complete el campo de archivo en la pestaña Body: 
  6.  El proceso de carga enviará la plantilla al servidor para que la utilice iris4word.
  7. Abra el documento de Word 2. Descargue y copie y pegue en el cuerpo este contenido JSON: 
    {
      "company": {
        "name": "ACM Ltda.",
        "address": "Main Street, 123",
        "city": "New York",
        "state": "NY"
      },
      "projects": [
        {
          "name": "System Development X",
          "beginDate": "2024-01-01",
          "endDate": "2024-06-06",
          "team": [
            {"name": "John Star", "role": "Senior Developer"},
            {"name": "Marie Loo", "role": "BDM"}
          ],
          "tasks": [
            {"description": "Requirements", "status": "Done"},
            {"description": "Development", "status": "Doing"}
          ]
        },
        {
          "name": "ERP Development Y",
          "beginDate": "2024-03-03",
          "endDate": "2025-12-12",
          "team": [
            {"name": "Peter Rogers", "role": "Project Manager"},
            {"name": "Robert Plant", "role": "ERP Specialist"}
          ],
          "tasks": [
            {"description": "ERP configuration", "status": "Done"},
            {"description": "User training", "status": "Doing"}
          ]
        }
      ],
      "principalContact": {
        "name": "Carlos Olivera",
        "email": "carlos.olivera@company.com",
        "phone": "+1 555 555-555"
      }
    }
     
  8. En el botón Enviar, seleccione la opción Send and Download:
  9. Vea los resultados:
  10. Compare el contenido JSON con la plantilla.docx y vea las marcas y etiquetas utilizadas.

Entre bastidores

Es muy fácil, con el archivo de plantilla guardado en /tmp/template.docx, simplemente llámelo:

ClassMethod DownloadDoc(template As %String) As %Status
{
    Set tUUID = $System.Util.CreateGUID() 
    Set filePath = "/tmp/"_tUUID_".docx"
    Set jsonContentString = {}.%FromJSON(%request.Content)
    Set sc = ##class(dc.iris4word.WordUtil).GenerateWordFileFromJSON(jsonContentString.%ToJSON(), "/tmp/"_template_".docx", filePath)

    Set %response.NoCharSetConvert=1
    Set %response.Headers("Access-Control-Allow-Origin")="*"
    Do %response.SetHeader("Content-Type","application/vnd.openxmlformats-officedocument.wordprocessingml.document")
    Do %response.SetHeader("Content-Disposition","attachment;filename="""_tUUID_".docx"_"""")
    
    Set stream=##class(%Stream.FileBinary).%New()
    Set sc=stream.LinkToFile(filePath)
    Do stream.OutputToDevice()
    
    Return sc
}

El método de clase ##class(dc.iris4word.WordUtil).GenerateWordFileFromJSON recibe los datos en forma de %DynamicObject, la ruta de la plantilla de Word y la ruta del archivo donde se creará el documento final. Ahora tienes un archivo de Word para enviar al usuario como respuesta. ¡Muy fácil!

El lenguaje de plantilla

iris4word le ofrece un lenguaje de plantilla flexible para componer documentos de Word dinámicos utilizando el editor de Microsoft Word.

Text tag

La etiqueta de texto es el tipo de etiqueta más básico en la plantilla de Word. {{name}} se reemplazará por el valor de la clave name en el modelo de datos. Si la clave no existe, la etiqueta se borrará (el programa puede configurar si se conserva la etiqueta o se lanza una excepción).

Template:

{{name}} always said life was like a box of {{thing}}.

Producción:

Mama always said life was like a box of chocolates.

Picture tag

La etiqueta de imagen empieza con @. Por ejemplo, {{@logo}} buscará el valor con la clave del logo en el modelo de datos y reemplazará la etiqueta con la imagen. Los datos correspondientes a la etiqueta de imagen pueden ser una URL simple, una cadena de ruta o una estructura que contenga el ancho y el alto de la imagen.

Template:

Fruit Logo:
watermelon {{@watermelon}}
lemon {{@lemon}}
banana {{@banana}}

Producción:

Fruit Logo:
watermelon 🍉
lemon 🍋
banana 🍌

Numeración

La etiqueta de lista corresponde a la lista de símbolos o lista numerada de Word, que comienza con *, como {{*number}}.

Template:

{{*list}}


Producción:

● Plug-in grammar
● Supports word text, pictures, table...
● Templates, not just templates, but also style templates

Secciones

Una sección se compone de dos etiquetas, una antes y otra después. La etiqueta de inicio se identifica con ? y la etiqueta de fin, con /. Por ejemplo, {{?section}} es la etiqueta de inicio del bloque de secciones, {{/section}} es la etiqueta de fin y "section" es el nombre de esta sección.

Las secciones son muy útiles al procesar una serie de elementos de documento. Los elementos de documento (texto, imágenes, tablas, etc.) ubicados en una sección pueden renderizarse cero, una o N veces, según el valor de la sección.

Valores falsos o colección vacía

Si el valor de la sección es nulo, falso o una colección vacía, no se mostrarán todos los elementos del documento ubicados en la sección, de forma similar a la condición de la sentencia if, que es falsa.

Modelo de datos:

{
  "announce": false
}
Template:

Made it,Ma!{{?announce}}Top of the world!{{/announce}}
Made it,Ma!
{{?announce}}
Top of the world!🎋
{{/announce}}

Producción:

Made it,Ma!
Made it,Ma!

Valores no falsos y no una colección

Si el valor de la sección no es nulo, falso ni una colección, todos los elementos del documento de la sección se renderizarán una vez, de forma similar a la condición de que la instrucción if sea verdadera.

Modelo de datos:

{
  "person": { "name": "Sayi" }
}
Template:

{{?person}}
  Hi {{name}}!
{{/person}}

Producción:

  Hi Sayi!

Colección no vacía

Si el valor de la sección es una colección no vacía, los elementos del documento de la sección se repetirán una o N veces, según el tamaño de la colección, de forma similar a la sintaxis foreach.

Modelo de datos:

{
  "songs": [
    { "name": "Memories" },
    { "name": "Sugar" },
    { "name": "Last Dance" }
  ]
}
Template:

{{?songs}}
{{name}}
{{/songs}}

Producción:

Memories
Sugar
Last Dance
In the loop, a special tag {{=#this}} can be used to directly refer to the object of the current iteration.

Modelo de datos:

{
  "produces": [
    "application/json",
    "application/xml"
  ]
}
Template:

{{?produces}}
{{=#this}}
{{/produces}}

Producción:

application/json
application/xml

El código Java desarrollado para crear la biblioteca iris4word

iris4word se creó con Java. InterSystems IRIS admite el uso de bibliotecas Java con la función de puerta de enlace externa de Java:

ClassMethod GenerateWordFileFromJSON(jsonContent As %String, wordTemplateFileName As %String, wordFileName As %String) As %Status
{
    Set tSC = $$$OK
    Try {
        
        set javaGate = $system.external.getJavaGateway()  
        do javaGate.addToPath($SYSTEM.Util.BinaryDirectory()_"iris4word-1.0.0-jar-with-dependencies.jar")
        set wordUtil = javaGate.new("iris4word.WordUtil")
...
}

La instrucción $system.external.getJavaGateway devolvió un motor Java y addToPath nos permite usar el archivo iris4word-1.0.0.0-jar-with-dependencies.jar. Esta biblioteca tiene la implementación de iris4word:

package iris4word;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.util.Map;

public class WordUtil {

    public void createFromFile(String jsonFileName, String wordTemplateFileName, String wordFileName) {
        
    	java.util.logging.Logger julLogger2 = java.util.logging.Logger.getLogger("com.deepoove.poi.render.processor.LogProcessor");
    	julLogger2.setLevel(java.util.logging.Level.OFF);
    	
    	java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger("org.slf4j.Logger");
        julLogger.setLevel(java.util.logging.Level.OFF);
        
    	ObjectMapper objectMapper = new ObjectMapper(); 
    	XWPFTemplate template = null;
    	
        try {
            File jsonFile = new File(jsonFileName);
            
            @SuppressWarnings("unchecked")
			Map<String, Object> data = objectMapper.readValue(jsonFile, Map.class);

            Configure config = Configure.builder().build();

            template = XWPFTemplate.compile(wordTemplateFileName, config).render(data);

            template.writeToFile(wordFileName);
            

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        	if(template != null) {        		
        		try {
					template.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
        	}
		}
    }
	
}

Iris4word utilizó la biblioteca de código abierto poi-tl (paquete com.deepoove.poi) para renderizar plantillas de Word con datos dinámicos. Iris4word transformó los datos JSON al formato poi-tl, los convirtió a poi-tl, ejecutó el proceso de renderizado y obtuvo el documento de Word. El documento se guardó en el disco para su uso en código ObjectScript.

ClassMethod GenerateWordFile(jsonFileName As %String, wordTemplateFileName As %String, wordFileName As %String) As %Status
{
    Set tSC = $$$OK
    Try {
        
        set javaGate = $system.external.getJavaGateway()  
        do javaGate.addToPath($SYSTEM.Util.BinaryDirectory()_"iris4word-1.0.0-jar-with-dependencies.jar")
        set wordUtil = javaGate.new("iris4word.WordUtil") 
        
        do wordUtil.createFromFile(jsonFileName, wordTemplateFileName, wordFileName)
        
    }
    Catch ex {
        Set tSC=ex.AsStatus()
    }

    return tSC
}

Este proyecto demuestra cómo no solo Python, sino también Java, pueden ampliar significativamente la funcionalidad de IRIS. ¡Disfrútalo!

Comentarios (0)1
Inicie sesión o regístrese para continuar