jueves, 29 de diciembre de 2016

El Libro del Día: .NET Development Using the Compiler API

El Libro del Día: 2016-12-29

Titulo: .NET Development Using the Compiler API
Autor: Jason Bock
Editorial: Apress
Nro Paginas: 175

Capítulos:
Chapter 1: An Overview of the Compiler API
Chapter 2: Writing Diagnostics
Chapter 3: Creating Refactorings and Handling Workspaces
Chapter 4: Using the Scripting API
Chapter 5: The Future of the Compiler API

Descarga:
NET_Development_Using_the_Compiler_API

miércoles, 28 de diciembre de 2016

El Libro del Día: Visual Studio 2015 Cookbook

El Libro del Día: 2016-12-28

Titulo: Visual Studio 2015 Cookbook (2nd Edition)
Autor: Jeff Martin
Editorial: Packt
Nro Paginas: 368

Capítulos:
Chapter 1: Exploring Visual Studio 2015
Chapter 2: Getting Started with Universal Windows Platform Apps
Chapter 3: Web Development
Chapter 4: .NET Framework Development
Chapter 5: Debugging Your .NET Application
Chapter 6: Asynchrony in .NET
Chapter 7: Unwrapping C++ Development
Chapter 8: Working with Team Foundation Server 2015
Chapter 9: Languages
Chapter 10: Final Polish

Descarga:
Visual_Studio_2015_Cookbook

martes, 27 de diciembre de 2016

El Libro del Día: WebGL Insights

El Libro del Día: 2016-12-27

Titulo: WebGL Insights
Editor: Patrick Cozzi
Publicador: CRC Press
Nro Paginas: 416

Capítulos:
Section I WebGL Implementations
1 ANGLE: A Desktop Foundation for WebGL
2 Mozilla’s Implementation of WebGL
3 Continuous Testing of Chrome’s WebGL Implementation
Section II Moving to WebGL
4 Getting Serious with JavaScript
5 Emscripten and WebGL
6 Data Visualization with WebGL: From Python to JavaScript
7 Teaching an Introductory Computer Graphics Course with WebGL
Section III Mobile
8 Bug-Free and Fast Mobile WebGL
Section IV Engine Design
9 WebGL Engine Design in Babylon.js
10 Rendering Optimizations in the Turbulenz Engine
11 Performance and Rendering Algorithms in Blend4Web
12 Sketchfab Material Pipeline: From File Variations to Shader Generation
13 glslify: A Module System for GLSL
14 Budgeting Frame Time
Section V Rendering
15 Deferred Shading in Luma
16 HDR Image-Based Lighting on the Web
17 Real-Time Volumetric Lighting for WebGL
18 Terrain Geometry - LOD Adapting Concentric Rings
Section VI Visualization
19 Data Visualization Techniques with WebGL
20 hare3d - Rendering Large Models in the Browser
21 The BrainBrowser Surface Viewer: WebGL-Based Neurological Data Visualization
Section VII Interaction
22 Usability of WebGL Applications
23 Designing Cameras for WebGL Applications

Descarga:
WebGL_Insights

lunes, 26 de diciembre de 2016

Entrenamiento - Charla Gratuita sobre Desarrollo de Software Ligero y Desconectado

Charla Gratuita sobre Desarrollo de Software Ligero y Desconectado

A los interesados en conocer de cerca mi arquitectura y metodología de desarrollo de software ligero y desconectado basado en Performance, les comunico que estaré dando una Charla Gratuita de 3 horas el día Domingo 8 de Enero del 2017 de 10:00 am a 1:00 pm y el lugar se estará enviando solo a los registrados.

Esta charla es solo para nuevos participantes, es decir, los alumnos que ya están llevando el Taller no sería recomendable que se inscriban para darle oportunidad a nuevas personas, ya sea profesionales o estudiantes de poder conocer las ventajas de mi forma de trabajo,

El procedimiento para registrarse es enviar un mail a Luis.duenash@gmail.com con la siguiente información:
- Nombre Completo
- Tipo Perfil: Profesional / Estudiante / Otro
- Lugar de Trabajo o Estudio (Nombre de la Universidad o Instituto)
- Ha sido ex-alumno (PECI, Web Developer, Carrera, etc)

Recuerden que las vacantes son limitadas por la capacidad del lugar y esta es la única forma de participar en mis Talleres, es decir, solo invito a los que constantemente muestran interés y no a cualquiera que tenga plata para pagar.

El Libro del Día: WebGL Programming Guide

El Libro del Día: 2016-12-26

Titulo: WebGL Programming Guide
Autor: Kouichi Matsuda, Rodger Lea
Editorial: Addison Wesley
Nro Paginas: 544

Capítulos:
1. Overview of WebGL
2. Your First Step with WebGL
3. Drawing and Transforming Triangles
4. More Transformations and Basic Animation
5. Using Colors and Texture Images
6. The OpenGL ES Shading Language (GLSL ES)
7. Toward the 3D World
8. Lighting Objects
9. Hierarchical Objects
10. Advanced Techniques
Anexos:
A. No Need to Swap Buffers in WebGL
B. Built-in Functions of GLSL ES 1.0
C. Projection Matrices
D. WebGL/OpenGL: Left or Right Handed
E. The Inverse Transpose Matrix
F. Load Shader Programs from Files
G. World Coordinate System Versus Local Coordinate System
H. Web Browser Settings for WebGL

Descarga:
WebGL_Programming_Guide

sábado, 24 de diciembre de 2016

El Libro del Día: Learning Virtual Reality

El Libro del Día: 2016-12-24

Titulo: Learning Virtual Reality
Autor: Tony Parisi
Editorial: O'Reilly
Nro Paginas: 128

Capítulos:
1. Introduction
2. Virtual Reality Hardware
3. Going Native: Developing for Oculus Rift on the Desktop
4. Going Mobile: Developing for Gear VR
5. WebVR: Browser-Based Virtual Reality in HTML5
6. VR Everywhere: Google Cardboard for Low-Cost Mobile Virtual Reality

Descarga:
Learning_Virtual_Reality

miércoles, 21 de diciembre de 2016

Presentación - Desarrollo de Software Ligero y Desconectado

Desarrollo de Software Ligero y Desconectado

Introducción

Comparto con ustedes una de mis presentaciones de este año sobre la Necesidad de una Nueva Arquitectura de Software de Alto Rendimiento (ASAR): Ligera, Desconectada, Segura y Disponible (LDSD) que busca cambiar el paradigma del desarrollo que actualmente esta orientado a la Reusabilidad (N-Capas, Servicios, Frameworks, Librerías, Plantillas, etc) y No a la Performance (que es algo que se necesita Urgente).

La actual arquitectura y los temas que se aprenden en todas partes del mundo solo llevan a que las Aplicaciones sean demasiado lentas ya que se conectan constantemente y ocupan todo el ancho de banda con los formatos existentes (XML, JSON), por lo cual es necesario desconectarse y usar un formato mas ligero (CSV).

En estos últimos años vengo trabajando mucho en este tema y mi intención es compartir con la mayor cantidad de personas mi visión sobre lo que debería corregirse en los Sistemas sino los problemas continuaran, es por eso comparto esta Presentación donde comento los Problemas de los Sistemas, las Causas y la Solución.

Presentación

Diapositiva 1

Diapositiva 2

Diapositiva 3

Diapositiva 4

Diapositiva 5

Diapositiva 6

Diapositiva 7

Diapositiva 8

Diapositiva 9

Diapositiva 10

Diapositiva 11

Diapositiva 12

Diapositiva 13

Diapositiva 14

Diapositiva 15

Diapositiva 16

Diapositiva 17

Diapositiva 18

Diapositiva 19

Comentario Final

Si su objetivo principal es que las aplicaciones sean rápidas, nada de lo que se enseña te va a ayudar en dicho objetivo, es decir, si aprendes el uso de Frameworks, Librerías, Plantillas, Patrones, etc, más el enfoque conectado, solo conseguirán que sus páginas sean mas lentas.

Mi aporte para resolver estos problemas los puedo resumir en lo siguiente:
1. Enviar la menor cantidad de archivos: La página, un solo JS, un solo CSS y un solo paquete con las imágenes.
2. Trabajar en forma desconectada para reducir el número de conexiones.
3. Usar CSV como formato de datos para el transporte y así reducir el ancho de banda.
4. Eliminar el uso de capas y bucles en el Back-End
5. Serializar los datos en el Servidor de Datos (SQL Server, Oracle, etc).
6. Trabajar con JavaScript la presentación, búsquedas, filtros, ordenaciones, paginaciones, exportaciones, importaciones, previews de archivos, etc.
7. Actualizar en tiempo real usando Sockets y no Servicios ni llamar constantemente al servidor, etc.

Este breve resumen es la implementación de mi Arquitectura Ligera y Desconectada que considero la alternativa mas eficiente para resolver el problema de la performance que es el "Gran Problema" y el más urgente de resolver.

La mayoría de desarrolladores solo piensan en "Crear" y aprenden muchas cosas que No servirán de nada y solo contribuirán a los problemas descritos en la presentación, los cuales pueden evitarse si uno entiende como funciona una aplicación.

Solo me queda aconsejar a los más jóvenes, sobre todo que recién empiezan, que no se dejen guiar por la moda y las "nuevas formas de desarrollar" que al final cuando trabajen se darán cuenta de que todo lo que estudiaron y las plantillas de arquitectura que les dieron para seguir No fueron las mejores.

En el colmo de la ignorancia, mucha gente que sigue el "Modelo Equivocado" y todavía se pregunta "Pero si ya aumentamos las características del Servidor (CPU, RAM, Disco, etc), porque las Aplicaciones siguen Lentas". La respuesta es simple: "NO es problema de Hardware, pero si de Software, en este caso de Aplicación" y la capacitación que seguiste, la arquitectura que elegiste y todo lo que aprendiste "No resolverá dicho problema".

Los que han visto mi trabajo en este último año y basta como prueba lo que hicimos este Domingo en el Seminario de JavaScript saben que en todos los extremos desde el Back-End hasta el Front-End mejoramos el tiempo de respuesta convirtiendo a la aplicación en "Super Rápida".

Para finalizar, quiero agradecer a todos mis alumnos que durante este año me permitieron mostrar mi trabajo y compartir muchos momentos de reflexión los cuales dieron sus frutos creando una arquitectura sólida en cuanto a performance, la cual vamos a mejorar al próximo año aumentando la seguridad, que son los principales problemas al cual debemos enfocarnos y en el cual trato de aportar algo.

El Libro del Día: WebRTC Cookbook

El Libro del Día: 2016-12-21

Titulo: WebRTC Cookbook
Autor: Andrii Sergiienko
Editorial: Packt
Nro Paginas: 230

Capítulos:
Chapter 1: Peer Connections
Chapter 2: Supporting Security
Chapter 3: Integrating WebRTC
Chapter 4: Debugging a WebRTC Application
Chapter 5: Working with Filters
Chapter 6: Native Applications
Chapter 7: Third-party Libraries
Chapter 8: Advanced Functions

Descarga:
WebRTC_Cookbook

martes, 20 de diciembre de 2016

El Libro del Día: Getting Started with WebRTC

El Libro del Día: 2016-12-20

Titulo: Getting Started with WebRTC
Autor: Rob Manson
Editorial: Packt
Nro Paginas: 114

Capítulos:
Chapter 1: An Introduction to Web-based Real-Time Communication
Chapter 2: A More Technical Introduction to Web-based Real-Time Communication
Chapter 3: Creating a Real-time Video Call
Chapter 4: Creating an Audio Only Call
Chapter 5: Adding Text-based Chat
Chapter 6: Adding File Sharing
Chapter 7: Example Application 1 – Education and E-learning
Chapter 8: Example Application 2 – Team Communication

Descarga:
Getting_Started_with_WebRTC

sábado, 22 de octubre de 2016

Entrenamiento - Seminarios de JavaScript

Seminarios de JavaScript

Como muchos saben ya no pienso dictar Cursos ni Talleres Semanales de ASP.NET MVC & JavaScript, pero en el último Taller que acaba mañana Domingo 23 de Octubre hay temas que no pudimos ver que me gustaría tratarlos detalladamente por lo cual los voy a tocar a manera de Seminarios.

Temas de los Seminarios

1. WebRTC
2. WebGL
3. Maps (Google, Yahoo, Bind, etc)
4. Asynchronous & Parallel Programming (Promises, WebWorkers y ServiceWorkers)
5. Web Components (Polymer)
6. Functional Programming: map, filter, reduce (Elm, ReactiveX)
7. Reactive Programming (React, Flux y Redux)
8. Chrome Apps & Progressive Web Apps (Google)
9. Mobile Native Apps (iOS, Andorid, Xamarin)
10. Hybrid Mobile Apps (Titanium, NativeScript, PhoneGap)
11. Security (Obfuscation, XSS, CSRF, etc)
12. Image File Formats (BMP, JPG, PNG, WebP)
13. Native Data Export (XLSX, DOCX, PPTX, PDF)
14. High Performance Web Site (The Definitive Rules)

Observación

Todos los temas son de nivel avanzado, sobre todo los 4 últimos.

Información

Frecuencia: 1 vez al mes
Día: Último Domingo de cada mes
Horario: 9:00 am a 2:00 pm.
Inicio: 27 de Noviembre del 2016
Duración: 5 horas
Inversión: 100 Soles cada Seminario
Inscripciones: Luis.duenash@gmail.com 
Mínimo de Participantes: 15
Máximo de Participantes: 30
Lugar: Por confirmar (se enviará una semana antes a los registrados)

Comentario Final

Los interesados en participar en el Taller tienen que registrarse enviándome un correo con el Asunto: "Seminarios de JavaScript" e indicar su Nombre Completo y si es ex-alumno o no.

Además quiero resaltar que es obligatorio participar en todos los seminarios, no se puede faltar a ninguno, el que falta quedará retirado para los siguientes seminarios y se le dará la oportunidad a otros interesados.

Los que nunca han llevado algún curso conmigo, es su oportunidad para que vean la diferencia de nivel y profundidad de los temas tratados.

Cada seminario tendrá su PPT y sus respectivos demos o ejemplos muy interesantes y reales.

Para los que estaban pidiendo participar en algún curso o taller solo queda estos Seminarios una vez al mes con lo cual estaría cubriendo casi todo el "Desarrollo Web Desconectado con JavaScript orientado a Performance" que iniciamos hace unos años y donde cubrimos casi todas las APIs hasta la actualidad.

martes, 11 de octubre 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

A las Empresas interesadas en seguir una buena capacitación en ASP.NET MVC & JavaScript, les comunico que están disponibles nuevos horarios y con adiciones al contenido, los cuales incluyen además de las verdaderas buenas prácticas de Performance, los temas de Actualización en Tiempo Real (más a fondo) y Manejo de Gran Cantidad de Datos.

Horarios

1. Miércoles y Viernes de 6:00 pm a 9:00 pm (puede ser una hora antes o después)
2. Sábados de 2:00 pm a 8:00 pm.
3. Domingos de 8:00 am a 2:00 pm.

Fechas Propuestas de Inicio

1. Miércoles 26 de Octubre
2. Sábado 29 de Octubre
3. Domingo 30 de Octubre

Contenido del Curso

1. Entendiendo el Desarrollo Web en ASP .NET
1.1. Arquitectura de una Aplicación Web ASP.NET
1.2. Aplicaciones Web Forms y Aplicaciones MVC
1.3. El problema de la Performance en Sitios Web
1.4. Arquitectura de Alto Rendimiento de una Aplicación Web
2. Creando Aplicaciones Web Distribuidas
2.1. Creando Librerías de Entidades del Negocio
2.2. Creando Librerías de Acceso a Datos
2.3. Creando Librerías de Reglas del Negocio
2.4. Creando una Aplicación Web MVC
3. Listando Registros
3.1. Usando el control WebGrid con Listas de Objetos
3.2. Usando JQuery y JSON
3.3. Usando XHR y Strings
4. Trabajando Desconectado con JavaScript
4.1. Filtrando registros
4.2. Paginando registros
4.3. Ordenando registros
4.4. Exportando a Texto y Excel
5. Mantenimiento, Popups, Cabecera Detalle e Impresión
5.1. Mantenimiento de registros
5.2. Creando Popups usando Divs
5.3. Trabajando con Cabecera Detalle
5.4. Imprimiendo datos de la página
6. Presentación Personalizada y Reportes con JavaScript
6.1. Vista Tablas
6.2. Vista Jerárquica Horizontal
6.3. Vista Jerárquica Vertical
6.4. Vista Tabla Cruzada
7. Gráficos con HTML5 y JavaScript
7.1. Creando Gráficos de Datos con Canvas
7.2. Creando Gráficos de Datos con SVG
7.3. Creando Gráficos Interactivos
8. Trabajando con Servicios (WCF y Web API)
8.1. Creando y Consumiendo un Servicio WCF alojado en IIS
8.2. Creando y Consumiendo un Servicio WCF alojado en su propio Servidor
8.3. Creando un Servicio Web API y Consumiendo desde .NET
8.4. Creando un Servicio Web API y Consumiendo desde JavaScript
9. Programación En Tiempo Real en ASP.NET
9.1. Creando un Servidor WebSocket usando Fleck
9.2. Actualizando en Tiempo Real una App Web usando WebSockets
9.3. Creando un Servidor WebSocket propio alojado en IIS
9.4. Actualizando en Tiempo Real cualquier Aplicación usando Sockets
10. Manejando Gran Cantidad de Datos desde la App Web
10.1. Subir Archivos Gigantes desde la App Web al Sistema de Archivos
10.2. Bajar Archivos Gigantes desde el Sistema de Archivos al Cliente
10.3. Grabar Miles de Registros desde la App Web al Servidor de Datos
10.4. Mostrar Miles de Registros desde el Servidor de Datos al Cliente

Observaciones sobre el Contenido

- No Uso Frameworks ni Librerías de Terceros Ni en el Servidor Ni en el Cliente
- 10 % del código está en el servidor en C#
- 90% del código está en el cliente en JavaScript (APIs nativas multi navegador)
- Todo los ejemplos son reales del día a día del programador.

Duración del Curso

Total: 48 horas
Tiempo: 2 meses
Frecuencia: 6 horas semanales

Inversión

- Hasta 5 personas el costo es de 100 soles x hora, es decir, un total de 4800 soles.

- Más de 5 personas el costo es de 20 soles x hora x participante.
Ejemplo: Si son 10 personas el costo será de 200 soles x hora y el total será de 9600 soles.

Nota: Estos costos son solo para Empresas ubicadas en Lima - Perú. Si hay Empresas interesadas en Provincias o fuera del país podemos coordinar sobre la inversión.

Forma de Pago

- La mitad se paga al inicio de la capacitación.

- La otra parte se paga a la mitad de la capacitación.

Contacto

Los interesados enviar un mail a Luis.duenash@gmail.com con los siguientes datos:

Asunto: Capacitación ASP.NET MVC & JavaScript

Contenido:
- Empresa: xxx
- Rubro: xxx
- Número de Participantes: xx
- Horario de Interés: Miércoles y Viernes / Sábados / Domingos
- Contacto: xxx
- Teléfono: xxx
- Dirección: xxx

Para los interesados que envíen un mail se coordinará una visita para hacer una demostración de los temas y ejemplos del curso y para resolver cualquier duda de su personal técnico.

Comentario Final

Los que todavía no se han capacitado conmigo en este último año, no pierdan la oportunidad porque mis técnicas han evolucionado exponencialmente y trato de ver ejemplos que siempre han querido hacer y nunca han podido, es decir, los problemas más frecuentes cuando la red esta lenta, hay gran cantidad de datos que trabajar, pocos recursos en el servidor, etc.

Para darse cuenta de la evolución y las técnicas originales que utilizo pueden ver mi Canal de YouTube donde subo solo algunos videos de las Empresas que autorizan subir el Curso y de algunos ejemplos de mi último Taller:

Canal de YouTube de Luis Dueñas

La mayoría de cursos son iguales, todos te enseñan la mismas cosas que nunca han dado resultado, el problema principal es que las paginas son demasiado lentas y la solución esta en la forma cómo se programa, todos se "facilitan la vida en el desarrollo" usando Frameworks y Librerías pero se "Ponen la soga al cuello" ya que impactan sobre el rendimiento de la aplicación, sino pregúntenle a sus usuarios.

jueves, 6 de octubre de 2016

El Libro del Día: Effective C# (2nd Edition)

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

Titulo: Effective C# (2nd Edition)
Autor: Bill Wagner
Editorial: Addison-Wesley
Nro Paginas: 343

Capítulos:
Chapter 1 C# Language Idioms
- Item 1: Use Properties Instead of Accessible Data Members
- Item 2: Prefer readonly to const
- Item 3: Prefer the is or as Operators to Casts
- Item 4: Use Conditional Attributes Instead of #if
- Item 5: Always Provide ToString()
- Item 6: Understand the Relationships Among the Many Different Concepts of Equality
- Item 7: Understand the Pitfalls of GetHashCode()
- Item 8: Prefer Query Syntax to Loops
- Item 9: Avoid Conversion Operators in Your APIs
- Item 10: Use Optional Parameters to Minimize Method Overloads
- Item 11: Understand the Attraction of Small Functions
Chapter 2 .NET Resource Management
- Item 12: Prefer Member Initializers to Assignment Statements
- Item 13: Use Proper Initialization for Static Class Members
- Item 14: Minimize Duplicate Initialization Logic
- Item 15: Utilize using and try/finally for Resource Cleanup
- Item 16: Avoid Creating Unnecessary Objects
- Item 17: Implement the Standard Dispose Pattern
- Item 18: Distinguish Between Value Types and Reference Types
- Item 19: Ensure That 0 Is a Valid State for Value Types
- Item 20: Prefer Immutable Atomic Value Types
Chapter 3 Expressing Designs in C#
- Item 21: Limit Visibility of Your Types
- Item 22: Prefer Defining and Implementing Interfaces to Inheritance
- Item 23: Understand How Interface Methods Differ from Virtual Methods
- Item 24: Express Callbacks with Delegates
- Item 25: Implement the Event Pattern for Notifications
- Item 26: Avoid Returning References to Internal Class Objects
- Item 27: Prefer Making Your Types Serializable
- Item 28: Create Large-Grain Internet Service APIs
- Item 29: Support Generic Covariance and Contravariance
Chapter 4 Working with the Framework
- Item 30: Prefer Overrides to Event Handlers
- Item 31: Implement Ordering Relations with IComparable<T> and IComparer<T>
- Item 32: Avoid ICloneable
- Item 33: Use the new Modifier Only to React to Base Class Updates
- Item 34: Avoid Overloading Methods Defined in Base Classes
- Item 35: Learn How PLINQ Implements Parallel Algorithms
- Item 36: Understand How to Use PLINQ for I/O Bound Operations
- Item 37: Construct Parallel Algorithms with Exceptions in Mind
Chapter 5 Dynamic Programming in C#
- Item 38: Understand the Pros and Cons of Dynamic
- Item 39: Use Dynamic to Leverage the Runtime Type of Generic Type Parameters
- Item 40: Use Dynamic for Parameters That Receive Anonymous Types
- Item 41: Use DynamicObject or IDynamicMetaObjectProvider for Data Driven Dynamic Types
- Item 42: Understand How to Make Use of the Expression API
- Item 43: Use Expressions to Transform Late Binding into Early Binding
- Item 44: Minimize Dynamic Objects in Public APIs
Chapter 6 Miscellaneous
- Item 45: Minimize Boxing and Unboxing
- Item 46: Create Complete Application-Specific Exception Classes
- Item 47: Prefer the Strong Exception Guarantee
- Item 48: Prefer Safe Code
- Item 49: Prefer CLS-Compliant Assemblies
- Item 50: Prefer Smaller, Cohesive Assemblies

Descarga:
Effective_C#_2nd_Edition

viernes, 30 de septiembre de 2016

El Libro del Día: Exam Ref 70-480 Programming in HTML5 with JavaScript and CSS3

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

Titulo: Exam Ref 70-480 Programming in HTML5 with JavaScript and CSS3
Autor: Rick Delorme
Editorial: Microsoft Press
Nro Paginas: 353

Capítulos:
Chapter 1 Implement and manipulate document structures and objects
- Objective 1.1: Create the document structure
- Objective 1.2: Write code that interacts with UI controls
- Objective 1.3: Apply styling to HTML elements programmatically
- Objective 1.4: Implement HTML5 APIs
- Objective 1.5: Establish the scope of objects and variables
- Objective 1.6: Create and implement objects and methods
Chapter 2 Implement program flow
- Objective 2.1: Implement program flow
- Objective 2.2: Raise and handle an event
- Objective 2.3: Implement exception handling
- Objective 2.4: Implement a callback
- Objective 2.5: Create a web worker process
Chapter 3 Access and secure data
- Objective 3.1: Validate user input by using HTML5 elements
- Objective 3.2: Validate user input by using JavaScript
- Objective 3.3: Consume data
- Objective 3.4: Serialize, deserialize, and transmit data
Chapter 4 Use CSS3 in applications
- Objective 4.1: Style HTML text properties
- Objective 4.2: Style HTML box properties
- Objective 4.3: Create a flexible content layout
- Objective 4.4: Create an animated and adaptive UI
- Objective 4.5: Find elements using CSS selectors and jQuery
- Objective 4.6: Structure a CSS file by using CSS selectors

Descarga:
ExamRef_70480_Programming_HTML5_JavaScript_CSS3

martes, 27 de septiembre de 2016

El Libro del Día: Map Scripting 101

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

Titulo: Map Scripting 101
Autor: Adam DuVander
Editorial: No Starch Press
Nro Paginas: 380

Capítulos:
Chapter 1: Mapping Basics
Chapter 2: Plotting Markers and Message Boxes
Chapter 3: Geocoding
Chapter 4: Layer It On
Chapter 5: Handle Map Events
Chapter 6: Explore Proximity
Chapter 7: User Location
Chapter 8: Data Formats
Chapter 9: Go Server-Side
Chapter 10: Mashup Projects
Appendix A: JavaScript Quick Start
Appendix B: Mapstraction Reference

Descarga:
Map_Scripting_101

lunes, 26 de septiembre de 2016

El Libro del Día: Understanding ECMAScript 6

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

Titulo: Understanding ECMAScript 6
Autor: Nicholas C. Zakas
Editorial: No Starch Press
Nro Paginas: 355

Capítulos:
Chapter 1: Block Bindings
Chapter 2: Strings and Regular Expressions
Chapter 3: Functions
Chapter 4: Expanded Object Functionality
Chapter 5: Destructuring for Easier Data Access
Chapter 6: Symbols and Symbol Properties
Chapter 7: Sets and Maps
Chapter 8: Iterators and Generators
Chapter 9: Introducing JavaScript Classes
Chapter 10: Improved Array Capabilities
Chapter 11: Promises and Asynchronous Programming
Chapter 12: Proxies and the Reflection API
Chapter 13: Encapsulating Code with Modules
Appendix A: Minor Changes in ECMAScript 6
Appendix B: Understanding ECMAScript 7 (2016)

Descarga:
Understanding_ECMAScript_6

miércoles, 14 de septiembre de 2016

El Libro del Día: Understanding Compression

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

Titulo: Understanding Compression
Autor: Colt McAnlis, Aleks Haecky
Editorial: O'Reilly
Nro Paginas: 241

Capítulos:
1. Let’s Not Be Boring
2. Do Not Skip This Chapter
3. Breaking Entropy
4. Variable-Length Codes
5. Statistical Encoding
6. Adaptive Statistical Encoding
7. Dictionary Transforms
8. Contextual Data Transforms
9. Data Modeling
10. Switching Gears
11. Evaluating Compression
12. Compressing Image Data Types
13. Serialized Data
14. Lossy Data Compression
15. Making the World a Little Smaller
Glossary of Compression Words

Descarga:
Understanding_Compression

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