Nota: Se trata de una adaptación a la lógica de otro autor que encontré en internet.
Se requiere utilizar la librería iTextSharp la cual puede buscarse en internet.
Aqui una imagen de como es la apariencia:
Para facilitarles el proceso, aqui les dejo el código en una clase y mas abajo les explico acerca de su utlización:
Implementación:
using System; using System.Collections; using iTextSharp; using iTextSharp.text; using iTextSharp.text.pdf; using System.IO; namespace TyroDeveloperDLL{ public class TicketPDF{ public TicketPDF(){ myDocument.AddAuthor("TyroDeveloper"); myDocument.AddCreator("JUAN GABRIEL CASTILLO TURRUBIATES"); myDocument.AddTitle("Ticket de Venta"); } PdfWriter writer = null; PdfContentByte cb=null; private string headerImage = ""; bool _DrawItemHeaders = true; int count = 0; string path = ""; string file_name = ""; int maxChar = 40; int maxCharDescription = 20; int imageHeight = 0; float leftMargin = 0; float topMargin = 5; static int fontSize = 7; static BaseFont bfCourier = BaseFont.CreateFont(BaseFont.COURIER, BaseFont.CP1252, false); static Font font = new Font(bfCourier, fontSize, Font.NORMAL, Color.BLACK); Document myDocument = new Document(PageSize.LETTER); //Aqui se ponen todos los objetos string line = ""; #region Properties public String Path { get { return path; } set { path = value; } } public String FileName { get { return file_name; } set { file_name = value; } } public String FullFileName { get { return(String.Format("{0}{1}", path, file_name)); } } public String HeaderImage { get { return headerImage; } set { if (headerImage != value) headerImage = value; } } public int MaxChar { get { return maxChar; } set { if (value != maxChar) maxChar = value; } } public bool DrawItemHeaders{ set { _DrawItemHeaders = value; } } public int MaxCharDescription { get { return maxCharDescription; } set { if (value != maxCharDescription) maxCharDescription = value; } } public int FontSize { get { return fontSize; } set { if (value != fontSize) fontSize = value; } } public Font FontName { get { return font; } set { if (value != font) font = value; } } #endregion public void AddHeaderLine(string line) { headerLines.Add(line); } public void AddSubHeaderLine(string line){ subHeaderLines.Add(line); } public void AddItem(string cantidad, string item, string price){ items.Add(newItem.GenerateItem(cantidad, item, price)); } public void AddTotal(string name, string price){ totales.Add(newTotal.GenerateTotal(name, price)); } public void AddFooterLine(string line){ footerLines.Add(line); } private string AlignRightText(int lenght){ string espacios = ""; int spaces = maxChar - lenght; for (int x = 0; x < spaces; x++) espacios += " "; return espacios; } private string DottedLine(){ string dotted = ""; for (int x = 0; x < maxChar; x++) dotted += "="; return dotted; } public bool Print() { try{ //aqui para generar el PDF writer = PdfWriter.GetInstance(myDocument, myDocument.Open(); cb = writer.DirectContent; cb.SetFontAndSize(font.BaseFont, fontSize); cb.BeginText(); DrawImage(); DrawHeader(); DrawSubHeader(); DrawItems(); DrawTotales(); DrawFooter(); cb.EndText(); myDocument.Close(); return true; } catch (Exception ex) { throw (ex); } } private float YPosition(){ return (myDocument.PageSize.Height - (topMargin + (count * font.CalculatedSize + imageHeight))); } private void DrawImage() { try{ if ((headerImage != null) && (headerImage != "")){ if (File.Exists(headerImage)) { Image logo = Image.GetInstance(headerImage); double height = ((double)logo.Height / 58) * 15; imageHeight = (int)Math.Round(height) + 3; logo.SetAbsolutePosition(0, myDocument.PageSize.Height - imageHeight); logo.ScaleToFit(logo.Width,imageHeight); myDocument.Add(logo); } } } catch (Exception ex){throw (ex);} } private void DrawHeader(){ try{ foreach (string header in headerLines){ if (header.Length > maxChar) { int currentChar = 0; int headerLenght = header.Length; while (headerLenght > maxChar){ line = header.Substring(currentChar, maxChar); cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line); count++; currentChar += maxChar; headerLenght -= maxChar; } line = header; cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line.Substring(currentChar, line.Length - currentChar)); count++; } else{ line = header; cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line); count++; } } DrawEspacio(); } catch (Exception ex) { throw (ex); } } private void DrawSubHeader() { try{ line = DottedLine(); cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line); DrawEspacio(); foreach (string subHeader in subHeaderLines){ if (subHeader.Length > maxChar){ int currentChar = 0; int subHeaderLenght = subHeader.Length; while (subHeaderLenght > maxChar){ line = subHeader; cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line.Substring(currentChar, maxChar)); count++; currentChar += maxChar; subHeaderLenght -= maxChar; } line = subHeader; cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line.Substring(currentChar, line.Length - currentChar)); count++; line = DottedLine(); cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line); DrawEspacio(); } else { line = subHeader; cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line); count++; line = DottedLine(); cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line); count++; } } DrawEspacio(); } catch (Exception ex) { throw (ex); } } private void DrawItems() { if (_DrawItemHeaders){ cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText("CANT DESCRIPCION IMPORTE"); } count++; DrawEspacio(); foreach (string item in items){ line = ordIt.GetItemCantidad(item); cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line); line = ordIt.GetItemPrice(item); line = AlignRightText(line.Length) + line; cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line); string name = ordIt.GetItemName(item); leftMargin = 0; if (name.Length > maxCharDescription) { int currentChar = 0; int itemLenght = name.Length; while (itemLenght > maxCharDescription){ line = ordIt.GetItemName(item); cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(" " + line.Substring(currentChar, maxCharDescription)); count++; currentChar += maxCharDescription; itemLenght -= maxCharDescription; } line = ordIt.GetItemName(item); cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(" " + line.Substring(currentChar, maxCharDescription)); count++; } else{ cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(" " + ordIt.GetItemName(item)); count++; } } leftMargin = 0; DrawEspacio(); line = DottedLine(); cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line); count++; DrawEspacio(); } private void DrawTotales(){ foreach (string total in totales){ line = ordTot.GetTotalCantidad(total); line = AlignRightText(line.Length) + line; cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line); leftMargin = 0; line = "" + ordTot.GetTotalName(total); cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line); count++; } leftMargin = 0; DrawEspacio(); DrawEspacio(); } private void DrawFooter(){ foreach (string footer in footerLines){ if (footer.Length > maxChar){ int currentChar = 0; int footerLenght = footer.Length; while (footerLenght > maxChar){ line = footer; cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line.Substring(currentChar, maxChar)); count++; currentChar += maxChar; footerLenght -= maxChar; } line = footer; cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line.Substring(currentChar, maxChar)); count++; } else { line = footer; cb.SetTextMatrix(leftMargin, YPosition()); cb.ShowText(line); count++; } } leftMargin = 0; DrawEspacio(); } private void DrawEspacio(){ line = ""; cb.SetTextMatrix(leftMargin, YPosition()); cb.SetFontAndSize(font.BaseFont, fontSize); cb.ShowText(line); count++; } } public class TicketOrderItem{ public TicketOrderItem(char delimit){ } public string GetItemCantidad(string TicketOrderItem){ string[] delimitado = TicketOrderItem.Split(delimitador); return delimitado[0]; } public string GetItemName(string TicketOrderItem){ string[] delimitado = TicketOrderItem.Split(delimitador); return delimitado[1]; } public string GetItemPrice(string TicketOrderItem) { string[] delimitado = TicketOrderItem.Split(delimitador); return delimitado[2]; } public string GenerateItem(string cantidad, string itemName, string price){ return cantidad + delimitador[0] + itemName + delimitador[0] + price; } } public class TicketOrderTotal{ public TicketOrderTotal(char delimit){ } public string GetTotalName(string totalItem){ string[] delimitado = totalItem.Split(delimitador); return delimitado[0]; } public string GetTotalCantidad(string totalItem){ string[] delimitado = totalItem.Split(delimitador); return delimitado[1]; } public string GenerateTotal(string totalName, string price){ return totalName + delimitador[0] + price; } } }
Nota: Este es un ejemplo tal y cual lo utlicé para una aplicación web, el programador debe adaptar este código a sus necesidades.
public bool ImprimeTicket(int prmFolioTicket, string user, string path, string fileName, string prmHeaderImage) { try { double varEFECTIVO = 0; double varCAMBIO = 0; string varTOTAL_LETRA = ""; double varTOTAL = 0; double varDESCUENTO = 0; double varIVA = 0; ticket.Path = path; ticket.FileName = fileName; ticket.HeaderImage = prmHeaderImage; ticket.AddHeaderLine(clsMain.WebConfig("TICKET_HEADER_01")); ticket.AddHeaderLine(clsMain.WebConfig("TICKET_HEADER_02")); ticket.AddHeaderLine(clsMain.WebConfig("TICKET_HEADER_03")); ticket.AddHeaderLine(clsMain.WebConfig("TICKET_HEADER_04")); ticket.AddHeaderLine(clsMain.WebConfig("TICKET_HEADER_05")); cnnReporte.Open(); SqlCommand cmdReporte = cmdReporte.CommandType = CommandType.StoredProcedure; //params cmdReporte.Parameters.Add("@ID_VENTA", SqlDbType.Int).Value = prmFolioTicket; SqlDataReader drReporte; drReporte = cmdReporte.ExecuteReader(); while (drReporte.Read()) { //El metodo AddSubHeaderLine es lo mismo al //de AddHeaderLine con la diferencia //de que al final de cada linea //agrega una linea punteada "==========" ticket.AddSubHeaderLine("Caja # " + drReporte["CAJA"].ToString() + " - Ticket # " + prmFolioTicket.ToString() + ""); ticket.AddSubHeaderLine("Le atendió: " + drReporte["CAJERO"].ToString() + ""); ticket.AddSubHeaderLine("Fecha y Hora: " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString()); ticket.AddSubHeaderLine("Cliente: " + drReporte["CLIENTE"].ToString() + ""); varEFECTIVO = Convert.ToDouble(drReporte["EFECTIVO"]); varCAMBIO = Convert.ToDouble(drReporte["CAMBIO"]); varTOTAL_LETRA = drReporte["TOTAL_LETRA"].ToString(); } ////Details drReporte.Close(); cmdReporte.Parameters.Clear(); cmdReporte.CommandText = "proc_VENTA_DETALLE_TICKET"; //params cmdReporte.Parameters.Add("@ID_VENTA", SqlDbType.Int).Value = prmFolioTicket; drReporte = cmdReporte.ExecuteReader(); while (drReporte.Read()) { //El metodo AddItem requeire 3 parametros, //el primero es cantidad, el segundo es la descripcion //del producto y el tercero es el precio if (drReporte["PRODUCTO"].ToString().Length > 11) { ticket.AddItem(drReporte["CANTIDAD"].ToString(), drReporte["PRODUCTO"].ToString().Substring(0, 11), String.Format("{0:C}", Convert.ToDouble(drReporte["CANTIDAD"]) * Convert.ToDouble(drReporte["PRECIO_VENTA"]))); } else { ticket.AddItem(drReporte["CANTIDAD"].ToString(), drReporte["PRODUCTO"].ToString(), String.Format("{0:C}", Convert.ToDouble(drReporte["CANTIDAD"]) * Convert.ToDouble(drReporte["PRECIO_VENTA"]))); } varTOTAL += Convert.ToDouble(drReporte["TOTAL"]); varDESCUENTO += Convert.ToDouble(drReporte["DESCUENTO"]); varIVA += Convert.ToDouble(drReporte["IMPUESTO_DOS"]); } drReporte.Close(); cmdReporte.Dispose(); cnnReporte.Close(); cnnReporte.Dispose(); //El metodo AddTotal requiere 2 parametros, //la descripcion del total, y el precio ticket.AddTotal("SUBTOTAL", String.Format("{0:C}", varTOTAL - varIVA)); ticket.AddTotal("IVA", String.Format("{0:C}", varIVA)); ticket.AddTotal("TOTAL", String.Format("{0:C}", varTOTAL + varDESCUENTO)); ticket.AddTotal("DESCUENTO", String.Format("{0:C}", -varDESCUENTO)); ticket.AddTotal("GRAN TOTAL", String.Format("{0:C}", varTOTAL)); ticket.AddTotal("", "");//Ponemos un total //en blanco que sirve de espacio ticket.AddTotal("RECIBIDO", String.Format("{0:C}", varEFECTIVO)); ticket.AddTotal("CAMBIO", String.Format("{0:C}", varCAMBIO)); ticket.AddTotal("", "");//Ponemos un total //en blanco que sirve de espacio ticket.AddTotal("USTED AHORRA", String.Format("{0:C}", varDESCUENTO)); //El metodo AddFooterLine funciona igual que la cabecera ticket.AddFooterLine(clsMain.WebConfig("TICKET_FOOTER_01")); ticket.AddFooterLine(clsMain.WebConfig("TICKET_FOOTER_02")); ticket.AddFooterLine(clsMain.WebConfig("TICKET_FOOTER_03")); ticket.AddFooterLine(clsMain.WebConfig("TICKET_FOOTER_04")); ticket.AddFooterLine(clsMain.WebConfig("TICKET_FOOTER_05")); //Generamos if (ticket.Print()) { return (true); } else { return false; } } catch (Exception ex) { throw (ex); } finally { cnnReporte.Close(); } }
Listo, espero que les sirva.
Eres un tigre!!, Gracias Hermano.
ResponderEliminargracias, pídeme lo que quieras, hasta mi virginidad te doy.
ResponderEliminarhola como puedo hacerle para que aparesca completo el nombre del producto... te lo agradeceria mnucho si me explicaras un poco
ResponderEliminarjajjaja oye men muy buena pagina la neta y este queria saber como le puedo hacer mas o menos as de cuenta que tengo una base de datos de Mysql y que los datos de una tabla sean las ventas como podria irlos agregando ? tenia pensado hacerlo como tipo listbox y que mientras vayas agregando vantas vaya creciendo el largo del ticket y si quitas que logico disminuya el tamaño me podrias hechar una mano porfa?
ResponderEliminarpodrias contestar a este mail:
dar5_0094@hotmail.com
Porfavor men ayudame
Hola estoy usando c# 2008 y marca de color rojo en:
ResponderEliminarPath
FileName
HeaderImage
AddHeaderLine
y muchos mas que son de ticket.
Hasme tuyo !!!
ResponderEliminarlas veces que quieras!
ResponderEliminarEste tipo de impresión puede mandar secuencias de escape a la impresora para cortar el ticket y abrir el cajón de dinero
ResponderEliminarno lo se. Sin embargo, cuando este conectada la miniprinter con el cajón de dinero. Se abrirá el cajon de manera automática
EliminarQuisiera saber si se pueden agregar n cantidad de items en el detalle
ResponderEliminary si es posible que sea impreso en una impresora de tickets
Si es posible... Es probable que haga un espacio cuando encuentre salto de página tamaño carta
EliminarJuan buenas tardes, tengo un detalle que en algunas impresoras que no puedo configurar el top y bottom al inicio deja un espacio de 12 cm en blanco antes de imprimir, como pudiera corregir ese detalle
ResponderEliminargracias por tu ayuda
Hola
ResponderEliminartendrás algún ejemplo de como mandarlo imprimir a un miniprinter?
me gustaría imprimirlo en mi impresora térmica no en un pdf
mi correo es:
kike_master@hotmail.com
eres la ostia tio :v
ResponderEliminarQuizas te interese! Actualizado
Eliminarhttps://www.youtube.com/watch?v=I924aw5-CZk
Hola, la primera vez me funciona bien, posteriormente me dice que no se puede acceder al archivo cerrado, alguna idea?
ResponderEliminarcuando hay varios detalles se corta en pdf
ResponderEliminarLe hice algunos ajustes para adaptarlo a mis necesidades y funciona perfecto, lo estoy usando con .NET Core 3
ResponderEliminarSaludos amigos, donde indico el nombre de la impresora.
ResponderEliminarNo me ubico en esta parte.Si me podrian ayudar gracias.
public bool ImprimeTicket(int prmFolioTicket, string user, string path,string fileName, string prmHeaderImage)
{ }