<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>El Blog de Albert Mata &#187; Herramientas</title>
	<atom:link href="http://www.albertmata.net/category/herramientas/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.albertmata.net</link>
	<description>// anotaciones de análisis y programación en mi día a día como consultor de software</description>
	<lastBuildDate>Mon, 03 Aug 2009 19:22:21 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Todo lo que quisiste hacer con un PDF pero no supiste cómo.</title>
		<link>http://www.albertmata.net/2009/01/todo-lo-que-quisiste-hacer-con-un-pdf-pero-no-supiste-como/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=todo-lo-que-quisiste-hacer-con-un-pdf-pero-no-supiste-como</link>
		<comments>http://www.albertmata.net/2009/01/todo-lo-que-quisiste-hacer-con-un-pdf-pero-no-supiste-como/#comments</comments>
		<pubDate>Sun, 11 Jan 2009 07:55:30 +0000</pubDate>
		<dc:creator>Albert Mata</dc:creator>
				<category><![CDATA[Herramientas]]></category>
		<category><![CDATA[Páginas web]]></category>
		<category><![CDATA[blogoff]]></category>
		<category><![CDATA[pdf]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.albertmata.net/?p=199</guid>
		<description><![CDATA[A través de Menéame descubro este genial artículo de Blogoff en el que explican cómo trastear y manipular a nuestro antojo documentos PDF sin necesidad de tener el programa Adobe Acrobat versión completa (es decir, no el Reader que es gratuíto sino el completo, el de pago). Decido incorporarlo a mi propio blog para tenerlo [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.albertmata.net/public/uploads/2009/01/pdf.png" alt="" title="pdf" width="284" height="286" class="alignleft size-full wp-image-200" />A través de <a href="http://meneame.net" target="_blank">Menéame</a> descubro este genial artículo de <a href="http://www.blogoff.es/" target="_blank">Blogoff</a> en el que explican cómo trastear y manipular a nuestro antojo documentos PDF sin necesidad de tener el programa Adobe Acrobat versión completa (es decir, no el Reader que es gratuíto sino el completo, el de pago). Decido incorporarlo a mi propio blog para tenerlo más mano cuando lo necesite y para de paso hacerlo llegar a más gente. El artículo de Blogoff se puede encontrar <a href="http://www.blogoff.es/2009/01/09/todo-lo-que-quisiste-hacer-con-un-pdf-pero-no-supiste-como/" target="_blank">aquí</a> y a su vez está basado en el artículo en inglés original que se puede leer <a href="http://www.labnol.org/software/adobe-pdf-guide-tutorial/6296/" target="_blank">aquí</a>.</p>
<p>Todo lo que sigue a continuación no está escrito por mí sino que es el contenido íntegro de la entrada en el blog Blogoff... </p>
<p><strong>1. ¿Cómo creo documentos PDF en mi ordenador sin necesidad de Adobe Acrobat?</strong></p>
<p>Hazte con una copia del programa gratuito <a href="http://dopdf.com/" target="_blank">DoPDF</a> [<a href="http://www.blogoff.es/2007/09/05/otra-forma-de-crear-archivos-pdf/" target="_blank">Ver tutorial</a>]</p>
<p><strong>2. Pero no quiero instalar un programa cuando lo único que voy a convertir son unos pocos documentos.</strong></p>
<p>Sube tus documentos a <a href="http://docs.google.com/" target="_blank">Google Docs</a> a través del explorador y luego expórtalos como PDF. Así de simple</p>
<p><strong>3. Un cliente me ha mandado una presentación PowerPoint por e-mail y aquí no tengo nada para abrirlo ¿qué puedo hacer? </strong></p>
<p>Reenvía el correo (con el powerpoint adjunto) a pdf@koolwire.com. Ellos convertirán la presentación a PDF y te la mandarán de vuelta para que la puedas ver en la mayoría de los dispositivos portátiles.</p>
<p><strong>4. ¿Cómo guardo una página web como PDF sin guardarla como HTML primero?</strong></p>
<p>Sólo tienes que ir a <a href="https://online.primopdf.com/Default.aspx" target="_blank"><strong>PrimoPDF</strong></a>, escribir la dirección de la página y recibirás una copia de la misma en PDF en el correo que les hayas proporcionado.</p>
<p><strong>5. ¿Cómo puedo transformar un PDF a otros formatos como documento de Word, imagen, HTML, etc…?</strong></p>
<p>A través de una web como <a href="http://www.zamzar.com/" target="_blank">Zamzar </a>[<a href="http://www.blogoff.es/2006/11/10/cambiar-de-un-formato-a-otro-via-web/" target="_blank">ver tutorial</a>]</p>
<p><strong>6. ¿Cómo puedo juntar dos archivos PDF en uno? ¿Y cambiar el orden de las páginas?</strong></p>
<p><a href="http://www.download.com/PDFill-PDF-Tools-Free/3000-2075_4-10435051.html" target="_blank">PDFill</a> es una utilidad muy versátil que te permitirá combinar varios documentos PDF en uno, reordenar las páginas e incluso rotarlas desde dentro del PDF.</p>
<p><strong>7. Quiero extraer el texto de un PDF para usarlo en mi documento de Word ¿cuál es la mejor opción?</strong></p>
<p>Abre <a href="http://pdftextonline.com/" target="_blank">PDF Text Extraction</a> y sube tu PDF. Extraerá las 10 primeras páginas de tu documento en formato texto.</p>
<p><strong>8. No puedo usar el truco de arriba porque el documento PDF no se hizo desde Word sino que fue escaneado.</strong></p>
<p>Hay un modo de <a href="http://www.labnol.org/software/convert-scanned-pdf-images-to-text-with-google-ocr/5158/" target="_blank">extraer el texto de estos documentos a través del OCR de Google</a>. Quizás no la forma más rápida pero posiblemente la mejor solución gratuita.</p>
<p><strong>9. Tengo documentos PDF en mi ordenador en el sentido de que no se pueden imprimir o seleccionar texto en ellos con el ratón.</strong></p>
<p><a href="http://www.freewarefiles.com/Freeware-PDF-Unlocker-V_program_27137.html" target="_blank">PDF Unlocker</a> es una utilidad gratuita que borra las restricciones más habituales sobre un PDF sin pedir ningún tipo de password.</p>
<p><strong>10. Algunos PDF de mi empresa están protegidos con contraseñas que nadie recuerda después de la cena de empresa de ayer ¿qué puedo hacer?</strong></p>
<p>Échale un vistazo a <a href="http://labnol.blogspot.com/2007/01/how-to-open-password-protected-pdf.html" target="_blank">How to Open Password Protected PDF</a></p>
<p><strong>11. Busco un servicio que permita a mis visitantes bajarse los artículos como PDF.</strong></p>
<p>Añade el botón <a href="http://www.pdfonline.com/web2pdf/index.asp" target="_blank">Web2PDF</a> en algún sitio de tu página web. Convertirá la página a PDF de forma instantánea y además te permitirá mantener un registro de las conversiones.</p>
<p><strong>12. Alguien me ha enviado un documento PDF en un idioma que no entiendo.</strong></p>
<p>Puedes traducirlo con <a href="http://www.labnol.org/internet/tools/translate-pdf-word-documents-online-google-translate/3553/" target="_blank">Google Translate</a> y <a href="http://viewer.zoho.com/" target="_blank">Zoho Viewer</a>.</p>
<p><strong>13. ¿Cómo puedo añadir anotaciones o notas de texto a mis documentos PDF?</strong></p>
<p>Descarga <a href="http://www.pdfxviewer.com/home/prod_user/PDF-XChange_Tools/pdfx_viewer/" target="_blank">PDF-X Viewer</a> que es como Adobe Reader pero con algunas funciones adicionales. Puedes añadir las anotaciones que quieras e incluso pegar imágenes. Otra opción parecida es <a href="http://www.pdfescape.com/" target="_blank">PDF Escape</a>.</p>
<p><strong>14. ¿Cómo puedo abrir un documento PDF online sin tener el software de Adobe?</strong></p>
<p>Una alternativa fácil para abrir PDF en el navegador es el <a href="http://www.pdfmenot.com/" target="_blank">Free Online PDF Viewer</a>, aunque hay <a href="http://www.labnol.org/internet/tools/read-adobe-pdf-files-online-without-acrobat/1923/" target="_blank">otras muchas</a>.</p>
<p><strong>15. ¿Puedo rellenar formularios PDF online sin Acrobat Reader?</strong></p>
<p>Sólo tienes que ir a <a href="http://www.pdffiller.com/" target="_blank">PDF Filler</a>, subir el archivo y empezar a escribir.</p>
<p><strong>16. ¿Cómo puedo añadir una marca de agua o mi propia firma a un PDF?</strong></p>
<p>Lo primero que tienes que hacer es crear tu marca de agua o firma con Paint o cualquier otro programa de dibujo y luego guardarla como imagen. Asegúrate de haber recortado bien la firma y abre el documento PDF en el <a href="http://www.pdfxviewer.com/home/prod_user/PDF-XChange_Tools/pdfx_viewer/" target="_blank">PDF-X Viewer</a> que ya hemos mencionado. Una vez allí sólo tienes que pegarla dentro del documento.</p>
<p><strong>17. Tengo un libro en PDF que llega a las 200 páginas ¿hay algún modo de extraer algunas páginas en concreto y salvarlas como otro PDF?</strong></p>
<p>Puedes usar tanto <a href="http://pdfmerge.sourceforge.net/" target="_blank">PDF Merge </a>como <a href="http://www.pdfsam.org/" target="_blank">PDF SAM</a> para hacer esta operación.</p>
<p><strong>18. ¿Cómo puedo proteger mi documento PDF con una contraseña?</strong></p>
<p>En <a href="http://www.pdfhammer.com/" target="_blank">PDF Hammer</a> subes tu documento y le asignas la contraseña que quieras.</p>
<p><strong>19. Un PDF tiene muchos enlaces pero no puedo hacer click en ellos porque están en texto plano. ¿Cómo puedo convertilos en enlaces estándar?</strong></p>
<p>Una vez más, acude a <a href="http://www.pdfescape.com/" target="_blank">PDF Escape</a>, sube el PDF y coloca los hipervínculos donde consideres oportuno.</p>
<p><strong>20. ¿Qué servicios me rec0mendarías para subir archivos PDF a internet?</strong></p>
<p>En el artículo original recomiendan <a href="http://issuu.com/" target="_blank">Issuu</a> que aún no he probado. De los que he visto me quedo con <a href="http://scribd.com/" target="_blank">Scribd</a>.</p>
<p><strong>21 [Blogoff Bonus Track]. ¿Cómo puedo abrir un PDF más rápido con Adobe Reader?</strong></p>
<p><a href="http://www.genbeta.com/2005/11/26-adobe-acrobat-a-la-velocidad-de-la-luz" target="_blank">Desactivando los plugins</a> o usando <a href="http://www.blogoff.es/2006/04/16/adobe-reader-o-como-ahogar-tu-viejo-pc-foxitreader-al-rescate/" target="_blank">Foxit PDF</a> como lector de escritorio.</p>
<p><strong>21 [Blogoff Bonus Track]. ¿Cómo crear un PDF de un documento de Word?</strong></p>
<p><a href="http://www.blogoff.es/2006/09/10/como-crear-un-pdf-de-un-documento-word/" target="_blank">Con Express PDF</a><strong> </strong>(mi herramienta favorita)</p>
<p><strong>22. </strong><strong>[Blogoff Bonus Track]. ¿Cómo puedo manejar archivos PDF en OpenOffice?</strong></p>
<p><a href="http://www.blogoff.es/2008/11/05/editar-archivos-pdf-sin-adobe-acrobat-con-openoffice/" target="_blank">Plugin para editar archivos PDF en Open Office sin Adobe Reader</a><strong><br />
</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.albertmata.net/2009/01/todo-lo-que-quisiste-hacer-con-un-pdf-pero-no-supiste-como/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>TextBox mejorado en .NET.</title>
		<link>http://www.albertmata.net/2008/12/textbox-mejorado-en-net/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=textbox-mejorado-en-net</link>
		<comments>http://www.albertmata.net/2008/12/textbox-mejorado-en-net/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 05:00:55 +0000</pubDate>
		<dc:creator>Albert Mata</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Herramientas]]></category>
		<category><![CDATA[control personalizado]]></category>
		<category><![CDATA[dll]]></category>
		<category><![CDATA[double]]></category>
		<category><![CDATA[integer]]></category>
		<category><![CDATA[librería]]></category>
		<category><![CDATA[textbox]]></category>

		<guid isPermaLink="false">http://www.albertmata.net/?p=149</guid>
		<description><![CDATA[Cuando desarrollamos en .NET es habitual utilizar controles personalizados que mejoran los preexistentes. Habitualmente podremos hacer uso de librerías públicas que podemos obtener en internet (liberadas o de pago). Otras veces podremos crearnos nosotros mismos nuestras propias librerías de controles. Yo suelo hacer esto último cuando no se trata de algo demasiado complejo, ya que [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.albertmata.net/public/uploads/2008/12/textboxfocused.jpg" alt="" title="textboxfocused" width="245" height="244" class="alignleft size-full wp-image-150" />Cuando desarrollamos en .NET es habitual utilizar controles personalizados que mejoran los preexistentes. Habitualmente podremos hacer uso de librerías públicas que podemos obtener en internet (liberadas o de pago). Otras veces podremos crearnos nosotros mismos nuestras propias librerías de controles. Yo suelo hacer esto último cuando no se trata de algo demasiado complejo, ya que termino antes que buscando componentes de terceros y peleándome después con sus correspondientes licencias. Entre otras cosas porque cualquier tipo de licencia "share alike" no me sirve.</p>
<p>Uno de los controles que me ahorran mucho trabajo en la creación de formularios es este que presento hoy y que en su día llamé TextBoxFocused (en adelante TBF). Se trata de un TextBox que cambia de color al recibir y perder el foco (de ahí su nombre -por cierto, sé que debería ser FocusedTextBox, pero quería mantener lo de TextBox al inicio-) y permite controlar a priori y a posteriori qué se puede introducir en él.</p>
<p>Un formulario con algunos TBF se vería así:</p>
<p><img src="http://www.albertmata.net/public/uploads/2008/12/textboxfocused1.jpg" alt="" title="textboxfocused1" width="341" height="337" class="aligncenter size-full wp-image-151" /></p>
<p>Como se puede apreciar, sin tener que añadir código alguno al formulario, el TBF aparecerá sombreado cuando tenga el foco. Además cuando se esté introduciendo un texto se mostrará en rojo, y cuando ya esté validado quedará en verde, tal como se aprecia en las siguientes imágenes:</p>
<p><img src="http://www.albertmata.net/public/uploads/2008/12/textboxfocused2.jpg" alt="" title="textboxfocused2" class="aligncenter size-full wp-image-152" /></p>
<p><img src="http://www.albertmata.net/public/uploads/2008/12/textboxfocused3.jpg" alt="" title="textboxfocused3" width="344" height="339" class="aligncenter size-full wp-image-153" /></p>
<p>Nada realmente espectacular, pero queda bonito. Sin embargo en donde el TBF se muestra útil es en el control del contenido introducido. Este control se realiza de una doble manera: a priori y mediante una propiedad del control se establece qué tipo de introducciones se admitirán, a posteriori -si se ha seleccionado- se controla que lo que se ha introducido realmente fuera lo que se debía introducir, impidiendo abandonar el TBF en caso contrario.</p>
<p>Para ello, en la ventana de propiedades del control nos aparecen dos nuevas creadas para la ocasión, tal como se muestra a continuación:</p>
<p><img src="http://www.albertmata.net/public/uploads/2008/12/textboxfocused4.jpg" alt="" title="textboxfocused4" width="402" height="43" class="aligncenter size-full wp-image-154" /></p>
<p><img src="http://www.albertmata.net/public/uploads/2008/12/textboxfocused5.jpg" alt="" title="textboxfocused5" width="405" height="216" class="aligncenter size-full wp-image-155" /></p>
<p><img src="http://www.albertmata.net/public/uploads/2008/12/textboxfocused6.jpg" alt="" title="textboxfocused6" width="403" height="69" class="aligncenter size-full wp-image-156" /></p>
<p>En las propiedades de cosecha propia siempre añado el prefijo "am" para localizarlas todas juntas. En este caso amAllow permite fijar qué introducciones se permitirán (cualquier cosa, nada de nada, sólo enteros positivos, dobles negativos, etc.) y amPostVerification decide si se aplicará verificación posterior o no.</p>
<p>Esto de amPostVerification tiene un sentido claro. Y es que podemos decirle al control que admita números dobles negativos y así sólo permitirá introducir números, el signo negativo y el signo decimal. Pero es evidente que con esos caracteres se pueden crear expresiones que no se correspondan con un número doble negativo (p.ej. -30-3.8..-25). Con este control a posteriori verificamos que efectivamente lo sea.</p>
<p>A nivel de código el control a posteriori se podría haber implementado a base de cástings y control de errores, pero no ha sido la opción que he escogido. Queda al antojo de cada cual modificar el código como le plazca. </p>
<p>Para su implementación en una aplicación, basta con añadir una clase TextBoxFocused.vb, copiar todo el código que se adjunta a continuación, compilar la aplicación y a partir de entonces tendremos el control disponible para añadirlo en cualquier formulario. O también se puede <a href="http://www.albertmata.net/2008/06/crear-libreria-dll-en-net-%C2%A1y-utilizarla/" target="_blank"> añadir a una librería de controles personalizados</a> (que es lo que hago yo) y mantenerlo un poquito más organizado.</p>
<p>Código completo (de libre uso como todo lo que aparece publicado en este blog):</p>
<div class="code">&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#39;&#160;Author&#58;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Albert&#160;Mata&#160;&#40;www&#46;albertmata&#46;net&#41;<br />
&#39;&#160;Last&#160;time&#160;modified&#58;&#160;2008&#45;11&#45;13<br />
&#39;&#160;Description&#58;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Acts&#160;like&#160;a&#160;standard&#160;TextBox&#160;but&#160;with&#160;some&#160;<br />
&#39;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;better&#160;features&#160;like&#160;changing&#160;color&#160;when&#160;gets&#160;<br />
&#39;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;or&#160;losts&#160;focus&#160;and&#160;controlling&#160;allowed&#160;<br />
&#39;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;introductions&#46;<br />
&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
Imports&#160;System&#46;Drawing</p>
<p>Public&#160;Class&#160;TextBoxFocused<br />
&#160;&#160;&#160;&#160;Inherits&#160;System&#46;Windows&#46;Forms&#46;TextBox</p>
<p>&#35;Region&#160;&#34;Constants&#34;</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Constants&#160;for&#160;colors&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;COLOR&#95;FOCUSED&#160;As&#160;Color&#160;&#61;&#160;Color&#46;FromArgb&#40;255&#44;&#160;240&#44;&#160;157&#41;<br />
&#160;&#160;&#160;&#160;Private&#160;COLOR&#95;NON&#95;FOCUSED&#160;As&#160;Color&#160;&#61;&#160;Color&#46;White<br />
&#160;&#160;&#160;&#160;Private&#160;COLOR&#95;VALIDATED&#160;As&#160;Color&#160;&#61;&#160;Color&#46;Green<br />
&#160;&#160;&#160;&#160;Private&#160;COLOR&#95;NON&#95;VALIDATED&#160;As&#160;Color&#160;&#61;&#160;Color&#46;Red</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Constants&#160;for&#160;special&#160;keys&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;ASC&#95;BACKSPACE&#160;As&#160;Integer&#160;&#61;&#160;8<br />
&#160;&#160;&#160;&#160;Private&#160;ASC&#95;SUPPRESS&#160;As&#160;Integer&#160;&#61;&#160;127<br />
&#160;&#160;&#160;&#160;Private&#160;ASC&#95;DASH&#160;As&#160;Integer&#160;&#61;&#160;45<br />
&#160;&#160;&#160;&#160;Private&#160;ASC&#95;COMMA&#160;As&#160;Integer&#160;&#61;&#160;44</p>
<p>&#35;End&#160;Region</p>
<p>&#35;Region&#160;&#34;Enumerations&#34;</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Enumerations&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Public&#160;Enum&#160;Introduction<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;NothingAtAll<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;PositiveInteger<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;NegativeInteger<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;PositiveDouble<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;NegativeDouble<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;OnlyLetter<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;OnlyLetterOrDigit<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Password<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Everything<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;EverythingNonCasing<br />
&#160;&#160;&#160;&#160;End&#160;Enum</p>
<p>&#35;End&#160;Region</p>
<p>&#35;Region&#160;&#34;Attributes&#38;Properties&#34;</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Attributes&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;aAllow&#160;As&#160;Introduction&#160;&#61;&#160;Introduction&#46;Everything<br />
&#160;&#160;&#160;&#160;Private&#160;aPostVerification&#160;As&#160;Boolean&#160;&#61;&#160;True</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Public&#160;properties&#160;to&#160;be&#160;shown&#160;in&#160;design&#160;time&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Public&#160;Property&#160;amAllow&#40;&#41;&#160;As&#160;Introduction<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Get<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;Me&#46;aAllow<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;Get<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Set&#40;ByVal&#160;value&#160;As&#160;Introduction&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Me&#46;aAllow&#160;&#61;&#160;value<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;Set<br />
&#160;&#160;&#160;&#160;End&#160;Property<br />
&#160;&#160;&#160;&#160;Public&#160;Property&#160;amPostVerification&#40;&#41;&#160;As&#160;Boolean<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Get<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;Me&#46;aPostVerification<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;Get<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Set&#40;ByVal&#160;value&#160;As&#160;Boolean&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Me&#46;aPostVerification&#160;&#61;&#160;value<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;Set<br />
&#160;&#160;&#160;&#160;End&#160;Property</p>
<p>&#35;End&#160;Region</p>
<p>&#35;Region&#160;&#34;GraphicalControls&#34;</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Event&#160;Me&#46;GotFocus&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Sub&#160;TextBoxFocused&#95;GotFocus&#40;ByVal&#160;sender&#160;As&#160;Object&#44;&#160;&#95;<br />
&#160;&#160;&#160;&#160;ByVal&#160;e&#160;As&#160;System&#46;EventArgs&#41;&#160;Handles&#160;Me&#46;GotFocus<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;MyBase&#46;BackColor&#160;&#61;&#160;COLOR&#95;FOCUSED<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;MyBase&#46;ForeColor&#160;&#61;&#160;COLOR&#95;NON&#95;VALIDATED<br />
&#160;&#160;&#160;&#160;End&#160;Sub</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Event&#160;Me&#46;LostFocus&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Sub&#160;TextBoxFocused&#95;LostFocus&#40;ByVal&#160;sender&#160;As&#160;Object&#44;&#160;&#95;<br />
&#160;&#160;&#160;&#160;ByVal&#160;e&#160;As&#160;System&#46;EventArgs&#41;&#160;Handles&#160;Me&#46;LostFocus<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Me&#46;CheckText&#40;&#41;&#160;Or&#160;Not&#160;Me&#46;aPostVerification&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;MyBase&#46;BackColor&#160;&#61;&#160;COLOR&#95;NON&#95;FOCUSED<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;MyBase&#46;ForeColor&#160;&#61;&#160;COLOR&#95;VALIDATED<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Else<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Me&#46;Focus&#40;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;End&#160;Sub</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Event&#160;Me&#46;KeyPress&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Sub&#160;TextBoxFocused&#95;KeyPress&#40;ByVal&#160;sender&#160;As&#160;Object&#44;&#160;&#95;<br />
&#160;&#160;&#160;&#160;ByVal&#160;e&#160;As&#160;System&#46;Windows&#46;Forms&#46;KeyPressEventArgs&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;Handles&#160;Me&#46;KeyPress<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Select&#160;Case&#160;Me&#46;aAllow<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;NothingAtAll<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Allowing&#160;no&#160;character&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;e&#46;Handled&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#61;&#160;ASC&#95;BACKSPACE&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;MyBase&#46;Text&#160;&#61;&#160;&#34;&#34;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;PositiveInteger<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Allowing&#160;just&#160;digits&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Not&#160;Char&#46;IsDigit&#40;e&#46;KeyChar&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;BACKSPACE&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;SUPPRESS&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;e&#46;Handled&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;NegativeInteger<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Allowing&#160;just&#160;digits&#160;and&#160;&#39;&#45;&#39;&#160;character&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Not&#160;Char&#46;IsDigit&#40;e&#46;KeyChar&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;BACKSPACE&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;SUPPRESS&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;DASH&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;e&#46;Handled&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;PositiveDouble<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Allowing&#160;just&#160;digits&#160;and&#160;&#39;&#44;&#39;&#160;character&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Not&#160;Char&#46;IsDigit&#40;e&#46;KeyChar&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;BACKSPACE&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;SUPPRESS&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;COMMA&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;e&#46;Handled&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;NegativeDouble<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Allowing&#160;just&#160;digits&#160;and&#160;&#39;&#45;&#39;&#160;and&#160;&#39;&#44;&#39;&#160;characters&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Not&#160;Char&#46;IsDigit&#40;e&#46;KeyChar&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;BACKSPACE&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;SUPPRESS&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;DASH&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;COMMA&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;e&#46;Handled&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;OnlyLetter<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Allowing&#160;only&#160;letters&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Not&#160;Char&#46;IsLetter&#40;e&#46;KeyChar&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;BACKSPACE&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;SUPPRESS&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;e&#46;Handled&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Else<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;e&#46;KeyChar&#160;&#61;&#160;Char&#46;ToUpper&#40;e&#46;KeyChar&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;OnlyLetterOrDigit<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Allowing&#160;only&#160;letters&#160;and&#160;digits&#160;and&#160;upper&#160;casing&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;letters&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Not&#160;Char&#46;IsLetterOrDigit&#40;e&#46;KeyChar&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;BACKSPACE&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;SUPPRESS&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;e&#46;Handled&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Else<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;e&#46;KeyChar&#160;&#61;&#160;Char&#46;ToUpper&#40;e&#46;KeyChar&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;Password<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Allowing&#160;only&#160;letters&#160;and&#160;digits&#160;but&#160;not&#160;upper&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;casing&#160;letters&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Not&#160;Char&#46;IsLetterOrDigit&#40;e&#46;KeyChar&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;BACKSPACE&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;AscW&#40;e&#46;KeyChar&#41;&#160;&#60;&#62;&#160;ASC&#95;SUPPRESS&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;e&#46;Handled&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;Everything<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Allowing&#160;everything&#160;upper&#160;casing&#160;letters&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;e&#46;KeyChar&#160;&#61;&#160;Char&#46;ToUpper&#40;e&#46;KeyChar&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;EverythingNonCasing<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Allowing&#160;everything&#160;not&#160;upper&#160;casing&#160;letters&#160;&#40;so&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;doing&#160;nothing&#41;&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;Select<br />
&#160;&#160;&#160;&#160;End&#160;Sub</p>
<p>&#35;End&#160;Region</p>
<p>&#35;Region&#160;&#34;PrivateMethods&#34;</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Checks&#160;introduced&#160;text&#160;according&#160;to&#160;Me&#46;amAllow&#160;property&#160;and&#160;<br />
&#160;&#160;&#160;&#160;&#39;&#160;returns&#160;True&#160;only&#160;when&#160;introduced&#160;text&#160;respects&#160;desired&#160;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Me&#46;amAllow&#160;property&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Function&#160;CheckText&#40;&#41;&#160;As&#160;Boolean<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Select&#160;Case&#160;Me&#46;aAllow<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;NothingAtAll<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Checking&#160;no&#160;character&#160;has&#160;been&#160;introduced&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;Me&#46;Text&#160;&#61;&#160;&#34;&#34;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;PositiveInteger<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Checking&#160;a&#160;right&#160;positive&#160;integer&#160;has&#160;been&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;introduced&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;Me&#46;IsPositiveInteger&#40;Me&#46;Text&#41;&#160;Or&#160;Me&#46;Text&#160;&#61;&#160;&#34;&#34;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;NegativeInteger<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Checking&#160;a&#160;right&#160;negative&#160;integer&#160;has&#160;been&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;introduced&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;Me&#46;IsNegativeInteger&#40;Me&#46;Text&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Or&#160;Me&#46;IsPositiveInteger&#40;Me&#46;Text&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Or&#160;Me&#46;Text&#160;&#61;&#160;&#34;&#34;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;PositiveDouble<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Checking&#160;a&#160;right&#160;positive&#160;double&#160;has&#160;been&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;introduced&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;Me&#46;IsPositiveDouble&#40;Me&#46;Text&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Or&#160;Me&#46;IsPositiveInteger&#40;Me&#46;Text&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Or&#160;Me&#46;Text&#160;&#61;&#160;&#34;&#34;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;NegativeDouble<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Checking&#160;a&#160;right&#160;negative&#160;double&#160;has&#160;been&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;introduced&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;Me&#46;IsNegativeDouble&#40;Me&#46;Text&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Or&#160;Me&#46;IsPositiveDouble&#40;Me&#46;Text&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Or&#160;Me&#46;IsNegativeInteger&#40;Me&#46;Text&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Or&#160;Me&#46;IsPositiveInteger&#40;Me&#46;Text&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Or&#160;Me&#46;Text&#160;&#61;&#160;&#34;&#34;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;OnlyLetter<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Checking&#160;only&#160;letters&#160;have&#160;been&#160;introduced&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;Me&#46;HasOnlyLetters&#40;Me&#46;Text&#41;&#160;Or&#160;Me&#46;Text&#160;&#61;&#160;&#34;&#34;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;OnlyLetterOrDigit&#44;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Introduction&#46;Password<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Allowing&#160;only&#160;letters&#160;and&#160;digits&#160;have&#160;been&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;introduced&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;Me&#46;HasOnlyLettersOrDigits&#40;Me&#46;Text&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Or&#160;Me&#46;Text&#160;&#61;&#160;&#34;&#34;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Case&#160;Introduction&#46;Everything&#44;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Introduction&#46;EverythingNonCasing<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Allowing&#160;everything&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;Select<br />
&#160;&#160;&#160;&#160;End&#160;Function</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Checks&#160;a&#160;right&#160;positive&#160;integer&#160;has&#160;been&#160;introduced&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Function&#160;IsPositiveInteger&#40;ByVal&#160;S&#160;As&#160;String&#41;&#160;As&#160;Boolean<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;R&#160;As&#160;Boolean<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Not&#160;String&#46;IsNullOrEmpty&#40;S&#41;&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;IT&#160;As&#160;IEnumerator&#160;&#61;&#160;S&#46;GetEnumerator&#40;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;C&#160;As&#160;Char<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;While&#160;IT&#46;MoveNext&#160;And&#160;R<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;C&#160;&#61;&#160;DirectCast&#40;IT&#46;Current&#44;&#160;Char&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;Char&#46;IsDigit&#40;C&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;While<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Else<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;False<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;R<br />
&#160;&#160;&#160;&#160;End&#160;Function</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Checks&#160;a&#160;right&#160;negative&#160;integer&#160;has&#160;been&#160;introduced&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Function&#160;IsNegativeInteger&#40;ByVal&#160;S&#160;As&#160;String&#41;&#160;As&#160;Boolean<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;R&#160;As&#160;Boolean<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Not&#160;String&#46;IsNullOrEmpty&#40;S&#41;&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;IT&#160;As&#160;IEnumerator&#160;&#61;&#160;S&#46;GetEnumerator&#40;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;C&#160;As&#160;Char<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;While&#160;IT&#46;MoveNext&#160;And&#160;R<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;C&#160;&#61;&#160;DirectCast&#40;IT&#46;Current&#44;&#160;Char&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;Char&#46;IsDigit&#40;C&#41;&#160;OrElse&#160;C&#160;&#61;&#160;ChrW&#40;ASC&#95;DASH&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;While<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Else<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;False<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Checking&#58;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;&#160;&#160;&#45;&#160;first&#160;character&#160;is&#160;a&#160;dash&#160;character&#44;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;&#160;&#160;&#45;&#160;length&#160;must&#160;be&#160;at&#160;least&#160;2&#160;characters&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;R&#160;And&#160;S&#46;LastIndexOf&#40;ChrW&#40;ASC&#95;DASH&#41;&#41;&#160;&#61;&#160;0&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;S&#46;Length&#160;&#62;&#61;&#160;2<br />
&#160;&#160;&#160;&#160;End&#160;Function</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Checks&#160;a&#160;right&#160;positive&#160;double&#160;has&#160;been&#160;introduced&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Function&#160;IsPositiveDouble&#40;ByVal&#160;S&#160;As&#160;String&#41;&#160;As&#160;Boolean<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;R&#160;As&#160;Boolean<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Not&#160;String&#46;IsNullOrEmpty&#40;S&#41;&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;IT&#160;As&#160;IEnumerator&#160;&#61;&#160;S&#46;GetEnumerator&#40;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;C&#160;As&#160;Char<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;While&#160;IT&#46;MoveNext&#160;And&#160;R<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;C&#160;&#61;&#160;DirectCast&#40;IT&#46;Current&#44;&#160;Char&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;Char&#46;IsDigit&#40;C&#41;&#160;OrElse&#160;C&#160;&#61;&#160;ChrW&#40;ASC&#95;COMMA&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;While<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Else<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;False<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Checking&#58;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;&#160;&#160;&#45;&#160;there&#39;s&#160;one&#160;comma&#160;character&#160;and&#160;it&#39;s&#160;not&#160;the&#160;first&#160;one&#44;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;&#160;&#160;&#45;&#160;there&#39;s&#160;exactly&#160;only&#160;one&#160;comma&#160;character&#44;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;&#160;&#160;&#45;&#160;the&#160;comma&#160;character&#160;it&#39;s&#160;not&#160;the&#160;last&#160;one&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;R&#160;And&#160;S&#46;IndexOf&#40;ChrW&#40;ASC&#95;COMMA&#41;&#41;&#160;&#62;&#160;0&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;S&#46;IndexOf&#40;ChrW&#40;ASC&#95;COMMA&#41;&#41;&#160;&#61;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;S&#46;LastIndexOf&#40;ChrW&#40;ASC&#95;COMMA&#41;&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;S&#46;LastIndexOf&#40;ChrW&#40;ASC&#95;COMMA&#41;&#41;&#160;&#60;&#160;S&#46;Length&#160;&#45;&#160;1<br />
&#160;&#160;&#160;&#160;End&#160;Function</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Checks&#160;a&#160;right&#160;negative&#160;double&#160;has&#160;been&#160;introduced&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Function&#160;IsNegativeDouble&#40;ByVal&#160;S&#160;As&#160;String&#41;&#160;As&#160;Boolean<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;R&#160;As&#160;Boolean<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Not&#160;String&#46;IsNullOrEmpty&#40;S&#41;&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;IT&#160;As&#160;IEnumerator&#160;&#61;&#160;S&#46;GetEnumerator&#40;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;C&#160;As&#160;Char<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;While&#160;IT&#46;MoveNext&#160;And&#160;R<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;C&#160;&#61;&#160;DirectCast&#40;IT&#46;Current&#44;&#160;Char&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;Char&#46;IsDigit&#40;C&#41;&#160;OrElse&#160;C&#160;&#61;&#160;ChrW&#40;ASC&#95;DASH&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;OrElse&#160;C&#160;&#61;&#160;ChrW&#40;ASC&#95;COMMA&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;While<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Else<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;False<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Checking&#58;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;&#160;&#160;&#45;&#160;first&#160;character&#160;is&#160;a&#160;dash&#160;character&#44;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;&#160;&#160;&#45;&#160;length&#160;must&#160;be&#160;at&#160;least&#160;4&#160;characters&#44;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;&#160;&#160;&#45;&#160;there&#39;s&#160;one&#160;comma&#160;character&#160;and&#160;it&#39;s&#160;not&#160;the&#160;first&#160;or&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;&#160;&#160;&#160;&#160;second&#160;one&#160;&#40;&#45;0&#44;0&#41;&#44;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;&#160;&#160;&#45;&#160;there&#39;s&#160;exactly&#160;only&#160;one&#160;comma&#160;character&#44;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;&#160;&#160;&#45;&#160;the&#160;comma&#160;character&#160;it&#39;s&#160;not&#160;the&#160;last&#160;one&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;R&#160;And&#160;S&#46;LastIndexOf&#40;ChrW&#40;ASC&#95;DASH&#41;&#41;&#160;&#61;&#160;0&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;S&#46;Length&#160;&#62;&#61;&#160;4&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;S&#46;IndexOf&#40;ChrW&#40;ASC&#95;COMMA&#41;&#41;&#160;&#62;&#160;1&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;S&#46;IndexOf&#40;ChrW&#40;ASC&#95;COMMA&#41;&#41;&#160;&#61;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;S&#46;LastIndexOf&#40;ChrW&#40;ASC&#95;COMMA&#41;&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;And&#160;S&#46;LastIndexOf&#40;ChrW&#40;ASC&#95;COMMA&#41;&#41;&#160;&#60;&#160;S&#46;Length&#160;&#45;&#160;1<br />
&#160;&#160;&#160;&#160;End&#160;Function</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Checks&#160;only&#160;letters&#160;have&#160;been&#160;introduced&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Function&#160;HasOnlyLetters&#40;ByVal&#160;S&#160;As&#160;String&#41;&#160;As&#160;Boolean<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;R&#160;As&#160;Boolean<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Not&#160;String&#46;IsNullOrEmpty&#40;S&#41;&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;IT&#160;As&#160;IEnumerator&#160;&#61;&#160;S&#46;GetEnumerator&#40;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;C&#160;As&#160;Char<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;While&#160;IT&#46;MoveNext&#160;And&#160;R<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;C&#160;&#61;&#160;DirectCast&#40;IT&#46;Current&#44;&#160;Char&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;Char&#46;IsLetter&#40;C&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;While<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Else<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;False<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;R<br />
&#160;&#160;&#160;&#160;End&#160;Function</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Checks&#160;only&#160;letters&#160;and&#160;digits&#160;have&#160;been&#160;introduced&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Function&#160;HasOnlyLettersOrDigits&#40;ByVal&#160;S&#160;As&#160;String&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;As&#160;Boolean<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;R&#160;As&#160;Boolean<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Not&#160;String&#46;IsNullOrEmpty&#40;S&#41;&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;IT&#160;As&#160;IEnumerator&#160;&#61;&#160;S&#46;GetEnumerator&#40;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;C&#160;As&#160;Char<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;True<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;While&#160;IT&#46;MoveNext&#160;And&#160;R<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;C&#160;&#61;&#160;DirectCast&#40;IT&#46;Current&#44;&#160;Char&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;Char&#46;IsLetterOrDigit&#40;C&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;While<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Else<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;R&#160;&#61;&#160;False<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;R<br />
&#160;&#160;&#160;&#160;End&#160;Function</p>
<p>&#35;End&#160;Region</p>
<p>End&#160;Class</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.albertmata.net/2008/12/textbox-mejorado-en-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Formato no disponible en Snapshot de Access.</title>
		<link>http://www.albertmata.net/2008/06/formato-no-disponible-en-snapshot-de-access/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=formato-no-disponible-en-snapshot-de-access</link>
		<comments>http://www.albertmata.net/2008/06/formato-no-disponible-en-snapshot-de-access/#comments</comments>
		<pubDate>Mon, 09 Jun 2008 07:10:14 +0000</pubDate>
		<dc:creator>Albert Mata</dc:creator>
				<category><![CDATA[Access]]></category>
		<category><![CDATA[Batch]]></category>
		<category><![CDATA[Herramientas]]></category>
		<category><![CDATA[snapshot]]></category>

		<guid isPermaLink="false">http://www.albertmata.net/?p=32</guid>
		<description><![CDATA[Hace un tiempo, cuando me dedicaba fundamentalmente a programar aplicaciones en Access, me encontré con un problema que irremediablemente todos mis clientes sufrían tarde o temprano. Es un problema que se refiere a las versiones XP y 2003 (ignoro si alguna más) y que ocurre cuando se quiere generar un informe en formato Snapshot. Este [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-33" title="snapshot" src="http://www.albertmata.net/public/uploads/2008/06/snapshot.jpg" alt="" width="253" height="199" />Hace un tiempo, cuando me dedicaba fundamentalmente a programar aplicaciones en <strong>Access</strong>, me encontré con un problema que irremediablemente todos mis clientes sufrían tarde o temprano. Es un problema que se refiere a las versiones <strong>XP</strong> y <strong>2003</strong> (ignoro si alguna más) y que ocurre cuando se quiere generar un informe en formato <strong>Snapshot</strong>. Este formato es muy útil para exportar informes en archivos <strong>.snp</strong> que se pueden visualizar desde prácticamente cualquier ordenador (y si no existe un <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=b73df33f-6d74-423d-8274-8b7e6313edfb&amp;displaylang=en" target="_blank">visualizador gratuito de <strong>Microsoft</strong></a>).</p>
<p>Bien, el problema increíblemente reside en que al instalar <strong>Microsoft Access</strong> en español, la instalación crea una clave en el registro de <strong>Windows</strong> (<strong>regedit.exe</strong>) con la descripción en castellano:</p>
<div class="code">snp,,1,Formato Snapshot (*.snp),0</div>
<p>Pero cuando el propio <strong>Access</strong> busca el valor para esa clave espera encontrarlo en inglés:</p>
<div class="code">snp,,1,Snapshot Format (*.snp),0</div>
<p>Y al no encontrarlo muestra un mensaje diciendo que el formato en cuestión no está disponible. O sea, una chapuza monumental de los señores de <strong>Microsoft</strong>, sí.</p>
<p>Para solucionar esto simplemente hay que cambiar la entrada correspondiente en el registro de <strong>Windows</strong> para cambiar el primer valor por el segundo. Ojito, todos sabemos que puede ser crítico cambiar cosas en dicho registro, así que cada cual sabrá lo que hace (pero este cambio es bastante inofensivo, eso sí <img src='http://www.albertmata.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ). En cualquier caso la entrada a modificar es la siguiente para <strong>Access XP</strong>:</p>
<div class="code">HKEY_LOCAL_MACHINE\_<br />
&#160;&#160;&#160;&#160;&#160;SOFTWARE\Microsoft\Office\10.0\Access\Report Formats</div>
<p>Y esta otra para <strong>Access 2003</strong>:</p>
<div class="code">HKEY_LOCAL_MACHINE\_<br />
&#160;&#160;&#160;&#160;&#160;SOFTWARE\Microsoft\Office\11.0\Access\Report Formats</div>
<p>Y la entrada concreta a la que hay que cambiarle el valor es <strong>Snapshot Format</strong>.</p>
<p>A mis clientes solía enviarles un archivo <strong>.bat</strong> para facilitarles la modificación, que consistía simplemente en la instrucción:</p>
<div class="code">REG ADD &#34;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\<br />
Office\11.0\Access\Report Formats&#34; /v &#34;Snapshot Format&#34; /d &#34;snp,<br />
,1,Snapshot Format(*.snp),0&#34; /f</div>
<p>Todo junto en la misma línea y sin espacios en los saltos de línea, ¿ok? Ah, y en donde pone <strong>11.0</strong> cambiarlo por <strong>10.0</strong> cuando la versión de <strong>Access</strong> sea la <strong>XP</strong>.</p>
<p>Por último añadir que en mi caso el uso del formato <strong>Snapshot</strong> era como paso intermedio para la creación de archivos <strong>PDF</strong> directamente desde <strong>Access</strong> sin necesidad de tener instalada ninguna impresora <strong>PDF</strong>, utilizando para ello la magnífica herramienta de <strong><a href="http://www.lebans.com" target="_blank">Lebans</a></strong>.</p>
<p><strong>Actualización:</strong> Iván aporta amablemente en los comentarios de esta misma entrada que en su caso para que pasara a funcionarle tuvo que cambiar el valor en castellano por este otro:</p>
<div class="code">Formats\snp,,1,Snapshot Format (*.snp),0</div>
<p>Es decir, añadiéndole el <strong>Formats\</strong> delante. Así que si estáis intentando resolver este problema y con las indicaciones del post no se os resuelve, no dejéis de probar también esta alternativa.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.albertmata.net/2008/06/formato-no-disponible-en-snapshot-de-access/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Copias de seguridad en MySQL con mysqldump.</title>
		<link>http://www.albertmata.net/2008/06/copias-de-seguridad-en-mysql-con-mysqldump/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=copias-de-seguridad-en-mysql-con-mysqldump</link>
		<comments>http://www.albertmata.net/2008/06/copias-de-seguridad-en-mysql-con-mysqldump/#comments</comments>
		<pubDate>Thu, 05 Jun 2008 18:54:34 +0000</pubDate>
		<dc:creator>Albert Mata</dc:creator>
				<category><![CDATA[Batch]]></category>
		<category><![CDATA[Herramientas]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[bases de datos]]></category>
		<category><![CDATA[copias de seguridad]]></category>
		<category><![CDATA[gnu-gpl]]></category>
		<category><![CDATA[mysqldump]]></category>

		<guid isPermaLink="false">http://www.albertmata.net/?p=30</guid>
		<description><![CDATA[En los pocos días de vida que tiene este blog es posible que haya mencionado ya que en el proyecto en el que estoy trabajando actualmente estamos utilizando una base de datos MySQL. Sí, lo sé, unas cuantas veces llevo ya... pero es que realmente va muy bien, estamos muy contentos con sus prestaciones hasta [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-31" title="mysqldump" src="http://www.albertmata.net/public/uploads/2008/06/mysqldump.jpg" alt="" width="233" height="118" />En los pocos días de vida que tiene este blog es posible que haya mencionado ya que en el proyecto en el que estoy trabajando actualmente estamos utilizando una base de datos <strong>MySQL</strong>. Sí, lo sé, unas cuantas veces llevo ya... pero es que realmente va muy bien, estamos muy contentos con sus prestaciones hasta la fecha. Se está mostrando rápida y muy fiable... y todo ello con una licencia <strong>GPL</strong>, no lo olvidemos.</p>
<p>Bueno, el caso es que como es evidente, cuando trabajamos con cualquier sistema tenemos que tener muy bien previsto un método decente de copias de seguridad. En el caso de <strong>MySQL</strong> tenemos varias alternativas, pero la que a mí más me ha convencido ha sido la herramienta <strong>mysqldump</strong>. Es realmente sencilla de utilizar y tremendamente funcional. Su funcionamiento exacto con las decenas de opciones que admite se puede encontrar en el propio <a href="http://dev.mysql.com/doc/refman/5.0/en/mysqldump.html" target="_blank">manual de referencia de MySQL</a>. No requiere instalación alguna, simple y llanamente que dispongamos del archivo <strong>mysqldump.exe</strong> que conseguiremos sin problemas en la página oficial de <strong>MySQL</strong> y que si hemos instalado el servidor <strong>MySQL</strong> probablemente tendremos ya en nuestro equipo.</p>
<p>La herramienta <strong>mysqldump</strong> nos genera archivos con extensión <strong>.sql</strong> que incluyen -según hayamos configurado- las instrucciones necesarias para restaurar una base de datos entera -o todas las que tengamos en el servidor <strong>MySQL</strong>-, desde su creación hasta la adición de los datos pasando por la creación de las tablas. Realmente completito. Para una restauración sólo habría que hacer algo así en una línea de comandos (<strong>localhost</strong> o servidor según corresponda):</p>
<div class="code">mysql -u root -p -h localhost &lt; C:\archivo_backup.sql</div>
<p>No obstante lo que quiero explicar hoy es cómo he automatizado estas copias de seguridad que hago con <strong>mysqldump</strong> a través de un archivo <strong>batch</strong>. Expongo código y después lo comento.</p>
<div class="code">&#64;echo&#160;off</p>
<p>set&#160;path&#95;mysqldump&#61;&#34;C&#58;&#92;Program&#160;Files&#92;MySQL&#92;MySQL&#160;Server&#160;5&#46;0&#92;bin&#34;<br />
set&#160;path&#95;backups&#61;&#34;&#92;&#92;99&#46;24&#46;13&#46;29&#92;BBDD&#92;Backups&#34;<br />
set&#160;user&#61;root<br />
set&#160;password&#61;mi&#95;password<br />
set&#160;host&#61;99&#46;24&#46;13&#46;26</p>
<p>if&#160;&#37;time&#58;&#126;0&#44;2&#37;&#160;GEQ&#160;10&#160;goto&#160;&#58;DespuesDeLas10</p>
<p>&#58;AntesDeLas10<br />
&#37;path&#95;mysqldump&#37;&#92;mysqldump&#160;&#45;&#45;user&#61;&#37;user&#37;&#160;&#45;&#45;password&#61;&#37;password&#37;&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#45;h&#160;&#37;host&#37;&#160;&#45;&#45;databases&#160;db&#95;offers&#160;&#45;&#45;single&#45;transaction&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#62;&#160;&#37;path&#95;backups&#37;&#92;backup&#95;&#37;date&#58;&#126;6&#44;4&#37;&#37;date&#58;&#126;3&#44;2&#37;&#37;date&#58;&#126;0&#44;2&#37;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#95;0&#37;time&#58;&#126;1&#44;1&#37;&#37;time&#58;&#126;3&#44;2&#37;&#46;sql<br />
goto&#160;&#58;Salir</p>
<p>&#58;DespuesDeLas10<br />
&#37;path&#95;mysqldump&#37;&#92;mysqldump&#160;&#45;&#45;user&#61;&#37;user&#37;&#160;&#45;&#45;password&#61;&#37;password&#37;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#45;h&#160;&#37;host&#37;&#160;&#45;&#45;databases&#160;db&#95;offers&#160;&#45;&#45;single&#45;transaction&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#62;&#160;&#37;path&#95;backups&#37;&#92;backup&#95;&#37;date&#58;&#126;6&#44;4&#37;&#37;date&#58;&#126;3&#44;2&#37;&#37;date&#58;&#126;0&#44;2&#37;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#95;&#37;time&#58;&#126;0&#44;2&#37;&#37;time&#58;&#126;3&#44;2&#37;&#46;sql<br />
&#58;Salir</p></div>
<p>Antes que nada, comentar que las líneas que comienzan por <strong>%path</strong>... aparecen aquí cortadas por temas de espacio (en píxeles, no en bytes <img src='http://www.albertmata.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ) en el blog, pero en realidad deben formar una sola línea que termina con <strong>.sql</strong>. Debe haber un espacio entre <strong>%password%</strong> y <strong>-h</strong> y después otro entre <strong>transaction</strong> y <strong>&gt; %path_</strong>, pero en cambio la última linea va sin espacio (<strong>%date:~0,2%_0%time</strong> va todo seguido, ¿ok?).</p>
<p>Paso a explicarlo. Las primeras cinco líneas después del archiconocido <strong>@echo off</strong> son asignaciones de valores a las variables que después utilizaremos. Es la parte de configuración del archivo <strong>batch</strong>.</p>
<p>1) <strong>path_mysqldump</strong> contiene la ruta del directorio donde se encuentra el archivo <strong>mysqldump.exe</strong>.</p>
<p>2) <strong>path_backups</strong> contiene la ruta del directorio donde se almacenará la copia de seguridad, en este ejemplo he puesto una carpeta en un servidor.</p>
<p>3) <strong>user</strong> es el usuario con el que se ejecutará <strong>mysqldump</strong>. Parece una perogrullada, pero hay que tener en cuenta que debe disponer de permisos suficientes, aunque no es necesario que sea el usuario <strong>root</strong> (de hecho mucho mejor si no lo es, ya que así no quedará en un archivo <strong>batch</strong> visualizable el password del usuario <strong>root</strong>).</p>
<p>4) <strong>password</strong> es... sí, eso.</p>
<p>5) <strong>host</strong> es la máquina donde se encuentra el servidor <strong>MySQL</strong> que queremos backupear. Si es nuestro propio ordenador escribiremos <strong>localhost</strong>. A destacar que el servidor <strong>MySQL</strong> debe estar corriendo en el momento de lanzar el <strong>mysqldump</strong>.</p>
<p>Lo que sigue es ya la ejecución. En mi caso las copias de seguridad las quiero en formato <strong>backup_YYYYMMDD_HHMM</strong> con la fecha y la hora de esta manera, ya que así una simple ordenación alfabética de los archivos lleva a cabo también una ordenación por fechas. Para lograr eso hay que jugar con los <strong>date:~6,4</strong> y similares y además hay que programar dos ramas en función de que sean antes o después de las 10 de la mañana, ya que hasta entonces necesito concatenar un <strong>0</strong> y un <strong>time:~1,1</strong> para la hora con dos dígitos y a partir de las 10 me vale con <strong>time:~0,2</strong>. Podemos prescindir de hacer estas dos alternativas si vamos a lanzar siempre el batch a la misma hora y será más tardía que esas 10am de la <em>madrugada</em>. En cualquier caso para discernir entre si seguir un camino u otro utilizamos el...</p>
<div class="code">if %time:~0,2% GEQ 10 goto <img src='http://www.albertmata.net/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> espuesDeLas10</div>
<p>...donde <strong>GEQ</strong> equivale a lo que en lenguaje de programación normal y corriente diríamos <strong>&gt;=</strong>.</p>
<p>Por último comentar que con esto obtenemos un archivo <strong>.bat</strong> que podemos ejecutar manualmente o programar para que se ejecute periódicamente a nuestro antojo. Por ejemplo con una simple tarea programada de <strong>Windows</strong> si no nos queremos complicar demasiado la vida.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.albertmata.net/2008/06/copias-de-seguridad-en-mysql-con-mysqldump/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Sobrevivir a los cáràctërês extraños.</title>
		<link>http://www.albertmata.net/2008/06/sobrevivir-a-los-caracteres-extranos/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=sobrevivir-a-los-caracteres-extranos</link>
		<comments>http://www.albertmata.net/2008/06/sobrevivir-a-los-caracteres-extranos/#comments</comments>
		<pubDate>Tue, 03 Jun 2008 05:55:52 +0000</pubDate>
		<dc:creator>Albert Mata</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Herramientas]]></category>
		<category><![CDATA[entidades]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.albertmata.net/?p=27</guid>
		<description><![CDATA[Pues aquí está lo que comentaba en el post anterior: una pequeña y simple aplicación que sirve para traducir masivamente caracteres a sus correspondientes entidades seguras. Digo pequeña y simple porque realmente lo es: no está especialmente optimizada ni tiene muchas opciones que digamos. Apenas un textbox para introducir el texto a... mmmh "codificar", y [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-28" title="xml_logo2" src="http://www.albertmata.net/public/uploads/2008/06/xml_logo2.jpg" alt="" width="257" height="73" />Pues aquí está lo que comentaba en el <a href="http://www.albertmata.net/?p=25" target="_blank">post anterior</a>: una pequeña y simple aplicación que sirve para traducir masivamente caracteres a sus correspondientes entidades seguras. Digo pequeña y simple porque realmente lo es: no está especialmente optimizada ni tiene muchas opciones que digamos. Apenas un <strong>textbox</strong> para introducir el texto a... mmmh "codificar", y un botón para hacerlo. Nada más. Se me ocurre que se podría mejorar haciendo que sólo cambie un espacio por <strong>&amp;#160;</strong> cuando haya más de uno consecutivo con el fin de no inundar de <strong>&amp;#160;</strong> un texto normal convirtiéndolo así en ilegible. También se podría ofrecer al usuario de la aplicación la opción de parametrizar qué entidades quiere reemplazar y cuáles no, ya que yo por ejemplo sí que reemplazo <strong>&lt;</strong> y <strong>&gt;</strong> porque en realidad no utilizo la aplicación para páginas web, sino para los fragmentos de código de este propio blog. Pero está claro que alguien que utilice una aplicación así para páginas web no querrá reemplazar esos dos caracteres ni tampoco la barra <strong>/</strong>.</p>
<p>En fin, sólo sugiero posibles modificaciones que le puede hacer al programita quien lo desee.</p>
<p>Aquí dejo el link para descargarse el ejecutable correspondiente. No requiere instalación alguna de mínimo que es el programita. Eso sí, como está desarrollado en <strong>.NET</strong> requerirá el correspondiente <strong>Framework</strong>. Mucha gente lo tiene ya en su ordenador sin siquiera saberlo, y si no se puede <a href="http://www.microsoft.com/downloads/details.aspx?displaylang=es&amp;FamilyID=0856eacb-4362-4b0d-8edd-aab15c5e04f5" target="_blank">descargar gratuitamente desde la página de Microsoft</a>. No es más que una especie de máquina virtual más o menos análoga a la <strong>MVJ</strong> de <strong>Java</strong>.</p>
<p><a href="http://www.albertmata.net/entidades/XMLReplacer.exe"><img class="alignnone size-medium wp-image-29" title="linkreplacer" src="http://www.albertmata.net/public/uploads/2008/06/linkreplacer.jpg" alt="" width="109" height="71" /></a></p>
<p>El programa está basado sólo en un formulario y una clase auxiliar. He aquí el código del formulario principal:</p>
<div class="code">&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#39;&#160;Author&#58;&#160;Albert&#160;Mata&#160;&#40;www&#46;albertmata&#46;net&#41;<br />
&#39;&#160;Date&#58;&#160;20080601<br />
&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;</p>
<p>&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#39;&#160;Main&#160;class&#160;to&#160;replace&#160;all&#160;problematic&#160;characters&#160;in&#160;a<br />
&#39;&#160;text&#160;to&#160;make&#160;it&#160;XML&#45;valid&#46;<br />
&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
Public&#160;Class&#160;frmXML</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Attributes&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;arrEntities&#160;As&#160;New&#160;ArrayList&#40;&#41;&#160;&#39;of&#160;clsEntity</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Loads&#160;all&#160;desired&#160;entities&#160;translations&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Sub&#160;frmXML&#95;Load&#40;ByVal&#160;sender&#160;As&#160;Object&#44;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;ByVal&#160;e&#160;As&#160;System&#46;EventArgs&#41;&#160;Handles&#160;Me&#46;Load<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Me&#46;LoadEntities&#40;&#41;<br />
&#160;&#160;&#160;&#160;End&#160;Sub</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Main&#160;method&#160;to&#160;make&#160;the&#160;replacements&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Sub&#160;cmdMain&#95;Click&#40;ByVal&#160;sender&#160;As&#160;Object&#44;&#160;&#95;<br />
&#160;&#160;&#160;&#160;ByVal&#160;e&#160;As&#160;System&#46;EventArgs&#41;&#160;Handles&#160;cmdMain&#46;Click<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Me&#46;txtMain&#46;Text&#160;&#61;&#160;FullReplace&#40;Me&#46;txtMain&#46;Text&#41;<br />
&#160;&#160;&#160;&#160;End&#160;Sub</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Iterates&#160;all&#160;problematic&#160;entities&#160;and&#160;replaces&#160;them<br />
&#160;&#160;&#160;&#160;&#39;&#160;in&#160;the&#160;original&#160;text&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Function&#160;FullReplace&#40;ByVal&#160;FullString&#160;As&#160;String&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;As&#160;String<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;Temp&#160;As&#160;String&#160;&#61;&#160;FullString<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;IT&#160;As&#160;IEnumerator&#160;&#61;&#160;arrEntities&#46;GetEnumerator&#40;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;While&#160;IT&#46;MoveNext<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;Current&#160;As&#160;clsEntity&#160;&#61;&#160;IT&#46;Current<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Temp&#160;&#61;&#160;Replace&#40;Temp&#44;&#160;Current&#46;Bad&#44;&#160;Current&#46;Safe&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;While<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;Temp<br />
&#160;&#160;&#160;&#160;End&#160;Function</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Loads&#160;all&#160;entities&#160;to&#160;be&#160;replaced&#46;&#160;Make&#160;here&#160;all&#160;the<br />
&#160;&#160;&#160;&#160;&#39;&#160;changes&#160;you&#160;like&#33;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Private&#160;Sub&#160;LoadEntities&#40;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Avoiding&#160;&#34;&#38;&#35;&#59;&#34;&#160;characters&#160;are&#160;replaced&#160;twice&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;arrEntities&#46;Add&#40;New&#160;clsEntity&#40;&#34;&#38;&#34;&#44;&#160;&#34;TEMP00001&#34;&#41;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;arrEntities&#46;Add&#40;New&#160;clsEntity&#40;&#34;&#35;&#34;&#44;&#160;&#34;TEMP00002&#34;&#41;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;arrEntities&#46;Add&#40;New&#160;clsEntity&#40;&#34;&#59;&#34;&#44;&#160;&#34;TEMP00003&#34;&#41;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;arrEntities&#46;Add&#40;New&#160;clsEntity&#40;&#34;&#33;&#34;&#44;&#160;&#34;&#38;&#35;33&#59;&#34;&#41;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;arrEntities&#46;Add&#40;New&#160;clsEntity&#40;&#34;&#34;&#34;&#34;&#44;&#160;&#34;&#38;&#35;34&#59;&#34;&#41;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;HE&#160;ELIMINADO&#160;DECENAS&#160;DE&#160;ENTIDADES&#160;AQU&#205;&#160;POR&#160;NO&#160;HACER<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;UN&#160;POST&#160;KILOM&#201;TRICO&#46;&#46;&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Avoiding&#160;&#34;&#38;&#35;&#59;&#34;&#160;characters&#160;are&#160;replaced&#160;twice&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;arrEntities&#46;Add&#40;New&#160;clsEntity&#40;&#34;TEMP00001&#34;&#44;&#160;&#34;&#38;&#35;38&#59;&#34;&#41;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;arrEntities&#46;Add&#40;New&#160;clsEntity&#40;&#34;TEMP00002&#34;&#44;&#160;&#34;&#38;&#35;35&#59;&#34;&#41;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;arrEntities&#46;Add&#40;New&#160;clsEntity&#40;&#34;TEMP00003&#34;&#44;&#160;&#34;&#38;&#35;59&#59;&#34;&#41;&#41;<br />
&#160;&#160;&#160;&#160;End&#160;Sub</p>
<p>End&#160;Class</p></div>
<p>Y aquí la clase auxiliar que he utilizado:</p>
<div class="code">&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#39;&#160;Author&#58;&#160;Albert&#160;Mata&#160;&#40;www&#46;albertmata&#46;net&#41;<br />
&#39;&#160;Date&#58;&#160;20080601<br />
&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;</p>
<p>&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#39;&#160;Auxiliar&#160;class&#160;representing&#160;an&#160;entity&#160;&#40;its&#160;problematic<br />
&#39;&#160;character&#160;and&#160;the&#160;safe&#160;one)&#46;<br />
&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
Public&#160;Class&#160;clsEntity</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Attributes&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Public&#160;Bad&#160;As&#160;String<br />
&#160;&#160;&#160;&#160;Public&#160;Safe&#160;As&#160;String</p>
<p>&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;&#39;&#160;Constructor&#160;method&#46;<br />
&#160;&#160;&#160;&#160;&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#160;&#160;&#160;&#160;Public&#160;Sub&#160;New&#40;ByVal&#160;Bad&#160;As&#160;String&#44;&#160;ByVal&#160;Safe&#160;As&#160;String&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Me&#46;Bad&#160;&#61;&#160;Bad<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Me&#46;Safe&#160;&#61;&#160;Safe<br />
&#160;&#160;&#160;&#160;End&#160;Sub</p>
<p>End&#160;Class</p></div>
<p>Con esto se puede reconstruir la aplicación sin problemas, pero de todos modos si alguien está interesado en que le envíe los archivos fuente no tiene más que pedirlo por correo electrónico (mi dirección aparece en la página <strong>Acerca de mí...</strong>) y con gusto se los remitiré.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.albertmata.net/2008/06/sobrevivir-a-los-caracteres-extranos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cáràctërês extraños en XML.</title>
		<link>http://www.albertmata.net/2008/06/caracteres-extranos-en-xml/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=caracteres-extranos-en-xml</link>
		<comments>http://www.albertmata.net/2008/06/caracteres-extranos-en-xml/#comments</comments>
		<pubDate>Sun, 01 Jun 2008 07:45:07 +0000</pubDate>
		<dc:creator>Albert Mata</dc:creator>
				<category><![CDATA[Herramientas]]></category>
		<category><![CDATA[entidades]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.albertmata.net/?p=25</guid>
		<description><![CDATA[Todo aquel que en algún momento haya programado (o incluso simplemente diseñado) alguna página web se habrá encontrado con los típicos problemas al poner tildes y caracteres extraños que algunos navegadores interpretan bien y otros, oh sorpresa, no lo hacen. A mí al menos me ha pasado. Y ya no digamos si en lugar de [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-26" title="xml_logo" src="http://www.albertmata.net/public/uploads/2008/05/xml_logo.jpg" alt="" width="200" height="73" />Todo aquel que en algún momento haya programado (o incluso simplemente diseñado) alguna página web se habrá encontrado con los típicos problemas al poner tildes y caracteres extraños que algunos navegadores interpretan bien y otros, oh sorpresa, no lo hacen. A mí al menos me ha pasado. Y ya no digamos si en lugar de un documento <strong>HTML</strong> (o <strong>ASP</strong> o <strong>PHP</strong>) se trata de uno <a href="http://es.wikipedia.org/wiki/XML" target="_blank">XML</a>. En ese caso ya no hay duda posible: un documento <strong>XML</strong> no nos aceptará sin quejarse un carácter acentuado ni fuera de lo común. Total, que a menudo nos vemos obligados a recurrir a lo que se conoce como entidades, o lo que es lo mismo, en lugar de utilizar los caracteres de la primera columna utilizar los de la segunda:</p>
<div class="code">&#160;&#160;&#60;&#160;&#160;&#160;&#160;&#160;&#38;#60;<br />
&#160;&#160;&#64;&#160;&#160;&#160;&#160;&#160;&#38;#64;<br />
&#160;&#160;&#225;&#160;&#160;&#160;&#160;&#160;&#38;#225;<br />
&#160;&#160;&#241;&#160;&#160;&#160;&#160;&#160;&#38;#241;</div>
<p>También puede resultar útil si queremos poner más de un espacio consecutivo, ya que por defecto los navegadores igualan esto:</p>
<div class="code">Albert&#160;&#160;&#160;&#160;&#160;Mata</div>
<p>A esto otro:</p>
<div class="code">Albert Mata</div>
<p>Para evitarlo podemos sustituir el espacio por su propia entidad (<strong>&#38;#160;</strong>) tantas veces como deseemos y entonces se nos respetarán los espacios (de hecho así es como lo he hecho en el ejemplo anterior).</p>
<p>Total, que de vez en cuando me encuentro una vez más buceando en internet en busca de una tabla de entidades para buscar cuál era el código de una en concreto. Así que para ya no tener que hacerlo nunca más me he creado una propia donde aparecen las más habituales. La enlazo a continuación. ¡Si buscando como tantas veces antes he buscado yo das con ella, tienes mi permiso para guardarte una copia! <img src='http://www.albertmata.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p><a href="http://www.albertmata.net/entidades/" target="_blank">Tabla de entidades en HTML y XML</a>.</p>
<p>Esta tabla puede servir como recurso puntual, pero está claro que andar sustituyendo caracteres por códigos en un documento completo puede ser de lo más engorroso. Queda pues pendiente para próximo post una pequeña aplicación que nos lo haga de manera automática...</p>
]]></content:encoded>
			<wfw:commentRss>http://www.albertmata.net/2008/06/caracteres-extranos-en-xml/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simulando DLookup fuera de Access (III).</title>
		<link>http://www.albertmata.net/2008/05/simulando-dlookup-fuera-de-access-iii/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=simulando-dlookup-fuera-de-access-iii</link>
		<comments>http://www.albertmata.net/2008/05/simulando-dlookup-fuera-de-access-iii/#comments</comments>
		<pubDate>Fri, 30 May 2008 07:45:27 +0000</pubDate>
		<dc:creator>Albert Mata</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Access]]></category>
		<category><![CDATA[Herramientas]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[bases de datos]]></category>
		<category><![CDATA[connection string]]></category>
		<category><![CDATA[data adapter]]></category>
		<category><![CDATA[dlookup]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[stored function]]></category>
		<category><![CDATA[stored procedure]]></category>

		<guid isPermaLink="false">http://www.albertmata.net/?p=22</guid>
		<description><![CDATA[En los dos posts anteriores he mostrado maneras de simular un DLookup en una base de datos MySQL mediante stored procedures y stored functions (primera aproximación y versión mejorada). No obstante, ha quedado claro que hacerlo así aunque puede resultar útil tiene sus limitaciones. Es por ello que normalmente prefiero utilizar un DLookup llevado a [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.albertmata.net/public/uploads/2008/05/visualstudio.jpg" alt="" title="visualstudio" width="299" height="94" class="alignleft size-full wp-image-24" />En los dos posts anteriores he mostrado maneras de simular un DLookup en una base de datos <a href="http://www.mysql.com" target="_blank">MySQL</a> mediante stored procedures y stored functions (<a href="http://www.albertmata.net/2008/05/simulando-dlookup-fuera-de-access-i/" target="_blank">primera aproximación</a> y <a href="http://www.albertmata.net/2008/05/simulando-dlookup-fuera-de-access-ii/" target="_blank">versión mejorada</a>). No obstante, ha quedado claro que hacerlo así aunque puede resultar útil tiene sus limitaciones. Es por ello que normalmente prefiero utilizar un DLookup llevado a cabo desde la parte de la aplicación. En mi caso esto equivale a realizarlo en VisualBasic.NET. Y sin más preámbulos veamos el código de la función:</p>
<div class="code">&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#39;&#160;Author&#58;&#160;&#160;&#160;&#160;&#160;&#160;Albert&#160;Mata&#160;&#40;www&#46;albertmata&#46;net&#41;<br />
&#39;&#160;Date&#58;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;20080530<br />
&#39;&#160;Description&#58;&#160;Function&#160;to&#160;simulate&#160;Microsoft&#160;Access&#160;DLookup&#46;&#160;<br />
&#39;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
Public&#160;Function&#160;DLookup&#40;ByVal&#160;Field&#160;As&#160;String&#44;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;ByVal&#160;Table&#160;As&#160;String&#44;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Optional&#160;ByVal&#160;Condition&#160;As&#160;String&#160;&#61;&#160;&#34;TRUE&#34;&#41;&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;As&#160;Object<br />
&#160;&#160;&#160;&#160;Try<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Creating&#160;SQL&#160;string&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;SQL&#160;As&#160;String<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;SQL&#160;&#61;&#160;&#34;SELECT&#160;&#34;&#160;&#38;&#160;Field&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#38;&#160;&#34;&#160;FROM&#160;&#34;&#160;&#38;&#160;Table&#160;&#95;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#38;&#160;&#34;&#160;WHERE&#160;&#34;&#160;&#38;&#160;Condition<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Filling&#160;dataset&#160;with&#160;desired&#160;value&#46;&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;DS&#160;As&#160;New&#160;DataSet<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;DA&#160;As&#160;New&#160;MySqlDataAdapter&#40;SQL&#44;&#160;CONNECTION&#95;STRING&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;DA&#46;Fill&#40;DS&#44;&#160;&#34;anyname&#34;&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;Returning&#160;value&#160;or&#160;Null&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;If&#160;Not&#160;IsDBNull&#40;DS&#46;Tables&#40;&#34;anyname&#34;&#41;&#46;Rows&#40;0&#41;&#46;Item&#40;0&#41;&#41;&#160;Then<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;DS&#46;Tables&#40;&#34;anyname&#34;&#41;&#46;Rows&#40;0&#41;&#46;Item&#40;0&#41;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Else<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;X&#160;As&#160;Object&#160;&#61;&#160;Convert&#46;DBNull<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;X<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;End&#160;If<br />
&#160;&#160;&#160;&#160;Catch<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;If&#160;error&#160;happens&#44;&#160;returning&#160;Null&#46;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Dim&#160;X&#160;As&#160;Object&#160;&#61;&#160;Convert&#46;DBNull<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Return&#160;X<br />
&#160;&#160;&#160;&#160;End&#160;Try<br />
End&#160;Function</div>
<p>Cabe aclarar que CONNECTION_STRING será una constante definida en algún punto de la aplicación que recogerá la cadena de conexión para nuestra base de datos. En mi caso es algo como:</p>
<div class="code">Database&#160;&#61;&#160;nombre&#95;bbdd&#59;&#160;&#95;<br />
Data&#160;Source&#160;&#61;&#160;localhost&#59;&#160;&#95;<br />
User&#160;ID&#160;&#61;&#160;root&#59;&#160;&#95;<br />
Password&#160;&#61;&#160;mi&#95;password</div>
<p>Relacionado con cadenas de conexión, recomendado darse un paseo por <a href="http://www.connectionstrings.com/" target="_blank">ConnectionStrings.com</a>.</p>
<p>Yo estoy trabajando con una base de datos MySQL, por eso el DataAdapter es en realidad un MySqlDataAdapter, pero el funcionamiento sería análogo con cualquier otra base de datos y utilizando un objeto DataAdapter convencional. Lo único es que si se trabaja con MySQL es necesario previamente haber agregado la referencia correspondiente al proyecto, y para mayor comodidad en temas de nomenclatura importar el espacio de nombres correspondiente en la parte superior de la clase:</p>
<div class="code">Imports MySql.Data.MySqlClient</div>
<p>Respecto a la función, poco que explicar. Pasarle el campo y la tabla deseados y de manera opcional una condición en formato <a href="http://es.wikipedia.org/wiki/SQL" target="_blank">SQL</a> sin el WHERE. Si no se desea condición se pueden informar sólo dos argumentos, en esta ocasión no es necesario enviar una cadena vacía ni nada por el estilo. Además, el valor que nos devuelve la función es de tipo Object, así que no tendremos ningún problema con el tipo de dato devuelto, nos admitirá cualquier tipo de campo que quiera que sea el campo en cuestión de la tabla en cuestión. En caso de producirse algún error (nombre de campo o tabla mal escritos, conexión a base de datos fallida...) o si no se halla ningún registro, la función nos devolverá un valor nulo, con lo cual desde código podremos recogerlo sin problemas y actuar en consecuencia. <img src='http://www.albertmata.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.albertmata.net/2008/05/simulando-dlookup-fuera-de-access-iii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simulando DLookup fuera de Access (II).</title>
		<link>http://www.albertmata.net/2008/05/simulando-dlookup-fuera-de-access-ii/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=simulando-dlookup-fuera-de-access-ii</link>
		<comments>http://www.albertmata.net/2008/05/simulando-dlookup-fuera-de-access-ii/#comments</comments>
		<pubDate>Wed, 28 May 2008 08:20:32 +0000</pubDate>
		<dc:creator>Albert Mata</dc:creator>
				<category><![CDATA[Access]]></category>
		<category><![CDATA[Herramientas]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[bases de datos]]></category>
		<category><![CDATA[dlookup]]></category>
		<category><![CDATA[stored function]]></category>
		<category><![CDATA[stored procedure]]></category>

		<guid isPermaLink="false">http://www.albertmata.net/?p=19</guid>
		<description><![CDATA[En el anterior post expuse una manera de realizar un DLookup en MySQL mediante stored procedures y stored functions y comenté que para el siguiente post me reservaba un modo de hacer lo mismo desde .NET. No obstante me permito intercalar otra manera de realizar otra vez el DLookup desde MySQL algo más sencilla que [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-medium wp-image-20" title="mysql_access" src="http://www.albertmata.net/public/uploads/2008/05/mysql_access.jpg" alt="" width="254" height="134" />En el <a href="http://www.albertmata.net/2008/05/simulando-dlookup-fuera-de-access-i/" target="_blank">anterior post</a> expuse una manera de realizar un DLookup en <a href="http://www.mysql.com" target="_blank">MySQL</a> mediante stored procedures y stored functions y comenté que para el siguiente post me reservaba un modo de hacer lo mismo desde .NET. No obstante me permito intercalar otra manera de realizar otra vez el DLookup desde MySQL algo más sencilla que la primera aunque para recuperar el valor necesitaremos igualmente una doble consulta. Veamos cómo queda el código en esta ocasión:</p>
<div class="code">&#35;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#35;&#160;Author&#58;&#160;&#160;&#160;&#160;&#160;&#160;Albert&#160;Mata&#160;&#40;www&#46;albertmata&#46;net&#41;<br />
&#35;&#160;Date&#58;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;20080527<br />
&#35;&#160;Description&#58;&#160;MySQL&#160;procedure&#160;to&#160;simulate&#160;Microsoft&#160;Access&#160;<br />
&#35;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;function&#160;DLookup&#46;&#160;<br />
&#35;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;</p>
<p>&#35;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#35;&#160;Returns&#160;DLookup&#160;value&#160;using&#160;fourth&#160;parameter&#46;<br />
&#35;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
DROP&#160;PROCEDURE&#160;IF&#160;EXISTS&#160;DLookup&#59;<br />
DELIMITER&#160;&#47;&#47;<br />
CREATE&#160;PROCEDURE&#160;DLookup&#40;IN&#160;campo&#160;VARCHAR&#40;7&#41;&#44;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;IN&#160;tabla&#160;VARCHAR&#40;14&#41;&#44;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;IN&#160;condicion&#160;VARCHAR&#40;250&#41;&#44;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;OUT&#160;valor&#160;VARCHAR&#40;250&#41;&#41;<br />
BEGIN</p>
<p>DROP&#160;TABLE&#160;IF&#160;EXISTS&#160;tbl&#95;dlookupaux&#59;<br />
CREATE&#160;TABLE&#160;tbl&#95;dlookupaux&#160;&#40;tbl&#95;res&#160;VARCHAR&#40;250&#41;&#41;&#59;<br />
SET&#160;&#64;query&#160;&#61;&#160;CONCAT&#40;&#39;INSERT&#160;INTO&#160;tbl&#95;dlookupaux&#160;SELECT&#160;&#39;&#44;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;campo&#44;&#160;&#39;&#160;FROM&#160;&#39;&#44;&#160;tabla&#44;&#160;&#39;&#160;WHERE&#160;&#39;&#44;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;IF&#40;ISNULL&#40;condicion&#41;&#44;&#39;TRUE&#39;&#44;condicion&#41;&#44;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;&#160;LIMIT&#160;1&#39;&#41;&#59;</p>
<p>PREPARE&#160;running&#160;FROM&#160;&#64;query&#59;<br />
EXECUTE&#160;running&#59;<br />
DEALLOCATE&#160;PREPARE&#160;running&#59;<br />
SELECT&#160;tbl&#95;res&#160;INTO&#160;valor&#160;FROM&#160;tbl&#95;dlookupaux&#59;<br />
DROP&#160;TABLE&#160;IF&#160;EXISTS&#160;tbl&#95;dlookupaux&#59;</p>
<p>END<br />
&#47;&#47;<br />
DELIMITER&#160;&#59;</p></div>
<p>Esta vez utilizo únicamente una stored procedure, pero lo hago tomando parámetros tanto de entrada (campo, tabla y condicion) como de salida (valor). Con esto lo que hago es almacenar el resultado en el parámetro valor en lugar de almacenarlo provisionalmente en una tabla para luego recuperarlo de allí (bueno, internamente la stored procedure sí almacena en una tabla temporal, pero en tanto que la misma stored procedure la borra este proceso es transparente al usuario).</p>
<p>Recuerdo que partíamos de una tabla cty_nicecities con esta estructura:</p>
<div class="code">+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+<br />
|&#160;cty_id&#160;|&#160;cty_nam&#160;&#160;&#160;|&#160;cty_cou&#160;|<br />
+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+<br />
|&#160;&#160;&#160;&#160;&#160;&#160;1&#160;|&#160;Paris&#160;&#160;&#160;&#160;&#160;|&#160;France&#160;&#160;|&#160;<br />
|&#160;&#160;&#160;&#160;&#160;&#160;2&#160;|&#160;Rome&#160;&#160;&#160;&#160;&#160;&#160;|&#160;Italy&#160;&#160;&#160;|&#160;<br />
|&#160;&#160;&#160;&#160;&#160;&#160;3&#160;|&#160;Frankfurt&#160;|&#160;Germany&#160;|&#160;<br />
|&#160;&#160;&#160;&#160;&#160;&#160;4&#160;|&#160;Dortmund&#160;&#160;|&#160;Germany&#160;|&#160;<br />
|&#160;&#160;&#160;&#160;&#160;&#160;5&#160;|&#160;Milan&#160;&#160;&#160;&#160;&#160;|&#160;Italy&#160;&#160;&#160;|&#160;<br />
+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+</div>
<p>La llamada debe ahora realizarse así:</p>
<div class="code">CALL&#160;DLookup&#160;&#40;&#39;cty&#95;nam&#39;&#44;&#160;&#39;cty&#95;nicecities&#39;&#44;&#160;&#39;cty&#95;id&#160;&#61;&#160;4&#39;&#44;&#160;&#64;my&#95;city&#41;&#59;<br />
SELECT&#160;&#64;my&#95;city&#59;</div>
<p>Almacenamos pues el valor en una variable (@my_city) y después lo rescatamos:</p>
<div class="code">+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+<br />
| @my_city |<br />
+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+<br />
| Dortmund |<br />
+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+</div>
<p>Tal vez este método es más limpio que el anterior. De todos modos <a href="http://www.albertmata.net/2008/05/simulando-dlookup-fuera-de-access-iii/" target="_blank">para la próxima entrega</a>, esta vez sí, postearé el DLookup mediante código en .NET, que será bastante más potente al incorporar gestión de errores y no tener limitaciones fruto de tener que especificar el tipo de datos concreto que esperamos obtener. No obstante un DLookup en MySQL se ejecutará íntegramente en el servidor, mientras que uno en .NET tendrá una parte ejecutándose en la máquina cliente, así que dependerá del gusto de cada cual escoger uno u otro. Yo me inclino por la versión en .NET...</p>
]]></content:encoded>
			<wfw:commentRss>http://www.albertmata.net/2008/05/simulando-dlookup-fuera-de-access-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simulando DLookup fuera de Access (I).</title>
		<link>http://www.albertmata.net/2008/05/simulando-dlookup-fuera-de-access-i/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=simulando-dlookup-fuera-de-access-i</link>
		<comments>http://www.albertmata.net/2008/05/simulando-dlookup-fuera-de-access-i/#comments</comments>
		<pubDate>Tue, 27 May 2008 09:10:27 +0000</pubDate>
		<dc:creator>Albert Mata</dc:creator>
				<category><![CDATA[Access]]></category>
		<category><![CDATA[Herramientas]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[bases de datos]]></category>
		<category><![CDATA[dcount]]></category>
		<category><![CDATA[dlookup]]></category>
		<category><![CDATA[dmax]]></category>
		<category><![CDATA[stored function]]></category>
		<category><![CDATA[stored procedure]]></category>
		<category><![CDATA[VBA]]></category>

		<guid isPermaLink="false">http://www.albertmata.net/?p=18</guid>
		<description><![CDATA[Para todos aquellos que empezamos en bases de datos con Access y que programamos aplicaciones con VBA, las funciones DCount, DMax y similares nos resultan de lo más útiles para obtener valores puntuales de una base de datos sin tener que recuperar explícitamente un recordset. La más útil de todas probablemente sea DLookup. La sintaxis [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-medium wp-image-17" title="mysql_access" src="http://www.albertmata.net/public/uploads/2008/05/mysql_access.jpg" alt="" width="254" height="134" />Para todos aquellos que empezamos en bases de datos con <a href="http://office.microsoft.com/es-es/access/default.aspx" target="_blank">Access</a> y que programamos aplicaciones con <a href="http://es.wikipedia.org/wiki/Visual_Basic_for_Applications" target="_blank">VBA</a>, las funciones DCount, DMax y similares nos resultan de lo más útiles para obtener valores puntuales de una base de datos sin tener que recuperar explícitamente un recordset. La más útil de todas probablemente sea DLookup. La sintaxis resumida de DLookup es la siguiente (<a href="http://support.microsoft.com/kb/208786" target="_blank">para una más detallada explicación se puede consultar la propia ayuda de Access</a>):</p>
<div class="code">DLookup (nombre_campo, nombre_tabla, condicion_opcional)</div>
<p>Y nos devuelve el valor del campo correspondiente de la tabla indicada, en el primer registro que cumpla la condición opcionalmente pasada como parámetro.</p>
<p>Pues bien, como ya he comentado en posts anteriores, la base de datos con la que actualmente estoy trabajando es <a href="http://www.mysql.com" target="_blank">MySQL</a>, y por desgracia esta función tan útil no existe de manera predeterminada en MySQL. No obstante, ello no quiere decir que no podamos utilizar algo similar, sí que podemos, aunque vamos a tener que programar un poco antes. He aquí el código:</p>
<div class="code">&#35;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#35;&#160;Author&#58;&#160;&#160;&#160;&#160;&#160;&#160;Albert&#160;Mata&#160;&#40;www&#46;albertmata&#46;net&#41;<br />
&#35;&#160;Date&#58;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;20080527<br />
&#35;&#160;Description&#58;&#160;MySQL&#160;procedure&#160;and&#160;function&#160;to&#160;simulate&#160;Microsoft<br />
&#35;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Access&#160;function&#160;DLookup&#46;&#160;<br />
&#35;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;</p>
<p>&#35;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#35;&#160;Creates&#160;an&#160;auxiliar&#160;table&#160;to&#160;store&#160;the&#160;value&#46;<br />
&#35;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
DROP&#160;PROCEDURE&#160;IF&#160;EXISTS&#160;PreDLookupAux&#59;<br />
DELIMITER&#160;&#47;&#47;<br />
CREATE&#160;PROCEDURE&#160;PreDLookup&#40;campo&#160;VARCHAR&#40;7&#41;&#44;&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;tabla&#160;VARCHAR&#40;14&#41;&#44;&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;condicion&#160;VARCHAR&#40;250&#41;&#41;<br />
BEGIN</p>
<p>DROP&#160;TABLE&#160;IF&#160;EXISTS&#160;tbl&#95;dlookupaux&#59;<br />
CREATE&#160;TABLE&#160;tbl&#95;dlookupaux&#160;&#40;tbl&#95;res&#160;VARCHAR&#40;250&#41;&#41;&#59;<br />
SET&#160;&#64;query&#160;&#61;&#160;CONCAT&#40;&#39;INSERT&#160;INTO&#160;tbl&#95;dlookupaux&#160;SELECT&#160;&#39;&#44;&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;campo&#44;&#160;&#39;&#160;FROM&#160;&#39;&#44;&#160;tabla&#44;&#160;&#39;&#160;WHERE&#160;&#39;&#44;&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;IF&#40;ISNULL&#40;condicion&#41;&#44;&#39;TRUE&#39;&#44;condicion&#41;&#44;&#160;<br />
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#39;&#160;LIMIT&#160;1&#39;&#41;&#59;<br />
PREPARE&#160;running&#160;FROM&#160;&#64;query&#59;<br />
EXECUTE&#160;running&#59;<br />
DEALLOCATE&#160;PREPARE&#160;running&#59;</p>
<p>END<br />
&#47;&#47;<br />
DELIMITER&#160;&#59;&#160;</p>
<p>&#35;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
&#35;&#160;Gets&#160;the&#160;value&#160;from&#160;auxiliar&#160;table&#160;created&#160;before&#46;<br />
&#35;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;<br />
DROP&#160;FUNCTION&#160;IF&#160;EXISTS&#160;DLookup&#59;<br />
DELIMITER&#160;&#47;&#47;<br />
CREATE&#160;FUNCTION&#160;DLookup&#40;&#41;&#160;RETURNS&#160;VARCHAR&#40;250&#41;<br />
BEGIN</p>
<p>DECLARE&#160;aux&#160;VARCHAR&#40;250&#41;&#59;&#160;<br />
SET&#160;aux&#160;&#58;&#61;&#160;&#40;SELECT&#160;tbl&#95;res&#160;FROM&#160;tbl&#95;dlookupaux&#41;&#59;<br />
RETURN&#160;aux&#59;</p>
<p>END<br />
&#47;&#47;<br />
DELIMITER&#160;&#59;</p></div>
<p>Hay unas cuantas cosas que explicar:</p>
<p>1) Hasta la versión 5.0.45 de MySQL (la última GA cuando escribo esto y por tanto la de uso recomendado) las stored functions <a href="http://dev.mysql.com/doc/refman/5.0/en/routine-restrictions.html" target="_blank">no permiten hacer ciertas cosas</a> que harían mucho más fácil crear el DLookup en un solo paso, por eso se tiene que crear en un doble paso.</p>
<p>2) En el primer paso creamos una tabla auxiliar con un único campo y le insertamos un único registro con el valor que sale de la combinación campo-tabla-condicion que le hemos pasado. En el segundo paso nos devuelve ese valor que hemos almacenado temporalmente en la tabla auxiliar.</p>
<p>3) He puesto una longitud de 7 caracteres para el nombre del campo y de 14 para el de la tabla porque son las longitudes que tienen siempre mis nombres de campos y tablas, no obstante se puede modificar al gusto.</p>
<p>4) En cambio en tipo de campo de salida he puesto VARCHAR(250) por intentar ser algo genérico. Con esta definición nos devolverá sin problemas fechas y números, pero hay que tener en cuenta esta definición por si se utiliza DLookup con tipos de datos que no tengan cabida en un genérico VARCHAR(250).</p>
<p>5) Si no se desea pasar ningúna condición se puede establecer a cadena vacía (<code>''</code>) o bien a NULL, pero una stored function de MySQL no permite poner argumentos como de introducción opcional.</p>
<p>Veámoslo en funcionamiento. Tengo una tabla cty_nicecities con esta estructura:</p>
<div class="code">+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+<br />
|&#160;cty_id&#160;|&#160;cty_nam&#160;&#160;&#160;|&#160;cty_cou&#160;|<br />
+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+<br />
|&#160;&#160;&#160;&#160;&#160;&#160;1&#160;|&#160;Paris&#160;&#160;&#160;&#160;&#160;|&#160;France&#160;&#160;|&#160;<br />
|&#160;&#160;&#160;&#160;&#160;&#160;2&#160;|&#160;Rome&#160;&#160;&#160;&#160;&#160;&#160;|&#160;Italy&#160;&#160;&#160;|&#160;<br />
|&#160;&#160;&#160;&#160;&#160;&#160;3&#160;|&#160;Frankfurt&#160;|&#160;Germany&#160;|&#160;<br />
|&#160;&#160;&#160;&#160;&#160;&#160;4&#160;|&#160;Dortmund&#160;&#160;|&#160;Germany&#160;|&#160;<br />
|&#160;&#160;&#160;&#160;&#160;&#160;5&#160;|&#160;Milan&#160;&#160;&#160;&#160;&#160;|&#160;Italy&#160;&#160;&#160;|&#160;<br />
+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+</div>
<p>Y puedo utilizar mi DLookup particular de esta manera:</p>
<div class="code">CALL&#160;PreDLookup&#160;&#40;&#39;cty&#95;nam&#39;&#44;&#160;&#39;cty&#95;nicecities&#39;&#44;&#160;&#39;cty&#95;id&#160;&#61;&#160;4&#39;&#41;&#59;<br />
SELECT&#160;DLookUp&#40;&#41;&#59;</div>
<p>Para obtener:</p>
<div class="code">+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+<br />
|&#160;DLookup()&#160;|<br />
+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+<br />
|&#160;Dortmund&#160;&#160;|&#160;<br />
+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+</div>
<p>Y otro ejemplo, si pongo:</p>
<div class="code">CALL&#160;PreDLookup&#160;&#40;&#39;cty&#95;nam&#39;&#44;&#160;&#39;cty&#95;nicecities&#39;&#44;&#160;&#39;cty&#95;cou&#160;&#61;&#160;&#92;&#39;Italy&#92;&#39;&#39;&#41;&#59;<br />
SELECT&#160;DLookUp&#40;&#41;&#59;</div>
<p>Obtengo:</p>
<div class="code">+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+<br />
|&#160;DLookup()&#160;|<br />
+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+<br />
|&#160;Rome&#160;&#160;&#160;&#160;&#160;&#160;|&#160;<br />
+&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;+</div>
<p>Funciona aceptablemente bien y nos puede resultar muy útil cuando queramos utilizar la función DLookup en MySQL, sin embargo no es una solución idonea. Quizá cuando MySQL elimine las restricciones comentadas anteriormente se pueda crear una mejor solución. Por lo pronto en el próximo post subiré una solución infinitamente más elegante y potente para hacer lo mismo sólo que en lugar de hacerlo desde el lado del servidor MySQL lo haremos desde el lado de una aplicación programada en .NET. <img src='http://www.albertmata.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<div class="subtitle">Actualización.</div>
<p>En el <a href="http://www.albertmata.net/2008/05/simulando-dlookup-fuera-de-access-ii/" target="_blank">siguiente post</a> hay una versión distinta más breve y elegante del DLookup en MySQL.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.albertmata.net/2008/05/simulando-dlookup-fuera-de-access-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Servidor de bolsillo con WOS Portable.</title>
		<link>http://www.albertmata.net/2008/05/servidor-de-bolsillo-con-wos-portable/#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=servidor-de-bolsillo-con-wos-portable</link>
		<comments>http://www.albertmata.net/2008/05/servidor-de-bolsillo-con-wos-portable/#comments</comments>
		<pubDate>Sun, 25 May 2008 15:54:26 +0000</pubDate>
		<dc:creator>Albert Mata</dc:creator>
				<category><![CDATA[Herramientas]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Páginas web]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[bases de datos]]></category>
		<category><![CDATA[gnu-gpl]]></category>
		<category><![CDATA[joomla]]></category>
		<category><![CDATA[localhost]]></category>
		<category><![CDATA[mambo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[phpmyadmin]]></category>
		<category><![CDATA[usb]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[wos portable]]></category>

		<guid isPermaLink="false">http://www.albertmata.net/?p=12</guid>
		<description><![CDATA[En el proyecto en el que actualmente estoy trabajando, decidimos utilizar una base de datos MySQL por su bajo coste y excelente rendimiento. De hecho fue una recomendación mía que la Dirección aceptó, por lo cual celebro que de momento nos esté dando el resultado tan bueno que nos está dando.
Así pues en mi portátil [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-medium wp-image-15" title="wos" src="http://www.albertmata.net/public/uploads/2008/05/wos.jpg" alt="" width="183" height="80" />En el proyecto en el que actualmente estoy trabajando, decidimos utilizar una base de datos MySQL por su bajo coste y excelente rendimiento. De hecho fue una recomendación mía que la Dirección aceptó, por lo cual celebro que de momento nos esté dando el resultado tan bueno que nos está dando.</p>
<p>Así pues en mi portátil de trabajo tengo instalado un servidor MySQL en local. En él hago toda la fase de desarrollo antes de pasar tablas, triggers, procedimientos y demás al servidor MySQL del servidor de la empresa. Pero en ocasiones no tengo mi portátil a mano y me gustaría poder probar algunas cosas en otro PC. Hasta ahora tenía que desestimar la idea porque andar instalando el servidor MySQL en ordenadores ajenos es inviable. Pero hace poco he descubierto <a href="http://www.chsoftware.net/en/useware/wos/wos.htm" target="_blank">WOS Portable</a>. Una maravilla. WOS Portable es un software que se instala en un pendrive cualquiera (bueno, dicen que algunos modelos dan problemas, pero parecen ser los menos y en cualquier caso a mí no me ha ocurrido) y nos permite que al conectar después ese pendrive en cualquier PC con Windows y ejecutar el archivo wos.exe automáticamente dispondremos de un servidor <a href="http://www.apache.org/" target="_blank">Apache</a> + <a href="http://www.php.net/" target="_blank">PHP</a> + <a href="http://www.mysql.com/" target="_blank">MySQL</a> funcionando perfectamente, de tal manera que si en un navegador escribimos:</p>
<div class="code">http://localhost</div>
<p>Obtendremos la página index.php que tenemos alojada en el pendrive (en el directorio www). Y si en una consola escribimos:</p>
<div class="code">mysql -u root</div>
<p>Tendremos un servidor MySQL a nuestra entera disposición. (ver nota 1)</p>
<p>Personalmente este software me ha parecido una maravilla y creo que es muy útil para desarrolladores que solemos trabajar con más de un PC, ya que así nuestros datos pueden estar siempre en el pendrive y no tenemos que andar backupeándolos y restaurándolos constantemente. También se me ha ocurrido que puede resultar extremadamente útil como sistema de seguridad. Me explico: en mi empresa las aplicaciones funcionan como he dicho contra una base de datos MySQL alojada en el servidor. Si éste sufriera un accidente o cualquier imprevisto, la actividad se paralizaría y hasta que se restaurara el correcto funcionamiento del servidor podrían pasar horas o incluso días. En cambio ahora tenemos un pendrive con WOS Portable y cada X días le restauramos una copia de seguridad de la base de datos productiva. Con ello, ante cualquier eventualidad nos basta con conectar este pendrive, hacer un doble clic y ya tenemos de nuevo las aplicaciones funcionando. Realmente genial y recomendable.</p>
<p>Pues bien, WOS Portable se puede descargar libremente (es GNU-GPL) desde su sitio web. Para ello la única peculiaridad es que en lugar de bajarnos un archivo estándar podemos configurar qué aplicaciones extras (<a href="http://www.joomla.org/" target="_blank">Joomla</a>, <a href="http://mambo-foundation.org/" target="_blank">Mambo</a>, <a href="http://wordpress.org/" target="_blank">Wordpress</a>, etc) queremos incorporar al paquete de instalación. Lo básico es Apache + PHP + MySQL, y personalmente no recomiendo añadirle mucha cosa más desde un inicio, puesto que siempre estamos a tiempo de hacer actualizaciones con nuevos paquetes. No obstante, yo sí le añadí el <a href="http://www.phpmyadmin.net/home_page/index.php" target="_blank">phpMyAdmin</a> porque considero que en ocasiones resulta muy útil.</p>
<p>Una vez seleccionados los componentes nos generarán un archivo comprimido personalizado que sólo tendremos que bajarnos, descomprimirlo en el pendrive y ejecutar el fichero wos.exe. Con eso se llevará a cabo un proceso de configuración que tarda un ratito pero que no tiene complicación alguna. <img src='http://www.albertmata.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<div class="subtitle">Nota 1.</div>
<p>Para que esta sentencia funcione tenemos que tener un cliente MySQL (un archivo mysql.exe) en el PC y la ruta donde éste se encuentra guardada en la variable del sistema Path. Si no es así, cosa probable si no estamos en nuestro PC, siempre podemos ir primero a buscar el cliente:</p>
<div class="code">F:<br />
cd mysql/bin<br />
mysql -u root</div>
]]></content:encoded>
			<wfw:commentRss>http://www.albertmata.net/2008/05/servidor-de-bolsillo-con-wos-portable/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
