programa de Facturacion y ventas con codigo fuente

Seguimos con el programa de Facturación y Ventas. Les comento a todos los que lo estan esperando, que no se desesperen, seguramente entre el 28 y 30 voy a estar publicando una versión casi completa y terminada del programa y luego toda la información con el diseño conceptual del mismo.

De momento la mayor novedad es que el manejo de datos se lleva a cabo casi completamente con LINQ y ahora es un solo proyecto de Visual Studio (Visual Basic) para que todos los que no cuentan con la versión Standard o Professional o Team puedan abrirlo con la versión Express.

Espero que aquellos que enviaron mensajes con respecto al tema de que se van a ver afectadas muchas personas con este programa (sobre todo desarrolladores de este tipo de sistemas) no se angustien demasiado ya que dudo que la competencia se vuelva un problema si es que realmente son tan buenos como dicen ser, además a tomar en cuenta que está pensado para ayudar a gente que quiere aprender a programar con la práctica o para alumnos de universidades e institutos de enseñanza en la informática que necesitan un modelo de sistema para comenzar a desarrollar sus propios proyectos, así que con esto espero que terminemos con las “amenazas” por parte de estas personas.

Por ahora me despido y ya nos veremos de aquí a unos días.

Código para Convertir de Números a Letras

Es muy fácil decir que el número 123456.78 es lo mismo que "CIENTO VEINTITRÉS MIL CUATROCIENTOS CINCUENTA Y SEIS CON 78", pero para una computadora esto no es para nada fácil, principalmente porque como ya sabemos nuestra computadora trabaja con un grupo de 0's y 1's, por lo tanto nuestro lenguaje de programación actúa como un traductor universal, y para esto tenemos que saber cómo indicarle a nuestro lenguaje que traduzca la información.


Este código es realmente muy simple, y bastante viejo, incluso podemos encontrar distintas versiones del mismo código con algunas mejoras, algunos errores, y también podemos encontrarlo en varios lenguajes, pero como lo nuestro está dirigido principalmente a Visual Basic, así es como les presentaré el código:


''' <summary>
''' Función para convertir de números a letras.
''' </summary>
''' <param name="valor">Número de longitud Double.</param>
''' <returns>El número convertido en una cadena de texto.</returns>

Public Function NumerosALetras(ByVal valor As Double) As String

' Creamos una instrucción Select...Case

Select Case valor

' Para cada número escribimos su contraparte en letras
' que será devuelto al final de la función.

Case 0
NumerosALetras = "CERO"
Case 1
NumerosALetras = "UN"
Case 2
NumerosALetras = "DOS"
Case 3
NumerosALetras = "TRES"
Case 4
NumerosALetras = "CUATRO"
Case 5
NumerosALetras = "CINCO"
Case 6
NumerosALetras = "SEIS"
Case 7
NumerosALetras = "SIETE"
Case 8
NumerosALetras = "OCHO"
Case 9
NumerosALetras = "NUEVE"
Case 10
NumerosALetras = "DIEZ"
Case 11
NumerosALetras = "ONCE"
Case 12
NumerosALetras = "DOCE"
Case 13
NumerosALetras = "TRECE"
Case 14
NumerosALetras = "CATORCE"
Case Is < 20
NumerosALetras = "DIECI" & NumerosALetras(valor - 10)
Case 20
NumerosALetras = "VEINTE"
Case Is < 30
NumerosALetras = "VEINTI" & NumerosALetras(valor - 20)
Case 30
NumerosALetras = "TREINTA"
Case 40
NumerosALetras = "CUARENTA"
Case 50
NumerosALetras = "CINCUENTA"
Case 60
NumerosALetras = "SESENTA"
Case 70
NumerosALetras = "SETENTA"
Case 80
NumerosALetras = "OCHENTA"
Case 90
NumerosALetras = "NOVENTA"
Case Is < 100
NumerosALetras = NumerosALetras(Int(valor \ 10) * 10) & " Y " & NumerosALetras(valor Mod 10)
Case 100
NumerosALetras = "CIEN"
Case Is < 200
NumerosALetras = "CIENTO" & NumerosALetras(valor - 100)
Case 200, 300, 400, 600, 800
NumerosALetras = NumerosALetras(Int(valor \ 100)) & "CIENTOS"
Case 500
NumerosALetras = "QUINIENTOS"
Case 700
NumerosALetras = "SETECIENTOS"
Case 900
NumerosALetras = "NOVECIENTOS"
Case Is < 1000
NumerosALetras = NumerosALetras(Int(valor \ 100) * 100) & " " & NumerosALetras(valor Mod 100)
Case 1000
NumerosALetras = "MIL"
Case Is < 2000
NumerosALetras = "MIL" & NumerosALetras(valor Mod 1000)
Case Is < 1000000
NumerosALetras = NumerosALetras(Int(valor \ 1000)) & " MIL"
If valor Mod 1000 Then NumerosALetras = NumerosALetras & " " & NumerosALetras(valor Mod 1000)
Case 1000000
NumerosALetras = "UN MILLÓN"
Case Is < 2000000
NumerosALetras = "UN MILLÓN" & NumerosALetras(valor Mod 1000000)
Case Is < 1000000000000.0#
NumerosALetras = NumerosALetras(Int(valor / 1000000)) & " MILLONES" If (valor - Int(valor / 1000000) * 1000000) Then NumerosALetras = NumerosALetras & " " & _
NumerosALetras(valor - Int(valor / 1000000) * 1000000)
Case 1000000000000.0#
NumerosALetras = "UN BILLÓN"
Case Is < 2000000000000.0#
NumerosALetras = "UN BILLÓN" & NumerosALetras(valor - Int(valor / 1000000000000.0#) * 1000000000000.0#)
Case Else
NumerosALetras = NumerosALetras(Int(valor / 1000000000000.0#)) & " BILLONES"
If (valor - Int(valor / 1000000000000.0#) * 1000000000000.0#) Then NumerosALetras = NumerosALetras & _
" " & NumerosALetras(valor - Int(valor / 1000000000000.0#) * 1000000000000.0#)
End Select

' Devolvemos el valor de la conversión como una cadena de texto.

Return NumerosALetras
End Function

Introducción a LINQ

La pregunta del millón ¿Qué es LINQ?

LINQ (Language Integrated Query o Lenguaje Integrado de Consultas - LINC :p) es algo más que una innovación a Visual Studio y el .NET Framework, ya que su función es la de eliminar la distancia que separa el mundo de los objetos y el mundo de los datos.

Por lo general, cuando queremos realizar consultas a una base de datos, lo hacemos, ya sea, con una cadena de consulta textual o bien con un procedimiento almacenado dentro de la base de datos accediéndola mediante métodos y propiedades, esto no nos permite comprobar los tipos en tiempo de compilación ni tampoco nos permite utilizar el querido IntelliSense de Visual Studio (comunmente llamado el "salvador" en algunos casos, y en otros "reverendo h...........", disculpen el lenguaje pero hay veces en las que realmente uno lo odia en Visual Studio 2005, más adelante les cuento porqué). Otra de las ventajas que tiene LINQ es que de acuerdo al motor de bases de datos que estemos utilizando, será necesario aprender el lenguaje de consultas específico (SQL, XML, Servicios Web, etc). Para ayudar en este sentido, LINQ convierte una consulta en una construcción del lenguaje de primera clase en Visual Basic (también en C#). Las consultas se escriben para colecciones de objetos con establecimiento inflexible de tipos, utilizando palabras clave del lenguaje y operadores con los que ya estamos familiarizados (algunos un poco más que otros). La imagen que se encuentra abajo muestra una consulta LINQ parcialmente completada en una base de datos de SQL Server en C# (esto es así porque la imagen viene de la documentación de Visual Studio, y a los muchachos de Microsoft les gusta más C#, a mi personalmente me gusta solo cuando lo necesito), con comprobanción de tipos completa y compatibilidad con IntelliSense.

Bb397897_Query_Intell(es-es,VS_90).png

Con Visual Studio podemos escribir consultas LINQ en Visual Basic con bases de Datos SQL Server, XML, conjuntos de datos ADO.NET, y cualquier colección de objetos que admita IEnumerable o la interfaz genérica IEnumerable<(Of<(T>)>). No es momento para que cunda el pánico, todo está muy bien explicado en la documentación de Visual Studio, aunque de todos modos en futuros posts intentaré profundizar en estos temas tan (des)agradables. Una de las cosas más importantes de LINQ es que podemos extender sus capacidades y encontrarnos con una gran cantidad de proveedores que ya lo hacen para distintas implementaciones de bases de datos y servicios web.

Nuestra Primera Consulta con LINQ

Como ya todos sabemos (porque fuimos a Hardvard, sobre todo los que recién comienzan con el mundo de la programación), una consulta es una expresión que recupera datos a partir de un origen de datos. Las consultas se expresan en un lenguaje de consultas dedicado (esto quiere decir, que se expresan en un patrón general, ya sea SQL, XML, etc.). Esto quiere decir, que nosotros, como desarrolladores, tenemos que aprender cada nuevo lenguaje de consultas que aparece en el mercado, y aunque no todos los días aparece uno nuevo, puedo asegurarles que hay de todos los sabores y colores, es por esto que LINQ viene al rescate como un caballero de la mesa redonda (muy cursi!!!). En LINQ "SIEMPRE" trabajamos con objetos, por lo tanto siempre utilizamos los mismos modelos de codificación básicos para consultar y transformar los datos en diferentes formatos, ya sea XML, SQL, conjuntos de datos y entidades de ADO.NET, colecciones de .NET Framework y cualquier otro formato de u origen de datos para el que tengamos disponible un proveedor LINQ.

' 1. Origen de datos.
Dim numeros() As Integer = {0, 1, 2, 3, 4, 5, 6}

' 2. Creación de la consulta.
Dim evensQuery = From num In numeros _

Where num Mod 2 = 0 _

Select num

' 3. Ejecución de la consulta.
For Each numero In evensQuery

Console.Write(number & " ")

Next

En el ejemplo, el resultado nos dará algo como esto:

0, 2, 4, 6

Inferencia de Tipos

Como podemos observar, LINQ no es complicado para nada y una de las grandes ventajas que presenta es la de "Inferencia de Tipos". Esta inferencia de tipos es la que nos permite crear una consulta del tipo que vemos en el punto 2 del código fuente, permitiéndonos declarar una variable sin definir su tipo. La definición del tipo es asignada automáticamente por el compilador de Visual Basic. Esta deducción que realiza el compilador la logra de acuerdo al contenido de la variable (aunque a veces no es bueno, Visual Basic es lo suficientemente inteligente como para hacer la deducción correcta).

Public Sub inferenceExample()

' Declaración Explícita.

Dim num1 As Integer = 3

' Inferencia local de tipos.
Dim num2 = 3

End Sub

La inferencia de tipos permite establecer el tipo de una variable de manera inflexible (lo que quiere decir que éste será el último tipo que se utilizará, en el caso del ejemplo será de tipo Integer), en lugar de dejarla como tipo Object. El compilador utiliza el inicializador de una variable para determinar su tipo con el fin de generar código de enlace en tiempo de compilación.

La inferencia de tipo se produce cuando una variable local se declara sin ninguna cláusula As y se le asigna un valor. El compilador utiliza el tipo del valor como el tipo de la variable.

La inferencia de tipo sólo se puede utilizar para las variables locales no estáticas; no se puede usar para determinar el tipo de los campos de clase, las propiedades o las funciones.

Creo que con esto podemos tener una vaga idea de lo que es LINQ. Les recomiendo que lo utilicen cuando lo crean necesario, ya que a pesar de todas las ventajas que presenta, también tiene sus contras, uno de ellos es el que al crear demasiadas consultas LINQ podemos hacer que nuestro programa consuma más memoria de la necesaria, y otro contra que tiene es que como el caso de un programa que estuve analizando hace poco, podemos encontrarnos con una chanchada de código que ni siquiera el programador entendía, pero bueno, son cosas que pasan cuando no utilizamos "COMENTARIOS". Me imagino que todos comentan los programas ¿o no?.

Saludos y nos encontramos en el próximo post en el que hablaremos de LINQ to SQL, uno de los temas más importantes si queremos llegar al final de nuestro programa de facturación (algún día dejaremos las promesas y llegaremos al final).

Habilitar Conexiones de Red Remotas de SQL Server 2008 Express en Vista

Después de haber buscado en casi toda la documentación de SQL Server, logré encontrar lo que buscaba. ¿Cómo habilitar conexiones remotas desde la red en el "popular" Windows Vista? Resuelto. Aunque hubiera sido más fácil buscar en internet… si tuviera la conexión a internet en casa.

Generalmente, para el desarrollo siempre utilizamos una instancia local de SQL Server, por lo que Visual Studio es la herramienta ideal para trabajar de este modo. El problema (casi) siempre aparece cuando tenemos que configurar una aplicación en la red de una empresa, o dentro del entorno de desarrollo para probar nuestras soluciones en un entorno más profesional. Por seguridad el "querido" SQL Server 2005/2008 decide bloquear el acceso remoto para estar en un lugar seguro. Aquí les muestro los pasos a seguir para poder configurar SQL Server y las benditas conexiones remotas:

  1. Abrir el Administrador de Configuración de SQL Server (SQL Server Configuration Manager). Programas->Microsoft SQL Server 2008->Configuration Tools->SQL Server Configuration Manager.
  2. Expandir el nodo SQL Server Network Configuration y seleccionar los protocolos para SQLEXPRESS.
  3. Habilitar TCP/IP haciendo clic derecho y seleccionando "Enable" (Habilitar), luego Aceptar.
  4. Hacer clic en el nodo SQL Server Services y en el panel derecho hacer clic derecho sobre SQL Server (EXPRESS) y seleccionar reiniciar el servicio.
  5. Clic derecho sobre SQL Server Browser y seleccionar Iniciar el servicio browser si todavía no está iniciado. Esto nos permitirá acceder a la instancia de SQL Server Express por el nombre de la computadora.
  6. Abrir SQL Server Management Studio como Administrador. Si no tenemos instalado SSMS, aquí lo podemos conseguir).
  7. En el Explorador de Objetos dentro del nodo Seguridad, agreguemos un nuevo usuario para la cuenta que se conectará haciendo clic derecho y seleccionando "Nuevo Usuario". Esto abrirá la página de Propiedades de Inicio. Si estamos en un dominio entonces utilizaremos la Autenticación de Windows. Para mi caso en particular no me encontraba conectado en un dominio así que agregué un inicio y contraseña de SQL Server. (Para habilitar los inicios de SQL Server primero necesitamos hacer clic derecho sobre la instancia de SQL Server Express arriba, seleccionar Propiedades y bajo Seguridad seleccionar "Modo de autenticación de Windows y SQL Server".
  8. Seleccionar User Mapping en las propiedades de Inicio y luego marcar la base de datos a la cual nos queremos conectar. Si solo estamos probando, podemos seleccionar db_owner en el sector de roles/miembros para brindar acceso total a la base de datos, incluyendo alterar el esquema. Tomar nota de que esto no es seguro pero siempre funciona para probar y desarrollar.
    Si queremos estar seguros podemos configurar permisos bajo el nodo de seguridad para las copias de seguridad en el Explorador de Objetos. Pero si estamos en un dominio, yo recomendaría que creáramos un grupo de seguridad de Windows con privilegios dentro del dominio y luego agregarlo al SQL Server Role en el cual podremos configurar permisos específicos (ej. GRANT EXECUTE en los procedimientos almacenados CRUD y GRANT SELECT en las tablas, no permitir DELETE, INSERT y UPDATE directamente). Luego sólo podremos usar la seguridad normal de Windows para agregar usuarios al grupo del dominio. Esto también nos permitirá usar la seguridad integrada en las cadenas de conexión, lo cual es mucho más seguro.
  9. Configurar el Firewall. Esto es el peor de los pasos y el que más me hizo bendecir a toda la familia de Microsoft. Abrir el Firewall de Windows y seleccionar Cambiar Opciones, seleccionar la pestaña de Excepciones y hacer clic en Agregar Programa. Necesitaremos seleccionar SQLServer.exe en Archivos de Programa (Program Files)\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\Binn\ y SQLBrowser.exe en Program Files\Microsoft SQL Server\90\Shared\. Luego seleccionaremos las opciones para cada uno de ellos y luego haremos clic sobre el botón "Cambiar Ámbito". Luego seleccionaremos el ámbito apropiado. Para desarrollo y pruebas podemos especificar la dirección IP de la computadora remota o especificar la opción de toda la subred interna. Recomiendo no permitir el acceso a los usuarios de Internet.


    SQLFirewallWindows.JPG

  10. Configurar la cadena de conexión. Ahora de vuelta en Visual Studio podemos configurar la cadena de conexión en la Configuración de Proyecto (app.config). Si utilizamos la Autenticación de Windows entonces es realmente fácil:

Data Source=SERVIDOR\sqlexpress;Initial Catalog=BaseDatos;Integrated Security=True

Si utilizamos el Inicio de SQL entonces debemos proporcionar una cadena de conexión menos segura con el nombre de usuario y la contraseña:

Data Source=NOMBRESERVIDOR\sqlexpress;Initial Catalog=BaseDatos; User ID=nombre; Password=contraseña

Espero que les sea útil. Aunque personalmente creo que así lo será si lo que realmente desean es construir aplicaciones empresariales de alta escalabilidad y rendimiento.

Sigan el desarrollo del sistema que ahora comienza en serio con muchas novedades, entre las cuales nos encontramos con la utilización principalmente de una base de datos SQL Server, algo que muchos han pedido, y que lamentablemente por falta de tiempo jamás puedo terminar, además de esto también he rediseñado el programa para poder utilizar LINQ, algo que nos permitirá sobre todo trabajar mucho más rápido y realizando consultas sobre la base de datos de un modo más eficiente y más al estilo de un programador, en vez de andar con tantas consultas o con DataSets tipados, que seguramente los verán.

Para poder seguir con el desarrollo del programa les recomiendo que lean la ayuda de Visual Studio en este tema, que está muy completo y que seguramente los llevará por un mejor camino en la creación de programas profesionales.

Tengo que aclarar que para poder crear el programa será un requisito (aunque no 100% necesario) que utilicen Visual Studio Professional o superior, ya que para las bibliotecas seguramente se encontrarán con problemas al querer agregar otros proyectos. Aunque esto todavía está abierto a debate con un amigo y colega en la programación que me ha recomendado reunir todo en una sola solución. Pero para los Express, les recomiendo que no se emocionen demasiado porque personalmente no me gusta tener todo apilado en un solo lugar, ya que de este modo todo suele hacerse un lío y luego no encuentro nada (ya de por sí soy bastante desordenado, así que imagínense como puede terminar esto).

Les pido que tengan paciencia y que cada vez que tengan tiempo se den una vuelta por el blog.