por Justin Joyce, LANtek
Nota
Este artículo forma parte de una colección de entradas de cuatro años del blog Get the Point para usuarios finales de SharePoint.
Información general: informes de antigüedad personalizados sin código
Una de las partes funcionales más solicitadas de un sitio de SharePoint es un informe de antigüedad para tareas o elementos de lista. En otras palabras, ¿cuántos días/meses han pasado desde la última modificación de este elemento de lista?
En la superficie, esto parece ser una solicitud muy simple. Después de todo, tenemos fechas para los elementos que se crean y modifican, tenemos la capacidad de almacenar fechas personalizadas cuando se producen ciertos cambios en los elementos a través de receptores de eventos. Hemos calculado columnas en las que podemos incluir fórmulas similares a Excel para trabajar con nuestra información. Esta parece una propuesta bastante sencilla. Seleccionamos un campo de fecha, creamos una columna calculada y, a continuación, hacemos una fórmula similar a [DateField] – [Today]. ¡Ah, aunque no tan rápido! Como sabe cualquiera que haya intentado esta tarea "simple", tratar de usar algo como [Hoy] en una columna calculada causa problemas. Intente insertar [Hoy] en el cuadro de fórmula de la columna calculada le dará un mensaje de error similar al siguiente:
¿Por qué pasa esto? Bueno, tiene que ver con la forma en que se calculan las columnas calculadas.
Tomemos una fórmula simple como ejemplo:
= IF( [Columna1]<=[Columna2], "Correcto", "No correcto")
Todo esto dice que si Columna1 es menor o igual que Columna2, mostrar Correcto, de lo contrario, mostrar No correcto. Esta es una fórmula básica bastante típica para una columna calculada y hace una suposición básica sobre el elemento de lista que contiene estas columnas: Los valores de Columna1 y Columna2 nunca podrán cambiar sin un evento de actualización en el elemento de lista.
Así es, las columnas calculadas solo se recalcularán cuando se actualice (o cree) la lista, ya que suponen que la información que está calculando está contenida en el propio elemento. Esto crea un problema cuando intenta usar algo que cambia independientemente de los campos del elemento, como la fecha actual.
Ahora bien, no estuve en la reunión en la que decidieron que esta es la forma en que funcionarían las columnas calculadas, sin embargo, si tuviera que hacer una suposición informada, asumiría que funcionan de esta manera para el rendimiento. Imagine que tiene una lista de varios miles de elementos, cada uno de los cuales contiene una columna calculada que necesita una actualización "activa". Eso significaría que algún mecanismo, tal vez un trabajo de temporizador, tendría que iterar a través de cada elemento que contiene esa columna calculada de vez en cuando y actualizar su valor. Esto podría ser extremadamente agotador en términos de rendimiento porque con implementaciones más grandes, este trabajo podría ejecutarse constantemente y cambiar las cosas. Eso es solo mi suposición, pero tiene bastante sentido si lo piensas.
Hay algunas sugerencias para soluciones similares que implican engañar a SharePoint para que acepte un valor Hoy creando primero una columna denominada Hoy, agregándola a la fórmula y eliminándola. Todo esto está muy bien, pero recuerde lo que dije sobre cuándo se actualizan las columnas calculadas. Este valor solo cambiará cuando se actualice el elemento, lo que significa que los valores pronto serán incorrectos, especialmente en el caso de un cálculo de un día.
He visto a otros usar JavaScript inteligente para escribir los valores en la página. Esto también funcionaría, pero estoy bastante en contra del script del cliente cuando se puede evitar.
Implementación:
Entonces, ¿qué hacer? Las columnas calculadas están fuera de discusión para las llamadas funciones "volátiles" como Hoy. Es posible que podamos desarrollar algún código personalizado para que se encargue de esto por nosotros, como una columna calculada, un trabajo de temporizador o un proceso programado para venir y actualizar cada elemento que necesita este cálculo. Sin embargo, eso nos lleva de vuelta al problema del rendimiento que mencioné en el último párrafo y, además, es una solución frágil que sería muy específica para el sitio/lista/columna en cuestión. Además de esas dos preocupaciones, también tendrías que ir a buscar a un tipo nerd, como yo, que sepa cómo codificar y persuadirlo para que desarrolle esta solución para ti. Pero hay una manera más fácil.
Si tiene derechos para crear campos y editar páginas en su sitio, y tiene un poco de conocimiento sobre XSLT y la creación de vistas, puede armar una plantilla XSL que se pueda incluir en una vista de lista y calculará fielmente su valor cada vez que se solicite la página. Este escenario elimina nuestra preocupación sobre el rendimiento y no requiere que se desarrolle e implemente código personalizado a través de una solución.
Perfecto. Entonces, ¿cómo lo hacemos?
- Cree o seleccione el campo que actuará como nuestro origen. Debe ser un tipo de fecha.
- Cree nuestro campo que actuará como marcador de posición para el valor que se está calculando.
- Agregue ambos campos a un tipo de contenido y agregue ese tipo de contenido a una lista.
- Cree una vista de la lista que contenga las columnas origen y marcador de posición.
- Cargue la plantilla XSL en la biblioteca de estilos.
- Establezca la propiedad "Vínculo XSL" para el elemento web Vista de lista a través de la interfaz de usuario.
- ¡Perfecto!
Exploremos un caso de uso de ejemplo y recorramos la implementación. Nuestro cliente quería una vista de su lista principal que le indicara cuánto tiempo había estado en su estado un elemento de la lista en particular. Esta lista contenía un tipo de contenido de sitio personalizado derivado del tipo de elemento y agregado a la lista. Ya había un receptor de eventos que captura cada vez que se cambió el campo de estado del elemento de lista y guardó esa fecha en una columna denominada "Estado de fecha cambiado". Todo este cableado no es necesario y se puede hacer con CUALQUIER campo de fecha (da la casualidad de que esta es nuestra implementación, pero siéntase libre de experimentar). Lo mínimo que necesitará es su campo de fecha de origen y el campo de marcador de posición para mantener su cálculo (más sobre esto en el siguiente párrafo) agregado a su lista, aunque le sugiero que use columnas de sitio y tipos de contenido de sitio en caso de que desee reutilizar esta solución en otros lugares de su sitio.
Así que tenemos nuestra fecha de origen que podemos usar en nuestro cálculo contra la fecha de hoy. Ahora podemos crear una columna de sitio personalizada para usarla como contenedor de nuestro valor calculado. En este caso, elegí usar una columna calculada, ya que no se podrá cambiar en los formularios nuevos o editar elementos, pero se puede seleccionar para mostrarla en las vistas, ya que no queremos que los usuarios ingresen valores arbitrarios en esta columna. Podría ser confuso por qué no se muestra en las vistas, etc.
Ahora que tenemos nuestra columna de sitio, podemos agregarla a nuestros tipos de contenido que se usarán en nuestra lista. A continuación, debemos crear nuestra vista que luego se personalizará con nuestro XSLT. Asegúrese de crear una vista estándar que contenga su columna de fecha de origen y su nueva columna calculada que actuará como marcador de posición para el valor calculado.
Ahora tenemos todo lo que necesitaremos para respaldar nuestro informe de envejecimiento personalizado. Todo lo que queda es crear nuestra plantilla XSL, cargarla en la Biblioteca de estilos del sitio y vincularla a nuestra vista de lista. La plantilla XSL que usaremos contendrá un marcado normal generado por SharePoint para generar la vista, así como nuestro propio marcado personalizado que se usa para anular ciertas partes de esto y calcular el valor deseado para nosotros.
Dando crédito a quien se lo merece, las plantillas XSL para hacer los cálculos reales que estoy usando para esta solución fueron proporcionadas amablemente por "swirch" en los foros de MSDN:
http://social.msdn.microsoft.com/Forums/en-US/sharepointcustomization/thread/aeda905b-9bc6-40c4-bd22-21306c5cb0d2/
Descargue la hoja de estilo XSL (aging.zip) que he reunido y que se encuentra aquí:
https://OneDrive.live.com/?cid=c262e8e2d59a86d9&permissionsChanged=1&id=C262E8E2D59A86D9!104
Al abrir esto en su editor de texto favorito, verá un montón de marcado XSL normal de SharePoint para representar las vistas, si sigue desplazándose hacia abajo hasta la línea 357, verá el inicio de las plantillas personalizadas que agregué al marcado, la primera es la plantilla "DateDiff" seguida de "calculate-julian-day" y "FieldRef_printTableCell_EcbAllowed.Days_x0020_At_x0020_Status". Estas son nuestras tres plantillas que realizarán y mostrarán nuestros cálculos en nuestras vistas. Si va a usar nombres de campo diferentes a los especificados anteriormente en este artículo, deberá revisar estas plantillas y reemplazar cualquier referencia a los otros nombres. Recuerde que, para esto, querrá usar el nombre INTERNO del campo, no el nombre para mostrar.
Una vez que esté satisfecho de que la plantilla está lista para funcionar, navegue hasta su biblioteca de estilos y cárguela en la carpeta "Hojas de estilo XSL" y luego copie el enlace al archivo. Esto nos permitirá realizar cambios fácilmente más tarde o agregarlo a diferentes partes del sitio a nuestro antojo.
Después, vaya a la lista y seleccione la vista que creó anteriormente en este artículo. En el menú "Acciones del sitio", haga clic en "Editar página".
Busque el elemento web Vista de lista en la página y abra el menú Elemento web haciendo clic en la pequeña flecha orientada hacia abajo de la esquina superior derecha. En este menú, seleccione "Editar elemento web".
Se abrirá el menú del elemento web en el lado derecho de la ventana del explorador.
Haga clic en + para la sección "Miscelánea" y localice la propiedad "Enlace XSL".
Pegue el vínculo al archivo XSL en la biblioteca de estilos que copió anteriormente (puede ser un vínculo relativo o absoluto).
Haga clic en "Aceptar" para guardar sus cambios y luego haga clic en el botón "Detener edición" en la cinta "Página" en la parte superior de la página.
Si todo se configuró correctamente, ahora debería ver números en la columna "Días en estado".
Y finalmente, así es como se vería con algunos datos de prueba de varias fechas:
Resumen:
Ahí está: una forma bien formateada, robusta y de mejor rendimiento para crear un informe antiguo en SharePoint, completa con una simple implementación sin código. Esto tiene bastantes aplicaciones potenciales, aparte del caso de uso que exploramos aquí. Otro escenario común para este tipo de informe es adjuntarlo a una lista de tareas para que pueda ver de un vistazo cuánto tiempo ha transcurrido desde que se creó una tarea.
¡A disfrutar!
--Justin
Justin Joyce, LANtek
Comentarios
Pasos que faltan
10/8/2012 3:51 AM
ok Seguí los pasos, pero debe faltar algo: ¿cómo sabrá el XSL qué fecha usar o en qué campo agregar los días desde entonces? Odio cuando se pierden pasos.
No-Code, ¡de acuerdo!
30/08/2012 12:12
Estoy de acuerdo, no creo que esto realmente cuente como "sin código".
Curiosamente, a través de un error de SharePoint, tengo una columna calculada en funcionamiento usando Hoy ... no estoy seguro de cómo o por qué porque no puedo hacer que lo vuelva a hacer, pero el uno todavía está ahí y funcionando.
Fórmula para la columna calculada "Días en estado"?
02/05/2012 07:39
Justin: ¿Cuál es la fórmula que usó para la columna de sitio calculado "Días en el estado" (columna de marcador de posición)? ¿Fue "=hoy"?
SharePoint 2007
12/2/2011 11:29 AM
Actualmente no he intentado aplicar esta solución a SharePoint 2007, pero estoy estudiando. Desafortunadamente, no hay ninguna propiedad XslLink en el elemento web a través de la interfaz de usuario.
Gran publicación
11/30/2011 9:53 AM
Hola:
Gran publicación.
Estoy usando SharePoint 2007.
No tengo una sección Miscelánea como se señaló anteriormente.
¿Tiene pasos para una configuración del SP2007?
Gracias.
Re: Solución sin código: mostrar los días desde la última vez que se cambió un elemento de lista de SharePoint
10/11/2011 8:24 AM
Hola Chris.
¡Gran hallazgo!
Voy a echar un vistazo a lo que publicaste, con suerte, más tarde hoy y ver si puedo hacer que esta solución sea un poco más sólida.
Me alegro de que te haya gustado la publicación y me alegro mucho de que hayas podido encontrar una solución al formato de fecha europeo. :)
-Justin
Solución para formatos de fecha europeos
10/11/2011 6:45 AM
Hola de nuevo Justin,
Para su información, encontré una solución para el problema que mencioné anteriormente en esta página;
https://sharepointbydummies.wordpress.com/2011/07/13/possible-work-around-to-date-format-issue-sharepoint-2010/
Formatos de fecha europeos
7/10/2011 3:59 AM
Hola Justin,
Esta es una muy buena solución, gracias, ¡y justo el tipo de cosas que he pasado los últimos dos días buscando! Sin embargo, estoy teniendo un pequeño problema con eso y esperaba que pudieras ayudarme.
He alterado ligeramente su código para calcular el número de días hasta que suceda algo, en lugar de desde entonces, cambiando las variables en la última línea de la función "DateDiff";
<xsl:value-of select="$JulianToday - $JulianStartDate"></xsl:value-of>
Sin embargo, solo puedo hacer que calcule la diferencia correctamente la mitad de las veces. Entonces, por ejemplo, con esta fecha (formato dd / MM / aaaa);
30/12/2011
Calcula correctamente, pero con esta fecha (mismo formato)
12/10/2011
Se calcula como si fuera 10-dic-2011 en lugar de 12-oct-2011.
Intenté simplemente cambiar las posiciones de los valores del día y el mes en la variable "JulianStartDate", así;
<xsl:with-param name="Month" select="substring(ddwrt:FormatDateTime(string($StartDate), 1033, 'yyyyMMdd'),7,2)"/>
<xsl:with-param name="Day" select="substring(ddwrt:FormatDateTime(string($StartDate), 1033, 'yyyyMMdd'),5,2)"/>
Y esto corrigió el problema con la segunda cita, ¡sin embargo, fue incorrecto para la primera cita!
También intenté alterar las llamadas FormatDateTime para usar LCID europeos y varias alteraciones en el último parámetro de FormatDateTime (por ejemplo, ddMMyyyy, MMddyyyy) con los ajustes apropiados a los parámetros posicionales de subcadena sin éxito.
Agradecería mucho cualquier consejo que pueda ofrecer.
Gracias,
Chris
No-Code
9/21/2011 4:27 AM
No creo que XSL califique como una solución "sin código", ya que comprender el lenguaje XSL no es para todos, sin embargo, no implica programación. Además de eso: ¡Buena solución, gracias!