Crear botón de impresión en ReportViewer de ASP.NET WebForms

Hola nuevamente. Este post es una segunda versión del post titulado Imprimir reporte de ReportViewer desde otro navegador web que no sea IE. Entre las mejoras de esta nueva versión está que en vez de añadir un botón normal para la impresión fuera del ReportViewer, ahora se añade el botón de impresión dentro de la barra de herramientas del ReportViewer, y luce exactamente igual al botón propio del control. Además, con esta nueva versión también se logra que la impresión funcione en IE 9 y 10 en modo normal. La única desventaja es que hay que desactivar la renderización asíncrona y los postbacks asíncronos, para poder colocar el botón de impresión con jQuery, ya que se necesita alguna forma de saber en qué momento colocar el botón, y la única forma que encontré es hacerlo al momento de cargar la página web luego del postback en el que se solicita la generación del reporte, durante el evento load.

Los pasos para colocar nuestro botón de impresión personalizado en la barra de herramientas del ReportViewer son los siguientes:

    1. Incluir la librería jQuery en el encabezado de la página web:
      <script src="<%=Page.ResolveUrl("~/Scripts/jquery-1.7.1.min.js") %>" type="text/javascript"></script>
      
    2. Agregar el control de ReportViewer, desactivando el renderizado asíncrono y el postback asíncrono, y ocultando el botón de impresión:
      <rsweb:ReportViewer ID="ReportViewer1" runat="server" AsyncRendering="False" InteractivityPostBackMode="AlwaysSynchronous" ShowPrintButton="False">
      </rsweb:ReportViewer>
      
    3. Colocar en el encabezado de la página web el siguiente código JavaScript (el cual se explica un poco en los comentarios):
      // Guardando la URL de la imagen del botón imprimir. Esta imagen es una copia de la imagen mostrada en el ReportViewer, guardada en la carpeta de imágenes de la aplicación web.
      var urlImg = '<%=Page.ResolveUrl("~/Content/themes/base/minified/images/Print.gif") %>';
      
      // Función que se ejecuta una vez se ha terminado de cargar el DOM de la página web en el navegador
      $(document).ready(function () {
          colocarBtnImprimir();    // Colocar el botón de imprimir en la barra de herramientas del ReportViewer
          $("#BtnImprimir").click(imprimirDiv);  // Asignando la función "imprimirDiv" al evento click del botón de impresión
      });
      
      // Esta función coloca el botón de imprimir en la barra de herramientas del ReportViewer
      function colocarBtnImprimir() {
          var jqoBarraRpt = $('div#ReportViewer1_ctl05>div:first-child');    // Buscando el div que contiene la barra de herramientas del RportViewer
      
          if (jqoBarraRpt && jqoBarraRpt.length > 0    // Verificando que el DIV barra de herramientas fue encontrado,
              && jqoBarraRpt.find('#BtnImprimir').length <= 0) {    // y verificando que el botón de imprimir no existe ya
      
              // Colocando el botón de impresión, con una estructura similar a la que tiene el botón original en el ReportViewer
              jqoBarraRpt.append('<table cellpadding="0" cellspacing="0" ToolbarSpacer="true" style="display:inline;width:10px;"><tr><td></td></tr></table><div style="display:inline;font-family:Verdana;font-size:8pt;vertical-align:top;"><table cellpadding="0" cellspacing="0" style="display:inline;"><tr><td height="28px"><div"><div id="BtnImprimir"><table title="Print"><tr><td><img title="Print" src="' + urlImg + '" alt="Print" style="border-style:None;height:16px;width:16px;" /></td></tr></table></div><div disabled="disabled" style="display:none;border:1px transparent Solid;"><table title="Print"><tr><td><input type="image" disabled="disabled" title="Print" src="' + urlImg + '" alt="Print" style="border-style:None;height:16px;width:16px;cursor:default;" /></td></tr></table></div></div></td></tr></table></div>');
          }
      }
      
      // Función que se encarga de imprimir el reporte
      function imprimirDiv()
      {
          var divImprimir = $("div[id$='ReportDiv']").parent();    // Obteniendo el DIV que contiene el reporte a imprimir
          var newWin = window.open();    // Abriendo una nueva ventana del navegador
          newWin.document.open();    // Abriendo el documento de la nueva ventana, para escribir su contenido
          newWin.document.write('<html><head><style type="text/css">' + getAllStyleSheetsAsText() + '</style></head><body>' + divImprimir.html() + '</body>');
          newWin.document.close();
          newWin.print();
          newWin.close();
      }
      
      function getAllStyleSheetsAsText() {
          var cssText = '';
          var sheets = document.styleSheets;
          for (var c = 0; c < sheets.length; c++) {
              var sheet = sheets[c];
              if ((sheet.ownerNode || sheet.owningElement).id.endsWith('_ReportControl_styles')) {
                  var rules = sheet.rules || sheet.cssRules;
                  for (var r = 0; r < rules.length; r++) {
                      var cssRule = rules[r];
                      if ($.browser.msie) {
                          var cssText = cssText + cssRule.selectorText + '{' + cssRule.style.cssText.toLowerCase() + '}';
                      } else {
                          var cssText = cssText + cssRule.cssText;
                      }
                  }
              }
          }
          return cssText;
      }
      
    4. Finalmente, hay que agregar el estilo CSS para el botón de impresión, para que luzca igual al botón original del ReportViewer:
      #BtnImprimir {
          border: 1px solid transparent;
      }
      #BtnImprimir:hover {
          border: 1px solid rgb(51,102,153);
          background-color: rgb(221,238,247);
          cursor:pointer;
      }
      

Y ¡listo!. Ahora veremos que cada vez que se genere el reporte y se muestre la barra de herramientas del ReportViewer, se mostrará nuestro botón de impresión personalizado:

Botón de impresión

Botón de impresión

Lo único que tengo que mencionar es que aún no he probado la impresión de reportes con más de una página. Pero para reportes de una sola página parece funcionar correctamente.

Saludos.

Anuncios

Viejos posts publicados

Minientrada

Saludos a todos. Estuve revisando un poco mis documentos y encontré algunos posts que ya tenía listos para publicar desde hace varios años. Un par de ellos fueron colaboraciones al blog de un amigo de la universidad, y otros en realidad son manuales que escribí para acordarme cómo hacer las cosas. Les dejo abajo los enlaces a dos de estos posts, y espero posteriormente incluir otros más:

Conexión a fuente de datos (PostgreSQL) en iReport 3.7.3

PLT Scheme – Verificar que una cadena contiene solo letras minúsculas

Para finalizar esta entrada, les dejo una frase un tanto soberbia de Nikola Tesla, con respecto al trabajo de Thomas Alva Edison:

“If Edison had a needle to find in a haystack, he would proceed at once with the diligence of the bee to examine straw after straw until he found the object of his search… I was a sorry witness of such doings, knowing that a little theory and calculation would have saved him ninety per cent of his labor.”
– Nikola Tesla, New York Times, October 19, 1931

Traducido:

“Si Edison tuviera que encontrar una aguja en un pajar, procedería inmediatamente con la diligencia de una abeja a examinar paja por paja hasta que encontrara el objeto de su búsqueda… Fui testigo arrepentido de tales hechos, sabiendo que un poco de teoría y cálculo le hubiera ahorrado el noventa por ciento de su tarea.”
– Nikola Tesla, New York Times, 19 de octubre de 1931

Es muy curioso que esta frase parece mostrarse reactiva o contrastante a la siguiente frase de Edison:

“No me equivoque mil veces para hacer una bombilla, descubri mil maneras de como no hacer una bombilla.”
– Thomas Alva Edison

Esta frase la encontré en un archivo viejo en el que tenía una recopilación de frases que me habían llamado la atención. Nikola Tesla es uno de mis científicos favoritos, y según parece sus invenciones no son muy conocidas incluso en la actualidad, en comparación con el trabajo de Thomas Alva Edison.

Feliz día.

Enviar mensajes a sesiones de terminal server desde línea de comandos

¡Me mudo! Pueden encontrar esta entrada en mi nuevo blog: http://itsouvenirs.blogspot.com/2013/04/wp-enviar-mensajes-sesiones-de-terminal.html

Anoche se presentó un problema en mi trabajo. Debido al incremento de trabajo por parte de los usuarios conectados vía Terminal Server a uno de los servidores de la empresa, este se quedó sin recursos suficientes para poder iniciar otra sesión más. Se decidió reiniciar el servidor, pero era necesario informar a los usuarios. ¿Cómo enviar un mensaje directo vía Terminal Server, sin iniciar sesión en el servidor ni entrar al administrador de TS? Una opción sencilla y directa es hacer uso del comando msg desde la línea de comandos en una computadora conectada a dicho servidor:

msg { nombre_usuario | id_sesion_ts | * } [/SERVER:servidor] “mensaje”

El primer parámetro puede ser el nombre del usuario, el ID de la sesión, o asterisco, que indica que el mensaje se enviará a todas las sesiones activas en la computadora. El segundo parámetro, que es el de servidor es opcional, y puede colocarse el nombre del equipo o bien la IP. Si no se especifica, el mensaje se enviará a todas las sesiones activas en la computadora local. El parámetro final es el mensaje, que debe especificarse entre comillas dobles en caso de poseer caracteres de espacio en blanco.

Por ejemplo:

msg juanperez “Hola mundo”

msg DOMINIO\juanperez /SERVER:mi-servidor “Hola mundo”

Cabe mencionar que no he especificado todas las opciones del comando msg. Para conssultar todas las opciones que ofrece este comando, basta con digitar msg en la línea de comandos de Windows, y presionar Enter. Si no me equivoco, este es el comando que se recomienda usar en vez de NET SEND a partir de Windows XP y Windows Server 2003 (corríjanme si me equivoco, jejeje).