C # Ticket printing

0

I would like to ask for help with a program that prints sales tickets, I have made all the printing of tickets but I need to add a header image and a text at the end as a footer, I hope you can help me leave the code to be reviewed and in case someone serves him.

public class CrearTicket
{
    StringBuilder linea = new StringBuilder();
    private Image headerImage = null;
    //Creamos una variable para almacenar el numero maximo de caracteres que permitiremos en el ticket.
    int maxCar = 48, cortar;//Para una impresora ticketera que imprime a 40 columnas. La variable cortar cortara el texto cuando rebase el limte.

    public Image HeaderImage
    {
        get { return headerImage; }
        set { if (headerImage != value) headerImage = value; }
    }

    //Creamos el primer metodo, este dibujara lineas guion.
    public string lineasGuio()
    {
        string lineasGuion = "";
        for (int i = 0; i < maxCar; i++)
        {
            lineasGuion += "-";//Agregara un guio hasta llegar la numero maximo de caracteres.
        }
        return linea.AppendLine(lineasGuion).ToString(); //Devolvemos la lineaGuion
    }

    //Metodo para dibujar una linea con asteriscos
    public string lineasAsteriscos()
    {
        string lineasAsterisco = "";
        for (int i = 0; i < maxCar; i++)
        {
            lineasAsterisco += "*";//Agregara un asterisco hasta llegar la numero maximo de caracteres.
        }
        return linea.AppendLine(lineasAsterisco).ToString(); //Devolvemos la linea con asteriscos
    }

    //Realizamos el mismo procedimiento para dibujar una lineas con el signo igual
    public string lineasIgual()
    {
        string lineasIgual = "";
        for (int i = 0; i < maxCar; i++)
        {
            lineasIgual += "=";//Agregara un igual hasta llegar la numero maximo de caracteres.
        }
        return linea.AppendLine(lineasIgual).ToString(); //Devolvemos la lienas con iguales
    }

    //Creamos un metodo para poner el texto a la izquierda
    public void TextoIzquierda(string texto)
    {
        //Si la longitud del texto es mayor al numero maximo de caracteres permitidos, realizar el siguiente procedimiento.
        if (texto.Length > maxCar)
        {
            int caracterActual = 0;//Nos indicara en que caracter se quedo al bajar el texto a la siguiente linea
            for (int longitudTexto = texto.Length; longitudTexto > maxCar; longitudTexto -= maxCar)
            {
                //Agregamos los fragmentos que salgan del texto
                linea.AppendLine(texto.Substring(caracterActual, maxCar));
                caracterActual += maxCar;
            }
            //agregamos el fragmento restante
            linea.AppendLine(texto.Substring(caracterActual, texto.Length - caracterActual));
        }
        else
        {
            //Si no es mayor solo agregarlo.
            linea.AppendLine(texto);
        }
    }

    //Creamos un metodo para poner texto a la derecha.
    public void TextoDerecha(string texto)
    {
        //Si la longitud del texto es mayor al numero maximo de caracteres permitidos, realizar el siguiente procedimiento.
        if (texto.Length > maxCar)
        {
            int caracterActual = 0;//Nos indicara en que caracter se quedo al bajar el texto a la siguiente linea
            for (int longitudTexto = texto.Length; longitudTexto > maxCar; longitudTexto -= maxCar)
            {
                //Agregamos los fragmentos que salgan del texto
                linea.AppendLine(texto.Substring(caracterActual, maxCar));
                caracterActual += maxCar;
            }
            //Variable para poner espacios restntes
            string espacios = "";
            //Obtenemos la longitud del texto restante.
            for (int i = 0; i < (maxCar - texto.Substring(caracterActual, texto.Length - caracterActual).Length); i++)
            {
                espacios += " ";//Agrega espacios para alinear a la derecha
            }

            //agregamos el fragmento restante, agregamos antes del texto los espacios
            linea.AppendLine(espacios + texto.Substring(caracterActual, texto.Length - caracterActual));
        }
        else
        {
            string espacios = "";
            //Obtenemos la longitud del texto restante.
            for (int i = 0; i < (maxCar - texto.Length); i++)
            {
                espacios += " ";//Agrega espacios para alinear a la derecha
            }
            //Si no es mayor solo agregarlo.
            linea.AppendLine(espacios + texto);
        }
    }

    //Metodo para centrar el texto
    public void TextoCentro(string texto)
    {
        if (texto.Length > maxCar)
        {
            int caracterActual = 0;//Nos indicara en que caracter se quedo al bajar el texto a la siguiente linea
            for (int longitudTexto = texto.Length; longitudTexto > maxCar; longitudTexto -= maxCar)
            {
                //Agregamos los fragmentos que salgan del texto
                linea.AppendLine(texto.Substring(caracterActual, maxCar));
                caracterActual += maxCar;
            }
            //Variable para poner espacios restntes
            string espacios = "";
            //sacamos la cantidad de espacios libres y el resultado lo dividimos entre dos
            int centrar = (maxCar - texto.Substring(caracterActual, texto.Length - caracterActual).Length) / 2;
            //Obtenemos la longitud del texto restante.
            for (int i = 0; i < centrar; i++)
            {
                espacios += " ";//Agrega espacios para centrar
            }

            //agregamos el fragmento restante, agregamos antes del texto los espacios
            linea.AppendLine(espacios + texto.Substring(caracterActual, texto.Length - caracterActual));
        }
        else
        {
            string espacios = "";
            //sacamos la cantidad de espacios libres y el resultado lo dividimos entre dos
            int centrar = (maxCar - texto.Length) / 2;
            //Obtenemos la longitud del texto restante.
            for (int i = 0; i < centrar; i++)
            {
                espacios += " ";//Agrega espacios para centrar
            }

            //agregamos el fragmento restante, agregamos antes del texto los espacios
            linea.AppendLine(espacios + texto);

        }
    }

    //Metodo para poner texto a los extremos
    public void TextoExtremos(string textoIzquierdo, string textoDerecho)
    {
        //variables que utilizaremos
        string textoIzq, textoDer, textoCompleto = "", espacios = "";

        //Si el texto que va a la izquierda es mayor a 18, cortamos el texto.
        if (textoIzquierdo.Length > 22)
        {
            cortar = textoIzquierdo.Length - 22;
            textoIzq = textoIzquierdo.Remove(22, cortar);
        }
        else
        { textoIzq = textoIzquierdo; }

        textoCompleto = textoIzq;//Agregamos el primer texto.

        if (textoDerecho.Length > 24)//Si es mayor a 20 lo cortamos
        {
            cortar = textoDerecho.Length - 24;
            textoDer = textoDerecho.Remove(24, cortar);
        }
        else
        { textoDer = textoDerecho; }

        //Obtenemos el numero de espacios restantes para poner textoDerecho al final
        int nroEspacios = maxCar - (textoIzq.Length + textoDer.Length);
        for (int i = 0; i < nroEspacios; i++)
        {
            espacios += " ";//agrega los espacios para poner textoDerecho al final
        }
        textoCompleto += espacios + textoDerecho;//Agregamos el segundo texto con los espacios para alinearlo a la derecha.
        linea.AppendLine(textoCompleto);//agregamos la linea al ticket, al objeto en si.
    }

    //Creamos el encabezado para los articulos
    public void EncabezadoVenta()
    {
        //Escribimos los espacios para mostrar el articulo. En total tienen que ser 40 caracteres
        linea.AppendLine("ITEM                          |CANT  |PRECIO    ");
    }

    public void Header(object sender, PrintPageEventArgs e)
    {
        Image logo = Image.FromFile("C:\Work\detacoopltda\SucursalVirtual\DetamaticTotem\Images\Logo-Minimalista.png");
        e.Graphics.DrawImage(logo, 0, 0, 238, 73);
    }

    //Metodo para agregar los totales d ela venta
    public void AgregarTotales(string texto, decimal total)
    {
        //Variables que usaremos
        string resumen, valor, textoCompleto, espacios = "";

        if (texto.Length > 29)//Si es mayor a 25 lo cortamos
        {
            cortar = texto.Length - 29;
            resumen = texto.Remove(29, cortar);
        }
        else
        { resumen = texto; }

        textoCompleto = resumen;
        valor = total.ToString("#,#.00");//Agregamos el total previo formateo.

        //Obtenemos el numero de espacios restantes para alinearlos a la derecha
        int nroEspacios = maxCar - (resumen.Length + valor.Length);
        //agregamos los espacios
        for (int i = 0; i < nroEspacios; i++)
        {
            espacios += " ";
        }
        textoCompleto += espacios + valor;
        linea.AppendLine(textoCompleto);
    }

    //Metodo para agreagar articulos al ticket de venta
    public void AgregaArticulo(string articulo, int cant, decimal precio)
    {
        //Valida que cant precio e importe esten dentro del rango.
        if (cant.ToString().Length <= 7 && precio.ToString().Length <= 11)
        {
            string elemento = "", espacios = "";
            bool bandera = false;//Indicara si es la primera linea que se escribe cuando bajemos a la segunda si el nombre del articulo no entra en la primera linea
            int nroEspacios = 0;

            //Si el nombre o descripcion del articulo es mayor a 20, bajar a la siguiente linea
            if (articulo.Length > 24)
            {
                //Colocar la cantidad a la derecha.
                nroEspacios = (7 - cant.ToString().Length);
                espacios = "";
                for (int i = 0; i < nroEspacios; i++)
                {
                    espacios += " ";//Generamos los espacios necesarios para alinear a la derecha
                }
                elemento += espacios + cant.ToString();//agregamos la cantidad con los espacios

                //Colocar el precio a la derecha.
                nroEspacios = (11 - precio.ToString().Length);
                espacios = "";
                for (int i = 0; i < nroEspacios; i++)
                {
                    espacios += " ";//Genera los espacios
                }
                //el operador += indica que agregar mas cadenas a lo que ya existe.
                elemento += espacios + precio.ToString();//Agregamos el precio a la variable elemento

                int caracterActual = 0;//Indicara en que caracter se quedo al bajae a la siguiente linea

                //Por cada 20 caracteres se agregara una linea siguiente
                for (int longitudTexto = articulo.Length; longitudTexto > 24; longitudTexto -= 24)
                {
                    if (bandera == false)//si es false o la primera linea en recorrerer, continuar...
                    {
                        //agregamos los primeros 20 caracteres del nombre del articulos, mas lo que ya tiene la variable elemento
                        linea.AppendLine(articulo.Substring(caracterActual, 24) + elemento);
                        bandera = true;//cambiamos su valor a verdadero
                    }
                    else
                        linea.AppendLine(articulo.Substring(caracterActual, 24));//Solo agrega el nombre del articulo

                    caracterActual += 24;//incrementa en 20 el valor de la variable caracterActual
                }
                //Agrega el resto del fragmento del  nombre del articulo
                linea.AppendLine(articulo.Substring(caracterActual, articulo.Length - caracterActual));

            }
            else //Si no es mayor solo agregarlo, sin dar saltos de lineas
            {
                for (int i = 0; i < (24 - articulo.Length); i++)
                {
                    espacios += " "; //Agrega espacios para completar los 20 caracteres
                }
                elemento = articulo + espacios;

                //Colocar la cantidad a la derecha.
                nroEspacios = (7 - cant.ToString().Length);// +(20 - elemento.Length);
                espacios = "";
                for (int i = 0; i < nroEspacios; i++)
                {
                    espacios += " ";
                }
                elemento += espacios + cant.ToString();

                //Colocar el precio a la derecha.
                nroEspacios = (11 - precio.ToString().Length);
                espacios = "";
                for (int i = 0; i < nroEspacios; i++)
                {
                    espacios += " ";
                }
                elemento += espacios + precio.ToString();

                linea.AppendLine(elemento);//Agregamos todo el elemento: nombre del articulo, cant, precio, importe.
            }
        }
        else
        {
            linea.AppendLine("Los valores ingresados para esta fila");
            linea.AppendLine("superan las columnas soportdas por éste.");
            throw new Exception("Los valores ingresados para algunas filas del ticket\nsuperan las columnas soportdas por éste.");
        }
    }

    //Metodos para enviar secuencias de escape a la impresora
    //Para cortar el ticket
    public void CortaTicket()
    {
        linea.AppendLine("\x1B" + "m"); //Caracteres de corte. Estos comando varian segun el tipo de impresora
        linea.AppendLine("\x1B" + "d" + "\x00"); //Avanza 9 renglones, Tambien varian
    }

    //Para abrir el cajon
    public void AbreCajon()
    {
        //Estos tambien varian, tienen que ever el manual de la impresora para poner los correctos.
        linea.AppendLine("\x1B" + "p" + "\x00" + "\x0F" + "\x96"); //Caracteres de apertura cajon 0
        //linea.AppendLine("\x1B" + "p" + "\x01" + "\x0F" + "\x96"); //Caracteres de apertura cajon 1
    }

    //Para mandara a imprimir el texto a la impresora que le indiquemos.
    public void ImprimirTicket(string impresora)
    {
        //Este metodo recibe el nombre de la impresora a la cual se mandara a imprimir y el texto que se imprimira.
        //Usaremos un código que nos proporciona Microsoft. https://support.microsoft.com/es-es/kb/322091

        RawPrinterHelper.SendStringToPrinter(impresora, linea.ToString()); //Imprime texto.
        //linea.Clear();//Al cabar de imprimir limpia la linea de todo el texto agregado.
    }
}

//Clase para mandara a imprimir texto plano a la impresora
public class RawPrinterHelper
{
    // Structure and API declarions:
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class DOCINFOA
    {
        [MarshalAs(UnmanagedType.LPStr)]
        public string pDocName;
        [MarshalAs(UnmanagedType.LPStr)]
        public string pOutputFile;
        [MarshalAs(UnmanagedType.LPStr)]
        public string pDataType;
    }
    [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);

    [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool ClosePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);

    [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool EndDocPrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool StartPagePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool EndPagePrinter(IntPtr hPrinter);

    [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);

    // SendBytesToPrinter()
    // When the function is given a printer name and an unmanaged array
    // of bytes, the function sends those bytes to the print queue.
    // Returns true on success, false on failure.
    public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
    {
        Int32 dwError = 0, dwWritten = 0;
        IntPtr hPrinter = new IntPtr(0);
        DOCINFOA di = new DOCINFOA();
        bool bSuccess = false; // Assume failure unless you specifically succeed.

        di.pDocName = "Ticket de Venta";//Este es el nombre con el que guarda el archivo en caso de no imprimir a la impresora fisica.
        di.pDataType = "RAW";//de tipo texto plano
        //di.pOutputFile = "D:\ticket.txt";

        // Open the printer.
        if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
        {
            // Start a document.
            if (StartDocPrinter(hPrinter, 1, di))
            {
                // Start a page.
                if (StartPagePrinter(hPrinter))
                {
                    // Write your bytes.
                    bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                    EndPagePrinter(hPrinter);
                }
                EndDocPrinter(hPrinter);
            }
            ClosePrinter(hPrinter);
        }
        // If you did not succeed, GetLastError may give more information
        // about why not.
        if (bSuccess == false)
        {
            dwError = Marshal.GetLastWin32Error();
        }
        return bSuccess;
    }

    public static bool SendStringToPrinter(string szPrinterName, string szString)
    {
        IntPtr pBytes;
        Int32 dwCount;
        // How many characters are in the string?
        dwCount = szString.Length;
        // Assume that the printer is expecting ANSI text, and then convert
        // the string to ANSI text.
        pBytes = Marshal.StringToCoTaskMemAnsi(szString);
        // Send the converted ANSI string to the printer.
        SendBytesToPrinter(szPrinterName, pBytes, dwCount);
        Marshal.FreeCoTaskMem(pBytes);
        return true;
    }
}

To print it is called as follows:

CrearTicket ticket = new CrearTicket();
ticket.TextoIzquierda(" ");
        ticket.TextoCentro("TICKET CIERRE DE CAJA");
        ticket.TextoIzquierda(" ");
        ticket.TextoExtremos("FECHA : " + DateTime.Now.Date, "HORA : " + DateTime.Now.Hour);
        ticket.TextoIzquierda(" ");
        ticket.EncabezadoVenta();
        ticket.lineasGuio();
        //foreach (DataGridViewRow fila in dataGridView1.Rows)
        //{
        //    ticket.AgregaArticulo(fila.Cells[1].Value.ToString(), int.Parse(fila.Cells[0].Value.ToString()), decimal.Parse(fila.Cells[3].Value.ToString()));
        //}
        ticket.lineasIgual();
        ticket.AgregarTotales("          TOTAL COMPRADO : $ ", decimal.Parse("1000000"));
        ticket.AgregarTotales("          TOTAL VENDIDO  : $ ", decimal.Parse("1000000"));
        ticket.TextoIzquierda(" ");
        ticket.AgregarTotales("          GANANCIA       : $ ", decimal.Parse("1000000000"));
        ticket.TextoIzquierda(" ");
        ticket.TextoIzquierda(" ");
        ticket.TextoIzquierda(" ");
        ticket.TextoIzquierda(" ");
        ticket.TextoIzquierda(" ");
        ticket.TextoIzquierda(" ");
        ticket.ImprimirTicket("EPSON TM-T20 Receipt"); 
    
asked by vcasas 30.07.2018 в 19:59
source

1 answer

0

You have to review the following method:

public void ImprimirTicket(string impresora)
{
    RawPrinterHelper.SendStringToPrinter(impresora, linea.ToString()); 
}

the method that you are using here only prints strings, I would look for a method that would print images like:.

public void ImprimirTicket(string impresora)
{
    RawPrinterHelper.SendFileToPrinter(impresora, "Imagen.png")
    RawPrinterHelper.SendStringToPrinter(impresora, linea.ToString()); 
}

to add the footnote at the end would be something like this:

    ticket.TextoCentro("Pie de Pagina");

before the printing line:

ticket.PrintTicket ("EPSON TM-T20 Receipt");

    
answered by 30.07.2018 в 20:34