0

I need to create 2 column mailing labels in itextsharp PDF. I already have created the logic for 1 column labels and it is working fine. As, I am unable to understand how to do it for labels with 2 column. Pl consider the below scenario,

I need to do the logic like below format

enter image description here

Code which I have

        public Stream CreatePDF(Label _label)
    {
        FontFactory.RegisterDirectories();
        Rectangle pageSize;
        switch (_label.PageSize)
        {
            case Enums.PageSize.A4:
                pageSize = iTextSharp.text.PageSize.A4;
                break;
            default:
                pageSize = iTextSharp.text.PageSize.A4;
                break;
        }

        var doc = new Document(pageSize,
                               _label.PageMarginLeft,
                               _label.PageMarginRight,
                               _label.PageMarginTop,
                               _label.PageMarginBottom);

        var output = new MemoryStream();

        var writer = PdfWriter.GetInstance(doc, output);

        writer.CloseStream = false;
        doc.Open();
        var numOfCols = _label.LabelsPerRow + (_label.LabelsPerRow - 1);
        var tbl = new PdfPTable(numOfCols);
        var colWidths = new List<float>();
        for (int i = 1; i <= numOfCols; i++)
        {
            if (i % 2 > 0)
            {
                colWidths.Add(_label.Width);
            }
            else
            {
                colWidths.Add(_label.HorizontalGapWidth);
            }
        }

        var w = iTextSharp.text.PageSize.A4.Width - (doc.LeftMargin + doc.RightMargin);
        var h = iTextSharp.text.PageSize.A4.Height - (doc.TopMargin + doc.BottomMargin);
        var size = new iTextSharp.text.Rectangle(w, h);
        tbl.SetWidthPercentage(colWidths.ToArray(), size);
        var val = System.IO.File.ReadLines("C:\\Users\\lenovo\\Desktop\\test stock\\testing3.txt").ToArray();
        int cnt = 0;
        for (int iRow = 0; iRow < ((val.Count() / _label.LabelsPerRow) + 1); iRow++)
        {

            var rowCells = new List<PdfPCell>();
            for (int iCol = 1; iCol <= numOfCols; iCol++)
            {
                if (val.Count() > cnt)
                {
                    if (iCol % 2 > 0)
                    {
                        var cellContent = new Phrase();
                        if (val[cnt] != "")
                        {
                            var fontHeader = FontFactory.GetFont("Verdana", BaseFont.CP1250, true, 12, 0);
                            cellContent.Add(new Chunk("Default Header\n\n", fontHeader));
                            Code39BarcodeDraw barcode39 = BarcodeDrawFactory.Code39WithoutChecksum;
                            System.Drawing.Image img = barcode39.Draw(val[cnt], 25);
                            var pdfImg = iTextSharp.text.Image.GetInstance(ReadImage(img));
                            var width = pdfImg.PlainWidth;
                            if (width > colWidths.ToArray()[0])
                                pdfImg.ScaleAbsoluteWidth(colWidths.ToArray()[0] - 5);
                            cellContent.Add(new Chunk(pdfImg, 0, 0, true));
                            var font = FontFactory.GetFont("Verdana", BaseFont.CP1250, true, 12, 0);
                            cellContent.Add(new Chunk("\n\n" + val[cnt], font));
                        }
                        cnt += 1;
                        var cell = new PdfPCell(cellContent);
                        cell.FixedHeight = _label.Height;
                        cell.HorizontalAlignment = Element.ALIGN_CENTER;
                        cell.Border = IncludeLabelBorders ? Rectangle.BOX : Rectangle.NO_BORDER;
                        rowCells.Add(cell);
                    }
                    else
                    {
                        var gapCell = new PdfPCell();
                        gapCell.FixedHeight = _label.Height;
                        gapCell.Border = Rectangle.NO_BORDER;
                        rowCells.Add(gapCell);
                    }
                }
                else
                {
                    var gapCell = new PdfPCell();
                    gapCell.FixedHeight = _label.Height;
                    gapCell.Border = Rectangle.NO_BORDER;
                    rowCells.Add(gapCell);
                }
            }
            tbl.Rows.Add(new PdfPRow(rowCells.ToArray()));
            if ((iRow + 1) < _label.LabelRowsPerPage && _label.VerticalGapHeight > 0)
            {
                tbl.Rows.Add(CreateGapRow(numOfCols));
            }

        }
        doc.Add(tbl);
        doc.Close();
        output.Position = 0;
        return output;

    }
Chris Haas
  • 53,986
  • 12
  • 141
  • 274
DonMax
  • 970
  • 3
  • 12
  • 47
  • Where did you get that code? It's very awkward. Why are you using `PdfPRow`. There is no need to use that class, is there? – Bruno Lowagie Aug 19 '15 at 04:46
  • I got the code from here https://github.com/wheelibin/SharpPDFLabel#readme. I changed a bit of code from that. – DonMax Aug 19 '15 at 05:58
  • That's not the official documentation, isn't it? I can only repeat what I've said before: there is no reason why you'd need `PdfPRow` in your code. – Bruno Lowagie Aug 19 '15 at 06:27
  • I rewrote the SharpPDFLabel code this week as I needed it to be a lot more flexible (and to work). https://github.com/finalcut/SharpPDFLabel I added the ability to specify the contents of each individual label if you want (or to continue creating a sheet of identical labels too). – Bill Rawlinson Nov 12 '15 at 21:06

1 Answers1

0

I don't really feel like re-writing someone else's code from 4 years ago but in general, if you want to have multiple tables in a row you can either use the PdfPTable.WriteSelectedRows() method or you can use a second outer table.

PdfPTable.WriteSelectedRows() is very powerful but it will be completely up to you to calculate things. If you literally need to create Avery labels that align perfectly to pre-formed stickers then this might be the only path that you can guarantee these things.

If you want (as my friend would say) "the emotion of" Avery labels then a second outer table might work just fine for you. The below code shows this off in general but it doesn't go into specifics of defining table and cell dimensions since you already have the code for that.

I removed the PdfPRow since, as Bruno said, there's almost never a good reason to ever use that. I would also recommend not passing Stream objects around because you need to deal with things like Position, CanRead, CanWrite and "buffers". Instead, I generally recommend operating on a Stream and then grabbing the bytes at the end which you then can pass on. The rest of the code is commented pretty heavily but if you have any question just let me know.

//Number of labels across
var labelsAcross = 2;

//Total number of labels that you need.
//This variable could come from a .Count() or you could
//remove it and customize the for loop below
var labelCount = 7;

//We're going to dump our PDF into this when done
Byte[] bytes;

//Standard iTextSharp setup here, nothing special
using (var ms = new MemoryStream()) {

    //Change the margins if you want to
    using (var doc = new Document()) {
        using (var writer = PdfWriter.GetInstance(doc, ms)) {
            doc.Open();

            //Create a master outer table to hold everything
            var masterTable = new PdfPTable(labelsAcross);

            //We don't want borders on the master table
            //The DefaultCell is also where you can adjust
            //padding between labels themselves
            masterTable.DefaultCell.BorderWidth = 0;

            //Create a bunch of labels
            for (var i = 1; i <= labelCount; i++) {

                var t = new PdfPTable(2);
                t.AddCell("This is my left cell");
                t.AddCell("This is my right cell");

                masterTable.AddCell(t);
            }

            //Just in case we don't have enough cells
            //tell the master table to "fill in the blanks"
            masterTable.CompleteRow();

            //Add the master table to the document
            doc.Add(masterTable);
            doc.Close();
        }
    }

    //Right before closing out our stream grab the underlying byte array
    bytes = ms.ToArray();
}

//For demo purposes, write the bytes to the desktop
System.IO.File.WriteAllBytes(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Test.pdf"), bytes);
Chris Haas
  • 53,986
  • 12
  • 141
  • 274
  • How to set the height, width of the each table?? as well as I need to set the font dynamically to the table cell content. – DonMax Aug 25 '15 at 02:04
  • See [this for table height](http://stackoverflow.com/a/25287384/231316). See [this](http://stackoverflow.com/q/1481139/231316) and [this](http://stackoverflow.com/a/9208937/231316) for table widths. See [this for registering fonts](http://stackoverflow.com/q/24007492/231316). See [this](http://stackoverflow.com/a/12338081/231316) and [this](http://itextpdf.com/examples/iia.php?id=212) for font usage. – Chris Haas Aug 25 '15 at 13:11
  • Also, check out [iText's website](http://itextpdf.com/learn) which has some great resources for getting started with iText and iTextSharp. – Chris Haas Aug 25 '15 at 13:11