Recorrer datos de un ListView y imprimir con Printer.Print

Iniciado por jack06, 31 Agosto 2018, 00:34 AM

0 Miembros y 1 Visitante están viendo este tema.

jack06

Muy buenas tardes amigos.

Una consulta, no se si alguien de usted a trabajado con Impresoras de Tiqueteras.

Pues bien estos usando el Metodo Ptinter.Print lo que neceseto es recorrer un Listview y imprimir directo, pero eh estado probando un codigo que encontre aca:

http://www.recursosvisualbasic.com.ar/htm/trucos-codigofuente-visual-basic/111-imprimir-listview.htm

El problema es que me sale muy separado los espacios de las filas estuve modificando algo el codigo pero me salen muy separadas no logro cuadrarlas, me quedan asi mas o menos para que tengan la idea.



Y uso esta parte de codigo:

'A esta función se le envía el control LV a imprimir
Public Sub Imprimir_ListView(ListView As ListView)
 
    Dim i As Integer, Espacio As Integer, X As Integer
    Dim Item As ListItem
   
    'Encabezado de ejemplo
    Printer.Print ""
    Printer.Print "                                   ~DON MEGIA~ "
    Printer.Print "                              POLLOS A LA BRASA"
    Printer.Print "                  CAL. MORALES BERMUDEZ N° 323"
    Printer.Print ""
    Printer.Print "                                 TICKET DE VENTA"
    Printer.Print
    Printer.Print "  Recibo:          "
    Printer.Print "  Fecha:           " & Date & "  " & Time
    Printer.Print "  Mesa:            "
    Printer.Print "  Atendido Por:    "
   
    Printer.Print
    Printer.Print "  Descripcion                                 Precio       Cant        Total"
    Printer.Print "  -----------------------------------------------------------------------------"

    With ListView
   
        'Este bucle recorre los items y subitems del ListView  y los imprime
        For i = 1 To .ListItems.Count
           
            Espacio = 0
         
            Set Item = .ListItems(i)
   
            'Recorremos las columnas
            For X = 1 To 4
                Espacio = Espacio + CInt(.ColumnHeaders(X).Width)
'                Printer.CurrentX = Espacio
                Printer.Print "  " & Item.SubItems(X);
            Next
         
            'Otro espacio en blanco
       Printer.Print
  Next
   
  End With
   
  Printer.Print

  Printer.Print
  'Texto del pie
  Printer.Print "               ¡¡¡GRACIAS POR SU PREFERENCIA!!!"
   
  'Comenzamos la impresión
  Printer.EndDoc
End Sub


O quizas aya otra forma de hacerlo esto trabajadno con base de datos con access eso quiero que se imprima cuando le doy en un boton cobrar y directo lo imprima por la ticketera, desde ya muchas gracias, haber si alguien tiene experiencia en eso y me oriente.

Gracias....
(̅_̅̅_̅(̅_̅_̅_̅_̅() ڪ €l $åßîø nø d nµn¢å tødø lø qµ£ Þî£n$å, Þ£®ø $î£mÞ®£ Þî£n$å tødø lø qµ£ d (̅_̅̅_̅(̅_̅_̅_̅_̅() ڪ

Serapis

#1
Las filas ocupan el espacio entre una fila y la siguiente.
Las columnas ocupan el espacio entre un carácter y el siguiente...

Y digo esto, porqué no a cuál te refieres exactamente, yo veo bien las filas.

En cualuqier caso es algo que depende de la fuente utilizada, así que puedes probar con diferentes fuentes para el  objeto printer:

Código (vb) [Seleccionar]
printer.font = "verdana"

Y también puedes jugar con el tamaño:
Código (vb) [Seleccionar]
printer.font.size = 12

y por último y más interesante, si estás satisfecho con la fuente y tal... simplemente puedes indicarle que la siguiente línea la imprima algo más arriba...

Esto es crea una función tal que así CambiarFuente, que invocaremos cada vez que queramos cambiar la fuente o su tamaño, y que nos devolverá el alto de la fuente (simepre actualizado), para luego usar una función 'Saltar... puesta más abajo...

...yo te pongo código, esto antedicho y algo más que te explico más abajo, tu lo pruebas en otro proyecto aparte, cambiar lo que proceda, lo pruebas de nuevo y entonces que quedes satisfecho, lo integras en tu proyecto)...

Añade un botón y un listbox como se muestra en la imagen capturada ...

Código (vb) [Seleccionar]

Dim AltoLinea As Single  ' en píxeles


Private Sub Command1_Click()
   Call IntentaCambiarFuenteEInforma("Verdana")        ' 13
   Call IntentaCambiarFuenteEInforma("Arial")          ' 14
   Call IntentaCambiarFuenteEInforma("8514oem")        ' 20
   ' Esta dará error, porque su nombre es 'Monospac' sobra la 'e'... para probar...
   Call IntentaCambiarFuenteEInforma("Monospace821 Bt", 22) ' monoespaciada
   Call IntentaCambiarFuenteEInforma("Agatha")         ' 21
   
   Call IntentaCambiarFuenteEInforma("Fixedsys")       ' 20
   Call IntentaCambiarFuenteEInforma("Impact")         ' 22
   Call IntentaCambiarFuenteEInforma("Lucida Console") ' 18 monoespaciada
   Call IntentaCambiarFuenteEInforma("Math B", 32)     ' 13--> 49
   Call IntentaCambiarFuenteEInforma("Mini Pics Lil Edibles") ' 43 esta tiene comida, que tal un símbolo en cada artículo ?
   
   With Me
       .CurrentX = 3200
       .CurrentY = 45
       .ForeColor = vbRed
       Print ("%*lq8Dev") ' hamburguesa, pizza, espaguetis?, perrito caliente, helado, fruta, pollo, bebida
   End With
End Sub

Private Sub IntentaCambiarFuenteEInforma(Optional ByRef Nombrefuente As String, Optional size)
   Dim fuenteprevia As String, fuenteReasign As String, fuenteFinal As String
   Dim sizePrevio As Single, sizeActual As Single
   Dim cmb As String
   
   fuenteprevia = Me.FontName: sizePrevio = Me.FontSize
   
   If Me.CambiarFuente(Nombrefuente, size) Then
       'MsgBox "Nueva fuente. Alto de una línea con la fuente '" & Nombrefuente & "':  " & CStr(AltoLinea)
       fuenteFinal = Nombrefuente
       cmb = "Cambiada"
   Else
       fuenteFinal = Me.FontName
       cmb = "Forzada"
       'MsgBox "Alto de una línea con la fuente reasignada '" & CStr(Me.FontName) & "':  " & CStr(AltoLinea)
   End If
   sizeActual = Me.FontSize
   
   
   linea = Concatena(cmb, fuenteprevia, CStr(sizePrevio), Nombrefuente, fuenteFinal, CStr(sizeActual))
   List1.AddItem (linea)
End Sub

Private Function Concatena(a As String, b As String, c As String, d As String, e As String, f As String) As String
   Dim c1 As String, f1 As String
   
   a = FijarNumchars(a, 10)
   b = FijarNumchars(b, 17)
   c = FijarNumchars(c, 10, vbRightJustify)
   d = FijarNumchars(d, 17)
   e = FijarNumchars(e, 17)
   f = FijarNumchars(f, 10, vbRightJustify)
   
   Concatena = Join(Array(a, b, c, d, e, f), " | ")
End Function

' Devuelve texto truncado al número de caracteres indicado (corta o añade espacios).
Private Function FijarNumchars(ByRef Valor As String, ByVal Numchars As Byte, Optional Lado As AlignmentConstants = vbLeftJustify) As String
   Dim size As Byte, par As Byte
   
   
   size = Len(Valor)
   If (size > Numchars) Then
       FijarNumchars = Left$(Valor, Numchars)
   ElseIf (size < Numchars) Then ' Hay q ue añadir espacios en alguna o más partes...
       Select Case Lado
           Case vbLeftJustify
               FijarNumchars = Valor & (Space$(Numchars - size))
           Case vbRightJustify
               FijarNumchars = (Space$(Numchars - size)) & Valor
           Case Else ' centrado
               par = (size And 1) ' si es par= 0, si no suma 1
               size = ((Numchars - size) \ 2)
               
               FijarNumchars = (Space$(size) & Valor & Space$(size + par))
       End Select
   Else
       FijarNumchars = Valor
   End If
End Function

Private Sub Form_Load()
   Dim linea As String
   
   Call CambiarFuente
   
   linea = Concatena("Cambio", "Actual", "Alto", "Solicitada", "Final", "Alto")
   With List1
       .Font = Me.Font
       .Width = Me.TextWidth(linea & "  ")
       Me.Width = .Width + (.Left * 2) + 60  ' suma 4 píxeles del margen de la ventana...
       
       .AddItem (linea)
       Call .AddItem(String(100, "-"))
   End With
End Sub


' Intenta cambiar la fuente... en caso de hacerlo devuelve TRUE.
'   aunque no se produzca ningún cambio, SIEMPRE calcula el alto para la fuente actual.
' OJO: Cambiar la fuente puede cambiar el alto, ya que cada fuente tiene su propia altura específica.
Function CambiarFuente(Optional ByRef Nombrefuente As String, Optional size) As Boolean
   Static basta As Boolean
   Dim intentoFallido As Boolean
   On Error Resume Next  ' por si no existe la fuente...

   ' Cambia la fuente
   If (Len(Nombrefuente) > 0) Then
       Me.Font = Nombrefuente
       
       If (Me.FontName = Nombrefuente) Then
           CambiarFuente = True ' la fuente cambió.
       Else
           intentoFallido = True ' ha habido un intento de cambiod e fuente fallido...
           ' pero un fallo en esto, implica que asigna una fuente del parent
           MsgBox "Nueva fuente: " & Me.FontName & vbCrLf & "Reasignada por intento fallido de : " & Nombrefuente & vbCrLf & "Ha habido un intento de cambio de fuente fallido... quizás no esté instalada en tu sistema (o el nombre de la fuente esté mal redactado)."
           ' OJO: La reasignación de fuente, cambia la fuente, pero deja el tamaño previo que hubiere (truncado al más próximo que permite la nueva fuente).
       End If
   End If
   
   ' Size se deja como variant, para preguntar si se recibió valor para dicho parámetro.
   If IsMissing(size) = False Then
       ' si hubo error al tratar de cambiar de fuente, no se deja cambiar el tamaño...
       If (intentoFallido = False) Then
           ' No necesariamente se cambiará al valor reclamado, cada fuente tiene sus tamaños, así que se ajusta al más 'similar'.
           If (Me.FontSize <> size) Then
               Me.Font.size = size
               MsgBox "tamaño de fuente cambiado a: " & CStr(Me.FontSize)
           End If
       End If
   End If

   ' Y obtiene el alto de cada línea (en realidad basta con un carácter, pués se basa en la fuente)
   '   En realidad si solo es una línea (de alto) una cadena vacía es suficiente...
   AltoLinea = (Me.TextHeight("Whisky para todos.") / Screen.TwipsPerPixelY)
   
   
   If (basta = False) Then ' es suficiente con mostrarlo una vez...
       ' OJO: Si el texto se compone de varias líneas (porque lleva CRLF), devuelve el alto acumulado entre todas ellas.
       ' ejemplo:
       Dim x As Single
       x = ((Me.TextHeight("Whisky" & vbCrLf & " para" & vbCrLf & " todos.") / 3) / Screen.TwipsPerPixelY)
       MsgBox "¿el alto de una línea es el mismo que el de tres si dividimos su alto entre tres?" & vbCrLf & vbTab & CStr(x = AltoLinea)
       
       basta = True
   End If
End Function


Bien, hay varias cosas que decir del código previo, pero antes vamos a lo que te urge...
El código anterior nos ofrece el alto de línea... (en el ejemplo es para el form, pero cambiando en la función deseada (CambiarFuente), Me. por Printer. donde procede, llegamos a los mismo, no tengo impresora conectada a este equipo)...



Código (vb) [Seleccionar]

' Función: Reposiciona el puntero de escritura.
' Parámetros:
'    AvanceUnitario: es la cantidad de píxels (u otro tipo de medida, esto debes consensuarlo con el "ScaleMode" que tengas), que sube o bajas sobre el alto de una fila. Un valor 0 señala que es el alto que ofrece la fuente.
'    AvanceLineas: es para cuando debas saltar más de una línea (típicamente porque dejas alguna en blanco), pero por defecto tiene valor de 1 linea.
'    IncHorizontal: valor de Incremento horizontal.
'    Absoluto: Señala si el valor es absoluto o relativo (que se suma (o se resta si es menor que 0) a la posiciópn horizontal actual).
Private Sub SaltarLinea(ByVal AvanceUnitario As Byte, Optional AvanceLineas As Byte = 1, Optional ByVal IncHorizontal As Integer = 0, Optional ByVal Absoluto As Boolean = True)
   Dim x As Integer
   
   Printer.CurrentY = Printer.CurrentY + ((AltoLinea + AvanceUnitario) * AvanceLineas)
   
   ' Puede que queramos saltar de línea arriba abajo, pero seguir en la posición horizontal, o cambiarla...
   If (IncHorizontal <> 0) Then
       x = IncHorizontal
       If (Absoluto = True) Then
           Printer.CurrentX = IncHorizontal
       Else
           Printer.CurrentX = (Printer.CurrentX + IncHorizontal)
       End If
   Else
       If (Absoluto = True) Then Printer.CurrentX = 0
   End If
End Sub
' Para saltar 3 líneas, con un alto de 2 píxeles más de alto entre cada línea)
SaltarLinea(2, 3)

' Para saltar a la siguiente línea con 1 píxel más arriba de lo que tiene cada línea:
SaltarLinea(-1, 1)

'  Recuerda Si ya saltaste la línea ...
' SaltarLinea( x, AvanceLineas: =0 )
SaltarLinea(-3 , 0) ' de la línea actual sube 3 pixels.


Recuerda que  'print' tiene la siguiente sintaxis:
print {Spc(n) | Tab(n)} expression charpos

- Spc(n): es opcional y quiere decir que pudes indicar x espacios (columnas)
- Tab(n): es opcional y quiere decir que puedes imprimir en la columna x de dicha línea (incluso más atrás de la actual, donde apunte currentX, es decir es un valor absoluto).
En realidad Tab es lo adecuado, cuando tienes varias columnas, pués conociendo el punto de comienzo de cada ciolumna, puedes escribirlas en cualquier orden... ya que controla el punto de escritura en la línea con el 'tabulador' ...
- expression: se refiere al texto que vas a escribir.
- charpos: son opciones que indican adónde apuntar tras escribir la 'expressión'. Si se omite (por defecto es así), se salta de línea, si se pone "," (una coma), equivale a añadir vbtab al texto. Si se pone ";",  simplemente avanza a la posición dle siguiente carácter... es decir es lo adecuado si quieres usar la función "saltarLinea", indicando cuantas líneas y el resto de parámetros, etc......






Y una vez aclarado tu problema...
Por lo demás, veo que las columnas no coinciden... tienes columnas de artículo, precio, cantidad total...
Tu primer trabajo es determinar la posición donde termina cada una de las columnas, o mejor darles formato y señalar cuantas columnas ocupa cada una...
Es decir, la columna artículo, se imprime alineada a la izquierda (se hace así con el texto), pero las otras columnas son numéricas y los números se alinean a la derecha...
Sabiendo la delimitación de un campo (punto de comienzo y fin), como te he indicado más arriba puedes usar Tab(x), para empezar a imprimir ahí...

...en el código he puesto también ejemplo para alinear texto sobre columnas... que espero te sirvan de ayuda para mejorar la presentación, como se ve en la imagen.



cuestiones menores... puedes usar negrita para algún campo dentro de la etiquetas de factura.
Incluso la veleidad de que si seleccionas la fuente "Mini Pics Lil Edibles", que contiene símbolos de comida, podría antecerse el texto de la columna del artículo con un carácter...  para diferenciar por ejemplo comida de bebidas, postre, café, licores, etc...



p.d.:
No uses instrucciones de esta forma:
Código (vb) [Seleccionar]

 Printer.Print "               ¡¡¡GRACIAS POR SU PREFERENCIA!!!"


Usa mejor la función como la que te he pasado....
Código (vb) [Seleccionar]

dim Gracias as string

gracias = "¡¡¡GRACIAS POR SU PREFERENCIA!!!"
printer.print FijarNumchars(gracias, printer.width, vbCenter)

Recuerda siempre el ScaleMode, para ejemplos de código, sin probar uno no va a estar poniendo cada cosa meticulosamente , eso corresponde al interesado... Si printer.width, no te ofrece valores traduce desde  printer.papersize, y si no establece un valor manualmente al cargar la aplicación sabido el ancho del papel...