jueves, 2 de junio de 2016

Fórmula de porcentaje en tabla de referencias cruzadas de Cyrstal Reports

En múltiples ocasiones debemos crear en Crystal Reports una tabla de referencias cruzadas. En la mayoría de las veces mostraremos en dicha tabla varios valores por casilla. Hay veces que necesitaremos crear una fórmula basada en un cálculo entre datos de la casilla, por ejemplo el porcentaje que representa una comisión sobre el total de esa casilla.

Si optamos por crear una fórmula normal de Crystal Reports, observaremos que nos funciona casilla a casilla, pero en los resúmenes totales no, puesto que se sumará, y no hará el cálculo.

Para evitar esto, procederemos de la siguiente manera.

Pulsaremos con botón derecho, dentro de la tabla de referencias cruzadas, sobre el primer campo que actuará en nuestra fórmula. Seleccionaremos Resumen incrustado -> Insertar resumen incrustado.

Esto nos creará un nuevo valor en la tabla. Lo pulsamos con botón derecho y seleccionamos Resumen incrustado -> Editar fórmula de cálculo. Se nos abrirá un editor de fórmulas, y de ahí obtendremos los valores de la casilla deseados para crear nuestra fórmula de la siguiente forma:
Local Numbervar comision := GridValueAt (CurrentRowIndex, CurrentColumnIndex, 2);
Local Numbervar primaNeta := GridValueAt (CurrentRowIndex, CurrentColumnIndex, 1);

If primaNeta = 0 Then
  0
Else
  (comision*100)/primaNeta

Donde 2 y 1 son la posición del campo de la casilla a utilizar. Con esto, nuestra fórmula funcionará tanto en cada casilla como en los resúmenes totales.

Configurar conexiones remotas en SQL Server

Cuando se instala un servidor de SQL Server, en la mayoría de ocasiones deseamos hacer accesible ese servidor desde otros equipos de la red, es decir, no queremos que funcione sólo de manera local. Para conseguir esto hay que activar las conexiones remotas a SQL Server. Para hacer esto hemos de seguir los siguientes pasos (estos pasos se han seguido en la vesrsión 2012, pero es similiar en el resto de versiones):

1. Activar las conexiones remotas
   Abrir SQL Manangement Studio, y sobre la instancia instalada de SQL Server, dar con botón derecho-Propiedades, y dentro de la opción "Conexiones", comprobar que está marcado "Permitir conexiones remotas con este servidor".

2. Configurar las conexiones remotas
  Abrir el SQL Server Configuration Manager
  Dentro de SQL Server Network Configuration -> Protocols for <instanciaSQL>, comprobar que TCP/IP se encuentre en Enabled.
  Pulsar TCP/IP con botón derecho y dar a Propiedades. En la primera solapa, comprobar que "Listen All" esté en "Yes".
  En la segunda solapa, IP Addresses, bajar hasta donde pone IPAll, y en TCP Port indicar el puerto 1433. TPC Dynamic Ports se puede dejar vacío.
  Aplicar los cambios y reiniciar el servicio de SQL Server (Servicios-> SQL Server y SQL Browser).

2. Abrir el cortafuegos de Windows
   Si probamos a desactivarlo, comprobaremos como ya podemos conectar. Lo volvemos a activar y vamos a configurar las reglas de acceso a SQL Server.

3. Abrir el cortafuegos de Windows con seguridad avanzada.
   En el debemos crear 2 reglas de entrada: Una para el puerto TCP 1433, y otra para el puerto UDP 1434.

Con esto, SQL Server ya debe estar configurado para aceptar conexiones remotas.

Hay un video donde se explica muy bien aquí.

miércoles, 4 de marzo de 2015

Sistema de encuestas

La empresa en la que trabajamos dispone de distintos certificados de calidad. Una de las condiciones que se deben cumplir para estar en posesión de estos certificados, consiste en la realización de encuestas de satisfacción al cliente para conocer su opinión sobre los servicios ofrecidos. Para ello, se nos pide integrar esta posibilidad en el software de gestión.

La forma en que desea que funcionen las encuestas es la siguiente: periódicamente, cada viernes, el servidor creará de forma automática una serie de alertas para encuestar a clientes, basándose en ciertas condiciones de negocio (básicamente servicios entregados al cliente en los últimos X días). En este caso, no desean que el sistema seleccione aleatoriamente las encuestas, sino que desean que se notifique a un administrador de forma que sea él quien asigne las encuestas a la persona encargada de hacerlas, que será a su vez notificada mediante otra alerta.



Posteriormente, generaremos también de forma automática y periódica informes con las respuestas dadas por los clientes así como datos estadísticos sobre las mismas entre las fechas deseadas.
La solución ha sido la siguiente. Hemos creado una serie de tablas para la gestión de encuestas, que se detallan a continuación:

Encuestras.Preguntas
En esta tabla almacenaremos las preguntas a realizar para cada tipo de encuesta. Su estructura es la siguiente:

id / nombre / descripción / area / p1 / v1 / t1 / p2 / v2 / t2 / ..... / p20 / v20 / t20 / notas / recomedaciones

Donde p1 = pregunta1, v1 = posibles valores, separados por punto y coma, de la respuesta 1, t1 = peso de la pregunta en la encuesta

Encuestas.Rechazos
Esta tabla almacena las encuestas que se han descartado, de forma que no aparezcan más como posibles para encuestarse. Se compone de:

id / id_encuesta / id_asignacion / tabla_referencia / codigo_referencia / cod_usuario / fecha / tipo / cod_motivo / motivo_rechazo

Encuestas.MotivosRechazo
Es simplemente una tabla auxiliar para cuando se rechaza una encuesta, se indique el motivo. Los motivos pueden ser distintos según el tipo de encuesta, por lo que su estructura es esta:

cod_motivo / descripcion / id_encuesta

Encuestas.Respuestas
Almacena las respuestas de los clientes, y está formada por:

id / id_encuesta / cod_usuario / fecha / id_asignacion / tabla_referencia / codigo_referencia / nombre_encuestado / r1 / r2 / .... / r20 / notas / recomendaciones / fecha_auditoria

Encuestas.Asignacion
Por último tenemos esta tabla, que es la que asocia una encuesta a una persona para que la realice, y se compone de:

id / tipo / tabla_referencia / codigo_referencia / fecha_decision / cod_decisor / encuestar / cod_encuestador

Con esta estructura de tablas, es posible montar el sistema. El código del mismo será publicado en otra entrada.


El código asociado se encuentra aquí.

viernes, 27 de febrero de 2015

Tips de Crystal Reports

Quitar decimales a un numero en una formula
ToText(valor,0)
valor es el número a convertir
0 son los decimales
Se puede incluir un tercer parámetro para indicar el formato de separadores (''=ninguno)

Utilizar parámetros en un comando de un subinforme
Crear el comando en el subinforme. A la derecha crear el parámetro. Para usarlo, incluirlo en la sentencia SQL como {?NombreParametro}.
Luego, desde el informe principal, vincular el campo deseado al parámetro en cuestión del subinforme.

Utilizar un valor calculado en un subinforme en el informe principal
Supongamos que tenemos un valor que se calcula o se obtiene en un subinforme y deseamos utilizarlo (para mostrarlo o utilizarlo) en el informe principal.

Esto se soluciona utilizando variables compartidas, usadas desde la versión 7 de Crystal Report, y la solución consiste en lo siguiente:

Se debe tener en cuenta que el reporte primero evalúa la fórmula en donde se llena el valor de la variable compartida, y luego realiza la fórmula en donde se muestran los datos, independientemente de dónde se encuentre la fórmula y la variable, ya sea en el principal o en el subinforme.

1. En el subinforme, crear una formula parecida a esta:
//@SubFormula
//Guardar el total del campo {Orders.Order Amount}
//en una variable compartida llamada 'miTotal'
Shared CurrencyVar miTotal := Sum ({Orders.Order Amount})
Poner esta fórmula en el subinforme.
En el informe principal, crear una fórmula que declara el nombre de la misma variable:
//@FormulaPrincipal
//Retorna el valor que fue guardado en la variable compartida llamada
//miTotal del subinforme
Shared CurrencyVar miTotal;
miTotal
Poner la @FormulaPrincipal en el informe principal debajo de la sección que contiene el subinforme. Esto sirve para asegurar que el Crystal evalue antes la @SubFormula antes de la @FormulaPrincipal.

Una vez que tenemos el valor que necesitamos en la @FormulaPrincipal podemos hacer uso de ella como más nos convenga, por ejemplo, ocultar una sección dependiendo del monto que devuelve la @SubFormula.

jueves, 12 de febrero de 2015

Cargar el resultado de un fichero PHP dentro de un DIV con jQuery

Esta entrada muestra como podemos, dentro de una etiqueta DIV de nuestra página, colocar el resultado obtenido al hacer una llamada a una página php. Para poder hacer esto, lo primero que necesitamos es definir el DIV donde vamos a introducir el contenido:
<div class="contentWrapper" id="contenido"></div>
A cotinuación, con jQuery, en el lugar donde nos interese, haremos lo siguiente:
$("#contenido").load('url_al_archivo.php');
Paso de parámetros GET
Si queremos además pasar algún parametro por GET, se puede hacer de la siguiente forma:
$("#contenido").load('url_al_archivo.php?var1=x&var2=y&var3=z');
Paso de parámetros POST
En el caso de que los parámetros sean por POST, utilizaremos el siguiente formato.
$("#contenido").load('url_al_archivo.php', {var1:x, var2:y, var3:z});
Es todo, así de sencillo.

miércoles, 11 de febrero de 2015

Uso de fuentes externas sólo en fichero CSS

Si se desean usar fuentes externas, como por ejemplo Google Fonts, normalmente nos indicarán que para hacerlo necesitamos hacer un link href en la cabecera de nuestra página, y luego en nuestro fichero CSS ya podremos hacer referencia a la fuente. He aqui un ejemplo:
<link href="http://fonts.googleapis.com/css?family=Cuprum" type="text/css" rel="stylesheet" />
body {
  font-family: 'Cuprum', serif;
  font-size: 48px;
}
En ocasiones no nos interesa hacerlo así, ya que en cada página tendremos que incluir la referencia a la fuente, y si queremos cambiarla tendremos que ir página a página. O puede que estemos editando un fichero CSS de WordPress y queramos incluir una fuente sin tener acceso a las páginas HTML o PHP. En estos casos, podemos importar la fuente directamente desde dentro del fichero CSS. Hay varias formas de hacerlo, y aquí vamos a ver dos de ellas:

Forma 1
@font-face{
  font-family:'Droid Serif';
  font-style:normal;
  font-weight:400;
  src:local('Droid Serif'),local('DroidSerif'),url(http://fonts.gstatic.com/s/droidserif/v6/0AKsP294HTD-nvJgucYTaIbN6UDyHWBl620a-IRfuBk.woff) format('woff');
 }
body {
  font-family: 'Droid Serif';
  font-size: 14px;
}
Forma 2
@import url(http://fonts.googleapis.com/css?family=Open+Sans);
body {
  font-family: 'Open Sans';
  font-size: 14px;
}
Facil, ¿verdad?

viernes, 6 de febrero de 2015

Crear un WebService con PHP

Si trabajamos con PHP, una tarea con la casi seguro que nos encontraremos habitualmente es con la de construir un servicio web que exponga una serie de datos. Esto es muy sencillo de hacer en PHP, y vamos a ver como se hace.

Antecedentes
Supongamos que vamos a realizar un webservice que se conecte a una base de datos MySQL para lanzarle consultas y devolver los resultados. Esto será válido para la mayoría de casos con que nos encontramos, independientemente de que después debamos ampliar el servicio con otros métodos (como por ejemplo incluir seguridad, encriptación, etc).

Lo primero que se nos puede ocurrir, es crear una serie de métodos en el WebService de forma que cada uno reciba sus parámetros, monte las consultas, y las lance contra la base de datos para terminar devolviendo los resultados. Esto es correcto, pero vamos a crear una técnica más potente.

En vez de hacer un método por cada consulta a lanzar, vamos a tener un sólo método. Este, recibirá un nombre de opción a ejecutar, y según esa opción, lanzará una u otra consulta. Es más, no tendremos que tener las consultas dentro del propio WebService, sino que nos basaremos para configurarlas en un fichero XML. Esto nos va a permitir disponer de un código muy limpio y claro, con muy poco mantenimiento posterior, y configuraremos las posibles opciones y sus consultas relacionadas en un fichero XML, de forma que para crear, modificar, o eliminar nuevos métodos, no modificaremos el servicio web, sino únicamente el XML. Veamos cómo.

Fichero de configuración
Vamos a crear un fichero XML de configuración que contendrá los métodos de que dispondrá el servicio web. Posteriormente, dicho servicio recibirá el método a ejecutar, su lista de parámetros, y devolverá los resultados.

El fichero podría ser el siguiente:
<?xml version="1.0" encoding="utf-8" ?>
<OpcionesDisponibles>
  <opcion>
    <nombre>GetPaises</nombre>
    <SQL>SELECT cod_pais,pais FROM paises order by pais</SQL>
  </opcion>
  <opcion>
    <nombre>GetPais</nombre>
    <SQL>SELECT cod_pais,pais FROM paises WHERE cod_pais='#PARAMETRO_1#'</SQL>
  </opcion>
</OpcionesDisponibles>
Como se puede ver, es extremadamente simple, y nos permitirá ampliar, modificar, o reducir el servicio web sin tener que modificarlo.

El WebService
Una vez que sabemos lo que queremos, y que tenemos nuestro fichero de configuración de métodos definido, sólo nos queda crear el servicio web.

Nuestro servicio recibirá tres parámetros: la opción a ejecutar, la lista de parámetros relativas a esa función, y el formato de resultado que deseamos. Así pues, manos a la obra:
<?php
  // Recoger parámetros de entrada. Se permite GET y POST
  $paramOpcion = $_REQUEST['opcion'];
  $paramLista = $_REQUEST['listaParametros'];
  $formato = strtolower($_REQUEST['format']) == 'xml' ? 'xml' : 'json';

  // Obtener consulta SQL a ejecutar
  $sql = getSQL($paramOpcion);
  $sql = aplicarParametrosSQL($sql,$paramLista);

  // Lanzar consulta a la base de datos
  if ($sql == '')
    die ('Opcion incorrecta');
  else
  {    
    $datos = getArrayDatos($sql);
    echo formatData($datos,$formato); 
  }


  // Dado un nombre de opción, buscar en el xml su SQL correspondiente
  function getSQL($nombreOpcion)
  {
    $xmlOpciones = simplexml_load_file('opciones.xml');
    $sql = ""; 
    foreach ($xmlOpciones->opcion as $opcion)
    {
      $nombre = $opcion->nombre;
      if ($nombre == $nombreOpcion)
      {
        $sql = $opcion->SQL;
        break;
      }
    }
    return $sql;
  }

  // Aplicar parámetros de la sentencia SQL
  function aplicarParametrosSQL($sql, $listaPametros)
  {    
    if ($listaPametros != '')
    {
      $arrParam = explode('#',$listaPametros);
      for ($i=0; $i<count($arrParam); $i++)
      {
        $nomParam = '#PARAMETRO_'.($i+1).'#';
        $valor = $arrParam[$i];
        $sql = str_replace($nomParam, $valor, $sql);
      }
    }
    return $sql;
  }

  function getArrayDatos($sql)
  {
    $db = mysql_connect('servidor_base_datos','usuario','clave') or die('No se pudo conectar con la base de datos');
    mysql_select_db('base_de_datos',$db) or die('No se pudo seleccionar la base de datos.');
    $resul = mysql_query($sql,$db) or die('Consulta incorrecta:  '.$sql);

    /* create one master array of the records */
    $datos = array();
    if(mysql_num_rows($resul)) 
    {
     while($row = mysql_fetch_assoc($resul)) 
     {
      $datos[] = $row;
     }
    }

    /* disconnect from the db */
    @mysql_close($db);    

    /* Return data array */
    return $datos;        
  }

  function formatData($data,$format='json')
 {
    if($format == 'json' || $format == 'jsonp') 
    {
      header('Content-type: application/json');
      if (isset($_REQUEST['callback']))   // Peticiones ajax
        return $_REQUEST['callback'].'('.json_encode($data).')';
      else
        return json_encode($data);
    }
    else
    {
      header('Content-type: text/xml');
      $xml = new SimpleXMLElement('<response/>');
      return array2xml($data, $xml);
    }
  }

  function array2xml($array, $xml = false)
  {
    if($xml === false)
    {
      $xml = new SimpleXMLElement('<root/>');
    }
    foreach($array as $key => $value)
    {
      if(is_array($value))
      {
        //array2xml($value, $xml->addChild($key));
        array2xml($value, $xml->addChild('item'));
      }
      else
      {
        $xml->addChild($key, htmlspecialchars($value));
      }
    }
    return $xml->asXML();
  }

?>
Y eso es todo. Potente, ¿verdad?. Ahora sólo debemos modificar el fichero XML a nuestro gusto para adaptarlo a nuestras necesidades (ojo, recordar introducir algún sistema de seguridad, y a ser posible, excluir el fichero XML en el fichero robots.txt de nuestro servidor para que no sea indexado).

En otra entrada veremos como consumir un webservice.

 

Copyright @ 2015 Tosblama