lunes, 26 de mayo de 2014

SPD 2013: Cómo tratar en un Workflow cada fila de las repeating tables de Infopath.

Si alguna vez habéis utilizado Infopath para implantar formularios con lógica, vistas y estructuras de repetición, sabréis que estas últimas tan solo se pueden trabajar cuando SharePoint se basa en una “form list”, ya que la optimización con infopath que se nos permite hacer en el resto de listas está “capada” y muchas de sus opciones no se pueden utilizar, como el caso de las “repeating tables”.
En una FormList, las columnas de datos, no se crean en SharePoint para ser interpretadas por Infopath, sino que es a la inversa: Infopath genera las columnas al publicar el formulario. Algunas de ellas son de tipo especial y no existe forma de poderlas editar posteriormente desde la administración de listas de SharePoint.
Las repeating tables son ese tipo de estructuras que se pueden visualizar en las vistas de SharePoint, pero no podemos manipularlas desde él. Imaginemos un formulario de “informe de gastos mensuales”, donde el usuario puede reportar “n” filas de gastos en función de lo que haya viajado ese mes, o de los diferentes proyectos en los que ha trabajado. Ese informe posteriormente debe ser tratado por un flujo de trabajo, que sirva tanto para autorizar o no los gastos reportados (validación), como para extraer la información fila a fila, de cada gasto reportado, para tratarlos de forma individual en una lista de “gastos mensuales por proyecto”. En esta lista final se sumarían tanto los gastos provenientes del “informe de gastos mensuales” como de otros reportes posibles, tales como “solicitudes de compra” o “solicitudes de viaje”. Pues bien, ¿Cómo tratar esas filas de las repeating tables de InfoPath una a una en el Workflow de SharePoint Designer? Hoy mostraremos la solución en este post.
Para nuestro ejemplo, utilizaremos una repeating table con los siguientes campos:
  • Project: Indica el proyecto donde imputa el gasto
  • Date: Indica la data en la que se produjo el gasto
  • Expense Type: Indica el tipo de gasto
  • Description: Líneas de texto libre para comentar detalles sobre el gasto
  • Amount: Cantidad que hemos gastado.
image
Lo primero que tendremos que hacer desde Infopath es asegurarnos de que todas las columnas incluidas en la repeating table (en nuestro ejemplo “Project”, “Date”, “Expense Type”, “Description” i “Amount”), cuando las publicamos en la Form List con el Publishing Wizard, están añadidas en la sección de “..will be available as colums in SharePoint sites…” y que además la función con las que se representen sea “merge”.

image
Esta función almacena los “n” valores que pueda haber en una repeating table, separados por un salto de línea cada una. En el ejemplo que he mostrado, estas columnas se verían así desde el listado de la Form List de SharePoint:
image
Una vez tengamos las columnas de la repeating table publicadas en SharePoint de este modo, ya podemos empezar con nuestro workflow en SharePoint Designer.
Es importante crear el flujo en modo “SharePoint 2013”, pues utilizaremos algunas funciones que únicamente tiene 2013 y no existían en 2010. Lo primero que haremos será crear las variables que necesitaremos en nuestro flujo. Crearemos 2 variables de tipo String para cada uno de los campos que tiene nuestra repeating table (Projects i Project, Dates i Date, Amounts i Amount, etc.). También necesitaremos una variable de tipo integer (En mi caso la llamé “index”) que haga de índice de iteración por cada fila de la repeating table y otra de tipo number (En mi caso la llamé “calc”) como receptora del cálculo de incremento del índice en cada iteración.
image
Bien, vamos a empezar con el Workflow en sí mismo. En mi caso me interesa que el flujo se ejecute una vez la solicitud de gastos haya sido aprovada, y el proceso de validación pongamos que sea algo tan sencillo como que el campo “Approval Status” cambie a estado “Approved”. Utilizo aquí el “Content Approval” definido en “Yes” dentro de los settings de la Form List (Version Settings) para no complicar el flujo en exceso.
image Así pues, configuramos el flujo para que se ejecute cada vez que el ítem cambie, y su primera línea será la siguiente condición:
image Después de esto estableceremos el valor de las variables que hemos creado para almacenar los strings completos de cada columna de datos. Es decir, usaremos la acción “Set Workflow Variable” (en "Core Actions") para cada una de las columnas que están en la repeating table. Al final podemos poner un “Log to history list” para tener un punto de control sobre el valor inicial de estas variables.
image
Recordemos que estas variables almacenan todos los valores contenidos en la repeating table para cada columna, separados por un salto de línea.
A continuación utilizaremos la acción “Find Substring in String” (en "Utility Actions", únicamente en SPD 2013) para encontrar en qué posición existe un salto de línea. Para ello usaremos cualquiera de las variables inicializadas con los campos de la repeating table del paso anterior. En el ejemplo utilizo la variable “Projects”. Tras esta acción la variable Index almacenará la posición del primer salto de línea.
image

A continuación crearemos el bucle que irá separando cada línea (cada valor) de las columnas de la repeating table. Para ello utilizaremos el "Loop with condition" (En el menú "Loop") y le indicaremos que se ejecutará cuando la variable "index is greater tan 0". De esta forma nos aseguramos que siempre que continúen habiendo saltos de línea el bucle irá extrayendo nuevos valores de la repeating table.

image

 A fin de facilitar la comprensión y implantación del flujo, recomiendo en este punto crear un nuevo step con un título claro sobre lo que vamos a implantar a continuación: Extraer un valor particular de una variable con múltiples valores.

image

Dentro de este step, la primera acción a utilizar será "Extract Substring from Start of String" (en "Utility Actions"). Copiaremos los n caracteres marcados por la variable "index" desde uno de los strings que habíamos inicializado al principio del flujo (contenedor de todas las líneas de la repeating table) a uno de los segundos strings creados para cada variable. En mi ejemplo el substring lo creo desde "Projects" a "Project".

image

El siguiente paso es incrementar en una unidad el valor de la variable Index (para que se situe una posición posterior al salto de línea). Para ello utilizaremos la acción "Do calculation" (En "Core Actions"). El resultado lo guardaremos en la variable que habíamos creado de tipo "Number" (en caso de no haberla creado, SPD la generará automáticamente).

image

Ahora tenemos que actualizar la variable Index con el resultado de este cálculo (la acción "Do Calculation" no permite almacenar el resultado en una variable de tipo "Integer", y por eso tenemos que hacer este paso intermedio). Para ello utilizaremos la acción "Set Workflow Variable" (En "Core Actions").

image

La siguiente acción será "Extract subtring from index of string" (en "Utility Actions"), mediante la cual eliminaremos la línea ya extraída hasta el salto de línea del string inicial que contenía todos los valores de la repeating table. De esta forma dicho string se reducirá en una línea (ya extraída) y entrará en la siguiente iteración del bucle con esa línea menos.

image

Esta acción será la última del Step que habíamos creado. Sin embargo, este Step contiene únicamente las acciones necesarias para extraer una línea de una de las columnas de la repeating table. Ahora tendríamos que hacer exactamente lo mismo para el resto de columnas que la componen. Una de las ventajas de haberlo contenido en un Step, es que podremos, simplemente, copiar y pegar ese Step, y hacer las modificaciones únicamente relativas a las variables que afectan a cada columna en concreto. En la siguiente pantalla, muestro 3 de los 5 Steps que necesito en mi flujo, los otros 2 serían exactamente iguales, como podréis ver en el pantallazo final del flujo al final del post.

image
Tras los Steps de cada una de las columnas de datos de la repeating table, recomendaría hacer un "Log to History List" (en "Core Actions") para poder visualizar en el log del flujo algunas de las variables tratadas y poder tener un punto de control de las mismas.

image

En este punto procederemos a copiar todos los datos de la fila de datos extraída a un nuevo ítem de la lista de "Monthly Expenses", que como expliqué al inicio del ejemplo, contendrá información que vendrá de diversas solicitudes (solicitudes de gasto, solicitudes de viaje, solicitudes de compra...). Para ello utilizaremos la acción "Create List Ítem" (en "List Actions"). SPD creará por defecto una nueva variable de salida (output) donde almacenará el GUID del nuevo ítem creado en la lista de destino.

image

En el detalle de la acción deberíamos tener algo similar a lo siguiente:

image

Y ya como último paso del bucle (loop), actualizaremos de nuevo la variable Index para que tras toda la operativa realizada en la última iteración del bucle, este sepa si ha de volver a realizar una iteración más o no. Para ello volveremos a utilizar la acción “Find Substring in String” (en "Utility Actions", únicamente en SPD 2013), de forma exacta a la descrita antes de entrar en el bucle.

image

Ya fuera del bucle, hay que tener en cuenta que el último retal del string original (última línea de la repeating table) no se habrá copiado dentro del bucle (ya que al no haber más saltos de línea Index será inferior a "0"). Por lo tanto, esta última línea la crearemos una vez el bucle ya haya finalizado, de nuevo con la acción "Create List Ítem" (en "List Actions") tal y como la habíamos utilizado anteriormente en el flujo. También podemos añadir aquí un último Log en el historial del flujo con la acción "Log to History List" (en "Core Actions"), para tener un último punto de control del mismo.

image

¡Y ya lo tenemos listo! Por fin hemos descompuesto todas las filas de la repeating table, únicamente con InfoPath y SharePoint Designer. ¿Alguien lo dudaba?

El flujo final tendrá un aspecto similar al de la siguiente imagen:

Ya con esto me despido por hoy. Espero con este tipo de ejemplos dejar claro que aunque SharePoint Designer e InfoPath tienen sus limitaciones, se pueden construir aplicaciones y flujos relativamente complejos con ellos. Tan solo hay que saber encontrar la manera de ir resolviendo cada reto.

¡¡Un saludo SharePointeros!!

1 comentario:

manuel evelio cutz ake dijo...

Porque cuando me copia los datos a una lista este, no copia el primero de la tabla y el segundo me copia los datos de la segunda y tercera fila de la tabla en una columna de la nueva lista?