jueves, 12 de abril de 2018

Aplicación SAPUI5 para ver un PDF: Introducción (I)

Una aplicación muy común que nos van a pedir en algún momento, es aquella que nos permitirá visualizar un PDF. Pero no un PDF cualquiera, no, nada de un archivo que hemos creado y colgado en algún repositorio, sino un smartform o un adobe form que ya tenemos en SAP y que queremos mostrar. O incluso algún report estándar que se usa mucho y queremos colgarlo en el portal. Nos puede venir a la mente aplicaciones estándar como la del recibo de nómina (my paystubs), donde vamos a ver las monedas de oro que cobramos mensualmente mediante la visualización de un PDF.

Pues nada, eso es lo que vamos a aprender en esta ocasión, la creación de un servicio oData que nos devolverá el contenido de un PDF y visualizaremos en una aplicación SAPUI5.

Lo veremos en tres post, que son los siguientes:

  • En el primero (en este), no jugaremos aún con Fiori. Lo que haremos será generar, en ABAP, el contenido de un PDF en una variable de tipo XSTRING, que es con lo que vamos a trabajar. Para ello, vamos a ver los pasos a seguir para smatforms y adobe forms y haremos un ejemplo más detallado con un report, del que recuperaremos la salida para generar más tarde el PDF. Ojo, que esto del report es sólo para tener un punto de partida, ser tan cutre no debería ser la norma.

  • En el siguiente post, crearemos un servicio oData para poner accesible el contenido del PDF: Aprenderemos a usar entidades de tipo "media" y a saber para qué sirve la opción $value, tocaremos la model provider class (MPC_EXT... sí, esa clase que nunca hace falta tocar) y pondremos disponible el contenido del PDF en la data provider class (DPC_EXT) mediante el método GET_STREAM, usando la función que hemos creado en el punto uno.

  • En el último post, mostraremos el PDF en nuestra aplicación SAPUI5. Para ello, usaremos un componente de tipo sap.ui.core.HTML, donde añadiremos el código HTML estándar que nos permita incrustar el PDF en la página. La URL a usar será la del servicio oData con la opción $value.

Obtener el contenido de un Smartform o un Adobe Form


La forma más evidente que nos puede venir a la mente para obtener un formulario en PDF, es utilizar alguna de las herramientas de las que disponemos para generar formularios dentro de SAP: los smartforms (con la transacción SMARTFORMS) y los formularios de tipo Adobe Form (transacción SFP). No es el ejemplo que vamos a ver en este post, pero sí que veremos las directrices que necesitamos para usarlos.

En ambos casos, el proceso para trabajar es similar:

  • Partimos de un formulario funcional, que nos permite visualizar datos en formato OTF o en formato PDF, pero siempre dentro de SAP.
  • Cada formulario tiene asociado un módulo de funciones, que se regenera cada vez que activamos el formulario y con el que podemos obtener el contenido. Pero para saber el nombre de dicho módulo de funciones, necesitaremos otro módulo de funciones estándar que nos lo devolverá.
  • Tras recuperar su nombre, lo llamamos para obtener el contenido del formulario, que puede ser directamente el XSTRING que buscamos (para el Adobe Form) o el contenido en formato OTF (para el Smartform), que tendremos que convertir con otro módulo de funciones estándar a XSTRING.

Smartform


Los pasos a seguir para un smartform son:

- Recuperamos el nombre del módulo de funciones a usar con:
CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME'
  EXPORTING formname = 'NOMBRE_DEL_SMARTFORM'
  IMPORTING fm_name = lv_nombre_mod_funciones.

- Invocamos el módulo de funciones que hemos obtenido en el punto anterior:
CALL FUNCTION lv_nombre_mod_funciones
  EXPORTING parametros de control y de datos
  IMPORTING job_output_info = ls_resultado.

- Convertimos la salida en XSTRING
CALL FUNCTION 'CONVERT_OTF'
  EXPORTING format = 'PDF'
  IMPORTING bin_file = lv_xstring
  TABLES otf = ls_resultado-otfdata.


Adobe Form


Para el Adobe Form, debemos tener instalados los Adobe Document Services (alias ADS), con el que posiblemente ya hayamos tenido algunos encontronazos. Pero no vamos a entrar en detalles, ya que para los Adobe Forms tendríamos para un montón de post (adobe print forms, adobe interactive forms, procesos y formularios, procesos y formularios en Web Dynpro ABAP, licencias..., vamos, para rato).

Para saber si lo tenemos instalado, nos vale con ejecutar el report FP_TEST_00 (sin miedo, si da error es que no lo tenemos instalado).

El proceso para obtener el contenido de un Adobe Form sería el siguiente:

- Recuperamos el nombre del módulo de funciones a usar con:
CALL FUNCTION 'FP_FUNCTION_MODULE_NAME'
  EXPORTING i_name = 'NOMBRE_DEL_SFP'
  IMPORTING e_funcname = lv_nombre_mod_funciones.

- Abrimos un job para la generación del PDF con
CALL FUNCTION 'FP_JOB_OPEN'
  CHANGING ie_outputparams = configuracion_de_impresion.

- Invocamos el módulo de funciones que usamos, de donde obtenemos el XSTRING
CALL FUNCTION lv_nombre_mod_funciones
  EXPORTING /1BCDWB/DOCXML = datos_de_entrada
  IMPORTING /1BCDWB/FORMOUTPUT = datos_de_salida.

DATA lv_xstring TYPE xstring.
lv_xstring = datos_de_salida-pdf.

- Cerramos el job del PDF:
CALL FUNCTION 'FP_JOB_CLOSE'.

Obtener el contenido en plan cutre: De la salida de un report


Nosotros no nos vamos a complicar tanto la vida para este ejemplo. En lugar de crear un smartform o un Adobe Form, utilizaremos la salida de un simple report (de esos de la SE38, como unos campeones).

¿Esto que utilidad tiene? Que nos permitirá generar un PDF a partir de cualquier report con una salida clásica, incluso de reports estándar.

Sí, suena cutre, es como tener el poder de crear elfos pero preferir crear trollkins... pero a lo mejor es más útil de lo que nos pensamos.

En nuestro ejemplo, vamos a crear un sencillo report, que debería consultar una tabla de autores y libros... frikis, por supuesto. Aunque lo vamos a picar todo por código.

El listado de salida será diferente, dependiendo de un parámetro de entrada

Lo que haremos será volcar el contenido de dicho listado ABAP al SPOOL y, de ahí, podremos usar una función estándar para recuperar el contenido en formato XSTRING.

El ejemplo es muy básico, porque no es el objetivo final del post, pero esto nos valdrá para poder generar una aplicación con PDF.

El report


Primero nos creamos el report, uno sencillo como el siguiente, que hace una serie de WRITES dependiendo del parámetro de entrada:

Menuda pedazo de aplicación

Lo que queremos es mostrar la salida de nuestro report pero en formato PDF. Dicha salida sería tan magnífica como ésta:

Sí, "la Úrsula" tiene muchos más libros, pero tampoco me voy a poner a picar todos

Recuperar el XSTRING con la salida del report


Para poder usar esta salida, tendremos que usar cierto código que podríamos encapsular en el método correspondiente del servicio oData. Pero en nuestro caso lo vamos a hacer en un módulo de funciones, que nos devolverá el XSTRING, y en el siguiente post reutilizaremos dicho módulo en el método del servicio oData.

La función hará un submit al report y lo volcará en el SPOOL.

Ojo, este sistema no es el ideal para volcar información confidencial, ya que alguien sin autorización para ver esta información, podría acceder a ella de forma indirecta si tuviese autorización para ver el SPOOL. No obstante, podemos añadir código adicional que borre la entrada del spool tras recuperar el contenido. En nuestro ejemplo no hay problemas de confidencialidad, así que esto no es importante.

Del SPOOL leeremos la última entrada del usuario actual (en la tabla TSP01 o con la función RSPO_FIND_SPOOL_REQUESTS). Como es una salida de ABAP, usamos la función CONVERT_ABAPSPOOLJOB_2_PDF para generar el XSTRING que buscamos.

Es un ejemplo muy sencillo, sin gestión de errores ni nada por el estilo, sólo buscamos entender el proceso, que es:

- Llamar al report y volcarlo en el SPOOL, pero sin que aparezca la pantalla del propio SPOOL.
SUBMIT report TO SAP-SPOOL
  WITHOUT SPOOL DYNPRO
  WITH param1 = dato1
  WITH param2 = dato2
  ...
  AND RETURN.

- Recuperar el id del SPOOL que vamos a leer:
SELECT a la tabla TSP01 o usar la función RSPO_FIND_SPOOL_REQUESTS.

- Convertir la salida ABAP en XSTRING:
CONVERT_ABAPSPOOLJOB_2_PDF
  EXPORTING
    scr_spoolid =  el_id_recuperado_antes
    no_dialog = 'X'
    pdf_destination = 'X'.



Y con esto, ya hemos obtenido el contenido que buscábamos, un XSTRING que devolvemos en la variable EV_XCONTENT.

En el siguiente post, nos crearemos el servicio oData que llamará a este módulo de funciones para poner el PDF disponible para la aplicación.

3 comentarios:

  1. Super interesante! muchas gracias ! ! ! ! ya me estaba planteando hacer algo asi . Bueno ahora si leer tu articulo primero vine a dar las gracias jeje

    ResponderEliminar
    Respuestas
    1. Bueno, ésta era la parte básica, en el siguiente ya comienza lo interesante, el oData, y luego la app.

      Eliminar

Nota: solo los miembros de este blog pueden publicar comentarios.