我有一个模板PDF,其中包含一个恒定高度的表单数据。根据该数据,我需要添加一个具有动态高度的表。此表可能只有一行,一行,或者可能包含1000行和/或1-1000行。
这是我的代码,它的工作正常,但是,如果表格很大,表格将不会跨越到新页面。
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”参数包含我要将表添加到的原始文件的位置。
甚至可以这样做,如果是的话,我错过了什么?
编辑:
这是我尝试的另一个功能(使用压模)。我也可能会离开这个,但这正是我试图找到的:
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)
我不知道这是否有帮助,但我已将Bruno sample code移植并稍微修改为C#版本。第一个块(file_1
)创建一个示例文件并存储最后一个已知坐标,以便我们稍后可以使用表恢复。然后,第二个块(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);
}
}
}
}