viernes, 16 de diciembre de 2011

Imprimir tickets

Un modo de generar un documento con un formato no muy complejo e imprimirlo es utilizando un formulario, añadiendole los controles deseados hasta obtener el aspecto requerido y después imprimirlo. Yo he puesto en práctica esta opción para la creación de tickets y facturas de venta.
A continuación, muestro como se realizaría esta tarea en el caso de los ticket. Para las facturas se hace de forma muy parecida, sólo hay que añadir los datos del cliente y cambiar un poco el formato.


Cuando se crea un objeto de la clase fTicket se le debe pasar una lista que incluye los artículos incluidos en la cuenta para la que se va a generar el ticket. La lista de la cuenta será una lista de objetos que contengan la información relevante de cada concepto a mostrar en el ticket.

Public Class fTicket
    Private _listaCuenta As ArrayList

    Public Sub New(ByRef cuenta As ArrayList)
        InitializeComponent()
        _listaCuenta = cuenta
    End Sub

Al mostrar el formulario se añadirán todos los controles (etiquetas, en este caso) necesariios para lograr el formato deseado. A continuación se muestra como se añadiría una línea por cada concepto en la cuenta, y posteriormente las lineas con los totales y el pie de página. La cabecera del ticket ya se ha creado en vista de diseño en el formulario ya que no cambia nunca.


    Private Sub fTicket_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
        Dim itemCuenta As ItemCuenta
        Dim i As Integer = 0
        Dim yMax As Integer, yPie As Integer

        'Para cada elemento en la lista debemos crear una línea en
        'en el ticket (añadir las etiquetas correspondientes al formulario)
        For Each o As Object In _listaCuenta
            itemCuenta = CType(o, ItemCuenta)
            'Descartamos el primer elemento porque no contiene un artículo,
            'sólo la cantidad entregada por el cliente
            If itemCuenta.nombreArticulo <> "Entregado" Then

                Dim lblDescr As Label = New Label
                lblDescr.Location = New Point(6, 134 + (i * 15))
                lblDescr.Text = itemCuenta.nombreArticulo
                lblDescr.AutoSize = False
                lblDescr.Size = New System.Drawing.Size(117, 13)
                Dim lblCantidad As Label = New Label
                lblCantidad.Location = New Point(135, 134 + (i * 15))
                lblCantidad.Text = itemCuenta.cantidadArticulo.ToString()
                lblCantidad.AutoSize = False
                lblCantidad.Size = New System.Drawing.Size(19, 13)
                lblCantidad.TextAlign = System.Drawing.ContentAlignment.MiddleRight
                Dim lblPVP As Label = New Label
                lblPVP.Location = New Point(160, 134 + (i * 15))
                lblPVP.Text = itemCuenta.precioArticulo.ToString("0.00")
                lblPVP.AutoSize = False
                lblPVP.Size = New System.Drawing.Size(45, 13)
                lblPVP.TextAlign = System.Drawing.ContentAlignment.MiddleRight
                Dim lblImporte As Label = New Label
                lblImporte.Location = New Point(211, 134 + (i * 15))
                lblImporte.Text = itemCuenta.importeArticulo.ToString("0.00")
                lblImporte.AutoSize = False
                lblImporte.Size = New System.Drawing.Size(59, 13)
                lblImporte.TextAlign = System.Drawing.ContentAlignment.MiddleRight

                Me.Controls.Add(lblDescr)
                Me.Controls.Add(lblCantidad)
                Me.Controls.Add(lblPVP)
                Me.Controls.Add(lblImporte)
                i += 1
            End If

        Next

        'Obtenemos la posición de la última línea de la cuenta para desplazar
        yMax = 134 + ((i - 1) * 15)
        yPie = yMax + 30

        'Base Imponible
        Dim lblBaseImp As Label = New Label()
        lblBaseImp.AutoSize = True
        lblBaseImp.Location = New System.Drawing.Point(117, yPie)
        lblBaseImp.Size = New System.Drawing.Size(42, 13)
        lblBaseImp.Text = "BASE IMP."
        Me.Controls.Add(lblBaseImp)

        'Obtenemos el importe total que se corresponde con el IVA
        '
        Dim lblBaseImp2 As Label = New Label()
        lblBaseImp2.AutoSize = False
        lblBaseImp2.Location = New System.Drawing.Point(117, yPie + 17)
        lblBaseImp2.Size = New System.Drawing.Size(56, 13)
        lblBaseImp2.TextAlign = System.Drawing.ContentAlignment.MiddleRight
        lblBaseImp2.Text = Utilidades.CalcularImporteTotalSinIVA(_listaCuenta).ToString("0.00")

        'Importe IVA
        Dim lblImporteIVA As Label = New Label()
        lblImporteIVA.AutoSize = True
        lblImporteIVA.Location = New System.Drawing.Point(195, yPie)
        lblImporteIVA.Size = New System.Drawing.Size(36, 13)
        lblImporteIVA.Text = "IMPORTE IVA"
        Me.Controls.Add(lblImporteIVA)

        'Obtenemos la suma del importe total de los artículos de la cuenta sin IVA
        '
        Dim lblImporteIVA2 As Label = New Label()
        lblImporteIVA2.AutoSize = False
        lblImporteIVA2.Location = New System.Drawing.Point(198, yPie + 17)
        lblImporteIVA2.Size = New System.Drawing.Size(73, 13)
        lblImporteIVA2.TextAlign = System.Drawing.ContentAlignment.MiddleRight
        lblImporteIVA2.Text = Utilidades.CalcularImporteIVA(_listaCuenta).ToString("0.00")

        '
        Me.Controls.Add(lblBaseImp2)
        Me.Controls.Add(lblImporteIVA2)

        '
        Dim lblTotalPagar As Label = New Label()
        lblTotalPagar.AutoSize = True
        lblTotalPagar.Location = New System.Drawing.Point(98, yPie + 50)
        lblTotalPagar.Size = New Size(95, 13)
        lblTotalPagar.Text = "TOTAL A PAGAR:"

        '
        Dim lblTotalPagar2 As Label = New Label()
        lblTotalPagar2.AutoSize = False
        lblTotalPagar2.Location = New System.Drawing.Point(201, yPie + 50)
        lblTotalPagar2.TextAlign = System.Drawing.ContentAlignment.MiddleRight
        lblTotalPagar2.Size = New Size(70, 13)
        lblTotalPagar2.Text = Utilidades.CalcularImporteTotalCuenta(_listaCuenta).ToString("0.00")

        '
        Me.Controls.Add(lblTotalPagar)
        Me.Controls.Add(lblTotalPagar2)

        '
        Dim lblEntregado As Label = New Label()
        lblEntregado.AutoSize = True
        lblEntregado.Location = New System.Drawing.Point(98, yPie + 72)
        lblEntregado.Size = New Size(95, 13)
        lblEntregado.Text = "ENTREGADO:"

        '
        Dim lblEntregado2 As Label = New Label()
        lblEntregado2.AutoSize = False
        lblEntregado2.Location = New System.Drawing.Point(201, yPie + 72)
        lblEntregado2.TextAlign = System.Drawing.ContentAlignment.MiddleRight
        lblEntregado2.Size = New Size(70, 13)
        lblEntregado2.Text = CType(_listaCuenta(0), ItemCuenta).precioArticulo.ToString("0.00")

        '
        Me.Controls.Add(lblEntregado)
        Me.Controls.Add(lblEntregado2)

        '
        Dim lblCambio As Label = New Label()
        lblCambio.AutoSize = True
        lblCambio.Location = New System.Drawing.Point(98, yPie + 94)
        lblCambio.Text = "CAMBIO:"

        '
        Dim lblCambio2 As Label = New Label()
        lblCambio2.AutoSize = False
        lblCambio2.Location = New System.Drawing.Point(201, yPie + 94)
        lblCambio2.TextAlign = System.Drawing.ContentAlignment.MiddleRight
        lblCambio2.Size = New Size(70, 13)
        lblCambio2.Text = (CType(_listaCuenta(0), ItemCuenta).precioArticulo - Utilidades.CalcularImporteTotalCuenta(_listaCuenta)).ToString("0.00")

        '
        Me.Controls.Add(lblCambio)
        Me.Controls.Add(lblCambio2)

        'IVA Incluido
        Dim lblIVAIncluido As Label = New Label()
        lblIVAIncluido.Location = New System.Drawing.Point(193, yPie + 118)
        lblIVAIncluido.Text = "IVA INCLUIDO"

        '
        Me.Controls.Add(lblImporteIVA)
        Me.Controls.Add(lblImporteIVA2)

        'Gracias por su visita
        Dim lblGraciasVisita As Label = New Label()
        lblGraciasVisita.AutoSize = True
        lblGraciasVisita.Location = New System.Drawing.Point(13, yPie + 145)
        lblGraciasVisita.TextAlign = System.Drawing.ContentAlignment.MiddleRight
        'lblGraciasVisita.Size = New Size(78, 13)
        lblGraciasVisita.Text = "GRACIAS POR SU VISITA"

        '
        Me.Controls.Add(lblIVAIncluido)
        Me.Controls.Add(lblGraciasVisita)

        If yPie + 170 > Me.Height Then
            Me.MinimumSize = New Size(Me.Width, yPie + 190)
        End If

        PrintDocument1.Print()
    End Sub


En el código que se muestra a continuación se puede ver como se realiza la impresión del ticket. La idea consiste en dibujar el texto contenido en las etiquetas en el evento e en la misma posición en la que se situaron dichas etiquetas dentro del formulario.
Para llevar a cabo este proceso se recorren todos los controles del formulario y se descartan todos aquellos que no sean del tipo que queremos imprimir. Los que sean del tipo que deseamos imprimir se dibujarán en el objeto e en una posición acorde a la que tienen en el formulario.


    Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e  As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

        DibujarTicket(e.Graphics())
    End Sub





    Private Sub DibujarTicket(ByVal g As Graphics)
        ' Create the source rectangle from the BackgroundImage Bitmap Dimensions
        Dim srcRect As Rectangle = New Rectangle(0, 0, Me.Width, Me.Height)
        Dim nWidth As Integer = Me.Width       
        Dim nHeight As Integer = Me.Height
        Dim destRect As Rectangle = New Rectangle(0, 0, nWidth, CInt(Math.Ceiling(nHeight / 2)))
        Dim lbl As Label

        Dim scalex As Double = 1 * CSng(destRect.Width / srcRect.Width)
        Dim scaley As Double = 2 * CSng(destRect.Height / srcRect.Height)
        Dim aPen As New Pen(Brushes.Black, 1)
        ' Recorre todos los controles. Determina si es un label y dibuja el valor de la propiedad text
        ' en la posición correcta (en función de la propiedad location del control label en cuestión)

        For Each o As Object In Me.Controls
            If o.GetType() = Label1.GetType() Then
                lbl = CType(o, Label)
                If lbl.TextAlign = ContentAlignment.MiddleRight Then
                    g.DrawString(lbl.Text, lbl.Font, Brushes.Black, CSng((lbl.Bounds.Right - 6 * lbl.Text.Length) * scalex),
                                 CSng(lbl.Bounds.Top * scaley), New StringFormat())
                Else
                    g.DrawString(lbl.Text, lbl.Font, Brushes.Black, CSng((lbl.Bounds.Left) * scalex),
                                 CSng(lbl.Bounds.Top * scaley), New StringFormat())

                End If

            End If
        Next

        Me.Close()
    End Sub

No hay comentarios:

Publicar un comentario