<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>VarioNet</title>
	<atom:link href="https://varionet.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://varionet.wordpress.com</link>
	<description>C# vb.net asp.net sqlserver y ...</description>
	<lastBuildDate>Mon, 18 Mar 2013 16:57:53 +0000</lastBuildDate>
	<language>es</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='varionet.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>https://s0.wp.com/i/buttonw-com.png</url>
		<title>VarioNet</title>
		<link>https://varionet.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="https://varionet.wordpress.com/osd.xml" title="VarioNet" />
	<atom:link rel='hub' href='https://varionet.wordpress.com/?pushpress=hub'/>
	<item>
		<title>Everything: Una herramienta productiva.</title>
		<link>https://varionet.wordpress.com/2009/11/17/everything-una-herramienta-adictivamente-productiva/</link>
					<comments>https://varionet.wordpress.com/2009/11/17/everything-una-herramienta-adictivamente-productiva/#respond</comments>
		
		<dc:creator><![CDATA[Alejandro Hernández]]></dc:creator>
		<pubDate>Wed, 18 Nov 2009 01:47:31 +0000</pubDate>
				<category><![CDATA[utilidades]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[buscador]]></category>
		<category><![CDATA[Everything]]></category>
		<guid isPermaLink="false">http://varionet.wordpress.com/?p=145</guid>

					<description><![CDATA[Existe una multitud de herramientas, plugins para Visual Studio, editores, y demás que nos asisten a la hora de desarrollar. Yo particularmente soy amigo de las más sencillas, ya bastante con aprender todos los vericuetos del entorno. Entre estas herramientas que me «conquistaron», la que más me gusta es Everything, Un buscador de archivos. No &#8230; <a href="https://varionet.wordpress.com/2009/11/17/everything-una-herramienta-adictivamente-productiva/" class="more-link">Continuar leyendo<span class="screen-reader-text"> "Everything: Una herramienta&#160;productiva."</span></a>]]></description>
										<content:encoded><![CDATA[<p>Existe una multitud de herramientas, plugins para Visual Studio, editores, y demás que nos asisten a la hora de desarrollar. Yo particularmente soy amigo de las más sencillas, ya bastante con aprender todos los vericuetos del entorno.</p>
<p>Entre estas herramientas que me «conquistaron», la que más me gusta es <a title="Download Everything" href="http://www.voidtools.com/" target="_blank">Everything</a>, Un buscador de archivos. No hace nada que no se pueda hacer con Windows o con muchas otras herramientas que realizan la misma tarea y ofrecen mucha más funcionalidad, básicamente escribimos partes del nombre del cualquier archivo separadas por espacios y nos muestra una lista de todos los que coinciden con el patrón buscado.</p>
<p>¿Por que vale la pena entonces? El secreto de Everything es que lo que hace lo hace bien, es gratis (vale donar ¡eh!), consume escasos recursos y es muy, muy, MUY rápido.</p>
<figure data-shortcode="caption" id="attachment_146" aria-describedby="caption-attachment-146" style="width: 207px" class="wp-caption alignright"><a href="https://varionet.wordpress.com/wp-content/uploads/2009/11/nat-meth-cs-everything.png"><img data-attachment-id="146" data-permalink="https://varionet.wordpress.com/2009/11/17/everything-una-herramienta-adictivamente-productiva/nat-meth-cs-everything/" data-orig-file="https://varionet.wordpress.com/wp-content/uploads/2009/11/nat-meth-cs-everything.png" data-orig-size="207,200" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="Everything" data-image-description="" data-image-caption="&lt;p&gt;La respuesta es inmediata&lt;/p&gt;
" data-medium-file="https://varionet.wordpress.com/wp-content/uploads/2009/11/nat-meth-cs-everything.png?w=207" data-large-file="https://varionet.wordpress.com/wp-content/uploads/2009/11/nat-meth-cs-everything.png?w=207" class="size-full wp-image-146 " style="border:1px solid black;" title="Everything" src="https://varionet.wordpress.com/wp-content/uploads/2009/11/nat-meth-cs-everything.png?w=840" alt="Busqueda en Everything"   srcset="https://varionet.wordpress.com/wp-content/uploads/2009/11/nat-meth-cs-everything.png 207w, https://varionet.wordpress.com/wp-content/uploads/2009/11/nat-meth-cs-everything.png?w=150&amp;h=145 150w" sizes="(max-width: 207px) 85vw, 207px" /></a><figcaption id="caption-attachment-146" class="wp-caption-text">El secreto: Respuesta inmediata.</figcaption></figure>
<p>Para ser claro, a la pulsación de cada tecla tendremos nuestra lista de archivos filtrada. Para escanear todo el disco rígido por primera vez solo tarda unos segundos, y los cambios que se hagan a los archivos, afectan los resultados de Everything en tiempo real.</p>
<p>Ahora, si trabajan en proyectos con cientos o miles de archivos créanme que con un poco de uso de Everything se van a olvidar de navegar por árboles infinitos de carpetas y listas interminables de archivos. Abrir un archivo en Visual Studio se convierte en activar el Everything con un shortcut, escribir unas letras y presionar enter.</p>
<p>Unos pocos tips para su uso:</p>
<ul>
<li>Incluirlo entre los programas de inicio, pesa muy poco e inicia sin que lo notemos.
<p><figure data-shortcode="caption" id="attachment_149" aria-describedby="caption-attachment-149" style="width: 255px" class="wp-caption alignright"><a href="https://varionet.wordpress.com/wp-content/uploads/2009/11/opciones-everything.png"><img data-attachment-id="149" data-permalink="https://varionet.wordpress.com/2009/11/17/everything-una-herramienta-adictivamente-productiva/opciones-everything/" data-orig-file="https://varionet.wordpress.com/wp-content/uploads/2009/11/opciones-everything.png" data-orig-size="399,487" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="Opciones Everything" data-image-description="" data-image-caption="&lt;p&gt;La única configuración necesaria el HotKey.&lt;/p&gt;
" data-medium-file="https://varionet.wordpress.com/wp-content/uploads/2009/11/opciones-everything.png?w=246" data-large-file="https://varionet.wordpress.com/wp-content/uploads/2009/11/opciones-everything.png?w=399" class="size-medium wp-image-149 " style="border:1px solid black;" title="Opciones Everything" src="https://varionet.wordpress.com/wp-content/uploads/2009/11/opciones-everything.png?w=245&#038;h=300" alt="Setear HotKey" width="245" height="300" srcset="https://varionet.wordpress.com/wp-content/uploads/2009/11/opciones-everything.png?w=245 245w, https://varionet.wordpress.com/wp-content/uploads/2009/11/opciones-everything.png?w=123 123w, https://varionet.wordpress.com/wp-content/uploads/2009/11/opciones-everything.png 399w" sizes="(max-width: 245px) 85vw, 245px" /></a><figcaption id="caption-attachment-149" class="wp-caption-text">La única configuración necesaria: el HotKey.</figcaption></figure></li>
<li>Setear un shortcut, no viene por defecto y es uno de los secretos para su uso, yo uso Windows + S. (Se agrega en: Tools – General – New Windows HotKey Modifier / Key)</li>
<li>Excluir las carpetas sobre las que no queremos resultados: (Tools – Exclude / Volumes)</li>
<li>Si queremos buscar dentro de una carpeta específica, la escribimos antes del nombre del nombre del archivo seguida de barra invertida. («MiProyecto\  app.config»)</li>
<li>Si trabajan con varios entornos abiertos, asegurensé de tener el foco sobre el que quieren abrir el archivo buscado antes de activar Everything.</li>
</ul>
<p><strong>¡Extra, Extra!</strong></p>
<p>Everything tiene como extra unas pocas pero poderosas funcionalidades.</p>
<p>Permite exponer un disco o carpetas seleccionadas con Everything actuando como un mini web server, pudiendo hacer busquedas desde otra máquina mediante un browser ¡y bajarse los archivos encontrados!</p>
<figure data-shortcode="caption" id="attachment_157" aria-describedby="caption-attachment-157" style="width: 508px" class="wp-caption alignleft"><a href="https://varionet.wordpress.com/wp-content/uploads/2009/11/servidor-http-de-everything2.png"><img data-attachment-id="157" data-permalink="https://varionet.wordpress.com/2009/11/17/everything-una-herramienta-adictivamente-productiva/servidor-http-de-everything-3/" data-orig-file="https://varionet.wordpress.com/wp-content/uploads/2009/11/servidor-http-de-everything2.png" data-orig-size="508,285" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="Servidor Http de Everything" data-image-description="" data-image-caption="&lt;p&gt;Podemos exponer parte de nuestros archivos por HTTP. ¡Usar con responsabilidad!&lt;/p&gt;
" data-medium-file="https://varionet.wordpress.com/wp-content/uploads/2009/11/servidor-http-de-everything2.png?w=300" data-large-file="https://varionet.wordpress.com/wp-content/uploads/2009/11/servidor-http-de-everything2.png?w=508" class="size-full wp-image-157    " style="border:1px solid black;" title="Servidor Http de Everything" src="https://varionet.wordpress.com/wp-content/uploads/2009/11/servidor-http-de-everything2.png?w=840" alt=""   srcset="https://varionet.wordpress.com/wp-content/uploads/2009/11/servidor-http-de-everything2.png 508w, https://varionet.wordpress.com/wp-content/uploads/2009/11/servidor-http-de-everything2.png?w=150&amp;h=84 150w, https://varionet.wordpress.com/wp-content/uploads/2009/11/servidor-http-de-everything2.png?w=300&amp;h=168 300w" sizes="(max-width: 508px) 85vw, 508px" /></a><figcaption id="caption-attachment-157" class="wp-caption-text">Podemos exponer parte de nuestros archivos por HTTP. ¡Usar con responsabilidad!</figcaption></figure>
<p>Posee un protocolo propio (ETP: Everything Transfer Protocol) que nos permite setear una instancia Everything como servidor y utilizar otras como clientes de búsqueda, con la misma funcionalidad que usándolo en forma local. Fantástico.</p>
<p>Si quieren hilar fino se puede configurar para usar Regular expressions, permite exportar a un archivo de texto la lista de archivos encontrados, y tiene multiplicidad de opciones que vienen configuradas como para no tener que tocarlas.</p>
<p>Asique ya saben, basta del perro de XP y de la (mucho mejor pero igualmente) no muy efectiva barra de búsqueda de Vista, no tienen nada que hacer al lado de Everything. Después me cuentan.</p>
<p>links: <a title="Download Everything" href="http://www.voidtools.com/" target="_blank">Everything</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://varionet.wordpress.com/2009/11/17/everything-una-herramienta-adictivamente-productiva/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://0.gravatar.com/avatar/6ac4a1d95580a307da123b4c5a56eb7e711ff8e6f9fc72c35c79ccd4a9f0ebd5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Alejandro Hernández</media:title>
		</media:content>

		<media:content url="https://varionet.wordpress.com/wp-content/uploads/2009/11/nat-meth-cs-everything.png" medium="image">
			<media:title type="html">Everything</media:title>
		</media:content>

		<media:content url="https://varionet.wordpress.com/wp-content/uploads/2009/11/opciones-everything.png?w=245" medium="image">
			<media:title type="html">Opciones Everything</media:title>
		</media:content>

		<media:content url="https://varionet.wordpress.com/wp-content/uploads/2009/11/servidor-http-de-everything2.png" medium="image">
			<media:title type="html">Servidor Http de Everything</media:title>
		</media:content>
	</item>
		<item>
		<title>Sobre base64. Para que usarlo, para que no, y como manejarlo en .net y Asp.Net</title>
		<link>https://varionet.wordpress.com/2009/11/06/sobre-base64-para-que-usarlo-para-que-no-y-como-manejarlo-en-net-y-asp-net/</link>
					<comments>https://varionet.wordpress.com/2009/11/06/sobre-base64-para-que-usarlo-para-que-no-y-como-manejarlo-en-net-y-asp-net/#comments</comments>
		
		<dc:creator><![CDATA[Alejandro Hernández]]></dc:creator>
		<pubDate>Fri, 06 Nov 2009 04:01:31 +0000</pubDate>
				<category><![CDATA[asp.net]]></category>
		<category><![CDATA[base64]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[ToBase64String]]></category>
		<category><![CDATA[UrlTokenEncode]]></category>
		<guid isPermaLink="false">http://varionet.wordpress.com/?p=47</guid>

					<description><![CDATA[¿Que es base64? Base64 no es en principio otra cosa mas que un sistema numérico, el cual debido a sus características se emplea en muchos ámbitos de la informática para representar información binaria. Todos los sistemas de numeración tienen una lista de símbolos que utilizan para representar valores, por ejemplo: Binario: &#8217;01&#8217; Decimal: &#8216;0123456789&#8217; Hexadecimal: &#8230; <a href="https://varionet.wordpress.com/2009/11/06/sobre-base64-para-que-usarlo-para-que-no-y-como-manejarlo-en-net-y-asp-net/" class="more-link">Continuar leyendo<span class="screen-reader-text"> "Sobre base64. Para que usarlo, para que no, y como manejarlo en .net y&#160;Asp.Net"</span></a>]]></description>
										<content:encoded><![CDATA[<p><strong>¿Que es base64?</strong></p>
<p>Base64 no es en principio otra cosa mas que un sistema numérico, el cual debido a sus características se emplea en muchos ámbitos de la informática para representar información binaria.</p>
<p>Todos los sistemas de numeración tienen una lista de símbolos que utilizan para representar valores, por ejemplo:</p>
<p>Binario: &#8217;01&#8217;<br />
Decimal: &#8216;0123456789&#8217;<br />
Hexadecimal: &#8216;0123456789ABCDEF&#8217;<br />
y para base64 el conjunto es:<br />
&#8216;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&#8217;</p>
<p>Como vemos, es un subconjunto de ASCII, y tiene como particularidad que todos sus caracteres son imprimibles, de hecho 64 es la mayor potencia de 2 que permite ser representada por un subconjunto de caracteres ASCII imprimibles, por eso, si pasamos cualquier información a su representación de base64, tenemos la seguridad de que no tendremos problemas al transmitirla, almacenarla o leerla, incluso aunque esta contega los más remotos caracteres unicode, una imagen o un mp3, ya que para convertir algo a base64 trataremos directamente con los bits.</p>
<p><strong>¿Como codificamos en base64?</strong></p>
<p>Veamos (en este ejemplo flagrantemente <a href="http://es.wikipedia.org/wiki/Base64" target="_blank">robado de Wikipedia</a>) como se codifica la palabra “Man”.</p>
<table border="1">
<tbody>
<tr>
<td>Texto de entrada</td>
<td colspan="8" align="center"><strong>M</strong></td>
<td colspan="8" align="center"><strong>a</strong></td>
<td colspan="8" align="center"><strong>n</strong></td>
</tr>
<tr>
<td>ASCII</td>
<td colspan="8" align="center">77</td>
<td colspan="8" align="center">97</td>
<td colspan="8" align="center">110</td>
</tr>
<tr>
<td>Bits</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>Índice</td>
<td colspan="6" align="center">19</td>
<td colspan="6" align="center">22</td>
<td colspan="6" align="center">5</td>
<td colspan="6" align="center">46</td>
</tr>
<tr>
<td>Resultado en Base64</td>
<td colspan="6" align="center"><strong>T</strong></td>
<td colspan="6" align="center"><strong>W</strong></td>
<td colspan="6" align="center"><strong>F</strong></td>
<td colspan="6" align="center"><strong>u</strong></td>
</tr>
</tbody>
</table>
<p>Tenemos que la M es en ASCII el caracter 77 (01001101 en binario), y como el primer paso para nuestra tarea es convertir la información de origen en bits (más sobre esto en un momento), transformamos toda la cadena en una secuencia de unos y ceros, los cuales tomamos en grupos de a seis.</p>
<p>El primero de estos grupos (010011) representa 19, y si tomamos la posición 19 en la lista de símbolos de base64 (empezando a contar desde cero, claro) obtenemos la T, y continuando con este algoritmo llegamos al resultado “TWFu”.</p>
<p><strong>Caracteres de Relleno</strong></p>
<p>base64 se codifica tomando los bytes de tres como entrada en cuatro sextetos, o sea de a 24 bits. Cuando esta cantidad no coincide, completamos con el caracter de relleno “=” los sextetos restantes.</p>
<p>Por ejemplo, si hubiéramos codificado solamente el texto “Ma”, veríamos que no coincide la cantidad de octetos con la de sextetos, luego de “TW” me quedaría 0001, por lo que completo con ocho ceros y obtengo “TWE”. El sexteto vacío que queda se completa con el caraceter “=” quedando como resultado: “TWE=”</p>
<p>Hasta aquí como se codifica. De la misma manera, podría codificar un archivo ejecutable, una imagen, archivos de sonido o simplemente como en este caso, Texto Plano.</p>
<p>Ooops, acabo de decir “texto plano”, pero como bien dice <a href="http://www.joelonsoftware.com/articles/Unicode.html" target="_blank">Joel Spolsky</a> (<a href="http://es.wikipedia.org/wiki/TANSTAAFL" target="_blank">parafraseando</a> a famoso <a href="http://es.wikipedia.org/wiki/Milton_Friedman" target="_blank">economista</a> que parafraseaba a conocido <a href="http://es.wikipedia.org/wiki/Robert_A._Heinlein" target="_blank">escritor de ciencia ficción</a>): “No existe tal cosa como el texto plano”. Y acá es donde entra a fastidiarnos la palabra “Encoding”.</p>
<p><strong>Encoding</strong></p>
<p>La representación lógica de una cadena de texto, como puede serlo un String de .net, se puede convertir a bits de muchas maneras. No es lo mismo la representación binaria de texto en ASCII que en Unicode, al respecto recomiendo encarecidamente leer el citado post de Joel Spolsky, pero lo que quiero destacar ahora a los efectos prácticos de comprender el código es que, cuando trabamos con texto, este es para nosotros la representación <em>lógica</em> de la información, la cual se perderá al momento de trabajar directramente con los bits, y como la conversión de esta información lógica a bits puede realizarse de muchas maneras distintas, debemos tener control de este paso al momento de codificar y decodificar texto en y desde base64.</p>
<p><strong>Base64 en .net</strong></p>
<p>Para convertir texto a bytes .net nos ofrece la clase abstracta Encoding y sus derivados concretos, en el ejemplo utilizaremos UTF8Encoding. Si no necesitamos usarlas en grandes iteraciones, podemos obtener instancias de estas clases desde las propiedades estáticas que nos da la clase Encoding, (.UTF8, .UTF7, .ASCII).</p>
<p>Y para obtener los bytes utilizamos el método GetBytes, dado un string “s”:</p>
<pre style="border-left:1px solid gainsboro;border-bottom:1px solid gainsboro;background-image:none;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#0000ff;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;">Encoding</span></span><span style="font-size:small;"><span style="color:#000000;">.UTF8.GetBytes(s)</span></span></span></span></span></span></span></span></span></pre>
<p>Estos bytes se los pasamos a Convert.ToBase64String:</p>
<pre style="border-left:1px solid gainsboro;border-bottom:1px solid gainsboro;background-image:none;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#0000ff;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;">String</span></span><span style="color:#000000;font-size:small;"> b64 = </span><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;">Convert</span></span><span style="color:#000000;font-size:small;">.ToBase64String(</span><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;">Encoding</span></span><span style="font-size:small;"><span style="color:#000000;">.UTF8.GetBytes(s));</span></span></span></span></span></pre>
<p>y a la inversa, mediante el método GetString de la misma clase de Encoding que hayamos utilizado en la conversión:</p>
<pre style="border-left:1px solid gainsboro;border-bottom:1px solid gainsboro;background-image:none;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#0000ff;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;">String</span></span><span style="color:#000000;font-size:small;"> s = </span><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;">Encoding</span></span><span style="color:#000000;font-size:small;">.UTF8.GetString(</span><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;">Convert</span></span><span style="font-size:small;"><span style="color:#000000;">.FromBase64String(b64));</span></span></span></span></span></span></span></pre>
<p><strong>URLTokenEncode, base64 en ASP.NET</strong></p>
<p>Utilizar parámetros codificados en base64 en un query string nos aporta la seguridad de que no tendremos problemas con los caracteres reservados por HTML, así como la ofuscación de la información ante los usuarios, pero nos encontramos ante el problema de los símbolos “+”, “/”  y “=” que tienen un significado dentro de una URI.</p>
<p>Ante esta limitación .net nos da una alternativa a la codificación clásica mediante el método estático UrlTokenEncode de la clase HttpServerUtility, en System.Web:</p>
<pre style="border-left:1px solid gainsboro;border-bottom:1px solid gainsboro;background-image:none;line-height:12pt;background-color:#f4f4f4;width:100%;"><span style="color:#0000ff;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;">String</span></span><span style="color:#000000;font-size:small;"> b64=</span><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;">HttpServerUtility</span></span><span style="color:#000000;font-size:small;">.UrlTokenEncode(</span><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;">Encoding</span></span><span style="font-size:small;"><span style="color:#000000;">.UTF8.GetBytes(s));</span></span><span style="font-size:small;"><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;">
String</span></span><span style="color:#000000;font-size:small;"> s=</span><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;">Encoding</span></span><span style="color:#000000;font-size:small;">.UTF8.GetString(</span><span style="color:#2b91af;font-size:small;"><span style="color:#2b91af;font-size:small;">HttpServerUtility</span></span><span style="font-size:small;"><span style="color:#000000;">.UrlTokenDecode(b64));</span></span></span></span></pre>
<p>Con este método, los caracteres “+” y “/” son reemplazados por “-“ y “_” respectivamente y los simbolos “=” de complemento se reemplazan por un dígito numérico indicando la cantidad de los mismos, de esta manera la cadena “ûï¾x%óaxz” se códifica (en UTF8) como: “w7vDr8K+eCXDs2F4eg==” según el método estándar y con UrlTokenEncode “w7vDr8K-eCXDs2F4eg2”, donde el «2” final representa los “==” al final del resultado estándar y el “-“ reemplaza al “+”.</p>
<p>De esta manera obtenemos una cadena totalmente segura para utilizar en el ámbito web.</p>
<p><strong>Algunos hechos sobre base64</strong></p>
<ul>
<li>Base64 no es un método de encriptación. Si bien ofusca la información ante la simple vista no hace falta mucho conocimiento ni pericia para recuperar la información original.</li>
<li>Base64 “pesa” un 33% más que la información original. Esta ralación está dada por la relación 8 a 6 bits por caracter, (o sea, un caracter de base64 representa menos información que un caracter normal).</li>
<li>Aparte del nombrado Issue en su utilización en Web, en otros ámbitos también hay caracteres que se tornan problemáticos, por ejemplo en regular expressions, se suelen reemplazar “+” y “/” por “[“ y “]”. Observesé que la codificación que utiliza UrlTokenEncode no serviría en este caso ya que los “+” tienen  significado propio en Regular Expression, por lo que habría que escaparlos.</li>
<li>Insisto: No sirve para encriptar información. No utiliza claves ni certificados, la conversión a la información original es prácticamente directa y no está pensado para este fin.</li>
<li>Si podemos, en cambio, utilizarlo para guardar o transmitir información previamente cifrada que suele presentar caracteres problemáticos para ser transmitidos o almacenados.</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://varionet.wordpress.com/2009/11/06/sobre-base64-para-que-usarlo-para-que-no-y-como-manejarlo-en-net-y-asp-net/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
		
		<media:content url="https://0.gravatar.com/avatar/6ac4a1d95580a307da123b4c5a56eb7e711ff8e6f9fc72c35c79ccd4a9f0ebd5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Alejandro Hernández</media:title>
		</media:content>
	</item>
		<item>
		<title>Diferencia entre Find y Filter en jQuery</title>
		<link>https://varionet.wordpress.com/2009/07/15/diferencia-entre-find-y-filter-en-jquery/</link>
					<comments>https://varionet.wordpress.com/2009/07/15/diferencia-entre-find-y-filter-en-jquery/#comments</comments>
		
		<dc:creator><![CDATA[Alejandro Hernández]]></dc:creator>
		<pubDate>Wed, 15 Jul 2009 03:30:17 +0000</pubDate>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<guid isPermaLink="false">http://varionet.wordpress.com/?p=130</guid>

					<description><![CDATA[Es muy común confundirse entre estos dos métodos al comenzar con jQuery, pero ambos realizan tareas muy distintas. Mientras .filter quita, de los elementos contenidos en el objeto $, los que no cumplan con el selector que se le indica, .find busca en los descendientes de los objetos seleccionados. $(&#34;div.nav&#34;).find(&#34;a&#34;) Encuentra los links dentro de &#8230; <a href="https://varionet.wordpress.com/2009/07/15/diferencia-entre-find-y-filter-en-jquery/" class="more-link">Continuar leyendo<span class="screen-reader-text"> "Diferencia entre Find y Filter en&#160;jQuery"</span></a>]]></description>
										<content:encoded><![CDATA[<p><a href="https://varionet.wordpress.com/wp-content/uploads/2009/07/jquery_thumb.jpg"><img style="display:inline;border-width:0;margin:0 0 5px 25px;" title="jquery_thumb" border="0" alt="jquery_thumb" align="right" src="https://varionet.wordpress.com/wp-content/uploads/2009/07/jquery_thumb_thumb.jpg?w=244&#038;h=175" width="244" height="175" /></a>Es muy común confundirse entre estos dos métodos al comenzar con jQuery, pero ambos realizan tareas muy distintas. <a href="https://varionet.wordpress.com/wp-content/uploads/2009/07/jquery_thumb.jpg"></a></p>
<p>Mientras .filter quita, de los elementos contenidos en el objeto $, los que no cumplan con el selector que se le indica, .find busca en los descendientes de los objetos seleccionados.</p>
<p><span style="background-image:none;border-bottom:gainsboro 1px solid;border-left:gainsboro 1px solid;line-height:12pt;background-color:#f4f4f4;padding-left:5px;padding-right:5px;font-family:consolas,&#39;color:black;font-size:8pt;overflow:auto;border-top:gainsboro 1px solid;border-right:gainsboro 1px solid;padding-top:3px;margin:0;">$(&quot;<span style="color:#8b0000;">div.nav</span>&quot;).find(&quot;<span style="color:#8b0000;">a</span>&quot;)</span> Encuentra los links dentro de cualquier <em>div</em> con la clase css <em>nav, en cambio:</em></p>
<p><span style="background-image:none;border-bottom:gainsboro 1px solid;border-left:gainsboro 1px solid;line-height:12pt;background-color:#f4f4f4;padding-left:5px;padding-right:5px;font-family:consolas,&#39;color:black;font-size:8pt;overflow:auto;border-top:gainsboro 1px solid;border-right:gainsboro 1px solid;padding-top:3px;margin:0;">$(&quot;<span style="color:#8b0000;">a</span>&quot;).addClass(&quot;<font color="#8b0000">.link</font>&quot;).filter(&quot;<font color="#8b0000">[href^=http://]</font>&quot;).addClass(&quot;<font color="#8b0000">.externo</font>&quot;)</font>;</span> Agrega la clase “link” a todos los &lt;a&gt; y la clase “externo”, solo a los que poseen una valor para el atributo <em>href</em> que comienza con “http://”, Este es otro ejemplo clásico de jQuery. (Los corchetes se utilizan para buscar en atributos del HTML y el ^ indica el que la cadena buscada debe estar al comienzo del valor del atributo.)</p>
<p>En general .filter se utiliza para trabajar con un subconjunto de otro conjunto sobre el ya realicé una acción, permitiéndonos encadenar varias sentencias en una como en el ejemplo.</p>
<p>En cambio .find es un método muy poderoso que me sirve para navegar dentro del DOM por relaciones “descendiente de” entre elementos. Buscará en los elementos descendientes de los contenidos en $, sin tener en cuenta estos últimos.</p>
<p>Por ejemplo, dado:</p>
<pre style="background-image:none;border-bottom:gainsboro 1px solid;border-left:gainsboro 1px solid;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:consolas,&#39;height:100px;color:black;font-size:8pt;overflow:auto;border-top:gainsboro 1px solid;border-right:gainsboro 1px solid;margin:0;padding:5px;"><span style="color:#0000ff;">&lt;</span><span style="color:#800000;">div</span> <span style="color:#ff0000;">id</span>=<span style="color:#0000ff;">&quot;padre&quot;</span><span style="color:#0000ff;">&gt;</span>
   <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">div</span> <span style="color:#ff0000;">id</span>=<span style="color:#0000ff;">&quot;hijo1&quot;</span><span style="color:#0000ff;">&gt;</span>
      <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">div</span> <span style="color:#ff0000;">id</span>=<span style="color:#0000ff;">&quot;nieto1&quot;</span><span style="color:#0000ff;">&gt;</span><span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">div</span><span style="color:#0000ff;">&gt;</span>
   <span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">div</span><span style="color:#0000ff;">&gt;</span>
   <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">div</span> <span style="color:#ff0000;">id</span>=<span style="color:#0000ff;">&quot;hijo2&quot;</span><span style="color:#0000ff;">&gt;</span><span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">div</span><span style="color:#0000ff;">&gt;</span>
<span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">div</span><span style="color:#0000ff;">&gt;</span></pre>
<p><span style="background-image:none;border-bottom:gainsboro 1px solid;border-left:gainsboro 1px solid;line-height:12pt;background-color:#f4f4f4;padding-left:5px;padding-right:5px;font-family:consolas,&#39;color:black;font-size:8pt;overflow:auto;border-top:gainsboro 1px solid;border-right:gainsboro 1px solid;padding-top:3px;margin:0;">$(&quot;<span style="color:#8b0000;">#padre</span>&quot;).find(&quot;<span style="color:#8b0000;">div</span>&quot;)</span> Encuentra “hijo1”, “hijo2” y “nieto1”, (y no el div “padre” contenido en el objeto $.)</p>
<p>Este tipo de métodos denominados “transversales”, son los que nos ampliarán el campo de acción cuando excedamos las posibilidades de los selectores.</p>
<p>¡Hasta pronto!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://varionet.wordpress.com/2009/07/15/diferencia-entre-find-y-filter-en-jquery/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		
		<media:content url="https://0.gravatar.com/avatar/6ac4a1d95580a307da123b4c5a56eb7e711ff8e6f9fc72c35c79ccd4a9f0ebd5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Alejandro Hernández</media:title>
		</media:content>

		<media:content url="https://varionet.wordpress.com/wp-content/uploads/2009/07/jquery_thumb_thumb.jpg" medium="image">
			<media:title type="html">jquery_thumb</media:title>
		</media:content>
	</item>
		<item>
		<title>Checkear todos los CheckBox con jQuery</title>
		<link>https://varionet.wordpress.com/2009/06/17/como-checkear-todos-los-checkbox-de-una-columna-con-jquery/</link>
					<comments>https://varionet.wordpress.com/2009/06/17/como-checkear-todos-los-checkbox-de-una-columna-con-jquery/#comments</comments>
		
		<dc:creator><![CDATA[Alejandro Hernández]]></dc:creator>
		<pubDate>Wed, 17 Jun 2009 11:50:29 +0000</pubDate>
				<category><![CDATA[asp.net]]></category>
		<category><![CDATA[gridview]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<guid isPermaLink="false">http://varionet.wordpress.com/?p=94</guid>

					<description><![CDATA[Uno de los artículos más consultados de este blog explica como configurar una tabla para que al clickear en un Checkbox en la cabecera de una columna, todos los checks de la misma tomen el mismo estado «checked/unchecked». Sin embargo, ese código requiere de algunas condiciones: La tabla debe poseer un ID. Cada checkbox debe &#8230; <a href="https://varionet.wordpress.com/2009/06/17/como-checkear-todos-los-checkbox-de-una-columna-con-jquery/" class="more-link">Continuar leyendo<span class="screen-reader-text"> "Checkear todos los CheckBox con&#160;jQuery"</span></a>]]></description>
										<content:encoded><![CDATA[<p>Uno de los <a href="https://varionet.wordpress.com/2007/11/03/chequear-todos-los-checkbox-de-un-gridview-con-javascript/" target="_blank">artículos</a> más consultados de este blog explica como configurar una tabla para que al clickear en un Checkbox en la cabecera de una columna, todos los checks de la misma tomen el mismo estado «checked/unchecked».</p>
<p>Sin embargo, ese código requiere de algunas condiciones:</p>
<ul>
<li>La tabla debe poseer un ID.</li>
<li>Cada checkbox debe ser el primer elemento de la celda.</li>
<li>Hay que escribir una llamada al evento onclick del checkbox en la cabecera, pasando como parámetro el ID de la tabla, ya sea escribiéndolo o navegando por el DOM para obtenerlo.</li>
</ul>
<p>Y tiene un grave problema, no funciona en navegadores no-IE.</p>
<p>Cuando empecé a investigar jQuery, quise emular como práctica este código y me encontré con que jQuery nos lleva a plantear una solución mucho mas completa, que no solo resuelve todos los problemas anteriores, si no que nos lleva a escribir en el body la cantidad de javascript: ¡cero!.</p>
<p>Vamos al grano:</p>
<p>Primer paso: Agregar el include del archivo js donde está el código. (aparte del de jQuery por supuesto)</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:consolas,'Courier New',courier,monospace;color:black;font-size:8pt;margin:0;padding:5px;"><span style="color:#0000ff;">&lt;</span><span style="color:#800000;">script</span> <span style="color:#ff0000;">src</span>=<span style="color:#0000ff;">"js/jquery.js"</span> <span style="color:#ff0000;">type</span>=<span style="color:#0000ff;">"text/javascript"</span><span style="color:#0000ff;">&gt;</span><span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">script</span><span style="color:#0000ff;">&gt;</span>
<span style="color:#0000ff;">&lt;</span><span style="color:#800000;">script</span> <span style="color:#ff0000;">src</span>=<span style="color:#0000ff;">"js/miScript.js"</span> <span style="color:#ff0000;">type</span>=<span style="color:#0000ff;">"text/javascript"</span><span style="color:#0000ff;">&gt;</span><span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">script</span><span style="color:#0000ff;">&gt;</span></pre>
<p>Segundo y último paso: En miScript.js el siguiente código:</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:consolas,'Courier New',courier,monospace;height:130px;color:black;font-size:8pt;margin:0;padding:5px;">$(<span style="color:#0000ff;">function</span>() {
    $("<span style="color:#8b0000;">table th :checkbox</span>").click(<span style="color:#0000ff;">function</span>() {
        $(<span style="color:#0000ff;">this</span>).closest("<span style="color:#8b0000;">table</span>")
            .<span style="color:#0000ff;">find</span>("<span style="color:#8b0000;">td:nth-child(</span>" + ($(<span style="color:#0000ff;">this</span>).closest("<span style="color:#8b0000;">th</span>").prevAll().size() + 1) + "<span style="color:#8b0000;">) :checkbox</span>")
            .attr("<span style="color:#8b0000;">checked</span>", $(<span style="color:#0000ff;">this</span>).attr("<span style="color:#8b0000;">checked</span>"));
    });
});</pre>
<p>Aparte de esto, solo nos queda asegurarnos de que los checkbox de la cabecera estén en un TH y no en un TD.</p>
<p>Ahora ya no nos importa si usamos un GridView, una tabla estática, ni si posee tags THEAD y TBODY o solo TRs, ni si el checkbox es un control de servidor o simple HTML. Todos los checkboxs que tengamos en la cabecera (TH) de una tabla provocarán al cambiar su estado que cambien todos los de la misma columna.</p>
<p><span>No se a Uds. pero a mi me parece fantástico que solamente incluyendo un tag para jQuery y otro para un .js con el script (que seguramente ya estoy incorporando a nuestras páginas para utilizar otras funciones), tenga el problema resuelto en todas las páginas sin hacer más que olvidarme del tema.</span></p>
<p><span>Respecto al código, voy a usarlo como parte de la continuación de mi artículo anterior de introducción a jQuery para los que quieran entenderlo.</span></p>
<p>Nota: Debido al uso de la (excelente) función <em>closest </em>el código requiere jQuery 1.3+.</p>
<p><span>Saludos: Alejandro</span></p>
]]></content:encoded>
					
					<wfw:commentRss>https://varionet.wordpress.com/2009/06/17/como-checkear-todos-los-checkbox-de-una-columna-con-jquery/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		
		<media:content url="https://0.gravatar.com/avatar/6ac4a1d95580a307da123b4c5a56eb7e711ff8e6f9fc72c35c79ccd4a9f0ebd5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Alejandro Hernández</media:title>
		</media:content>
	</item>
		<item>
		<title>Introducci&#243;n a jQuery</title>
		<link>https://varionet.wordpress.com/2009/05/08/introduccin-a-jquery-i/</link>
					<comments>https://varionet.wordpress.com/2009/05/08/introduccin-a-jquery-i/#comments</comments>
		
		<dc:creator><![CDATA[Alejandro Hernández]]></dc:creator>
		<pubDate>Fri, 08 May 2009 19:59:47 +0000</pubDate>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<guid isPermaLink="false">http://varionet.wordpress.com/?p=93</guid>

					<description><![CDATA[He estado usando un poco jQuery y, por si después de lo que ya había visto hacía falta algo más, me terminé de convencer de que jQuery es una tremenda ayuda para quienes programamos mucho o poco en JavaScript. Este es el primero de una serie de artículos introductorios los que voy a tratar de &#8230; <a href="https://varionet.wordpress.com/2009/05/08/introduccin-a-jquery-i/" class="more-link">Continuar leyendo<span class="screen-reader-text"> "Introducci&#243;n a jQuery"</span></a>]]></description>
										<content:encoded><![CDATA[<p>He estado usando un poco jQuery y, por si después de lo que ya había visto hacía falta algo más, me terminé de convencer de que jQuery es una tremenda ayuda para quienes programamos mucho o poco en JavaScript. Este es el primero de una serie de artículos introductorios los que voy a tratar de mechar con otros con ejemplos reales. Ahí vamos:</p>
<p><strong>¿Que es jQuery?</strong></p>
<p>Una biblioteca javascript (un .js de 19k en su versión de producción) que tiene las siguientes características:</p>
<ul>
<li>Todo lo que hagamos con jQuery es «Browser-Agnostic», o sea ¡funciona igual en todos los navegadores!</li>
<li>Adhiere al concepto de Unobstrusive javascript, o sea, «No metas javascript en tu HTML», esto abarca los eventos en los tags y absolutamente todo lo que tenga que ver con javascript en el body, así como la mayoría de los &lt;script&gt; en el head, si no todos. Esto entre otras cosas facilita mucho la separación de tareas entre programador-diseñador.</li>
<li>Es OpenSource y al mismo tiempo posee cierto soporte de Microsoft, lo que incluye una versión con Intelisense y la inclusión por defecto en el nuevo  ASP.NET MCV.</li>
<li>Una comunidad importantísima, una enorme documentación y cantidad de tutoriales. Unas cuantas de estas cosas están en español.</li>
<li>Es extensible y posee una cantidad enorme de Plugins desarrollados, donde «enorme» quiere decir que en el sitio oficial hay más de mil.</li>
<li>Posee poderosos métodos para trabajar con Ajax.</li>
<li>Muchos efectos gráficos incluidos para manipular los objetos de nuestra página.</li>
</ul>
<p>También presenta tres conceptos que definen la sintaxis de jQuery y gran parte de su funcionalidad:</p>
<ol>
<li>Utiliza en su sintaxis el concepto de encadenamiento de sentencias, (A.K.A. fluent interfaces o «chaining»), que nos permite realizar una gran cantidad de acciones en una sola sentencia y nos evita declarar infinidad de variables.</li>
<li>Posee un conjunto de selectores muy poderoso con los cuales podemos recorrer el DOM a gusto y piaccere.</li>
<li>Posee una sintaxis para trabajar con eventos que permite no tener que introducir llamadas a los mismos en los tags y en increíblemente flexible.</li>
</ol>
<p>Estas características son las que veremos a lo largo de estos introducctorios, pero primero empecemos de cero:</p>
<p><strong>Incorporando jQuery a nuestras páginas</strong></p>
<p>En el sitio oficial: <a href="http://www.jquery.com/">www.jquery.com</a> podemos bajar la biblioteca en sus versiones de desarrollo, producción (minified) y visual studio, está última es una versión comentada que permite el intelisense. El sitio también es referencia en cuando a información se refiere.</p>
<p>Una vez incluido el archivos .js en nuestro proyecto, arrastramos el mismo al tag head de nuestra página, lo que genera lo siguiente:</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:consolas,'Courier New',courier,monospace;color:black;font-size:8pt;margin:0;padding:5px;"><span style="color:#0000ff;">&lt;</span><span style="color:#800000;">script</span> <span style="color:#ff0000;">src</span>=<span style="color:#0000ff;">"js/jquery-1.3.2.min.js"</span> <span style="color:#ff0000;">type</span>=<span style="color:#0000ff;">"text/javascript"</span><span style="color:#0000ff;">&gt;</span><span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">script</span><span style="color:#0000ff;">&gt;</span></pre>
<p>para la versión minified 1.3.2, la actual al momento de escribir esto. (No hay que olvidar cambiar la versión de desarrollo por la de producción cuando ya no la necesitamos y no es mala práctica renombrar el archivo a jQuery a secas para facilitar el cambio de versiones.)</p>
<p><strong>El objeto jQuery ($):</strong></p>
<p>Casi toda la funcionalidad de jQuery está contenida en un objeto llamado también jQuery. Este objeto tiene un alias que es el símbolo $, o sea que en cada lugar donde escribimos $ podemos cambiar por jQuery y viceversa. Como el símbolo $ es el estandar vamos a verlo así escrito en este artículo. Veamos la estructura de una típica sentencia jQuery:</p>
<p><span style="font-size:x-small;"> </span></p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:consolas,'Courier New',courier,monospace;color:black;font-size:8pt;margin:0;padding:5px;">$("<span style="color:#8b0000;">selector</span>").acción(parámetros);</pre>
<p><em>$(«selector»)</em> captura, a partir del selector indicado, el conjunto del DOM identificado sobre el cual aplicamos la acción, pero el valor de retorno no es directamente un array de objetos, sino que es el propio objeto $ conteniendo los objetos en su interior.</p>
<p>Cuando ejecutamos un método sobre el objeto $ que contiene los elementos que seleccionamos, este aplica dicha acción a cada uno de los objetos recuperados. Un ejemplo concreto:</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:consolas,'Courier New',courier,monospace;color:black;font-size:8pt;margin:0;padding:5px;">$("<span style="color:#8b0000;">#mensaje</span>").fadeOut(3000);</pre>
<p>Llama para el elemento con id=»mensaje» a la función fadeOut, que aumenta su transparencia hasta hacerlo desaparecer al cabo de los tres segundos indicados como parámetro.</p>
<p><strong>La función .ready</strong></p>
<p>Ya tenemos un pequeño ejemplo de código jQuery, pero ¿donde lo ponemos?</p>
<p>Si leímos bien, una de las características de jQuery es que nos permite no introducir llamadas a funciones javascript en los tags HTML, más tarde vamos a ver como atachar eventos a los objetos del DOM, pero hay un método para ejecutar código en la carga de la página y que veremos hasta en la sopa, la función ready.</p>
<p>Normalmente cuando queremos ejecutar una rutina js en la carga de la página, utilizamos el evento <em>onload</em> del body, pero esto tiene la desventaja de hacernos esperar hasta que se carga toda la página, imágenes inclusive. jQuery nos presenta un camino alternativo que es la función ready, está se ejecuta ni bien el navegador levanto el DOM en memoria, ¿y que hace? bueno, lo que nosotros querramos, ya que toma como único parámetro un callback, o sea, una función javascript, veamos la sintaxis:</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:consolas,'Courier New',courier,monospace;color:black;font-size:8pt;margin:0;padding:5px;">$(<span style="color:#0000ff;">document</span>).ready(
	<span style="color:#0000ff;">function</span>() { ... }
);</pre>
<p>Como vemos ready es una función del objeto $, el cual en este caso ha sido creado a partir del document. Como parámetro de ready, estamos enviando una función cuyo código será el que se ejecute correctamente. De esta manera si quisieramos cumplir con la inutil misión de que el código del ejemplo anterior se ejecute en primera instancia al cargar la página, tendríamos que escribir lo siguiente:</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:consolas,'Courier New',courier,monospace;color:black;font-size:8pt;margin:0;padding:5px;">&lt;script type="<span style="color:#8b0000;">text/javascript</span>"&gt;
$(<span style="color:#0000ff;">document</span>).ready(<span style="color:#0000ff;">function</span>() {
   $("<span style="color:#8b0000;">#mensaje</span>").fadeOut(3000);
});
&lt;/script&gt;</pre>
<p>Donde hemos reemplazado únicamente los «&#8230;» por nuestra función.</p>
<p>En mucha de la documentación más vieja se ve esta sintaxis, pero jQuery presenta una abreviación que es la que vamos a usar:</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:consolas,'Courier New',courier,monospace;color:black;font-size:8pt;margin:0;padding:5px;">&lt;script type="<span style="color:#8b0000;">text/javascript</span>"&gt;
    $(<span style="color:#0000ff;">function</span>() {
    	$("<span style="color:#8b0000;">#mensaje</span>").fadeOut(3000);
    });
&lt;/script&gt;</pre>
<p>Hasta aquí hemos visto solo la manera de hacer de forma interesante algo muy inútil, y es que en la gran mayoría de documentos introductorios a jQuery verán que se presenta la librería haciendo uso de fadeIn, fadeOut y varias funciones gráficas que son muy impactantes a la vez que sencillas de utilizar. He estado hace unas semanas en una charla de jQuery donde toda la atención la despertaba este tipo de funcionalidad y en el mismo sitio oficial se presenta la librería con un lindo efecto.</p>
<p>Todo eso está genial, pero si Uds, como yo, nacieron sin la parte del cerebro que se utiliza para el diseño, antes de creer que jQuery es un compendio de efectos o de hacks para algunas funcionalidades, sigan leyendo y encontrarán un tesoro de la mano de la manipulación del DOM, los selectores, el encadenamiento de sentencias, la facilidad para trabajar con AJAX, el manejo de eventos y el crossbrowsing real, por sobre otros instrumentos no tan útiles a la hora de programar comportamientos y manejo de datos en la UI.</p>
<p>Saludos.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://varionet.wordpress.com/2009/05/08/introduccin-a-jquery-i/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		
		<media:content url="https://0.gravatar.com/avatar/6ac4a1d95580a307da123b4c5a56eb7e711ff8e6f9fc72c35c79ccd4a9f0ebd5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Alejandro Hernández</media:title>
		</media:content>
	</item>
		<item>
		<title>Atachar procesos automáticamente con macros de Visual Studio</title>
		<link>https://varionet.wordpress.com/2008/07/16/atachar-procesos-automaticamente-con-macros-de-visual-studio/</link>
					<comments>https://varionet.wordpress.com/2008/07/16/atachar-procesos-automaticamente-con-macros-de-visual-studio/#respond</comments>
		
		<dc:creator><![CDATA[Alejandro Hernández]]></dc:creator>
		<pubDate>Wed, 16 Jul 2008 06:30:55 +0000</pubDate>
				<category><![CDATA[debug]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[macros]]></category>
		<category><![CDATA[VisualStudio]]></category>
		<guid isPermaLink="false">http://varionet.wordpress.com/?p=52</guid>

					<description><![CDATA[La manera de atachar un proceso a Visual Studio es clasicamente mediante &#8216;Debug &#8211; Attach to process&#8217; o el más productivo Ctrl + Alt + P, y luego seleccionar el o los procesos que querramos depurar. En desarrollos medianamente importantes es muy probable que debamos realizar este procedimiento repetidas veces para depurar un proyecto fuera &#8230; <a href="https://varionet.wordpress.com/2008/07/16/atachar-procesos-automaticamente-con-macros-de-visual-studio/" class="more-link">Continuar leyendo<span class="screen-reader-text"> "Atachar procesos automáticamente con macros de Visual&#160;Studio"</span></a>]]></description>
										<content:encoded><![CDATA[<p>La manera de atachar un proceso a Visual Studio es clasicamente mediante &#8216;Debug &#8211; Attach to process&#8217; o el más productivo Ctrl + Alt + P, y luego seleccionar el o los procesos que querramos depurar.</p>
<p>En desarrollos medianamente importantes es muy probable que debamos realizar este procedimiento repetidas veces para depurar un proyecto fuera de la interface de usuario, expuesto mediante una capa de servicios, llámese WS, remoting, WCF, etc. Ni hablar del worker process de ASP.NET,  &#8216;<span>aspnet_wp.exe&#8217;. También es común que corramos un proyecto desde fuera del Visual Studio para evitar la compilación, y luego lo atachemos al IDE.<br />
</span></p>
<p>Entonces, si los procesos que atachamos son siempre los mismos, ¿por que no automatizar la tarea?, bueno, la solución que propongo es una macro de Visual Studio que haga este trabajo, atachando con un atajo de teclado todos los procesos que sean necesarios.</p>
<p>Para incluirla en VS, vamos al editor de macros (Alt + F11), agregamos un nuevo módulo y reemplazamos el contenido por el siguiente:</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;font-size:8pt;width:100%;height:400px;color:black;line-height:12pt;font-family:consolas,'Courier New',courier,monospace;background-color:#f4f4f4;margin:0;padding:5px;"><span style="color:#0000ff;">Imports</span> System.Collections.Generic
<span style="color:#0000ff;">Imports</span> EnvDTE
<span style="color:#0000ff;">Imports</span> EnvDTE80
<span style="color:#0000ff;">Imports</span> System.Text

<span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Module</span> DebugMacros

    <span style="color:#0000ff;">Private</span> <span style="color:#0000ff;">Enum</span> EnumAction
        ResultOK
        ReRunWithDisatach
        Abort
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Enum</span>

    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Sub</span> AttachProcs()
        <span style="color:#0000ff;">Dim</span> ProcessList <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">New</span> List(<span style="color:#0000ff;">Of</span> <span style="color:#0000ff;">String</span>)
        ProcessList.Add("<span style="color:#8b0000;">InterfaceUsuario.exe</span>")
        ProcessList.Add("<span style="color:#8b0000;">MiServiceLayer.exe</span>")
        AttachProcs(<span style="color:#0000ff;">False</span>, ProcessList)
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Sub</span>

    <span style="color:#0000ff;">Private</span> <span style="color:#0000ff;">Sub</span> AttachProcs(<span style="color:#0000ff;">ByVal</span> detachAll <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>, <span style="color:#0000ff;">ByVal</span> ProcessList <span style="color:#0000ff;">As</span> List(<span style="color:#0000ff;">Of</span> <span style="color:#0000ff;">String</span>))

        <span style="color:#0000ff;">If</span> detachAll <span style="color:#0000ff;">Then</span> DTE.Debugger.DetachAll()

        <span style="color:#0000ff;">Dim</span> isOK <span style="color:#0000ff;">As</span> EnumAction = EnumAction.ResultOK
        <span style="color:#0000ff;">Dim</span> sbErrorResult <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">New</span> StringBuilder

        <span style="color:#0000ff;">For</span> <span style="color:#0000ff;">Each</span> proc <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span> <span style="color:#0000ff;">In</span> ProcessList
            <span style="color:#0000ff;">Dim</span> match <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span> = <span style="color:#0000ff;">False</span>
            <span style="color:#0000ff;">For</span> i <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Integer</span> = 1 <span style="color:#0000ff;">To</span> DTE.Debugger.LocalProcesses.Count
                <span style="color:#0000ff;">If</span> DTE.Debugger.LocalProcesses.Item(i).Name.EndsWith(proc) <span style="color:#0000ff;">Then</span>
                    match = <span style="color:#0000ff;">True</span>
                    <span style="color:#0000ff;">Exit</span> <span style="color:#0000ff;">For</span>
                <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
            <span style="color:#0000ff;">Next</span>
            <span style="color:#0000ff;">If</span> <span style="color:#0000ff;">Not</span> match <span style="color:#0000ff;">Then</span>
                sbErrorResult.Append("<span style="color:#8b0000;">El proceso '</span>" + proc + "<span style="color:#8b0000;">' no se está ejecutando.</span>" + vbCrLf)
                isOK = EnumAction.Abort
            <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
        <span style="color:#0000ff;">Next</span>

        <span style="color:#0000ff;">If</span> isOK = EnumAction.ResultOK <span style="color:#0000ff;">Then</span>
            'Desatacho todos los procesos
            <span style="color:#0000ff;">Dim</span> dbg2 <span style="color:#0000ff;">As</span> EnvDTE80.Debugger2 = DTE.Debugger
            <span style="color:#0000ff;">Dim</span> trans <span style="color:#0000ff;">As</span> EnvDTE80.Transport = dbg2.Transports.Item("<span style="color:#8b0000;">Default</span>")
            <span style="color:#0000ff;">Dim</span> dbgeng(1) <span style="color:#0000ff;">As</span> EnvDTE80.Engine
            dbgeng(0) = trans.Engines.Item("<span style="color:#8b0000;">Managed</span>")
            <span style="color:#0000ff;">Dim</span> proc2 <span style="color:#0000ff;">As</span> EnvDTE80.Process2
            <span style="color:#0000ff;">For</span> <span style="color:#0000ff;">Each</span> processName <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span> <span style="color:#0000ff;">In</span> ProcessList
                <span style="color:#0000ff;">Try</span>
                    proc2 = dbg2.GetProcesses(trans, "<span style="color:#8b0000;">.</span>").Item(processName)
                    proc2.Attach2(dbgeng)
                <span style="color:#0000ff;">Catch</span> ex <span style="color:#0000ff;">As</span> Exception
                    <span style="color:#0000ff;">If</span> ex.Message.EndsWith("<span style="color:#8b0000;">8971001E</span>") <span style="color:#0000ff;">Then</span>
                        sbErrorResult.Append("<span style="color:#8b0000;">Error atachando </span>" + processName + "<span style="color:#8b0000;">. </span>" + "<span style="color:#8b0000;">El proceso ya se encuentra atachado</span>" + vbCrLf)
                        isOK = EnumAction.ReRunWithDisatach
                    <span style="color:#0000ff;">Else</span>
                        sbErrorResult.Append("<span style="color:#8b0000;">Error inesperado atachando </span>" + processName + "<span style="color:#8b0000;">. </span>" + ex.Message + vbCrLf)
                        isOK = EnumAction.Abort
                    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
                <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Try</span>
            <span style="color:#0000ff;">Next</span>
        <span style="color:#0000ff;">Else</span>
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>

        <span style="color:#0000ff;">Select</span> <span style="color:#0000ff;">Case</span> isOK
            <span style="color:#0000ff;">Case</span> EnumAction.Abort
                DTE.Debugger.DetachAll()
                MsgBox(sbErrorResult.ToString + vbCrLf + "<span style="color:#8b0000;">No se ha atachado ningún proceso</span>", MsgBoxStyle.OkOnly, "<span style="color:#8b0000;">Error al atachar proceso</span>")
            <span style="color:#0000ff;">Case</span> EnumAction.ReRunWithDisatach
                <span style="color:#0000ff;">If</span> MsgBox("<span style="color:#8b0000;">Hay procesos previamente atachados. ¿Desea reatacharlos?</span>", _
                                    MsgBoxStyle.YesNo, "<span style="color:#8b0000;">Atachar Proceso</span>") = MsgBoxResult.Yes <span style="color:#0000ff;">Then</span>
                    AttachProcs(<span style="color:#0000ff;">True</span>, ProcessList)
                    <span style="color:#0000ff;">Exit</span> <span style="color:#0000ff;">Sub</span>
                <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
            <span style="color:#0000ff;">Case</span> EnumAction.ResultOK
                <span style="color:#0000ff;">Dim</span> Resultado <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">New</span> StringBuilder
                <span style="color:#0000ff;">For</span> <span style="color:#0000ff;">Each</span> s <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span> <span style="color:#0000ff;">In</span> ProcessList
                    Resultado.Append(s + vbCrLf)
                <span style="color:#0000ff;">Next</span>
                MsgBox("<span style="color:#8b0000;">Se han atachado los siguientes procesos: </span>" + vbCrLf + Resultado.ToString, MsgBoxStyle.OkOnly, "<span style="color:#8b0000;">Proceso atachados</span>")
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Select</span>
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Sub</span>

<span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Module</span></pre>
<p>Observar que en AttachProcs() hay una colección con los nombres de los procesos la cual hay que editar de acuerdo a nuestras necesidades.</p>
<p>Ahora solo falta asignarle una combinación de teclas, desde Tools &#8211; Options &#8211; Keyboard, filtramos por «Macro» o «AtachProcs» y una vez ubicada la macro le asignamos una combinación de teclas.</p>
<p>Ahora solo basta correr los procesos por fuera de Visual Studio y atacharlos con la combinación de teclas.</p>
<p>Si el código encuentra alguno de los procesos atachado, desatacha todos los procesos e intenta nuevamente.</p>
<p>Nota: Este simple código está hecho a partir de la grabadora de macros (Tools &#8211; Macros &#8211; Record Temporary Macro), recordemos que todo lo que hacemos en VS queda registrado en la grabadora y que casi todo en el entorno es un objeto que se puede manipular.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://varionet.wordpress.com/2008/07/16/atachar-procesos-automaticamente-con-macros-de-visual-studio/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://0.gravatar.com/avatar/6ac4a1d95580a307da123b4c5a56eb7e711ff8e6f9fc72c35c79ccd4a9f0ebd5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Alejandro Hernández</media:title>
		</media:content>
	</item>
		<item>
		<title>Depurar sin complicarnos la vida utilizando Debugging Attributes</title>
		<link>https://varionet.wordpress.com/2008/05/29/depurar-sin-complicarnos-la-vida-utilizando-debugging-attributes/</link>
					<comments>https://varionet.wordpress.com/2008/05/29/depurar-sin-complicarnos-la-vida-utilizando-debugging-attributes/#respond</comments>
		
		<dc:creator><![CDATA[Alejandro Hernández]]></dc:creator>
		<pubDate>Thu, 29 May 2008 21:01:55 +0000</pubDate>
				<category><![CDATA[debug]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[Attributes]]></category>
		<category><![CDATA[VisualStudio]]></category>
		<guid isPermaLink="false">http://varionet.wordpress.com/?p=48</guid>

					<description><![CDATA[Cuando depuramos con Visual Studio es un verdadero fastidio el hecho de tener que entrar a todos los métodos o propiedades que se encuentran dentro de una llamada, por ejemplo: void MiMétodo(DameUnString()) { //algo acá que si quiero depurar } String DameUnString() { //¡No quiero depurar esto! return "Este es tu String!"; } DebuggerStepThrough y &#8230; <a href="https://varionet.wordpress.com/2008/05/29/depurar-sin-complicarnos-la-vida-utilizando-debugging-attributes/" class="more-link">Continuar leyendo<span class="screen-reader-text"> "Depurar sin complicarnos la vida utilizando Debugging&#160;Attributes"</span></a>]]></description>
										<content:encoded><![CDATA[<p>Cuando depuramos con Visual Studio es un verdadero fastidio el hecho de tener que entrar a todos los métodos o propiedades que se encuentran dentro de una llamada, por ejemplo:</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;font-size:8pt;width:100%;height:150px;color:black;line-height:12pt;font-family:consolas,'Courier New',courier,monospace;background-color:#f4f4f4;margin:0;padding:5px;">void MiMétodo(DameUnString())
{
<span style="color:#008000;">   //algo acá que si quiero depurar</span>
}
String DameUnString()
{
<span style="color:#008000;">   //¡No quiero depurar esto!</span>
   return "Este es tu String!";
}</pre>
<p><strong>DebuggerStepThrough y DebuggerHidden</strong></p>
<p>Cuando se trabaja en cualquier sistema medianamente complejo es muy molesto depurar código como el anterior ya que no hay manera en VS de indicar que queremos ir directamente al cuerpo del método que estamos por depurar, sin entrar a cada parámetro.</p>
<p>Lo mismo ocurre cuando presionamos por error F11 en vez de F10 y entramos a un interminable método que nos obliga a poner un break al final (y luego a quitarlo para no parar nuevamente)</p>
<p>Una solución parcial pero util son los atributos DebuggerStepThrough y DebuggerHidden.</p>
<p>Poniendo DebuggerHidden a un método logramos que Visual Studio no pase nunca por el método:</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;font-size:8pt;width:100%;height:40px;color:black;line-height:12pt;font-family:consolas,'Courier New',courier,monospace;background-color:#f4f4f4;margin:0;padding:5px;">[System.Diagnostics<span style="color:#99ccff;">.</span><span style="color:#3366ff;"><span style="color:#3366ff;">DebuggerHidden</span><span style="color:#000000;">]</span>
String </span>DameUnString(){...}</pre>
<p>hará que nunca depuremos el método DameUnString.</p>
<p>En cambio con el más util DebuggerStepThrough, el entorno se detiene en el método si colocamos un break, pero no de otra manera.</p>
<p>Realmente sería más util una tecla para «Avanzar StepThrough», incluso por ahí he visto una solicitada para su inclusión en VS&#8230;pero esta es la solución parcial que tenemos disponible.</p>
<p><strong>DebuggerBrowsable y DebuggerDisplay</strong></p>
<p>Por defecto VS nos permite ver los miembros privados de las clases y estructuras que escribimos al momento de depurarlas. Si bien esto puede ser util, cuando la clase es un contenedor de datos, no es práctico disponer de esta información que está expuesta nuevamente en las propiedades públicas. Ni hablar si nuestra clase va a ser expuesta a terceros.</p>
<p>Por ejemplo si depuramos una clase «Persona» con tres propiedades vemos en la ventana de Watch una molesta duplicación de datos:</p>
<p><a href="https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug.jpg"><img loading="lazy" data-attachment-id="49" data-permalink="https://varionet.wordpress.com/2008/05/29/depurar-sin-complicarnos-la-vida-utilizando-debugging-attributes/capturadebug/" data-orig-file="https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug.jpg" data-orig-size="430,170" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="capturadebug" data-image-description="&lt;p&gt;Watch de un struct con propiedades&lt;/p&gt;
" data-image-caption="" data-medium-file="https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug.jpg?w=300" data-large-file="https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug.jpg?w=430" class="alignnone size-full wp-image-49" src="https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug.jpg?w=840" alt=""   srcset="https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug.jpg 430w, https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug.jpg?w=150&amp;h=59 150w, https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug.jpg?w=300&amp;h=119 300w" sizes="(max-width: 430px) 85vw, 430px" /></a></p>
<p>El atributo DebuggerBrowsable nos permite especificar que no se deben mostrar en el depurador los métodos, miembros o propiedades decorados con el mismo.</p>
<p>DebuggerDisplay, a su vez, nos permite especificar el texto a mostrar en la columna value de las ventanas de depuración. En la cadena que nos pide podemos especificar entre llaves «{}» código ejecutable, pero la mejor manera de entender esto es ver un ejemplo. Si la clase de la imagen anterior estuviera declarada de la siguiente manera:</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;font-size:8pt;width:100%;height:50px;color:black;line-height:12pt;font-family:consolas,'Courier New',courier,monospace;background-color:#f4f4f4;margin:0;padding:5px;">[<span style="color:#3366ff;">DebuggerDisplay</span>(<span style="color:#993366;">"{this.GetType().ToString(),nq} ({_nombre,nq} {_apellido,nq}, {_edad} años)"</span>)]<span style="color:#0000ff;">
public struct</span> <span style="color:#3366ff;">Persona</span> {...}</pre>
<p>(nq significa «No Quotes», para quitar las comillas de las cadenas)</p>
<p>y los miembros privados estuvieran decorados así:</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;font-size:8pt;width:100%;height:40px;color:black;line-height:12pt;font-family:consolas,'Courier New',courier,monospace;background-color:#f4f4f4;margin:0;padding:5px;">[<span style="color:#3366ff;">DebuggerBrowsable</span>(<span style="color:#3366ff;">DebuggerBrowsableState</span>.Never)]<span style="color:#0000ff;">
private <span style="color:#3366ff;">Int32</span></span><span style="color:#3366ff;"> </span>_edad;</pre>
<p>Entonces lo que veríamos en la ventana de Watch sería:</p>
<p><a href="https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug2.jpg"><img loading="lazy" data-attachment-id="50" data-permalink="https://varionet.wordpress.com/2008/05/29/depurar-sin-complicarnos-la-vida-utilizando-debugging-attributes/capturadebug2/" data-orig-file="https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug2.jpg" data-orig-size="521,110" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="capturadebug2" data-image-description="" data-image-caption="" data-medium-file="https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug2.jpg?w=300" data-large-file="https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug2.jpg?w=521" class="alignnone size-full wp-image-50" src="https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug2.jpg?w=840" alt=""   srcset="https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug2.jpg?w=510&amp;h=108 510w, https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug2.jpg?w=150&amp;h=32 150w, https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug2.jpg?w=300&amp;h=63 300w, https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug2.jpg 521w" sizes="(max-width: 510px) 85vw, 510px" /></a></p>
<p>Mucho más claro si tenemos en cuenta que el tipo persona lo escribiremos una sola vez pero lo depurarán por miles de años.</p>
<p>Hay otros atributos de debugging que permiten desde wrappear en otra clase lo que se va a mostrar al depurar, hasta implementar un viewer customizado para un tipo, como el que Visual Studio trae para el DataSet.</p>
<p>Nota: No olvidar que estos atributos pertenecen al namespace System.Diagnostics, por lo que hay que agregar el correspondiente using/Imports.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://varionet.wordpress.com/2008/05/29/depurar-sin-complicarnos-la-vida-utilizando-debugging-attributes/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://0.gravatar.com/avatar/6ac4a1d95580a307da123b4c5a56eb7e711ff8e6f9fc72c35c79ccd4a9f0ebd5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Alejandro Hernández</media:title>
		</media:content>

		<media:content url="https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug.jpg" medium="image" />

		<media:content url="https://varionet.wordpress.com/wp-content/uploads/2008/05/capturadebug2.jpg" medium="image" />
	</item>
		<item>
		<title>Numalet: convertir números a letras en C# y VB</title>
		<link>https://varionet.wordpress.com/2007/11/29/convertir-numeros-a-letras/</link>
					<comments>https://varionet.wordpress.com/2007/11/29/convertir-numeros-a-letras/#comments</comments>
		
		<dc:creator><![CDATA[Alejandro Hernández]]></dc:creator>
		<pubDate>Thu, 29 Nov 2007 05:51:28 +0000</pubDate>
				<category><![CDATA[.NET General]]></category>
		<category><![CDATA[números a letras]]></category>
		<category><![CDATA[Numalet]]></category>
		<category><![CDATA[utilidades]]></category>
		<guid isPermaLink="false">http://varionet.wordpress.com/2007/11/29/convertir-numeros-a-letras/</guid>

					<description><![CDATA[Indefectiblemente en algún momento necesitamos o vamos a necesitar código para transformar un número a su numeral cardinal, o sea: 44 en “Cuarenta y cuatro”. Este es otro caso en donde buscamos en google “numeros a letras” o algo así esperando una solución hecha. Bueno, aca la mía: Bajar Numalet, Esta es una solución de &#8230; <a href="https://varionet.wordpress.com/2007/11/29/convertir-numeros-a-letras/" class="more-link">Continuar leyendo<span class="screen-reader-text"> "Numalet: convertir números a letras en C# y&#160;VB"</span></a>]]></description>
										<content:encoded><![CDATA[<p>Indefectiblemente en algún momento necesitamos o vamos a necesitar código para transformar un número a su numeral cardinal, o sea: 44 en “Cuarenta y cuatro”. Este es otro caso en donde buscamos en google “numeros a letras” o algo así esperando una solución hecha. Bueno, aca la mía: <a title="Numalet. Formato: Solución VS 2005" href="https://www.dropbox.com/s/8eqz7hb6yyrsy5y/NumaletNet.zip">Bajar Numalet</a>, Esta es una solución de VS 2005 con una clase en C#, en VB, un form para probar la clase y un sencillo test unitario para comprobar que las clases en ambos lenguajes funcionan igual.</p>
<p>Al final del post está el código de la clase en C# y en VB para copiarlo directamente.</p>
<p>¿por que usar esta clase y no otra? realmente no hay ningún motivo en especial, cualquier código que resuelva este trivial tema esta bien. La clase que presento genera números acorde a la <a href="http://buscon.rae.es/dpdI/SrvltGUIBusDPD?origen=RAE&amp;lema=cardinales">especificación de la RAE</a>, respetando acentos, apócopes, etc.</p>
<p>Por otro lado, todos los algoritmos que vi generan la salida según el uso del país de quien lo programa, y si queremos otra salida debemos copiar el algoritmo o perder la configuración anterior, asique agregué algunas propiedades que permiten configurar la salida con bastante libertad para cada instancia de la clase.</p>
<p>Hechas estas aclaraciones, veamos un ejemplo sencillo:</p>
<p>C#:<em> </em><em>Numalet.ToCardinal(8,25);</em></p>
<p>VB:<em> Numalet.ToCardinal(8,25)</em></p>
<p>retorna:</p>
<p><em>ocho con 25/100.-</em></p>
<p>No hace falta instanciar la clase ya que el método <em>ToCardinal</em> es estático, ahora, si queremos una salida distinta (ahora si instanciando la clase), podemos jugar con las siguientes propiedades:</p>
<ul>
<li> <span style="color:#000000;"><span style="text-decoration:underline;">CultureInfo</span>: </span>Permite especificar que configuración regional se utiliza para parsear los números en la sobrecarga que toma strings, en nuestro caso nos importa qué separador decimal (punto o coma) reconocerá, por defecto está seteado en la configuración del thread en que corre el proceso, para cambiarlo de manera que reconozca el punto, por caso, el valor de la propiedad podría ser <em>new CultureInfo(«en-US»)</em>. <em></em>El método estático ToCardinal tiene opcionalmente una sobrecarga que acepta un CultureInfo, por lo que en una máquina donde el separador decimal es la coma, podemos traducir un número que tiene punto como separador decimal de la siguiente manera:</li>
</ul>
<p>Numalet.ToCardinal(«15.2»,<em>CultureInfo(”en-US”));</em></p>
<p>Lo que retorna: «quince con 20/100.-«.</p>
<ul>
<li><span style="color:#000000;"><span style="text-decoration:underline;">SeparadorDecimalSalida</span>: </span>Es el texto que aparece entre la parte entera y la decimal, por defecto “con”, por ejemplo: 2,28 = Dos <strong>con </strong>28/100.-</li>
<li><span style="text-decoration:underline;">LetraCapital</span>: Por defecto <em>false, </em>permite obtener “<em>quince</em>” o “<em>Quince</em>“.</li>
<li><span style="text-decoration:underline;">ConvertirDecimales</span>: Por defecto <em>false</em>, permite especificar si los decimales se muestran como número o como texto.</li>
<li><span style="text-decoration:underline;">MascaraSalidaDecimal</span>: Es la forma en la que se muestran los decimales, utiliza una cadena para dar formato, por defecto es “00/100.-”.</li>
</ul>
<blockquote>
<p align="left">El comportamiento varía según se estén convirtiendo o no los decimales. Para ello he implementado la siguiente lógica: Si el valor de MascaraSalidaDecimal comienza con &#8216;#&#8217; o &#8216;0&#8217;, se interpreta como una máscara &#8216;numérica&#8217; y se utiliza como máscara para los decimales, por ejemplo el caso por defecto (00/100.-).</p>
<p align="left">Si en cambio la cadena empieza por cualquier otro caracter, se toma como literal y se agrega al final del resultado. Por ejemplo: MascaraSalidaDecimal = «centavos» =&gt; 45,28 = cuarenta y cinco con 28 centavos.</p>
<p align="left">Hay que notar que todos los caracteres posteriores a los &#8216;0&#8217; o &#8216;#&#8217; se toman como literales, internamente se entrecomillan con (&#8216; ) comilla simple, por lo tanto, si queremos que aparezca una comilla simple en la máscara, debemos escribirla doble, por ej. si <em>MascaraSalidaDecimal </em>= <em>litros de Jack Daniel»s</em>, (y <em>SeparadorDecimalSalida</em> = &#8216;coma&#8217; ) entonces 1,2 = <em>uno coma dos litros de Jack Daniel&#8217;s</em>.</p>
</blockquote>
<ul>
<li> <span style="text-decoration:underline;">Decimales</span>: Indica la posición decimal que se utilizará para redondear los decimales al convertirlos a enteros. Recordemos que al pasar un número a su nombre, los decimales se expresan como un entero (Ej. 0,21 = &#8216;cero con 21 centésimas&#8217;, el 21 es entero), pero en un número como 8,54613654 ¿cual será el entero que represente los decimales?. Bueno, es lo que se especifica con esta propiedad, por ejemplo si <em>Decimales=</em>2 (valor por defecto) entonces 8,54613654 = &#8216;ocho con 55/100.-&#8216;</li>
</ul>
<blockquote><p>Esta propiedad cambia automáticamente al variar <em>MascaraSalidaDecimal.</em> La cantidad de caracteres &#8216;0&#8217; o &#8216;#&#8217; hasta el primer caracter distinto se toma como valor para <em>Decimales</em>. O sea, si <em>MascaraSalidaDecimal = </em>«##0 sobre mil», entonces <em>Decimales</em> = 3, por lo que 456,45667 se convierte en &#8216;cuatrocientos cincuenta y seis con 457 sobre mil&#8217;</p>
<p>Tener en cuenta que el funcionamiento de <em>MascaraSalidaDecimal </em>es un poco diferente que las cadenas de formato del framework, por ejemplo, es lo mismo en el framework hacer #/100 que ###/100, pero en nuestro caso sirve para establecer que queremos redondear en tres decimales.<em><br />
</em></p></blockquote>
<blockquote><p>Sea cual sea el valor de <em>MascaraSalidaDecimal </em>podemos cambiar la propiedad <em>Decimales </em>con posterioridad y a nuestro gusto.</p></blockquote>
<ul>
<li><span style="text-decoration:underline;">ApocoparUnoParteDecimal</span>: En castellano, cuando los números cuantifican un sustantivo masculino, se apocopa (se recorta el final de la palabra) de las decenas mayores a veinte terminadas en uno, ¿que? que en vez de poner “treinta y <strong>uno</strong> elefantes” ponemos “treinta y <strong>un</strong> elefantes”. Esta propiedad se puede setear individualmente pero también cambia junto con el valor de ConvertirDecimales ya que si queremos convertir decimales a texto, lo normal es apocopar la palabra uno, por ejemplo <em>veintiún centavos. </em>Tener en cuenta que se utiliza solo cuando <em>ConvertirDecimales</em> es verdadero.</li>
<li><span style="text-decoration:underline;">ApocoparUnoParteEntera</span>: Lo mismo que la anterior pero para las unidades de nuestro número. Esta propiedad cambia junto con <em>SeparadorDecimalSalida</em>. Si seteamos esta última a, por ejemplo, «pesos con», entonces se deduce que estoy cualificando algo (pesos) y la segunda palabra (con) se toma como conjunción (adverbio conjuntivo para los puristas creo), por lo que <em>ApocoparUnoParteEntera </em>pasa a ser true. ¿No entendiste? somos dos, veamos algunos ejemplos:
<ul>
<li>si <em>SeparadorDecimalSalida</em> = &#8216;con&#8217; entonces <em>ApocoparUnoParteEntera</em> es false y 31,2 = &#8216;treinta y <strong>uno</strong> con 20/100.-&#8216;</li>
<li>si <em>SeparadorDecimalSalida</em> = &#8216;euros con&#8217; entonces <em>ApocoparUnoParteEntera</em> es true y 31,2 = &#8216;treinta y <strong>un </strong>euros con 20/100.-&#8216;</li>
</ul>
<p>Esta propiedad también se puede cambiar con posterioridad a <em>SeparadorDecimalSalida </em>si no se desea este comportamiento.<em><br />
</em></li>
</ul>
<p>El código tiene en cuenta que:</p>
<ul>
<li>Los números 16,21,22,23 y 26 se acentúan.</li>
<li>El 21 cuando se apocopa se acentúa (veintiún).</li>
<li>Cuando cuantificamos miles, cientos de miles o millones, hay que apocopar la palabra o terminación “uno”, por ejemplo 21 es “veinti<strong>uno</strong>”, pero 21.000 es “veinti<strong>ún</strong> mil”.</li>
<li>Permite convertir números mayores o iguales a cero y menores que un billón. o sea, el mayor número permitido es 999.999.999.999 ¿te alcanza?</li>
</ul>
<p>No tiene en cuenta el género femenino, por ejemplo no genera “quinientas mujeres”. Se puede tocar el código para tener en cuenta esto, pero hay que tener cuidado porque los millones son siempre masculinos: “quinientos millones quinientas mil mujeres”, y los apocopés no se utilizan en numéros femeninos, por ej. &#8216;treinta y una montañas&#8217; y no &#8216;treinta y un montañas&#8217;. Si alguien lo utiliza lo agrego.</p>
<p><strong>Rendimiento:<br />
</strong><br />
La clase convierte 1.000.000 de números generados al azar en menos de 7 segundos en mi máquina (P4). Casi no hay ventaja en instanciar la clase, conviene hacerlo solo si vamos a variar la configuración.</p>
<p><strong>Algunos ejemplos:</strong></p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas, 'Courier New', courier, monospace;background-color:#f4f4f4;margin:0;padding:5px;">MessageBox.Show(Numalet.ToCardinal(<span style="color:#006080;">"18,25"</span>));
<span style="color:#008000;">//dieciocho con 25/100.-</span>

<span style="color:#008000;">//Si tenemos el número en un string con otro separador decimal (por ejemplo punto):</span>
MessageBox.Show(Numalet.ToCardinal(<span style="color:#006080;">"155.38"</span>, <span style="color:#0000ff;">new</span> CultureInfo(<span style="color:#006080;">"en-US"</span>)));
<span style="color:#008000;">//ciento cincuenta y cinco con 38/100.-</span>

<span style="color:#008000;">//instanciando la clase podemos generar salidas variadas</span>
Numalet let;
let = <span style="color:#0000ff;">new</span> Numalet();
<span style="color:#008000;">//un porcentaje como he visto en algunos documentos de caracter legal:</span>
let.MascaraSalidaDecimal = <span style="color:#006080;">"por ciento"</span>;
let.SeparadorDecimalSalida = <span style="color:#006080;">"con"</span>;
let.ConvertirDecimales = <span style="color:#0000ff;">true</span>;
MessageBox.Show(let.ToCustomCardinal(21.2));
<span style="color:#008000;">//veintiuno con veinte por ciento</span>

let = <span style="color:#0000ff;">null</span>;
let = <span style="color:#0000ff;">new</span> Numalet();
<span style="color:#008000;">//al uso en México (creo):</span>
let.MascaraSalidaDecimal = <span style="color:#006080;">"00/100 M.N."</span>;
let.SeparadorDecimalSalida = <span style="color:#006080;">"pesos"</span>;
<span style="color:#008000;">//observar que sin esta propiedad queda "veintiuno pesos" en vez de "veintiún pesos":</span>
let.ApocoparUnoParteEntera = <span style="color:#0000ff;">true</span>;
MessageBox.Show(<span style="color:#006080;">"Son: "</span> + let.ToCustomCardinal(1121.24));
<span style="color:#008000;">//Son: un mil ciento veintiún pesos 24/100 M.N.</span>

<span style="color:#008000;">//algo más raro</span>
let.MascaraSalidaDecimal = <span style="color:#006080;">"###0 dracmas"</span>;
<span style="color:#008000;">//###0 quiere hace que se redondee a 4 decimales y no se muestren los ceros a la izquierda,</span>
<span style="color:#008000;">//en cambio 0000 haría que, aparte de redondear en 4, se muestren los ceros a la izquierda.</span>
let.SeparadorDecimalSalida = <span style="color:#006080;">"talentos y"</span>;
let.LetraCapital = <span style="color:#0000ff;">true</span>;
MessageBox.Show(let.ToCustomCardinal(12.085));
<span style="color:#008000;">//Doce talentos y 850 dracmas</span>

<span style="color:#008000;">//una variación del anterior redondeando decimales a mano</span>
let.ConvertirDecimales = <span style="color:#0000ff;">true</span>;
<span style="color:#008000;">//redondeando en cuatro decimales</span>
let.Decimales = 4;
let.MascaraSalidaDecimal = <span style="color:#006080;">"dracmas"</span>;
MessageBox.Show(let.ToCustomCardinal(21.50028354));
<span style="color:#008000;">//Veintiún talentos y cinco mil tres dracmas</span>
let = <span style="color:#0000ff;">null</span>;</pre>
<p>Para quien quiera un comportamiendo fijo distinto al que tiene la clase, puede cambiar los valores de las constantes en la clase.</p>
<p>Espero que les sirva y saludos.</p>
<p><strong>Clase en C#:</strong></p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;font-size:8pt;width:100%;height:400px;color:black;line-height:12pt;font-family:consolas, 'Courier New', courier, monospace;background-color:#f4f4f4;margin:0;padding:5px;"><span style="color:#0000ff;">using</span> System;
<span style="color:#0000ff;">using</span> System.Text;
<span style="color:#0000ff;">using</span> System.Globalization;

<span style="color:#808080;">/// &lt;summary&gt;</span>
<span style="color:#808080;">/// Convierte números en su expresión numérica a su numeral cardinal</span>
<span style="color:#808080;">/// &lt;/summary&gt;</span>
<span style="color:#0000ff;">public</span> <span style="color:#0000ff;">sealed</span> <span style="color:#0000ff;">class</span> Numalet
{
    #region Miembros estáticos

    <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">const</span> <span style="color:#0000ff;">int</span> UNI = 0, DIECI = 1, DECENA = 2, CENTENA = 3;
    <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">string</span>[,] _matriz = <span style="color:#0000ff;">new</span> <span style="color:#0000ff;">string</span>[CENTENA + 1, 10]
        {
            {<span style="color:#0000ff;">null</span>,"<span style="color:#8b0000;"> uno</span>", "<span style="color:#8b0000;"> dos</span>", "<span style="color:#8b0000;"> tres</span>", "<span style="color:#8b0000;"> cuatro</span>", "<span style="color:#8b0000;"> cinco</span>", "<span style="color:#8b0000;"> seis</span>", "<span style="color:#8b0000;"> siete</span>", "<span style="color:#8b0000;"> ocho</span>", "<span style="color:#8b0000;"> nueve</span>"},
            {"<span style="color:#8b0000;"> diez</span>","<span style="color:#8b0000;"> once</span>","<span style="color:#8b0000;"> doce</span>","<span style="color:#8b0000;"> trece</span>","<span style="color:#8b0000;"> catorce</span>","<span style="color:#8b0000;"> quince</span>","<span style="color:#8b0000;"> dieciséis</span>","<span style="color:#8b0000;"> diecisiete</span>","<span style="color:#8b0000;"> dieciocho</span>","<span style="color:#8b0000;"> diecinueve</span>"},
            {<span style="color:#0000ff;">null</span>,<span style="color:#0000ff;">null</span>,<span style="color:#0000ff;">null</span>,"<span style="color:#8b0000;"> treinta</span>","<span style="color:#8b0000;"> cuarenta</span>","<span style="color:#8b0000;"> cincuenta</span>","<span style="color:#8b0000;"> sesenta</span>","<span style="color:#8b0000;"> setenta</span>","<span style="color:#8b0000;"> ochenta</span>","<span style="color:#8b0000;"> noventa</span>"},
            {<span style="color:#0000ff;">null</span>,<span style="color:#0000ff;">null</span>,<span style="color:#0000ff;">null</span>,<span style="color:#0000ff;">null</span>,<span style="color:#0000ff;">null</span>,"<span style="color:#8b0000;"> quinientos</span>",<span style="color:#0000ff;">null</span>,"<span style="color:#8b0000;"> setecientos</span>",<span style="color:#0000ff;">null</span>,"<span style="color:#8b0000;"> novecientos</span>"}
        };

    <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">const</span> Char sub = (Char)26;
    <span style="color:#008000;">//Cambiar acá si se quiere otro comportamiento en los métodos de clase</span>
    <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">const</span> String SeparadorDecimalSalidaDefault = "<span style="color:#8b0000;">con</span>";
    <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">const</span> String MascaraSalidaDecimalDefault = "<span style="color:#8b0000;">00'/100.-'</span>";
    <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">const</span> Int32 DecimalesDefault = 2;
    <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">const</span> Boolean LetraCapitalDefault = <span style="color:#0000ff;">false</span>;
    <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">const</span> Boolean ConvertirDecimalesDefault = <span style="color:#0000ff;">false</span>;
    <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">const</span> Boolean ApocoparUnoParteEnteraDefault = <span style="color:#0000ff;">false</span>;
    <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">const</span> Boolean ApocoparUnoParteDecimalDefault = <span style="color:#0000ff;">false</span>;

    #endregion

    #region Propiedades

    <span style="color:#0000ff;">private</span> Int32 _decimales = DecimalesDefault;
    <span style="color:#0000ff;">private</span> CultureInfo _cultureInfo = CultureInfo.CurrentCulture;
    <span style="color:#0000ff;">private</span> String _separadorDecimalSalida = SeparadorDecimalSalidaDefault;
    <span style="color:#0000ff;">private</span> Int32 _posiciones = DecimalesDefault;
    <span style="color:#0000ff;">private</span> String _mascaraSalidaDecimal, _mascaraSalidaDecimalInterna = MascaraSalidaDecimalDefault;
    <span style="color:#0000ff;">private</span> Boolean _esMascaraNumerica = <span style="color:#0000ff;">true</span>;
    <span style="color:#0000ff;">private</span> Boolean _letraCapital = LetraCapitalDefault;
    <span style="color:#0000ff;">private</span> Boolean _convertirDecimales = ConvertirDecimalesDefault;
    <span style="color:#0000ff;">private</span> Boolean _apocoparUnoParteEntera = <span style="color:#0000ff;">false</span>;
    <span style="color:#0000ff;">private</span> Boolean _apocoparUnoParteDecimal;

    <span style="color:#808080;">/// &lt;summary&gt;</span>
    <span style="color:#808080;">/// Indica la cantidad de decimales que se pasarán a entero para la conversión</span>
    <span style="color:#808080;">/// &lt;/summary&gt;</span>
    <span style="color:#808080;">/// &lt;remarks&gt;Esta propiedad cambia al cambiar MascaraDecimal por un valor que empieze con '0'&lt;/remarks&gt;</span>
    <span style="color:#0000ff;">public</span> Int32 Decimales
    {
        <span style="color:#0000ff;">get</span> { <span style="color:#0000ff;">return</span> _decimales; }
        <span style="color:#0000ff;">set</span>
        {
            <span style="color:#0000ff;">if</span> (<span style="color:#0000ff;">value</span> &gt; 10) <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> ArgumentException(<span style="color:#0000ff;">value</span>.ToString() + "<span style="color:#8b0000;"> excede el número máximo de decimales admitidos, solo se admiten hasta 10.</span>");
            _decimales = <span style="color:#0000ff;">value</span>;
        }
    }

    <span style="color:#808080;">/// &lt;summary&gt;</span>
    <span style="color:#808080;">/// Objeto CultureInfo utilizado para convertir las cadenas de entrada en números</span>
    <span style="color:#808080;">/// &lt;/summary&gt;</span>
    <span style="color:#0000ff;">public</span> CultureInfo CultureInfo
    {
        <span style="color:#0000ff;">get</span> { <span style="color:#0000ff;">return</span> _cultureInfo; }
        <span style="color:#0000ff;">set</span> { _cultureInfo = <span style="color:#0000ff;">value</span>; }
    }

    <span style="color:#808080;">/// &lt;summary&gt;</span>
    <span style="color:#808080;">/// Indica la cadena a intercalar entre la parte entera y la decimal del número</span>
    <span style="color:#808080;">/// &lt;/summary&gt;</span>
    <span style="color:#0000ff;">public</span> String SeparadorDecimalSalida
    {
        <span style="color:#0000ff;">get</span> { <span style="color:#0000ff;">return</span> _separadorDecimalSalida; }
        <span style="color:#0000ff;">set</span>
        {
            _separadorDecimalSalida = <span style="color:#0000ff;">value</span>;
            <span style="color:#008000;">//Si el separador decimal es compuesto, infiero que estoy cuantificando algo,</span>
            <span style="color:#008000;">//por lo que apocopo el "uno" convirtiéndolo en "un"</span>
            <span style="color:#0000ff;">if</span> (<span style="color:#0000ff;">value</span>.Trim().IndexOf("<span style="color:#8b0000;"> </span>") &gt; 0)
                _apocoparUnoParteEntera = <span style="color:#0000ff;">true</span>;
            <span style="color:#0000ff;">else</span> _apocoparUnoParteEntera = <span style="color:#0000ff;">false</span>;
        }
    }

    <span style="color:#808080;">/// &lt;summary&gt;</span>
    <span style="color:#808080;">/// Indica el formato que se le dara a la parte decimal del número</span>
    <span style="color:#808080;">/// &lt;/summary&gt;</span>
    <span style="color:#0000ff;">public</span> String MascaraSalidaDecimal
    {
        <span style="color:#0000ff;">get</span>
        {
            <span style="color:#0000ff;">if</span> (!String.IsNullOrEmpty(_mascaraSalidaDecimal))
                <span style="color:#0000ff;">return</span> _mascaraSalidaDecimal;
            <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">return</span> "";
        }
        <span style="color:#0000ff;">set</span>
        {
            <span style="color:#008000;">//determino la cantidad de cifras a redondear a partir de la cantidad de '0' o '#' </span>
            <span style="color:#008000;">//que haya al principio de la cadena, y también si es una máscara numérica</span>
            <span style="color:#0000ff;">int</span> i = 0;
            <span style="color:#0000ff;">while</span> (i &lt; <span style="color:#0000ff;">value</span>.Length
                &amp;&amp; (<span style="color:#0000ff;">value</span>[i] == '0')
                    | <span style="color:#0000ff;">value</span>[i] == '#')
                i++;
            _posiciones = i;
            <span style="color:#0000ff;">if</span> (i &gt; 0)
            {
                _decimales = i;
                _esMascaraNumerica = <span style="color:#0000ff;">true</span>;
            }
            <span style="color:#0000ff;">else</span> _esMascaraNumerica = <span style="color:#0000ff;">false</span>;
            _mascaraSalidaDecimal = <span style="color:#0000ff;">value</span>;
            <span style="color:#0000ff;">if</span> (_esMascaraNumerica)
                _mascaraSalidaDecimalInterna = <span style="color:#0000ff;">value</span>.Substring(0, _posiciones) + "<span style="color:#8b0000;">'</span>"
                    + <span style="color:#0000ff;">value</span>.Substring(_posiciones)
                    .Replace("<span style="color:#8b0000;">''</span>", sub.ToString())
                    .Replace("<span style="color:#8b0000;">'</span>", String.Empty)
                    .Replace(sub.ToString(), "<span style="color:#8b0000;">'</span>") + "<span style="color:#8b0000;">'</span>";
            <span style="color:#0000ff;">else</span>
                _mascaraSalidaDecimalInterna = <span style="color:#0000ff;">value</span>
                    .Replace("<span style="color:#8b0000;">''</span>", sub.ToString())
                    .Replace("<span style="color:#8b0000;">'</span>", String.Empty)
                    .Replace(sub.ToString(), "<span style="color:#8b0000;">'</span>");
        }
    }

    <span style="color:#808080;">/// &lt;summary&gt;</span>
    <span style="color:#808080;">/// Indica si la primera letra del resultado debe estár en mayúscula</span>
    <span style="color:#808080;">/// &lt;/summary&gt;</span>
    <span style="color:#0000ff;">public</span> Boolean LetraCapital
    {
        <span style="color:#0000ff;">get</span> { <span style="color:#0000ff;">return</span> _letraCapital; }
        <span style="color:#0000ff;">set</span> { _letraCapital = <span style="color:#0000ff;">value</span>; }
    }

    <span style="color:#808080;">/// &lt;summary&gt;</span>
    <span style="color:#808080;">/// Indica si se deben convertir los decimales a su expresión nominal</span>
    <span style="color:#808080;">/// &lt;/summary&gt;</span>
    <span style="color:#0000ff;">public</span> Boolean ConvertirDecimales
    {
        <span style="color:#0000ff;">get</span> { <span style="color:#0000ff;">return</span> _convertirDecimales; }
        <span style="color:#0000ff;">set</span>
        {
            _convertirDecimales = <span style="color:#0000ff;">value</span>;
            _apocoparUnoParteDecimal = <span style="color:#0000ff;">value</span>;
            <span style="color:#0000ff;">if</span> (<span style="color:#0000ff;">value</span>)
            {<span style="color:#008000;">// Si la máscara es la default, la borro</span>
                <span style="color:#0000ff;">if</span> (_mascaraSalidaDecimal == MascaraSalidaDecimalDefault)
                    MascaraSalidaDecimal = "";
            }
            <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span> (String.IsNullOrEmpty(_mascaraSalidaDecimal))
                <span style="color:#008000;">//Si no hay máscara dejo la default</span>
                MascaraSalidaDecimal = MascaraSalidaDecimalDefault;
        }
    }

    <span style="color:#808080;">/// &lt;summary&gt;</span>
    <span style="color:#808080;">/// Indica si de debe cambiar "uno" por "un" en las unidades.</span>
    <span style="color:#808080;">/// &lt;/summary&gt;</span>
    <span style="color:#0000ff;">public</span> Boolean ApocoparUnoParteEntera
    {
        <span style="color:#0000ff;">get</span> { <span style="color:#0000ff;">return</span> _apocoparUnoParteEntera; }
        <span style="color:#0000ff;">set</span> { _apocoparUnoParteEntera = <span style="color:#0000ff;">value</span>; }
    }

    <span style="color:#808080;">/// &lt;summary&gt;</span>
    <span style="color:#808080;">/// Determina si se debe apococopar el "uno" en la parte decimal</span>
    <span style="color:#808080;">/// &lt;/summary&gt;</span>
    <span style="color:#808080;">/// &lt;remarks&gt;El valor de esta propiedad cambia al setear ConvertirDecimales&lt;/remarks&gt;</span>
    <span style="color:#0000ff;">public</span> Boolean ApocoparUnoParteDecimal
    {
        <span style="color:#0000ff;">get</span> { <span style="color:#0000ff;">return</span> _apocoparUnoParteDecimal; }
        <span style="color:#0000ff;">set</span> { _apocoparUnoParteDecimal = <span style="color:#0000ff;">value</span>; }
    }

    #endregion

    #region Constructores

    <span style="color:#0000ff;">public</span> Numalet()
    {
        MascaraSalidaDecimal = MascaraSalidaDecimalDefault;
        SeparadorDecimalSalida = SeparadorDecimalSalidaDefault;
        LetraCapital = LetraCapitalDefault;
        ConvertirDecimales = _convertirDecimales;
    }

    <span style="color:#0000ff;">public</span> Numalet(Boolean ConvertirDecimales, String MascaraSalidaDecimal, String SeparadorDecimalSalida, Boolean LetraCapital)
    {
        <span style="color:#0000ff;">if</span> (!String.IsNullOrEmpty(MascaraSalidaDecimal))
            <span style="color:#0000ff;">this</span>.MascaraSalidaDecimal = MascaraSalidaDecimal;
        <span style="color:#0000ff;">if</span> (!String.IsNullOrEmpty(SeparadorDecimalSalida))
            _separadorDecimalSalida = SeparadorDecimalSalida;
        _letraCapital = LetraCapital;
        _convertirDecimales = ConvertirDecimales;
    }
    #endregion

    #region Conversores de instancia

    <span style="color:#0000ff;">public</span> String ToCustomCardinal(Double Numero)
    { <span style="color:#0000ff;">return</span> Convertir((Decimal)Numero, _decimales, _separadorDecimalSalida, _mascaraSalidaDecimalInterna, _esMascaraNumerica, _letraCapital, _convertirDecimales, _apocoparUnoParteEntera, _apocoparUnoParteDecimal); }

    <span style="color:#0000ff;">public</span> String ToCustomCardinal(String Numero)
    {
        Double dNumero;
        <span style="color:#0000ff;">if</span> (Double.TryParse(Numero, NumberStyles.Float, _cultureInfo, <span style="color:#0000ff;">out</span> dNumero))
            <span style="color:#0000ff;">return</span> ToCustomCardinal(dNumero);
        <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> ArgumentException("<span style="color:#8b0000;">'</span>" + Numero + "<span style="color:#8b0000;">' no es un número válido.</span>");
    }

    <span style="color:#0000ff;">public</span> String ToCustomCardinal(Decimal Numero)
    { <span style="color:#0000ff;">return</span> ToCardinal((Numero)); }

    <span style="color:#0000ff;">public</span> String ToCustomCardinal(Int32 Numero)
    { <span style="color:#0000ff;">return</span> Convertir((Decimal)Numero, 0, _separadorDecimalSalida, _mascaraSalidaDecimalInterna, _esMascaraNumerica, _letraCapital, _convertirDecimales, _apocoparUnoParteEntera, <span style="color:#0000ff;">false</span>); }

    #endregion

    #region Conversores estáticos

    <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> String ToCardinal(Int32 Numero)
    {
        <span style="color:#0000ff;">return</span> Convertir((Decimal)Numero, 0, <span style="color:#0000ff;">null</span>, <span style="color:#0000ff;">null</span>, <span style="color:#0000ff;">true</span>, LetraCapitalDefault, ConvertirDecimalesDefault, ApocoparUnoParteEnteraDefault, ApocoparUnoParteDecimalDefault);
    }

    <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> String ToCardinal(Double Numero)
    {
        <span style="color:#0000ff;">return</span> ToCardinal((Decimal)Numero);
    }

    <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> String ToCardinal(String Numero, CultureInfo ReferenciaCultural)
    {
        Double dNumero;
        <span style="color:#0000ff;">if</span> (Double.TryParse(Numero, NumberStyles.Float, ReferenciaCultural, <span style="color:#0000ff;">out</span> dNumero))
            <span style="color:#0000ff;">return</span> ToCardinal(dNumero);
        <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> ArgumentException("<span style="color:#8b0000;">'</span>" + Numero + "<span style="color:#8b0000;">' no es un número válido.</span>");
    }

    <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> String ToCardinal(String Numero)
    {
        <span style="color:#0000ff;">return</span> Numalet.ToCardinal(Numero, CultureInfo.CurrentCulture);
    }

    <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> String ToCardinal(Decimal Numero)
    {
        <span style="color:#0000ff;">return</span> Convertir(Numero, DecimalesDefault, SeparadorDecimalSalidaDefault, MascaraSalidaDecimalDefault, <span style="color:#0000ff;">true</span>, LetraCapitalDefault, ConvertirDecimalesDefault, ApocoparUnoParteEnteraDefault, ApocoparUnoParteDecimalDefault);
    }

    #endregion

    <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> String Convertir(Decimal Numero, Int32 Decimales, String SeparadorDecimalSalida, String MascaraSalidaDecimal, Boolean EsMascaraNumerica, Boolean LetraCapital, Boolean ConvertirDecimales, Boolean ApocoparUnoParteEntera, Boolean ApocoparUnoParteDecimal)
    {
        Int64 Num;
        Int32 terna, centenaTerna, decenaTerna, unidadTerna, iTerna;
        String cadTerna;
        StringBuilder Resultado = <span style="color:#0000ff;">new</span> StringBuilder();

        Num = (Int64)Math.Abs(Numero);

        <span style="color:#0000ff;">if</span> (Num &gt;= 1000000000000 || Num &lt; 0) <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> ArgumentException("<span style="color:#8b0000;">El número '</span>" + Numero.ToString() + "<span style="color:#8b0000;">' excedió los límites del conversor: [0;1.000.000.000.000)</span>");
        <span style="color:#0000ff;">if</span> (Num == 0)
            Resultado.Append("<span style="color:#8b0000;"> cero</span>");
        <span style="color:#0000ff;">else</span>
        {
            iTerna = 0;
            <span style="color:#0000ff;">while</span> (Num &gt; 0)
            {
                iTerna++;
                cadTerna = String.Empty;
                terna = (Int32)(Num % 1000);

                centenaTerna = (Int32)(terna / 100);
                decenaTerna = terna % 100;
                unidadTerna = terna % 10;

                <span style="color:#0000ff;">if</span> ((decenaTerna &gt; 0) &amp;&amp; (decenaTerna &lt; 10))
                    cadTerna = _matriz[UNI, unidadTerna] + cadTerna;
                <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span> ((decenaTerna &gt;= 10) &amp;&amp; (decenaTerna &lt; 20))
                    cadTerna = cadTerna + _matriz[DIECI, unidadTerna];
                <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span> (decenaTerna == 20)
                    cadTerna = cadTerna + "<span style="color:#8b0000;"> veinte</span>";
                <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span> ((decenaTerna &gt; 20) &amp;&amp; (decenaTerna &lt; 30))
                    cadTerna = "<span style="color:#8b0000;"> veinti</span>" + _matriz[UNI, unidadTerna].Substring(1);
                <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span> ((decenaTerna &gt;= 30) &amp;&amp; (decenaTerna &lt; 100))
                    <span style="color:#0000ff;">if</span> (unidadTerna != 0)
                        cadTerna = _matriz[DECENA, (Int32)(decenaTerna / 10)] + "<span style="color:#8b0000;"> y</span>" + _matriz[UNI, unidadTerna] + cadTerna;
                    <span style="color:#0000ff;">else</span>
                        cadTerna += _matriz[DECENA, (Int32)(decenaTerna / 10)];

                <span style="color:#0000ff;">switch</span> (centenaTerna)
                {
                    <span style="color:#0000ff;">case</span> 1:
                        <span style="color:#0000ff;">if</span> (decenaTerna &gt; 0) cadTerna = "<span style="color:#8b0000;"> ciento</span>" + cadTerna;
                        <span style="color:#0000ff;">else</span> cadTerna = "<span style="color:#8b0000;"> cien</span>" + cadTerna;
                        <span style="color:#0000ff;">break</span>;
                    <span style="color:#0000ff;">case</span> 5:
                    <span style="color:#0000ff;">case</span> 7:
                    <span style="color:#0000ff;">case</span> 9:
                        cadTerna = _matriz[CENTENA, (Int32)(terna / 100)] + cadTerna;
                        <span style="color:#0000ff;">break</span>;
                    <span style="color:#0000ff;">default</span>:
                        <span style="color:#0000ff;">if</span> ((Int32)(terna / 100) &gt; 1) cadTerna = _matriz[UNI, (Int32)(terna / 100)] + "<span style="color:#8b0000;">cientos</span>" + cadTerna;
                        <span style="color:#0000ff;">break</span>;
                }
                <span style="color:#008000;">//Reemplazo el 'uno' por 'un' si no es en las únidades o si se solicító apocopar</span>
                <span style="color:#0000ff;">if</span> ((iTerna &gt; 1 | ApocoparUnoParteEntera) &amp;&amp; decenaTerna == 21)
                    cadTerna = cadTerna.Replace("<span style="color:#8b0000;">veintiuno</span>", "<span style="color:#8b0000;">veintiún</span>");
                <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span> ((iTerna &gt; 1 | ApocoparUnoParteEntera) &amp;&amp; unidadTerna == 1 &amp;&amp; decenaTerna != 11)
                    cadTerna = cadTerna.Substring(0, cadTerna.Length - 1);
                <span style="color:#008000;">//Acentúo 'veintidós', 'veintitrés' y 'veintiséis'</span>
                <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span> (decenaTerna == 22) cadTerna = cadTerna.Replace("<span style="color:#8b0000;">veintidos</span>", "<span style="color:#8b0000;">veintidós</span>");
                <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span> (decenaTerna == 23) cadTerna = cadTerna.Replace("<span style="color:#8b0000;">veintitres</span>", "<span style="color:#8b0000;">veintitrés</span>");
                <span style="color:#0000ff;">else</span> <span style="color:#0000ff;">if</span> (decenaTerna == 26) cadTerna = cadTerna.Replace("<span style="color:#8b0000;">veintiseis</span>", "<span style="color:#8b0000;">veintiséis</span>");

                <span style="color:#008000;">//Completo miles y millones</span>
                <span style="color:#0000ff;">switch</span> (iTerna)
                {
                    <span style="color:#0000ff;">case</span> 3:
                        <span style="color:#0000ff;">if</span> (Numero &lt; 2000000) cadTerna += "<span style="color:#8b0000;"> millón</span>";
                        <span style="color:#0000ff;">else</span> cadTerna += "<span style="color:#8b0000;"> millones</span>";
                        <span style="color:#0000ff;">break</span>;
                    <span style="color:#0000ff;">case</span> 2:
                    <span style="color:#0000ff;">case</span> 4:
                        <span style="color:#0000ff;">if</span> (terna &gt; 0) cadTerna += "<span style="color:#8b0000;"> mil</span>";
                        <span style="color:#0000ff;">break</span>;
                }
                Resultado.Insert(0, cadTerna);
                Num = (Int32)(Num / 1000);
            } <span style="color:#008000;">//while</span>
        }

        <span style="color:#008000;">//Se agregan los decimales si corresponde</span>
        <span style="color:#0000ff;">if</span> (Decimales &gt; 0)
        {
            Resultado.Append("<span style="color:#8b0000;"> </span>" + SeparadorDecimalSalida + "<span style="color:#8b0000;"> </span>");
            Int32 EnteroDecimal = (Int32)Math.Round((Double)(Numero - (Int64)Numero) * Math.Pow(10, Decimales), 0);
            <span style="color:#0000ff;">if</span> (ConvertirDecimales)
            {
                Boolean esMascaraDecimalDefault = MascaraSalidaDecimal == MascaraSalidaDecimalDefault;
                Resultado.Append(Convertir((Decimal)EnteroDecimal, 0, <span style="color:#0000ff;">null</span>, <span style="color:#0000ff;">null</span>, EsMascaraNumerica, <span style="color:#0000ff;">false</span>, <span style="color:#0000ff;">false</span>, (ApocoparUnoParteDecimal &amp;&amp; !EsMascaraNumerica<span style="color:#008000;">/*&amp;&amp; !esMascaraDecimalDefault*/</span>), <span style="color:#0000ff;">false</span>) + "<span style="color:#8b0000;"> </span>"
                    + (EsMascaraNumerica ? "" : MascaraSalidaDecimal));
            }
            <span style="color:#0000ff;">else</span>
                <span style="color:#0000ff;">if</span> (EsMascaraNumerica) Resultado.Append(EnteroDecimal.ToString(MascaraSalidaDecimal));
                <span style="color:#0000ff;">else</span> Resultado.Append(EnteroDecimal.ToString() + "<span style="color:#8b0000;"> </span>" + MascaraSalidaDecimal);
        }
        <span style="color:#008000;">//Se pone la primer letra en mayúscula si corresponde y se retorna el resultado</span>
        <span style="color:#0000ff;">if</span> (LetraCapital)
            <span style="color:#0000ff;">return</span> Resultado[1].ToString().ToUpper() + Resultado.ToString(2, Resultado.Length - 2);
        <span style="color:#0000ff;">else</span>
            <span style="color:#0000ff;">return</span> Resultado.ToString().Substring(1);
    }
}</pre>
<p><strong>Clase en VB:</strong></p>
<pre style="border:1px solid gainsboro;overflow:auto;height:400px;background-image:none;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas, 'Courier New', courier, monospace;background-color:#f4f4f4;margin:0;padding:5px;"><span style="color:#0000ff;">Imports</span> System
<span style="color:#0000ff;">Imports</span> System.Text
<span style="color:#0000ff;">Imports</span> System.Globalization

''' &lt;summary&gt;
''' Convierte números en su expresión numérica a su numeral cardinal
''' &lt;/summary&gt;
<span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">NotInheritable</span> <span style="color:#0000ff;">Class</span> Numalet

#Region "<span style="color:#8b0000;">Miembros estáticos</span>"

    <span style="color:#0000ff;">Private</span> <span style="color:#0000ff;">Const</span> UNI <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Integer</span> = 0, DIECI <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Integer</span> = 1, DECENA <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Integer</span> = 2, CENTENA <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Integer</span> = 3
    <span style="color:#0000ff;">Private</span> <span style="color:#0000ff;">Shared</span> _matriz <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>(,) = <span style="color:#0000ff;">New</span> <span style="color:#0000ff;">String</span>(CENTENA, 9) { _
        {<span style="color:#0000ff;">Nothing</span>, "<span style="color:#8b0000;"> uno</span>", "<span style="color:#8b0000;"> dos</span>", "<span style="color:#8b0000;"> tres</span>", "<span style="color:#8b0000;"> cuatro</span>", "<span style="color:#8b0000;"> cinco</span>", "<span style="color:#8b0000;"> seis</span>", "<span style="color:#8b0000;"> siete</span>", "<span style="color:#8b0000;"> ocho</span>", "<span style="color:#8b0000;"> nueve</span>"}, _
        {"<span style="color:#8b0000;"> diez</span>", "<span style="color:#8b0000;"> once</span>", "<span style="color:#8b0000;"> doce</span>", "<span style="color:#8b0000;"> trece</span>", "<span style="color:#8b0000;"> catorce</span>", "<span style="color:#8b0000;"> quince</span>", "<span style="color:#8b0000;"> dieciséis</span>", "<span style="color:#8b0000;"> diecisiete</span>", "<span style="color:#8b0000;"> dieciocho</span>", "<span style="color:#8b0000;"> diecinueve</span>"}, _
        {<span style="color:#0000ff;">Nothing</span>, <span style="color:#0000ff;">Nothing</span>, <span style="color:#0000ff;">Nothing</span>, "<span style="color:#8b0000;"> treinta</span>", "<span style="color:#8b0000;"> cuarenta</span>", "<span style="color:#8b0000;"> cincuenta</span>", "<span style="color:#8b0000;"> sesenta</span>", "<span style="color:#8b0000;"> setenta</span>", "<span style="color:#8b0000;"> ochenta</span>", "<span style="color:#8b0000;"> noventa</span>"}, _
        {<span style="color:#0000ff;">Nothing</span>, <span style="color:#0000ff;">Nothing</span>, <span style="color:#0000ff;">Nothing</span>, <span style="color:#0000ff;">Nothing</span>, <span style="color:#0000ff;">Nothing</span>, "<span style="color:#8b0000;"> quinientos</span>", <span style="color:#0000ff;">Nothing</span>, "<span style="color:#8b0000;"> setecientos</span>", <span style="color:#0000ff;">Nothing</span>, "<span style="color:#8b0000;"> novecientos</span>"}}
    <span style="color:#0000ff;">Private</span> <span style="color:#0000ff;">Const</span> [<span style="color:#0000ff;">sub</span>] <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Char</span> = <span style="color:#0000ff;">CChar</span>(ChrW(26))
    'Cambiar acá si se quiere otro comportamiento en los métodos de clase
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Const</span> SeparadorDecimalSalidaDefault <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span> = "<span style="color:#8b0000;">con</span>"
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Const</span> MascaraSalidaDecimalDefault <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span> = "<span style="color:#8b0000;">00'/100.-'</span>"
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Const</span> DecimalesDefault <span style="color:#0000ff;">As</span> Int32 = 2
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Const</span> LetraCapitalDefault <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span> = <span style="color:#0000ff;">False</span>
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Const</span> ConvertirDecimalesDefault <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span> = <span style="color:#0000ff;">False</span>
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Const</span> ApocoparUnoParteEnteraDefault <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span> = <span style="color:#0000ff;">False</span>
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Const</span> ApocoparUnoParteDecimalDefault <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span> = <span style="color:#0000ff;">False</span>

#<span style="color:#0000ff;">End</span> Region

#Region "<span style="color:#8b0000;">Propiedades</span>"

    <span style="color:#0000ff;">Private</span> _decimales <span style="color:#0000ff;">As</span> Int32 = DecimalesDefault
    <span style="color:#0000ff;">Private</span> _cultureInfo <span style="color:#0000ff;">As</span> CultureInfo = Globalization.CultureInfo.CurrentCulture
    <span style="color:#0000ff;">Private</span> _separadorDecimalSalida <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span> = SeparadorDecimalSalidaDefault
    <span style="color:#0000ff;">Private</span> _posiciones <span style="color:#0000ff;">As</span> Int32 = DecimalesDefault
    <span style="color:#0000ff;">Private</span> _mascaraSalidaDecimal <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>, _mascaraSalidaDecimalInterna <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span> = MascaraSalidaDecimalDefault
    <span style="color:#0000ff;">Private</span> _esMascaraNumerica <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span> = <span style="color:#0000ff;">True</span>
    <span style="color:#0000ff;">Private</span> _letraCapital <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span> = LetraCapitalDefault
    <span style="color:#0000ff;">Private</span> _convertirDecimales <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span> = ConvertirDecimalesDefault
    <span style="color:#0000ff;">Private</span> _apocoparUnoParteEntera <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span> = <span style="color:#0000ff;">False</span>
    <span style="color:#0000ff;">Private</span> _apocoparUnoParteDecimal <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>

    ''' &lt;summary&gt;
    ''' Indica la cantidad de decimales que se pasarán a entero para la conversión
    ''' &lt;/summary&gt;
    ''' &lt;remarks&gt;Esta propiedad cambia al cambiar MascaraDecimal por un valor que empieze con '0'&lt;/remarks&gt;
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Property</span> Decimales() <span style="color:#0000ff;">As</span> Int32
        <span style="color:#0000ff;">Get</span>
            <span style="color:#0000ff;">Return</span> _decimales
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Get</span>
        <span style="color:#0000ff;">Set</span>(<span style="color:#0000ff;">ByVal</span> value <span style="color:#0000ff;">As</span> Int32)
            <span style="color:#0000ff;">If</span> value &gt; 10 <span style="color:#0000ff;">Then</span>
                <span style="color:#0000ff;">Throw</span> <span style="color:#0000ff;">New</span> ArgumentException(value.ToString() + "<span style="color:#8b0000;"> excede el número máximo de decimales admitidos, solo se admiten hasta 10.</span>")
            <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
            _decimales = value
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Set</span>
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Property</span>

    ''' &lt;summary&gt;
    ''' Objeto CultureInfo utilizado para convertir las cadenas de entrada en números
    ''' &lt;/summary&gt;
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Property</span> CultureInfo() <span style="color:#0000ff;">As</span> CultureInfo
        <span style="color:#0000ff;">Get</span>
            <span style="color:#0000ff;">Return</span> _cultureInfo
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Get</span>
        <span style="color:#0000ff;">Set</span>(<span style="color:#0000ff;">ByVal</span> value <span style="color:#0000ff;">As</span> CultureInfo)
            _cultureInfo = value
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Set</span>
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Property</span>

    ''' &lt;summary&gt;
    ''' Indica la cadena a intercalar entre la parte entera y la <span style="color:#0000ff;">decimal</span> del número
    ''' &lt;/summary&gt;
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Property</span> SeparadorDecimalSalida() <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>
        <span style="color:#0000ff;">Get</span>
            <span style="color:#0000ff;">Return</span> _separadorDecimalSalida
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Get</span>
        <span style="color:#0000ff;">Set</span>(<span style="color:#0000ff;">ByVal</span> value <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>)
            _separadorDecimalSalida = value
            'Si el separador <span style="color:#0000ff;">decimal</span> es compuesto, infiero que estoy cuantificando algo,
            'por lo que apocopo el "<span style="color:#8b0000;">uno</span>" convirtiéndolo en "<span style="color:#8b0000;">un</span>"
            <span style="color:#0000ff;">If</span> value.Trim().IndexOf("<span style="color:#8b0000;"> </span>") &gt; 0 <span style="color:#0000ff;">Then</span>
                _apocoparUnoParteEntera = <span style="color:#0000ff;">True</span>
            <span style="color:#0000ff;">Else</span>
                _apocoparUnoParteEntera = <span style="color:#0000ff;">False</span>
            <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Set</span>
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Property</span>

    ''' &lt;summary&gt;
    ''' Indica el formato que se le dara a la parte <span style="color:#0000ff;">decimal</span> del número
    ''' &lt;/summary&gt;
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Property</span> MascaraSalidaDecimal() <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>
        <span style="color:#0000ff;">Get</span>
            <span style="color:#0000ff;">If</span> <span style="color:#0000ff;">Not</span> [<span style="color:#0000ff;">String</span>].IsNullOrEmpty(_mascaraSalidaDecimal) <span style="color:#0000ff;">Then</span>
                <span style="color:#0000ff;">Return</span> _mascaraSalidaDecimal
            <span style="color:#0000ff;">Else</span>
                <span style="color:#0000ff;">Return</span> ""
            <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Get</span>
        <span style="color:#0000ff;">Set</span>(<span style="color:#0000ff;">ByVal</span> value <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>)
            'determino la cantidad de cifras a redondear a partir de la cantidad de '0' o ''
            'que haya al principio de la cadena, y también si es una máscara numérica
            <span style="color:#0000ff;">Dim</span> i <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Integer</span> = 0
            <span style="color:#0000ff;">While</span> i &lt; value.Length <span style="color:#0000ff;">AndAlso</span> (value(i) = "<span style="color:#8b0000;">0</span>"c <span style="color:#0000ff;">OrElse</span> value(i) = "#")
                i += 1
            <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">While</span>
            _posiciones = i
            <span style="color:#0000ff;">If</span> i &gt; 0 <span style="color:#0000ff;">Then</span>
                _decimales = i
                _esMascaraNumerica = <span style="color:#0000ff;">True</span>
            <span style="color:#0000ff;">Else</span>
                _esMascaraNumerica = <span style="color:#0000ff;">False</span>
            <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
            _mascaraSalidaDecimal = value
            <span style="color:#0000ff;">If</span> _esMascaraNumerica <span style="color:#0000ff;">Then</span>
                _mascaraSalidaDecimalInterna = value.Substring(0, _posiciones) + "<span style="color:#8b0000;">'</span>" + value.Substring(_posiciones).Replace("<span style="color:#8b0000;">''</span>", [<span style="color:#0000ff;">sub</span>].ToString()).Replace("<span style="color:#8b0000;">'</span>", [<span style="color:#0000ff;">String</span>].Empty).Replace([<span style="color:#0000ff;">sub</span>].ToString(), "<span style="color:#8b0000;">'</span>") + "<span style="color:#8b0000;">'</span>"
            <span style="color:#0000ff;">Else</span>
                _mascaraSalidaDecimalInterna = value.Replace("<span style="color:#8b0000;">''</span>", [<span style="color:#0000ff;">sub</span>].ToString()).Replace("<span style="color:#8b0000;">'</span>", [<span style="color:#0000ff;">String</span>].Empty).Replace([<span style="color:#0000ff;">sub</span>].ToString(), "<span style="color:#8b0000;">'</span>")
            <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Set</span>
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Property</span>

    ''' &lt;summary&gt;
    ''' Indica si la primera letra del resultado debe estár en mayúscula
    ''' &lt;/summary&gt;
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Property</span> LetraCapital() <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>
        <span style="color:#0000ff;">Get</span>
            <span style="color:#0000ff;">Return</span> _letraCapital
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Get</span>
        <span style="color:#0000ff;">Set</span>(<span style="color:#0000ff;">ByVal</span> value <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>)
            _letraCapital = value
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Set</span>
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Property</span>

    ''' &lt;summary&gt;
    ''' Indica si se deben convertir los decimales a su expresión nominal
    ''' &lt;/summary&gt;
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Property</span> ConvertirDecimales() <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>
        <span style="color:#0000ff;">Get</span>
            <span style="color:#0000ff;">Return</span> _convertirDecimales
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Get</span>
        <span style="color:#0000ff;">Set</span>(<span style="color:#0000ff;">ByVal</span> value <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>)
            _convertirDecimales = value
            _apocoparUnoParteDecimal = value
            <span style="color:#0000ff;">If</span> value <span style="color:#0000ff;">Then</span>
                ' Si la máscara es la <span style="color:#0000ff;">default</span>, la borro
                <span style="color:#0000ff;">If</span> _mascaraSalidaDecimal = MascaraSalidaDecimalDefault <span style="color:#0000ff;">Then</span>
                    MascaraSalidaDecimal = ""
                <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
            <span style="color:#0000ff;">ElseIf</span> [<span style="color:#0000ff;">String</span>].IsNullOrEmpty(_mascaraSalidaDecimal) <span style="color:#0000ff;">Then</span>
                MascaraSalidaDecimal = MascaraSalidaDecimalDefault
                'Si no hay máscara dejo la <span style="color:#0000ff;">default</span>
            <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Set</span>
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Property</span>

    ''' &lt;summary&gt;
    ''' Indica si de debe cambiar "<span style="color:#8b0000;">uno</span>" por "<span style="color:#8b0000;">un</span>" en las unidades.
    ''' &lt;/summary&gt;
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Property</span> ApocoparUnoParteEntera() <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>
        <span style="color:#0000ff;">Get</span>
            <span style="color:#0000ff;">Return</span> _apocoparUnoParteEntera
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Get</span>
        <span style="color:#0000ff;">Set</span>(<span style="color:#0000ff;">ByVal</span> value <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>)
            _apocoparUnoParteEntera = value
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Set</span>
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Property</span>

    ''' &lt;summary&gt;
    ''' Determina si se debe apococopar el "<span style="color:#8b0000;">uno</span>" en la parte <span style="color:#0000ff;">decimal</span>
    ''' &lt;/summary&gt;
    ''' &lt;remarks&gt;El valor de esta propiedad cambia al setear ConvertirDecimales&lt;/remarks&gt;
    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Property</span> ApocoparUnoParteDecimal() <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>
        <span style="color:#0000ff;">Get</span>
            <span style="color:#0000ff;">Return</span> _apocoparUnoParteDecimal
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Get</span>
        <span style="color:#0000ff;">Set</span>(<span style="color:#0000ff;">ByVal</span> value <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>)
            _apocoparUnoParteDecimal = value
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Set</span>
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Property</span>

#<span style="color:#0000ff;">End</span> Region

#Region "<span style="color:#8b0000;">Constructores</span>"

    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Sub</span> <span style="color:#0000ff;">New</span>()
        MascaraSalidaDecimal = MascaraSalidaDecimalDefault
        SeparadorDecimalSalida = SeparadorDecimalSalidaDefault
        LetraCapital = LetraCapitalDefault
        ConvertirDecimales = _convertirDecimales
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Sub</span>

    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Sub</span> <span style="color:#0000ff;">New</span>(<span style="color:#0000ff;">ByVal</span> ConvertirDecimales <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>, <span style="color:#0000ff;">ByVal</span> MascaraSalidaDecimal <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>, <span style="color:#0000ff;">ByVal</span> SeparadorDecimalSalida <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>, <span style="color:#0000ff;">ByVal</span> LetraCapital <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>)
        <span style="color:#0000ff;">If</span> <span style="color:#0000ff;">Not</span> [<span style="color:#0000ff;">String</span>].IsNullOrEmpty(MascaraSalidaDecimal) <span style="color:#0000ff;">Then</span>
            <span style="color:#0000ff;">Me</span>.MascaraSalidaDecimal = MascaraSalidaDecimal
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
        <span style="color:#0000ff;">If</span> <span style="color:#0000ff;">Not</span> [<span style="color:#0000ff;">String</span>].IsNullOrEmpty(SeparadorDecimalSalida) <span style="color:#0000ff;">Then</span>
            _separadorDecimalSalida = SeparadorDecimalSalida
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
        _letraCapital = LetraCapital
        _convertirDecimales = ConvertirDecimales
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Sub</span>

#<span style="color:#0000ff;">End</span> Region

#Region "<span style="color:#8b0000;">Conversores de instancia</span>"

    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Function</span> ToCustomCardinal(<span style="color:#0000ff;">ByVal</span> Numero <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Double</span>) <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>
        <span style="color:#0000ff;">Return</span> Convertir(Convert.ToDecimal(Numero), _decimales, _separadorDecimalSalida, _mascaraSalidaDecimalInterna, _esMascaraNumerica, _letraCapital, _
        _convertirDecimales, _apocoparUnoParteEntera, _apocoparUnoParteDecimal)
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Function</span>

    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Function</span> ToCustomCardinal(<span style="color:#0000ff;">ByVal</span> Numero <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>) <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>
        <span style="color:#0000ff;">Dim</span> dNumero <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Double</span>
        <span style="color:#0000ff;">If</span> [<span style="color:#0000ff;">Double</span>].TryParse(Numero, NumberStyles.Float, _cultureInfo, dNumero) <span style="color:#0000ff;">Then</span>
            <span style="color:#0000ff;">Return</span> ToCustomCardinal(dNumero)
        <span style="color:#0000ff;">Else</span>
            <span style="color:#0000ff;">Throw</span> <span style="color:#0000ff;">New</span> ArgumentException("<span style="color:#8b0000;">'</span>" + Numero + "<span style="color:#8b0000;">' no es un número válido.</span>")
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Function</span>

    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Function</span> ToCustomCardinal(<span style="color:#0000ff;">ByVal</span> Numero <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Decimal</span>) <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>
        <span style="color:#0000ff;">Return</span> ToCardinal(Numero)
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Function</span>

    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Function</span> ToCustomCardinal(<span style="color:#0000ff;">ByVal</span> Numero <span style="color:#0000ff;">As</span> Int32) <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>
        <span style="color:#0000ff;">Return</span> Convertir(Convert.ToDecimal(Numero), 0, _separadorDecimalSalida, _mascaraSalidaDecimalInterna, _esMascaraNumerica, _letraCapital, _
        _convertirDecimales, _apocoparUnoParteEntera, <span style="color:#0000ff;">False</span>)
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Function</span>

#<span style="color:#0000ff;">End</span> Region

#Region "<span style="color:#8b0000;">Conversores estáticos</span>"

    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Shared</span> <span style="color:#0000ff;">Function</span> ToCardinal(<span style="color:#0000ff;">ByVal</span> Numero <span style="color:#0000ff;">As</span> Int32) <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>
        <span style="color:#0000ff;">Return</span> Convertir(Convert.ToDecimal(Numero), 0, <span style="color:#0000ff;">Nothing</span>, <span style="color:#0000ff;">Nothing</span>, <span style="color:#0000ff;">True</span>, LetraCapitalDefault, _
        ConvertirDecimalesDefault, ApocoparUnoParteEnteraDefault, ApocoparUnoParteDecimalDefault)
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Function</span>

    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Shared</span> <span style="color:#0000ff;">Function</span> ToCardinal(<span style="color:#0000ff;">ByVal</span> Numero <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Double</span>) <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>
        <span style="color:#0000ff;">Return</span> Convertir(Convert.ToDecimal(Numero), DecimalesDefault, SeparadorDecimalSalidaDefault, MascaraSalidaDecimalDefault, <span style="color:#0000ff;">True</span>, LetraCapitalDefault, _
        ConvertirDecimalesDefault, ApocoparUnoParteEnteraDefault, ApocoparUnoParteDecimalDefault)
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Function</span>

    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Shared</span> <span style="color:#0000ff;">Function</span> ToCardinal(<span style="color:#0000ff;">ByVal</span> Numero <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>, <span style="color:#0000ff;">ByVal</span> ReferenciaCultural <span style="color:#0000ff;">As</span> CultureInfo) <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>
        <span style="color:#0000ff;">Dim</span> dNumero <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Double</span>
        <span style="color:#0000ff;">If</span> [<span style="color:#0000ff;">Double</span>].TryParse(Numero, NumberStyles.Float, ReferenciaCultural, dNumero) <span style="color:#0000ff;">Then</span>
            <span style="color:#0000ff;">Return</span> ToCardinal(dNumero)
        <span style="color:#0000ff;">Else</span>
            <span style="color:#0000ff;">Throw</span> <span style="color:#0000ff;">New</span> ArgumentException("<span style="color:#8b0000;">'</span>" + Numero + "<span style="color:#8b0000;">' no es un número válido.</span>")
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Function</span>

    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Shared</span> <span style="color:#0000ff;">Function</span> ToCardinal(<span style="color:#0000ff;">ByVal</span> Numero <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>) <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>
        <span style="color:#0000ff;">Return</span> Numalet.ToCardinal(Numero, CultureInfo.CurrentCulture)
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Function</span>

    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Shared</span> <span style="color:#0000ff;">Function</span> ToCardinal(<span style="color:#0000ff;">ByVal</span> Numero <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Decimal</span>) <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>
        <span style="color:#0000ff;">Return</span> ToCardinal(Convert.ToDouble(Numero))
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Function</span>

#<span style="color:#0000ff;">End</span> Region

    <span style="color:#0000ff;">Private</span> <span style="color:#0000ff;">Shared</span> <span style="color:#0000ff;">Function</span> Convertir(<span style="color:#0000ff;">ByVal</span> Numero <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Decimal</span>, <span style="color:#0000ff;">ByVal</span> Decimales <span style="color:#0000ff;">As</span> Int32, <span style="color:#0000ff;">ByVal</span> SeparadorDecimalSalida <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>, <span style="color:#0000ff;">ByVal</span> MascaraSalidaDecimal <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>, <span style="color:#0000ff;">ByVal</span> EsMascaraNumerica <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>, <span style="color:#0000ff;">ByVal</span> LetraCapital <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>, _
    <span style="color:#0000ff;">ByVal</span> ConvertirDecimales <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>, <span style="color:#0000ff;">ByVal</span> ApocoparUnoParteEntera <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>, <span style="color:#0000ff;">ByVal</span> ApocoparUnoParteDecimal <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>) <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>
        <span style="color:#0000ff;">Dim</span> Num <span style="color:#0000ff;">As</span> Int64
        <span style="color:#0000ff;">Dim</span> terna <span style="color:#0000ff;">As</span> Int32, centenaTerna <span style="color:#0000ff;">As</span> Int32, decenaTerna <span style="color:#0000ff;">As</span> Int32, unidadTerna <span style="color:#0000ff;">As</span> Int32, iTerna <span style="color:#0000ff;">As</span> Int32
        <span style="color:#0000ff;">Dim</span> cadTerna <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>
        <span style="color:#0000ff;">Dim</span> Resultado <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">New</span> StringBuilder()

        Num = Math.Floor(Math.Abs(Numero))

        <span style="color:#0000ff;">If</span> Num &gt;= 1000000000001 <span style="color:#0000ff;">OrElse</span> Num &lt; 0 <span style="color:#0000ff;">Then</span>
            <span style="color:#0000ff;">Throw</span> <span style="color:#0000ff;">New</span> ArgumentException("<span style="color:#8b0000;">El número '</span>" + Numero.ToString() + "<span style="color:#8b0000;">' excedió los límites del conversor: [0;1.000.000.000.001]</span>")
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
        <span style="color:#0000ff;">If</span> Num = 0 <span style="color:#0000ff;">Then</span>
            Resultado.Append("<span style="color:#8b0000;"> cero</span>")
        <span style="color:#0000ff;">Else</span>
            iTerna = 0

            <span style="color:#0000ff;">Do</span> Until Num = 0

                iTerna += 1
                cadTerna = <span style="color:#0000ff;">String</span>.Empty
                terna = Num <span style="color:#0000ff;">Mod</span> 1000

                centenaTerna = Int(terna / 100)
                decenaTerna = terna - centenaTerna * 100 'Decena junto con la unidad
                unidadTerna = (decenaTerna - Math.Floor(decenaTerna / 10) * 10)

                <span style="color:#0000ff;">Select</span> <span style="color:#0000ff;">Case</span> decenaTerna
                    <span style="color:#0000ff;">Case</span> 1 <span style="color:#0000ff;">To</span> 9
                        cadTerna = _matriz(UNI, unidadTerna) + cadTerna
                    <span style="color:#0000ff;">Case</span> 10 <span style="color:#0000ff;">To</span> 19
                        cadTerna = cadTerna + _matriz(DIECI, unidadTerna)
                    <span style="color:#0000ff;">Case</span> 20
                        cadTerna = cadTerna + "<span style="color:#8b0000;"> veinte</span>"
                    <span style="color:#0000ff;">Case</span> 21 <span style="color:#0000ff;">To</span> 29
                        cadTerna = "<span style="color:#8b0000;"> veinti</span>" + _matriz(UNI, unidadTerna).Substring(1)
                    <span style="color:#0000ff;">Case</span> 30 <span style="color:#0000ff;">To</span> 99
                        <span style="color:#0000ff;">If</span> unidadTerna &lt;&gt; 0 <span style="color:#0000ff;">Then</span>
                            cadTerna = _matriz(DECENA, Int(decenaTerna / 10)) + "<span style="color:#8b0000;"> y</span>" + _matriz(UNI, unidadTerna) + cadTerna
                        <span style="color:#0000ff;">Else</span>
                            cadTerna += _matriz(DECENA, Int(decenaTerna / 10))
                        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
                <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Select</span>

                <span style="color:#0000ff;">Select</span> <span style="color:#0000ff;">Case</span> centenaTerna
                    <span style="color:#0000ff;">Case</span> 1
                        <span style="color:#0000ff;">If</span> decenaTerna &gt; 0 <span style="color:#0000ff;">Then</span>
                            cadTerna = "<span style="color:#8b0000;"> ciento</span>" + cadTerna
                        <span style="color:#0000ff;">Else</span>
                            cadTerna = "<span style="color:#8b0000;"> cien</span>" + cadTerna
                        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
                        <span style="color:#0000ff;">Exit</span> <span style="color:#0000ff;">Select</span>
                    <span style="color:#0000ff;">Case</span> 5, 7, 9
                        cadTerna = _matriz(CENTENA, Int(terna / 100)) + cadTerna
                        <span style="color:#0000ff;">Exit</span> <span style="color:#0000ff;">Select</span>
                    <span style="color:#0000ff;">Case</span> <span style="color:#0000ff;">Else</span>
                        <span style="color:#0000ff;">If</span> Int(terna / 100) &gt; 1 <span style="color:#0000ff;">Then</span>
                            cadTerna = _matriz(UNI, Int(terna / 100)) + "<span style="color:#8b0000;">cientos</span>" + cadTerna
                        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
                        <span style="color:#0000ff;">Exit</span> <span style="color:#0000ff;">Select</span>
                <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Select</span>
                'Reemplazo el 'uno' por 'un' si no es en las únidades o si se solicító apocopar
                <span style="color:#0000ff;">If</span> (iTerna &gt; 1 <span style="color:#0000ff;">OrElse</span> ApocoparUnoParteEntera) <span style="color:#0000ff;">AndAlso</span> decenaTerna = 21 <span style="color:#0000ff;">Then</span>
                    cadTerna = cadTerna.Replace("<span style="color:#8b0000;">veintiuno</span>", "<span style="color:#8b0000;">veintiún</span>")
                <span style="color:#0000ff;">ElseIf</span> (iTerna &gt; 1 <span style="color:#0000ff;">OrElse</span> ApocoparUnoParteEntera) <span style="color:#0000ff;">AndAlso</span> unidadTerna = 1 <span style="color:#0000ff;">AndAlso</span> decenaTerna &lt;&gt; 11 <span style="color:#0000ff;">Then</span>
                    cadTerna = cadTerna.Substring(0, cadTerna.Length - 1)
                    'Acentúo 'veintidós', 'veintitrés' y 'veintiséis'
                <span style="color:#0000ff;">ElseIf</span> decenaTerna = 22 <span style="color:#0000ff;">Then</span>
                    cadTerna = cadTerna.Replace("<span style="color:#8b0000;">veintidos</span>", "<span style="color:#8b0000;">veintidós</span>")
                <span style="color:#0000ff;">ElseIf</span> decenaTerna = 23 <span style="color:#0000ff;">Then</span>
                    cadTerna = cadTerna.Replace("<span style="color:#8b0000;">veintitres</span>", "<span style="color:#8b0000;">veintitrés</span>")
                <span style="color:#0000ff;">ElseIf</span> decenaTerna = 26 <span style="color:#0000ff;">Then</span>
                    cadTerna = cadTerna.Replace("<span style="color:#8b0000;">veintiseis</span>", "<span style="color:#8b0000;">veintiséis</span>")
                <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>

                'Completo miles y millones
                <span style="color:#0000ff;">Select</span> <span style="color:#0000ff;">Case</span> iTerna
                    <span style="color:#0000ff;">Case</span> 3
                        <span style="color:#0000ff;">If</span> Numero &lt; 2000000 <span style="color:#0000ff;">Then</span>
                            cadTerna += "<span style="color:#8b0000;"> millón</span>"
                        <span style="color:#0000ff;">Else</span>
                            cadTerna += "<span style="color:#8b0000;"> millones</span>"
                        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
                    <span style="color:#0000ff;">Case</span> 2, 4
                        <span style="color:#0000ff;">If</span> terna &gt; 0 <span style="color:#0000ff;">Then</span> cadTerna += "<span style="color:#8b0000;"> mil</span>"
                <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Select</span>
                Resultado.Insert(0, cadTerna)
                Num = Int(Num / 1000)
            <span style="color:#0000ff;">Loop</span>
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>

        'Se agregan los decimales si corresponde
        <span style="color:#0000ff;">If</span> Decimales &gt; 0 <span style="color:#0000ff;">Then</span>
            Resultado.Append("<span style="color:#8b0000;"> </span>" + SeparadorDecimalSalida + "<span style="color:#8b0000;"> </span>")
            <span style="color:#0000ff;">Dim</span> EnteroDecimal <span style="color:#0000ff;">As</span> Int32 = Int(Math.Round((Numero - Int(Numero)) * Math.Pow(10, Decimales)))
            <span style="color:#0000ff;">If</span> ConvertirDecimales <span style="color:#0000ff;">Then</span>
                <span style="color:#0000ff;">Dim</span> esMascaraDecimalDefault <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span> = MascaraSalidaDecimal = MascaraSalidaDecimalDefault
                Resultado.Append(Convertir(Convert.ToDecimal(EnteroDecimal), 0, <span style="color:#0000ff;">Nothing</span>, <span style="color:#0000ff;">Nothing</span>, EsMascaraNumerica, <span style="color:#0000ff;">False</span>, _
                <span style="color:#0000ff;">False</span>, (ApocoparUnoParteDecimal <span style="color:#0000ff;">AndAlso</span> <span style="color:#0000ff;">Not</span> EsMascaraNumerica), <span style="color:#0000ff;">False</span>) + "<span style="color:#8b0000;"> </span>" + (IIf(EsMascaraNumerica, "", MascaraSalidaDecimal)))
            <span style="color:#0000ff;">ElseIf</span> EsMascaraNumerica <span style="color:#0000ff;">Then</span>
                Resultado.Append(EnteroDecimal.ToString(MascaraSalidaDecimal))
            <span style="color:#0000ff;">Else</span>
                Resultado.Append(EnteroDecimal.ToString() + "<span style="color:#8b0000;"> </span>" + MascaraSalidaDecimal)
            <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
        'Se pone la primer letra en mayúscula si corresponde y se retorna el resultado
        <span style="color:#0000ff;">If</span> LetraCapital <span style="color:#0000ff;">Then</span>
            <span style="color:#0000ff;">Return</span> Resultado(1).ToString().ToUpper() + Resultado.ToString(2, Resultado.Length - 2)
        <span style="color:#0000ff;">Else</span>
            <span style="color:#0000ff;">Return</span> Resultado.ToString().Substring(1)
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Function</span>

<span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Class</span></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://varionet.wordpress.com/2007/11/29/convertir-numeros-a-letras/feed/</wfw:commentRss>
			<slash:comments>130</slash:comments>
		
		
		
		<media:content url="https://0.gravatar.com/avatar/6ac4a1d95580a307da123b4c5a56eb7e711ff8e6f9fc72c35c79ccd4a9f0ebd5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Alejandro Hernández</media:title>
		</media:content>
	</item>
		<item>
		<title>Chequear todos los checkbox de un gridview con javascript</title>
		<link>https://varionet.wordpress.com/2007/11/03/chequear-todos-los-checkbox-de-un-gridview-con-javascript/</link>
					<comments>https://varionet.wordpress.com/2007/11/03/chequear-todos-los-checkbox-de-un-gridview-con-javascript/#comments</comments>
		
		<dc:creator><![CDATA[Alejandro Hernández]]></dc:creator>
		<pubDate>Sat, 03 Nov 2007 05:50:04 +0000</pubDate>
				<category><![CDATA[asp.net]]></category>
		<category><![CDATA[checkbox]]></category>
		<category><![CDATA[gridview]]></category>
		<category><![CDATA[javascript]]></category>
		<guid isPermaLink="false">http://varionet.wordpress.com/2007/11/03/chequear-todos-los-checkbox-de-un-gridview-con-javascript/</guid>

					<description><![CDATA[NOTA 16/06/2009: He publicado como hacer esta misma tarea con jQuery en este artículo, recomiendo utilizar esa alternativa por los motivos que comento en dicho artículo. Muchas veces queremos chequear o deschequear todos los checkbox de un gridview de una sola vez, puede ser cuando el usuario realiza determinada acción en otro control, por ejemplo &#8230; <a href="https://varionet.wordpress.com/2007/11/03/chequear-todos-los-checkbox-de-un-gridview-con-javascript/" class="more-link">Continuar leyendo<span class="screen-reader-text"> "Chequear todos los checkbox de un gridview con&#160;javascript"</span></a>]]></description>
										<content:encoded><![CDATA[<p><em><strong>NOTA 16/06/2009:</strong></em> <em>He publicado como hacer esta misma tarea con jQuery <a href="https://varionet.wordpress.com/2009/06/17/como-checkear-todos-los-checkbox-de-una-columna-con-jquery">en este artículo</a>, recomiendo utilizar esa alternativa por los motivos que comento en dicho artículo.</em></p>
<p>Muchas veces queremos chequear o deschequear todos los checkbox de un gridview de una sola vez, puede ser cuando el usuario realiza determinada acción en otro control, por ejemplo un botón para «seleccionar todo», o que cuando se activa un CheckBox en la cabecera de la columna,  cambie el estado de todos los checks al de la cabecera.</p>
<p>Si bien esto se puede hacer con código de servidor, normalmente no queremos que se realice un postback solo para esto, la solución es javascript.</p>
<p><span style="color:#808080;"><em>(Nuevamente, si solo te interesa un código js que solucione el problema que acabo de describir, te recomiendo ir directamente a copiar los dos fragmentos de javascript al final del post.)</em></span></p>
<p>En su momento utilicé el código que Scott Mitchell publicó en <a title="Art�culo de Scott Mitchell sobre el tema de este post" href="http://aspnet.4guysfromrolla.com/articles/052406-1.aspx">este</a> artículo, pero esta solución, si bien funciona y no genera un postback, requiere código de  servidor, ya que en la creación de la página se registra mediante el método <a title="RegisterArrayDeclaration en MSDN" href="http://msdn2.microsoft.com/en-us/library/system.web.ui.clientscriptmanager.registerarraydeclaration.aspx">RegisterArrayDeclaration</a> un array con los ids que tendrá cada checkbox en el cliente, lo que nos obliga a hacerlo en cada postback o a recargar el estado, ya sea ViewState o Session.</p>
<p>Buscando otra alternativa encontré <a title="Art�culo de Mohammad Azam sobre el tema de este post" href="http://www.codeproject.com/aspnet/SelChkboxesDataGridView.asp">este</a> otro artículo de Mohammad Azam, el autor de <a title="Sitio exclisivamente sobre GridView" href="http://www.thedotnetguy.com/">GridViewGuy</a>. Este si es un ejemplo totalmente sobre javascript, pero tiene un gran defecto: opera sobre <span style="text-decoration:underline;">todos</span> los checkbox de la página, sin importar si están dentro de la grilla o no, ni hablar si tenemos dos grillas.</p>
<p>En este punto decidí escribir mi propia solución, o sea una totalmente en el cliente y que permita operar sobre los checkbox de una grilla en particular y, por que no, sobre una columna en particular, de manera que podamos tener más de una columna con checkbox y cambiar el estado de los checks de una de ellas sin afectar la otra.</p>
<p>Un poco de background que pueden saltarse si les parece:</p>
<p><strong>Como incluir CheckBox en una columna de un gridview</strong></p>
<p>Antes que nada hay que generar una columna con los checkbox. Hay dos maneras de hacer esto como cuenta Scott Mitchell en el artículo nombrado, yo utilizo también un TemplateField (no encontré todavía utilidad para los CheckBoxField), de modo que colocando un checkbox en el ItemTemplate genero uno en cada celda del TemplateField:</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,'Courier New',courier,monospace;background-color:#f4f4f4;margin:0;padding:5px;"><span style="color:#0000ff;">&lt;</span><span style="color:#C800000;">asp</span>:<span style="color:#800000;">TemplateField</span> <span style="color:#ff0000;">HeaderText</span>=<span style="color:#0000ff;">"chk"</span><span style="color:#0000ff;">&gt;</span>
   <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">ItemTemplate</span><span style="color:#0000ff;">&gt;</span>
      <span style="color:#0000ff;">&lt;</span><span style="color:#C800000;">asp</span>:<span style="color:#800000;">CheckBox</span> <span style="color:#ff0000;">ID</span>=<span style="color:#0000ff;">"chkColumna1"</span> <span style="color:#ff0000;">runat</span>=<span style="color:#0000ff;">"server"</span> <span style="color:#0000ff;">/&gt;</span>
   <span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">ItemTemplate</span><span style="color:#0000ff;">&gt;</span>
<span style="color:#0000ff;">&lt;/</span><span style="color:#C800000;">asp</span>:<span style="color:#800000;">TemplateField</span><span style="color:#0000ff;">&gt;</span></pre>
<p>Visualmente (en VisualStudio), agregamos un <em>TemplateField </em>al gridview y seleccionamos <em>EditTemplate </em>del menú contextual. Luego arrastramos un CheckBox a la zona <em>ItemTemplate</em>. Para finalizar: <em>End Template Editing</em>, en el menú contextual.</p>
<p><strong>Como chequear todos CheckBox de un GridView</strong></p>
<p>Esta rutina javascript cambia el estado de todos los checkbox de una grilla sin importar su ubicación:</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,'Courier New',courier,monospace;background-color:#f4f4f4;margin:0;padding:5px;"><span style="color:#0000ff;">function</span> ChangeAllChecks(gridViewName,newState)
{
   <span style="color:#0000ff;">var</span> tabla = <span style="color:#0000ff;">document</span>.getElementById(gridViewName);
   celdas = tabla.cells;
   <span style="color:#0000ff;">for</span>(i=0;i&lt;celdas.<span style="color:#0000ff;">length</span>-1;i++)
   {
   <span style="color:#0000ff;">if</span> (celdas[i].firstChild.type=="<span style="color:#8b0000;">checkbox</span>"
   &amp;&amp; celdas[i].firstChild.checked != newState)
      {
         celdas[i].firstChild.click();
      }
   }
}</pre>
<p>Para llamarla utilizamos <span style="text-decoration:underline;"><em>ChangeAllChecks(&#8216;GridView1&#8217;,true);</em></span> o false si es el caso</p>
<p><strong>Como chequear una columna específica</strong></p>
<p>Puede ocurrir que en un gridview tengamos más de un TemplateField con CheckBox, y que solo queramos chequear o deschequear una sola columna, para ello hice un nuevo método que toma como paramétro el índice de la columna (empezando por 0). (Actualizado 29/09/2008 según respuesta al comentario de Martín)</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,'Courier New',courier,monospace;background-color:#f4f4f4;margin:0;padding:5px;">function ChangeChecksByColumn(gridViewName, newState, columnIndex){
    <span style="color:#0000ff;">var</span> tabla = <span style="color:#0000ff;">document</span>.getElementById(gridViewName);
    <span style="color:#0000ff;">var</span> columnas = tabla.cells.<span style="color:#0000ff;">length</span> / tabla.rows.<span style="color:#0000ff;">length</span>;
    celdas = tabla.cells;
    <span style="color:#0000ff;">for</span> (i = columnas + columnIndex; i &lt; celdas.<span style="color:#0000ff;">length</span>; i += columnas){
        <span style="color:#0000ff;">if</span> (celdas[i].firstChild.type == "<span style="color:#8b0000;">checkbox</span>"
               &amp;&amp; celdas[i].firstChild.checked != newState
            <span style="color:#008000;">/* &amp;&amp; agregar aquí otras condiciones */</span>){
            celdas[i].firstChild.click();
        }
    }
}</pre>
<p><strong>Como chequear a partir de un CheckBox en la cabecera</strong></p>
<p>El código anterior no es muy útil porque nos solicita el estado (true=checked/false=unchequed) en el que queremos dejar los checkbox, la solución es agregar un checkbox en la cabecera de la TemplateColumn:</p>
<p>y agregamos una rutina que permita identificar el estado del mismo y la columna en que se encuentra, luego llamamos al método anterior: <em>ChangeChecksByColumn:</em></p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,'Courier New',courier,monospace;background-color:#f4f4f4;margin:0;padding:5px;"><span style="color:#0000ff;">function</span> CopyCheckStateByColumn(HeaderCheckBox, gridViewName)
{
    <span style="color:#0000ff;">var</span> columnIndex = HeaderCheckBox.parentElement.cellIndex;
    <span style="color:#0000ff;">var</span> newState = HeaderCheckBox.checked;
    ChangeChecksByColumn(gridViewName, newState, columnIndex);
}</pre>
<p>Para terminar, completamos el evento <em>onclick </em>del checkbox con una llamada a <em>CopyCheckStateByColumn </em>pasando como parámetro el propio checkbox y el nombre del gridview:<br />
(lo que sigue cambiado el 08/11 según la respuesta al comentario de Roger)</p>
<pre style="border:1px solid gainsboro;overflow:auto;background-image:none;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,'Courier New',courier,monospace;background-color:#f4f4f4;margin:0;padding:5px;"><span style="color:#0000ff;">&lt;</span><span style="color:#C800000;">asp</span>:<span style="color:#800000;">TemplateField</span> <span style="color:#ff0000;">HeaderText</span>=<span style="color:#0000ff;">"chk"</span><span style="color:#0000ff;">&gt;</span>
<span style="color:#0000ff;">&lt;</span><span style="color:#800000;">HeaderTemplate</span><span style="color:#0000ff;">&gt;</span>
    <span style="color:#0000ff;">&lt;</span><span style="color:#C800000;">asp</span>:<span style="color:#800000;">CheckBox</span> <span style="color:#ff0000;">ID</span>=<span style="color:#0000ff;">"chkHeader"</span> <span style="color:#ff0000;">runat</span>=<span style="color:#0000ff;">"server"</span> <span style="color:#ff0000;">onclick</span>=<span style="color:#0000ff;">"javascript:CopyCheckStateByColumn(this,this.offsetParent.offsetParent.id);"</span><span style="color:#0000ff;">/&gt;</span>
<span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">HeaderTemplate</span><span style="color:#0000ff;">&gt;</span>
<span style="color:#0000ff;">&lt;</span><span style="color:#800000;">ItemTemplate</span><span style="color:#0000ff;">&gt;</span>
    <span style="color:#0000ff;">&lt;</span><span style="color:#C800000;">asp</span>:<span style="color:#800000;">CheckBox</span> <span style="color:#ff0000;">ID</span>=<span style="color:#0000ff;">"chkTest"</span> <span style="color:#ff0000;">runat</span>=<span style="color:#0000ff;">"server"</span> <span style="color:#0000ff;">/&gt;</span>
<span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">ItemTemplate</span><span style="color:#0000ff;">&gt;</span>
<span style="color:#0000ff;">&lt;/</span><span style="color:#C800000;">asp</span>:<span style="color:#800000;">TemplateField</span><span style="color:#0000ff;">&gt;</span></pre>
<p>Una precaución: Tener en cuenta que el código javascript consulta si el contenido es un CheckBox mediante la propiedad <em>firstChild </em>para cada objeto de la colección <em>cells </em>del objeto <em>table</em>, o sea: el contenido de cada TD.  Si ponemos otro objeto en el ItemTemplate junto con el CheckBox, podemos tener problemas si nos descuidamos.</p>
<p>Un tip: Para <a title="Agregar código cliente en WebControls en la MSDN" href="http://msdn2.microsoft.com/es-es/library/7ytf5t7k(VS.80).aspx">llamar métodos javascript en el evento click de un control <em>Button</em></a>, se debe utilizar el evento <em>OnClientClick </em>en vez de <em>onclick.</em></p>
<p>Una desventaja: No funciona en Firefox.</p>
<p>Saludos</p>
]]></content:encoded>
					
					<wfw:commentRss>https://varionet.wordpress.com/2007/11/03/chequear-todos-los-checkbox-de-un-gridview-con-javascript/feed/</wfw:commentRss>
			<slash:comments>37</slash:comments>
		
		
		
		<media:content url="https://0.gravatar.com/avatar/6ac4a1d95580a307da123b4c5a56eb7e711ff8e6f9fc72c35c79ccd4a9f0ebd5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Alejandro Hernández</media:title>
		</media:content>
	</item>
		<item>
		<title>Envío de mail con framework 2.0, mi clase con autenticación</title>
		<link>https://varionet.wordpress.com/2007/10/30/envio-de-mail-con-framework-20-mi-clase-con-autenticacion/</link>
					<comments>https://varionet.wordpress.com/2007/10/30/envio-de-mail-con-framework-20-mi-clase-con-autenticacion/#comments</comments>
		
		<dc:creator><![CDATA[Alejandro Hernández]]></dc:creator>
		<pubDate>Tue, 30 Oct 2007 05:01:31 +0000</pubDate>
				<category><![CDATA[System.Net.Mail]]></category>
		<category><![CDATA[mail]]></category>
		<category><![CDATA[smtp]]></category>
		<category><![CDATA[ssl]]></category>
		<category><![CDATA[x509]]></category>
		<guid isPermaLink="false">http://varionet.wordpress.com/2007/10/30/envio-de-mail-con-framework-20-mi-clase-con-autenticacion/</guid>

					<description><![CDATA[A todos nos llega en algún momento la necesidad de que nuestro sistema envíe mails. Es ahí donde donde toda nuestra pasión por la programación se reduce a google y «ojala que alguién lo tenga resuelto». No es difícil encontrar como enviar mails con .Net, pero luego nos encontramos con diferentes requerimientos de formato, seguridad, &#8230; <a href="https://varionet.wordpress.com/2007/10/30/envio-de-mail-con-framework-20-mi-clase-con-autenticacion/" class="more-link">Continuar leyendo<span class="screen-reader-text"> "Envío de mail con framework 2.0, mi clase con&#160;autenticación"</span></a>]]></description>
										<content:encoded><![CDATA[<p>A todos nos llega en algún momento la necesidad de que nuestro sistema envíe mails. Es ahí donde donde toda nuestra pasión por la programación se reduce a google y «ojala que alguién lo tenga resuelto».</p>
<p>No es difícil encontrar como enviar mails con .Net, pero luego nos encontramos con diferentes requerimientos de formato, seguridad, etc. y como no queremos interiorizarnos en como MS implementó el aburrido protocolo SMTP en el framework, recurrimos nuevamente a google para aburrirnos un rato más. Bueno, he aquí el producto de mi tiempo desperdiciado y algunos comentarios sobre el tema. Si solamente necesitás una clase para enviar mails sin mucha vuelta te recomiendo ir directamente al código y aplicar un «copy-paste», ya que el código es bastante auto-explicativo y hay un solo método para utilizar.</p>
<p>El namespace utilizado es System.Net.Mail (solo framework 2.0, antes era System.Web.Mail)</p>
<p>Basicamente, lo que hacemos es:</p>
<ul>
<li>Crear un objeto MailMessage</li>
<li>Crear y asignar a la propiedad «From» del objeto MailMessage un objeto MailAddress con la dirección de salida</li>
<li>Crear y asignar a la propiedad «To» del objeto MailMessage una colección de objetos MailAddress conteniendo las direcciones de los destinatarios</li>
<li>Asignar un texto a las propiedades «Subject» y Body» del objeto MailMessage</li>
<li>Crear un objeto SmtpClient, definirle la dirección del host y el puerto,  e invocar a su método Send pasándole como parámetro nuestro MailMessage</li>
</ul>
<p>Esa es la manera de enviar un mail simple, con un body de texto plano, sin attachments y por el puerto 25 (default de SMTP), sin embargo, el único método público de mi clase (Enviar) tiene una serie de parámetros opcionales (serán sobrecargas para quien lo quiera pasar a C#) que permiten utilizar otras características:</p>
<p><em>MailPort</em> permite especificar la utilización de otro puerto para conectarse al host SMTP (por ejemplo 443 para utilizar ssl), altarando la propiedad Port del SmtpClient .</p>
<p><em>MailIsBodyHtml</em> permite especificar si el texto enviado es Html o texto plano (propiedad IsBodyHtml del objeto MailMessage).</p>
<p><em>EnableSSL</em> determina si se utiliza (1), o no (0) este protocolo en la conexión con el host (propiedad EnableSsl de SmtpClient).</p>
<p><em>SSLuser</em> y <em>SSLpass</em> permite enviar al host un user y password para establecer la conexión (propiedad Credentials de SmtpClient).</p>
<p>En el código no manejo attachments, pero para quien deba hacerlo, estos se incluyen por medio instancias de la clase <a href="http://msdn2.microsoft.com/es-es/library/system.net.mail.attachment(VS.80).aspx" title="System.Net.Attachment en MSDN">System.Net.Attachment</a>, que permite especificar un path o un stream como origen, el tipo de contenido (su mimetype) y algunas propiedades más. Estos objetos se adjuntan mediante el método Add de la colección Attachments del objeto MailMessage. Cuando pueda probar la clase con archivos adjuntos en un ambiente real, actualizo el código comentando si hubo algún issue al respecto.</p>
<p>Respecto al body en formato html, se puede comentar, aunque hablamos de SMTP y no de .Net, que si incluimos imágenes, nuestro html puede hacer referencia a imágenes hosteadas en algún server o a imágenes adjuntas, en cuyo caso se incluye solo el nombre de la imágen en el tag<em> img</em>.</p>
<p><strong>Autenticación en un host con ssl </strong></p>
<p>Donde hay muchas veces un gran problema, es en el uso de SSL para conectarse al host SMTP. Ocurre que para establecer el canal SSL el host utiliza un certificado, nuestra máquina cliente intentará validar ese certificado contra las autoridades certificantes registradas un su propio repositorio, y si no lo consigue arrojará una excepción con el fatídico texto «<em>The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel</em>»  y dentro de ella otra con el más aclaratorio: «<em>The remote certificate is invalid according to the validation procedure</em>«. Esto generalmente ocurre porque el certificado no está emitido por una autoridad (CA) reconocida en nuestra máquina cliente, entonces podemos:</p>
<ul>
<li>Obtener el certificado root de la <a href="http://es.wikipedia.org/wiki/Autoridad_de_certificaci%C3%B3n" title="Autoridad certificante en Wikipedia">CA</a> e instalarlo la máquina donde correrá nuestro sistema para que esta reconozca el certificado del host SMTP (esto no pasa mucho más lejos de un click derecho en el archivo del certificado), normalmente le pediremos el mismo al administrador del host.</li>
<li>Solicitarle al responsable del host que pague un certificado de una CA reconocida, digamos VeriSign, etc. (esto siempre por teléfono o mail, nunca personalmente y si es el caso preparar antes un CV, por si nos quedamos sin cliente por insolentes)</li>
<li>Considerar que lo unico que nos interesa es que nuestro sistema envíe los condenados mails y forzar al framework a realizar una validación personalizada o a aceptar como válido cualquier certificado que el host posea (está última la opción del ejemplo)</li>
</ul>
<p>Para ello (la tercera opción) el framework 2.0 nos expone una propiedad del objeto ServicePointManager, ServerCertificateValidationCallback, que nos permite especificar un delegado a una función que se encargue de validar el certificado a nuestro gusto, por ejemplo, retornando siempre true. Si quisieramos realizar una validación personalizada, como chequear el <a href="http://es.wikipedia.org/wiki/X.509" title="X509 en Wikipedia">DN</a> del certificado, deberíamos hacerlo aquí, ya que nuestro método de validación recibe el certificado en un parámetro, permitiendos acceder a todas sus propiedades.</p>
<p>Es importante destacar que esto último se aplica también a cualquier conexión http vía ssl realizada por el framework, llámese Web Service o HttpWebRequest.</p>
<p>Por último <a href="http://www.systemnetmail.com/" title="Sitio de Dave Wanta sobre System.Net.Mail">aquí</a> un sitio dedicado al namespace System.Net.Mail y, si necesitamos tocar los headers del mensaje, <a href="http://aspnet.4guysfromrolla.com/articles/101707-1.aspx" title="Art�culo de Scott Mitchell sobre env�o de mail con .Net">este</a> artículo de Scott Mitchell (cuando no) desde donde podemos acceder también a otros artículos de su autoría sobre envío de mails con .Net en sus diferente versiones.</p>
<pre style="border-right:gainsboro 1px solid;border-top:gainsboro 1px solid;font-size:8pt;background-image:none;overflow:auto;border-left:gainsboro 1px solid;width:100%;color:black;line-height:12pt;border-bottom:gainsboro 1px solid;font-family:consolas,'Courier New',courier,monospace;height:400px;background-color:#f4f4f4;margin:0;padding:5px;"><span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Class</span> Correo


    <span style="color:#0000ff;">Public</span> <span style="color:#0000ff;">Shared</span> <span style="color:#0000ff;">Sub</span> Enviar(<span style="color:#0000ff;">ByVal</span> MailDestinatarios <span style="color:#0000ff;">As</span> System.Net.Mail.MailAddressCollection, _
    <span style="color:#0000ff;">ByVal</span> MailDireccionOrigen <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>, _
    <span style="color:#0000ff;">ByVal</span> MailNombreOrigen <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>, _
    <span style="color:#0000ff;">ByVal</span> MailSubject <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>, _
    <span style="color:#0000ff;">ByVal</span> MailBody <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>, _
    <span style="color:#0000ff;">ByVal</span> MailHost <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span>, _
    <span style="color:#0000ff;">Optional</span> <span style="color:#0000ff;">ByVal</span> MailPort <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Integer</span> = 25, _
    <span style="color:#0000ff;">Optional</span> <span style="color:#0000ff;">ByVal</span> MailIsBodyHtml <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span> = <span style="color:#0000ff;">True</span>, _
    <span style="color:#0000ff;">Optional</span> <span style="color:#0000ff;">ByVal</span> EnableSSL <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Integer</span> = 0, _
    <span style="color:#0000ff;">Optional</span> <span style="color:#0000ff;">ByVal</span> SSLuser <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span> = <span style="color:#006080;">""</span>, _
    <span style="color:#0000ff;">Optional</span> <span style="color:#0000ff;">ByVal</span> SSLpass <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">String</span> = <span style="color:#006080;">""</span>)

        <span style="color:#008000;">'Se crea el mensaje</span>
        <span style="color:#0000ff;">Dim</span> oMensaje <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">New</span> MailMessage

        <span style="color:#008000;">'Se crea el cliente SMTP</span>
        <span style="color:#0000ff;">Dim</span> oSMTP <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">New</span> SmtpClient()

        <span style="color:#008000;">'Se agregan las direcciones</span>
        oMensaje.From = <span style="color:#0000ff;">New</span> MailAddress(MailDireccionOrigen, MailNombreOrigen)
        <span style="color:#0000ff;">For</span> <span style="color:#0000ff;">Each</span> addr <span style="color:#0000ff;">As</span> MailAddress <span style="color:#0000ff;">In</span> MailDestinatarios
            oMensaje.<span style="color:#0000ff;">To</span>.Add(addr)
        <span style="color:#0000ff;">Next</span>

        oMensaje.Subject = MailSubject
        oMensaje.Body = MailBody
        oMensaje.IsBodyHtml = MailIsBodyHtml
        <span style="color:#008000;">'Seteo que el server notifique solamente en el error de entrega</span>
        oMensaje.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure

        <span style="color:#008000;">'servidor smtp (dirección IP ó nombre de host)</span>
        oSMTP.Host = MailHost
        <span style="color:#008000;">'Puerto a utilizar (25 por defecto)</span>
        oSMTP.Port = MailPort

        <span style="color:#008000;">'Si se solicitó SSL, lo activo</span>
        <span style="color:#0000ff;">If</span> EnableSSL = 1 <span style="color:#0000ff;">Then</span>
            oSMTP.EnableSsl = <span style="color:#0000ff;">True</span>
            <span style="color:#008000;">'Bypass de validación de certificado (para problemas con servidores de SMTP con SSL con certificados que no validan en nuestra máquina)</span>
            ServicePointManager.ServerCertificateValidationCallback = <span style="color:#0000ff;">New</span> RemoteCertificateValidationCallback(<span style="color:#0000ff;">AddressOf</span> ValidarCertificado)
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>
        <span style="color:#008000;">'Cargo las credenciales si hacen falta</span>
        <span style="color:#0000ff;">If</span> <span style="color:#0000ff;">Not</span> <span style="color:#0000ff;">String</span>.IsNullOrEmpty(SSLuser) <span style="color:#0000ff;">Then</span>
            <span style="color:#0000ff;">Dim</span> credenciales <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">New</span> System.Net.NetworkCredential(SSLuser, SSLpass)
            oSMTP.Credentials = credenciales
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">If</span>

        <span style="color:#0000ff;">Try</span>
            oSMTP.Send(oMensaje)
        <span style="color:#0000ff;">Catch</span> ex <span style="color:#0000ff;">As</span> SmtpException
            <span style="color:#0000ff;">Throw</span> <span style="color:#008000;">'Aqui rutina de comprobación propia y logueo de excepción</span>
        <span style="color:#0000ff;">Catch</span> ex <span style="color:#0000ff;">As</span> Exception
            <span style="color:#0000ff;">Throw</span> <span style="color:#008000;">'Aqui logueo de excepción</span>
        <span style="color:#0000ff;">Finally</span>
            oMensaje = <span style="color:#0000ff;">Nothing</span>
            oSMTP = <span style="color:#0000ff;">Nothing</span>
        <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Try</span>
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Sub</span>


    <span style="color:#0000ff;">Private</span> <span style="color:#0000ff;">Shared</span> <span style="color:#0000ff;">Function</span> ValidarCertificado(<span style="color:#0000ff;">ByVal</span> sender <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Object</span>, <span style="color:#0000ff;">ByVal</span> certificate <span style="color:#0000ff;">As</span> X509Certificate, <span style="color:#0000ff;">ByVal</span> chain <span style="color:#0000ff;">As</span> X509Chain, <span style="color:#0000ff;">ByVal</span> sslPolicyErrors <span style="color:#0000ff;">As</span> System.Net.Security.SslPolicyErrors) <span style="color:#0000ff;">As</span> <span style="color:#0000ff;">Boolean</span>
        <span style="color:#008000;">'bypass de la validación del certificado (aplicar aquí validación personalizada si fuera el caso)</span>
        <span style="color:#0000ff;">Return</span> <span style="color:#0000ff;">True</span>
    <span style="color:#0000ff;">End</span> <span style="color:#0000ff;">Function</span>
<span style="color:#0000ff;">End</span> Class</pre>
<p>Cuando actualice el código con utilización de archivos adjuntos y/o la versión en C# avisaré como comentario del artículo.</p>
<p>Saludos.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://varionet.wordpress.com/2007/10/30/envio-de-mail-con-framework-20-mi-clase-con-autenticacion/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
		
		<media:content url="https://0.gravatar.com/avatar/6ac4a1d95580a307da123b4c5a56eb7e711ff8e6f9fc72c35c79ccd4a9f0ebd5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Alejandro Hernández</media:title>
		</media:content>
	</item>
	</channel>
</rss>
