martes, 2 de agosto de 2016

El Libro del Día: C# 6.0 in a Nutshell

El Libro del Día: 2016-08-02

Titulo: C# 6.0 in a Nutshell (6th Edition)
Autor: Joseph Albahari, Ben Albahari
Editorial: O'Reilly
Nro Paginas: 1133

Capítulos:
1. Introducing C# and the .NET Framework
2. C# Language Basics
3. Creating Types in C#
4. Advanced C#
5. Framework Overview
6. Framework Fundamentals
7. Collections
8. LINQ Queries
9. LINQ Operators
10. LINQ to XML
11. Other XML Technologies
12. Disposal and Garbage Collection
13. Diagnostics and Code Contracts
14. Concurrency and Asynchrony
15. Streams and I/O
16. Networking
17. Serialization
18. Assemblies
19. Reflection and Metadata
20. Dynamic Programming
21. Security
22. Advanced Threading
23. Parallel Programming
24. Application Domains
25. Interoperability
26. Regular Expressions
27. The Roslyn Compiler

Descarga:
C#_6.0_in_a_Nutshell

Videos - Carrito de Compras en ASP.NET MVC & JavaScript

Videos del Carrito de Compras en ASP.NET MVC & JavaScript

Quiero compartir con los que No asistieron a mi último taller y con los visitantes del Blog de otros países los videos de una aplicación completa en ASP.NET MVC & JavaScript que tiene un 20% de código en el servidor (C#) y un 80% de código en el cliente (JavaScript).

Partes de la Aplicación

La aplicación es un Carrito de Compras que trabaja con la BD Northwind a la cual se le aumento la tabla de Usuarios asociados a cada Cliente (para el Login y ordenar el Pedido).
Esta consta de 4 vistas o páginas:

- Login: Esta página permite el ingreso de un usuario y su clave, mas un código de Captcha.

- Categorias: Página que lista las Categorías de Productos.

- Productos: Página que lista los Productos de una cierta Categoría y permite agregar una cantidad al Carrito y también ir a ver.

- Pedidos: Página que permite mostrar los pedidos y cambiar su cantidad o eliminar un producto del pedido. También permite grabar el pedido al cliente.

Características Técnicas

Este Carrito de Compras tiene las siguientes características:

- Los controladores están protegidos por un Filtro de Autenticación usando una Sesión para el Cliente, es decir no se puede ir a ningún controlador o vista sino te autenticas (Login).

- Todas las llamadas al servidor son asíncronas con XHR (No jQuery, No Angular, etc)

- Todos los datos enviados al cliente se serializan a CSV (No XML ni JSON que son mas grandes por tener metadata).

- El Login usa un Captcha y cifrado en el cliente con WebCryptoAPI (No Librerías Externas JS)

- Todas las imágenes vienen en un solo viaje (No Sprite sino Serializado en Conjunto).

- Los datos del pedido se almacenan en el cliente con SessionStorage (No Session en el servidor).

- La grabación de la cabecera detalle es muy rápida ya que se pasa una cadena desde el cliente hasta el servidor web y de datos consumiendo una sola conexión y ejecutando un solo comando.

Videos del Carrito de Compras

Carrito de Compras Parte 1



Carrito de Compras Parte 2


Carrito de Compras Parte 3


Carrito de Compras Parte 4


Comentario Final

Este Carrito de Compras es totalmente distinto al que ven en la mayoría de sitios web que enseñan ASP.NET, ya que tiene muy poco código y trabaja casi desconectado donde toda la funcionalidad se construye con JavaScript y es 100% asíncrono con XHR.

No es un Carrito de Compras tradicional, es un "Formula 1" pura Performance usando JavaScript nativo que se ejecuta en cualquier Browser moderno.

Lástima que solo unos pocos pudieron apreciar esta interesante demostración de un nuevo tipo de aplicaciones. Para los que están en Lima y se atreven a pedir el código fuente, la respuesta es "hubieras participado en el taller" y para los del exterior pronto veremos la forma de que estos cursos se hagan virtuales (primero vería si tienen demanda, para lo cual están sus comentarios).

lunes, 1 de agosto de 2016

El Libro del Día: C# 6.0 Cookbook

El Libro del Día: 2016-08-01

Titulo: C# 6.0 Cookbook (4th Edition)
Autor: Jay Hilyard, Stephen Teilhet
Editorial: O'Reilly
Nro Paginas: 703

Capítulos:
1. Classes and Generics
2. Collections, Enumerators, and Iterators
3. Data Types
4. Language Integrated Query (LINQ) and Lambda Expressions
5. Debugging and Exception Handling
6. Reflection and Dynamic Programming
7. Regular Expressions
8. Filesystem I/O
9. Networking and Web
10. XML
11. Security
12. Threading, Synchronization, and Concurrency
13. Toolbox

Descarga:
C#_6.0_Cookbook

El Demo del Día: Exportar a Excel 2007 desde Listas y Tablas usando OLEDB

Exportar a Excel 2007 desde Listas y Tablas usando OLEDB

1. Requerimiento

- Se desea exportar a Excel 2007 varias hojas desde tablas en un DataSet.
- Se desea exportar a Excel 2007 varias hojas desde listas de objetos de un objeto contenedor.

2. Técnicas para Crear un Archivo de Excel

Existen muchas técnicas pero vamos a describir brevemente las 3 principales:

2.1 Automatización ActiveX o COM

Consiste en abrir una instancia de Excel desde otra aplicación (en este caso en .NET) y llenar las celdas de cada hoja una por una, luego grabar el archivo y cerrar la instancia de Excel abierta.

Hay 2 inconvenientes: el primero es que tenemos que tener instalado Excel donde se va a ejecutar la aplicación y si es web sería en el servidor, el segundo es que si es una aplicación web hay muchos problemas desde dar permisos al COM de Excel para que se ejecute hasta cerrar la instancia que siempre se queda abierta.

Esta técnica es la peor, pero quizás la más popular (por ser la más fácil), si es una aplicación Windows no hay muchos problemas por que cada aplicación corre en diferentes máquinas, pero si es web, les aconsejaría que cambien de técnica (jamás se debería usar en ASP.NET).

2.2. Usando OLEDB

Esta técnica consiste en crear un archivo de texto separados por comas o algún caracter delimitador y luego usando OLEDB ejecutar un comando que convierta el archivo de texto creado previamente en un archivo de Excel 2007.

También tenemos 2 grandes inconvenientes: el primero es que hay que tener instalado el "Microsoft Access Database Engine 2010 Redistributable", el segundo es que se presentarán problemas de codificación (Encoding), formatos y estilos, por ejemplo códigos que son cadenas con ceros a la izquierda que se convierten en numéricos (sin ceros a la izquierda), ajuste de decimales, formato de fechas y horas, campos memos, colores de fondo, colores de texto, tamaños, etc.

En este post veremos esta técnica sin considerar los problemas que se pueden presentar por el tipo de datos a exportar, el cual lo veremos en otro post que será de mucha ayuda para cientos de programadores que pasan por estos problemas.

2.3. Usado Archivos

Esta técnica es la más optima y natural, consiste en crear archivos XML con los formatos establecidos por Open XML y luego comprimirlos en un archivo de Excel 2007 (xlsx).

Si el programador conoce la especificación y formato de cada archivo xml necesario y sabe manejo de archivos para crearlos y comprimirlos, entonces lo más recomendable es que lo haga el mismo, sino, puede usar una librería de terceros que lo haga por él, tales como: SpreedSheet (DevExpress), NPOI, EPPlus, etc.

En otros post enseñaré como crear archivos de Excel simples (datos sin formato) y complejos (con imágenes, formatos, etc).

3. Crear una Aplicación Windows Forms en C#

Abrir Visual Studio y crear una aplicación Windows Forms en C# llamada "Excel_Crear_OLEDB", cambiarle de nombre al formulario por "frmExcel" y realizar el diseño similar a la figura mostrada:

Diseño del formulario "frmExcel"

En el diseño hay los siguientes controles:
- Botón para Llenar desde Listas llamado "btnLlenarLista".
- Botón para Llenar desde Tablas llamado "btnLlenarTabla".
- Botón para Exportar Listas a Excel llamado "btnExportarListas". Deshabilitado por defecto.
- Botón para Exportar Tablas a Excel llamado "btnExportarTablas". Deshabilitado por defecto.
- Control Tab llamado "tabExcel" con 2 tabPages: "tabCategorias" y "tabProducto".
- Control DataGridView llamado "dgvCategoria" ubicado en el tab de Categorias.
- Control DataGridView llamado "dgvProducto" ubicado en el tab de Productos.

4. Crear las Clases con las Entidades de Negocio

Lo primero que debemos crear son las clases de entidades para las listas de objetos de categorías y productos:

Archivo de Clase: beCategoria.cs

namespace Excel_Crear_OLEDB
{
    public class beCategoria
    {
        public int IdCategoria { get; set; }
        public string Nombre { get; set; }
    }
}

Archivo de Clase: beProducto.cs

namespace Excel_Crear_OLEDB
{
    public class beProducto
    {
        public int IdProducto { get; set; }
        public string Nombre { get; set; }
        public int IdCategoria { get; set; }
        public decimal Precio { get; set; }
        public short Stock { get; set; }
    }
}

Archivo de Clase: beCategoriaProducto.cs

using System.Collections.Generic;

namespace Excel_Crear_OLEDB
{
    public class beCategoriaProducto
    {
        public List<beCategoria> ListaCategoria { get; set; }
        public List<beProducto> ListaProducto { get; set; }
    }
}

5. Crear una Clase que permita llenar los Datos

Lo segundo que debemos hacer es crear una clase para llenar los datos de las tablas y listas de objetos tanto para categorías como productos.

En una aplicación real esto se reemplazará por la llamada a un componente de reglas del negocio y solo se elegirá uno de las 2 repositorios de datos: DataSet o Objeto con Listas. Lo recomendable es elegir el Objeto con Listas ya que consume menos memoria y procesa más rápido.

Archivo de Clase: Data.cs

using System;
using System.Collections.Generic;
using System.Data;

namespace Excel_Crear_OLEDB
{
    public class Data
    {
        public static List<beCategoria> ListaCategorias()
        {
            //Llenar la Lista de Categorias
            List<beCategoria> lbeCategoria = new List<beCategoria>();
            lbeCategoria.Add(new beCategoria
            {
                IdCategoria = 1,
                Nombre = "Bebidas"
            });
            lbeCategoria.Add(new beCategoria
            {
                IdCategoria = 2,
                Nombre = "Cereales"
            });
            lbeCategoria.Add(new beCategoria
            {
                IdCategoria = 3,
                Nombre = "Condimentos"
            });
            lbeCategoria.Add(new beCategoria
            {
                IdCategoria = 4,
                Nombre = "Lacteos"
            });
            lbeCategoria.Add(new beCategoria
            {
                IdCategoria = 5,
                Nombre = "Pastas"
            });
            return lbeCategoria;
        }

        public static List<beProducto> ListaProductos()
        {
            //Llenar la Lista de Productos
            List<beProducto> lbeProducto = new List<beProducto>();
            lbeProducto.Add(new beProducto
            {
                IdProducto = 1,
                Nombre = "Pepsi",
                IdCategoria = 1,
                Precio = 1.5M,
                Stock = 100
            });
            lbeProducto.Add(new beProducto
            {
                IdProducto = 2,
                Nombre = "Avena 3 Ositos",
                IdCategoria = 2,
                Precio = 2.0M,
                Stock = 50
            });
            lbeProducto.Add(new beProducto
            {
                IdProducto = 3,
                Nombre = "Ajinomoto",
                IdCategoria = 3,
                Precio = 0.5M,
                Stock = 200
            });
            lbeProducto.Add(new beProducto
            {
                IdProducto = 4,
                Nombre = "Leche Gloria",
                IdCategoria = 4,
                Precio = 3.5M,
                Stock = 300
            });
            lbeProducto.Add(new beProducto
            {
                IdProducto = 5,
                Nombre = "Fideos Lavaggi",
                IdCategoria = 5,
                Precio = 3.0M,
                Stock = 150
            });
            lbeProducto.Add(new beProducto
            {
                IdProducto = 6,
                Nombre = "Sprite",
                IdCategoria = 1,
                Precio = 2.0M,
                Stock = 200
            });
            lbeProducto.Add(new beProducto
            {
                IdProducto = 7,
                Nombre = "Quinua Avena",
                IdCategoria = 2,
                Precio = 2.5M,
                Stock = 150
            });
            lbeProducto.Add(new beProducto
            {
                IdProducto = 8,
                Nombre = "Tuco Sibarita",
                IdCategoria = 3,
                Precio = 0.5M,
                Stock = 200
            });
            lbeProducto.Add(new beProducto
            {
                IdProducto = 9,
                Nombre = "Leche Pura Vida",
                IdCategoria = 4,
                Precio = 3.5M,
                Stock = 300
            });
            lbeProducto.Add(new beProducto
            {
                IdProducto = 10,
                Nombre = "Spagetti Don Victorio",
                IdCategoria = 5,
                Precio = 2.0M,
                Stock = 250
            });
            return lbeProducto;
        }

        public static DataTable TablaCategorias()
        {
            //Llenar la Tabla de Categorias
            DataTable tblCategoria = new DataTable();
            tblCategoria.Columns.Add("IdCategoria",
                Type.GetType("System.Int32"));
            tblCategoria.Columns.Add("Nombre",
                Type.GetType("System.String"));
            DataRow drCat1 = tblCategoria.NewRow();
            drCat1[0] = 1;
            drCat1[1] = "Bebidas";
            tblCategoria.Rows.Add(drCat1);
            DataRow drCat2 = tblCategoria.NewRow();
            drCat2[0] = 2;
            drCat2[1] = "Cereales";
            tblCategoria.Rows.Add(drCat2);
            DataRow drCat3 = tblCategoria.NewRow();
            drCat3[0] = 3;
            drCat3[1] = "Condimentos";
            tblCategoria.Rows.Add(drCat3);
            DataRow drCat4 = tblCategoria.NewRow();
            drCat4[0] = 4;
            drCat4[1] = "Lacteos";
            tblCategoria.Rows.Add(drCat4);
            DataRow drCat5 = tblCategoria.NewRow();
            drCat5[0] = 5;
            drCat5[1] = "Pastas";
            tblCategoria.Rows.Add(drCat5);
            return tblCategoria;
        }

        public static DataTable TablaProductos()
        {
            //Llenar la Tabla de Productos
            DataTable tblProducto = new DataTable();
            tblProducto.Columns.Add("IdProducto",
                Type.GetType("System.Int32"));
            tblProducto.Columns.Add("Nombre",
                Type.GetType("System.String"));
            tblProducto.Columns.Add("IdCategoria",
                Type.GetType("System.Int32"));
            tblProducto.Columns.Add("Precio",
                Type.GetType("System.Decimal"));
            tblProducto.Columns.Add("Stock",
                Type.GetType("System.Int16"));
            DataRow drPro1 = tblProducto.NewRow();
            drPro1[0] = 1;
            drPro1[1] = "Pepsi";
            drPro1[2] = 1;
            drPro1[3] = 1.5M;
            drPro1[4] = 100;
            tblProducto.Rows.Add(drPro1);
            DataRow drPro2 = tblProducto.NewRow();
            drPro2[0] = 2;
            drPro2[1] = "Avena 3 Ositos";
            drPro2[2] = 2;
            drPro2[3] = 2.0M;
            drPro2[4] = 50;
            tblProducto.Rows.Add(drPro2);
            DataRow drPro3 = tblProducto.NewRow();
            drPro3[0] = 3;
            drPro3[1] = "Ajinomoto";
            drPro3[2] = 3;
            drPro3[3] = 0.5M;
            drPro3[4] = 200;
            tblProducto.Rows.Add(drPro3);
            DataRow drPro4 = tblProducto.NewRow();
            drPro4[0] = 4;
            drPro4[1] = "Leche Gloria";
            drPro4[2] = 4;
            drPro4[3] = 3.5M;
            drPro4[4] = 300;
            tblProducto.Rows.Add(drPro4);
            DataRow drPro5 = tblProducto.NewRow();
            drPro5[0] = 5;
            drPro5[1] = "Fideos Lavaggi";
            drPro5[2] = 5;
            drPro5[3] = 3.0M;
            drPro5[4] = 150;
            tblProducto.Rows.Add(drPro5);
            DataRow drPro6 = tblProducto.NewRow();
            drPro6[0] = 6;
            drPro6[1] = "Sprite";
            drPro6[2] = 1;
            drPro6[3] = 2.0M;
            drPro6[4] = 200;
            tblProducto.Rows.Add(drPro6);
            DataRow drPro7 = tblProducto.NewRow();
            drPro7[0] = 7;
            drPro7[1] = "Quinua Avena";
            drPro7[2] = 2;
            drPro7[3] = 2.5M;
            drPro7[4] = 150;
            tblProducto.Rows.Add(drPro7);
            DataRow drPro8 = tblProducto.NewRow();
            drPro8[0] = 8;
            drPro8[1] = "Tuco Sibarita";
            drPro8[2] = 3;
            drPro8[3] = 0.5M;
            drPro8[4] = 200;
            tblProducto.Rows.Add(drPro8);
            DataRow drPro9 = tblProducto.NewRow();
            drPro9[0] = 9;
            drPro9[1] = "Leche Pura Vida";
            drPro9[2] = 4;
            drPro9[3] = 3.5M;
            drPro9[4] = 200;
            tblProducto.Rows.Add(drPro9);
            DataRow drPro10 = tblProducto.NewRow();
            drPro10[0] = 10;
            drPro10[1] = "Spagetti Don Victorio";
            drPro10[2] = 5;
            drPro10[3] = 2.0M;
            drPro10[4] = 250;
            tblProducto.Rows.Add(drPro10);
            return tblProducto;
        }
    }
}

6. Crear una Clase que permita Crear Archivos de Texto

La tercera parte a codificar es crear una clase que permita crear archivos de texto desde Listas de Objetos o desde Tablas para lo cual usamos IO (FileStream y StreamWriter) y Reflection (PropertyInfo). Adicionalmente para las listas se usa los tipos Genéricos (<T>).

Archivo de Clase: Texto.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Data;
using System.Reflection;

namespace Excel_Crear_OLEDB
{
    public class Texto
    {
        public static void ExportarDeTabla(DataTable tabla, string archivo, char separador)
        {
            using (FileStream fs = new FileStream(archivo, FileMode.Create, 
                       FileAccess.Write, FileShare.Write))
            {
                using (StreamWriter sw = new StreamWriter(fs, Encoding.Default))
                {
                    for (int i = 0; i < tabla.Columns.Count; i++)
                    {
                        sw.Write(tabla.Columns[i].ColumnName);
                        if (i < tabla.Columns.Count - 1) sw.Write(separador);
                    }
                    sw.WriteLine();
                    for (int j = 0; j < tabla.Rows.Count; j++)
                    {
                        for (int i = 0; i < tabla.Columns.Count; i++)
                        {
                            sw.Write(tabla.Rows[j][i].ToString());
                            if (i < tabla.Columns.Count - 1) sw.Write(separador);
                        }
                        sw.WriteLine();
                    }
                }
            }
        }

        public static void ExportarDeLista<T>(List<T> lista, string archivo, char separador)
        {
            using (FileStream fs = new FileStream(archivo, FileMode.Create, 
                       FileAccess.Write, FileShare.Write))
            {
                using (StreamWriter sw = new StreamWriter(fs, Encoding.Default))
                {
                    PropertyInfo[] propiedades = lista[0].GetType().GetProperties();
                    for (int i = 0; i < propiedades.Length; i++)
                    {
                        sw.Write(propiedades[i].Name);
                        if (i < propiedades.Length - 1) sw.Write(separador);
                    }
                    sw.WriteLine();
                    for (int j = 0; j < lista.Count; j++)
                    {
                        propiedades = lista[j].GetType().GetProperties();
                        for (int i = 0; i < propiedades.Length; i++)
                        {
                            sw.Write(propiedades[i].GetValue(lista[j], null).ToString());
                            if (i < propiedades.Length - 1) sw.Write(separador);
                        }
                        sw.WriteLine();
                    }
                }
            }
        }
    }
}

6. Crear una Clase que permita Crear Archivos de Excel 2007

La cuarta parte a codificar y quizás la mas importante, es crear una clase que use OLEDB para crear archivos de Excel 2007 a partir del archivo de texto previamente creado.

Archivo de Clase: Excel.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Data;
using System.Data.OleDb;
using System.Reflection;

namespace Excel_Crear_OLEDB
{
    public class Excel
    {
        public static void ExportarDeLista<T>(List<T> lista, string archivoXlsx, string hoja)
        {          
            string ruta = Path.GetDirectoryName(archivoXlsx);
            string archivoTxt = String.Format("{0}\\{1}.txt", ruta, hoja);
            Texto.ExportarDeLista<T>(lista, archivoTxt, ',');
            crearExcel2007(archivoXlsx, hoja, true);
            File.Delete(archivoTxt);
        }

        public static void ExportarDeTabla(DataTable tabla, string archivoXlsx, string hoja)
        {
            string ruta = Path.GetDirectoryName(archivoXlsx);
            string archivoTxt = String.Format("{0}\\{1}.txt", ruta, hoja);
            Texto.ExportarDeTabla(tabla, archivoTxt, ',');
            crearExcel2007(archivoXlsx, hoja, true);
            File.Delete(archivoTxt);
        }

        static void crearExcel2007(string archivoXlsx, string hoja, bool eliminar)
        {
            string ruta = Path.GetDirectoryName(archivoXlsx);
            using (OleDbConnection con = new OleDbConnection
                      ("provider=Microsoft.Ace.oledb.12.0; data source=" + ruta + ";
                       extended properties=Text;"))
            {
                con.Open();
                OleDbCommand cmd = new OleDbCommand("Select * Into " + hoja +
                " In ''[Excel 12.0 xml;Database=" + archivoXlsx + "]From " + hoja + "#TXT", con);
                cmd.ExecuteNonQuery();
            }
        }

        static void crearExcel2003(string archivoXls, string hoja, bool eliminar)
        {
            string ruta = Path.GetDirectoryName(archivoXls);
            using (OleDbConnection con = new OleDbConnection
                      ("provider=Microsoft.Jet.oledb.4.0;data source=" + ruta + ";
                        extended properties=Text;"))
            {
                con.Open();
                OleDbCommand cmd = new OleDbCommand("Select * Into " + hoja +
                " In ''[Excel 8.0;Database=" + archivoXls + "]From " + hoja + "#TXT", con);
                cmd.ExecuteNonQuery();
            }
        }
    }
}

Nota: Solo se está usando la función crearExcel2007 que genera archivos xlsx, pero he incluido adicionalmente la función crearExcel2003 que genera archivos xls (por si alguno desea crear el formato antiguo).

7. Programar el formulario para que use las Clases creadas y Exporte

El último bloque a codificar es el formulario "frmExcel" en el cual debe escribir el siguiente código:

using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms;

namespace Excel_Crear_OLEDB
{
    public partial class frmExcel : Form
    {
        private beCategoriaProducto obeCatPro;
        private DataSet dstCatPro;
        private string archivoXlsx;

        public frmExcel()
        {
            InitializeComponent();
        }

        private void llenarDesdeListas(object sender, EventArgs e)
        {
            //Simular que se llenan las listas desde la base de datos
            obeCatPro = new beCategoriaProducto();
            obeCatPro.ListaCategoria = Data.ListaCategorias();          
            obeCatPro.ListaProducto = Data.ListaProductos();
            //Enlazar las listas del objeto principal a las grillas
            dgvCategoria.DataSource = obeCatPro.ListaCategoria;
            dgvProducto.DataSource = obeCatPro.ListaProducto;
            //Habilitar botón de Exportar Listas a Excel y deshabilitar el otro
            btnExportarListas.Enabled = true;
            btnExportarTablas.Enabled = false;
        }

        private void llenarDesdeTablas(object sender, EventArgs e)
        {
            //Simular que se llenan las tablas desde la base de datos
            dstCatPro = new DataSet();
            dstCatPro.Tables.Add(Data.TablaCategorias());
            dstCatPro.Tables.Add(Data.TablaProductos());
            //Enlazar las tablas del DataSet a las grillas
            dgvCategoria.DataSource = dstCatPro.Tables[0];
            dgvProducto.DataSource = dstCatPro.Tables[1];
            //Habilitar botón de Exportar Tablas a Excel y deshabilitar el otro
            btnExportarListas.Enabled = false;
            btnExportarTablas.Enabled = true;
        }

        private void guardarExcel(Action exportar)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Title = "Selecciona el Directorio e ingresa Nombre del Archivo Excel";
            sfd.Filter = "Archivos de Excel 2007|*.xlsx";
            if (sfd.ShowDialog().Equals(DialogResult.OK))
            {
                archivoXlsx = sfd.FileName;
                Stopwatch oCronometro = new Stopwatch();
                oCronometro.Start();
                exportar();
                oCronometro.Stop();
                MessageBox.Show(String.Format("Archivo Excel fué creado en {0:n0} msg",
                oCronometro.Elapsed.TotalMilliseconds));
            }
        }

        private void exportarDesdeListas()
        {
            if (File.Exists(archivoXlsx)) File.Delete(archivoXlsx);
            Excel.ExportarDeLista(obeCatPro.ListaCategoria, archivoXlsx, "Categorias");
            Excel.ExportarDeLista(obeCatPro.ListaProducto, archivoXlsx, "Productos");          
        }

        private void exportarDesdeTablas()
        {
            if (File.Exists(archivoXlsx)) File.Delete(archivoXlsx);
            Excel.ExportarDeTabla(dstCatPro.Tables[0], archivoXlsx, "Categorias");
            Excel.ExportarDeTabla(dstCatPro.Tables[1], archivoXlsx, "Productos");
        }

        private void exportarListasExcel(object sender, EventArgs e)
        {
            guardarExcel(exportarDesdeListas);
        }

        private void exportarTablasExcel(object sender, EventArgs e)
        {
            guardarExcel(exportarDesdeTablas);
        }
    }
}

Nota: Se usa la clase Stopwatch para medir el tiempo que demora en procesar cada técnica, el cual será similar ya que la demora en ambas es la primera vez que se establece conexión con Oledb.

8. Ejecutar y Probar la Aplicación Windows Forms

Grabar la aplicación y pulsar F5 para ejecutarla, se mostrará una ventana similar a la figura:

Ventana de ejecución del formulario "frmExcel"

Luego clic al primer botón "Llenar desde Listas" y se mostrará en las grillas los datos desde las listas de categorías y productos, tal como se muestra en las siguientes figuras:

Ventana con la Ficha de Categorías para Listas

Ventana con la Ficha de Productos para Listas

Se habilitará el botón de "Exportar Listas a Excel" al cual si se da click se mostrará el siguiente diálogo de guardar:

Diálogo de Guardar Excel para Listas

Escribir el nombre del archivo de Excel 2007, por ejemplo "Listas.xlsx" y "Guardar" e inmediatamente se mostrará un cuadro de diálogo con el tiempo que demoró la operación.

Nota: Como ya lo mencioné antes, la primera vez que se realiza una conexión con un origen de datos demora mas del doble, el resto de veces es más rápido, para cualquiera de los 2 orígenes de datos.

Continuando con las pruebas click al botón "Llenar desde Tablas" y se mostrará en las grillas los datos desde las tablas de categorías y productos, similar a las presentadas en las figuras de arriba.

Ventana con la Ficha de Categorías para Tablas

Se habilitará el botón de "Exportar Tablas a Excel" al cual si se da click se mostrará el siguiente diálogo de guardar:

Diálogo de Guardar Excel para Tablas

Escribir el nombre del archivo de Excel 2007, por ejemplo "Tablas.xlsx" y "Guardar" e inmediatamente se mostrará un cuadro de diálogo con el tiempo que demoró la operación.

Finalmente, pueden abrir los 2 archivos de Excel creados que contendrán ambos 2 hojas: Categorías y Productos con los datos de los orígenes.

9. Comentario Final

En este post hemos explicado detalladamente una de las técnicas que hay para crear un archivo XLSX de Excel 2007 (también hemos incluido la función para crear archivos XLS de Excel 2003) usando archivos de texto y OLEDB.

Como ya lo mencioné para datos simples como textos y números no hay muchos inconvenientes pero si queremos formatos en números, fechas y hora, usar campos memo, etc. se presentarán complicaciones que se resuelven usando un archivo de configuración (Schema.ini) el cual será motivo de otro post.

Pero otra desventaja de esta técnica es que si queremos incluir gráficos, imágenes u otros objetos, no es posible usando OLEDB, es solo para datos simples (No objetos), para lo cual mejor usamos la técnica de archivos XML comprimidos en un XLSX.

Finalmente, creo que este post les será de mucha utilidad a muchas personas que diariamente exportan a Excel listas de registros desde DataTables algunos y otros desde Listas de Objetos usando una instancia de Excel, lo cual no debe hacerse y aunque sea hay que reemplazarla por esta técnica.

10. Descarga la Aplicación Windows

domingo, 31 de julio de 2016

Entrenamiento - Capacitación a Empresas en Desarrollo Web ASP.NET MVC & JavaScript

Capacitación a Empresas en Desarrollo Web ASP.NET MVC & JavaScript

Hoy finalice mi último curso libre, porque ya no pienso dictar excepto a Empresas, pero me preguntaba porque si mi arquitectura de desarrollo web ligera y desconectada es tan buena no hay mucha demanda en el mercado y creo que la respuesta es que la mayoría de desarrolladores al no tener un punto de comparación no pueden ver las diferencias enormes en el tiempo de desarrollo de las aplicaciones ni el tiempo en ejecución de la aplicación.

Es por eso que he decidido dar una muestra gratis (sin costo) para hacer una visita a cualquier empresa que esté interesada en cambiar su esquema de trabajo actual consistente en tener muchos programadores que usan muchos Frameworks por todos lados (en el servidor y en cliente) y siempre se demoran en los proyectos y el resultado final (velocidad, seguridad, etc) deja mucho que desear y solo queda con conformarse ya que "ya se realizó la inversión" y a nadie le gusta perder y eligen que el monstruo concebido siga en producción.

La mecánica es bien simple, solo me envían un mail a Luis.duenash@gmail.com con los siguientes datos:
- Nombre de la Empresa
- Rubro
- Persona de Contacto
- Teléfono e Email del Contacto
- Fecha y Hora de la Exposición de 30 a 60 minutos con su equipo de desarrolladores
- Dirección del lugar de la Exposición

Si están convencidos de los resultados de la metodología, la arquitectura y las técnicas se programa la capacitación, sino no hay ningún compromiso.

En términos monetarios para un Gerente o Jefe, si se les capacita a los programadores para hacer el trabajo más eficiente y eficaz con pocos recursos en el menor tiempo, estas ganando mucho dinero y el costo (inversión) es mínimo comparado con lo que se van a ahorrar.

Uno de los valores agregados que doy a las empresas que me eligen para capacitarlos es que consigo (sin ningún costo) a desarrolladores que conocen mi metodología y que resultan ser los mejores en cada lugar donde se ubiquen.

El Libro del Día: C# 24-Hour Trainer

El Libro del Día: 2016-07-31

Titulo: C# 24-Hour Trainer (2nd Edition)
Autor: Rod Stephens
Editorial: Wrox
Nro Paginas: 597

Capítulos:
SECTION I THE VISUAL STUDIO IDE AND CONTROLS
LESSON 1 Getting Started with the Visual Studio IDE
LESSON 2 Creating Controls
LESSON 3 Making Controls Arrange Themselves
LESSON 4 Handling Events
LESSON 5 Making Menus
LESSON 6 Making Tool Strips and Status Strips
LESSON 7 Using RichTextBoxes
LESSON 8 Using Standard Dialogs
LESSON 9 Creating and Displaying New Forms
LESSON 10 Building Custom Dialogs
SECTION II VARIABLES AND CALCULATIONS
LESSON 11 Using Variables and Performing Calculations
LESSON 12 Debugging Code
LESSON 13 Understanding Scope
LESSON 14 Working with Strings
LESSON 15 Working with Dates and Times
LESSON 16 Using Arrays and Collections
LESSON 17 Using Enumerations and Structures
SECTION III PROGRAM STATEMENTS
LESSON 18 Making Choices
LESSON 19 Repeating Program Steps
LESSON 20 Reusing Code with Methods
LESSON 21 Handling Errors
LESSON 22 Preventing Bugs
SECTION IV CLASSES
LESSON 23 Defining Classes
LESSON 24 Initializing Objects
LESSON 25 Fine-Tuning Classes
LESSON 26 Overloading Operators
LESSON 27 Using Interfaces
LESSON 28 Making Generic Classes
SECTION V SYSTEM INTERACTIONST
LESSON 29 Using Files
LESSON 30 Printing
SECTION VI WINDOWS APPS
LESSON 31 Windows Store Apps
LESSON 32 Windows Phone Apps
SECTION VII SPECIALIZED TOPICS
LESSON 33 Localizing Programs
LESSON 34 Programming Databases, Part 1
LESSON 35 Programming Databases, Part 2
LESSON 36 LINQ to Objects
LESSON 37 LINQ to SQL

Descarga:
C#_24_Hour_Trainer

Entrenamiento - Fin del Taller de ASP.NET MVC & JavaScript

Fin del Taller de ASP.NET MVC & JavaScript

Este post es para agradecer a los participantes de mi último taller de ASP.NET MVC & JavaScript de los Domingos. Como no hay certificados, la mejor constancia que han culminado el entrenamiento en técnicas desconectadas usando JavaScript nativo es publicar sus nombres para que las Empresas conozcan al grupo de personas que está preparada con una visión diferente del desarrollo.

Gracias a todos ustedes por compartir momentos educativos cada fin de semana. La lista de participantes por orden alfabético es la siguiente:

01 Aranda Rosales, Jaime Jesús
02 Beteta, Antonio
03 Cabrera Otoya, Jimmy
04 Chávez Córdova, Billy Herbert
05 Ciudad, Brayan
06 Condor Castillo, Edgar
07 Gaspar Chumpitaz, Oscar Michael
08 Huamaní García, Eduardo Felipe
09 Llontop Caballero, Jhony Frank
10 Marquez Redhead, Jorge Manuel
11 Miraya Anamaría, Edgar
12 Moreno Gomez, Juan Carlos
13 Palacios, Mario
14 Paredes Urbano, Gary W.
15 Palomino Oliva, Alan Francesco
16 Rengifo Ocrospoma, Joseph
17 Reyes Espinoza, Ray
18 Reyes, Alex
19 Rivera Molina, Pool
20 Saavedra Mejia, Miguel
21 Schwarz Moreno, Edward
22 Silva, Madeleyne
23 Tasayco Trigozo, José
24 Tito Fernandez, Erick
25 Vallejo Aguilar, Fernando
26 Vera Morocho, Edinson
27 Zambrano Pérez, Rolando José

Suerte a todos ustedes y éxito para salir a conquistar el mercado que están muy bien preparados, quizás en un nivel que todavía tomará tiempo que otros exploren.