Categories
.NET ASP.NET Windows Forms

Exportar reportes a PDF desde código

A partir de Visual Studio 2005, se incluyeron nuevos controles (ReportViewer) y clases (LocalReport, ServerReport, etc) con los cuales se pueden diseñar reportes tanto para aplicaciones de escritorio como para aplicaciones Web.

Una característica útil de estas nuevas clases, al igual que los reportes diseñados en Crystal Reports, es que permiten automatizar el proceso de conversión de los reportes a diferentes a diferentes formatos: MS Excel, PDF e Imagenes (en formato TIFF).

Revisando documentación acerca de este conjunto de clases encontré un ejemplo publicado por Raj Kaimal que justamente exporta los reportes a formato PDF desde ASP.NET usando el método Render de la clase LocalReport:

csharp:

private void RenderReport()
{
    LocalReport localReport = new LocalReport();
    localReport.ReportPath = Server.MapPath("~/Productos.rdlc");

    ReportDataSource reportDataSource = new ReportDataSource("Ejemplo_Productos", GetData());
    localReport.DataSources.Add(reportDataSource);

    string reportType = "PDF";

    string mimeType;
    string encoding;
    string fileNameExtension;
   
    //The DeviceInfo settings should be changed based on the reportType
    //http://msdn2.microsoft.com/en-us/library/ms155397.aspx

    string deviceInfo =
    "<DeviceInfo>" +
    "  <OutputFormat>PDF</OutputFormat>" +
    "  <PageWidth>8.5in</PageWidth>" +
    "  <PageHeight>11in</PageHeight>" +
    "  <MarginTop>0.5in</MarginTop>" +
    "  <MarginLeft>1in</MarginLeft>" +
    "  <MarginRight>1in</MarginRight>" +
    "  <MarginBottom>0.5in</MarginBottom>" +
    "</DeviceInfo>";

    Warning[] warnings;
    string[] streams;
    byte[] renderedBytes;
   
    //Render the report
    renderedBytes = localReport.Render(
        reportType,
        deviceInfo,
        out mimeType,
        out encoding,
        out fileNameExtension,
        out streams,
        out warnings);
   
    Response.Clear();
    Response.ContentType = mimeType;
    Response.AddHeader("content-disposition", "attachment; filename=productos." + fileNameExtension);
    Response.BinaryWrite(renderedBytes);
    Response.End();
}

En la primera porción de código resaltada, reportType puede tomar los siguientes valores: PDF, Excel o Image; los valores para deviceInfo varían de acuerdo al formato que se use y están documentados en MSDN

Por si alguien está interesado, he preparado un pequeño ejemplo basado en el código mostrado.

Categories
.NET Windows Forms

Tip: Permitir sólo la entrada de números en un TextBox

Una forma sencilla de limitar que los usuarios sólo puedan ingresar números en determinados TextBox es la siguiente:

csharp:

public Form1()
{
    InitializeComponent();

    textBox1.KeyPress += new KeyPressEventHandler(textBox1_KeyPress);
}
void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    // Permitir sólo las teclas de control o números
    if (!(char.IsControl(e.KeyChar) || char.IsDigit(e.KeyChar)))
    {
        e.Handled = true;
    }
}

Puse a disposición el proyecto de prueba por si alguién está interesado.

Actualización: La porción de código mostrada todavía permite la entrada de otros caracteres (vía copiar & pegar), queda como tarea para el interesado completar la implementación de este ejemplo.

Categories
.NET ASP.NET Internet Explorer Web Windows Forms

Capturar una página Web de manera sencilla

Por si alguien necesita una funcionalidad parecida a lo que ofrecen sitios como WebSnapr o Snap, a continuación pongo la manera de capturar una página web como imagen.

csharp:

string url = "http://www.buayacorp.com/";
using (WebBrowser navegador = new WebBrowser())
{
    // Tamaño del navegador
    navegador.Size = new Size(1024, 768);
    // Deshabilitar la barra de scroll
    navegador.ScrollBarsEnabled = false;

    // Cargar la página
    navegador.Navigate(url);

    // Esperar a que cargue completamente la página
    while (navegador.ReadyState != WebBrowserReadyState.Complete)
    {
        Application.DoEvents();
    }
    // Tamaño de la imagen a capturar
    Rectangle tamaño = new Rectangle(0, 0, 1024, 768);
    Bitmap bitmap = new Bitmap(tamaño.Width, tamaño.Height);

    // Guardar la imagen de la página con el tamaño especificado
    navegador.DrawToBitmap(bitmap, tamaño);

    // Convertir y guardar la imagen como jpg
    Bitmap thumbnail = new Bitmap(tamaño.Width, tamaño.Height);
    Graphics gfx = Graphics.FromImage(thumbnail);
    gfx.DrawImage(bitmap, tamaño, tamaño, GraphicsUnit.Pixel);

    thumbnail.Save(@"E:\demos\demo.jpg", ImageFormat.Jpeg);
}

Esa porción de código hace una captura de 1024x728 pixeles, si se quiere capturar la página completa sólo es necesario jugar con los valores de navegador.Document.Body.ClientRectangle.

Por otro lado, como seguramente saben la clase WebControl usa internamente los controles de Internet Explorer disponibles en la máquina donde se ejecuta la aplicación, así que si un sitio se ve mal con este navegador, la imagen capturada también tendrá este pequeño problema.

Categories
.NET ASP.NET Desarrollo de Software Utilidades Web Windows Forms

Reflector 5.0

Al parecer ayer se liberó una nueva versión de Reflector, una herramienta muy útil que permite explorar, analizar, ver, etc. los ensamblados de .NET.

Entre las novedades que trae esta versión, están:

  • Soporte para LINQ y el .NET Framework 3. 5
  • Existe un nuevo protocolo "code://" que hace que Reflector cargue el tipo especificado, por ejemplo code://System.Web/System.Web.HttpResponse/TransmitFile(String) debería ubicarlos en el método TransmitFile de la clase HttpResponse.
  • Existe la posibilidad de registrar una extensión (Reflector.exe /register) para que cada vez que se haga click derecho sobre un ensamblado compatible con .NET, aparezca una opción "Browse with .NET Reflector" en el menú contextual.

Para sacarle más provecho a esta herramienta, se pueden agregar plugins de acuerdo a las necesidades que tenga uno.

Categories
.NET Desarrollo de Software Utilidades Windows Forms

Zoner & Seguridad de Acceso a Código

Los que han estado desarrollando aplicaciones de escritorio con .NET, seguramente saben que el CLR es el encargado de lo que puede o no hacer una aplicación en función a los permisos que reciba.

Code Access Security

Por si no saben todavía de la existencia de Zoner, ésta es una pequeña herramienta que permite probar si una determinada aplicación funciona o no en una zona determinada.

Este es el código de Zoner:

csharp:

using System;
using System.Reflection;
using System.Security;
using System.Security.Policy;

class App
{
    public static void Main(String[] args)
    {
        try
        {
            SecurityZone zone = SecurityZone.Internet;
            String url = "http://www.IBuySpy.com";
            String exe;
            String[] newArgs = null;

            for (Int32 index = 0; ; index++)
            {
                if (args[index][0] != '-' && args[index][0] != '/')
                {
                    exe = args[index];
                    newArgs = new String[args.Length - (index + 1)];
                    Array.Copy(args, index + 1, newArgs, 0, newArgs.Length);
                    break;
                }

                String setting = args[index].Substring(3);

                switch (args[index].ToUpper()[1])
                {
                    case 'Z': // Set zone
                        zone = (SecurityZone) Enum.Parse(typeof(SecurityZone), setting, true);
                        break;
                    case 'U': // Set url
                        url = setting;
                        break;
                    default:
                        throw (new ApplicationException());
                }
            }
            StartApp(exe, newArgs, zone, url);
        }
        catch (ArgumentException)
        {
            Usage();
        }
        catch (IndexOutOfRangeException)
        {
            Usage();
        }
        catch (ApplicationException) { Usage(); }
    }
    static void Usage()
    {
        Console.WriteLine(
           "Usage: zoner /u:[url] /z:[zone] [Executable File]\n" +
           "[url]\tUrl indicating the source of this .exe");
        Console.WriteLine();
        Console.Write("[zone]");
       
        String[] zones = Enum.GetNames(typeof(SecurityZone));
        foreach (String zone in zones)
        {
            Console.WriteLine("\t{0}", zone);
        }
        Console.WriteLine(
           "\nDefault:  zoner /u:http://www.IBuySpy.com /z:Internet");
    }
   
    static void StartApp(String exe,
       String[] newArgs, SecurityZone zone, String url)
    {
        Evidence evidence = new Evidence();

        evidence.AddHost(new Zone(zone));
        evidence.AddHost(new Url(url));
        AppDomain app = AppDomain.CreateDomain(exe, evidence);
        app.ExecuteAssembly(exe, evidence, newArgs);
    }
}

Lo que hace esta porción de código, es simplemente ejecutar en otro dominio la aplicación que se quiere probar, pero adjuntando información de la zona escogida.

Espero que esta pequeña utilidad les ayude a ahorrar un poco de tiempo :).