imprimir list1

Iniciado por corlo, 3 Octubre 2020, 16:32 PM

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

corlo

Hola soy corlo
tengo una duda para imprimir list1

el codigo que tengo hasta ahora es el siguiente





Private Sub Command7_Click()
' Imprimir
Dim total As String
Dim total1 As String
Dim total2 As String
Dim i As Integer

Dim factura As Integer

ReDim lbtab(1 To 4) As Long

lbtab(1) = 31
lbtab(2) = 141
lbtab(3) = 278
lbtab(4) = 478
SendMessageArray List1.hwnd, LB_SETTABSTOPS, 4, lbtab(1)

total = Label5.Caption
total1 = Label6.Caption
total2 = Label7.Caption

Printer.FontSize = 18

Printer.CurrentX = 3100
Printer.CurrentY = 0
Printer.Print "Factura Nº:"
Printer.CurrentX = 5000
Printer.CurrentY = 0
Printer.Print Txtnum.Text


Printer.CurrentX = 1000
Printer.CurrentY = 3000
Printer.Print "Cantidad"
Printer.CurrentX = 3500
Printer.CurrentY = 3000
Printer.Print "Producto"
Printer.CurrentX = 7350
Printer.CurrentY = 3000
Printer.Print "Precio"
Printer.CurrentX = 9900
Printer.CurrentY = 3000
Printer.Print "Subtotal"


For i = 0 To List1.ListCount - 1
List1.ListIndex = i

Printer.Print List1.List(i)
Next


List1.Clear

Printer.CurrentX = 8400
Printer.CurrentY = 10000
Printer.Print "Subtotal:"
Printer.CurrentX = 9300
Printer.CurrentY = 10500
Printer.Print "iva:"
Printer.CurrentX = 9000
Printer.CurrentY = 11000
Printer.Print "Total:"

Printer.CurrentX = 10000
Printer.CurrentY = 10000
Printer.Print total
Printer.CurrentX = 10000
Printer.CurrentY = 10500
Printer.Print total1
Printer.CurrentX = 10000
Printer.CurrentY = 11000
Printer.Print total2


Printer.Print









Printer.EndDoc



End Sub





la impresion lo hace bien


como puedo hacer las separaciones del list1 a la hora de imprimir las columnas
el list1 tiene 4 columnas

ReDim lbtab(1 To 4) As Long

lbtab(1) = 31
lbtab(2) = 141
lbtab(3) = 278
lbtab(4) = 478
SendMessageArray List1.hwnd, LB_SETTABSTOPS, 4, lbtab(1)



Serapis

#1
Básicamente tienes que concatenar el contenido, para formar tú mismo las 4 columnas como una solo string, o bien imprimir en la misma línea reposicionado el cursor...

Puede danrse diferentes casos. Por ejemplo;
- A - Que el ancho de las 4 columnas sea superior al del papel.
- B - Que el ancho de las 4 columnas sea notablemente inferior al del papel
- C - Que una de las columnas sea muy superior al resto y al final las 4 no quepan en el papel.
- D - Que el listbox tenga 4 columnas, pero no tenga ítems suficientes para las 4 columnas (una o más están vacías).
- E - Que el listbox acabe teniendo más de 4 columnas (lo que sucederá cuando añadas más ítems o acortes el alto dle control).
- F - Que en un listbox, con x columnas, la última no tiene porque tener los mismos ítems que las previas ya que un listbox, es una lista que al llegar a cierta cantidad de altura continúa en otra columna, es decir no es un 'grid', donde el número de filas y columnas discurren independientemente.

Lo ideal es tener solución para todos los casos y dado el presente, decidir cuál de ellos se da y qué solución se aplica.

Tratándose de un listbox, el reparto horizontal es automatico sin posibilidad de cambio y distribuye los elementos en columna a medida que tocan el alto del listbox, (requiere tener la propiedad IntegralHeight = TRUE), tampoco hay control sobre qué ancho se le da a la columna, que además es el mismo para todas.

Es decir, nótese que hablamos de una lista (un listbox, técnicamente  solo tiene 1 campo a pesar de que se muestre en varias columnas), luego la alineación, fuente, ancho de columna, color de tinta, etc... es solo uno y el mismo para todo), no hablamos de un grid, donde cada columna es un campo y puede tener propiedades distintas... incluído el tipo de datos que aloja (no solo texto).

Lo ideal es repartir proporcionalmente las 4 columnas al ancho del papel (salvo que fueren columnas cuyo ancho textual para cada ítem sea muy corto, en cuyo caso sería preferible añadir más columnas), para ello, hay que crear una función que concatene el número de textos cuyo número de columnas se requiere y que además considere la alineación.
Además por simpliicidad, en vez de proceder como hace VB6, donde deposita (por ejemplo): lunes, martes, miércoles, jueves, viernas, sabado, domingo... debajo uno de otro, es preferible hacer una transposición, y poner en la primera fila: lunes, martes, miercoles jueves, en la segunda viernes, sabado, domingo... etc...

Código ( vb) [Seleccionar]


private function ListarEnColumnas(byref lista as listbox, byval numCols as integer, byval MargenIzquierdo as integer, byval AnchoPapel as integer, byval alineacion as AlineacionHorizontal[izquierda, centrada, derecha])  ' entiéndase, no quiero perder tiempo escribiendo una enumeración...
   dim filas as long
   dim ultimafila as long
   dim k as long, j as long, anchocol as integer
   dim linea as string
   din fuente as stdfont


   set fuente = printer.font
   printer.fontname =  "Courier New" ' una fuente monoespaciada, si no el trabajo es más laborioso...
   filas = ((lista.listcount +1) \ numcols)
   ultimafila = ((lista.listcount +1) mod numcols)  ' columnas que tendrá la última fila.
   AnchoCol = ((AnchoPapel  - MargenIzquierdo )\numcols)

   
   for k = 0 to filas -1
        ' obtener la línea de texto en x columnas.
       linea = ConcatenarCols(lista, j, NumCols, NumCols, Margen, AnchoCol, Alineacion)
        ' imprime el texto de la línea
       printer.currentx = Margen
       printer.currenty = (printer.currenty + printer.textheight("t"))  ' el textheight depende de la fuente seleccionada en la impresora, no importa el texto entre paréntesis... es fijo para la  fuente.
       imprimir linea ' <----- mejor imprimir linea a línea
   next

   if (ultimafila > 0) luego
       ' obtener la línea de texto en x columnas (con las columnas que resten).
       linea = ConcatenarCols(lista, j, UltimaFila, NumCols, Margen, AnchoCol, Alineacion)
       ' imprime el texto de la línea
       printer.currentx = Margen
       printer.currenty = (printer.currenty + printer.textheight("t"))  
       imprimir linea
   end ifi

    set printer.font = fuente
end function


private function ConcatenarCols(lista as listbox,indice as long, byval cols as integer, byval maxCols as integer, byval X as integer, byval AnchoCol as integer, byval Alineacion as AlineacionHorizontal) as string
   dim k as integer, s as string, cols as string

   for k = j to (j+cols)
       col = Formatear(lista.list(k), AnchoCol, Alineacion)  
       s = (s & col)
   next

   ConcatenarCols = s
end function

' Recordar que usamos una fuente monoespaciada, porque sino el trabajo es mucho más laborioso...
private function Formatear(Texto as string, byval Ancho as integer, byval Alineacion as AlineacionHorizontal) as string
   dim k as integer, j as integer, s as string
   
   k = (Ancho - printer.textwidth(texto))
   j = (k \ printer.textwidth(" ")) ' siendo monoespaciada, da igual que carácter sea...
   
   if (Alineacion  = IZQUIERDA) then
       if (k > 0) then   ' añadir espacios...
           s = (Texto & space$(j))
       elseif (K < 0) then  ' cortar texto.
           s = (left$( Texto, len(texto) + j)) ' j es negativo, luego la suma, resta...
       else
           s = texto
       end if
   elseif (alineacion = CENTRO) then
       '  ' Solo consideor alineación izquierda, el resto quedaría a tu esfuerzo
   else ' DERECHA
       '  ' Solo considero alineación izquierda, el resto quedaría a tu esfuerzo
   end if

   Formatear = s
end function


Si estás completamente seguro que no se dan los casos etiquetados al comienzo como: 'A' y 'C', puede hacerse más directo (menos código, pero más ineficiente) y en general puede cambiarse cosas aquí y allá según el caso concreto de que se trate...

Código ( vb) [Seleccionar]

private function ListarEnColumnas(byref lista as listbox, byval numCols as integer, byval MargenIzquierdo as integer, byval AnchoPapel as integer)
   dim filas as long
   dim ultimafila as long
   dim k as long, j as long, i as integer, n as integer, anchocol as integer
   dim linea as string
   din fuente as stdfont
 

   set fuente = printer.font
   printer.fontname =  "Courier New" ' una fuente monoespaciada, si no el trabajo es más laborioso...
   filas = ((lista.listcount +1) \ numcols)
   ultimafila = ((lista.listcount +1) mod numcols)  ' columnas que tendrá la última fila.
   AnchoCol = ((AnchoPapel  - MargenIzquierdo )\numcols)

   
   for k = 0 to filas -1  
       n = Margen              
       for i = 0 to numcols -1
           printer.currentx = n  ' imprime el texto de la columna 'i'
           imprimir lista.list(j+i)
           n = (n + AnchoCol)
       next
       
       j = (j+NumCols)
       printer.currenty = (printer.currenty + printer.textheight("t"))  ' el textheight depende de la fuente seleccionada en la impresora, no importa el texto entre paréntesis... es fijo para la  fuente.
   next

   if (ultimafila > 0) then' la última fila tiene 1 o más columnas, pero menos que 'numcols'.
       n = Margen              
       for i = 0 to ultimafila -1
           printer.currentx = n  ' imprime el texto de la columna 'i'
           imprimir lista.list(j+i)
           n = (n + AnchoCol)
       next
   end if

    set printer.font = fuente
end function


Todo el código es genérico y requiere adaptación al caso concreto y retocar algunas cosas... por ejemplo es típico tener que pelearse con el 'scalemode'... Margen y AnchoPapel (y por extenson anchoCol) son dependientes de dicho valor, así como TextWidth y TextHeight, CurrentX y CurrentY... Si no se opera para todos con la misma escala, hay desajustes.

editado:
donde ponía: imprimir lista.list(j+n)  <---- imprimir, si el objeto es la impresora, sería: printer.print
debe poner: imprimir lista.list(j+i)
Faltaba restablecer la fuente al final d ela función: set printer.font = fuente

corlo

Hola Nebire
Gracias por contestar
una pregunta
para ir a la funcion de listar en columnas ¿como se dirige a la funcion , gracias?

Serapis

#3
Invocándola como cualquier otra función... con su nombre y parámetros obligatorios.

ejemplos:
Código ( vb) [Seleccionar]

dim x as integer, v as integer, Total as integer
v= 12

' Llamada con asignación.
x = Sumar(5,v)

' Llamada como subrutina y no como función. 'Total' sería un parámetro pasado por referencia...
Call SumaYSigue(5,v,Total)

' Lllamada como parámetro de otra función:
call Msgbox Sumar(5,v)
x = Restar(sumar(5,v),11)


' Las instrucción 'call' es opcional, pero si se añade, los paréntesis de la función son obligatorias... es decir estas 2 sentencias son equivalentes:
Código ( vb) [Seleccionar]

Call SumaYSigue(5,v,Total)
SumaYSigue 5, v, Total


Tú mismo tienes en tú código llamadas a funciones como:
Código ( vb) [Seleccionar]

Printer.Print Txtnum.Text
Printer.EndDoc    '   'enddoc' es una función o sub del objeto printer, igual que 'print'
SendMessageArray List1.hwnd, LB_SETTABSTOPS, 4, lbtab(1)


Vamos que sorprende una pregunta así...

corlo

He probado la funcion y no funciona
gracias

Serapis

#5
Tienes que adaptarla... el copy-paste, no siempre va a ser la solución...
Si entiendes lo que hace y conoces un poco el lenguaje no es nada complicado adaptarlo a exactamente lo que necesites según lo que tienes...

* Revisando, se ha escapado un gazapo, que cualquiera que entiende el código lo vería rápido (lo he corregido y comentado en el mensaje más arriba).

corlo

gracias por contestar

tu mismo lo dices que hay un error

asi no se solucionan las cosas


yo soy principiante en programacion

gracias por contestar

cierro tema

Serapis

#7
... mensaje duplicado

Serapis

Cuando escribes código 'al vuelo', es normal que se escape algún error... en ese punto, lo que importa es escribir y avanzar, sin importar si se ha escapado algún error, es luego cuando lo traslada uno al IDE, que a medida que lo pegas o redactas de nuevo que al tiempo vas repasando el código y los errores o cambios a efectuar saltan rápido a la vista.

Si ves trabajar a un escultor (por ejemplo)... en primera instancia hará un rebaje general que dé forma a la figura que trata de hacer, pero nunca será un acabado (salvo que se trate de una pieza muy pequeña)... tendrá que volver a repasar todo afinando cada detalle que lo precise.

...al programar cuando tengas solvencia, pasa lo mismo, escribes código o pseudocódigo, a veces mezclado, para escribir rápido la idea y cuando lo transcribes a código es cuando repasas cada detalle y lo afinas al caso concreto presente. De hecho a veces es común invocar funciones que ni siquiera has creado, pero cuya funcionalidad queda descrita en su nombre y resulta superfluo en primera instancia perder tiempo en escribirla o describirla... de hecho las funciones 'ConcatenarCols' y 'Formatear' no iba a realizarlas, precisamente porque entiendo que estás aprendiendo, es que las he abordado...

Ya te decía que 'Todo el código es genérico, requiere adaptación al caso concreto y retocar algunas cosas...', porque hay detalles que dependen exclusivamente del caso concreto, y por tanto no hay una solución única válida para todos los casos... y por lo mismo una función générica que pueda ser fácilmente adaptada a cualquier caso, es la mejor opción.

p.d:
De hecho... una vez que todo funciona sin errores, todavía se puede dar un último repaso cuyo cometido es optimizar. Cuando describes una idea no procede pensar en detalles para hacerla óptimo, porque pierdes tiempo, es solo el momento de describir la idea, describir el funcionaiento general, la optimización es la fase final... (en medio es escribir el código y lograr que funcione exactamente como se espera). Los aprendices suelen omitir la primera y última fases, es normal...

corlo

Hola nebire

no puedo seguir con el ejemplo que has puesto, porque no consigo separar las columnas
del list1 por impresora


gracias