Si está evaluando una herramienta de generación de informes para integrarla en una aplicación, o incluso para implementar un sistema empresarial de gestión de informes, Este artículo puede resultarle interesante.
¿Crystal Reports o Reporting Services?
Personalmente yo uso Reporting Services, pero no por decision propia sino porque la empresa nos impuso ese generador de informes, pero luego de un tiempo usandolo te adecuas.
Saludos.
Bienvenido a este espacio. Dejanos tus dudas y comentarios. Saludos.
viernes, 20 de febrero de 2009
jueves, 12 de febrero de 2009
Maqueteando los datos revueltos por _vti_bin/lists.asmx
Sharepoint nos ofrece acceso a sus datos a traves de Servicios Web, a los cuales podemos acceder a traves del famoso _vti_bin/lists.asmx, asi que desde el inicio del proyecto empece a utilzar estos Servicios Web, entre todos los metodos Web que ofrece hay uno que uso muy seguido GetListItems, que funciona de maravillas, la manera de trabajar con este Metodo Web es facil, haciendo uso de herramientas tales como: U2UCamlCreator podemos ir creando consultas en formato XML. Algo similar a la imagen
lo remarcado en la imagen nos usar como parametros para este Metodo Web.
Por temas de mejorar el diseño hice una DLL llamada MossHelper.dll que enmascara este ServicioWeb y ofrece un metodo llamado MyQueryList(string Myquery, string listGuid, int NumReg, string MyView), que fui armado segun las necesidades, si a alquien ayuda podria adjuntar el codigo de esta dll.
Mando los parametros necesario Myquery, es la primera region del grafico, listGuid es la GUID de la lista o libreria donde deseas consultar, NumReg es el numero de registros que deseas retornar (si deseas devolver todos, mandar 0) MyView, es la segunda region del grafico,
Hasta aqui todo funciona perfecto, pero la data me la devuelve de esta manera:
Inicialmente dije bueno, no importa total alli esta la data que necesitan (y otra data que realmente no se para que sirve, si alguien sabe que es toda esa data agradeceria decirmelo y sobre todo para que me puede servir), pero luego cree un algoritomo que mejore ese esquema XML y solo me muestre la data que pedi, y sin el prefijo "ows_" en todo los campos.
Algo como la siguiente Imagen.
Poco a poco fui haciendo un Algoritmo no optimizado por cierto, pero que funciona, queda en ustedes adecuarlo a su realidad y mejorarlo
Me hubiera gustado poder escribir el codigo, pero siempre hay problemas con las etiquetas de XML.
Bueno lo explico un poco.
Parta esto cree una clase llamada: ClassDatos, con 3 Campos Columna, Valor 1, Valor 2; para este caso el Columna tendra el nombre de la columna a consultar, Valor 1, un valor por defecto en caso que no encuentre el campo o el campo este vacio y Valor 2 el nombre con que deseas ver tu campo.
Hago uso de la funcion que mensione previamente.
Espero sea util, saludos.
El resto es tema revisar el codigo.
lo remarcado en la imagen nos usar como parametros para este Metodo Web.
Por temas de mejorar el diseño hice una DLL llamada MossHelper.dll que enmascara este ServicioWeb y ofrece un metodo llamado MyQueryList(string Myquery, string listGuid, int NumReg, string MyView), que fui armado segun las necesidades, si a alquien ayuda podria adjuntar el codigo de esta dll.
Mando los parametros necesario Myquery, es la primera region del grafico, listGuid es la GUID de la lista o libreria donde deseas consultar, NumReg es el numero de registros que deseas retornar (si deseas devolver todos, mandar 0) MyView, es la segunda region del grafico,
Hasta aqui todo funciona perfecto, pero la data me la devuelve de esta manera:
Inicialmente dije bueno, no importa total alli esta la data que necesitan (y otra data que realmente no se para que sirve, si alguien sabe que es toda esa data agradeceria decirmelo y sobre todo para que me puede servir), pero luego cree un algoritomo que mejore ese esquema XML y solo me muestre la data que pedi, y sin el prefijo "ows_" en todo los campos.
Algo como la siguiente Imagen.
Poco a poco fui haciendo un Algoritmo no optimizado por cierto, pero que funciona, queda en ustedes adecuarlo a su realidad y mejorarlo
Me hubiera gustado poder escribir el codigo, pero siempre hay problemas con las etiquetas de XML.
Bueno lo explico un poco.
Parta esto cree una clase llamada: ClassDatos, con 3 Campos Columna, Valor 1, Valor 2; para este caso el Columna tendra el nombre de la columna a consultar, Valor 1, un valor por defecto en caso que no encuentre el campo o el campo este vacio y Valor 2 el nombre con que deseas ver tu campo.
Hago uso de la funcion que mensione previamente.
Espero sea util, saludos.
El resto es tema revisar el codigo.
Reporting Services: Creando DataSorce y DataSet
Es el primer proyecto donde me he visto en la necesidad utilizar Reporting Services, por las circunstancias usar una fuente de datos XML y para acceder a ella usar WebServices.
Manos a la Obra.
Creamos un proyecto de tipo: Report Server Project, tal como se muestra en la imagen adjunta.
Tendramos una interfaz muy similar a la siguiente.
Tenemos 2 carpetas con los nombres: Shared Data Sources y Reports.
El primero permite crear una fuente de datos, para realizar esto click derecho y elgirla opcion: Add New Data Source; al realizar esto se mostrara la siguiente ventana.
Como usaremos un WebServices, seleccionamos Type XML, en mi caso mi webservices es http://localhost:2366/MasterTables/BPPS/Trend.asmx
Ahora para crear un reporte tenemos 2 opciones hacerlo manualmente o utilizar el Wizard, creo que sera mas util que sea manual, asi aprendemos mas; para ellos click derecho sobre Repots y elegimos la Opcion Add/New Item/ y elegimos Report.
Al realizar esto se mostrara una pantalla como la siguiente.
Aqui vemos 3 Pestañas Data | Layout | Preview:
Data, permite Crear Dataset
Layout, permite armar propiamente el reporte, crear parametros
Preview, nos muestra como va quedando el reporte.
Paso 1: Crear Data Set, click sobre la opcion New Dataset...
Para mi ejemplo, usare un Metodo Web llamado: BuscarEnPresupuesto, el namespace que uso es "http://tempuri.org/" y tiene varios parametros: string PresupuestoName_XML, string IdEquipo, string NroParte, string NroSerie, de los cuales solo el primero es obligatorio, con todos estos datos armamos, una estructura como la siguiente:
Estos nos servira como Query String, los errores mas comunes en este nivel es son por errores de tipo, no olvidar que es "Case Sensitive".
Si todo esta bien , ya deberia poder ver sus datos usando el boton Run [!].
Saludos
Mensajes de Error mas comunes en este nivel
Mensaje 1:
An error occurred while creating a data extension command.
The XmlDP query is invalid.
Razon: Se ha omitido alguna etiqueta, se han cometido errores de tipeo o cambiaron mayusculas por minusculas.
Espero esto les ayude, saludos.
Manos a la Obra.
Creamos un proyecto de tipo: Report Server Project, tal como se muestra en la imagen adjunta.
Tendramos una interfaz muy similar a la siguiente.
Tenemos 2 carpetas con los nombres: Shared Data Sources y Reports.
El primero permite crear una fuente de datos, para realizar esto click derecho y elgirla opcion: Add New Data Source; al realizar esto se mostrara la siguiente ventana.
Como usaremos un WebServices, seleccionamos Type XML, en mi caso mi webservices es http://localhost:2366/MasterTables/BPPS/Trend.asmx
Ahora para crear un reporte tenemos 2 opciones hacerlo manualmente o utilizar el Wizard, creo que sera mas util que sea manual, asi aprendemos mas; para ellos click derecho sobre Repots y elegimos la Opcion Add/New Item/ y elegimos Report.
Al realizar esto se mostrara una pantalla como la siguiente.
Aqui vemos 3 Pestañas Data | Layout | Preview:
Data, permite Crear Dataset
Layout, permite armar propiamente el reporte, crear parametros
Preview, nos muestra como va quedando el reporte.
Paso 1: Crear Data Set, click sobre la opcion New Dataset...
Para mi ejemplo, usare un Metodo Web llamado: BuscarEnPresupuesto, el namespace que uso es "http://tempuri.org/" y tiene varios parametros: string PresupuestoName_XML, string IdEquipo, string NroParte, string NroSerie, de los cuales solo el primero es obligatorio, con todos estos datos armamos, una estructura como la siguiente:
Estos nos servira como Query String, los errores mas comunes en este nivel es son por errores de tipo, no olvidar que es "Case Sensitive".
Si todo esta bien , ya deberia poder ver sus datos usando el boton Run [!].
Saludos
Mensajes de Error mas comunes en este nivel
Mensaje 1:
An error occurred while creating a data extension command.
The XmlDP query is invalid.
Razon: Se ha omitido alguna etiqueta, se han cometido errores de tipeo o cambiaron mayusculas por minusculas.
Espero esto les ayude, saludos.
martes, 3 de febrero de 2009
Enviar ampersand(&) en XML / Send ampersand in XML
Hace algunos dias tuve necesitaba mandar una ruta Url con parametros como valor de un nodo XML, similar a como se muestra en la imagen siguiente:
Al intentarlo obtenia un error similar a este:
"System.Xml.XmlException: An error occurred while parsing EntityName" y al parecer no estaba comiento ningun error, pero llege a la conclusion que cada vez que ponia un ampersand como valor del nodo, el webservices fallaba.
Buscando en google descubir que existe una lista de caracteres prohibidos en XML
Es muy comun que utilicemos ampersand en las URLs de los enlaces, por ejemplo para definir variales como esta:
Espero que este les ayude.
Saludos.
Al intentarlo obtenia un error similar a este:
"System.Xml.XmlException: An error occurred while parsing EntityName" y al parecer no estaba comiento ningun error, pero llege a la conclusion que cada vez que ponia un ampersand como valor del nodo, el webservices fallaba.
Buscando en google descubir que existe una lista de caracteres prohibidos en XML
Es muy comun que utilicemos ampersand en las URLs de los enlaces, por ejemplo para definir variales como esta:
/bpps/historial/Pages/ComponenteHistorial.asmx?NroParte=123&NroSeria=abc
esto es incorrecto la forma correcta seria:/bpps/historial/Pages/ComponenteHistorial.asmx?NroParte=123
&
NroSeria=abc
Espero que este les ayude.
Saludos.
miércoles, 3 de septiembre de 2008
Manipulando WorkFlows
Este es el segundo Post que abarca este tema.
En el primer posts Iniciar Automanticamente WorkFlow quedaron algunas dudas.
Como obtener el TemplateID de un workflow asociado a un Document Library.
Para esto haremos uso de una dll llamada Microsoft.SharePoint.dll que obviamente puede ser descargado de la pagina de microsoft.
Los parametros que usaremos seran:
urlSite: La direccion Url absoluta del site, donde estamos trabajando.
Libreria: El Nombre o GUID, de la libreria, donde estamos trabajando.
SPSite _site = new SPSite(urlSite);
SPWeb _Web = _site.OpenWeb();
String GUI = Libreria;//en formato similar a este: {68A5A98D-61AF-4BDF-B1DF-A326EA34460D}
Guid MiGUI = new Guid(GUI);
SPList _List = _Web.Lists[MiGUI];
SPWorkflowAssociationCollection MisWorkFlows=_List.WorkflowAssociations
En esta variable tenemos objetos del tipo SPWorkflowAssociation, que poseen 2 propiedades muy utiles: Name y Id, el primero obviamente si nombre lo dice, es el nombre del workflow y el segundo es el llamado TemplateID.
Pero ojo que se tendria que navegar la variable con un forech de esta manera:
Especificamente deseo conocer el TemplateID de un workflow cuyo nombre es pasado en la variable WFName="Mi WorkFlow".
string WFId="";
string WFName="MiWorkFlow";
foreach (SPWorkflowAssociation WF in _List.WorkflowAssociations)
{
if (WF.Name == WFName)
{
WFId=WF.Id.ToString();
}
}
De esta manera obtener el TemplateID de un WorkFlow, conociendo el nombre, libreria y site donde se encuentra este.
En el primer posts Iniciar Automanticamente WorkFlow quedaron algunas dudas.
Como obtener el TemplateID de un workflow asociado a un Document Library.
Para esto haremos uso de una dll llamada Microsoft.SharePoint.dll que obviamente puede ser descargado de la pagina de microsoft.
Los parametros que usaremos seran:
urlSite: La direccion Url absoluta del site, donde estamos trabajando.
Libreria: El Nombre o GUID, de la libreria, donde estamos trabajando.
SPSite _site = new SPSite(urlSite);
SPWeb _Web = _site.OpenWeb();
String GUI = Libreria;//en formato similar a este: {68A5A98D-61AF-4BDF-B1DF-A326EA34460D}
Guid MiGUI = new Guid(GUI);
SPList _List = _Web.Lists[MiGUI];
SPWorkflowAssociationCollection MisWorkFlows=_List.WorkflowAssociations
En esta variable tenemos objetos del tipo SPWorkflowAssociation, que poseen 2 propiedades muy utiles: Name y Id, el primero obviamente si nombre lo dice, es el nombre del workflow y el segundo es el llamado TemplateID.
Pero ojo que se tendria que navegar la variable con un forech de esta manera:
Especificamente deseo conocer el TemplateID de un workflow cuyo nombre es pasado en la variable WFName="Mi WorkFlow".
string WFId="";
string WFName="MiWorkFlow";
foreach (SPWorkflowAssociation WF in _List.WorkflowAssociations)
{
if (WF.Name == WFName)
{
WFId=WF.Id.ToString();
}
}
De esta manera obtener el TemplateID de un WorkFlow, conociendo el nombre, libreria y site donde se encuentra este.
jueves, 8 de mayo de 2008
Nuevo Proyecto: Sistema de Mantenimiento y Planificacion
Disculpando la carencia de entradas de mi blog.
Este post sera para dar inicio a un nuevo proyecto: Sistema de Mantenimiento y Planificacion.
Para el desarrollo de este sistema el equipo desarrollador conformado por:
Cristhian Sifuentes
Edwin Delgado
Marco Diaz
y un cuarto integrante.
Ademas del Jefe de Proyecto
La herramientas que utilizaremos son: Infopath 2007, sharepoint 2007,SQL2005,WorkFlow fundation y Visual Studio 2005.
Los principales temas que veremos son:
Acceso a datos del Sharepoint, a traves de webservices.
Construccion de WebPart para sharepoint.
Analisis de datos Sharepoint.
WorkFlow
Bueno, sin mas que decir me retiro hasta el proximo post.
Este post sera para dar inicio a un nuevo proyecto: Sistema de Mantenimiento y Planificacion.
Para el desarrollo de este sistema el equipo desarrollador conformado por:
Cristhian Sifuentes
Edwin Delgado
Marco Diaz
y un cuarto integrante.
Ademas del Jefe de Proyecto
La herramientas que utilizaremos son: Infopath 2007, sharepoint 2007,SQL2005,WorkFlow fundation y Visual Studio 2005.
Los principales temas que veremos son:
Acceso a datos del Sharepoint, a traves de webservices.
Construccion de WebPart para sharepoint.
Analisis de datos Sharepoint.
WorkFlow
Bueno, sin mas que decir me retiro hasta el proximo post.
Etiquetas:
Infopath 2007,
Sharepoint,
WebServices,
WorkFlows
jueves, 31 de enero de 2008
Iniciar Automaticamente un WORKFLOW
Hola a todos los visitantes, ya llevo mas de un mes sin postear nada.
Pero mas vale tarde que nunca.
Ahora vamos a ver como podemos por medio de programacion arrancar un WorkFlow.
Esto nos serviria en escenarios que el WorkFlow no requera un formulario de inicializacion, o donde de alguna manera se pueda tener acceso a data para el formulario de inicializacion.
Bueno para lo que ya han leido algunos de mis post, se habran dado cuenta que yo uso los webservices propios del Sharepoint, es decir: los famosos: _vti_bin/list.asmx en este caso usaremos el _vti_bin/worklows.asmx.
Y muchos se preguntaran porque usar esto que es un poco mas dificil, menos documentado y mas laborioso, el problema es que para poder hacer el testing o debug, puesto que otros componentes como sharepoint.dll no se puede hacer debug desde otra pc que no sea el servidor, asi que mientras no encuentre una solucion a este problema, seguire usando estos webservices propios del sharepoint.
Ahora si manos a la obra:
Para poder iniciar un workflow, necesitamos cierta informacion.
Tal como:
la url del documento a que vamos a aplicar el workflow.
la estructura del formulario de inicializacion del workflow(dejemos esto como opcional)
el nombre del workFlow o su Template ID(para este ejemplo asumamos que ya conocemos este valor de no se asi, tendremos que buscar la manera de obtenerlo, cosa que lo haremos en otro post)
Hacer una referencia web al webservices _vti_bin/Workflow.asmx, de manera visual.
en codigo hacer ..... mejor vean el codigo:
SiteRaizWF.Workflow WF = null;
WF = new SiteRaizWF.Workflow();
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
CredentialCache cache = new CredentialCache();
WF.Credentials = new System.Net.NetworkCredential("user_admin", "pwd_admin", "Dominio");
WF.PreAuthenticate = true;
XmlNode _ = WF.StartWorkflow(urlNewForm, new Guid(TemplateID), xmlFormInit);
bueno esto en el general todo el codigo necesario para iniciar un work flow por medio de programacion.
Antes que me llenen la bandeja con mail preguntando que son esos paremetros
urlNewForm: es el documento del archivo que desean aplicar el workflow
TemplateID: es el ID del template del workflow asociado, asociado a un documento.
xmlFormInit: es el formulario infopath de inicializacion en XML el tipo de dato es XmlNode.
Y como demonios obtendo este famoso xmlFormInit, hay varias opciones, podemos serializar previamente nuestro formulario a clases y luego pasarlos a XML,esto permitiria llenar los datos tambien por programacion (ojo que esto es una funcionalidad muy importante y que va a sacarlos de apuros como me saco a mi :D)
La otra es tener una string con una cadena representando este esquema XML luego llenar un xmldocument con esta cadena y listo.
Bueno por la premura del caso, dejaremos este post en este punto, si tienen dudas por favor no duden en escribirme:
marcodiazjr@gmail.com
Saludos y buena programacion.
PD: este codigo es parte de un webservice, es decir podemos invocar este metodo desde cualquier lugar, tambien podria ser parte de si documento infopath o simulares.
Pero mas vale tarde que nunca.
Ahora vamos a ver como podemos por medio de programacion arrancar un WorkFlow.
Esto nos serviria en escenarios que el WorkFlow no requera un formulario de inicializacion, o donde de alguna manera se pueda tener acceso a data para el formulario de inicializacion.
Bueno para lo que ya han leido algunos de mis post, se habran dado cuenta que yo uso los webservices propios del Sharepoint, es decir: los famosos: _vti_bin/list.asmx en este caso usaremos el _vti_bin/worklows.asmx.
Y muchos se preguntaran porque usar esto que es un poco mas dificil, menos documentado y mas laborioso, el problema es que para poder hacer el testing o debug, puesto que otros componentes como sharepoint.dll no se puede hacer debug desde otra pc que no sea el servidor, asi que mientras no encuentre una solucion a este problema, seguire usando estos webservices propios del sharepoint.
Ahora si manos a la obra:
Para poder iniciar un workflow, necesitamos cierta informacion.
Tal como:
la url del documento a que vamos a aplicar el workflow.
la estructura del formulario de inicializacion del workflow(dejemos esto como opcional)
el nombre del workFlow o su Template ID(para este ejemplo asumamos que ya conocemos este valor de no se asi, tendremos que buscar la manera de obtenerlo, cosa que lo haremos en otro post)
Hacer una referencia web al webservices _vti_bin/Workflow.asmx, de manera visual.
en codigo hacer ..... mejor vean el codigo:
SiteRaizWF.Workflow WF = null;
WF = new SiteRaizWF.Workflow();
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
CredentialCache cache = new CredentialCache();
WF.Credentials = new System.Net.NetworkCredential("user_admin", "pwd_admin", "Dominio");
WF.PreAuthenticate = true;
XmlNode _ = WF.StartWorkflow(urlNewForm, new Guid(TemplateID), xmlFormInit);
bueno esto en el general todo el codigo necesario para iniciar un work flow por medio de programacion.
Antes que me llenen la bandeja con mail preguntando que son esos paremetros
urlNewForm: es el documento del archivo que desean aplicar el workflow
TemplateID: es el ID del template del workflow asociado, asociado a un documento.
xmlFormInit: es el formulario infopath de inicializacion en XML el tipo de dato es XmlNode.
Y como demonios obtendo este famoso xmlFormInit, hay varias opciones, podemos serializar previamente nuestro formulario a clases y luego pasarlos a XML,esto permitiria llenar los datos tambien por programacion (ojo que esto es una funcionalidad muy importante y que va a sacarlos de apuros como me saco a mi :D)
La otra es tener una string con una cadena representando este esquema XML luego llenar un xmldocument con esta cadena y listo.
Bueno por la premura del caso, dejaremos este post en este punto, si tienen dudas por favor no duden en escribirme:
marcodiazjr@gmail.com
Saludos y buena programacion.
PD: este codigo es parte de un webservice, es decir podemos invocar este metodo desde cualquier lugar, tambien podria ser parte de si documento infopath o simulares.
Suscribirse a:
Entradas (Atom)