Я использую iTextSharp для создания PDF-файла. Этот PDF-файл содержит таблицу, которую я создаю с помощью DirectContent. Я считаю строки, которые пишу, и делаю document.NewPage()
, когда количество строк достигает 45. Кажется, все работает нормально пока не любая из строк переносится во вторую строку. Если это произойдет, мой счетчик строк будет отключен, и в конечном итоге мой разбиение на страницы будет неправильным. Есть ли у кого-нибудь идеи, как я могу обойти эту проблему? Моя полная программа следующая:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using iTextSharp.text;
using iTextSharp.text.pdf;
using static iTextSharp.text.Font;
namespace iTextSharp_long_table
{
class Program
{
static void Main(string[] args)
{
MemoryStream stream = new MemoryStream();
using (stream)
using (Document document = new Document(PageSize.LETTER))
{
PdfWriter writer = PdfWriter.GetInstance(document, stream);
document.Open();
PdfPTable table = new PdfPTable(4);
table.TotalWidth = 72 * 7.5f;
int nrows = 0;
int topOfPage = 0;
Font font = new Font(FontFamily.HELVETICA, 9, Font.BOLD);
Font fontPlain = new Font(FontFamily.HELVETICA, 9);
for (int i = 0; i < 20 ; i++) // jobs
{
if (nrows >= 45)
{
table.WriteSelectedRows(topOfPage, -1, 36, 9 * 72, writer.DirectContent);
document.NewPage();
topOfPage = table.Size;
nrows = 0;
}
PdfPCell cell2 = new PdfPCell(new Phrase("Job " + (i + 1).ToString(), font));
cell2.Border = PdfPCell.TOP_BORDER + PdfPCell.LEFT_BORDER + PdfPCell.BOTTOM_BORDER;
cell2.BackgroundColor = new BaseColor(227, 235, 247);
cell2.Colspan = 3;
table.AddCell(cell2);
string currency = string.Format("{0:C}", Math.Round(1.23, 2));
cell2 = new PdfPCell(new Phrase(currency, font));
cell2.BackgroundColor = new BaseColor(227, 235, 247);
cell2.HorizontalAlignment = Element.ALIGN_RIGHT;
cell2.Border = PdfPCell.TOP_BORDER + PdfPCell.RIGHT_BORDER + PdfPCell.BOTTOM_BORDER;
table.AddCell(cell2);
nrows++;
// workitems
DoWorkItems(ref table, ref nrows, ref topOfPage, document, ref writer, ref fontPlain);
// add a blank row before the next job
cell2 = new PdfPCell(new Phrase(" "));
cell2.Colspan = 4;
cell2.Border = PdfPCell.NO_BORDER;
table.AddCell(cell2);
nrows++;
}
table.WriteSelectedRows(topOfPage, -1, 36, 9 * 72, writer.DirectContent);
document.NewPage();
}
byte[] result = stream.GetBuffer();
File.WriteAllBytes(@"c:\temp\Long Table.pdf", result);
Process.Start(@"c:\temp\Long Table.pdf");
}
public static void DoWorkItems(ref PdfPTable table, ref int nrows, ref int topOfPage,
Document document, ref PdfWriter writer, ref Font fontPlain)
{
for (int j = 0; j < 5 ; j++) // workitems
{
if (nrows >= 45)
{
table.WriteSelectedRows(topOfPage, -1, 36, 9 * 72, writer.DirectContent);
document.NewPage();
topOfPage = table.Size;
nrows = 0;
}
string str = " - Item " + (j + 1).ToString();
Phrase phrase = new Phrase(str, fontPlain);
PdfPCell cell2 = new PdfPCell(phrase);
cell2.Colspan = 4;
cell2.Border = PdfPCell.NO_BORDER;
table.AddCell(cell2);
nrows++;
}
}
}
}
Да (хотя, может быть, мне и не нужно?). Я делаю это, потому что хочу запустить таблицу в определенном месте на странице (в реальной программе я рисую изображение вверху страницы).
Это не значит, что вы не можете добавить таблицу в документ. Просто установите поля страницы так, чтобы оставшееся пространство было там, где вы хотите разместить таблицу.
Спасибо, @mkl! Вы развеяли мое заблуждение и позволили мне решить эту проблему. Поскольку мне не нужно использовать прямой контент, я могу просто добавить таблицу в документ и позволить iTextSharp выполнить разбиение на страницы. Проблема решена :-).
Я напишу ответ по этому поводу.
Обычно лучше оставить детали макета в iText, в частности, для основного контента, который может или не может распространяться по страницам. Единственный контент, который обычно требуется для создания макета, - это верхний колонтитул, нижний колонтитул, фон и аналогичные материалы.
В данном случае в комментариях выяснилось, что причина, по которой OP сам обрабатывал детали макета, заключалась в следующем:
I do it because I want to start the table at a specific point on the page (in the real program, I draw an image at the top of the page).
Но это также возможно, если позволить iText обрабатывать макет: нужно просто установить поля страницы так, чтобы оставшееся пространство, пространство, которое iText использует для макета содержимого, было пространством, в котором нужно отображать свой контент.
(Осторожно: вы должны установить поля до, когда создается соответствующая страница. В случае первой страницы это, в частности, означает, что вы должны сделать это перед открытием документа.)
Это решило проблему OP:
Since I don't have to use direct content, I can just add the table to the document and let iTextSharp do the pagination. Problem solved :-).
Есть ли конкретная причина, по которой вы добавляете таблицу, используя прямое содержимое и
WriteSelectedRows
, вместо того, чтобы добавлять таблицу в документ и позволять itext разделить ее? Эта причина может быть важна для ответа и здесь.