2016-03-05 2 views
0

У меня есть шаблон PDF, который содержит данные формы, которые являются постоянной высотой. В соответствии с этими данными мне нужно добавить таблицу с динамической высотой. В этой таблице может быть только одна строка и одна строка, или она может содержать 1000 строк и/или 1-1000 строк.iTextSharp Таблица Span Pages с использованием Stamper

Это код, который у меня есть, который отлично работает, за исключением того, что таблица не будет переходить на новую страницу, если она большая.

private void InsertCurrentNeightborsOlder(string FileName) 
{ 
//Create new PDF document 
Document document = new Document(PageSize.LETTER, 20f, 20f, 0f, 20f); 
iTextSharp.text.Font fntTableFontHdr = FontFactory.GetFont("Times New Roman", 8, iTextSharp.text.Font.BOLD, BaseColor.BLACK); 
iTextSharp.text.Font fntTableFont = FontFactory.GetFont("Times New Roman", 8, iTextSharp.text.Font.NORMAL, BaseColor.BLACK); 


try { 
    PdfWriter.GetInstance(document, new FileStream(FileName, FileMode.Create)); 
    PdfPTable nTbl = new PdfPTable(5); 

    // Build the header 
    PdfPCell CellOneHdr = new PdfPCell(new Phrase("Name", fntTableFontHdr)); 
    nTbl.AddCell(CellOneHdr); 
    PdfPCell CellTwoHdr = new PdfPCell(new Phrase("Address", fntTableFontHdr)); 
    CellTwoHdr.HorizontalAlignment = Element.ALIGN_CENTER; 
    nTbl.AddCell(CellTwoHdr); 
    PdfPCell CellTreeHdr = new PdfPCell(new Phrase("Phone #", fntTableFontHdr)); 
    CellTreeHdr.HorizontalAlignment = Element.ALIGN_CENTER; 
    nTbl.AddCell(CellTreeHdr); 
    PdfPCell CellFouHdr = new PdfPCell(new Phrase("Method", fntTableFontHdr)); 
    CellFouHdr.HorizontalAlignment = Element.ALIGN_CENTER; 
    nTbl.AddCell(CellFouHdr); 
    PdfPCell CellFivHdr = new PdfPCell(new Phrase("Comments", fntTableFontHdr)); 
    nTbl.AddCell(CellFivHdr); 


    //create column sizes 
    float[] rows = { 
     100f, 
     100f, 
     70f, 
     100f, 
     100f 
    }; 
    //set row width 
    nTbl.SetTotalWidth(rows); 

    nTbl.CompleteRow(); 

    // Add the Cells to the data table 
    if (ReportDataSet.Tables("CurrentNeighbors").Rows.Count > 0) { 
     foreach (DataRow r in ReportDataSet.Tables("CurrentNeighbors").Rows) { 
      nTbl.AddCell(new Paragraph(r("FullName").ToString, fntTableFont)); 
      nTbl.AddCell(new Paragraph(r("Address").ToString, fntTableFont)); 

      PdfPCell cell = new PdfPCell(new Paragraph(r("PhoneNumber").ToString, fntTableFont)); 
      cell.HorizontalAlignment = 1; 
      nTbl.AddCell(cell); 


      // nTbl.AddCell(New Paragraph(r("PhoneNumber").ToString, fntTableFont)) 
      nTbl.AddCell(new Paragraph(r("ContactMethod").ToString, fntTableFont)); 
      nTbl.AddCell(new Paragraph(r("Comments").ToString, fntTableFont)); 
     } 
    } else { 
     nTbl.AddCell(new Paragraph("Nothing Entered", fntTableFont)); 
     nTbl.AddCell(new Paragraph("    ", fntTableFont)); 
     nTbl.AddCell(new Paragraph("    ", fntTableFont)); 
     nTbl.AddCell(new Paragraph("    ", fntTableFont)); 
     nTbl.AddCell(new Paragraph("    ", fntTableFont)); 
    } 
    document.Open(); 

    nTbl.HeaderRows = 1; 
    nTbl.SplitLate = false; 
    document.Add(nTbl); 

} catch (Exception ex) { 
} finally { 
    document.Close(); 
} 

}

«FileName» Параметр передается содержит местоположение исходного файла, который я хочу, чтобы добавить таблицу.

Возможно ли это сделать, и если да, то что мне не хватает?

EDIT:

Вот еще одна функция, которую я попробовал (с помощью Stamper). Может быть, я далеко на этом тоже, но это то, что я пытаюсь выяснить:

private void InsertCurrentNeightbors(string FileName) 
{ 
// This is the Temporary File that we are working with. This file already has data in it 
string oldFile = FileName; 
// Create a new Temporary file that we can write to 
string newFile = My.Computer.FileSystem.GetTempFileName(); 
iTextSharp.text.pdf.PdfReader reader = null; 
iTextSharp.text.pdf.PdfStamper stamper = null; 
iTextSharp.text.pdf.PdfContentByte cb = null; 
iTextSharp.text.Rectangle rect = null; 
int pageCount = 0; 

try { 
    reader = new iTextSharp.text.pdf.PdfReader(oldFile); 
    rect = reader.GetPageSizeWithRotation(1); 
    stamper = new iTextSharp.text.pdf.PdfStamper(reader, new System.IO.FileStream(newFile, System.IO.FileMode.Create)); 
    iTextSharp.text.Font fntTableFontHdr = FontFactory.GetFont("Times New Roman", 8, iTextSharp.text.Font.BOLD, BaseColor.BLACK); 
    iTextSharp.text.Font fntTableFont = FontFactory.GetFont("Times New Roman", 8, iTextSharp.text.Font.NORMAL, BaseColor.BLACK); 

    cb = stamper.GetOverContent(1); 
    dynamic ct = new ColumnText(cb); 
    ct.Canvas = stamper.GetOverContent(reader.NumberOfPages + 1); 
    ct.Alignment = Element.ALIGN_LEFT; 
    ct.SetSimpleColumn(70, 36, PageSize.A4.Width - 36, PageSize.A4.Height - 300); 
    PdfPTable nTbl = new PdfPTable(5); 

    // Build the header 
    PdfPCell CellOneHdr = new PdfPCell(new Phrase("Name", fntTableFontHdr)); 
    nTbl.AddCell(CellOneHdr); 
    PdfPCell CellTwoHdr = new PdfPCell(new Phrase("Address", fntTableFontHdr)); 
    CellTwoHdr.HorizontalAlignment = Element.ALIGN_CENTER; 
    nTbl.AddCell(CellTwoHdr); 
    PdfPCell CellTreeHdr = new PdfPCell(new Phrase("Phone #", fntTableFontHdr)); 
    CellTreeHdr.HorizontalAlignment = Element.ALIGN_CENTER; 
    nTbl.AddCell(CellTreeHdr); 
    PdfPCell CellFouHdr = new PdfPCell(new Phrase("Method", fntTableFontHdr)); 
    CellFouHdr.HorizontalAlignment = Element.ALIGN_CENTER; 
    nTbl.AddCell(CellFouHdr); 
    PdfPCell CellFivHdr = new PdfPCell(new Phrase("Comments", fntTableFontHdr)); 
    nTbl.AddCell(CellFivHdr); 


    //create column sizes 
    float[] rows = { 
     100f, 
     100f, 
     70f, 
     100f, 
     100f 
    }; 
    //set row width 
    nTbl.SetTotalWidth(rows); 

    nTbl.CompleteRow(); 

    // Add the Cells to the data table 
    if (ReportDataSet.Tables("CurrentNeighbors").Rows.Count > 0) { 
     foreach (DataRow r in ReportDataSet.Tables("CurrentNeighbors").Rows) { 
      nTbl.AddCell(new Paragraph(r("FullName").ToString, fntTableFont)); 
      nTbl.AddCell(new Paragraph(r("Address").ToString, fntTableFont)); 
      nTbl.AddCell(new Paragraph(r("PhoneNumber").ToString, fntTableFont)); 
      nTbl.AddCell(new Paragraph(r("ContactMethod").ToString, fntTableFont)); 
      nTbl.AddCell(new Paragraph(r("Comments").ToString, fntTableFont)); 
     } 
    } else { 
     nTbl.AddCell(new Paragraph("Nothing Entered", fntTableFont)); 
     nTbl.AddCell(new Paragraph("    ", fntTableFont)); 
     nTbl.AddCell(new Paragraph("    ", fntTableFont)); 
     nTbl.AddCell(new Paragraph("    ", fntTableFont)); 
     nTbl.AddCell(new Paragraph("    ", fntTableFont)); 
    } 



    nTbl.SplitLate() = false; 
    nTbl.WriteSelectedRows(0, 25, 85, 490, stamper.GetOverContent(reader.NumberOfPages)); 

    stamper.Close(); 
    reader.Close(); 
    ct.Go(); 

    // Now that the new temp file has been written, we need to delete the old temp file 
    // and rename the new temp file to the old temp file name 

    // Delete Old Temp file 
    My.Computer.FileSystem.DeleteFile(FileName); 

    // Rename the new temp file to the old temp file 

    My.Computer.FileSystem.RenameFile(newFile, System.IO.Path.GetFileName(FileName)); 

} catch (Exception ex) { 
    throw ex; 
} 

} 

Я попробовать по ссылке, которую вы предоставили, но он не работает, как ожидалось. Все, что я мог сделать, это повторить страницу источника 100 раз на целевую страницу. Я знаю, что все это было связано с моей интерпретации исходного кода и преобразование, но это то, что я получил:

private void manipulatePdf(string src, string dest) 
{ 
try { 
    // Read the template file into the reader variable 
    PdfReader reader = new PdfReader(src); 
    // Get the page side of the template file 
    iTextSharp.text.Rectangle pagesize = reader.GetPageSize(1); 

    // Create a Stamper for the destination file 
    PdfStamper stamper = new PdfStamper(reader, new System.IO.FileStream(dest, System.IO.FileMode.Create)); 

    // Create a new Paragraph 
    Paragraph p = new Paragraph(); 
    // Add Text into the new paragraph 
    p.Add(new Chunk("Hello ")); 
    p.Add(new Chunk("World")); 

    // Declare your AcroFields so we can get the last field's position 
    AcroFields form = stamper.AcroFields(); 
    // Get the Last AcroField's Position 
    Rectangle rect = form.GetFieldPositions("MethodOfVerification")(0).position; 

    int status = 0; 
    PdfImportedPage newPage = null; 
    ColumnText column = new ColumnText(stamper.GetOverContent(1)); 
    column.SetSimpleColumn(rect); 
    int pagecount = 1; 

    // Add's 100 Items 
    int i = 0; 
    while (i < 100) { 
     i += 1; 
     // Creates a new paragraph object 
     column.AddElement(new Paragraph("Hello " + i.ToString)); 

     // Adds the paragraph object to the column 
     column.AddElement(p); 
     // Draw content of column 
     status = column.Go(); 
     if (ColumnText.HasMoreText(status)) { 
      // Creates a new page and stamps the Source PDF into the Destination PDF 
      newPage = loadPage(newPage, reader, stamper); 
      triggerNewPage(stamper, pagesize, newPage, column, rect, System.Threading.Interlocked.Increment(pagecount)); 
     } 
    } 
    stamper.FormFlattening = true; 
    stamper.Close(); 
    reader.Close(); 

} catch (Exception ex) { 
} 

} 

public PdfImportedPage loadPage(PdfImportedPage page, PdfReader reader, PdfStamper stamper) 
{ 
if (page == null) { 
    return stamper.GetImportedPage(reader, 1); 
} 
return page; 
} 

public void triggerNewPage(PdfStamper stamper, Rectangle pagesize, PdfImportedPage page, ColumnText column, Rectangle rect, int pagecount) 
{ 
stamper.InsertPage(pagecount, pagesize); 
PdfContentByte canvas = stamper.GetOverContent(pagecount); 
canvas.AddTemplate(page, 0, 0); 
// column.setCanvas(canvas) 
column.Canvas() = canvas; 
column.SetSimpleColumn(rect); 
column.Go(); 
} 
+0

Можете ли вы начать динамический рендеринг на новой странице или он должен немедленно забрать, когда другой остановился? –

+0

Я хочу, чтобы он отображал, где остановился последний текст. Причина в том, что они связаны друг с другом. Я знаю, что легким ответом было бы динамическое создание первой части формы, но я надеюсь на более элегантный способ сделать это. Моя конечная цель - создать PDF-файл, который будет составлять в среднем 50 страниц. – Talsiter

+0

Одним из решений, которые вы могли бы попробовать, если бы вы могли начать новую страницу, было бы также создать новый pdf-файл с данными, полученными от чтения другого, а затем объединить два документа. –

ответ

0

Я не знаю, если это помогает, но я портирован и слегка изменен Bruno sample code версии C#. Первый блок() создает образец файла и сохраняет последнюю известную координату, чтобы мы могли возобновить работу со следующей таблицей. Второй блок (file_2) затем использует PdfStamper и ColumnText для запуска таблицы и непрерывно добавляет страницы до тех пор, пока таблица не будет соответствовать. Сам код, особенно второй блок, содержит комментарии, которые лучше объясняют.

Вы должны иметь возможность переделать первый блок в логику своей формы, чтобы получить координаты (кажется, что у вас есть эта часть вниз), а затем просто используйте второй блок с вашей локальной таблицей.

//Working folder 
var exportFolder = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "SO_17589177"); 
System.IO.Directory.CreateDirectory(exportFolder); 

//File 1 is our "template" file, File 2 is our final file 
var file_1 = System.IO.Path.Combine(exportFolder, "file_1.pdf"); 
var file_2 = System.IO.Path.Combine(exportFolder, "file_2.pdf"); 

//Will hold a rectangle based on the last known coordinates 
iTextSharp.text.Rectangle tableRectStart; 

using (var fs = new FileStream(file_1, FileMode.Create, FileAccess.Write, FileShare.None)) { 
    using (var doc = new Document()) { 
     using (var writer = PdfWriter.GetInstance(doc, fs)) { 
      doc.Open(); 

      for (var i = 0; i < 10; i++) { 
       doc.Add(new Paragraph("Hello world")); 
      } 

      //Store our coordinates for later 
      tableRectStart = new iTextSharp.text.Rectangle(doc.Left, doc.Bottom, doc.Right, writer.GetVerticalPosition(false)); 

      doc.Close(); 
     } 
    } 
} 

using (var r = new PdfReader(file_1)) { 
    using (var fs = new FileStream(file_2, FileMode.Create, FileAccess.Write, FileShare.None)) { 
     using (var stamper = new PdfStamper(r, fs)) { 

      //We want to target the last page of the previous PDF 
      int pageNumber = r.NumberOfPages; 

      //Store the last page's size which is what we'll use for new pages later 
      var docRect = r.GetPageSize(pageNumber); 

      //Create a giant table 
      var t = new PdfPTable(2); 
      for (var i = 0; i < 1000; i++) { 
       t.AddCell(String.Format("This is cell {0}", i)); 
      } 

      //Create our stamper bound to the last page of our source document 
      var ct = new ColumnText(stamper.GetOverContent(pageNumber)); 

      //Add our table to the stamper 
      ct.AddElement(t); 

      //Set the drawing area for the table 
      ct.SetSimpleColumn(tableRectStart); 

      //Infinite loop below that is responsible for breaking itself out 
      //Might want to add guards in case content gets too big and always overflows 
      while (true) { 

       //Draw the text and pass the status back to a helper 
       //method that tells us if there's more text to be drawn 
       if (! ColumnText.HasMoreText(ct.Go())) { 
        //If there isn't any more text then exit the infinite loop 
        break; 
       } 

       //Reset our rectangle to the document's rectangle 
       tableRectStart = docRect; 

       //Increment the current page number (which we need to keep track of) 
       //and insert a new page 
       stamper.InsertPage(++pageNumber, docRect); 

       //Tell the ColumnText to draw on a new page 
       ct.Canvas = stamper.GetOverContent(pageNumber); 

       //Reset the drawing canvas area 
       //TODO: Include some margin logic here probably 
       ct.SetSimpleColumn(docRect); 
      } 

     } 
    } 
} 
+0

, который работал, большое вам спасибо. Я не уверен, что смог бы это понять. Еще раз спасибо. – Talsiter

Смежные вопросы