Arreglo de parámetros en una función de VBA con ParamArray

Hace poco me programé una función para armar consultar de SQL Server desde VBA, pero de manera que cada parámetro fuese una línea de la consulta. Descubrí ParamArray que es basicamente un arreglo de parámetros en una función.

Esto también puede servir cuando no sabes cuantos parametros vas a recibir, pero sí que operación vas a hacer con esos parámetros. Se me ocurre por ejemplo, sumar todos los parametros que reciba la función. Vamos a ella:

Public Function SumarValores(ParamArray N()) as Double
  Dim ResultadoSuma as Double
  ResultadoSuma = 0
  Dim item As Variant
  If Ubound(N) >=0 then
    For Each item In N
      ResultadoSuma = ResultadoSuma + N
    Next
  End if
  SumarValores = ResultadoSuma
End Function

Con esto estaremos sumando todos los valores que recibamos como parámetros. Ya podrías validar si en efecto el parámetro es número o demás.

Se puede llamar así desde la consola o vista inmediato (CTRL + G):

?SumarValores(10,20,30,40,50)
?SumarValores(1,50,20)

Usa ParamArray 🙂

 

No imprime a puerto de Red en Windows 10

Tras una actualización de Windows 10, sin razón aparente dejó de funcionar la impresión de archivos de bajo nivel mediante un puerto de red. Te cuento:

En tiempos pasados, imprimir a un puerto serial o paralelo era sumamento sencillo. Abrias el puerto como si fuese un archivo y le escribías texto y salía en la impresora. A esto se le llama impresión de archivos de bajo nivel. Luego llegó USB y la cosa cambió…

Las impresoras USB no permiten escribir texto directamente sobre su puerto, por lo que los ingeniosos (no ingenieros), descubrieron que si compartían la impresora, sí se podía. Así que bendita solución.

Luego llegó Windows Vista e incluyó grupo hogar y ya se empezó a complicar la situación. Ahora no se podía simplemente escribir directamente sobre un puerto de red directemente sobre el, sin formar parte del mismo grupo de trabajo.

Luego llegó Windows 7. Ahora se llama grupo Hogar pero funciona igual. Luego en Windows 8 y 8.1 El grupo Hogar se puede protejer con una contraseña, por lo que ahora  necesitas formar parte de ese grupo ingresando la contraseña.

En Windows 10 sigue igual pero ya es más amigable, pero aún hay ocasiones en las que los permisos de escritura y lectura fallan.

Tras la última actualización de Windows 10, no se puede escribirle directamente a una impresora compartida en otro equipo. Desconozco si hay en algún lugar alguna configuración que permita habilitar esta opción, mientras tanto, aunque formes parte del Grupo Hogar no se puede. he buscado mucho y no he encontrado alguna configuración de ese tipo. Aunque deshabilites el firewall, sigue fallando.

Problema: en VBA esto no funciona (es algo similar para otros lenguajes):

Public Function ImprimirHolaMundo()
    Dim NPuerto as Long
    NPuerto = Freefile
    Open \\PC02\Impresora For Output As #NPuerto
    Print #NPuerto, "Hola Mundo"
    Close #NPuerto
End Function

Solución:

No es nueva ni mucho menos, esto se lleva usando desde hace muchos años. Y solo prongo la solución que a mi me ha funcionado.

Configurar un puerto virtual que haga referencia a esa ruta de la impresora compartida. Lo puedes hacer desde la consola con:

Net use LPT1: \\PC02\Impresora

Si quieres hacerlo persistente, que siga funcionando aunque cierres esa ventana de comandos:

Net use LPT1: \\PC02\Impresora /persistent: yes

Pero si reinicias, hay que volver a hacerlo. Así que puedes crear algún script para que se ejecute cada vez que se reinicie, ya toca echar imaginación.

Y la función inicial ahora funcionará perfetamente de esta manera:

Public Function ImprimirHolaMundo()
    Dim NPuerto as Long 
    NPuerto = Freefile 
    Open LPT1: For Output As #NPuerto
    Print #NPuerto, "Hola Mundo" Close #NPuerto
End Function

En mi caso, me hice una función para registrar y desregistrar este puerto virtual:

Public Function PuertoVirtual_Registrar(sImpresora As String, Optional sPuerto As String = "LPT1") As Boolean
 PuertoVirtual_Eliminar sPuerto
 Dim P As String
 P = "NET USE " & sPuerto & ": " & sImpresora
 R = Shell("cmd.exe /c " & P, vbHide)
 If R = 0 Then
   PuertoVirtual_Registrar = False
 Else
   PuertoVirtual_Registrar = True
 End If
End Function

Public Function PuertoVirtual_Eliminar(Optional sPuerto As String = "LPT1")
 Dim P As String
 P = "NET USE " & sPuerto & ": /DELETE"
 Shell "cmd.exe /c " & P, vbHide
End Function

Entiendo que quizá haya formas mas profesionales de hacerlo. Si tienes alguna sugerencia, por favor escríbeme en los comentarios.

Una solución de un ingenioso que no es ingeniero 🙂

Listar mas de 10,000 registros en los ComboBox de Access

Pues tal. Cuando llegas a tener muchos registros en una base de datos de Access o SQL Server y generas un formulario con un ComboBox que liste los resgitros de una Tabla y esta tenga mas de 10,000 registros, te darás cuenta de que solo filtra los primero 10,000 por defecto.

Esto se cambia en el menú Archivo > Opciones > Configuración del cliente y en la venta que se abre establece 0 en el campo: Nº Máximo de registros.

Parece una solución simple, pero encontrarla te puede llevar unas cuantas horas si eres novato como yo.

Generar la Cadena Original de un XML (CFDI) en VB6/VBA

Para crear la Cadena Original de un XML usando la XSLT proporcionada por el SAT en VBA debes hacer lo siguiente:

  1. Agregar a las referencias: «Microsoft XML, v3.0» (o 6.0)
  2. Usar el siguiente código:

 

Function getCadenaOriginal()
    Dim oXSlT As New DOMDocument
    Dim xXML As New DOMDocument
    Dim sCadenaOriginal As String
    oXSlT.Load "D:\proyectos\cadenaoriginal_3_2.xslt"
    xXML.Load "D:\Proyectos\util\F.xml"
    sCadenaOriginal = xXML.transformNode(oXSlT)
    Debug.Print sCadenaOriginal
End Function

Esto te devolverá la cadena original generada a partir de un XML.

getCadenaOriginal

Recuerda que debes tener un XML ya timbrado, y el archivo «cadenaoriginal_3_2.xslt» que lo puedes descargar desde el SAT.