Позвольте мне сначала дать вам пару ссылок для просмотра, когда у вас есть шанс:
- Поддержка ItextSharp для HTML и CSS
- Как применить свойства шрифта при передаче html в pdf, используя itextsharp
Эти ответы углубляются в то, что происходит, и я рекомендую прочитать их, когда у вас будет возможность. В частности, второй покажет вам, почему вам нужно использовать pt
вместо px
.
Чтобы ответить на ваш первый вопрос, позвольте мне показать вам другой способ использования класса HTMLWorker
. Этот класс имеет статический метод с именем ParseToList
, который преобразует HTML в List<IElement>
. Все объекты в этом списке являются специфическими версиями вашего HTML для iTextSharp. Обычно вы делаете foreach
для них и просто добавляете их в документ, но вы можете изменить их перед добавлением, что вы и хотите сделать. Ниже приведен код, который принимает статическую строку и делает это:
string file1 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "File1.pdf");
using (FileStream fs = new FileStream(file1, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (Document doc = new Document(PageSize.LETTER))
{
using (PdfWriter writer = PdfWriter.GetInstance(doc, fs))
{
doc.Open();
//Our HTML
string html = "<table><tr><th>First Name</th><th>Last Name</th></tr><tr><td>Chris</td><td>Haas</td></tr></table>";
//ParseToList requires a StreamReader instead of just a string so just wrap it
using (StringReader sr = new StringReader(html))
{
//Create a style sheet
StyleSheet styles = new StyleSheet();
//...styles omitted for brevity
//Convert our HTML to iTextSharp elements
List<IElement> elements = iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(sr, styles);
//Loop through each element (in this case there's actually just one PdfPTable)
foreach (IElement el in elements)
{
//If the element is a PdfPTable
if (el is PdfPTable)
{
//Cast it
PdfPTable tt = (PdfPTable)el;
//Change the widths, these are relative width by the way
tt.SetWidths(new float[] { 75, 25 });
}
//Add the element to the document
doc.Add(el);
}
}
doc.Close();
}
}
}
Надеюсь, вы увидите, что как только вы получите доступ к необработанному PdfPTable
, вы сможете настроить его по мере необходимости.
Чтобы ответить на ваш второй вопрос, если вы хотите использовать обычные Paragraph
и Chunk
объекты с PdfStamper
, тогда вам нужно использовать PdfContentByte
объект. Вы можете получить это из вашего штампа одним из двух способов, либо запросив тот, который находится «над» существующим контентом, stamper.GetOverContent(int)
, либо тот, который находится «под» существующим контентом, stamper.GetUnderContent(int)
. Обе версии принимают один параметр, указывающий, с какой страницей работать. Если у вас есть PdfContentByte
, вы можете создать связанный с ним объект ColumnText
и использовать метод AddElement()
этого объекта для добавления ваших обычных элементов. Прежде чем сделать это (и это ответит на ваш третий вопрос), вам нужно создать хотя бы одну «колонку». Когда я делаю это, я обычно создаю тот, который по существу покрывает всю страницу. (Эта часть может показаться странной, но мы, по сути, делаем одну строку, ячейку таблицы из одного столбца, к которой добавляем наши объекты.)
Ниже представлено полнофункциональное приложение WinForms для C # 2010, предназначенное для iTextSharp 5.1.1.0, которое демонстрирует все вышеперечисленное. Сначала он создает общий PDF на рабочем столе. Затем он создает второй документ на основе первого, добавляет абзац, а затем немного HTML. Смотрите комментарии в коде по любым вопросам.
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using iTextSharp.text;
using iTextSharp.text.html.simpleparser;
using iTextSharp.text.pdf;
using System.IO;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//The two files that we are creating
string file1 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "File1.pdf");
string file2 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "File2.pdf");
//Create a base file to write on top of
using (FileStream fs = new FileStream(file1, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (Document doc = new Document(PageSize.LETTER))
{
using (PdfWriter writer = PdfWriter.GetInstance(doc, fs))
{
doc.Open();
doc.Add(new Paragraph("Hello world"));
doc.Close();
}
}
}
//Bind a reader to our first document
PdfReader reader = new PdfReader(file1);
//Create our second document
using (FileStream fs = new FileStream(file2, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (PdfStamper stamper = new PdfStamper(reader, fs))
{
StyleSheet styles = new StyleSheet();
//...styles omitted for brevity
//Our HTML
string html = "<table><tr><th>First Name</th><th>Last Name</th></tr><tr><td>Chris</td><td>Haas</td></tr></table>";
//ParseToList requires a StreamReader instead of just a string so just wrap it
using (StringReader sr = new StringReader(html))
{
//Get our raw PdfContentByte object letting us draw "above" existing content
PdfContentByte cb = stamper.GetOverContent(1);
//Create a new ColumnText object bound to the above PdfContentByte object
ColumnText ct = new ColumnText(cb);
//Get the dimensions of the first page of our source document
iTextSharp.text.Rectangle page1size = reader.GetPageSize(1);
//Create a single column object spanning the entire page
ct.SetSimpleColumn(0, 0, page1size.Width, page1size.Height);
ct.AddElement(new Paragraph("Hello world!"));
//Convert our HTML to iTextSharp elements
List<IElement> elements = iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(sr, styles);
//Loop through each element (in this case there's actually just one PdfPTable)
foreach (IElement el in elements)
{
//If the element is a PdfPTable
if (el is PdfPTable)
{
//Cast it
PdfPTable tt = (PdfPTable)el;
//Change the widths, these are relative width by the way
tt.SetWidths(new float[] { 75, 25 });
}
//Add the element to the ColumnText
ct.AddElement(el);
}
//IMPORTANT, this actually commits our object to the PDF
ct.Go();
}
}
}
this.Close();
}
}
}