Pasa que no estás controlando la cantidad de líneas impresas para luego comprobarlo. Ya que en
listarcolumnas imprimes las líneas, ahí deberías hacer la comprobación, y mejor si usas otra variable porque
i ya se está utilizando para otras cosas
Por ejemplo usaré
lineas y resaltaré la parte que he agregado a tu código:
Private Sub listarcolumnas()
Dim AnchoPapel As Integer
Dim MargenIzquierdo As Integer
Dim numCols 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
Dim margen As Integer
Dim fuente As StdFont
Set fuente = Printer.Font
numCols = 9
Printer.FontName = "Courier New" ' una fuente monoespaciada, si no el trabajo es más laborioso...
filas = ((List1.ListCount + 1) \ numCols)
ultimafila = ((List1.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'
Printer.Print List1.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.
lineas = lineas + 9 'Arriba se imprimieron 9 líneas
If lineas > 24 Then
Printer.NewPage
encabezado
lineas = 0
End If
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'
Printer.Print List1.List(j + i)
n = (n + anchocol)
Next
End If
Set Printer.Font = fuente
End Sub
---
No es normal trabajar con coordenadas (x, y) para estos trabajos de impresión ya que requieren de buenos cálculos matemáticos y/o trabajar con prueba y error. Las coordenadas se usan más cuando el tipo y tamaño de fuente varían en la hoja a imprimir, se van a agregar elementos gráficos y se requiere moverse por toda la hoja para imprimir en diferentes lugares en cualquier orden.
- Pero si se va a trabajar con un tamaño de fuente determinado y que además es monoespaciada, es mejor crear una plantilla en un editor de texto plano como Notepad++ o similar, luego se facilita mucho la impresión de líneas usando Format y demás opciones que hay para formatear, alinear y distribuir el texto de acuerdo a la plantilla, por ejemplo esta plantilla para una hoja A4, y fuente Consolas de tamaño 10:
HORA: 05:19:42 LISTADO DE ALMACEN FECHA: 16/07/2024
=======================================================================================================
Código | Stock | Artículo | Precio | Impuesto | Uds.Caja | Umbral | Pedido | En Oferta
-------------------------------------------------------------------------------------------------------
A00001 | 5000 | Lapicero | 0.15 | 0.18 | 20.20 | 5.3 | 200 | 500
- El objetivo de esta plantilla es reconocer los tamaños y espaciados requeridos para el trabajo de impresión, luego con esto es más fácil usar Print porque ya se conocen estos detalles
- Ahí dejé libre la primera fila y las dos primeras columnas como margen
- Le puse barritas | como separador para que sea más legible pero se pueden quitar si molestan y de paso ganar más espacio
Para imprimir es fácil porque me basta con escribir tal cual las líneas o datos que no varían y formatear con la cantidad de caracteres correcta para los que si varían, todo dependerá de la plantilla. Acá dejo un ejemplo por si lo quieres probar, si no entiendes algo dale click a esa instrucción y presiona F1 para que te muestra a ayuda de VB, sino siempre puedes preguntar por acá.
Const n = 200 'Generaré 200 registros aleatorios para el ejemplo
Dim c1(n), c2(n), c3(n), c4(n), c5(n), c6(n), c7(n), c8(n), c9(n) As String
Private Sub Form_Load()
GenerarDatos 'Genera datos aleatorios para las columnas
Printer.Font.Name = "Consolas"
Printer.Font.Size = 10
Encabezado
ListarColumnas
Printer.EndDoc
End Sub
Sub Encabezado()
Printer.FontBold = True
Printer.Print 'Imprime una línea vacía
Printer.Print " HORA: "; Time; Spc(27); "LISTADO DE ALMACEN"; Spc(27); "FECHA: "; Date
Printer.Print " "; String(104, "=")
Printer.Print " Código | Stock | Artículo"; Spc(19); "| Precio | Impuesto | Uds.Caja | Umbral | Pedido | En Oferta"
Printer.Print " "; String(104, "-")
Printer.FontBold = False
End Sub
Sub ListarColumnas()
lineas = 0
For i = 0 To n
Printer.Print " "; c1(i);
Printer.Print " | "; Format(c2(i), "@@@@@");
Printer.Print " | "; Format(c3(i), "!@@@@@@@@@@@@@@@@@@@@@@@@@@");
Printer.Print " | "; Format(c4(i), "@@@@@@");
Printer.Print " | "; Format(c5(i), "@@@@@@@@");
Printer.Print " | "; Format(c6(i), "@@@@@@@@");
Printer.Print " | "; Format(c7(i), "@@@@@@");
Printer.Print " | "; Format(c8(i), "@@@@@@");
Printer.Print " | "; Format(c9(i), "@@@@@@@@@")
lineas = lineas + 1 'Arriba se imprimió 1 línea
If lineas > 64 Then
Printer.NewPage
Encabezado
lineas = 0
End If
Next
End Sub
Sub GenerarDatos()
For i = 0 To n
c1(i) = (Format(i, "A00000"))
c2(i) = Int((10000 * Rnd))
c3(i) = String(25 * Rnd + 1, "x")
c4(i) = Format(998 * Rnd + 1, "0.00")
c5(i) = 0.18
c6(i) = Int((1000 * Rnd))
c7(i) = Int((1000 * Rnd))
c8(i) = Int((1000 * Rnd))
c9(i) = Int((1000 * Rnd))
Next
End Sub
El resultado es:
https://mega.nz/file/spwmUZxI#qa8RkqNKuR_hxj3LyfIhnPBSxkcQyggQnEfEZjWthAYAcá dejo el Proyecto por si lo quieres descargar:
https://mega.nz/folder/wpx0hJQJ#TUpjfKk3hEqtKilP4fcE3g