miércoles, 17 de agosto de 2016

El Libro del Día: Modern JavaScript Applications

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

Titulo: Modern JavaScript Applications
Autor: Narayan Prusty
Editorial: Packt
Nro Paginas: 330

Capítulos:
Chapter 1: Breaking into Microservices Architecture
Chapter 2: Building a Coupon Site
Chapter 3: Communication between Browsers in Real Time
Chapter 4: Building a Chatroulette
Chapter 5: Bidirectional Communication in Real Time
Chapter 6: Building a Live Score Site
Chapter 7: Functional Reactive Programming
Chapter 8: Building an Advanced Profile Search Widget
Chapter 9: New Features of Bootstrap 4
Chapter 10: Building User Interfaces Using React
Chapter 11: Building an RSS Reader Using React and Flux
Chapter 12: New Features of Angular 2
Chapter 13: Building a Search Engine Template Using AngularJS 2
Chapter 14: Securing and Scaling Node.js Applications

Descarga:
Modern_JavaScript_Applications

jueves, 11 de agosto de 2016

El Libro del Día: AngularJS in Action

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

Titulo: AngularJS in Action
Autor: Lukas Ruebbelke
Editorial: Manning
Nro Paginas: 191

Capítulos:
PART 1 GET ACQUAINTED WITH ANGULARJS
1 Hello AngularJS
2 Structuring your AngularJS application
PART 2 MAKE SOMETHING WITH ANGULARJS
3 Views and controllers
4 Models and services
5 Directives
6 Animations
7 Structuring your site with routes
8 Forms and validations
APPENIDXES
A Setting up Karma
B Setting up a Node.js server
C Setting up a Firebase server
D Running the app

Descarga:
AngularJS_in_Action

miércoles, 10 de agosto de 2016

Entrenamiento - Ultima Semana de Charla Gratuita a Empresas

Ultima Semana de Charla Gratuita a Empresas

Solo hasta este Viernes 12 de Agosto estaré recibiendo correos para coordinar la charla gratuita de muestra a Empresas para Capacitación en ASP.NET MVC & JavaScript.

La charla dura 1.5 horas y tiene la siguiente agenda:

Título: "Desarrollo de Software Ligero y Desconectado"
1. Acerca del Instructor
  1.1. Estudios
  1.2. Experiencia Laboral
  1.3. Aportes
2. Desarrollo de Software
  2.1. Etapas del Desarrollo de Software
  2.2. Tipos de Aplicaciones
  2.3. Frameworks de Programación
3. Necesidad de una Nueva Arquitectura
  3.1. Problemas diarios en Sistemas
  3.2. Causas de los Problemas
  3.3. Solución de los Problemas
4. Introducción al Desarrollo Web
  4.1. Componentes de un Sitio Web
  4.2. El Problema de la Performance de las Páginas
  4.3. Principales Reglas de Performance
  4.4. Arquitecturas de Desarrollo Web
5. Desarrollo Web en ASP.NET
  5.1. Programando en el Servidor con C# (.NET)
  5.2. Programando en el Cliente con las APIs de JavaScript
6. Utilitarios, Aplicaciones y Demos
  6.1. Utilitarios de Lduenas
  6.2. Aplicaciones Web en Producción
  6.3. Demos de Clases y Capacitaciones
7. Preguntas y Respuestas

Los interesados envíar 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 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.

Las capacitaciones son 6 horas semanales y solo me queda un horario disponible: Lunes y Miércoles a partir de las 5:00 pm.

Gracias a todos por el interés.

martes, 9 de agosto de 2016

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

Exportar a Excel 2007 desde Listas y Tablas usando XML

1. Introducción

En el post anterior vimos las 3 técnicas que hay para crear un archivo de Excel 2007 exportando datos desde varias listas de objetos o varias tablas de un DataSet en .NET. En ese post se presentó un Demo de cómo usar OLEDB para crear el archivo Excel.

En este post vamos a ver algo inédito, que no hay en la web, que es como crear un archivo de Excel 2007, creando los archivos XML necesarios y luego comprimiendolo en un xlsx.

2. Ventajas de Crear un Archivo Excel usando XML

Existen muchas ventajas de usar esta técnica entre las 3 mas importantes tenemos:

- Es la más rápida en la creación de archivos Excel, casi 3 veces más rápida que OLEDB y mas de 10 veces más rápida que abrir una instancia de Excel (Automatización COM).

- No necesita tener instalado ni los Componentes de Acceso a Datos del "Microsoft Access Database Engine 2010 Redistributable" ni tampoco una instancia de Excel para crear el archivo.

Nota: Ni siquiera se necesita tener instalado el Excel para leer o ver el archivo ya que se puede hacer usando los Visores de los Demos pasados.

- Se puede crear no solo celdas con datos sino gráficos, dar estilo, formatos, etc, cosa que no se puede al usar OLEDB.

Nota: Si se puede abriendo una instancia de Excel pero se demora demasiado y consume muchos recursos, lo cual está terminantemente prohibido para Aplicaciones Web ASP.NET.

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

Abrir Visual Studio y crear una aplicación Windows Forms en C# llamada "Excel_Crear_XML", 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_XML
{
    public class beCategoria
    {
        public int IdCategoria { get; set; }
        public string Nombre { get; set; }
    }
}

Archivo de Clase: beProducto.cs

namespace Excel_Crear_XML
{
    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_XML
{
    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_XML
{
    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 XML y Comprimirlos

La tercera parte a codificar es crear una clase que permita crear los diferentes archivos XML necesitados y luego comprimirlos en un archivo XLSX.

Archivo de Clase: Excel.cs

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

namespace Excel_Crear_XML
{
    public class Excel
    {
        private enum TipoOrigen {
            Listas = 0,
            Tablas =1
        }
        private static string sArchivoXlsx;
        private static string[] sHojas;
        private static string[] sRango;
        private static int nHojas;
        private static TipoOrigen tipoOrigen;
        private static List<dynamic> data;

        public static void ExportarDeLista<T>(string archivoXlsx, string[] hojas, T objData)
        {
            data = new List<dynamic>();
            tipoOrigen = TipoOrigen.Listas;
            sArchivoXlsx = archivoXlsx;
            sHojas = hojas;
            nHojas = hojas.Length;
            sRango = new string[nHojas];
            PropertyInfo[] listas = objData.GetType().GetProperties();
            dynamic lista;
            PropertyInfo[] campos;
            for (int i = 0; i < listas.Length;i++)
            {
                lista = listas[i].GetValue(objData, null);
                data.Add(lista);
                campos = lista[0].GetType().GetProperties();
                sRango[i] = String.Format("${0}${1}", (char)(64 + campos.Length), lista.Count + 1);
            }
            crearDirectoriosArchivos();
        }

        public static void ExportarDeTabla(string archivoXlsx, string[] hojas, DataSet objData)
        {
            data = new List<dynamic>();
            tipoOrigen = TipoOrigen.Tablas;
            sArchivoXlsx = archivoXlsx;
            sHojas = hojas;
            nHojas = hojas.Length;
            sRango = new string[nHojas];
            DataTable tabla;
            for (int i = 0; i < objData.Tables.Count; i++)
            {
                tabla = objData.Tables[i];
                data.Add(tabla);
                sRango[i] = String.Format("${0}${1}",
                (char)(64 + tabla.Columns.Count), tabla.Rows.Count + 1);
            }
            crearDirectoriosArchivos();
        }

        private static void crearDirectoriosArchivos()
        {
            //Definir la ruta de los directorios a crear
            string sDirectorioRaiz = Path.Combine(Path.GetDirectoryName(sArchivoXlsx),
                Path.GetFileNameWithoutExtension(sArchivoXlsx));
            string sDirectorioRels = Path.Combine(sDirectorioRaiz, "_rels");
            string sDirectorioDocProps = Path.Combine(sDirectorioRaiz, "docProps");
            string sDirectorioXl = Path.Combine(sDirectorioRaiz, "xl");
            string sDirectorioXlRels = Path.Combine(sDirectorioXl, "_rels");
            string sDirectorioXlTheme = Path.Combine(sDirectorioXl, "theme");
            string sDirectorioXlWorksheets = Path.Combine(sDirectorioXl, "worksheets");

            //Definir la ruta de los archivos a crear
            string sArchivoContentTypes = Path.Combine(sDirectorioRaiz, "[Content_Types].xml");
            string sArchivoRels = Path.Combine(sDirectorioRels, ".rels");
            string sArchivoDocApp = Path.Combine(sDirectorioDocProps, "app.xml");
            string sArchivoDocCore = Path.Combine(sDirectorioDocProps, "core.xml");
            string sArchivoXlStyles = Path.Combine(sDirectorioXl, "styles.xml");
            string sArchivoXlWorkbook = Path.Combine(sDirectorioXl, "workbook.xml");
            string sArchivoXlRels = Path.Combine(sDirectorioXlRels, "workbook.xml.rels");
            string sArchivoXlTheme = Path.Combine(sDirectorioXlTheme, "theme1.xml");
            string[] sArchivoXlSheets = new string[nHojas];
            for (var i = 0; i < nHojas;i++) sArchivoXlSheets[i] =
                Path.Combine(sDirectorioXlWorksheets, String.Format("sheet{0}.xml",i+1));
         
            //Crear los Directorios definidos
            DirectoryInfo oDirectorioRaiz = Directory.CreateDirectory(sDirectorioRaiz);
            oDirectorioRaiz.CreateSubdirectory("_rels");
            oDirectorioRaiz.CreateSubdirectory("docProps");
            DirectoryInfo oDirectorioXl = oDirectorioRaiz.CreateSubdirectory("xl");
            oDirectorioXl.CreateSubdirectory("_rels");
            oDirectorioXl.CreateSubdirectory("theme");
            oDirectorioXl.CreateSubdirectory("worksheets");

            //Crear los Archivos definidos
            File.WriteAllText(sArchivoContentTypes, getContentTypes());
            File.WriteAllText(sArchivoRels, getRels());
            File.WriteAllText(sArchivoDocApp, getApp());
            File.WriteAllText(sArchivoDocCore, getCore());
            File.WriteAllText(sArchivoXlStyles, getXlStyles());
            File.WriteAllText(sArchivoXlWorkbook, getXlWorkbook());
            File.WriteAllText(sArchivoXlRels, getXlRels());
            File.WriteAllText(sArchivoXlTheme, getXlTheme());
            for (var i = 0; i < nHojas; i++) File.WriteAllText(sArchivoXlSheets[i], getXlSheet(i));

            //Comprimir los archivos en un Xlsx
            ZipFile.CreateFromDirectory(sDirectorioRaiz, sArchivoXlsx);
            //Borrar todo el directorio con los archivos temporales creados
            Directory.Delete(sDirectorioRaiz, true);
        }

        private static string getContentTypes()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
            sb.Append("<Types xmlns=\"http://schemas.openxmlformats.org/
            package/2006/content-types\">");
            sb.Append("<Default Extension=\"rels\" ContentType=
            \"application/vnd.openxmlformats-package.relationships+xml\"/>");
            //sb.Append("<Default Extension=\"wmf\" ContentType=\"image/x-wmf\"/>");
            sb.Append("<Default Extension=\"xml\" ContentType=\"application/xml\"/>");
            sb.Append("<Override PartName=\"/xl/workbook.xml\" ContentType=
            \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>");
            sb.Append("<Override PartName=\"/xl/styles.xml\" ContentType=
            \"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/>");
            sb.Append("<Override PartName=\"/xl/theme/theme1.xml\" ContentType=
            \"application/vnd.openxmlformats-officedocument.theme+xml\"/>");
            sb.Append("<Override PartName=\"/docProps/core.xml\" ContentType=
            \"application/vnd.openxmlformats-package.core-properties+xml\"/>");
            sb.Append("<Override PartName=\"/docProps/app.xml\" ContentType=
            \"application/vnd.openxmlformats-officedocument.extended-properties+xml\"/>");
            for (var i = 0; i < nHojas; i++)
            {
                sb.Append("<Override PartName=\"/xl/worksheets/sheet");
                sb.Append(i + 1);
                sb.Append(".xml\" ContentType=\"application/vnd.openxmlformats-officedocument.
                spreadsheetml.worksheet+xml\"/>");
            }
            sb.Append("</Types>");
            return sb.ToString();
        }

        private static string getRels()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
            sb.Append("<Relationships xmlns=\"http://schemas.openxmlformats.org/
            package/2006/relationships\">");
            sb.Append("<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/
            package/2006/relationships/metadata/core-properties\" Target=\"docProps/core.xml\"/>");
            //sb.Append("<Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/
            package/2006/relationships/metadata/thumbnail\" Target=\"docProps/thumbnail.wmf\"/>");
            sb.Append("<Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/
            officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>");
            sb.Append("<Relationship Id=\"rId3\" Type=\"http://schemas.openxmlformats.org/
            officeDocument/2006/relationships/extended-properties\"
            Target=\"docProps/app.xml\"/>");
            sb.Append("</Relationships>");
            return sb.ToString();
        }

        private static string getApp()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
            sb.Append("<Properties xmlns=\"http://schemas.openxmlformats.org/
            officeDocument/2006/extended-properties\"
            xmlns:vt=\"http://schemas.openxmlformats.org/
            officeDocument/2006/docPropsVTypes\">");
            sb.Append("<Application>Microsoft Access</Application>");
            sb.Append("<DocSecurity>0</DocSecurity>");
            sb.Append("<ScaleCrop>false</ScaleCrop>");
            sb.Append("<HeadingPairs>");
            sb.Append("<vt:vector size=\"2\" baseType=\"variant\">");
            sb.Append("<vt:variant><vt:lpstr>Worksheets</vt:lpstr></vt:variant>");
            sb.Append("<vt:variant><vt:i4>1</vt:i4></vt:variant>");
            sb.Append("</vt:vector>");
            sb.Append("</HeadingPairs>");
            sb.Append("<TitlesOfParts>");
            sb.Append("<vt:vector size=\"1\" baseType=\"lpstr\">");
            sb.Append("<vt:lpstr>A266FF2A662E84b639DA</vt:lpstr>");
            sb.Append("</vt:vector>");
            sb.Append("</TitlesOfParts>");
            sb.Append("<Company>Microsoft</Company>");
            sb.Append("<LinksUpToDate>false</LinksUpToDate>");
            sb.Append("<SharedDoc>false</SharedDoc>");
            sb.Append("<HyperlinksChanged>false</HyperlinksChanged>");
            sb.Append("<AppVersion>12.0000</AppVersion>");
            sb.Append("</Properties>");
            return sb.ToString();
        }

        private static string getCore()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
            sb.Append("<cp:coreProperties ");
            sb.Append("xmlns:cp=\"http://schemas.openxmlformats.org/package/2006/metadata/
            core-properties\" ");
            sb.Append("xmlns:dc=\"http://purl.org/dc/elements/1.1/\" ");
            sb.Append("xmlns:dcterms=\"http://purl.org/dc/terms/\" ");
            sb.Append("xmlns:dcmitype=\"http://purl.org/dc/dcmitype/\" ");
            sb.Append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">");
            sb.Append("<dc:creator>");
            sb.Append(Environment.UserName);
            sb.Append("</dc:creator>");
            sb.Append("<cp:lastModifiedBy>");
            sb.Append(Environment.UserName);
            sb.Append("</cp:lastModifiedBy>");
            sb.Append("<dcterms:created xsi:type=\"dcterms:W3CDTF\">");
            sb.Append(DateTime.Now.ToString("s"));
            sb.Append("Z</dcterms:created>");
            sb.Append("<dcterms:modified xsi:type=\"dcterms:W3CDTF\">");
            sb.Append(DateTime.Now.ToString("s"));
            sb.Append("Z</dcterms:modified>");
            sb.Append("</cp:coreProperties>");          
            return sb.ToString();
        }

        private static string getXlStyles()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<styleSheet xmlns=\"http://schemas.openxmlformats.org/
            spreadsheetml/2006/main\">");
            sb.Append("<fonts count=\"1\">");
            sb.Append("<font>");
            sb.Append("<sz val=\"11\"/>");
            sb.Append("<color theme=\"1\"/>");
            sb.Append("<name val=\"MS Sans Serif\"/>");
            sb.Append("<family val=\"2\"/>");
            sb.Append("<scheme val=\"minor\"/>");
            sb.Append("</font>");
            sb.Append("</fonts>");
            sb.Append("<fills count=\"2\">");
            sb.Append("<fill><patternFill patternType=\"none\"/></fill>");
            sb.Append("<fill><patternFill patternType=\"gray125\"/></fill>");
            sb.Append("</fills>");
            sb.Append("<borders count=\"1\">");
            sb.Append("<border><left/><right/><top/><bottom/><diagonal/></border>");
            sb.Append("</borders>");
            sb.Append("<cellStyleXfs count=\"1\">");
            sb.Append("<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/>");
            sb.Append("</cellStyleXfs>");
            sb.Append("<cellXfs count=\"1\">");
            sb.Append("<xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>");
            sb.Append("</cellXfs>");
            sb.Append("<cellStyles count=\"1\">");
            sb.Append("<cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\"/>");
            sb.Append("</cellStyles>");
            sb.Append("<dxfs count=\"0\"/>");
            sb.Append("<tableStyles count=\"0\" defaultTableStyle=\"TableStyleMedium9\"
            defaultPivotStyle=\"PivotStyleLight16\"/>");
            sb.Append("</styleSheet>");
            return sb.ToString();
        }

        private static string getXlWorkbook()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<workbook xmlns=\"http://schemas.openxmlformats.org/
            spreadsheetml/2006/main\" ");
            sb.Append("xmlns:r=\"http://schemas.openxmlformats.org/
            officeDocument/2006/relationships\">");
            sb.Append("<fileVersion appName=\"xl\" lastEdited=\"4\" lowestEdited=\"4\"
            rupBuild=\"4505\"/>");
            sb.Append("<workbookPr defaultThemeVersion=\"124226\"/>");
            sb.Append("<bookViews>");
            sb.Append("<workbookView xWindow=\"120\" yWindow=\"90\"
            windowWidth=\"23895\" windowHeight=\"14535\"/>");
            sb.Append("</bookViews>");
            sb.Append("<sheets>");
            for (var i = 0; i < nHojas; i++)
            {
                sb.Append("<sheet sheetId=\"");
                sb.Append(i + 1);
                sb.Append("\" r:id=\"rId");
                sb.Append(i + 3);
                sb.Append("\" name=\"");
                sb.Append(sHojas[i]);
                sb.Append("\"/>");
            }
            sb.Append("</sheets>");
            sb.Append("<definedNames>");
            for (var i = 0; i < nHojas; i++)
            {
                sb.Append("<definedName name=\"");
                sb.Append(sHojas[i]);
                sb.Append("\">'");
                sb.Append(sHojas[i]);
                sb.Append("'!$A$1:");
                sb.Append(sRango[i]);
                sb.Append("</definedName>");
            }
            sb.Append("</definedNames>");
            sb.Append("<calcPr calcId=\"125725\" fullCalcOnLoad=\"true\"/>");
            sb.Append("</workbook>");
            return sb.ToString();
        }

        private static string getXlRels()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
            sb.Append("<Relationships xmlns=\"http://schemas.openxmlformats.org/
            package/2006/relationships\">");
            sb.Append("<Relationship Id=\"rId1\" ");
            sb.Append("Type=\"http://schemas.openxmlformats.org/
            officeDocument/2006/relationships/styles\" ");
            sb.Append("Target=\"styles.xml\"/>");
            sb.Append("<Relationship Id=\"rId2\" ");
            sb.Append("Type=\"http://schemas.openxmlformats.org/
            officeDocument/2006/relationships/theme\" ");
            sb.Append("Target=\"theme/theme1.xml\"/>");
            for (var i = 0; i < nHojas; i++)
            {
                sb.Append("<Relationship Id=\"rId");
                sb.Append(i + 3);
                sb.Append("\" ");
                sb.Append("Type=\"http://schemas.openxmlformats.org/
                officeDocument/2006/relationships/worksheet\" ");
                sb.Append("Target=\"worksheets/sheet");
                sb.Append(i + 1);
                sb.Append(".xml\"/>");
            }
            sb.Append("</Relationships>");
            return sb.ToString();
        }

        private static string getXlTheme()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
            sb.Append("<a:theme xmlns:a=\"http://schemas.openxmlformats.org/
            drawingml/2006/main\" name=\"Office Theme\">");
            sb.Append("<a:themeElements>");
            sb.Append("<a:clrScheme name=\"Office\">");
            sb.Append("<a:dk1><a:sysClr val=\"windowText\" lastClr=\"000000\"/></a:dk1>");
            sb.Append("<a:lt1><a:sysClr val=\"window\" lastClr=\"FFFFFF\"/></a:lt1>");
            sb.Append("<a:dk2><a:srgbClr val=\"1F497D\"/></a:dk2>");
            sb.Append("<a:lt2><a:srgbClr val=\"EEECE1\"/></a:lt2>");
            sb.Append("<a:accent1><a:srgbClr val=\"4F81BD\"/></a:accent1>");
            sb.Append("</a:themeElements>");
            sb.Append("<a:objectDefaults/>");
            sb.Append("<a:extraClrSchemeLst/>");
            sb.Append("</a:theme>");
            return sb.ToString();
        }

        private static string getXlSheet(int nHoja)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<worksheet xmlns=\"http://schemas.openxmlformats.org/
            spreadsheetml/2006/main\" ");
            sb.Append("xmlns:r=\"http://schemas.openxmlformats.org/          
            officeDocument/2006/relationships\">");
            sb.Append("<dimension ref=\"A1:");
            sb.Append(sRango[nHoja]);
            sb.Append("\"/>");
            sb.Append("<sheetViews>");
            sb.Append("<sheetView tabSelected=\"1\" workbookViewId=\"0\" rightToLeft=\"false\">");
            sb.Append("<selection activeCell=\"A1\" sqref=\"A1\"/>");
            sb.Append("</sheetView>");
            sb.Append("</sheetViews>");
            sb.Append("<sheetFormatPr defaultRowHeight=\"15\"/>");
            sb.Append("<sheetData>");
            if(tipoOrigen.Equals(TipoOrigen.Listas)) sb.Append(getSheetList(nHoja));
            else sb.Append(getSheetTable(nHoja));
            sb.Append("</sheetData>");
            sb.Append("<pageMargins left=\"0.7\" right=\"0.7\" top=\"0.75\"
            bottom=\"0.75\" header=\"0.3\" footer=\"0.3\"/>");
            sb.Append("</worksheet>");
            return sb.ToString();
        }

        private static string getSheetList(int nHoja)
        {
            StringBuilder sb = new StringBuilder();
            var lista = data[nHoja];
            PropertyInfo[] campos = lista[0].GetType().GetProperties();
            sb.Append("<row outlineLevel=\"0\" r=\"1\">");
            string celda;
            string valor;
            string tipo;
            for (int j = 0; j < campos.Length; j++)
            {
                celda = String.Format("{0}1", (char)(65 + j));
                valor = campos[j].Name;
                sb.Append("<c r=\"");
                sb.Append(celda);
                sb.Append("\" s=\"0\" t=\"inlineStr\"><is><t>");
                sb.Append(valor);
                sb.Append("</t></is></c>");
            }
            sb.Append("</row>");
            for (int i = 0; i < lista.Count; i++)
            {
                sb.Append("<row outlineLevel=\"0\" r=\"");
                sb.Append(i + 2);
                sb.Append("\">");
                for (int j = 0; j < campos.Length; j++)
                {
                    celda = String.Format("{0}{1}", (char)(65 + j),i+2);
                    valor = lista[i].GetType().GetProperty(campos[j].Name).
                    GetValue(lista[i], null).ToString();
                    tipo = lista[i].GetType().GetProperty(campos[j].Name).PropertyType.ToString();
                    sb.Append("<c r=\"");
                    sb.Append(celda);
                    sb.Append("\" s=\"0\"");
                    if (tipo.Contains("String"))
                    {                      
                        sb.Append(" t=\"inlineStr\"><is><t>");
                        sb.Append(valor);
                        sb.Append("</t></is>");
                    }
                    else
                    {
                        sb.Append("><v>");
                        sb.Append(valor);
                        sb.Append("</v>");
                    }
                    sb.Append("</c>");
                }
                sb.Append("</row>");
            }          
            return sb.ToString();
        }

        private static string getSheetTable(int nHoja)
        {
            StringBuilder sb = new StringBuilder();
            var tabla = data[nHoja];
            DataColumnCollection campos = tabla.Columns;
            sb.Append("<row outlineLevel=\"0\" r=\"1\">");
            string celda;
            string valor;
            string tipo;
            for (int j = 0; j < campos.Count ; j++)
            {
                celda = String.Format("{0}1", (char)(65 + j));
                valor = campos[j].ColumnName;
                sb.Append("<c r=\"");
                sb.Append(celda);
                sb.Append("\" s=\"0\" t=\"inlineStr\"><is><t>");
                sb.Append(valor);
                sb.Append("</t></is></c>");
            }
            sb.Append("</row>");
            for (int i = 0; i < tabla.Rows.Count; i++)
            {
                sb.Append("<row outlineLevel=\"0\" r=\"");
                sb.Append(i + 2);
                sb.Append("\">");
                for (int j = 0; j < campos.Count; j++)
                {
                    celda = String.Format("{0}{1}", (char)(65 + j), i + 2);
                    valor = tabla.Rows[i][j].ToString();
                    tipo = campos[j].DataType.ToString();
                    sb.Append("<c r=\"");
                    sb.Append(celda);
                    sb.Append("\" s=\"0\"");
                    if (tipo.Contains("String"))
                    {
                        sb.Append(" t=\"inlineStr\"><is><t>");
                        sb.Append(valor);
                        sb.Append("</t></is>");
                    }
                    else
                    {
                        sb.Append("><v>");
                        sb.Append(valor);
                        sb.Append("</v>");
                    }
                    sb.Append("</c>");
                }
                sb.Append("</row>");
            }
            return sb.ToString();
        }
    }
}

7. Explicación Resumida de la Clase Excel

Para cada origen de datos se ha creado un método: "ExportarDeLista" que trabaja con Reflection para extraer los datos de las listas y "ExportarDeTabla" que trabaja con DataTable para extraer los datos de las tablas.

Ambos métodos llaman a una función común y principal llamada "crearDirectoriosArchivos" que primero define las rutas de los directorios y archivos a crear y luego crea los directorios y archivos definidos.

La función "crearDirectoriosArchivos" llama a diferentes funciones una para crear cada archivo XML y para llenar la data de las listas se usa la función "getSheetList" y para llenar la data de las tablas se usa la función "getSheetTable".

Finalmente se comprime los archivos en un solo archivo XLSX y se borra todos los directorios y archivos XML creados temporalmente.

8. 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_XML
{
    public partial class frmExcel : Form
    {
        private beCategoriaProducto obeCatPro;
        private DataSet dstCatPro;
        private string archivoXlsx;
        private string[] hojas;

        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;
                hojas = new string[]{"Categorias", "Productos"};
                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()
        {
            Excel.ExportarDeLista(archivoXlsx, hojas, obeCatPro);
        }

        private void exportarDesdeTablas()
        {
            Excel.ExportarDeTabla(archivoXlsx, hojas, dstCatPro);
        }

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

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

9. 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 "ListasXML.xlsx" y "Guardar" e inmediatamente se mostrará un cuadro de diálogo con el tiempo que demoró la operación.

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 "TablasXML.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.

10. Comentario Final

Personalmente considero este post como uno de mis favoritos ya que no hay información en Internet sobre cómo crear un archivo de Excel 2007 en forma nativa, es decir creando los archivos XML necesarios para luego comprimirlos en un solo archivo XLSX.

Esta técnica es muy rápida, no necesita de instalar nada, y puede crear archivos de Excel con todo tipo de objetos como gráficos, formas, estilos, formatos, etc. Es la mejor forma para exportar datos sobre todo en la Web ya que también se puede hacer por JavaScript nativo como lo veremos en otro post.

Espero que este post ayude a muchas programadores a entender como es la estructura de un archivo Excel y poder crearlo sin necesidad de usar librerías, ya que según mi opinión solo volviendo a "Crear la Rueda" se puede construir una mejor. Los que usen el refrán "Para que Inventar la Rueda" es porque "NO saben como crearla".

Este Blog nació con ese fin, demostrar que con un poco de ingenio y mucha investigación se puede hacer "cualquier cosa". Finalmente, los quiero dejar con otra reflexión: "Fácil es hacer Complejo lo Simple", pero "Difícil es hacer Simple lo Complejo".

Cuando uno aprende hacer lo Complejo Simple estará en condiciones de resolver cualquier problema en corto tiempo y no esperar a que otro lo haga por ti (Frameworks y Librerías) que éste se hace mas fuerte y tu dependiente de él. Además que te pierdes de lo más interesante.

11. Descarga la Aplicación Windows

2016_08_09_Demo_Excel_Crear_XML

El Libro del Día: Reliable JavaScript

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

Titulo: Reliable JavaScript
Autor: Lawrence D. Spencer, Seth H. Richards
Editorial: Wrox
Nro Paginas: 530

Capítulos:
Part I: Laying a Solid Foundation
Chapter 1 Practicing Skillful Software Engineering
Chapter 2 Tooling Up
Chapter 3 Constructing Reliable Objects
Part II: Testing Pattern-Based Code
Chapter 4 Reviewing the Benefits of Patterns
Chapter 5 Ensuring Correct Use of the Callback Pattern
Chapter 6 Ensuring Correct Use of the Promise Pattern
Chapter 7 Ensuring Correct Use of Partial Function Application
Chapter 8 Ensuring Correct Use of the Memoization Pattern
Chapter 9 Ensuring Correct Implementation of the Singleton Pattern
Chapter 10 Ensuring Correct Implementation of the Factory Pattern
Chapter 11 Ensuring Correct Implementation and Use of the Sandbox Pattern
Chapter 12 Ensuring Correct Implementation of the Decorator Pattern
Chapter 13 Ensuring Correct Implementation of the Strategy Pattern
Chapter 14 Ensuring Correct Implementation of the Proxy Pattern
Chapter 15 Ensuring Correct Implementation of Chainable Methods
Part III: Testing and Writing with Advanced JavaScript Features
Chapter 16 Conforming to Interfaces in an Interface-Free Language
Chapter 17 Ensuring Correct Argument Types
Chapter 18 Ensuring Correct Use of call, apply, and bind
Chapter 19 Ensuring Correct Use of Method Borrowing
Chapter 20 Ensuring Correct Use of Mixins
Chapter 21 Testing Advanced Program Architectures
Part IV: Special Subjects in Testing
Chapter 22 Testing DOM Access
Chapter 23 Ensuring Conformance to Standards
Part V: Summary
Chapter 24 Summary of the Principles of Test-Driven Development
Chapter 25 Summary of JavaScript Idioms in This Book

Descarga:
Reliable_JavaScript

lunes, 8 de agosto de 2016

El Libro del Día: Professional AngularJS

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

Titulo: Professional AngularJS
Autor: Valeri Karpov, Diego Netto
Editorial: Wrox
Nro Paginas: 399

Capítulos:
CHAPTER 1 Building a Simple AngularJS Application
CHAPTER 2 Intelligent Workflow and Build Tools
CHAPTER 3 Architecture
CHAPTER 4 Data Binding
CHAPTER 5 Directives
CHAPTER 6 Templates, Location, and Routing
CHAPTER 7 Services, Factories, and Providers
CHAPTER 8 Server Communication
CHAPTER 9 Testing and Debugging AngularJS Applications
CHAPTER 10 Moving On
APPENDIX Resources

Descarga:
Professional_AngularJS

domingo, 7 de agosto de 2016

El Libro del Día: Programming WCF Services

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

Titulo: Programming WCF Services (4th Edition)
Autor: Juval Lowy, Michael Montgomery
Editorial: O'Reilly
Nro Paginas: 1017

Capítulos:
1. WCF Essentials
2. Service Contracts
3. Data Contracts
4. Instance Management
5. Operations
6. Faults
7. Transactions
8. Concurrency Management
9. Queued Services
10. Security
11. The Azure Service Fabric
A. Introduction to Service Orientation
B. Headers and Contexts
C. Discovery
D. Publish-Subscribe Service
E. Generic Interceptor
F. WCF Coding Standard
G. ServiceModelEx Catalog

Descarga:
Programming_WCF_Services

sábado, 6 de agosto de 2016

El Libro del Día: Beginning Visual Basic 2015

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

Titulo: Beginning Visual Basic 2015
Autor: Bryan Newsome
Editorial: Wrox
Nro Paginas: 621

Capítulos:
Chapter 1 Welcome to Visual Basic 2015
Chapter 2 The Microsoft .NET Framework
Chapter 3 Writing Software
Chapter 4 Controlling the Flow
Chapter 5 Working with Data Structures
Chapter 6 Building Windows Applications
Chapter 7 Displaying Dialogs
Chapter 8 Creating Menus
Chapter 9 Debugging and Error Handling
Chapter 10 Building Objects
Chapter 11 Advanced Object-Oriented Techniques
Chapter 12 Accessing Data Using Structured Query Language
Chapter 13 Database Programming with SQL Server and ADO.NET
Chapter 14 ASP.NET
Chapter 15 Deploying Your Application
Chapter 16 Windows 8 Apps
Appendix Exercise Solutions

Descarga:
Beginning_Visual_Basic_2015

viernes, 5 de agosto de 2016

El Libro del Día: Beginning ASP.NET for Visual Studio 2015

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

Titulo: Beginning ASP.NET for Visual Studio 2015
Autor: William Penberthy
Editorial: Wrox
Nro Paginas: 793

Capítulos:
CHAPTER 1 Getting Started with ASP.NET 6.0
CHAPTER 2 Building an Initial ASP.NET Application
CHAPTER 3 Designing Your Web Pages
CHAPTER 4 Programming in C# and VB.NET
CHAPTER 5 ASP.NET Web Form Server Controls
CHAPTER 6 ASP.NET MVC Helpers and Extensions
CHAPTER 7 Creating Consistent-Looking Websites
CHAPTER 8 Navigation
CHAPTER 9 Displaying and Updating Data
CHAPTER 10 Working with Data—Advanced Topics
CHAPTER 11 User Controls and Partial Views
CHAPTER 12 Validating User Input
CHAPTER 13 ASP.NET AJAX
CHAPTER 14 jQuery
CHAPTER 15 Security in Your ASP.NET Website
CHAPTER 16 Personalizing Websites
CHAPTER 17 Exception Handling, Debugging, and Tracing
CHAPTER 18 Working with Source Control
CHAPTER 19 Deploying Your Website
APPENDIX Answers to Exercises

Descarga:
Beginning_ASP.NET_for_Visual_Studio_2015

jueves, 4 de agosto de 2016

El Libro del Día: Building Maintainable Software

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

Titulo: Building Maintainable Software (C# Edition)
Autor: Joost Visser
Editorial: O'Reilly
Nro Paginas: 172

Capítulos:
1. Introduction
2. Write Short Units of Code
3. Write Simple Units of Code
4. Write Code Once
5. Keep Unit Interfaces Small
6. Separate Concerns in Modules
7. Couple Architecture Components Loosely
8. Keep Architecture Components Balanced
9. Keep Your Codebase Small
10. Automate Tests
11. Write Clean Code
12. Next Steps
A. How SIG Measures Maintainability

Descarga:
Building_Maintainable_Software

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).