jueves, 29 de agosto de 2013

Añadir a Favoritos del IE un informe de Reporting Services desde Navision

Hemos visto en anteriores posts como lanzar un informe de reporting services. En este posts vamos a ver como podemos antes de abrirlo con el IE guardarlo en los favoritos para que se pueda sacar de manera rapida desde el IE sin necesidad de abrir navision.

Los Favoritos del IE es una carpeta dentro de la carpeta de usuario de windows que contiene los links a las paginas almacenadas como favoritas. En este ejemplo, vamos a ver como crear un link sencillo, pero las posibilidades del link permiten adornarlo mucho más.
Tambien vamos a crear una carpeta dentro de Favoritos para así ver como podriamos crear una estructura organizada por carpetas.

Dependiendo del SO puede ser que tengamos la carpeta Favoritos o en su defecto Favorites. En este ejemplo veremos como comprobar cual es la correcta para almacenar nuestro link.

NameDataTypeSubtype
CarpetaPersonalText
CarpetaAutomation'Microsoft Scripting Runtime'.FileSystemObject
CarpetaMiaText
TempInformesRecordInformes
LCarpetaFavoritosText
ContinuarBoolean
FicheroFile
LinkText

//Creo las variables de la carpeta de favoritos mia que voy a crear, la del link de mi informe y
 //la variable de entorno donde esta la carpeta favoritos
   CarpetaPersonal := ENVIRON('USERPROFILE');
    CarpetaRaiz := 'MIS INFORMES';
    Link := 'http://servidor/......MIS INFORME';
//Creo el controlador de carpetas
   IF ISCLEAR(Carpeta) THEN
      CREATE(Carpeta);
//Compruebo si existe en español o ingles
   IF Carpeta.FolderExists(CarpetaPersonal + '\Favorites') THEN BEGIN
      Continuar := TRUE;
      LCarpetaFavoritos := '\Favorites';
   END ELSE BEGIN
      IF Carpeta.FolderExists(CarpetaPersonal + '\Favoritos') THEN BEGIN
         Continuar := TRUE;
         LCarpetaFavoritos := '\Favoritos';
      END ELSE BEGIN
         Continuar := FALSE;
      END;
   END;
//Continuo si encuentro Favoritos en el idioma español o ingles
   IF Continuar = TRUE THEN BEGIN
      //Creo mi carpeta dentro de favoritos
      IF NOT Carpeta.FolderExists(CarpetaPersonal + LCarpetaFavoritos + '\'+ CarperaRaiz) THEN BEGIN
         Carpeta.CreateFolder(CarpetaPersonal + LCarpetaFavoritos + '\' + CarperaRaiz);
      END;
     //Creo el fichero .url dentro de mi carpeta de favoritos Informe de Prueba.url es el nombre que aparecera en el menu de favoritos
     Fichero.CREATE(CarpetaPersonal + LCarpetaFavoritos + '\' + CarperaRaiz + '\' + 'Informe de Prueba.url');
     Fichero.WRITEMODE := TRUE;
     Fichero.TEXTMODE  := TRUE;
     Fichero.WRITE('[InternetShortcut]');
     Fichero.WRITE('URL='+Link);
     Fichero.WRITE('IDList=');
     Fichero.CLOSE;
END;

Con este código podemos facilitar el sacar informes de Reporting Services haciendolo directamente desde IE.

miércoles, 21 de agosto de 2013

Imprimir archivos con Navision

Como habiamos comentado en un post anterior, vamos a explicar como imprimir archivos de una manera rápida y sencilla desde Navision.
En post previos habiamos visto como descargar un informe desde Reporting Services y guardarlo en PDF. Ahora en este post vamos a coger un fichero PDF e imprimirlo.
Para eso utilizaremos el SHELL de windows. Lo que vamos a hace es simular lo que hace el boton derecho del raton sobre un fichero pdf

Cuando se desplegan las opciones tenemos la posibilidad de imprimir. Desde C/AL vamos a hacer esto mismo:

NameDataTypeSubtype
objShellAutomation'Microsoft Shell Controls And Automation'.Shell
objFolderAutomation'Microsoft Shell Controls And Automation'.Folder
objFolderItemsAutomation'Microsoft Shell Controls And Automation'.FolderItems
objFolderItemAutomation'Microsoft Shell Controls And Automation'.FolderItem
objVerbsAutomation'Microsoft Shell Controls And Automation'.FolderItemVerbs
objVerbAutomation'Microsoft Shell Controls And Automation'.FolderItemVerb
iInteger
 
//Funcion que imprime un archivo pasado de una carpeta especifica
funcion imprimirarchivo(txtCarpeta text 1024,txtArchivo text 1024)
{
//Creamos el objeto SHELL y todos los relacionados para obtener el menu contextual
CREATE(objShell);
objFolder          := objShell.NameSpace(DELCHR(txtCarpeta,'>','\'));
objFolderItems := objFolder.Items;
objFolderItem   := objFolderItems.Item(txtArchivo);
objVerbs           := objFolderItem.Verbs;
i  
                       := -1;
//Recorremos las opciones de menu para encontrar el que pone IMPRIMIR
REPEAT
   i := i+1;
   IF (i < objVerbs.Count) THEN BEGIN
      objVerb := objVerbs.Item(i);
   END;
UNTIL (ControlImprimir(objVerb.Name) = TRUE) OR (i >= objVerbs.Count);

IF (i <= objVerbs.Count) THEN BEGIN
   //Ejecutamos la opción de menú que pqueremos
   objVerb.DoIt;
   EXIT(TRUE);
END ELSE BEGIN
   EXIT(FALSE);
END;

}
//Funcion que nos devuelve si la opcion de menu es la que queremos
funcion imprimirarchivo(txtCarpeta text 1024,txtArchivo text 1024)
{
//Comprobamos que es la de imprimir.
IF STRPOS(UPPERCASE(DELCHR(txtTexto,'=','&')),'IMPRIMIR')>0 THEN BEGIN
   EXIT(TRUE);
END;
EXIT(FALSE);

}

De esta manera podemos imprimir los ficheros deseados. Combinando la descarga del Reporting Services de post anteriores con la impresion de archivos de este post podemos imprimir los informes de reporting directamente sin la intervencion del usuario.

miércoles, 14 de agosto de 2013

Obtener el Servidor y la Base de Datos actual en SQL

Cuando queremos acceder a la Base de datos y/o Servidor actual por algún motivo (Bien sea una consulta por ADO o para ver las BBDD que tenemos creadas) C/AL nos lo pone muy sencillo al tener a nuestra disposición unas tablas virtuales que nos exponen estos datos:
NameDataTypeSubtype
recServerRecordServer
recDatabaseRecordDatabase

Pero cuando accedemos por web service nos da un error porque las tablas virtuales no tienen generados los metadatos para ser utilizadas por estos.
Una de las formas de conseguirlo es mediante el archivo Config de los web services donde esta indicado el servidor y la BBDD. El archivo es CustomSettings.config y esta en la carpeta de la aplicacion. Este archivo es un XML con los parametros de configuracion que los web services desplegan al iniciar el servicio.

NameDataTypeSubtype
recServerRecordServer
recDatabaseRecordDatabase
recUsuarioSQLRecordUsuario
cu50203CodeunitCodeSQL
DomDocAutomation'Microsoft XML, v4.0'.DOMDocument
DomNodeAutomation'Microsoft XML, v4.0'.IXMLDOMNode
MyServerNameText
MyBBDDNameText
//Comprobamos si es el WEB Service o no
IF ISSERVICETIER THEN BEGIN
  //Creamos un objeto XML para tratar el archivo config  IF ISCLEAR(DomDoc) THEN
    CREATE(DomDoc);
  

  //Cargamos el archivo config
  DomDoc.load(APPLICATIONPATH + 'CustomSettings.config');

  //Leemos Los Nodos
  DomNode := DomDoc.selectSingleNode('//appSettings/add[@key='DatabaseServer']');
  MyServerName := DomNode.attributes.item(1).text;
  DomNode := DomDoc.selectSingleNode('//appSettings/add[@key='DatabaseName']');
  MyBBDDName := DomNode.attributes.item(1).text;

END ELSE BEGIN

   //Si no es WEB Service lo hacemos de la manera tradicional
   recServer.RESET;
   recServer.SETRANGE("My Server",TRUE);
   IF recServer.FINDSET THEN BEGIN
       recDatabase.RESET;
       recDatabase.SETRANGE("My Database",TRUE);
       IF recDatabase.FINDSET THEN BEGIN
          MyServerName := recServer."Server Name";

          MyBBDDName :=recDatabase."Database Name";
       END;
   END;
END;


Con esto tenemos resuelto el problema.

miércoles, 7 de agosto de 2013

Poner el idioma de los web services en español

Con la arquitectura por capas que presenta navision, es posible que se genere alguna discordancia por configuraciones distintas en diferentes capas.
La que vamos a ver en este post es la referente a la configuracion de la capa de los web services. Es posible que instalemos la capa del servidor de navision en español y la capa de los web services los instalemos en ingles.
Esto puede parecer algo banal en principio, pero se puede convertir en un autentico quebradero de cabeza cuando trabajamos por ejemplo con fechas, en los web services las tratamos en formato mm/dd/aa y en el cliente clasico como dd/mm/aa.
No solo afecta en esto, tambien los calculos de fechas se ven afectados al tener que tratar con un lenguaje u otro.
Por ejemplo para calcular 1 semana en un idioma es 1S y en otro es 1W.

Para solucionarlo hay que seguir los siguientes pasos:

Instalamos el paquete de idioma español, esta en el cd de instalacion en la ruta Installers\ES\Server, con esto se instala el idioma. Una vez instalada se creara en el servidor dentro de la carpeta C:\Program Files (x86)\Microsoft Dynamics NAV\60\Service (La carpeta de los web services, la ruta puede variar) una carpeta es-ES y ESP.


 


Cuando se instalan los web services se configura en el servicio una cuenta de ejecucion que tiene que tener que ser un usuario con permisos en navision.

En la tabla 2000000073 se crea una entrada con el usuario de los web services y el idioma que queremos, que en nuestro caso es el español.


Vereis en muchas webs diferentes codificaciones, pero la que a mi me ha funcionado es la 1034.

Para finalizar, microsoft recomienda ejecutar la instruccion GLOBALLANGUAGE(1034); al menus una vez.
¿Que quiere decir esto? pues muy sencillo, crear una codeunit con una funcion que contenga la instruccion. Publicarla y ejecutarla desde nuestra aplicacion que consume los web services.

Con esto tendremos ambas capas en español.

Renderizar en PDF un Informe de Reporting Services

Aprovechando los posts anteriores, vamos a explicar en este, como combinar el renderizar un informe como PDF y capturar el resultado para crear un fichero para después imprimirlo o adjuntarlo a un correo o simplemente guardarlo.
Para eso, vamos a llamar a nuestro informe utilizando el objeto automation XMLHTTP.
Gracias a el llamaremos al informe y obtendremos un stream con el resultado. Luego solamente se crea el archivo (Para que devuelva un PDF es necesario Como hemos comentado en otros posts renderizarlo en formato PDF añadiendo la opcion &Format=PDF).
También se podria hacer un fichero de excel simplemente cambiando en la url el &Format=PDF por &Format=Excel.

URL                                                   Automation       'Microsoft WinHTTP Services, version 5.1'.WinHttpRequest      
XMLHTTP                                        Automation       'Microsoft XML, v3.0'.XMLHTTP              
Grabador                                        Record               Información empresa  
btArchivoRecibido                        BigText               
isArchivoRecibido                         InStream                           
osEscribeArchivoRecibido           OutStream                    
vRespuesta                                    Variant     
 
//Creamos el objeto XMLHTTP para capturar el stream de la web
CREATE(XMLHTTP);
//Abrimos la WEB donde txtURL es la direccion de nuestro informe recordad que hay que poner el formato que queremos para renderizar
XMLHTTP.open('GET',txtURL,FALSE);
//Mandamos la cabecera
XMLHTTP.setRequestHeader('Content-Type','application/pdf');

//Establecemos la conexion
XMLHTTP.send();

//Comprobamos el status de la conexion
IF (XMLHTTP.status = 200) THEN BEGIN
  CLEAR(vRespuesta);

  //Metemos en VRespuesta el resultado del informe
  vRespuesta := XMLHTTP.responseStream;

  //Generamos el archivo fisicamente en la direccion txtFichero
  isArchivoRecibido := vRespuesta;
  btArchivoRecibido.READ(isArchivoRecibido);
  CLEAR(Grabador);
  Grabador.DELETEALL;
  Grabador.INIT;
  Grabador.Imagen.CREATEOUTSTREAM(osEscribeArchivoRecibido);
  btArchivoRecibido.WRITE(osEscribeArchivoRecibido);

  //Grabamos el fichero en la direccion txtFichero
  Grabador.Imagen.EXPORT(txtFichero,FALSE);
END;


En post sucesivos explicaremos como imprimir directamente el PDF generado desde Navision.


Abrir Informe Reporting Services con IE

Hemos visto en post anteriores como abrir un informe de Reporting Services llamando a la URL del servicio web. Desde C/AL podemos llamar al informe utilizando: HYPERLINK(URLDeseada);
Pero no se vosotros, pero a mí los informes en Reporting Sevices dependiendo del explorador que utilicemos se veran mejor o peor. Para asegurarnos que lo abrimos con el IE (Que en definitiva es el que mejor nos asegura el funcionamiento) lo haremos de la siguiente manera:

IE = 'Microsoft Internet Controls'.InternetExplorer
WINDOWS = 'Windows Script Host Object Model'.WshShell
//Creamos el objeto AUTOMATION del IE
CREATE(IE);

//Creamos el objeto automation del Shell de Windows
CREATE(WINDOWS);


//Ponemos el IE visible para poder verlo en pantalla
IE.Visible := TRUE;

//Por si aparece pero en segundo plano lo ponemos en primer plano
WINDOWS.AppActivate(IE);

//Abrimos el informe como el HYPERLINK
IE.Navigate(URLDeseada);

Abrir Informe de Reporting Services

Hoy vamos a ver como se puede llamar a un informe de Reporting Services indicando en la URL de llamada que nos lo renderice con un formato especificado.
A los informes de Reporting Services hay 2 maneras de llamarlos.
Bien llamando al informe publicado:
http://servidor-Instancia/ReportServer/Pages/ReportViewer.aspx?%2fCARPETA%INFORME&rs:Command=Render
O utilizando el servicio web asociado al informe:
http://servidor-Instancia/Reports/Pages/Report.aspx?ItemPath=%2fCARPETA%2fINFORME

Cuando utilizamos la llamada al servicio web relacionado, podemos incluir en la URL una serie de parámetros que nos permite controlar ciertos aspectos de nuestros informes.
Los que nos afectan en este post son los del formato que queremos que se renderice el informe.
Así entonces, si incluimos en la url los siguiente:
&rs:Format=Formato deseado el informe se mostrará directamente en el formato indicado.

Por ejemplo en PDF sería:
&rs:Format=PDF
En Excel:
&rs:Format=Excel
Para ver todos los formatos y todas las opciones del servicio web podéis consultar el siguiente enlace:
http://msdn.microsoft.com/en-us/library/ms152835.aspx