<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss'><id>tag:blogger.com,1999:blog-9291335</id><updated>2009-11-06T15:40:16.509+01:00</updated><title type='text'>Rafinguer Blog: El blog de tecnología</title><subtitle type='html'>&lt;p&gt;Un lugar donde compartir inquietudes, reflexiones, opiniones, comentarios, recomendaciones, noticias, trucos, cachivaches, ... referidos a la tecnología.&lt;/p&gt;</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default?start-index=26&amp;max-results=25'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>429</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9291335.post-4072422462175286840</id><published>2009-11-01T17:05:00.002+01:00</published><updated>2009-11-01T17:08:14.616+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tecnillusions'/><title type='text'>Tecnillusions estrena nueva web</title><content type='html'>Ya está disponible la nueva web de Tecnillusions, una compañía especializada en soluciones tecnológicas a medida. Su nueva web está basada en tecnología Flex y Flash, en donde se presenta la compañía y su apuesta por las nuevas tecnologías en base a la sencillez y el diseño. La nueva web está tanto en castellano como en inglés, y en ella se ha plasmado el espíritu y la filosofía de la misma.&lt;br /&gt;&lt;br /&gt;Algunas de las pantallas de esta nueva Web son las siguientes:&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_WQAa3IBJLQY/Su2wq6wCZXI/AAAAAAAAACI/3-4r3bq0VRI/s1600-h/WebTecnillusions0.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_WQAa3IBJLQY/Su2wq6wCZXI/AAAAAAAAACI/3-4r3bq0VRI/s320/WebTecnillusions0.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_WQAa3IBJLQY/Su2wuPcxx3I/AAAAAAAAACQ/4YRTqdOJq9w/s1600-h/WebTecnillusions1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_WQAa3IBJLQY/Su2wuPcxx3I/AAAAAAAAACQ/4YRTqdOJq9w/s320/WebTecnillusions1.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_WQAa3IBJLQY/Su2wwQRChgI/AAAAAAAAACY/dZATxc37L9s/s1600-h/WebTecnillusions2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_WQAa3IBJLQY/Su2wwQRChgI/AAAAAAAAACY/dZATxc37L9s/s320/WebTecnillusions2.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_WQAa3IBJLQY/Su2wyNA1zxI/AAAAAAAAACg/elpzPRogAYA/s1600-h/WebTecnillusions3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_WQAa3IBJLQY/Su2wyNA1zxI/AAAAAAAAACg/elpzPRogAYA/s320/WebTecnillusions3.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_WQAa3IBJLQY/Su2w0W1twUI/AAAAAAAAACo/MAAEQn22ZVk/s1600-h/WebTecnillusions4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_WQAa3IBJLQY/Su2w0W1twUI/AAAAAAAAACo/MAAEQn22ZVk/s320/WebTecnillusions4.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_WQAa3IBJLQY/Su2w2djWRtI/AAAAAAAAACw/4gfkQ_xQ5Q0/s1600-h/WebTecnillusions5.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_WQAa3IBJLQY/Su2w2djWRtI/AAAAAAAAACw/4gfkQ_xQ5Q0/s320/WebTecnillusions5.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/center&gt;&lt;br /&gt;Enlace a la página web: &lt;a href="http://www.tecnillusions.com"&gt;http://www.tecnillusions.com&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-4072422462175286840?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/4072422462175286840/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=4072422462175286840&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/4072422462175286840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/4072422462175286840'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/11/tecnillusions-estrena-nueva-web.html' title='Tecnillusions estrena nueva web'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_WQAa3IBJLQY/Su2wq6wCZXI/AAAAAAAAACI/3-4r3bq0VRI/s72-c/WebTecnillusions0.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-1488976669907378318</id><published>2009-10-31T06:16:00.001+01:00</published><updated>2009-10-31T06:17:17.926+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software'/><category scheme='http://www.blogger.com/atom/ns#' term='Tecnillusions'/><title type='text'>Trazalogic: Software para trazabilidad de alimentos</title><content type='html'>&lt;b&gt;Trazalogic&lt;/b&gt; es un proyecto actualmente en desarrollo para dar cobertura a la trazabilidad de alimentos para empresas de elaboración y manipulación de alimentos. Las principales características de &lt;b&gt;Trazalogic&lt;/b&gt; con respecto a otros productos similares son las siguientes:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Costes mínimos:&lt;/b&gt;&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Desarrollado bajo estándares de software libre:&lt;/b&gt;&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Servidor de aplicaciones Apache Tomcat&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Procesos de negocio servidos mediante Java&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Base de datos PostgreSQL&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Front-end basado en Adobe AIR/Flash&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Mínimo mantenimiento&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Libertad de licencias:&lt;/b&gt;&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Sin restricciones en cuanto a equipos instalados&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Sin restricciones en cuanto a tiempo&lt;/li&gt;&lt;br /&gt;&lt;li&gt;El soporte es opcional, y sólo se paga por el plan deseado acorde al uso del mismo&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Sencillez y productividad optimizadas:&lt;/b&gt;&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Interfaces de usuario ricas&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Sistema de inteligencia que anticipa los procesos&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Menos operaciones manuales y más procesos automatizados&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Entorno muy intuitivo que apenas requiere aprendizaje&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Pensado también para pantallas táctiles&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Arquitectura web:&lt;/b&gt;&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Instale un único servidor, acceda desde múltiples puestos en cualquier lugar&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Versatilidad en configuraciones de acceso&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Acceso restringido a usuarios previamente configurados&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Sistema abierto para acceso mediante servicios web, de cara a que otras aplicaciones se puedan integrar con &lt;b&gt;Trazalogic&lt;/b&gt; (con requerimiento de firma)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Múltiples idiomas:&lt;/b&gt; Inicialmente en castellano y en inglés, pero sería fácil agregar cualquier otro idioma con sistema de caracteres latinos&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Múltiples plataformas:&lt;/b&gt; Puede ser utilizado en Windows y en Linux&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Las principales características funcionales de &lt;b&gt;Trazalogic&lt;/b&gt; son las siguientes:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Sistema de administración:&lt;/b&gt;&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Gestión de usuarios&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Gestión de clientes&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Gestión de proveedores&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Gestión de inventario&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Gestión de puntos de control y almacenes&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Gestión de recetas o preparación de alimentos&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Trazabilidad de actividad del sistema&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Trazabilidad de los alimentos&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Estadísticas y cuadros de mando&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Informes&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Sistema de operación:&lt;/b&gt;&lt;/li&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Gestión de lotes (entrada y salida)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Gestión de productos&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Recepción de alimentos primarios&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Gestión de almacenamiento de alimentos (entrada y salida)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Elaboración de alimentos&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Gestión del envasado&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Gestión de salida de productos elaborados&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;A continuación algunas pantallas de &lt;b&gt;Trazalogic&lt;/b&gt; en acción:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_WQAa3IBJLQY/SuvGCroueaI/AAAAAAAAABY/lDDqpqH5-cw/s1600-h/trazalogic1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_WQAa3IBJLQY/SuvGCroueaI/AAAAAAAAABY/lDDqpqH5-cw/s320/trazalogic1.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_WQAa3IBJLQY/SuvGGU8RcUI/AAAAAAAAABg/cId25R6K0ZU/s1600-h/trazalogic2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_WQAa3IBJLQY/SuvGGU8RcUI/AAAAAAAAABg/cId25R6K0ZU/s320/trazalogic2.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_WQAa3IBJLQY/SuvGJ3zGTnI/AAAAAAAAABo/hH35RTShrS0/s1600-h/trazalogic3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_WQAa3IBJLQY/SuvGJ3zGTnI/AAAAAAAAABo/hH35RTShrS0/s320/trazalogic3.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_WQAa3IBJLQY/SuvGL2NSwhI/AAAAAAAAABw/Z2jB6dcUKDA/s1600-h/trazalogic4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_WQAa3IBJLQY/SuvGL2NSwhI/AAAAAAAAABw/Z2jB6dcUKDA/s320/trazalogic4.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_WQAa3IBJLQY/SuvGOacq9qI/AAAAAAAAAB4/fvroiSoiwyU/s1600-h/trazalogic5.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_WQAa3IBJLQY/SuvGOacq9qI/AAAAAAAAAB4/fvroiSoiwyU/s320/trazalogic5.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_WQAa3IBJLQY/SuvGQqCP5CI/AAAAAAAAACA/5qdFrqdmRjA/s1600-h/trazalogic6.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_WQAa3IBJLQY/SuvGQqCP5CI/AAAAAAAAACA/5qdFrqdmRjA/s320/trazalogic6.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Puede solicitar información sin compromiso sobre &lt;b&gt;Trazalogic&lt;/b&gt;, a través del correo electrónico: &lt;a href="mailto:info@tecnillusions.com"&gt;info@tecnillusions.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Tecnillusions:&lt;/b&gt; &lt;a href="http://www.tecnillusions.com"&gt; http://www.tecnillusions.com&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-1488976669907378318?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='related' href='http://tecnillusions.blogspot.com/2009/10/trazalogic-software-para-trazabilidad.html' title='Trazalogic: Software para trazabilidad de alimentos'/><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/1488976669907378318/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=1488976669907378318&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/1488976669907378318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/1488976669907378318'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/10/trazalogic-software-para-trazabilidad.html' title='Trazalogic: Software para trazabilidad de alimentos'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_WQAa3IBJLQY/SuvGCroueaI/AAAAAAAAABY/lDDqpqH5-cw/s72-c/trazalogic1.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-6587274173783167271</id><published>2009-10-25T20:42:00.002+01:00</published><updated>2009-10-25T20:52:08.215+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Libros'/><title type='text'>Firma de libros en la Conferencia de SPI en Pontevedra</title><content type='html'>El pasado viernes, 23 de Octubre de 2009, se celebró en Pontevedra una conferencia sobre SPI, a la que fui invitado por la presidenta de la AESPI, Esperanza López Maquieira. El acto fue presidido, además de por la presidenta de la AESPI, por la vicepresidenta Teresa Pinto, la tesorera Mª Jesús Catalán, el doctor Diego García-Borreguero y el vicepresidente de la diputación de Pontevedra D. José Juan Durán.&lt;br /&gt;&lt;br /&gt;En el acto se presentó mi libro "SPI: el demonio que me despierta mientras duermo", que se entregó al final de la conferencia entre los asistentes, y a los que, gustosamente, firmé.&lt;br /&gt;&lt;br /&gt;A los interesados, podéis conseguir información sobre el SPI y descargaros mi libro, desde la página de la AESPI: &lt;a href="http://www.aespi.net"&gt;http://www.aespi.net&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Existe un foro donde podrás encontrar información de todo tipo (asociaciones, médicos, consultas, tratamientos, noticias, etc.): &lt;a href="http://groups.google.com/group/sindrome-de-piernas-inquietas"&gt;http://groups.google.com/group/sindrome-de-piernas-inquietas&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_T-uXeKcGTnM/SuShKRWQjuI/AAAAAAAABPI/Ui59bOtWIBE/s1600-h/P1020087.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/_T-uXeKcGTnM/SuShKRWQjuI/AAAAAAAABPI/Ui59bOtWIBE/s400/P1020087.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5396615451324223202" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_T-uXeKcGTnM/SuSiJw151bI/AAAAAAAABPQ/X5yV6bgpUGo/s1600-h/P1020086.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://3.bp.blogspot.com/_T-uXeKcGTnM/SuSiJw151bI/AAAAAAAABPQ/X5yV6bgpUGo/s400/P1020086.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5396616542110209458" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_T-uXeKcGTnM/SuSi0ZbDmcI/AAAAAAAABPY/poSYeD43zcs/s1600-h/P1020084.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://3.bp.blogspot.com/_T-uXeKcGTnM/SuSi0ZbDmcI/AAAAAAAABPY/poSYeD43zcs/s400/P1020084.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5396617274557962690" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_T-uXeKcGTnM/SuSkL7Dgh7I/AAAAAAAABPg/4j8zSbkO5_g/s1600-h/P1020075.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://2.bp.blogspot.com/_T-uXeKcGTnM/SuSkL7Dgh7I/AAAAAAAABPg/4j8zSbkO5_g/s400/P1020075.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5396618778234619826" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_T-uXeKcGTnM/SuSlnVibiMI/AAAAAAAABPo/dROyJhiKqsE/s1600-h/P1020055.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://3.bp.blogspot.com/_T-uXeKcGTnM/SuSlnVibiMI/AAAAAAAABPo/dROyJhiKqsE/s400/P1020055.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5396620348711733442" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-6587274173783167271?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/6587274173783167271/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=6587274173783167271&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/6587274173783167271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/6587274173783167271'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/10/firma-de-libros-en-la-conferencia-de.html' title='Firma de libros en la Conferencia de SPI en Pontevedra'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_T-uXeKcGTnM/SuShKRWQjuI/AAAAAAAABPI/Ui59bOtWIBE/s72-c/P1020087.JPG' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-277751425581853318</id><published>2009-10-20T19:17:00.003+02:00</published><updated>2009-10-20T19:48:19.787+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>Flex/AIR: Error de conversión a ArrayCollection de ObjectProxy en llamadas HTTPService</title><content type='html'>Me he encontrado con un problema habitual, y ocurre cuando uno hace una llamada a un HTTPService, y en la función que gestiona (handle) la llamada, al asignar el resultado del XML a un ArrayCollection, se encuentra con que no puede asignarse un objeto ObjectProxy al ArrayCollection. Este tipo de operaciones son habituales cuando hay que cargar una lista o un ComboBox. Este problema ocurre cuando solamente se tiene un elemento en la lista, mientras que si hay más de uno, este problema no ocurre. Asimismo, si no hay resultado, también puede dar un error de null. Creo que se trata de un bug de Flex, ya que en estos casos, automáticamente debería dar un ArrayCollection de todas maneras, con cero, uno o más de un item.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Antes de continuar, indicar que este post no contiene un ejemplo completo para poder probar, si no que explica detalladamente como resolver esta situación.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Tras dar vueltas y vueltas al problema, he realizado una pequeña "ñapa" o "parche" para que la carga del ArrayCollection se realice sin problemas. &lt;br /&gt;&lt;br /&gt;En primer lugar voy a presentar el XML que devuelve el HTTPService:&lt;br /&gt;&lt;br /&gt;&lt;font size="1"&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="ISO-8859-1" ?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;products_providers_in_use&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;product_provider_in_use&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;data&amp;gt;6&amp;lt;/data&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;label&amp;gt;Bill&amp;nbsp;Gates&amp;lt;/label&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;id_product&amp;gt;21&amp;lt;/id_product&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;name_product&amp;gt;Escalope&amp;nbsp;de&amp;nbsp;ternera&amp;lt;/name_product&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;total&amp;gt;0&amp;lt;/total&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/product_provider_in_use&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;&amp;lt;products_providers_in_use&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;La definición del HTTPService permite definir en qué funciones delegar la ejecución en caso de error (fault) o de éxito (result), así como la URL al HTTPService (url). &lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;!--&amp;nbsp;Call&amp;nbsp;to&amp;nbsp;srvGetProductsProvidersInUse&amp;nbsp;service&amp;nbsp;--&amp;gt;&lt;br /&gt;&amp;lt;mx:HTTPService&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;result="handleProductsProvidersInUse(event);"&lt;br /&gt;&amp;nbsp;&amp;nbsp;fault="handleFault(event);"&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;id="nombre_del_servicio"&amp;nbsp;resultFormat="object"&lt;br /&gt;&amp;nbsp;&amp;nbsp;url="url_al_httpservice"&lt;br /&gt;&amp;nbsp;&amp;nbsp;useProxy="false"&amp;gt;&lt;br /&gt;&amp;lt;/mx:HTTPService&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Es necesario definir el ArrayCollection como una variable de ámbito local, que pueda ser accedida por todas funciones del módulo, componente, etc.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[Bindable]&lt;br /&gt;import mx.collections.ArrayCollection;&lt;br /&gt;&lt;br /&gt;private var acInUse:ArrayCollection;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;La llamada al HTTPService se realiza mediante el objeto HTTPService (referenciando el nombre indicado en la propiedad id) y al método "send" en el momento que sea necesario (en el creationComplete, al pulsar un botón, etc.):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;nombre_del_servicio.send();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Una vez se ejecuta el HTTPService, éste accederá a dicho servicio para obtener un XML. En el caso de que no se haya producido ningún problema en la comunicación, se delegará la ejecución en la función definida en "result". El código para leer correctamente este XML en todos los casos (ya corregido el bug) es el siguiente:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;private&amp;nbsp;function&amp;nbsp;handleProductsProvidersInUse(event:ResultEvent):void&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;try&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;acInUse&amp;nbsp;=&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;event.result.products_providers_in_use.product_provider_in_use&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;as&amp;nbsp;ArrayCollection;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;catch&amp;nbsp;(err:Error)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;acInUse=new&amp;nbsp;ArrayCollection();&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(acInUse==null)&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;o:Object;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o=event.result.products_providers_in_use.product_provider_in_use;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;acInUse&amp;nbsp;=&amp;nbsp;new&amp;nbsp;ArrayCollection(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[{data:o.data,label:o.label,id_product:o.id_product,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name_product:o.name_product,total:o.total}]);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Para controlar las excepciones se abre un bloque try...catch para intentar acceder al XML recogido. Lo normal es asignar al ArrayCollection la colección de datos del XML que se repite. El XML está contenido dentro del parámetro de evento, y en la propiedad "result". El primer elemento del XML ("products_providers_in_use") no se repite, y marca el principio y fin del grupo de datos. Por ello hay que llegar hasta el siguiente nivel del XML: "product_provider_in_use". En teoría, este nivel retornaría un ArrayCollection. En el caso de que tenga más de un elemento no hay problema, pero si hay un sólo elemento, no produce ninguna excepción, pero, inexplicablemente, nos retorna un null. Por ello, tras el catch se hace una comprobación de si es nulo, en cuyo caso se crea un ArrayCollection nuevo, se recoge el único elemento del resultado en un objeto genérico, y se crea un elemento con la información recogida en el XML. En el caso de que el XML estuviera vacío o tuviera algún problema, saltaría una excepción, la cual es recogida por el bloque "catch" y crea un ArrayCollection nuevo, pero vacío, &lt;b&gt;pero no null&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Espero que este ejemplo corte definitivamente el tiempo que os haya hecho perder esta singular situación.&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-277751425581853318?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/277751425581853318/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=277751425581853318&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/277751425581853318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/277751425581853318'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/10/flexair-error-de-conversion.html' title='Flex/AIR: Error de conversión a ArrayCollection de ObjectProxy en llamadas HTTPService'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-9182863281314293805</id><published>2009-10-20T11:17:00.009+02:00</published><updated>2009-10-20T12:18:10.203+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>Flex/AIR: Listas personalizadas con ItemRenderer</title><content type='html'>Una de las mayores virtudes de Flex es que es posible personalizar la vista de una lista o de un Datagrid, pudiendo añadir elementos que no son estándares (la típica etiqueta o texto), sino que se pueden añadir también elementos gráficos o incluso elementos de interfaz de usuario.&lt;br /&gt;&lt;br /&gt;Para ver una muestra de ello, la siguiente imagen muestra una lista con un icono a la izquierda, dependiendo del estado del item:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_T-uXeKcGTnM/St2BbYV8COI/AAAAAAAABOg/tpJ22P6iaaU/s1600-h/DemoItemRenderer1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 154px; height: 186px;" src="http://1.bp.blogspot.com/_T-uXeKcGTnM/St2BbYV8COI/AAAAAAAABOg/tpJ22P6iaaU/s400/DemoItemRenderer1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5394610236050639074" /&gt;&lt;/a&gt;&lt;br /&gt;Como puede apreciarse, aunque sea un ejemplo sencillo, da alas a multitud de posibilidades, tanto de visualización como de edición.&lt;br /&gt;&lt;br /&gt;El poder de ItemRenderer es poder incrustar en lugar de un item un componente. Esto es, en lugar de una fila en una lista, o de una columna en un DataGrid.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Planteamiento&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;El planteamiento de este componente o, mejor dicho, su utilidad, es poder realizar una lista que nos permita seleccionar un elemento, pero que, dependiendo de su estado, se pueda interactuar de una manera u otra. &lt;br /&gt;&lt;br /&gt;Por ejemplo, imaginemos una lista de frutas asociadas a un pedido. Puede haber frutas que han sido ya entregadas (estado false o no disponibles) y otras que aún no han sido entregadas (estado true o disponibles). De esa lista, es posible quitar frutas para que no sean servidas. Obviamente, aquellas que ya han sido entregadas no podrán quitarse del pedido, y sí aquellas aún no han sido entregadas. Además del dato de estado, una ayuda visual se agradece, indicando con un pequeño icono o algún estilo de texto cuáles están disponibles y cuáles no.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Componente de contenido&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;El componente de contenido será aquel que será renderizado en el item. En nuestro caso será un simple HBox, que contendrá una imagen de 20x20 (en formato png, por las transparencias), y una etiqueta con el texto a visualizar. &lt;br /&gt;&lt;br /&gt;El código de este componente es el siguiente:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_T-uXeKcGTnM/St2ILNxQ1fI/AAAAAAAABOo/wVx7eE-sE24/s1600-h/codeContentComponent1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 386px; height: 400px;" src="http://4.bp.blogspot.com/_T-uXeKcGTnM/St2ILNxQ1fI/AAAAAAAABOo/wVx7eE-sE24/s400/codeContentComponent1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5394617654915945970" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_T-uXeKcGTnM/St2IhP-q7sI/AAAAAAAABOw/8EV3UHHyaos/s1600-h/codeContentComponent2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 197px;" src="http://2.bp.blogspot.com/_T-uXeKcGTnM/St2IhP-q7sI/AAAAAAAABOw/8EV3UHHyaos/s400/codeContentComponent2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5394618033466175170" /&gt;&lt;/a&gt;&lt;br /&gt;Es importante señalar que en una lista la interacción de los datos ha de coordinarse, pues al hacer clic sobre el item, éste también debe retornar la información. Si no fuera así, sólamente sería un elemento decorativo y no se podría seleccionar. Es por ello que se haya sobreescrito (override) los método set data y get data. Cuando la lista comienza a dibujar (render) cada item, utiliza este componente que hemos utilizado, y le pasa (set) los datos. Internamente, cuando recibe los datos, llama al método refresh para pintarlos adecuadamente. Por otro lado, cuando el usuario hace clic sobre el item, éste debe devolverle (get) a la lista los datos para que pueda seleccionarse e interactuar con el código.&lt;br /&gt;&lt;br /&gt;Otra cosa importante a señalar es el uso de la función loadImage:&lt;br /&gt;&lt;code lang="perl"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// This function loads the image&lt;br /&gt;private function loadImage(imgURL:String):void {&lt;br /&gt;  var loader:Loader = new Loader();&lt;br /&gt;  loader.contentLoaderInfo.addEventListener(Event.COMPLETE,&lt;br /&gt;    function (e:Event):void {&lt;br /&gt;      itImage.source=e.currentTarget.content; });&lt;br /&gt;           &lt;br /&gt;  loader.load(new URLRequest(encodeURI(imgURL)));          &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Se le llama con la ruta donde se alojan las imágenes (puede ser en disco duro, o una URL externa, o una referencia desde el directorio raíz). En el ejemplo, se ha creado un directorio "resources" dentro del raíz del código Flex, y por ello se indica en la ruta como "resources/imagen". Esta función es más recomendable que usar simplemente la propiedad source de la imagen, pues además permite recoger la información correspondiente a la imagen si queremos hacer uso de ella.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;LISTA&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;En el ejemplo, se visualizará la lista correspondiente a partir de unos datos almacenados en un ArrayCollection. Estos datos están incrustados en el código, pero podrían ser leídos de un HTTPService o de un servicio Web. &lt;br /&gt;&lt;br /&gt;Los campos de información son los siguientes: &lt;br /&gt;- label: etiqueta o texto a visualizar en la lista&lt;br /&gt;- data: código numérico del producto (no se visualiza)&lt;br /&gt;- state: true/false. Indica la disponibilidad del item&lt;br /&gt;&lt;br /&gt;El código es el siguiente:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_T-uXeKcGTnM/St2L921mShI/AAAAAAAABO4/jUjB-TFIKEU/s1600-h/codeList.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 361px;" src="http://1.bp.blogspot.com/_T-uXeKcGTnM/St2L921mShI/AAAAAAAABO4/jUjB-TFIKEU/s400/codeList.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5394621823468325394" /&gt;&lt;/a&gt;&lt;br /&gt;El punto de inflexión está en la propiedad itemRenderer de la lista, en donde se indica qué componente va a dibujarse en el item de la lista. &lt;br /&gt;&lt;br /&gt;El resultado será, además del visual, el que cuando un usuario seleccione un item de la lista, se mostrará una alerta con los datos del item seleccionado, tal y como muestra la siguiente imagen:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_T-uXeKcGTnM/St2M7KsOFGI/AAAAAAAABPA/RsXYFnknyW4/s1600-h/DemoItemRenderer2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 364px; height: 196px;" src="http://2.bp.blogspot.com/_T-uXeKcGTnM/St2M7KsOFGI/AAAAAAAABPA/RsXYFnknyW4/s400/DemoItemRenderer2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5394622876769719394" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-9182863281314293805?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/9182863281314293805/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=9182863281314293805&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/9182863281314293805'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/9182863281314293805'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/10/flexair-listas-personalizadas-con.html' title='Flex/AIR: Listas personalizadas con ItemRenderer'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_T-uXeKcGTnM/St2BbYV8COI/AAAAAAAABOg/tpJ22P6iaaU/s72-c/DemoItemRenderer1.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-4502152087105649227</id><published>2009-10-18T13:02:00.007+02:00</published><updated>2009-10-18T13:37:42.485+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>Flex/AIR: Teclado virtual avanzado para pantallas táctiles</title><content type='html'>Ya está disponible una nueva versión del teclado virtual para pantallas táctiles, con las siguientes mejoras y cambios:&lt;br /&gt;&lt;br /&gt;- Posibilidad de elegir entre un texto simple (una línea) o un texto multilínea.&lt;br /&gt;- Se ha evitado los estados para hacer más sencilla la recepción del texto, con tan sólo cerrar la ventana.&lt;br /&gt;- La tecla "Aceptar" se ha sustituito por el "Intro" o retorno de carro.&lt;br /&gt;- Se ha agregado el botón "Anular", con el que se anula por completo el texto actual.&lt;br /&gt;- Se puede interactuar con el teclado tradicional, haciendo editable el display. De esta manera, cuando el texto sea más grande que el display, se hará scrolling, accediendo a la zona de edición (en la versión anterior se cortaba, pues sólo se veía el principio).&lt;br /&gt;- Es posible editar texto para su sustitución por un carácter pulsado en el teclado, o por la tecla borrar.&lt;br /&gt;- Es posible especificar el tamaño máximo del texto (número de caracteres).&lt;br /&gt;- Se ha incluido un status en el que se visualiza cuántos caracteres hay escritos y cuántos caracteres se pueden escribir (tamaño máximo del texto).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_T-uXeKcGTnM/Str93g_j3bI/AAAAAAAABOY/YATdgsxEZ9c/s1600-h/keyboard2_multilinea.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 233px;" src="http://2.bp.blogspot.com/_T-uXeKcGTnM/Str93g_j3bI/AAAAAAAABOY/YATdgsxEZ9c/s400/keyboard2_multilinea.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5393902633920748978" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;En la segunda demo, se ha incluído un fondo para ver cómo el teclado utiliza las transparencias con el fondo. Hay una caja de texto simple y una TextArea. La edición de ambas cajas de texto se realiza, simplemente, haciendo click sobre cada una de ellas.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Cajas de texto simple y multilínea&lt;/i&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_T-uXeKcGTnM/Str7uUpZMvI/AAAAAAAABOI/txXfbsErEsk/s1600-h/Keyboard2_1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 250px;" src="http://3.bp.blogspot.com/_T-uXeKcGTnM/Str7uUpZMvI/AAAAAAAABOI/txXfbsErEsk/s400/Keyboard2_1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5393900276964471538" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Teclado virtual avanzado editando multilínea&lt;/i&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_T-uXeKcGTnM/Str8FcW-PSI/AAAAAAAABOQ/7IwRAZqjCkI/s1600-h/keyboard2_2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 250px;" src="http://4.bp.blogspot.com/_T-uXeKcGTnM/Str8FcW-PSI/AAAAAAAABOQ/7IwRAZqjCkI/s400/keyboard2_2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5393900674171682082" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;El código de la demo es el siguiente:&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_T-uXeKcGTnM/Str5l8qOxKI/AAAAAAAABNw/9h0XnvhlPgk/s1600-h/keyboard2_code.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 334px; height: 400px;" src="http://2.bp.blogspot.com/_T-uXeKcGTnM/Str5l8qOxKI/AAAAAAAABNw/9h0XnvhlPgk/s400/keyboard2_code.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5393897934063322274" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;La explicación del código es muy similar a la del ejemplo anterior (mirar &lt;a href="http://rafinguer.blogspot.com/2009/10/flexair-teclado-virtual-para-pantallas.html"&gt;http://rafinguer.blogspot.com/2009/10/flexair-teclado-virtual-para-pantallas.html&lt;/a&gt; para el detalle). Tan sólo añadir que se pasa al componente, a través de la función "setTextType()", el tipo de texto a visualizar: TYPE_SINGLE (opcional) o TYPE_MULTILINE (en caso de querer un texto multilínea). Asimismo, también se especifica el tamaño máximo a editar para el texto, mediante la función "setMaxChars()".&lt;br /&gt;&lt;br /&gt;Otro detalle a considerar es que ahora, al no tener estados o acciones (sólo el cierre de la ventana del teclado), el  evento a gestionar es de tipo "Event.CLOSE", cuya función delegada simplemente ha de obtener el texto (función "getText()") sin necesidad de evaluar estados.&lt;br /&gt;&lt;br /&gt;Para ver la demo en directo: &lt;a href="http://www.tecnillusions.com/demos/DemoKeyboard2/DemoKeyboard2.html"&gt;http://www.tecnillusions.com/demos/DemoKeyboard2/DemoKeyboard2.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Para descargarse el código fuente y el ejecutable: &lt;a href="http://www.tecnillusions.com/demos/DemoKeyboard2/DemoKeyboard2.zip"&gt;http://www.tecnillusions.com/demos/DemoKeyboard2/DemoKeyboard2.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-4502152087105649227?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/4502152087105649227/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=4502152087105649227&amp;isPopup=true' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/4502152087105649227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/4502152087105649227'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/10/flexair-teclado-virtual-mejorado-para.html' title='Flex/AIR: Teclado virtual avanzado para pantallas táctiles'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_T-uXeKcGTnM/Str93g_j3bI/AAAAAAAABOY/YATdgsxEZ9c/s72-c/keyboard2_multilinea.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-2607371315228834165</id><published>2009-10-17T21:40:00.006+02:00</published><updated>2009-10-17T22:42:24.395+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>Flex/AIR: Teclado virtual para pantallas táctiles</title><content type='html'>En esta ocasión no voy a explicar algún detalle sobre alguna técnica concreta, si no que voy a publicar, íntegramente un componente que muestra un teclado virtual que puede ser utilizado en lugar del teclado físico, ya sea con el ratón o bien en una pantalla táctil.&lt;br /&gt;&lt;br /&gt;El teclado es de tipo QWERTY, y tiene tres modos: normal (minúsculas), mayúsculas y símbolos. Incluye también los números.&lt;br /&gt;&lt;br /&gt;Otro detalle importante es que posee transparencia con el fondo y posee efectos especiales al utilizar los botones. ¿Qué más se puede pedir?&lt;br /&gt;&lt;br /&gt;El aspecto que presenta es el siguiente:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Modo normal&lt;/i&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_T-uXeKcGTnM/Stofm1leE7I/AAAAAAAABMo/Ph3Yh2ee8E4/s1600-h/Keyboard1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 228px;" src="http://2.bp.blogspot.com/_T-uXeKcGTnM/Stofm1leE7I/AAAAAAAABMo/Ph3Yh2ee8E4/s400/Keyboard1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5393658255809319858" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Modo Mayúsculas&lt;/i&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_T-uXeKcGTnM/StofwVABiFI/AAAAAAAABMw/zWau07w9baw/s1600-h/Keyboard2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 213px;" src="http://3.bp.blogspot.com/_T-uXeKcGTnM/StofwVABiFI/AAAAAAAABMw/zWau07w9baw/s400/Keyboard2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5393658418861017170" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Modo Símbolo&lt;/i&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_T-uXeKcGTnM/Stof4O3S7oI/AAAAAAAABM4/lRHbQRmDKWg/s1600-h/Keyboard3.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 225px;" src="http://3.bp.blogspot.com/_T-uXeKcGTnM/Stof4O3S7oI/AAAAAAAABM4/lRHbQRmDKWg/s400/Keyboard3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5393658554652749442" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;El modo de utilizarlo es muy sencillo. El código para el ejemplo es el siguiente:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_T-uXeKcGTnM/StonMSlxBOI/AAAAAAAABNA/hiTLAfTR1WM/s1600-h/EjemploKeyboard.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 367px;" src="http://3.bp.blogspot.com/_T-uXeKcGTnM/StonMSlxBOI/AAAAAAAABNA/hiTLAfTR1WM/s400/EjemploKeyboard.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5393666595831743714" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;El ejemplo parte de que el componente está en la misma carpeta que la aplicación. Si no fuese así, habría que hacer el "import" correspondiente. &lt;br /&gt;&lt;br /&gt;El ejemplo es muy sencillo: en una caja de texto escribiremos parte de un texto. Cuando se pulse el botón "Teclado" aparecerá el el teclado virtual con el texto escrito. En ese momento se modificará el texto con este teclado. Al darle al botón "Aceptar", el nuevo texto aparecerá en la caja de texto. Si se cerrase la ventana con el botón de cierre, mostrará un texto indicando que el texto no fue aceptado, y no habrá cambio alguno.&lt;br /&gt;&lt;br /&gt;El componente &lt;b&gt;KeyboardWindow&lt;/b&gt; es un "TitleWindow" o PopUp. Hay que importar la clase PopUpManager y declarar una variable de este tipo KeyboardWindow:&lt;br /&gt;&lt;br /&gt;&lt;font face="courier" size="1"&gt;&lt;br /&gt;import mx.managers.PopUpManager;&lt;br /&gt;import mx.controls.Alert;&lt;br /&gt;         &lt;br /&gt;private var wKeyboard:KeyboardWindow;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Cuando el usuario haga click sobre el botón "Aceptar" se ejecutará la función "showKeyboard()":&lt;br /&gt;&lt;br /&gt;&lt;font face="courier" size="1"&gt;&lt;br /&gt;private function showKeyboard():void {&lt;br /&gt;&amp;nbsp;&amp;nbsp;wKeyboard = KeyboardWindow(PopUpManager.createPopUp(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this, KeyboardWindow, true));&lt;br /&gt;    &lt;br /&gt;&amp;nbsp;&amp;nbsp;wKeyboard.addEventListener(Event.REMOVED, checkText);&lt;br /&gt;&amp;nbsp;&amp;nbsp;PopUpManager.centerPopUp(wKeyboard);&lt;br /&gt;&amp;nbsp;&amp;nbsp;wKeyboard.setText(myText.text);&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;La primera sentencia crea la ventana emergente (PopUp), indicando cual es el contenedor padre (this o la propia aplicación), así como de qué tipo es la ventana hija (KeyboardWindow).&lt;br /&gt;&lt;br /&gt;La segunda sentencia agrega el evento Event.REMOVED que permite escuchar cuándo la ventana emergente se cierra, enviando la ejecución del código a la función checkText.&lt;br /&gt;&lt;br /&gt;La tercer sentencia se encarga de centrar la ventana emergente dentro del contenedor (en nuestro caso, la aplicación).&lt;br /&gt;&lt;br /&gt;La cuarta sentencia le pasa al teclado virtual el texto que tenemos en la caja de texto, para su gestión.&lt;br /&gt;&lt;br /&gt;Por último, queda la función checkText(), cuyo código es el siguiente:&lt;br /&gt;&lt;br /&gt;&lt;font face="courier" size="1"&gt;&lt;br /&gt;private function checkText(e:Event):void {&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (wKeyboard.action==wKeyboard.ACTION_OK)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;myText.text = wKeyboard.getText();&lt;br /&gt;&amp;nbsp;&amp;nbsp;else if (wKeyboard.action==wKeyboard.ACTION_CANCEL)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Alert.show("Texto no aceptado");&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;El componente &lt;b&gt;KeyboardWindow&lt;/b&gt; tiene una variable que contiene el estado o acción realizada antes de cerrar la ventana. Si se hizo click sobre el botón "Aceptar", el estado será ACTION_OK. Si se hizo click sobre el botón de cierre de la ventana, la acción o estado será ACTION_CANCEL. En el primer caso, se recogerá el texto gestionado por el teclado virtual mediante el método getText(), y se colocará en la caja de texto principal. En el segundo caso, se mostrará una alerta indicando que el texto no fue aceptado.&lt;br /&gt;&lt;br /&gt;El aspecto final de este ejemplo es el siguiente:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_T-uXeKcGTnM/StorAuCKboI/AAAAAAAABNI/IHXDbGhk3H0/s1600-h/EjemploKeyboard2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 225px;" src="http://1.bp.blogspot.com/_T-uXeKcGTnM/StorAuCKboI/AAAAAAAABNI/IHXDbGhk3H0/s400/EjemploKeyboard2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5393670795086687874" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Para ejecutar el ejemplo en directo:&lt;br /&gt;&lt;a href="http://www.tecnillusions.com/demos/DemoKeyboard/DemoKeyboard.html"&gt;http://www.tecnillusions.com/demos/DemoKeyboard/DemoKeyboard.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Para descargar el componente y el código fuente:&lt;br /&gt;&lt;a href="http://www.tecnillusions.com/demos/DemoKeyboard/DemoKeyboard.zip"&gt;http://www.tecnillusions.com/demos/DemoKeyboard/DemoKeyboard.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-2607371315228834165?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/2607371315228834165/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=2607371315228834165&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/2607371315228834165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/2607371315228834165'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/10/flexair-teclado-virtual-para-pantallas.html' title='Flex/AIR: Teclado virtual para pantallas táctiles'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_T-uXeKcGTnM/Stofm1leE7I/AAAAAAAABMo/Ph3Yh2ee8E4/s72-c/Keyboard1.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-4946698015934569792</id><published>2009-10-17T13:44:00.000+02:00</published><updated>2009-10-17T13:45:24.255+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OLED'/><title type='text'>¿Razones para apostar por la tecnología OLED?</title><content type='html'>Sólo una:&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/f8S8tbQMp2k&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=es&amp;feature=player_embedded&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/f8S8tbQMp2k&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=es&amp;feature=player_embedded&amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-4946698015934569792?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/4946698015934569792/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=4946698015934569792&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/4946698015934569792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/4946698015934569792'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/10/razones-para-apostar-por-la-tecnologia.html' title='¿Razones para apostar por la tecnología OLED?'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-56104884407558044</id><published>2009-10-16T08:37:00.013+02:00</published><updated>2009-10-16T10:25:19.933+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software'/><title type='text'>Software por la patilla</title><content type='html'>&lt;h1&gt;OFICINA&lt;/h1&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;&lt;a href="http://mindraider.sourceforge.net"&gt;MindRaider:&lt;/a&gt;&lt;/u&gt;&lt;/b&gt; Excelente gestor de ideas, a modo de mapa conceptual. Disponible para Windows y Linux.&lt;br /&gt;&lt;a href="http://mindraider.sourceforge.net/images/MindRaider.title.png"&gt;&lt;img src="http://mindraider.sourceforge.net/images/MindRaider.title.png"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;&lt;a href="http://www.pdfforge.org"&gt;PDF Creator:&lt;/a&gt;&lt;/u&gt;&lt;/b&gt; Permite convertir cualquier documento en formato PDF. Para ello, imprimir el documento seleccionando PDFCreator como impresora. Para Windows.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;MULTIMEDIA&lt;/h1&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;&lt;a href="http://www.gomlab.com/eng"&gt;Gom Player:&lt;/a&gt;&lt;/u&gt;&lt;/b&gt; Fantástico reproductor multimedia para Windows, que incluye la mayor parte de codecs para vídeos y música. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;&lt;a href="http://www.irfanview.com"&gt;Irfanview:&lt;/a&gt;&lt;/u&gt;&lt;/b&gt; Excelente visor de imágenes y reproductor de vídeos, que tiene en su haber el contar con el mayor catálogo de formatos. Para Windows.&lt;br /&gt;&lt;a href="http://www.irfanview.com/images/startbild_engl-small.gif"&gt;&lt;img src="http://www.irfanview.com/images/startbild_engl-small.gif" width="400"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;PROGRAMACION&lt;/h1&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;&lt;a href="http://www.aptana.org"&gt;Aptana Studio:&lt;/a&gt;&lt;/u&gt;&lt;/b&gt; Increíble entorno (IDE) de desarrollo basado en eClipse, y que permite desarrollar en Java, Ruby on Rails, AIR (Adobe), HTML, CSS, Python, PHP, Ajax y Javascript. Disponible en Windows, Linux y Mac.&lt;br /&gt;&lt;a href="http://www.aptana.org/images/img_studio_screenshot.png"&gt;&lt;img src="http://www.aptana.org/images/img_studio_screenshot.png"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;UTILIDADES&lt;/h1&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;&lt;a href="http://www.piriform.com/defraggler"&gt;Defraggler:&lt;/a&gt;&lt;/u&gt;&lt;/b&gt; Una utilidad imprescindible. Permite organizar y ordenar (defragmentar) los datos en el disco duro. A medida que se usa el ordenador, la información se va degradando y haciéndose más lento. Defragmentar el disco permite acceder más rápidamente a la información y realizar menos accesos. Para Windows.&lt;br /&gt;&lt;a href="http://www.piriform.com/media/1683/Defraggler4.png"&gt;&lt;img src="http://www.piriform.com/media/1683/Defraggler4.png" width="400"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;&lt;a href="http://www.winstep.net/default.asp?cat=nexus"&gt;Nexus:&lt;/a&gt;&lt;/u&gt;&lt;/b&gt; Nexus añade un dock al escritorio de Windows. Esto es una herramienta muy útil que permite, entre otras cosas, tener a mano los iconos más utilizados y les permite añadir efectos especiales, o cambiar el aspecto completo del escritorio y de los elementos de ventana (hay varios temas).&lt;br /&gt;&lt;a href="http://www.winstep.net/images/screenshots/ivory.jpg"&gt;&lt;img src="http://www.winstep.net/images/screenshots/ivory.jpg" width="400"&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;&lt;a href="http://www.fbackup.com"&gt;FBackup:&lt;/a&gt;&lt;/u&gt;&lt;/b&gt; Potente y sencilla herramienta para realizar copias de seguridad de cualquier unidad de almacenamiento, permitiendo comprimir la copia y protegerla con contraseña. Para Windows.&lt;br /&gt;&lt;a href="http://www.fbackup.com/screenshots/small/free-backup-software.gif"&gt;&lt;img src="http://www.fbackup.com/screenshots/small/free-backup-software.gif" width="400"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;&lt;a href="http://mbrwizard.com"&gt;MBR Wizard:&lt;/a&gt;&lt;/u&gt;&lt;/b&gt; Utilidad para recuperar el Master Boot Record (o gestor de arranque) del disco duro, en el caso de que esté corrupto, permitiendo definir la partición activa.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;SEGURIDAD&lt;/h1&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;&lt;a href="http://www.avast.com/index_esp.html"&gt;Avast Antivirus Protection:&lt;/a&gt;&lt;/u&gt;&lt;/b&gt; Completa solución contra virus, rookits, troyanos y P2P. La versión gratuita está disponible para Windows y Linux.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;INTERNET&lt;/h1&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;&lt;a href="http://www.opera.com/browser/"&gt;Opera:&lt;/a&gt;&lt;/u&gt;&lt;/b&gt; Para mí, el navegador más innovador de todos, además del más rápido y eficaz, capaz de cargar páginas hechas específicamente para Explorer y para Firefox. Para Windows, Linux, Mac y Mobile.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;&lt;a href="http://www.digsby.com"&gt;Digsby:&lt;/a&gt;&lt;/u&gt;&lt;/b&gt; Cliente de mensajería que permite conectar con todas los protocolos y redes existentes, incluyendo correo electrónico y redes sociales. Todo en uno. Para Windows.&lt;br /&gt;&lt;img src="http://img.digsby.com/tmpl/logo.png"&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-56104884407558044?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/56104884407558044/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=56104884407558044&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/56104884407558044'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/56104884407558044'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/10/software-por-la-patilla.html' title='Software por la patilla'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-3974393337382625538</id><published>2009-10-14T07:32:00.003+02:00</published><updated>2009-10-14T07:34:11.663+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='TI Facturas'/><title type='text'>TI Facturas v2009 ha sido liberado como Freeware</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_T-uXeKcGTnM/StVil8E9lMI/AAAAAAAABMc/CKTuKnSKQaI/s1600-h/Firma.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 343px; height: 192px;" src="http://4.bp.blogspot.com/_T-uXeKcGTnM/StVil8E9lMI/AAAAAAAABMc/CKTuKnSKQaI/s400/Firma.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5392324532767659202" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;b&gt;TI Facturas&lt;/b&gt; ahora es completamente funcional, sin limitaciones &lt;b&gt;Y GRATIS&lt;/b&gt;. Puede descargarse la versión completa con total libertad, y poder utilizarla en entornos de producción y sin limitaciones de tiempo, máquinas o usuarios. Únicamente, no incluye soporte ni garantía, que puede ser contratado de manera opcional.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;TI Facturas&lt;/b&gt; es el software imprescindible e ideal para que cualquier PYME o cualquier trabajador autónomo pueda gestionar de forma sencilla y económica sus presupuestos y facturas. Se ha optimizado al máximo la sencillez del programa, para que empezar a trabajar con él no sea un reto, y que el día a día sea algo natural y no consuma mucho tiempo, el cual se requeriría o se aprovecharía para otras actividades más importantes. &lt;br /&gt;&lt;br /&gt;Para más información y descarga:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.tecnillusions.com/TIFacturas/principal.html"&gt;http://www.tecnillusions.com/TIFacturas/principal.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-3974393337382625538?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/3974393337382625538/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=3974393337382625538&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/3974393337382625538'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/3974393337382625538'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/10/ti-facturas-v2009-ha-sido-liberado-como.html' title='TI Facturas v2009 ha sido liberado como Freeware'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_T-uXeKcGTnM/StVil8E9lMI/AAAAAAAABMc/CKTuKnSKQaI/s72-c/Firma.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-3385603839336790743</id><published>2009-10-13T18:23:00.008+02:00</published><updated>2009-10-13T19:22:20.658+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>Flex/AIR: Reemplazar datos en tiempo de visualización</title><content type='html'>Hay ocasiones en las que ha de tratarse los datos que se van a visualizar. Por ejemplo, imaginemos una tabla en la que se visualiza los datos recogidos de una consulta, pero el valor de cierto campo posee datos que puedan ser ambiguos, tales como un número (códigos, por ejemplo) o valores true/false. Los datos son almacenados así en el origen de datos, pero mostrarlos al usuario puede ocasionarle confusión. En estos casos sería de gran utilidad poder definir qué valores se van a visualizar (como el texto correspondiente a cada código o un texto en lugar de true o false).&lt;br /&gt;&lt;br /&gt;Aunque este post vaya dirigido al DataGrid y el AdvancedDataGrid, sirve también para otros componentes que muestren la información basada en un ArrayCollection, tales como una lista, un combo o un Tree.&lt;br /&gt;&lt;br /&gt;Flex/AIR nos permite controlar el modo en que se van visualizando los datos a partir de la colección de datos. Esto se puede controlar gracias a la propiedad labelFunction, que estos componentes.&lt;br /&gt;&lt;br /&gt;El funcionamiento es muy sencillo. Se indica en esta propiedad el nombre de una función o método que se ejecutará cada vez que trate el dato (en cada fila y columna en el caso de los DataGrid). En la definición del correspondiente DataGridColumn o de AdvancedDataGridColumn (el que contenga la revisión de la información a tratar). Ejemplo:&lt;br /&gt;&lt;br /&gt;&lt;font face="courier" size="1" color="#0000AA"&gt;&lt;br /&gt;&amp;lt;mx:AdvancedDataGridColumn &lt;br /&gt;&amp;nbsp;&amp;nbsp;dataField="product_raw" &lt;br /&gt;&amp;nbsp;&amp;nbsp;labelFunction="replaceValuesColumn"/&amp;gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;La función se definiría así:&lt;br /&gt;&lt;br /&gt;&lt;font face="courier" size="1" color="#0000AA"&gt;&lt;br /&gt;private function replaceValuesColumn(&lt;br /&gt;&amp;nbsp;&amp;nbsp;item:Object, column:AdvancedDataGridColumn):String &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;// Código que tratará cada dato&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;Los parámetros dependerán de cada tipo de componente. En el caso de un DataGrid, el parámetro 'column' será de tipo DataGridColumn. Las listas no tienen este parámetro.&lt;br /&gt;&lt;br /&gt;Esta función se lanzará cada vez que el DataGrid (en este caso) vaya a rellenar esa columna en la fila actual. Aquí se evaluará los valores y, en consecuencia, decidir qué dato visualizar, el cual será indicado en el return de la función en formato String. En nuestro caso, el campo' product_raw' contiene los datos true o false, que indican si el producto es un ingediente o un producto elaborado. &lt;br /&gt;&lt;br /&gt;El código a utilizar dentro en la función 'replaceValuesColumn' (se puede dar el nombre que uno quiera) sería el siguiente:&lt;br /&gt;&lt;br /&gt;&lt;font face="courier" size="1" color="#0000AA"&gt;&lt;br /&gt;private function replaceValuesColumn(&lt;br /&gt;&amp;nbsp;&amp;nbsp;item:Object, column:AdvancedDataGridColumn):String &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var result:String="";&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (item.product_raw==true)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result="Ingrediente";&lt;br /&gt;&amp;nbsp;&amp;nbsp;else if (item.product_raw==false)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result="Elaborado";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return result;&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;Resumiendo: los componentes, a la hora de rellenar cada dato en el componente, permiten utilizar una función para el tratamiento específico de dicho dato. Dicha función evalúa el dato y devuelve el valor que se ha de utilizar para visualizarlo.&lt;br /&gt;&lt;br /&gt;En el caso de un AdvancedDataGrid, si hace uso de un agrupamiento, el tratamiento del item se complica, pues la estructura interna a la hora de agrupar varía. &lt;br /&gt;&lt;br /&gt;Como ejemplo vamos ver el siguiente AdvancedDataGrid:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_T-uXeKcGTnM/StS3Mt1PqEI/AAAAAAAABMU/ibvhHwOnjE0/s1600-h/AdvancedDataGrid.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 391px; height: 400px;" src="http://4.bp.blogspot.com/_T-uXeKcGTnM/StS3Mt1PqEI/AAAAAAAABMU/ibvhHwOnjE0/s400/AdvancedDataGrid.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5392136082958559298" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;En este caso tenemos un agrupamiento por el campo "name_product_type" (tipo de producto), y además un campo resumen (Total). Al depurar la función, veremos que cuando se trata del agrupamiento, se crea un nivel de colección children con los datos del item en su interior, mientras que si trata directamente las filas de datos (ya agrupadas), este nivel no existe. Para tratar este caso, el código a utilizar sería el siguiente:&lt;br /&gt;&lt;br /&gt;&lt;font face="courier" size="1" color="#0000AA"&gt;&lt;br /&gt;private function replaceValuesColumn(&lt;br /&gt;&amp;nbsp;&amp;nbsp;item:Object, column:AdvancedDataGridColumn):String &lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var result:String="";&lt;br /&gt;&amp;nbsp;&amp;nbsp;     &lt;br /&gt;&amp;nbsp;&amp;nbsp;try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (item.product_raw==true)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result="Ingrediente";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else if (item.product_raw==false)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result="Elaborado";&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;catch (e:Error) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (item.children[0].product_raw==true)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result="Ingrediente";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else if (item.children[0].product_raw==false)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result="Elaborado";&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;   &lt;br /&gt;&amp;nbsp;&amp;nbsp;return result;&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-3385603839336790743?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/3385603839336790743/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=3385603839336790743&amp;isPopup=true' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/3385603839336790743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/3385603839336790743'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/10/flexair-reemplazar-datos-en-tiempo-de.html' title='Flex/AIR: Reemplazar datos en tiempo de visualización'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_T-uXeKcGTnM/StS3Mt1PqEI/AAAAAAAABMU/ibvhHwOnjE0/s72-c/AdvancedDataGrid.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-5786511549328542911</id><published>2009-10-12T22:36:00.008+02:00</published><updated>2009-10-12T23:05:22.325+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>Flex/AIR: Estilos personalizados para Alert</title><content type='html'>Los diálogos Alert de Flex/AIR no son componentes propiamente dichos, si no un objeto previamente definido por defecto en la interfaz de usuario, que se muestran como un PopUp. Este tipo de diálogo hereda los mismos atributos de visualización que el contenedor padre que lo invoca.&lt;br /&gt;&lt;br /&gt;Es posible modificar sus atributos mediante CSS, de la siguiente manera:&lt;br /&gt;&lt;br /&gt;&lt;font face="courier" size="1" color="#0000AA"&gt;&lt;br /&gt;&amp;lt;mx:Style&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;.alertTitle{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color:#aaaaff;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fontWeight:bold;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;Alert {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;backgroundColor:#AAAAAA;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;backgroundAlpha: 0.8;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color: #aaaaff;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;borderColor: #000000;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;borderAlpha: 0.8;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;headerHeight:25;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;themeColor: #666666;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;titleStyleName:alertTitle;           &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dropShadowEnabled:true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;shadowDirection:right;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cornerRadius:10;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;lt;/mx:Style&amp;gt;&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;Pero para que funcione, estos estilos no se deben definir desde un componente, si no desde la aplicación principal (Application en el caso de Flex, y WindowedApplication en el caso de AIR). Los estilos definidos aquí para Alert serán válidos para todos los Alert de la aplicación, en cualquier componente contenido.&lt;br /&gt;&lt;br /&gt;Para más información sobre estilos que se pueden aplicar:&lt;br /&gt;&lt;a href="http://www.cristalab.com/tips/personalizar-diseno-del-componente-alert-de-flex-con-css-c47959l/"&gt;http://www.cristalab.com/tips/personalizar-diseno-del-componente-alert-de-flex-con-css-c47959l/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-5786511549328542911?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/5786511549328542911/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=5786511549328542911&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/5786511549328542911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/5786511549328542911'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/10/flexair-estilos-personalizados-para.html' title='Flex/AIR: Estilos personalizados para Alert'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-6371530500183194880</id><published>2009-10-11T21:07:00.002+02:00</published><updated>2009-10-11T22:03:30.365+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Molinux Zero: una pequeña maravilla</title><content type='html'>&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Tengo mi viejo portátil Pentium III con unos 500 Mhz de velocidad, y con apenas 128 MB RAM. Si bien mi inglés es bueno y mis conocimientos sobre Linux son un poco avanzados, he decidido delegar este equipo a mi hija, con 8 años, para que comience a aprender a utilizar el ordenador y usarlo para sus deberes del colegio. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Ya Windows 95 (el sistema original de este equipo) era un poco pesado, y, sobre todo inextable. Windows XP es mejor ni pensarlo, si no quieres morir con sobredosis de cafeína tomando un café entre clic de botón y que empiece a funcionar algo.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;La solución es Linux, con un entorno gráfico y con herramientas de Office y de escritorio con lo que poder empezar a adentrarse en este mundillo. Eso sí: en castellano.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Encontrar una distribución Linux muy, muy ligera, sencilla y por ende en castellano, se convierte en una tarea un tanto difícil. Las opciones son aquellas que tengan un escritorio ligero, tales como FluxBox, XFCE o LXDE. La lista se reduce considerablemente. Xubuntu es una distro que funciona muy bien, y, desde luego, la recomiendo.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Pero probé Molinux Zero, por curiosidad, y me ha encantado por su velocidad y por la cantidad de recursos con los que cuenta, con apenas 100 MB de ISO, y que es un "Puplet" o derivado de la distribución "Puppy". Podéis encontrar esta distro en la siguiente URL:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://ceslcam.com/molinux/ver-categoria.html"&gt;http://ceslcam.com/molinux/ver-categoria.html&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;La distro es un live-CD, que solicitará en su inicio algunos parámetros de configuración, como el idioma, el teclado, la resolución de pantalla, el ratón... Una vez cargado en memoria, impresiona la velocidad a la que se ejecuta, incluso funcionando con un docklet en la parte superior (similar a la del MacOS X), y con unos widgets en la parte derecha, similar a la del Windows Vista.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Tiene multitud de opciones de configuración, así como aplicaciones de escritorio, de red, de seguridad, diseño gráfico, internet, multimedia, etc.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Os recomiendo bajaros y probar on live esta distribución. Merece la pena darle una segunda oportunidad a ese viejo ordenador. &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-6371530500183194880?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/6371530500183194880/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=6371530500183194880&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/6371530500183194880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/6371530500183194880'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/10/molinux-zero-una-pequena-maravilla.html' title='Molinux Zero: una pequeña maravilla'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-6945092394263118040</id><published>2009-10-05T10:36:00.007+02:00</published><updated>2009-10-05T10:52:42.228+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Spectrum'/><title type='text'>Jugar al Spectrum online sin emulador</title><content type='html'>Los nostálgicos estamos de enhorabuena. Por fin podemos jugar a los juegos del Spectrum sin necesidad de instalarnos ningún software emulador, gracias a una pequeña maravilla. En la siguiente URL:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.zxspectrum.net"&gt;http://www.zxspectrum.net&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Podemos encontrar un emulador online realizado en Java, en el que podremos cargar cientos de juegos (a la izquierda) del mítico Spectrum. Además, podemos escribir nuestros programillas en Basic o en ensamblador, pues la consola está disponible. ¿A qué esperas para echarte una pachanga?&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_T-uXeKcGTnM/SsmzSYMWfiI/AAAAAAAABLk/27CJ2y_1Slw/s1600-h/spectrum1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 242px;" src="http://3.bp.blogspot.com/_T-uXeKcGTnM/SsmzSYMWfiI/AAAAAAAABLk/27CJ2y_1Slw/s400/spectrum1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5389035557438783010" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_T-uXeKcGTnM/SsmzYo3jxJI/AAAAAAAABLs/q49WS7QX0yE/s1600-h/spectrum2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 242px;" src="http://1.bp.blogspot.com/_T-uXeKcGTnM/SsmzYo3jxJI/AAAAAAAABLs/q49WS7QX0yE/s400/spectrum2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5389035664994190482" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_T-uXeKcGTnM/SsmzfiAwB3I/AAAAAAAABL0/sxlzC3nCNvU/s1600-h/spectrum3.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 242px;" src="http://2.bp.blogspot.com/_T-uXeKcGTnM/SsmzfiAwB3I/AAAAAAAABL0/sxlzC3nCNvU/s400/spectrum3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5389035783412778866" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_T-uXeKcGTnM/Ssmzk828FVI/AAAAAAAABL8/cYPMS0N2xZo/s1600-h/spectrum4.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 242px;" src="http://3.bp.blogspot.com/_T-uXeKcGTnM/Ssmzk828FVI/AAAAAAAABL8/cYPMS0N2xZo/s400/spectrum4.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5389035876518729042" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_T-uXeKcGTnM/Ssmztt5adoI/AAAAAAAABME/2zIk3fiz3Ls/s1600-h/spectrum5.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 242px;" src="http://4.bp.blogspot.com/_T-uXeKcGTnM/Ssmztt5adoI/AAAAAAAABME/2zIk3fiz3Ls/s400/spectrum5.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5389036027121399426" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-6945092394263118040?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/6945092394263118040/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=6945092394263118040&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/6945092394263118040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/6945092394263118040'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/10/jugar-al-spectrum-sin-emulador.html' title='Jugar al Spectrum online sin emulador'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_T-uXeKcGTnM/SsmzSYMWfiI/AAAAAAAABLk/27CJ2y_1Slw/s72-c/spectrum1.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-5369796240512413941</id><published>2009-10-03T14:06:00.005+02:00</published><updated>2009-10-03T14:32:00.274+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>Flex/AIR: Imágenes en DataGrid</title><content type='html'>El ejemplo que hoy nos ocupa es muy sencillo y no pretende ambiciosos objetivos. Básicamente, permitirá a un DataGrid visualizar una imagen en una determinada celda que va vinculado al valor que lo contiene. Aunque esta entrada esté dedicada a un DataGrid, lo mismo puede aplicarse a las listas.&lt;br /&gt;&lt;br /&gt;Para ilustrar el ejemplo, vamos a ver una captura del resultado final:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_T-uXeKcGTnM/Ssc_Yj_B80I/AAAAAAAABLc/ByNS9uzYTgw/s1600-h/DataGridItemRenderer.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 357px;" src="http://1.bp.blogspot.com/_T-uXeKcGTnM/Ssc_Yj_B80I/AAAAAAAABLc/ByNS9uzYTgw/s400/DataGridItemRenderer.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5388345170381108034" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Como puede observarse, la columna Type (tipo) visualiza el tipo de lote (batch) mediante un simple gráfico: entrada (verde) o salida (rojo).&lt;br /&gt;&lt;br /&gt;No voy a exponer cómo cargar los datos en el DataGrid, pues aquí, lo que nos ocupa es precisamente cómo cargar esas imágenes dependiendo del valor de la columna.&lt;br /&gt;&lt;br /&gt;En este caso, sólo hay dos valores posibles, por lo que en la tabla de la base de datos sólo almacena en el campo "input_batch" los valores true o false, y para los mismos valores se han creado dos imágenes de 20x20, llamadas "true.png" y "false.png".&lt;br /&gt;&lt;br /&gt;Por defecto, los DataGrids y las listas muestran la información en formato texto. Pero Flex/AIR puede permitir representar la información en formato gráfico. Para ellos existen lo que se denominan renderers (presentadores). Existen varios tipos de renderers, como cellRenderer o itemRenderer. Para nuestro ejemplo vamos a utilizar un itemRenderer de forma muy sencilla:&lt;br /&gt;&lt;br /&gt;&amp;lt;mx:DataGrid id="dgBatches" &lt;br /&gt;&amp;nbsp;&amp;nbsp;dataProvider="{batchesList}"&lt;br /&gt;&amp;nbsp;&amp;nbsp;left="18" right="18" top="50" bottom="18"&amp;gt;&lt;br /&gt;   &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;mx:columns&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;mx:DataGridColumn dataField="date" headerText="Date" width="80"/&amp;lt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;mx:DataGridColumn dataField="id_batch" headerText="Batches"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;mx:DataGridColumn dataField="input_batch" headerText="Type" width="50"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;mx:itemRenderer&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;mx:Component&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;mx:HBox width="100%" horizontalAlign="center"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;mx:Image source="/resources/batches/{data.input_batch}.png" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/mx:HBox&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/mx:Component&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/mx:itemRenderer&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/mx:DataGridColumn&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/mx:columns&amp;gt;&lt;br /&gt;&amp;lt;/mx:DataGrid&amp;gt;&lt;br /&gt;&lt;br /&gt;El punto clave está en la columna "input_batch", la cual recoge el tipo de lote (entrada (true) o salida (false). Esta columna contiene un elemento de tipo "itemRenderer", que es el encargado de presentar el valor de dicha celda. En su interior se crea un componente simple, compuesto únicamente por un HBox como contenedor, y como contenido tendrá una imagen que apuntará a la imagen a cargar. En este caso se encuetra en el directorio "/resources/batches/" y el nombre del archivo es el propio valor del campo (data.input_batch" con la extensión ".png".&lt;br /&gt;&lt;br /&gt;Este mismo ejemplo podría servir para cargar imágenes ya predefinidas, en lugar de dos valores únicos de tipo true/false. También podrían residir en una URL concreta en lugar de en el disco duro.&lt;br /&gt;&lt;br /&gt;Los renderers son muy flexibles y potentes, y permiten también introducir elementos de interfaz de usuario, como listas desplegables, campos numéricos, de texto, checkboxes, etc.&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-5369796240512413941?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/5369796240512413941/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=5369796240512413941&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/5369796240512413941'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/5369796240512413941'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/10/flexair-imagenes-en-datagrid.html' title='Flex/AIR: Imágenes en DataGrid'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_T-uXeKcGTnM/Ssc_Yj_B80I/AAAAAAAABLc/ByNS9uzYTgw/s72-c/DataGridItemRenderer.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-704496911840557417</id><published>2009-09-30T19:34:00.007+02:00</published><updated>2009-09-30T21:03:01.753+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>Flex/AIR: Eventos personalizados</title><content type='html'>La dinámica de desarrollo en Flex está orientada a crear componentes independientes lo más atomizado posible, con el fin de componer interfaces ricas de forma ergonómica e independiente, lo que además, permite aislar problemas concretos dentro de las interfaces, además de contribuir a la reutilización de los mismos.&lt;br /&gt;&lt;br /&gt;Para entender un poco mejor el párrafo anterior imaginemos una interfaz típica en la que hay un grid con el conjunto de datos, y además una ficha de registro. Podemos pensar en realizar todo en un mismo contenedor, ya sea en la misma visualización, activando desactivando opciones según se requieran, o bien crear estados para activar o desactivar el modo lista o el modo ficha. &lt;br /&gt;&lt;br /&gt;Para ir un poco más finos, se puede crear un componente lista que se encargue de forma exclusiva de presentar los datos en un DataGrid, y operar con unos filtros para búsquedas más concretas de información. &lt;br /&gt;&lt;br /&gt;Para ser lo más interactivos posibles, habría un botón "Agregar" para añadir un nuevo registro, con lo que presentaría la ficha vacía. Para editar o eliminar un dato concreto, cuando el usuario haga clic sobre una fila determinada se mostraría la ficha con los datos.&lt;br /&gt;&lt;br /&gt;El componente ficha aparecería cuando se pulse el botón "Agregar" en modo edición y vacío. Si se hace clic sobre una fila, aparecería en modo visualización, con la opción de editarlo o eliminarlo. Como acciones tendría "Guardar", "Eliminar", "Cancelar" y "Cerrar". Su objetivo es tratar individualmente los datos de un registro específico.&lt;br /&gt;&lt;br /&gt;El contenedor padre únicamente insertaría estos componentes y realizar las relaciones entre ambos según se requieran, pero los objetivos concretos están dentro de cada componente, y en el caso de depurar, corregir, modificar o agregar funcionalidades, el nivel de aislamiento permite claramente "tocar" sólo la parte responsable.&lt;br /&gt;&lt;br /&gt;Espero que con este planteamiento esté claro la organización de una funcionalidad clásica de tratamiento y gestión de datos. &lt;br /&gt;&lt;br /&gt;Ahora bien, un pensamiento típico para aquel que empieza a desarrollar con componentes es crear las relaciones con elementos (propiedades, variables o métodos) públicos). Esto, además de complicar el desarrollo, la sincronización entre las partes estaría forzada de forma implícita por código, lo que haría un sistema un tanto inestable e inseguro, amén de sacrificado por el esfuerzo que requiere después modificaciones o correcciones. A esto se le denomina acoplamiento fuerte, y todo depende de otras acciones u operaciones.&lt;br /&gt;&lt;br /&gt;Es posible hacer más sencillo este desarrollo realizando un acoplamiento débil, y que no sea todo tan dependiente y preocuparnos de las relaciones cuando deban ocurrir, y de una forma menos forzosa. Para ello, podremos definir nuestros propios eventos en los componentes, y a través de ellos pasar información (como los datos de una fila o la acción a emprender).&lt;br /&gt;&lt;br /&gt;Para empezar, recomiendo utilizar dos clases en ActionScript. La primera de ellas será una clase para almacenar la información que se pasará al evento, como los datos de la fila seleccionada o la acción solicitada por el usuario. Puede declararse en la carpeta o paquete que uno requiera. &lt;br /&gt;&lt;br /&gt;package com.agenda&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;public class Agenda&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public static const ACTION_NEW:int=0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public static const ACTION_SELECT:int=1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public var accion:int;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public var nombre:String;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public var direccion:String;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public var telefono:String;&lt;br /&gt;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public function Agenda()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;accion=ACTION_NEW;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nombre="";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;direccion="";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;telefono="";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public function toString():String&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return "accion:"+accion+"|"+&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nombre+"|"+&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;direccion + "|" +&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;telefono;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Básicamente define los campos, un constructor por defecto (con una carga inicial de datos) y un método toString() que muestra la información de la instancia actual.&lt;br /&gt;&lt;br /&gt;La segunda clase define el evento personalizado, y para ello se crea una clase que hereda de la superclase base Event y, al igual que la otra clase, podemos colgarla del paquete que creamos más oportuno (en este caso en el mismo paquete que la anterior):&lt;br /&gt;&lt;br /&gt;package com.agenda&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;import flash.events.Event;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public class AgendaEvent extends Event&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public var agenda:Agenda;&lt;br /&gt;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public function AgendaEvent(agenda:Agenda, type:String)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super(type);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.agenda=agenda;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public override function clone():Event {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return new AgendaEvent(agenda, type);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;La clase Event es la clase básica para cualquier evento, y por ello, esta clase hereda (extiende) aquella, añadiendo una funcionalidad propia. En primer lugar se crea una propiedad que contiene un objeto de tipo Agenda (definido en la clase anterior), conteniendo la información necesaria. A continuación se crea un constructor especial, en donde se pasa el objeto Agenda a tratar y el tipo de evento a construir (que será de este tipo). El constructor invoca a su superclase indicando este tipo, y asigna la información al objeto Agenda.&lt;br /&gt;&lt;br /&gt;Se sobreescribe el método clone(), el cual crea y devuelve un objeto evento de sí mismo (mejor no entremos en detalle, pero es un punto importante a implementar).&lt;br /&gt;&lt;br /&gt;El siguiente paso será ir al componente que va a generar el evento, en nuestro caso al componente del DataGrid, que es el que contiene la lista de datos. En este componente hay que declarar el evento para que sea visible por el resto de componentes que lo utilicen. Para ello, hay que crear este código justo después del comienzo de la declaración del componente (el contenedor que lo forma. Canvas, HBox, VBox...), que sea el primer código del mismo (no es esencialmente así, pero sí recomendable):&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;br /&gt;&amp;lt;mx:Canvas&lt;br /&gt;   xmlns:mx="http://www.adobe.com/2006/mxml"&lt;br /&gt;   width="450" &lt;br /&gt;   height="400"&lt;br /&gt;   &amp;gt;&lt;br /&gt;&lt;br /&gt;   &amp;lt;!-- EVENTS --&amp;gt;&lt;br /&gt;   &amp;lt;mx:Metadata&amp;gt;&lt;br /&gt;      [Event(name="selectAgenda",type="com.agenda.AgendaEvent")]&lt;br /&gt;      [Event(name="addAgenda",type="com.agenda.AgendaEvent")]&lt;br /&gt;   &amp;lt;/mx:Metadata&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;&lt;br /&gt;&amp;lt;/Canvas&amp;gt;&lt;br /&gt;&lt;br /&gt;El bloque Metadata declara dos eventos para este componente:&lt;br /&gt;- selectAgenda -&gt; cuando el usuario hace clic sobre una fila del DataGrid&lt;br /&gt;- addAgenda -&gt; cuando el usuario hace clic sobre el botón "Agregar"&lt;br /&gt;&lt;br /&gt;Ambos eventos son del tipo AgendaEvent.&lt;br /&gt;&lt;br /&gt;Esta parte sólo declara los eventos, para que sea visible por el componente padre que utiliza a éste (se puede probar a insertar el componente y con Ctrl+Espacio extraer las propiedades y métodos de este componente, donde aparecerán estos dos eventos). En realidad la declaración no hace que se produzcan, pues hay que controlar cuándo y cómo se lanzan estos dos eventos.&lt;br /&gt;&lt;br /&gt;El primero de ellos se lanza cuando el usuario hace clic sobre una fila del DataGrid. Para ello, se captura el evento de la selección:&lt;br /&gt;&lt;br /&gt;&amp;lt;mx:DataGrid id="dgAgenda"&lt;br /&gt;&amp;nbsp;&amp;nbsp;itemClick="selectItemAgenda();"&lt;br /&gt;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;&lt;br /&gt;El código correspondiente para despachar el evento "selectAgenda" es el siguiente:&lt;br /&gt;&lt;br /&gt;private function selectItemAgenda():void&lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;var miAgenda:Agenda = new Agenda();&lt;br /&gt;&amp;nbsp;&amp;nbsp;miAgenda.action = Agenda.ACTION_SELECT;&lt;br /&gt;&amp;nbsp;&amp;nbsp;miAgenda.nombre = dgAgenda.selectedItem.nombre;&lt;br /&gt;&amp;nbsp;&amp;nbsp;miAgenda.direccion = dgAgenda.selectedItem.direccion;&lt;br /&gt;&amp;nbsp;&amp;nbsp;miAgenda.telefono = dgAgenda.selectedItem.telefono;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var e:AgendaEvent = new AgendaEvent(agenda, "selectAgenda");&lt;br /&gt;&amp;nbsp;&amp;nbsp;this.dispatchEvent(e);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Se instancia la clase Agenda para almacenar la información que se va a utilizar en el componente principal o padre. La información se extrae del DataGrid (dgAgenda), de la fila actualmente seleccionada (selectedItem) y de cada uno de los campos definidos en el DataGrid (nombre, direccion y telefono).&lt;br /&gt;&lt;br /&gt;A continuación se crea un objeto de tipo evento AgendaEvent, pasando esta información, y dando el nombre del evento "selectAgenda" que ya fue declarado (bloque MetaData). Por último, se despacha el evento (dispatchEvent), que saltará en el componente padre cuando éste se produzca.&lt;br /&gt;&lt;br /&gt;Para el evento addAgenda el código es similar. Al hacer clic sobre el botón se invoca al método que despachará el evento:&lt;br /&gt;&lt;br /&gt;&amp;lt;mx:Button id="btnAdd" click="addItemAgenda();" /&amp;gt;&lt;br /&gt;&lt;br /&gt;El código a implementar sería el siguiente:&lt;br /&gt;&lt;br /&gt;private function addItemAgenda():void&lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;var agenda:Agenda = new Agenda();&lt;br /&gt;&amp;nbsp;&amp;nbsp;var e:AgendaEvent = new AgendaEvent(agenda, "addAgenda");&lt;br /&gt;&amp;nbsp;&amp;nbsp;this.dispatchEvent(e); &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Cuando el usuario haga clic sobre el botón "Agregar" se creará el evento "addAgenda", que será lanzado hacia los componentes padre que utilicen este componente.&lt;br /&gt;&lt;br /&gt;Ahora queda la parte en que estos eventos son capturados por el componente padre o que contiene a este componente. He de reconocer que me volví un poco loco porque creí que no me funcionaba todo lo anterior, ya que al incrustar el componente del DataGrid dentro del componente principal, al intentar ver los eventos, métodos y propiedaes con Ctrl+Espacio en el editor de Flex, no me aparecía nada. Incluso traté de declarar el evento para lanzar un método simple o lanzar un Alert, pero no funcionaba. Si esto os ocurre os contaré por qué. &lt;br /&gt;&lt;br /&gt;Utilizo un paquete específico para los componentes. Si se ubica un componente en un paquete o carpeta distinto al del componente padre, parece no verlo, aunque se especifique la ruta completa de forma implícita y se vea el componente y aparentemente funciona (recoge datos y los visualiza, e incluso funciona el filtro). Pero los eventos no funcionaban. Al final, he ubicado todos los componentes, tanto padres e hijos en el mismo paquete, y así iba bien. Estoy de acuerdo que esta explicación no puede ser del todo convincente, pero el hecho es que así me funcionó a mi.&lt;br /&gt;&lt;br /&gt;Ahora, en el componente padre, cuando se incrusta el componente hijo, al dar el espacio y al pulsar las teclas Ctrl+Espacio, se verán los eventos declarados y dispuestos para ser utilizados:&lt;br /&gt;&lt;br /&gt;&amp;lt;components:ListaAgenda &lt;br /&gt;&amp;nbsp;&amp;nbsp;selectBatch="doSelectAgenda(event);"&lt;br /&gt;&amp;nbsp;&amp;nbsp;addBatch="doAddAgenda(event);"&lt;br /&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Al enviar el parámetro "event", éste contendrá la información contenida:&lt;br /&gt;&lt;br /&gt;private function doSelectAgenda(e:AgendaEvent):void {&lt;br /&gt;&amp;nbsp;&amp;nbsp;Alert.show("Evento selectAgenda: " + e.agenda.toString());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private function doAddAgenda(e:AgendaEvent):void {&lt;br /&gt;&amp;nbsp;&amp;nbsp;Alert.show("Evento addAgenda: " + e.agenda.toString());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Espero que este tutorial básico sobre eventos personalizados os sea de utilidad.&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-704496911840557417?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/704496911840557417/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=704496911840557417&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/704496911840557417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/704496911840557417'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/09/flexair-eventos-personalizados.html' title='Flex/AIR: Eventos personalizados'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-9203408507606720042</id><published>2009-09-30T15:58:00.014+02:00</published><updated>2009-09-30T19:26:57.616+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>Flex/AIR: filtros de datos</title><content type='html'>Es muy habitual tener una colección de datos en nuestras interfaces de usuario. Cuando ésta es muy numerosa, es conveniente facilitar al usuario de medios para poder acceder más rápida y directa a una información concreta, y para ello se aplican filtros.&lt;br /&gt;&lt;br /&gt;En el ejemplo que voy a exponer utilizaré un DataGrid, que es uno de los elementos de interfaz más utilizados para presentar colecciones de datos. Lo mismo puede aplicarse a otros elementos de interfaz, como las listas o AdvancedDataGrids.&lt;br /&gt;&lt;br /&gt;Antes de iniciar el cómo vamos realizar un planteamiento. La mayor parte de las veces, los datos provendrán de fuentes externas o remotas, como un fichero, un HTTPService o un WebService. La invocación a un servicio de datos remoto, normalmente se obtiene en formato e4x, para poder trabajar cómodamente en XML. Pero este sistema carece de la cualidad de filtrar o realizar búsquedas concretas. Se puede realizar filtros manualmente e invocar a los servicios de datos con los parámetros del filtro, pero esto implicaría desperdiciar muchos recursos, ya que cada filtrado es una invocación remota (una llamada a un servicio remoto), con el tiempo que esto conlleva, ejecutar el código de invocación, carga y visualización de datos. &lt;br /&gt;&lt;br /&gt;Así pues, nos queda otra opción: obtener la información y almacenarlo en un ArrayCollection, que posee métodos para filtrado y que puede ser enlazado a elementos de interfaz de usuario. En este caso, los datos son los mismos que en la primera carga, e internamente, en memoria, se realiza el filtrado, por lo que es mucho más óptimo en recursos (tiempo, ejecuciones, memoria, etc.)&lt;br /&gt;&lt;br /&gt;Para ello, se define un ArrayCollection en la región dedicado al ActionScript (&amp;lt;mx:Script&amp;gt;...&amp;lt;/mx:Script&amp;gt;):&lt;br /&gt;&lt;br /&gt;[Bindable]&lt;br /&gt;private var miAC:ArrayCollection;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;En este post se pondrá un ejemplo con un HTTPService, que es el método más habitual de obtener la información. Recordemos que HTTPService invoca a una URL donde se retornará una fichero XML formado con un nodo padre y con varios hijos en forma de lista (cada uno como un registro o fila del DataGrid). Esta invocación puede realizarse a una página ASP, JSP, PHP, Servlet, etc, que en lugar de retornar una página web retorne un XML. También puede ser una URL con un fichero XML.&lt;br /&gt;&lt;br /&gt;&amp;lt;mx:HTTPService &lt;br /&gt;&amp;nbsp;&amp;nbsp;result="handleResultMetodo(event);"&lt;br /&gt;&amp;nbsp;&amp;nbsp;fault="handleFaultMetodo(event);" &lt;br /&gt;&amp;nbsp;&amp;nbsp;id="nombreServicio" resultFormat="object"&lt;br /&gt;&amp;nbsp;&amp;nbsp;url="URLHTTPService"&lt;br /&gt;&amp;nbsp;&amp;nbsp;useProxy="false"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;mx:request xmlns=""&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;nombreParametro&amp;gt;valorParametro&amp;lt;/nombreParametro&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/mx:request&amp;gt;&lt;br /&gt;&amp;lt;/mx:HTTPService&amp;gt;&lt;br /&gt;&lt;br /&gt;Los parámetros a utilizar son:&lt;br /&gt;- result -&gt; Nombre del método que gestionará el resultado de la invocación&lt;br /&gt;- fault -&gt; Nombre del método que se ejecutará en caso de haber un error en la invocación&lt;br /&gt;- id -&gt; Nombre que se da al servicio&lt;br /&gt;- url -&gt; URL donde se encuentra el XML (ASP, JSP, PHP, Servlet, fichero XML...)&lt;br /&gt;- resultFormat -&gt; Formato del resultado. En este caso se ha usado un tipo "object" para que sea recogido por el ArrayCollection. En casos normales se utiliza el formato "e4x" que permite gestionar cómodamente cualquier XML.&lt;br /&gt;&lt;br /&gt;El bloque mx:request es opcional, y se utiliza en el caso de que el recurso XML requiera de parámetros de entrada para formar el XML resultante.&lt;br /&gt;&lt;br /&gt;En algún momento determinado del ciclo de vida de la aplicación, se invocará al HTTPService para recoger el XML con los datos. Habitualmente se realiza en el método creationComplete de la aplicación, o del componente Flex. En algunas ocasiones se realiza en respuesta a algún evento (como un clic sobre un botón). El código que realiza la invocación sería el siguiente:&lt;br /&gt;&lt;br /&gt;nombreServicio.send();&lt;br /&gt;&lt;br /&gt;Una vez invocado el servicio HTTPService generará un resultado (en caso de ir bien) o bien un error (en caso de ir mal). En ambos casos se invocará a los métodos respectivos declarados:&lt;br /&gt;&lt;br /&gt;private function handleResultMetodo(event:ResultEvent):void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;miAC = event.result.elementoPadre.elementoHijo;&lt;br /&gt;}&lt;br /&gt;   &lt;br /&gt;private function handleFaultMetodo(event:FaultEvent):void&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;Alert.show(event.fault.faultString, "ERROR");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Cuando la invocación ha sido exitosa se ejecutará el primer método, pasando en el parámetro "event" el resultado del XML. Para agregar este XML en el ArrayCollection, hay que acceder a la propiedad "result" del mismo, e indicar cuál es el elemento padre y cuál el elemento hijo (registro o fila). Por ejemplo, un XML con esta estructura:&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="ISO-8859-1" ?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;producto&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;item&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;codigo&amp;gt;1&amp;lt/codigo&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;nombre&amp;gt;Boligrafo negro&amp;lt/nombre&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;precio&amp;gt;1.25&amp;lt/nombre&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/item&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;item&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;codigo&amp;gt;2&amp;lt/codigo&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;nombre&amp;gt;Boligrafo azul&amp;lt/nombre&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;precio&amp;gt;1.50&amp;lt/nombre&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/item&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;item&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;codigo&amp;gt;3&amp;lt/codigo&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;nombre&amp;gt;Boligrafo rojo&amp;lt/nombre&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;precio&amp;gt;1.75&amp;lt/nombre&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/item&amp;gt;&lt;br /&gt;&amp;lt;producto/&amp;gt;&lt;br /&gt;&lt;br /&gt;El elemento padre sería "producto", y el elemento hijo sería "item". El ArrayCollection contendría 3 registros (uno por cada elemento hijo), y cada uno de estos registros sería una fila en el DataGrid.&lt;br /&gt;&lt;br /&gt;El ArrayCollection está cargado en este momento con la información. El ArrayCollection definido es enlazable (tiene la propiedad Bindable), lo que permite o un control visual, como un DataGrid o un List, enlazarse a los datos de este ArrayCollection, y cada cambio en áquel actualiza automáticamente los datos del control.&lt;br /&gt;&lt;br /&gt;El DataGrid se define así:&lt;br /&gt;&lt;br /&gt;&amp;lt;mx:DataGrid &lt;br /&gt;&amp;nbsp;&amp;nbsp;id="miDataGrid"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;DataProvider="{miAC}"&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;ltmx:DataGridColumn dataField="codigo" headerText="CODIGO" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;ltmx:DataGridColumn dataField="nombre" headerText="NOMBRE" /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;ltmx:DataGridColumn dataField="precio" headerText="PRECIO" /&amp;gt;&lt;br /&gt;&amp;lt;/mx:DataGrid&amp;gt;&lt;br /&gt;&lt;br /&gt;El control DataGrid es un control de datos en forma de tabla. El atributo "id" define el nombre para el DataGrid. El elemento "DataProvider" indica al DataGrid de dónde debe obtener los datos. En este caso, se indica entre llaves el nombre del ArrayCollection para que se lleve a cabo el enlace automático.&lt;br /&gt;&lt;br /&gt;El DataGrid tiene tres columnas, que se definen con "DataGridColumn". El atributo "dataField" especifica el campo de donde va a obtener el valor ("codigo", "nombre" o "precio", definidos en el XML). El atributo "headerText" define el título que aparecerá en la cabecera superior de cada columna.&lt;br /&gt;&lt;br /&gt;Ahora viene la parte interesante, y es el filtro. Para ello, se definen controles de usuario, como una caja de texto, una lista desplegable o un calendario para obtener una fecha. En cualquiera de los casos utilizados, se ha de invocar a una método cuando el valor de estos controles cambia (el que aplique según el caso). En este caso, vamos a poner que haya sido un campo de texto y un botón de anulación:&lt;br /&gt;&lt;br /&gt;&amp;lt;mx:TextInput id="txtBuscar" change="buscarMetodo()" /&amp;gt;&lt;br /&gt;&amp;lt;mx:Button label="Reiniciar" click="reiniciarMetodo()" /&amp;gt;&lt;br /&gt;&lt;br /&gt;En el caso de que se introduzca un carácter en la caja de texto se producirá un cambio, que recogerá el evento "change", y aquí le indicamos que ejecute el método &lt;br /&gt;buscarMetodo(), el cual contiene el siguiente código:&lt;br /&gt;&lt;br /&gt;private function buscarMetodo():void {&lt;br /&gt;&amp;nbsp;&amp;nbsp;miAC.filterFunction = filtroMetodo;&lt;br /&gt;&amp;nbsp;&amp;nbsp;miAC.refresh();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;El ArrayCollection tiene una propiedad que se encarga de la gestión de filtrado de los datos que contiene. Para ello, delega en un método que especifica cómo llevar a cabo este filtrado, y el cual, su nombre se especifica a esta propiedad, en este caso, "filtroMetodo". Este método contendrá el siguiente código:&lt;br /&gt;&lt;br /&gt;private function filtroMetodo(item:Object):Boolean{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var encontrado:Boolean = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if(item.nombre.toLowerCase().search(txtBuscar.text.toLowerCase()) != -1){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;encontrado = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}               &lt;br /&gt;&amp;nbsp;&amp;nbsp;return encontrado;               &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;El ArrayCollection ejecutará este método por cada fila que contiene, enviando en el objeto "item" la fila que se está procesando. Aquí se compara la fila ("item") y el campo a comparar (en este caso "nombre"), anmbos igualados en minúsculas. En caso de que case esta comparación se retorna un valor true (se muestra) o en caso contrario retorna un valor false (no se muestra).&lt;br /&gt;&lt;br /&gt;Otra forma de comparación sería así:&lt;br /&gt;&lt;br /&gt;private function filtroMetodo(item:Object):Boolean{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var encontrado:Boolean = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var filter:String = item["nombre"];  // valor del campo "nombre"&lt;br /&gt;&amp;nbsp;&amp;nbsp;if(filter.toLowerCase().indexOf(txtBuscar.text.toLowerCase())&lt;0){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;encontrado = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}               &lt;br /&gt;&amp;nbsp;&amp;nbsp;return encontrado;               &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Una vez se ha procesado todas las filas e identificadas cuáles cumplen los requisitos del filtro, la siguiente sentencia:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;miAC.refresh();&lt;br /&gt;&lt;br /&gt;Para anular los filtros y que el ArrayCollection (y por ende, el DataGrid) contenga toda la información, hay que anular la propiedad "filterFunction" y refrescar el Arraycollection:&lt;br /&gt;&lt;br /&gt;private function reiniciarMetodo():void {&lt;br /&gt;&amp;nbsp;&amp;nbsp;miAC.filterFunction = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;miAC.refresh();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Refresca o actualiza el contenido del ArrayCollection, propagándose automáticamente hacia el DataGrid que actualizará la información a mostrar.&lt;br /&gt;&lt;br /&gt;Un ejemplo muy sencillo es el siguiente:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&amp;lt;?xml version=&lt;span style="color: #0000ff"&gt;"1.0"&lt;/span&gt; encoding=&lt;span style="color: #0000ff"&gt;"utf-8"&lt;/span&gt;?&amp;gt;&lt;br /&gt; &lt;span style='color: #000080'&gt;&amp;lt;mx:Application xmlns:mx=&lt;span style="color: #0000ff"&gt;"&lt;a target="_blank" href="http://www.adobe.com/2006/mxml"&gt;http://www.adobe.com/2006/mxml&lt;/a&gt;"&lt;/span&gt; layout=&lt;span style="color: #0000ff"&gt;"vertical"&lt;/span&gt; creationComplete=&lt;span style="color: #0000ff"&gt;"initData()"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;     &lt;span style='color: #000080'&gt;&amp;lt;mx:Script&amp;gt;&lt;/span&gt;&lt;br /&gt;         &amp;lt;![CDATA[&lt;br /&gt;             import mx.collections.ArrayCollection;&lt;br /&gt;            [Bindable]&lt;br /&gt;            private var dataList:ArrayCollection ; &lt;br /&gt;            &lt;br /&gt;            private function initData():void{&lt;br /&gt;             dataList= new ArrayCollection([&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Atlantic City Medical Center-City Division"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Atlantic City"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Atlantic City Medical Center-Mainland Division"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Pomona "&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Barnert Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Paterson"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Bayonne Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Bayonne"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Bayshore Community Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Holmdel"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Bergen Regional Medical Center. L.P."&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Paramus"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Burdette Tomlin Memorial Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Cape May"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Capital Health System - Fuld Campus"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Trenton"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Capital Health System - Mercer Campus"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Trenton"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"CentraState Healthcare System"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Freehold"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Chilton Memorial Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Pompton Plains"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Christ Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Jersey City"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Clara Maass Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Belleville"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Columbus Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Newark"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Community Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Toms River"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"East Orange General Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"East Orange"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Englewood Hospital and Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Englewood"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Hackensack University Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Hackensack"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Hackettstown Community Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Hackettstown"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Holy Name Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Teaneck"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Hospital Center at Orange"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Orange"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Hunterdon Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Flemington"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Irvington General Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Irvington"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Jersey Shore University Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Neptune"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"JFK Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Edison"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Kennedy Memorial Hospitals/UMC Cherry Hill"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Cherry Hill"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Kennedy Memorial Hospitals/UMC Stratford"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Stratford"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Kennedy Memorial Hospitals/UMC Washington Twp"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Turnersville"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Kessler Memorial Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Hammonton"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Kimball Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Lakewood"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"LibertyHealth-Greenville Hospital Campus"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Jersey City"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"LibertyHealth-Jersey City Medical Center Campus"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Jersey City"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"LibertyHealth-Meadowlands Hospital Campus"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Secaucus"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Lourdes Medical Center of Burlington County"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Willingboro"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Monmouth Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Long Branch"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"MONOC"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Eatontown"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Morristown Memorial Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Morristown"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Muhlenberg Regional Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Plainfield"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Newark Beth Israel Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Newark"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Newton Memorial Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Newton"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Ocean Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Brick"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Our Lady of Lourdes Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Camden"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Overlook Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Summit"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Palisades Medical Center-New York Presbyterian "&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"North Bergen"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Pascack Valley Hospital "&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Westwood"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"PBI Regional Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Passaic"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Raritan Bay Medical Center - Old Bridge"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Old Bridge"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Raritan Bay Medical Center - Perth Amboy"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Perth Amboy"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Riverview Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Red Bank"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Robert Wood Johnson Univ Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"New Brunswick"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Robert Wood Johnson Univ Hospital at Hamilton"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Hamilton"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Robert Wood Johnson Univ Hospital at Rahway"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Rahway"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Saint Barnabas Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Livingston"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Saint Clares Hospital/Boonton Township"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Boonton"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Saint Clares Hospital/Denville"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Denville"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Saint Clares Hospital/Sussex"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Sussex"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Saint James Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Newark"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Saint Michaels Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Newark"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Saint Peters University Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"New Brunswick"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Shore Memorial Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Somers Point"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Somerset Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Somerville"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"South Jersey Healthcare-Bridgeton Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Bridgeton"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"South Jersey Healthcare-Elmer Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Elmer"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"South Jersey Healthcare-Newcomb Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Vineland"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Southern Ocean County Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Manahawkin"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"St. Francis Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Trenton"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"St. Josephs Regional Medical Center"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Paterson"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"St. Josephs Wayne Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Wayne"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"St. Mary Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Hoboken"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"St. Marys Hospital Passaic"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Passaic"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Summit Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Summit"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"The Cooper Health System"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Camden"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"The Memorial Hospital of Salem County"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Salem"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"The Mountainside Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Montclair"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"The Valley Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Ridgewood"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Trinitas Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Elizabeth"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Underwood-Memorial Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Woodbury "&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Union Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Union"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"University Medical Center at Princeton"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Princeton"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"University of Medicine &lt;strong&gt;&lt;em&gt;&amp;amp;amp;&lt;/em&gt;&lt;/strong&gt; Dentistry of NJ-Univ Hosp"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Newark"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Virtua Memorial Hospital Burlington County"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Mount Holly"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Virtua West Jersey Hospital-Berlin"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Berlin"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Virtua West Jersey Hospital-Marlton"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Marlton"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Virtua West Jersey Hospital-Voorhees"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Voorhees"&lt;/span&gt;},&lt;br /&gt;             {name:&lt;span style="color: #0000ff"&gt;"Warren Hospital"&lt;/span&gt;, city:&lt;span style="color: #0000ff"&gt;"Phillipsburg"&lt;/span&gt;}&lt;br /&gt;            ]) &lt;br /&gt;            }&lt;br /&gt;            &lt;br /&gt;            private function filterDemo():void{&lt;br /&gt;                dataList.filterFunction = searchDemo;&lt;br /&gt;                dataList.refresh();&lt;br /&gt;            }&lt;br /&gt;            &lt;br /&gt;            private function searchDemo(item:Object):Boolean{&lt;br /&gt;                var isMatch:Boolean = false&lt;br /&gt;                if(item.name.toLowerCase().search(search.text.toLowerCase()) != -1){&lt;br /&gt;                    isMatch = true&lt;br /&gt;                }               &lt;br /&gt;                return isMatch;               &lt;br /&gt;            }&lt;br /&gt;            &lt;br /&gt;            private function clearSearch():void{&lt;br /&gt;                dataList.filterFunction = null;&lt;br /&gt;                dataList.refresh();&lt;br /&gt;                search.text = '';&lt;br /&gt;            }&lt;br /&gt;         ]]&amp;gt;&lt;br /&gt;     &lt;span style='color: #000080'&gt;&amp;lt;/mx:Script&amp;gt;&lt;/span&gt;&lt;br /&gt;          &lt;span style='color: #000080'&gt;&amp;lt;mx:Form&amp;gt;&lt;/span&gt;&lt;br /&gt;             &lt;span style='color: #000080'&gt;&amp;lt;mx:FormItem label=&lt;span style="color: #0000ff"&gt;"Search"&lt;/span&gt; direction=&lt;span style="color: #0000ff"&gt;"horizontal"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color: #000080'&gt;&amp;lt;mx:TextInput id=&lt;span style="color: #0000ff"&gt;"search"&lt;/span&gt; change=&lt;span style="color: #0000ff"&gt;"filterDemo()"&lt;/span&gt; /&amp;gt;&lt;/span&gt; &lt;br /&gt;                &lt;span style='color: #000080'&gt;&amp;lt;mx:Button label=&lt;span style="color: #0000ff"&gt;"Clear Search"&lt;/span&gt; click=&lt;span style="color: #0000ff"&gt;"clearSearch()"&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;br /&gt;             &lt;span style='color: #000080'&gt;&amp;lt;/mx:FormItem&amp;gt;&lt;/span&gt; &lt;br /&gt;          &lt;span style='color: #000080'&gt;&amp;lt;/mx:Form&amp;gt;&lt;/span&gt;&lt;br /&gt;          &lt;span style='color: #000080'&gt;&amp;lt;mx:DataGrid dataProvider=&lt;span style="color: #0000ff"&gt;"{dataList}"&lt;/span&gt; width=&lt;span style="color: #0000ff"&gt;"400"&lt;/span&gt; height=&lt;span style="color: #0000ff"&gt;"400"&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;             &lt;span style='color: #000080'&gt;&amp;lt;mx:columns&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color: #000080'&gt;&amp;lt;mx:DataGridColumn headerText=&lt;span style="color: #0000ff"&gt;"Name"&lt;/span&gt; dataField=&lt;span style="color: #0000ff"&gt;"name"&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;br /&gt;                &lt;span style='color: #000080'&gt;&amp;lt;mx:DataGridColumn headerText=&lt;span style="color: #0000ff"&gt;"City"&lt;/span&gt; dataField=&lt;span style="color: #0000ff"&gt;"city"&lt;/span&gt; /&amp;gt;&lt;/span&gt; &lt;br /&gt;             &lt;span style='color: #000080'&gt;&amp;lt;/mx:columns&amp;gt;&lt;/span&gt; &lt;br /&gt;          &lt;span style='color: #000080'&gt;&amp;lt;/mx:DataGrid&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt; &lt;span style='color: #000080'&gt;&amp;lt;/mx:Application&amp;gt;&lt;/span&gt;&lt;br /&gt; &lt;/div&gt;&lt;br /&gt;&lt;br /&gt;En este caso, la información está en el propio código (por eso es tan extenso), y se carga directamente en el ArrayCollection sin usar un HTTPService. Pero el objetivo principal era demostrar el uso de los filtros.&lt;br /&gt;&lt;br /&gt;Este ejemplo (el último) está en el siguiente enlace: &lt;a href="http://www.boyzoid.com/blog/index.cfm/2006/10/19/Filtering-Data-in-Flex"&gt;http://www.boyzoid.com/blog/index.cfm/2006/10/19/Filtering-Data-in-Flex&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Para terminar, indicar que los dos ejemplos expuestos anteriormente se han basado en un único campo, pero lo más normal es que un filtro pueda tener varios campos y se combinen entre sí. &lt;br /&gt;&lt;br /&gt;A continuación voy a poner un ejemplo (no completo, si no únicamente en lo que concierne a este punto), con dos campos: uno en una combo y otro en un calendario.&lt;br /&gt;&lt;br /&gt;El primero filtra un tipo de lotes. Sus valores pueden ser: * (todos), "I" (entrada o true) y "O" (salida o false).&lt;br /&gt;&lt;br /&gt;Los dos campos de filtro, invocan a sus respectivos métodos cuando cambian su valor:&lt;br /&gt;&lt;br /&gt;// User click on combo type of batch&lt;br /&gt;private function changeType():void {&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (cboTipoLote.value!="*" || datLote.text!=null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.batchesList.filterFunction=filterBatches;&lt;br /&gt;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.batchesList.filterFunction=null;&lt;br /&gt;         &lt;br /&gt;&amp;nbsp;&amp;nbsp;this.batchesList.refresh();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// User change date on date field &lt;br /&gt;private function changeDate():void {&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (cboTipoLote.value!="*" || datLote.text!=null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.batchesList.filterFunction=filterBatches;&lt;br /&gt;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.batchesList.filterFunction=null;&lt;br /&gt;         &lt;br /&gt;&amp;nbsp;&amp;nbsp;this.batchesList.refresh();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;El ArrayCollection está definido en "batchesList". &lt;br /&gt;&lt;br /&gt;El método delegado para el filtrado es el siguiente:&lt;br /&gt;&lt;br /&gt;// Filter of batches&lt;br /&gt;private function filterBatches(item:Object):Boolean&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var match:Boolean = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;var sDate:String="";&lt;br /&gt;&amp;nbsp;&amp;nbsp;var sType:String="";&lt;br /&gt;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;if (cboTipoLote.value=="I")&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sType="true";&lt;br /&gt;&amp;nbsp;&amp;nbsp;else if (cboTipoLote.value=="O")&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sType="false";&lt;br /&gt;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sType="";&lt;br /&gt;      &lt;br /&gt;&amp;nbsp;&amp;nbsp;if (datLote.text !="") {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sDate =""+datLote.selectedDate.fullYear +"-";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var vValue:String=""+(datLote.selectedDate.month+1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (vValue.length==1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vValue = "0" + vValue;&lt;br /&gt;           &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sDate+= vValue + "-";&lt;br /&gt;   &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vValue = ""+(datLote.selectedDate.date);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (vValue.length==1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vValue = "0" + vValue;&lt;br /&gt;              &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sDate += vValue;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sDate = "";&lt;br /&gt;         &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var filter1:String = item["input_batch"];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var filter2:String = item["date"];&lt;br /&gt;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (sDate!="" &amp;&amp; sType=="") {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!filter2 || filter2.indexOf(sDate)&lt;0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;match=false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else if (sDate=="" &amp;&amp; sType!="") {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!filter1 || &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;filter1.toLowerCase().indexOf(sType.toLowerCase())&lt;0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;match=false;   &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (!filter1 || &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;filter1.toLowerCase().indexOf(sType.toLowerCase())&lt;0 ||&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;!filter2 || filter2.indexOf(sDate)&lt;0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;match=false;   &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;        &lt;br /&gt;&amp;nbsp;&amp;nbsp;return match;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;En este caso se contemplan 3 casos:&lt;br /&gt;1) Se ha facilitado tipo pero no fecha&lt;br /&gt;2) Se ha facilitado fecha pero no tipo&lt;br /&gt;3) Se han facilitado tipo y fecha&lt;br /&gt;&lt;br /&gt;Espero que estos ejemplos sean claros y útiles para desarrollar aplicaciones AIR y Flex más interactivas y optimizadas.&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-9203408507606720042?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/9203408507606720042/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=9203408507606720042&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/9203408507606720042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/9203408507606720042'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/09/flexair-filtros-de-datos.html' title='Flex/AIR: filtros de datos'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-3824934020812610928</id><published>2009-09-25T19:24:00.004+02:00</published><updated>2009-09-25T21:27:43.935+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='J2EE'/><category scheme='http://www.blogger.com/atom/ns#' term='PostgreSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Tomcat'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><category scheme='http://www.blogger.com/atom/ns#' term='Bases de Datos'/><title type='text'>Configurar NetBeans, Tomcat y un pool de conexiones a PostgreSQL</title><content type='html'>Este post va dedicado a crear un entorno de desarrollo para aplicaciones web, utilizando el lenguaje Java, la base de datos PostgreSQL y el IDE NetBeans. No me voy a detener en la instalación y configuración de Java ni de PostgreSQL, si no en el entorno en concreto.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;B&gt;&lt;U&gt;PREPARATIVOS&lt;/U&gt;&lt;/B&gt;&lt;br /&gt;El ejemplo que se ilustra aquí utiliza PostgreSQL 8.3 (&lt;a href="http://www.postgresql.org"&gt;http://www.postgresql.org&lt;/a&gt;, Java v6u14 (&lt;a href="http://java.sun.com"&gt;http://java.sun.com&lt;/a&gt;), Tomcat 6.0.20 (&lt;a href="http://tomcat.apache.org"&gt;http://tomcat.apache.org&lt;/a&gt;) y NetBeans 6.7.1 (&lt;a href="http://www.netbeans.org"&gt;http://www.netbeans.org&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;En primer lugar ha de estar instalado el SDK de Java y la base de datos PostgreSQL.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;B&gt;&lt;U&gt;TOMCAT&lt;/B&gt;&lt;/U&gt;&lt;br /&gt;Ahora, para instalar Tomcat, es preferible descomprimir la versión no instalable, ya que incorpora los archivos catalina.bat y catalina.sh, los cuales son gestionados por NetBeans para lanzar y depurar las aplicaciones. Yo recomiendo, para los usuarios de Windows, instalarlo en el directorio raíz del disco duro, pues en Windows Vista, Windows 7 y Windows Server 2008 utiliza el perfil de usuario para gestiones propias del entorno de sesión, y podría no funcionar.&lt;br /&gt;&lt;br /&gt;Una vez instalado Tomcat, acceder al archivo conf/tomcat-users.xml y añadir el usuario administrador y el usuario manager:&lt;br /&gt;&lt;br /&gt;&amp;lt;user username="admin" password="admin" roles="tomcat"/&amp;gt;&lt;br /&gt;&amp;lt;user username="manager" password="manager" roles="manager"/&amp;gt;&lt;br /&gt;&lt;br /&gt;El siguiente paso es descargarse el driver jdbc de PostgreSQL, el cual puede ser descargado de &lt;a href="http://jdbc.postgresql.org"&gt;http://jdbc.postgresql.org&lt;/a&gt;. Descargar el driver correspondiente a &lt;b&gt;jdbc3&lt;/b&gt;. Una vez descargado el archivo .jar, copiar éste en el directorio lib de Tomcat.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;B&gt;&lt;U&gt;NETBEANS&lt;/U&gt;&lt;/B&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Configuración del servidor&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Una vez instalado NetBeans, hay que agregar el servidor Tomcat. Para ello:&lt;br /&gt;- Menú "Tools" + Opción "Servers"&lt;br /&gt;- Botón "Add Server..." (parte inferior izquierda)&lt;br /&gt;- Seleccionar de la lista "Tomcat 6.0" y botón "Next"&lt;br /&gt;- En el campo "Server Location", hacer clic en el botón "Browse..." y seleccionar la carpeta donde se aloja Tomcat.&lt;br /&gt;- En el campo "Username" ingresar el nombre del usuario "manager"&lt;br /&gt;- En el campo "Password" ingresar la contraseña del usuario "manager"&lt;br /&gt;- Botón "Finish"&lt;br /&gt;&lt;br /&gt;El servidor se habrá agregado a la lista de servidores configurados. Al seleccionar este servidor, aparecerán sus propiedades a la derecha. Clic en el botón "Close".&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Crear proyecto web&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Vamos a crear un proyecto web para configurar el pool de conexiones y mostrar un ejemplo de conexión:&lt;br /&gt;- Menú "File" + opción "New Project..."&lt;br /&gt;- En la lista "Categories" seleccionar "Java Web", y en la lista "Projects" seleccionar "Web Application"&lt;br /&gt;- Botón "Next"&lt;br /&gt;- En el campo "Project Name" dar el nombre del proyecto, por ejemplo "Prueba".&lt;br /&gt;- Botón "Next"&lt;br /&gt;- En el campo "Server" seleccionar "Tomcat 6.0"&lt;br /&gt;- Botón "Finish"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Referencia a la librería de PostgreSQL&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Creado el proyecto, lo primero que vamos a hacer es añadir una referencia a la librería de PostgreSQL. Para ello, en el panel "Project" (parte izquierda), aparecerá el proyecto con los diversos elementos del mismo. Hacer clic con el botón derecho sobre "Libraries" y seleccionar "Add JAR/Folder". Navegar hasta el directorio lib de Tomcat y seleccionar el archivo .jar de PostgreSQL. La librería aparecerá en el árbol subyacente.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Configurar pool de conexiones&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;A continuación vamos a configurar el pool de conexiones. Antes de empezar, comentar que en la versiones recientes de Tomcat, por motivos de seguridad y eficiencia, la configuración de contextos y recursos se realiza por aplicación, y en no en el contexto general de Tomcat. Aclarado ésto vamos a proceder a la configuración.&lt;br /&gt;&lt;br /&gt;Desplegar, en el panel de proyecto, el elemento "Web pages" del proyecto. Desplegar ahora el elemento "WEB-INF" y hacer doble clic sobre el archivo "web.xml". Seleccionar ahora el botón "XML" (parte superior de la zona de trabajo), con lo que aparecerá el contenido del archivo. Aquí aparecerá un bloque principal encerrado entre los tags &amp;lt;web-app&amp;gt; y &amp;lt;/web-app&amp;gt;. Situarse justo antes del cierre de este bloque y añadir las siguientes líneas:&lt;br /&gt;&lt;br /&gt;&amp;lt;resource-ref&amp;gt;&lt;br /&gt;  &amp;lt;description&amp;gt;Referencia al pool de conexiones&amp;lt;/description&amp;gt;&lt;br /&gt;  &amp;lt;res-ref-name&amp;gt;jdbc/[nombreJNDI]&amp;lt;/res-ref-name&amp;gt;&lt;br /&gt;  &amp;lt;res-type&amp;gt;javax.sql.DataSource&amp;lt;/res-type&amp;gt;&lt;br /&gt;  &amp;lt;res-auth&amp;gt;Container&amp;lt;/res-auth&amp;gt;&lt;br /&gt;&amp;lt;/resource-ref&amp;gt;&lt;br /&gt;&lt;br /&gt;El campo &amp;lt;res-ref-name&amp;gt; contiene el nombre JNDI que se utilizará como contexto para el pool de conexiones.&lt;br /&gt;&lt;br /&gt;El siguiente paso es acceder al elemento "Web pages" del proyecto. Desplegar ahora el elemento "META-INF" y hacer doble clic sobre el archivo "context.xml". Se mostrará el contenido:&lt;br /&gt;&lt;br /&gt;&amp;lt;Context antiJARLocking="true" path="/TrazalogicOperator"/&amp;gt;&lt;br /&gt;&lt;br /&gt;Modificar esta línea para definir dos líneas (apertura y cierre) en lugar de una:&lt;br /&gt;&lt;br /&gt;&amp;lt;Context antiJARLocking="true" path="/[NombreProyecto]"&amp;gt;&lt;br /&gt;&amp;lt/Context&amp;gt;&lt;br /&gt;&lt;br /&gt;[NombreProyecto] es asignado automáticamente por NetBeans, y no es necesario cambiarlo.&lt;br /&gt;&lt;br /&gt;Entre estas dos líneas añadir lo siguiente para crear el contexto del pool:&lt;br /&gt;&lt;br /&gt;  &amp;lt;Resource name="jdbc/[nombreJNDI]"&lt;br /&gt;    auth="Container"&lt;br /&gt;    type="javax.sql.DataSource"&lt;br /&gt;    username="[usuarioPostgreSQL]"&lt;br /&gt;    password="[passwordPostgreSQL]"&lt;br /&gt;    driverClassName="org.postgresql.Driver"&lt;br /&gt;    url="jdbc:postgresql://[servidor]:[puerto]/[nombrebasedatos]"&lt;br /&gt;    maxActive="8"&lt;br /&gt;    maxIdle="4"/&amp;gt;&lt;br /&gt;&lt;br /&gt;Un ejemplo de url sería:&lt;br /&gt;&lt;br /&gt;url="jdbc:postgresql://localhost:5432/miBaseDatos"&lt;br /&gt;&lt;br /&gt;Si la base de datos va a residir en la misma máquina que Tomcat y la aplicación web, se utilizaría "localhost". Si estuviera en otra máquina, especificar el nombre de la misma (si está configurado en un servidor DNS) o bien la dirección IP de la misma.&lt;br /&gt;&lt;br /&gt;El puerto 5432 es el puerto por defecto de la base de datos PostgreSQL. Si se ha configurado otro puerto, modificar este parámetro.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Probar todo&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Para probar tanto el servidor de aplicaciones como el pool de conexiones, vamos a crear un Servlet. Para ello:&lt;br /&gt;- Menú "File" + opción "New File..."&lt;br /&gt;- En la lista "Categories" seleccionar "Web", y en la lista "File Type" seleccionar "Servlet".&lt;br /&gt;- Botón "Next"&lt;br /&gt;- En el campo "Class Name" escribir el nombre del servlet, por ejemplo "ServletPrueba".&lt;br /&gt;- En el campo "Package" escribir el nombre del paquete donde se ubicará el servlet, por ejemplo "com.prueba.servlet"&lt;br /&gt;- Botón "Next"&lt;br /&gt;- Botón "Finish"&lt;br /&gt;&lt;br /&gt;Se creará el servlet con un código mínimo.&lt;br /&gt;&lt;br /&gt;En la sección "import" añadir las siguientes importaciones:&lt;br /&gt;&lt;br /&gt;import java.sql.*;&lt;br /&gt;import javax.sql.*;&lt;br /&gt;import javax.naming.*;&lt;br /&gt;&lt;br /&gt;Buscar el método processRequest y escribir el siguiente código:&lt;br /&gt;&lt;br /&gt;protected void processRequest(HttpServletRequest request, HttpServletResponse response)&lt;br /&gt;&amp;nbsp;throws ServletException, IOException {&lt;br /&gt;&amp;nbsp;&amp;nbsp;response.setContentType("text/html;charset=UTF-8");&lt;br /&gt;&amp;nbsp;&amp;nbsp;PrintWriter out = response.getWriter();&lt;br /&gt;&amp;nbsp;&amp;nbsp;try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out.println("&amp;lt;html&amp;gt;");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out.println("&amp;lt;head&amp;gt;");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out.println("&amp;lt;title&amp;gt;Servlet ServletPrueba&amp;lt;/title&amp;gt;");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out.println("&amp;lt;/head&amp;gt;");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out.println("&amp;lt;body&amp;gt;");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out.println("INICIO...&amp;lt;br&amp;gt;");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Context initCtx = new InitialContext();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Context envCtx = (Context) initCtx.lookup("java:comp/env");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DataSource ds = (DataSource)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;envCtx.lookup("jdbc/[nombreJNDI]");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Connection conn = ds.getConnection();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//... Insertar aquí las consultas y actualizaciones a base de datos&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;conn.close();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out.println("...FIN&amp;lt;br&amp;gt;");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out.println("&amp;lt;/html&amp;gt;");&lt;br /&gt;&amp;nbsp;&amp;nbsp;} catch (Exception ex) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out.println("Error: " + ex.toString();&lt;br /&gt;&amp;nbsp;&amp;nbsp;} finally {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;out.close();&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;A través del nombre JNDI se extrae el contexto para el pool de base de datos, retornando un objeto de tipo DataSource. Una vez obtenido el DataSource, es posible obtener la conexión (método getConnection()). A partir de ahí, con la conexión, procederemos a realizar las consultas a base de datos, o las actualizaciones pertinentes.&lt;br /&gt;&lt;br /&gt;El código, tal y como está, servirá para verificar que se obtiene la conexión. Si todo va bien, devolverá una página Web, con el único texto "INICIO...  / ...FIN". Si hubiera algún error, retornaría también el error producido.&lt;br /&gt;&lt;br /&gt;Para ejecutar este servlet, en el panel de proyecto (parte izquierda), abrir la carpeta "Source Packages" + "com.prueba.servlet", y con el botón derecho hacer clic sobre el elemento "ServletPrueba.java" y seleccionar "Run File" (para ejecutar el servlet) o "Debug File" (para depurar el servlet, previo marcado un punto de interrupción).&lt;br /&gt;&lt;br /&gt;Antes de finalizar, comentar qué me ha llevado a escribir este post, tras tres días devanándome la cabeza con Eclipse y con GlassFish, con los que he tenido multitud de problemas y una complejidad bastante elevada en cuanto a una configuración para trabajar. Soy de los que piensan que tenemos ya mucho trabajo por delante como para perder el tiempo descifrando o poniéndote delante de una bola de cristal para intentar explicar cómo configurar algo que debería ser automático y simple, y que en apenas unos segundos y de manera intuitiva debería dejarte empezar a trabajar. Ahí radica el éxito de Visual Studio de Microsoft, que facilita el trabajo multiplicando la productividad.&lt;br /&gt;&lt;br /&gt;Con Eclipse, de forma inexplicable, los cambios en mi servlet no se actualizaba ni desplegaba en el servidor. Por más que he intentado saber por qué, aún no me lo explico.&lt;br /&gt;&lt;br /&gt;Con GlassFish, que parece un servidor potente y muy bien diseñado, veía muchos pasos para configurar el pool de conexiones (primero una conexión, luego el pool y luego el resource, y luego configurar el context.xml y el web.xml). Pero aún así, mirando la documentaciónd e GlassFish, PostgreSQL no venía homologado en las especificaciones, aunque en realidad sí que permitía su configuración, y la conexión, de hecho me permitía mirar la estructura de la base de datos y ejecutar consultas desde el IDE. Pero a la hora de desarrollar, el DataSource era imposible de capturar, y desde el propio GlassFish, probar el DataSource me daba un error FATAL por que database devolvía null. El problema es que el driver de conexión es peculiar en PostgreSQL, y se obtiene mediante un DataSource "especial" llamado org.postgreSQL.ds.PGSimpleDataSource, el cual es incompatible o no se puede convertir a un DataSource normal. Asimismo, incluso intentando obtener un PGSimpleDataSource en lugar de un DataSource, también daba error porque internamente trabaja con DataSource. Vamos un galimatías que me hizo desistir.&lt;br /&gt;&lt;br /&gt;Al final, me empapé la documentación de Tomcat (concretamente &lt;a href="http://localhost:8080/docs/jndi-resources-howto.html"&gt;http://localhost:8080/docs/jndi-resources-howto.html&lt;/a&gt;) y trasteando con Tomcat, conseguí definir este procedimiento de configuración, simplificándolo al máximo y que funciona.&lt;br /&gt;&lt;br /&gt;Espero que os sea de utilidad.&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-3824934020812610928?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/3824934020812610928/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=3824934020812610928&amp;isPopup=true' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/3824934020812610928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/3824934020812610928'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/09/configurar-netbeans-tomcat-y-un-pool-de.html' title='Configurar NetBeans, Tomcat y un pool de conexiones a PostgreSQL'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-635774061522736802</id><published>2009-09-22T15:24:00.010+02:00</published><updated>2009-09-22T16:32:23.080+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tecnología'/><category scheme='http://www.blogger.com/atom/ns#' term='Hardware'/><category scheme='http://www.blogger.com/atom/ns#' term='Software libre'/><category scheme='http://www.blogger.com/atom/ns#' term='Software'/><category scheme='http://www.blogger.com/atom/ns#' term='SIMO'/><title type='text'>Visita al SIMO 2009</title><content type='html'>Día inaugural de SIMO 2009. El retorno de la consagrada feria de las tecnologías de la información, tras dos años en dique seco debido a la crisis mundial. Expectación, pues en la última edición me negué a ir porque ya era un circo, y acudía hasta el apuntador, desprestigiando a los profesionales. Este año (en teoría) era sólo para profesionales (aunque he visto alguna que otra familia con los nenes).&lt;br /&gt;&lt;br /&gt;Empieza las 10:00. Personas fuera esperando. En el interior hay escáners para bolsas, paquetes y equipajes, como en el aeropuerto. También hay arcos detectores, y bandejas para dejar los objetos metálicos. Todo lleno de policias nacionales y algún que otro trajeado con "pinganillo", al estilo de la CIA o del FBI. Esto parece de película. ¿Será por seguridad o sólo porque el principito Felipe va a venir, seguramente con la corte de pelotas como Gallardón (alcalde de Madrid) y la Espe (presidenta de la Comunidad de Madrid?. No lo sé, pues no me quedé a esperarles.&lt;br /&gt;&lt;br /&gt;Para entrar y salir en todos los pabellones y accesos, hay que pasar la tarjeta de identificación (código de barras en 2D y 3D) por un lector para el torniquete.&lt;br /&gt;&lt;br /&gt;Primera sorpresa, vas andando desde el pabellón 1, y andas y andas, y andas, y todos los pabellones, a izquierda y derecha CERRADOS!!!! Llegamos al final, y el número 7 está abierto.&lt;br /&gt;&lt;br /&gt;¡¡¡ Sorpresa !!! El pabellón 7 es muy diáfano, con pocos stands, muy separados y... adividinad: ¿quién ocupa más de la mitad del pabellón?. Nada más y nada menos que Microsoft, presentando su Ventanucos 7, su Exchange 2008, el Office y el Dynamics (por cierto, una pasada viendo cómo funciona en una mesa de pantalla táctil).&lt;br /&gt;&lt;br /&gt;Pruebo algún que otro equipo funcionando con Ventanucos 7. Nada mal, acostumbrado a mi Vista. Parece (a primer a vista) más estable, robusto y funcional. Mi feeling es bueno.&lt;br /&gt;&lt;br /&gt;Junto a Microsoft hay alguna que otra consultora de las que andan, como las rémoras, junto al gran tiburón blanco. Curiosamente, está Sun Microsystems con un stand muy pequeño, promocionando únicamente hardware, como sistemas de almacenamiento, y algún servidor modular. Una cosa extrañamente curiosa, y al final os contaré mi reflexión.&lt;br /&gt;&lt;br /&gt;Bueno, vamos al pabellón 9, hay bastantes stands pequeñitos, como los de las ferias de pueblo. Los más pudientes tiene algún stand un poco más grande, como Acer o Airis. Pero los más grande pertenecen a SAP, HP, DELL (en un camión tráiler de color negro) y a la editorial que edita MacWorld. Alguno que otro ha contratado a un maestro cortador de jamón, que sabe rancio en esta feria (no por el jamón, es una ironía). Sorprendentemente, cerca de un cuarto del espacio de este pabellón está vallado y desaprovechado.&lt;br /&gt;&lt;br /&gt;Salimos fuera y nos encontramos que el resto de pabellones al otro lado están cerrados. ¡No puede ser! ¿Cómo va a haber sólo dos pabellones para el SIMO?. Volvemos a entrar y preguntamos. ¡SOLO HAY DOS PABELLONES! Algo que ves en apenas una hora y media.&lt;br /&gt;&lt;br /&gt;En Telefonía está Vodafone y Telefónica. Pero no hay fabricantes de teléfonos móviles, como Nokia, Panasonic, Samsung o Motorla, como en otras ediciones. Sólo hay compañías de telefonía, y sólo las más grandes (echo en falta a Symio, Yoigo u Orange).&lt;br /&gt;&lt;br /&gt;En software están los de SAP y los más conocidos en ERP y en CRM. Pero empiezo a echar en falta a los grandes fabricantes de software y de bases de datos (como Oracle). No han acudido Adobe, ni Java, ni empresas de software libre (sólo encontré Opentrad, con un software de traducción libre, y Cenatic, de forma muy discreta), ni Hispalinux, ni la comunidad de Extremadura (con su Linex), ni la Junta de Andalucia... ¿DONDE ESTAN?&lt;br /&gt;&lt;br /&gt;Pregunto a unos amigos que tenían un stand en la feria (hace años trabajé con ellos), y me chistan para que baje la voz y no pronuncie la palabra maldita: software libre. Este gesto me mosquea. ¿No hay pasta para estos fabricantes debido a la crisis? ¿La organización del SIMO ha hecho algo por lo que estos fabricantes no estén de acuerdo y no hayan asistido? ¿O acaso hay una política discriminatoria con respecto al software libre? Lo ignoro, pero el retorno del SIMO es agridulce ante esta perspectiva desoladora.&lt;br /&gt;&lt;br /&gt;Me quedan todas las dudas del mundo acerca de lo que Oracle va a hacer con los productos de Sun Microsystems, como Java, MySQL o StarOffice. Me quedan dudas sobre qué hace ahora Borland que ha sido otra vez adquirida. Se hablaba de un Delphi 2010, pero me quedo con las ganas. Me quedo con las ganas también de conocer alternativas a estos tiburones, sean o no libres. Opentrad (que por cierto, el comercial que me atendió fue amabilísimo, me explicó todo muy bien e incluso me invitó a un zumo de naranja recién exprimido), era el único fabricante de software libre, pero no competía con nadie de la feria en su terreno. Lo mismo ocurría con algunos fabricantes de hardware humildes. Se pone de manifiesto el abismo entre ricos y pobres, las apariencias y la publicidad que ponen ante la diferencia de imagen, los que tienen un poder abusivo y que no permiten la competencia.&lt;br /&gt;&lt;br /&gt;Mi opinión es que el SIMO ha vuelto, y es un buena noticia, pues se vuelve a reactivar el mercado y hay esperanzas de volver a la fertilidad tecnológica. Por otro lado, el sabor amargo ante la poca oferta que imponen, la diferencia abismal entre tiburones, rémoras y gorriones que pican las migajas, y que el software libre haya sido eliminado del directorio de la feria, siendo hoy en día uno de los principales candidatos a un nuevo mercado rico en ideas y en competitividad. Está visto que el SIMO pertenece a cuatro gigantes que no deja crecer la hierba bajo su sombra.&lt;br /&gt;&lt;br /&gt;Me fui de la feria dos horas y cuarto después de haber llegado, desazonado y triste. No tuve ni ganas de ver al principito y su corte de pelotas con afán de cámara y publicidad falsa. Para colmo, las dos horas y cuarto de parking me salió por 4,15 euros. TODO UN ROBO!!!!&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-635774061522736802?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/635774061522736802/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=635774061522736802&amp;isPopup=true' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/635774061522736802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/635774061522736802'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/09/visita-al-simo-2009.html' title='Visita al SIMO 2009'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-4970941654892597571</id><published>2009-09-21T22:13:00.003+02:00</published><updated>2009-09-21T22:15:02.212+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software'/><category scheme='http://www.blogger.com/atom/ns#' term='Tecnillusions'/><title type='text'>TI Facturas listo para su descarga</title><content type='html'>Se ha liberado la versión definitiva de &lt;a&gt;TI Facturas&lt;/a&gt;, el software imprescindible para que cualquier PYME o cualquier trabajador autónomo pueda gestionar de forma sencilla y económica sus presupuestos y facturas. Se ha optimizado al máximo la sencillez del programa, para que empezar con él no sea un reto, y que el día a día sea algo natural y no consuma mucho tiempo que se requeriría para actividades más importantes.&lt;br /&gt;&lt;br /&gt;&lt;a&gt;Descarga y documentación:&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.tecnillusions.com"&gt;http://www.tecnillusions.com&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_T-uXeKcGTnM/SrfeppimaOI/AAAAAAAABLU/_jiqZBSKNFM/s1600-h/Firma.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 343px; height: 192px;" src="http://2.bp.blogspot.com/_T-uXeKcGTnM/SrfeppimaOI/AAAAAAAABLU/_jiqZBSKNFM/s400/Firma.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5384016686651697378" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-4970941654892597571?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/4970941654892597571/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=4970941654892597571&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/4970941654892597571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/4970941654892597571'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/09/ti-facturas-listo-para-su-descarga.html' title='TI Facturas listo para su descarga'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_T-uXeKcGTnM/SrfeppimaOI/AAAAAAAABLU/_jiqZBSKNFM/s72-c/Firma.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-5641540786829703004</id><published>2009-09-19T19:19:00.006+02:00</published><updated>2009-09-19T19:59:04.533+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQLite'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Bases de Datos'/><title type='text'>Base de datos bloqueada en SQLite y .NET</title><content type='html'>En post anteriores se ha hablado sobre las bondades de SQLite trabajando en conjunción con .NET, un gran equipo que es eficiente y rápido (amén de optimizado por lo recursos que consume), pero puede dar alguno que otro quebradero de cabeza, especialmente con el bloqueo de base de datos (database locked).&lt;br /&gt;&lt;br /&gt;La principal razón de que esto ocurra es que SQLite trabaja en una única sesión, por lo que la concurrencia queda descartada para grandes pretensiones. Incluso con esto en mente, trabajando en una aplicación de escritorio (no en servidor), esto puede suponer también un problema cuando queremos trabajar con varias consultas anidadas y actualizaciones.&lt;br /&gt;&lt;br /&gt;En este post voy a contar mi experiencia y cómo he capeado este problema.&lt;br /&gt;&lt;br /&gt;Ante todo, hay que reutilizar el código, por lo que el acceso a base de datos la realizo desde una clase con métodos públicos. En esta clase defino los objetos clave para el uso de la base de datos:&lt;br /&gt;&lt;br /&gt;&lt;font face="courier" size="1" color="#00AA00"&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Linq;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.Data;&lt;br /&gt;using System.Data.SQLite;  // No olvidar esta referencia&lt;br /&gt;&lt;br /&gt;// Clase específica para acceso y carga de datos desde la base de datos&lt;br /&gt;namespace TI_Facturas&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;class DatosManager&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private SQLiteConnection con = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private SQLiteCommand cmd = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private SQLiteDataReader dtr = null;&lt;br /&gt;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;Los objetos deben tener un uso exclusivo cada vez, por lo que se definen dos métodos: uno para iniciarlos y otro para despacharlos.&lt;br /&gt;&lt;br /&gt;&lt;font face="courier" size="1" color="#00AA00"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// Inicializa los objetos de base de datos&lt;br /&gt;&amp;nbsp;&amp;nbsp;private void initSQL()&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;con = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dtr = null;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;con = new SQLiteConnection("Data Source=ti_facturas.db;Version=3;New=False;Compress=True;");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;con.Open();&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;// Prepara la clase para ser despachada&lt;br /&gt;&amp;nbsp;&amp;nbsp;public void dispose()&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (cmd != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd.Dispose();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (dtr != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dtr.Close();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dtr.Dispose();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (con != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;con.Close();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;con.Dispose();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;con = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dtr = null;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;GC.Collect();&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;El método initSQL() ha de invocarse antes de empezar cualquier operación con la base de datos. A continuación se realizan las operaciones con la base de datos (accesos y actualizaciones). Y por último se invoca al método dispose() para finiquitar los objetos.&lt;br /&gt;&lt;br /&gt;La sentencia GC.Collect() permite vaciar el Garbage Collector, un repositorio que .NET utiliza para depositar los objetos que dejan de ser utilizados. Es posible que en algunas ocasiones, aunque cerremos convenientemente los objetos para despacharlos al Garbage Collector, éste aún pueda tener la referencia a SQLite y no haya procesado su limpieza automática, por lo que nos dará, inevitablemente, el conocido error de "database locked", a pesar de ser meticulosos y despachar a medida que dejamos de utilizar.&lt;br /&gt;&lt;br /&gt;Recomiendo utilizar en esta clase los métodos de acceso a la base de datos, e ir invocándolo desde nuestras propias clase. Por ejemplo, ahí van las más utilizadas de forma genérica:&lt;br /&gt;&lt;br /&gt;&lt;font face="courier" size="1" color="#00AA00"&gt;&lt;br /&gt;// Ejecuta una sentencia de actualizacion (NO SELECT)&lt;br /&gt;public String executeNonQuery(string sql)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;String result = "" ;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;try&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;initSQL();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd = new SQLiteCommand(sql, con);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int rows = cmd.ExecuteNonQuery();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (rows == 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result = "No se ha realizado ningun cambio [" + sql + "]";&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;catch (Exception argEx)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result = "Error al ejecutar SQL ["+sql+"]: " + argEx.Message;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;dispose();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return result;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Obtiene el valor de un unico campo para una consulta de un solo registro&lt;br /&gt;public String getUniqueValue(string sql)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;String result = "";&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;try&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;initSQL();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd = new SQLiteCommand(sql, con);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dtr = cmd.ExecuteReader();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dtr.Read();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result = (String)dtr[0].ToString();&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;catch (Exception argEx)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result = "";&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;dispose();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return result;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Obtiene el conjunto de registros de una consulta SQL Select&lt;br /&gt;public SQLiteDataReader executeReader(string sql)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;try&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;initSQL();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd = new SQLiteCommand(sql, con);&lt;br /&gt;&amp;nbsp;&amp;nbsp;dtr = cmd.ExecuteReader();&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;catch (Exception argEx)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;dtr = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;return dtr;&lt;br /&gt;}&lt;br /&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;EJEMPLOS DE USO:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo 1: Actualización&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;font face="courier" size="1" color="#00AA00"&gt;&lt;br /&gt;string sql="insert into paises (id_pais, pais) values (1, 'Spain')";&lt;br /&gt;DatosManager dm = new DatosManager();&lt;br /&gt;dm.executeNonQuery(sql);&lt;br /&gt;dm.dispose();&lt;br /&gt;&lt;/font face&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo 2: Consulta campo especifico en registro unico&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;font face="courier" size="1" color="#00AA00"&gt;&lt;br /&gt;string sql="select nombre from clientes where id_cliente=32";&lt;br /&gt;DatosManager dm = new DatosManager();&lt;br /&gt;string nombre=dm.getUniqueValue(sql);&lt;br /&gt;dm.dispose();&lt;br /&gt;&lt;/font face&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Ejemplo 3: Consulta con conjunto de varios registros&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;font face="courier" size="1" color="#00AA00"&gt;&lt;br /&gt;string sql="select id_provincia, provincia from provincias order by provincia";&lt;br /&gt;DatosManager dm = new DatosManager();&lt;br /&gt;SQLiteDataReader dr=dm.executeReader(sql);&lt;br /&gt;while (dr.Read())&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;// Tratamiento de cada registro&lt;br /&gt;}&lt;br /&gt;dr.Close();  // Despachar primero el DataReader&lt;br /&gt;dr.Dispose();&lt;br /&gt;dm.dispose();&lt;br /&gt;&lt;/font face&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-5641540786829703004?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/5641540786829703004/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=5641540786829703004&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/5641540786829703004'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/5641540786829703004'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/09/base-de-datos-bloqueada-en-sqlite-y-net.html' title='Base de datos bloqueada en SQLite y .NET'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-4221777938770261704</id><published>2009-09-17T15:41:00.015+02:00</published><updated>2009-09-17T16:13:03.525+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software'/><category scheme='http://www.blogger.com/atom/ns#' term='Tecnillusions'/><title type='text'>TI_Facturas v2009 Beta</title><content type='html'>Acaba de liberarse la versión Beta de &lt;span style="font-weight: bold;"&gt;TI_Facturas v2009&lt;/span&gt;, de la empresa &lt;span style="font-weight: bold;"&gt;Tecnillusions&lt;/span&gt; (&lt;a href="http://www.blogger.com/http.//www.tecnillusions.com"&gt;http.//www.tecnillusions.com&lt;/a&gt;), un sencillo y potente gestor de presupuestos y facturas, orientado a la pequeña y mediana empresa.&lt;br /&gt;&lt;br /&gt;Entre sus características cabe destacar las siguientes:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Sencillo e intuitivo, lo que tiene un período muy breve de aprendizaje.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Rápido, eficaz y ligero en recursos.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Gestión de múltiples empresas.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Numeración automática de presupuestos y de facturas, independientemente de la empresa.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Gestión de empresas.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Gestión de clientes.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Internacionalidad en empresas y clientes.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Configuración de unidades métricas a ser utilizadas en los conceptos.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Configuración de las formas de pago de las facturas.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Generación de facturas a partir de los presupuestos aceptados.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Configuración de los impuestos y descuentos a aplicar de forma genérica (por empresa), o individual (por factura).&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Registro de plazos de pago&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Libertad en la redacción de los conceptos:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Varias líneas por concepto.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Texto extenso, que automáticamente es distribuido en varias líneas.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Cantidad, Unidad, Precio y Total, libres y opcionales de mostrar.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Cálculo automático del Total si Cantidad y Precio son introducidos.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Autopaginación. Los totales se visualizan en la última página, y cada página es enumerada.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Posibilidad de agrupar facturas en una factura, formando parte del concepto de la misma.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Potente filtro con combinatoria de criterios de búsqueda:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Por empresa&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Por cliente&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Por una fecha determinada&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Por un rango de fechas (desde...hasta)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Aceptado (presupuesto) o pagada (factura)&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Configuración de logotipo para su publicación en presupuestos y facturas.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Alarmas de plazos vencidos.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Sistema operativo Windows XP, 7 o Vista.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Sin licencias por máquina: se puede instalar en cuantas máquinas se desee, teniendo en cuenta que los datos de cada una es independiente de la otra.&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Modalidades:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Gratuito: Completamente funcional, con algunas limitaciones.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Premium:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+ Sin limitaciones&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+ Soporte y garantía de 1 año contra defectos.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+ Servicio de actualización gratuito.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+ Por sólo 150 euros&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Soporte adicional y opcional (previo presupuesto)&lt;br /&gt;&amp;nbsp;&amp;nbsp;* Personalización a medida (previo presupuesto):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Funcionalidades a medida&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Traducción al idioma requerido&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Personalización del presupuesto&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+ Modelo&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+ Tipografía&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+ Distribución&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o Personalización de la factura&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+ Modelo&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+ Tipografía&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+ Distribución&lt;br /&gt;&lt;br /&gt;Para solicitar la versión gratuita para probar &lt;span style="font-weight: bold;"&gt;TI_Facturas&lt;/span&gt; sin compromiso enviar un correo a &lt;a href="mailto:info@tecnillusions.com"&gt;info@tecnillusions.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Capturas de pantalla:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_T-uXeKcGTnM/SrI9oQHGZ1I/AAAAAAAABKE/mRcG-svkIAc/s1600-h/TI_Facturas_Pral.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 243px;" src="http://4.bp.blogspot.com/_T-uXeKcGTnM/SrI9oQHGZ1I/AAAAAAAABKE/mRcG-svkIAc/s400/TI_Facturas_Pral.jpg" alt="" id="BLOGGER_PHOTO_ID_5382432266389972818" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_T-uXeKcGTnM/SrI90VGiKDI/AAAAAAAABKM/AbPjQxa1SF8/s1600-h/TI_Facturas_Empresas.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 250px;" src="http://4.bp.blogspot.com/_T-uXeKcGTnM/SrI90VGiKDI/AAAAAAAABKM/AbPjQxa1SF8/s400/TI_Facturas_Empresas.jpg" alt="" id="BLOGGER_PHOTO_ID_5382432473888204850" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_T-uXeKcGTnM/SrI983BeHuI/AAAAAAAABKU/t_OmUNMUcAY/s1600-h/TI_Facturas_Unidades.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 250px;" src="http://2.bp.blogspot.com/_T-uXeKcGTnM/SrI983BeHuI/AAAAAAAABKU/t_OmUNMUcAY/s400/TI_Facturas_Unidades.jpg" alt="" id="BLOGGER_PHOTO_ID_5382432620432727778" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_T-uXeKcGTnM/SrI-FepOK9I/AAAAAAAABKc/14rt2IjRw-Y/s1600-h/TI_Facturas_FormaPago.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 250px;" src="http://4.bp.blogspot.com/_T-uXeKcGTnM/SrI-FepOK9I/AAAAAAAABKc/14rt2IjRw-Y/s400/TI_Facturas_FormaPago.jpg" alt="" id="BLOGGER_PHOTO_ID_5382432768507390930" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_T-uXeKcGTnM/SrI-QhzGJBI/AAAAAAAABKk/wrdwbe6et4w/s1600-h/TI_Facturas_Presupuesto.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 250px;" src="http://1.bp.blogspot.com/_T-uXeKcGTnM/SrI-QhzGJBI/AAAAAAAABKk/wrdwbe6et4w/s400/TI_Facturas_Presupuesto.jpg" alt="" id="BLOGGER_PHOTO_ID_5382432958332675090" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_T-uXeKcGTnM/SrI-bMrF5_I/AAAAAAAABKs/JTrFWKkjF5c/s1600-h/TI_Facturas_ImprimirPresupuesto.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 379px; height: 400px;" src="http://2.bp.blogspot.com/_T-uXeKcGTnM/SrI-bMrF5_I/AAAAAAAABKs/JTrFWKkjF5c/s400/TI_Facturas_ImprimirPresupuesto.jpg" alt="" id="BLOGGER_PHOTO_ID_5382433141640521714" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_T-uXeKcGTnM/SrI-km8Yd0I/AAAAAAAABK0/tm89xjH8ChM/s1600-h/TI_Facturas_Factura.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 250px;" src="http://3.bp.blogspot.com/_T-uXeKcGTnM/SrI-km8Yd0I/AAAAAAAABK0/tm89xjH8ChM/s400/TI_Facturas_Factura.jpg" alt="" id="BLOGGER_PHOTO_ID_5382433303311185730" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_T-uXeKcGTnM/SrI-xaUSKnI/AAAAAAAABK8/PO3oBRkUBzs/s1600-h/TI_Facturas_AgruparFactura.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 250px;" src="http://4.bp.blogspot.com/_T-uXeKcGTnM/SrI-xaUSKnI/AAAAAAAABK8/PO3oBRkUBzs/s400/TI_Facturas_AgruparFactura.jpg" alt="" id="BLOGGER_PHOTO_ID_5382433523260074610" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_T-uXeKcGTnM/SrI-9yg6YrI/AAAAAAAABLE/XU638P3F-Zo/s1600-h/TI_Facturas_ImprimirFactura.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 327px;" src="http://2.bp.blogspot.com/_T-uXeKcGTnM/SrI-9yg6YrI/AAAAAAAABLE/XU638P3F-Zo/s400/TI_Facturas_ImprimirFactura.jpg" alt="" id="BLOGGER_PHOTO_ID_5382433735913923250" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_T-uXeKcGTnM/SrI_JmODlcI/AAAAAAAABLM/z9mVmSs_9OE/s1600-h/TI_Facturas_Filtro.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 250px;" src="http://2.bp.blogspot.com/_T-uXeKcGTnM/SrI_JmODlcI/AAAAAAAABLM/z9mVmSs_9OE/s400/TI_Facturas_Filtro.jpg" alt="" id="BLOGGER_PHOTO_ID_5382433938772039106" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-4221777938770261704?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/4221777938770261704/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=4221777938770261704&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/4221777938770261704'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/4221777938770261704'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/09/tifacturas-v2009-beta.html' title='TI_Facturas v2009 Beta'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_T-uXeKcGTnM/SrI9oQHGZ1I/AAAAAAAABKE/mRcG-svkIAc/s72-c/TI_Facturas_Pral.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-2871919563422491431</id><published>2009-09-17T00:43:00.006+02:00</published><updated>2009-09-30T19:24:55.159+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQLite'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Bases de Datos'/><title type='text'>Consultas SQLite desde .NET</title><content type='html'>SQLite se integra muy bien con .NET, siendo muy fácil desarrollar un proyecto con esta base de datos, con unos costes muy reducidos al no tener que pagar licencias propietarias, como en el caso de Oracle o de SQL Server.&lt;br /&gt;&lt;p&gt;El primer paso a dar es instalarse el conector System.Data.SQLite.dll (se puede descargar de &lt;a href="http://sqlite.phxsoftware.com"&gt;http://sqlite.phxsoftware.com&lt;/a&gt;). Una vez instalado, hay que hacer referencia a dicho conector mediante Project &gt; Add Reference... (Proyecto &gt; Añadir referencia...), buscar el conector y OK (Aceptar).&lt;/p&gt;&lt;p&gt;El siguiente paso es añadir al inicio del código el uso de las clases de esta librería:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;using System.Data.SQLite; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Los ejemplos que aquí se muestran están escritos en C#, pero la adaptación a VB.NET no debería suponer gran transcendencia.&lt;/p&gt;&lt;p&gt;En primer lugar hay que encerrar todo el proceso de acceso a la base de datos en un bloque &lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;try...catch&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. Dentro de este bloque comenzaremos abriendo la conexión, mediante:&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;SQLiteConnection sql_con = new SQLiteConnection &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;("DataSource=ARCHIVOBBDD;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;   Version=3;New=False;Compress=True;");&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;                sql_con.Open();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;donde, &lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;ARCHIVOBBDD&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; es el nombre del archivo de la base de datos. Si este archivo se encuentra en una ruta fija, hay que indicar toda la ruta. Si se escribe únicamente el nombre del archivo, éste debería estar ubicado en el directorio &lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;debug&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; y &lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;release&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; del proyecto.&lt;/p&gt;&lt;p&gt;A continuación se crea el comando de la sentencia a ejecutar (en este caso una consulta o &lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;SELECT&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;):&lt;/p&gt;&lt;p&gt;                &lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;string CommandText = "select id_empresa, nombre from EMPRESAS order by nombre";&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;                SQLiteCommand sql_cmd = new SQLiteCommand(CommandText, sql_con);&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;El siguiente paso será ejecutar el comando para obtener el resultado de la consulta, el cual estará en un DataReader:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;SQLiteDataReader sql_dtr = sql_cmd.ExecuteReader();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;En este momento, el puntero del cursor se encuentra justo antes del primer registro. Con el método &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;Read()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;se obtenerá el siguiente registro o fila, retornando &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;true &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;si se leyó correctamente, o &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;si no se leyó, en cuyo caso se habrá alcanzado el final del resultado. La lectura de todos los registros se puede realizar dentro de un bucle como éste:&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;while (sql_dtr.Read())&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;   ... // Bloque para tratar los campos de la fila obtenida&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;El acceso a cada campo se realiza a modo de array con el DataReader, comenzando desde 0, que sería el primer campo, hasta n-1. También se podría acceder indicando dentro del elemento del array el nombre del campo entre comillas, en lugar del índice. Las dos siguientes líneas realizan lo mismo:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;string nombreEmpresa = (string)sql_dtr[1];&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;string nombreEmpresa = (string)sql_dtr["nombre"];&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;En todos los casos hay que hacer un casting del tipo de dato (anteponiendo y encerrando entre paréntesis el tipo de dato), por lo que hay que tener especial cuidado con los datos que son numéricos o de fecha. Las siguientes líneas son una muestra de ello, aunque no tengan que ver con el ejemplo que estamos planteando:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;long lData = (Int64)sql_dtr[0];  // Tipo entero largo&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;Single sData = (Single)sql_dtr[1];  // Tipo decimal&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;Double dData = (Double)sql_dtr[0];  // Tipo decimal de doble precisión&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;Para hacer una captura correcta de datos, lo mejor es comprobar si el dato no es nulo y un parseo en consecuencia, como en el siguiente ejemplo:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color:#006600;"&gt;Single sCant=0;&lt;br /&gt;string sData = dtr[0].ToString();&lt;br /&gt;                  if (sData != null &amp;amp;&amp;amp; sData != "")&lt;br /&gt;                           sCant = Single.Parse(sData);  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;                 &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;Si el dato no admite nulos, se puede realizar el parseo directamente:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;long plazo = (long)long.Parse(sql_dtr[6].ToString()) ;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt; &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;Double dData = Double.Parse(sql_dtr[0].ToString());&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;DateTime dtFecha = DateTime.Parse(sql_dtr["fecha"].ToString());&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;Una vez se han leído los registros y no se vaya a utilizar más el DataReader, hay que cerrarlo para optimizar recursos:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;sql_dtr.Close();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;Si la conexión ya no es necesaria por el momento, cerrarla también:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;sql_con.Close();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;El código completo del ejemplo, es el siguiente, y su objetivo es cargar una lista de empresas en una combo (lista desplegable):&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;// Carga la combo de empresas&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;        private void loadEmpresas()&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;        {&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;  try&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;  {&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    SQLiteConnection sql_con = new SQLiteConnection&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;      ("Data Source=ti_facturas.db;Version=3;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;      New=False;Compress=True;");&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    sql_con.Open();&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    string CommandText = &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;      "select id_empresa, nombre from EMPRESAS order by nombre";&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    SQLiteCommand sql_cmd = new SQLiteCommand(CommandText, sql_con);&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    SQLiteDataReader sql_dtr = sql_cmd.ExecuteReader();&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    DataTable dt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    dt = new DataTable("Datos");&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    dt.Columns.Add("id_empresa");&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    dt.Columns.Add("empresa");&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    DataRow dr;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    while (sql_dtr.Read())&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    {&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;      dr = dt.NewRow();&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;      dr["id_empresa"] = ((Int64)sql_dtr[0]);&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;      dr["empresa"] = (string)sql_dtr[1];&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;      dt.Rows.Add(dr);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#006600;"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    cboEmpresa.DataSource = dt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    cboEmpresa.ValueMember = "id_empresa";&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    cboEmpresa.DisplayMember = "empresa";&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    sql_dtr.Close();&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    sql_con.Close();&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;            catch (Exception argEx)&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;  {&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    Console.WriteLine("Exception message: " + argEx.Message);&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;        }&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-2871919563422491431?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/2871919563422491431/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=2871919563422491431&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/2871919563422491431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/2871919563422491431'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/09/consultas-sqlite-desde-net.html' title='Consultas SQLite desde .NET'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-6413309111170338959</id><published>2009-09-14T16:04:00.009+02:00</published><updated>2009-09-14T17:53:40.396+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQLite'/><category scheme='http://www.blogger.com/atom/ns#' term='Bases de Datos'/><title type='text'>Primeros pasos en SQLite</title><content type='html'>&lt;div&gt;&lt;b&gt;INTRODUCCION&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;SQLite es una base de datos que sorprende por lo increíblemente ligera que es (apenas ocupa 250KB), pero no por ello deja de ser potente, rápida y eficiente, basándose en SQL estándar para su gestión.&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;center&gt;&lt;a href="http://sqlite.org"&gt;&lt;img src="http://www.sqlite.org/images/SQLite.gif"&gt;&lt;/a&gt;&lt;/center&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;Las características más importantes de SQLite son las siguientes:&lt;br /&gt;- Transacciones atómicas, aisladas y consistentes.&lt;br /&gt;- No requiere instalación ni administración.&lt;br /&gt;- Implementa la mayor parte del estándar SQL92&lt;br /&gt;- Una base de datos completa se almacena en un único archivo en el disco duro.&lt;br /&gt;- Soporta bases de datos que ocupan terabytes, y cadenas y BLOBs que ocupan gigabytes.&lt;br /&gt;- Ejecución muy rápida y consume muy pocos recursos de la máquina.&lt;br /&gt;- No requiere de dependencias de terceros ni externas.&lt;br /&gt;- Es de dominio público.&lt;br /&gt;- Disponible para Linux, Windows y MacOS X.&lt;br /&gt;- Incluye una consola para la gestión y administración de bases de datos.&lt;br /&gt;- Se puede utilizar en proyectos escritos en:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Basic y dialectos (Visual Basic, PowerBasic, PureBasic...)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- C y C++&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- C# y VB .NET&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Clipper&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Lisp&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Curl&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- D&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Delphi&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Macromedia Director&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Flash Actionscript 2&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Fortran&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Java&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Javascript&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Matlab&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- .NET&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Perl&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- PHP&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- PL/SQL&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Python&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Ruby&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Smalltalk&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Tcl/tk&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;- Y otros...&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;INSTALACION&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Para instalar SQLite hemos de acceder a su página principal &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;http://sqlite.org&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Y descargar (Download) la última versión ejecutable (Binaries) de la plataforma (Windows, Linux, MacOS X) en la que vayamos a utilizarla. También aquí se puede descargar la documentación de la misma.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;El archivo está comprimido, y simplemente hay que descomprimirlo en la carpeta de nuestro disco de nuestra preferencia. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;CONSOLA SQLITE&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Una vez descomprimido hemos de abrir una consola de comandos (en caso de Windows, también se llama consola DOS, y se accede mediante "tecla Windows" + "R", y ejecutar "cmd") para utilizar SQLite. Una vez tengamos abierta la consola de comandos, hay que acceder al directorio donde se descomprimió SQLite, y ejecutar el comando:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;sqlite3 &lt;archivo_basedatos&gt;&lt;/archivo_basedatos&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;donde &lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;archivo_basedatos&gt;&lt;/archivo_basedatos&gt;&lt;/span&gt;&lt;/span&gt; es un path a un archivo donde contendrá una base de datos. Si no existe, creará la base de datos. Si existe, utilizará ésta. Como recomendación, poner una extensión fácil de reconocer, como &lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;".db"&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; o &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;".sqlite"&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;La ejecución de este comando nos introducirá en la consola de SQLite, donde podremos ejecutar cualquier comando SQL para gestionar la base de datos. Asimismo, también hay otros comandos específicos de esta consola:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.help&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; ó &lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.h&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Muestra una ayuda de los comandos disponibles&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.quit&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; ó &lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.q&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Termina la sesión de consola SQLite, retornando a la de comandos&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;.exit&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; ó &lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Termina la sesión de consola SQLite, retornando a la de comandos&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.databases&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Lista las bases de datos en uso&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.tables&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Lista las tablas de la base de datos&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.tables 'P%'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Lista las tablas que empiecen por 'P' (patrón LIKE)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.backup &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ARCHIVO&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Realiza una copia de seguridad de la base de datos principal a &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ARCHIVO&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.backup 'BBDD' ARCHIVO&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Realiza una copia de seguridad de la base de datos &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;'BBDD'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; a &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ARCHIVO&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.schema TABLA&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Muestra la estructura de la tabla especificada (en formato SQL), incluyendo los índices&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.indices TABLA&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; muestra los índices de la tabla especificada&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.output stdout&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Establece la salida a pantalla (por defecto)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.output ARCHIVO&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Establece la salida al archivo indicado en archivo&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.mode MODO&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Establece el modo de salida, donde &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;MODO &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;puede ser uno de estos valores:&lt;/div&gt;&lt;div&gt;   &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;csv &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&gt; valores separados por comas&lt;/div&gt;&lt;div&gt;   &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;column &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&gt; columnas alineadas a la izquierda (ver &lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.width&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;   &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;html&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; código TABLE en HTML&lt;/div&gt;&lt;div&gt;   &lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;insert &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&gt; código INSERT en SQL&lt;/div&gt;&lt;div&gt;   &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;line &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&gt; un valor por línea&lt;/div&gt;&lt;div&gt;   &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;list &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&gt; valores delimitados por &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.separator&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (por defecto)&lt;/div&gt;&lt;div&gt;   &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;tabs &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&gt; valores separados por tabuladores&lt;/div&gt;&lt;div&gt;   &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;tcl &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&gt; lista de elementos tcl&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.width num&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Establece el ancho para las columnas (salida)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.separator string&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Establece string como cadena delimitadora (salida)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.dump&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Vuelca en la salida la estructura y datos de la base de datos, es decir, muestra las sentencias SQL (creación de tablas, índices, inserción de datos actuales, etc.), de todas las tablas de la base de datos.  &lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.dump TABLA&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Vuelca en la salida la estructura y datos de la tabla especificada, es decir, que muestra las sentencias SQL para la TABLA especificada&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.restore ARCHIVO&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Restaura la copia de seguridad realizada con &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.backup&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; almacenada en &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ARCHIVO&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, en la base de datos en curso&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;.restore 'BBDD' ARCHIVO&lt;/span&gt;&lt;/span&gt; &gt; Restaura la copia de seguridad almacenada en  &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ARCHIVO&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, en la base de datos especificada con &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;'BBDD'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.read ARCHIVO&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &gt; Ejecuta las sentencias SQL que están almacenadas en &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ARCHIVO&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;EJEMPLOS&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.mode csv&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;select * from paises;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Muestra los datos de la tabla &lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;paises &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;separados por comas.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.mode html&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;select * from paises;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Muestra los datos de la tabla &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;paises &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;en una tabla HTML&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;.mode insert&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;select * from paises;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Muestra las sentencias INSERT para cada uno de los registros de la tabla &lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;paises&lt;/span&gt;&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.output paises.sql&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.mode insert&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;select * from paises;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Vuelca en el archivo &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;paises.sql&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; las sentencias INSERT para los datos de la tabla &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;paises&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.output paises.sql&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.dump paises&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Vuelca en el archivo &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;paises.sql&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; las sentencias de creación de tabla e índice, así como la inserción de datos, para la tabla &lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;paises&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.output stdout&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;.dump paises&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Restaura la salida a la pantalla, y vuelca la tabla &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;paises &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;en dicha salida.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;IDE's PARA SQLITE&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Afortunadamente, existen IDE o interfaces de usuario, que permitirán gestionar nuestras bases de datos SQLite, sin necesidad de la consola. Algunas de las más populares son:&lt;/div&gt;&lt;div&gt;- SQLite Administrator &gt; &lt;a href="http://sqliteadmin.orbmu2k.de/"&gt;http://sqliteadmin.orbmu2k.de/&lt;/a&gt;&lt;/div&gt;&lt;div&gt;- SQLite Database Browser &gt; &lt;a href="http://sqlitebrowser.sourceforge.net/"&gt;http://sqlitebrowser.sourceforge.net/&lt;/a&gt;&lt;/div&gt;&lt;div&gt;- SQLite Manager &gt; &lt;a href="http://sqlitemanager.findmysoft.com/"&gt;http://sqlitemanager.findmysoft.com&lt;/a&gt;&lt;/div&gt;&lt;div&gt;- SQLite Spy &gt; &lt;a href="http://www.yunqa.de/delphi/doku.php/products/sqlitespy/index"&gt;http://www.yunqa.de/delphi/doku.php/products/sqlitespy/index&lt;/a&gt;&lt;/div&gt;&lt;div&gt;- SQLite Studio &gt; &lt;a href="http://sqlitestudio.one.pl/index.rvt"&gt;http://sqlitestudio.one.pl/index.rvt&lt;/a&gt;&lt;/div&gt;&lt;div&gt;- SQLite Browser &gt; &lt;a href="http://sourceforge.net/projects/sqlitebrowser/"&gt;http://sourceforge.net/projects/sqlitebrowser/&lt;/a&gt;&lt;/div&gt;&lt;div&gt;- Liteman &gt; &lt;a href="http://igorkh.freeshell.org/en/software/liteman.html"&gt;http://igorkh.freeshell.org/en/software/liteman.html&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-6413309111170338959?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/6413309111170338959/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=6413309111170338959&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/6413309111170338959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/6413309111170338959'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/09/primeros-pasos-en-sqlite.html' title='Primeros pasos en SQLite'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9291335.post-728908323510057003</id><published>2009-09-14T12:41:00.003+02:00</published><updated>2009-09-14T13:22:53.587+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQLite'/><category scheme='http://www.blogger.com/atom/ns#' term='Bases de Datos'/><title type='text'>Uso de fechas en SQLite</title><content type='html'>Este es mi primer post sobre SQLite, una base de datos muy ligera, pero potente y rápida, y que no necesita apenas administración. Es software libre, por lo que no necesitarás pagar licencias por su uso, y tendrás un importante ahorro de costes. Por otro lado, hay versiones para varias plataformas, incluyendo a Microsoft Windows, Linux, BSD, etc.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;En un reciente proyecto personal en el que estoy embarcado, utilizo C#, en donde sólo es necesario una referencia a la librería System.Data.SQLite.dll (se puede descargar de &lt;a href="http://sqlite.phxsoftware.com/"&gt;http://sqlite.phxsoftware.com/&lt;/a&gt;). En el ordenador final, a la hora de instalarse, no es necesario tener el motor de la base de datos, pues la propia librería actúa como tal, y de una manera muy rápida y eficiente.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Pero SQLite puede utilizarse de muchas maneras, como embebido en C, o desde Java, o desde PHP (sólo por citar las más populares). Además, existen multitud de IDE's para diseñar y gestionar la base de datos, y no sólo una consola de comandos, por lo que no hay excusa para no probar esta base de datos.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Querría haber empezado una serie de posts sobre SQLite desde el principio (cosa que haré más adelante), pero por tiempo empezaré directamente con algo que puede despistarnos con respecto a otras bases de datos, y son el uso de fechas.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Un campo fecha se define como:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;CREATE TABLE &lt;/span&gt;&lt;/span&gt;&lt;tabla&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt; (nombre_campo &lt;/span&gt;&lt;/span&gt;&lt;campo_fecha&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;DATE ...);&lt;/span&gt;&lt;/span&gt;&lt;/campo_fecha&gt;&lt;/tabla&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Aunque permite insertar o modificar los datos en el formato &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'trebuchet ms';"&gt;'dd/mm/yyyy'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; es recomendable almacenar las fechas en el formato ordenable, del estilo &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;'2004-06-26T20:11:04'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (en .NET se realiza mediante &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;String.Format("{0:s}", valor_datetime)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. Aunque este formato es válido, a la hora de comparar fechas tendrá en cuenta también la hora, por lo que si la precisión que se desea es sobre el día, y no sobre día y hora, el formato recomendado sería &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;'yyyy-mm-dd'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, que en .NET se obtendría mediante &lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;String.Format("{0:yyyy'-'MM'-'dd}", valor_datetime)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;La razón de de este formato es que SQLite, internamente, la fecha se almacena como una cadena de texto. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Pero a la hora de hacer una búsqueda por fechas, del estilo:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;SELECT ...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;FROM ...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;WHERE fecha1&gt;fecha2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;nos llevaremos una sorpresa al comprobar que no nos hace mucho caso.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A la hora de comparar fechas, hay que utilizar el formato juliano, y ello se consigue mediante una función especial de SQLite.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;SELECT ...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;FROM ...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;span class="Apple-style-span"  style="color:#009900;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;WHERE julianday(fecha1)&gt;julianday(fecha2)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;De esta manera la comparación de fechas funcionará sin problemas.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;Technology IT News&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9291335-728908323510057003?l=rafinguer.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://rafinguer.blogspot.com/feeds/728908323510057003/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=9291335&amp;postID=728908323510057003&amp;isPopup=true' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/728908323510057003'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9291335/posts/default/728908323510057003'/><link rel='alternate' type='text/html' href='http://rafinguer.blogspot.com/2009/09/uso-de-fechas-en-sqlite.html' title='Uso de fechas en SQLite'/><author><name>Rafael Hernampérez</name><uri>http://www.blogger.com/profile/04102640369106899565</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07497919286376096415'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>