ITextSharp是一個生成Pdf文件的開源項目,最近在項目中有使用到這個項目,對使用中的經驗作一個小結.
ITextSharp中相關的概念:
一、Document
這個對象有三個構造函數:
-
public Document();
-
public Document(Rectangle pageSize);
-
public Document(Rectangle pageSize,
-
int marginLeft,
-
int marginRight,
-
int marginTop,
-
int marginBottom);
第一個構造函數以A4頁面作為參數調用第二個構造函數,第二個構造函數以每邊36磅頁邊距為參數調用調用第三個構造函數。
頁面尺寸:
你可以通過指定的顏色和大小創建你自己的頁面,示例代碼0102創建一個細長的淺黃色背景的頁面:
Rectangle pageSize = new Rectangle(144, 720);
pageSize.BackgroundColor = new Color(0xFF, 0xFF, 0xDE);
Document document = new Document(pageSize);
通常,你不必創建這樣的頁面,而可以從下面頁面尺寸中選擇:
A0-A10, LEGAL, LETTER, HALFLETTER, _11x17, LEDGER, NOTE, B0-B5, ARCH_A-ARCH_E, FLSA 和 FLSE
大多數情況下使用縱向頁面,如果希望使用橫向頁面,你只須使用rotate()函數:
Document document = new Document(PageSize.A4.rotate());
詳細代碼見示例代碼0103。
頁邊距:
當創建一個文件時,你還可以定義上、下、左、右頁邊距:
Document document = new Document(PageSize.A5, 36, 72, 108, 180);
說明:
當創建一個矩形或設置邊距時,你可能希望知道該用什么度量單位:厘米、英寸或象素,事實上,默認的度量系統以排版單位磅為基礎得出其他單位的近似值,如1英寸=72磅,如果你想在A4頁面的PDF中創建一個矩形,你需要計算以下數據:
21 厘米 / 2.54 = 8.2677 英寸
8.2677英寸* 72 = 595 磅
29.7 厘米 / 2.54 = 11.6929 英寸
11.6929英寸* 72 = 842 磅
默認邊距為36磅即半英寸。
如果你修改了頁面尺寸,僅僅影響到下一頁,如果你修改了頁邊距,則影響到全部,故慎用。
二、Writer
一旦創建了document,我們可以創建該文檔的多個Writer的實例,所有這些Writer實例均繼承自抽象類“iTextSharp.text.DocWriter”。
同時還有另外一種情況,你可以用iTextSharp.text.pdf.PdfWriter產生文檔PDF文件,如果你想創建一個TeX文檔,你可以使用iTextSharp.text.TeX.TeXWriter包。
Writer類的構造函數是私有的,你只能通過下面的方法創建一個實例:
public static xxxWriter getInstance(Document document, Stream os);(xxx 是 Pdf 或 Xml)
你可以通過下面的方法創建一個實例:
PdfWriter writer = PdfWriter.getInstance(document, new FileStream("Chap01xx.pdf"));
但是你幾乎永遠不會用到Writer實例(除非你想創建高級PDF或者希望用一些非常特殊的函數,如ViewerPreferences 或 Encryption)。所以通過下面的辦法得到實例已經足夠了: PdfWriter.getInstance(document, new FileStream("Chap01xx.pdf"));
在第一步中創建一個文檔時,第一個參數意義不大,第二個參數可以是任何一種流,到目前為止我們一直使用System.IO.FileStream將Document寫入文件中,示例代碼0105用到了System.IO.MemoryStream(這不是一個獨立的例子,你必須在Servlet Engine中測試這些代碼。
文檔加密:
public void setEncryption(boolean strength, String userPassword, String ownerPassword, int permissions);
· strength 是下面兩個常量之一:
o PdfWriter.STRENGTH40BITS: 40 位
o PdfWriter.STRENGTH128BITS: 128位 (Acrobat Reader 5.0及以上版本支持)
· UserPassword和ownerPassword 可以為空或零長度, 這種情況下, ownerPassword 將被隨機的字符串代替
· Permissions 為下列常量之一:
o PdfWriter.AllowPrinting
o PdfWriter.AllowModifyContents
o PdfWriter.AllowCopy
o PdfWriter.AllowModifyAnnotations
o PdfWriter.AllowFillIn
o PdfWriter.AllowScreenReaders
o PdfWriter.AllowAssembly
PdfWriter.AllowDegradedPrinting
三、塊(Chunk)
塊(Chunk)是能被添加到文檔的文本的最小單位,塊可以用於構建其他基礎元素如短句、段落、錨點等,塊是一個有確定字體的字符串,要添加塊到文檔中時,其他所有布局變量均要被定義。
四、短句(Phrases)
短句(Phrases)是一系列以特定間距(兩行之間的距離)作為參數的塊,一個短句有一個主字體,但短句中的一些塊具有不同於主字體的字體,你有更多的選擇去創建短句。
五、段落
段落是一系列塊和(或)短句。同短句一樣,段落有確定的間距。用戶還可以指定縮排;在邊和(或)右邊保留一定空白,段落可以左對齊、右對齊和居中對齊。添加到文檔中的每一個段落將自動另起一行。
說明:一個段落有一個且僅有一個間距,如果你添加了一個不同字體的短句或塊,原來的間距仍然有效,你可以通過SetLeading來改變間距,但是段落中所有內容將使用新的中的間距。
更改分割符
通常,當文本不能放在一行時,文本將被分割成不同的部分,iText首先會查找分割符,如果沒有找到,文本將在行尾被截斷。有一些預定的分割符如“ ”空格和“-”連字符,但是你可以使用setSplitCharacter方法來覆蓋這些默認值。
以使用IndentationLeft和IndentationRight,FirstLineIndent屬性設置縮排;
六、錨點(Anchor)
如果你想在文檔中添加一個外部鏈接(例如使用URL鏈接到WEB上的其他文檔),你可以簡單地使用Anchor對象,它派生於Phrase對象,使用方法相同。只有兩種額外方法定義兩種額外變量:setName和 setReference。
外部鏈接示例:
-
Anchor anchor = new Anchor("website", FontFactory.getFont(FontFactory.HELVETICA, 12, Font.UNDERLINE, new Color(0, 0, 255)));
-
anchor.Reference = http://itextsharp.sourceforge.net;
-
anchor.Name = "website";
如果你想添加內部鏈接,你需要選擇該鏈接不同的名稱,就象你相位在HTML中利用名稱作為錨點一樣。為達到該目的,你需要添加一個“#”。
內部鏈接示例:
-
Anchor anchor1 = new Anchor("This is an internal link");
-
anchor1.Name = "link1";
-
Anchor anchor2 = new Anchor("Click here to jump to the internal link");
-
anchor.Reference = "#link1";
七、列表(List,ListItem)
通過類List 和ListItem,你可以添加列表到PDF文件中,對於列表你還可以選擇是否排序。
排序列表示例:
-
List list = new List(true, 20);
-
list.Add(new ListItem("First line"));
-
list.Add(new ListItem("The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?"));
-
list.Add(new ListItem("Third line"));
結果如下:
1. First line
2. The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?
3. Third line
不排序示例如下:
-
List overview = new List(false, 10);
-
overview.Add(new ListItem("This is an item"));
-
overview.Add("This is another item");
結果如下:
· This is an item
· This is another item
可以通過SetListSymbol方法來更改列表符號,可以使用圖片或其它對象作為列表符號。
-
// 用字符串作為列表符號
-
list1.ListSymbol = "*";
-
// 用Chunk 作為列表符號(包含“•”字符)
-
list2.ListSymbol = new Chunk("\u2022", FontFactory.getFont(FontFactory.HELVETICA, 20));
-
//用圖片作為列表符號
-
list3.ListSymbol = new Chunk(Image.getInstance("myBullet.gif"), 0, 0);
還可以使用IndentationLeft和IndentationRight屬性設置縮排,列表符號的縮排使用SymbolIndent屬性,也可以在構造函數中設置。
八、注釋
你可以添加一小段文本到你的文檔中,但它並非文檔內容的一部分,注釋有標題和內容:
Annotation a = new Annotation(
"authors",
"Maybe it's because I wanted to be an author myself that I wrote iText.");
外部鏈接注釋:
你需要指定一個可點擊的矩形和一個字符串(URL描述)或URL對象:
Annotation annot = new Annotation(100f, 700f, 200f, 800f, new URL("http://www.lowagie.com"));
Annotation annot = new Annotation(100f, 700f, 200f, 800f, "http://www.lowagie.com");
外部PDF文件鏈接注釋:
你需要指定一個可點擊的矩形和一個字符串(文件名稱)和目的文件或頁碼。
Annotation annot = new Annotation(100f, 700f, 200f, 800f, "other.pdf", "mark");
Annotation annot = new Annotation(100f, 700f, 200f, 800f, "other.pdf", 2);
指定行為鏈接注釋
你需要指定一個可點擊的矩形和一個指定的行為:
Annotation annot = new Annotation(100f, 700f, 200f, 800f, PdfAction.FIRSTPAGE);
u 應用程序鏈接注釋:
你需要指定一個可點擊的矩形和一個應用程序:
Annotation annot = new Annotation(300f, 700f, 400f, 800f, "C://winnt/notepad.exe", null, null, null);
我們無須在頁面上指定一個位置,iText會內部處理。你能夠看到iText添加文本注釋在頁面上當前位置下面,第一個在段后第一行下面,第二個在短句結束處的下面。
所有其他注釋需要指定想匹配的矩形區域,在示例代碼0304中,我們畫了一些正方形(使用的函數將在第十章中介紹),為每個正方形添加了一些鏈接注釋。
九、頁眉頁腳
在舊版本中,有HeaderFooter對象就可以設置頁眉頁腳,但是新版本中,已經不存在這個對象。
新版本中,使用新的對象PdfWriter中有一個對象:PdfEvent對象,它實現了如下接口:
-
public interface IPdfPageEvent
-
{
-
void OnChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title);
-
void OnChapterEnd(PdfWriter writer, Document document, float paragraphPosition);
-
void OnCloseDocument(PdfWriter writer, Document document);
-
void OnEndPage(PdfWriter writer, Document document);
-
void OnGenericTag(PdfWriter writer, Document document, Rectangle rect, string text);
-
void OnOpenDocument(PdfWriter writer, Document document);
-
-
void OnParagraph(PdfWriter writer, Document document, float paragraphPosition);
-
void OnParagraphEnd(PdfWriter writer, Document document, float paragraphPosition);
-
-
void OnSection(PdfWriter writer, Document document, float paragraphPosition, int depth, Paragraph title);
-
void OnSectionEnd(PdfWriter writer, Document document, float paragraphPosition);
-
-
void OnStartPage(PdfWriter writer, Document document);
-
-
}
可以在這里面實現。
十、章節(Chapter)和區域(Section)
章節的使用就比較少了,並且不太好控制,這就不作說明
十一、書簽
簡單創建書簽,使用如下代碼:
-
protected PdfOutline SetDestination(PdfOutline root, Chunk chk, string name, string destination)
-
{ chk.SetLocalDestination(destination); return new PdfOutline(root, PdfAction.GotoLocalPage(destination, false), name); }
復雜的書簽就要使用Pdfaction,PdfOutline,PdfDestination三個對象來創建了。
十二、中文語言支持
中文語言支持,要加入一些擴展dll,加入方法如下所示:
public static void RegisterFont()
{
if (!_isRegisterFont) { lock (typeof(TextSharpHelper)) { if (!_isRegisterFont) { BaseFont.AddToResourceSearch("iTextAsian.dll"); BaseFont.AddToResourceSearch("iTextAsianCmaps.dll"); FontFactory.Register(Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\..\Fonts\STSONG.ttf"); FontFactory.Register(Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\..\Fonts\simhei.ttf"); FontFactory.Register(Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\..\Fonts\simsun.ttc"); _isRegisterFont = true; } } } }
上面的兩個dll是注冊中文語言支持,后面是注冊系統下的一些中文字體文件。
十三、文字、表格、圖像混排
在進行文字、表格、圖像混排中,有時比較難控制位置,最好是把文字、表格、圖像分別放到不同的段落中,這樣才能很好控制位置。
十四、表單寫入
讀取表單中的域:
-
public static Dictionary<string, string> ReadForm(string pdfTemplate)
-
{
-
Dictionary<string, string> dic = new Dictionary<string, string>();
-
PdfReader pdfReader = null;
-
try
-
{
-
pdfReader = new PdfReader(pdfTemplate);
-
AcroFields pdfFormFields = pdfReader.AcroFields;
-
foreach (KeyValuePair<string, AcroFields.Item> de in pdfFormFields.Fields)
-
{
-
dic.Add(de.Key, "");
-
}
-
}
-
finally
-
{
-
if (pdfReader != null)
-
{
-
pdfReader.Close();
-
}
-
}
-
return dic;
-
}
對表單中的域進行填充:
-
public static void FillForm(string pdfTemplate, string newFile, Dictionary<string, string> dic)
-
{
-
PdfReader pdfReader = null;
-
PdfStamper pdfStamper = null;
-
try
-
{
-
pdfReader = new PdfReader(pdfTemplate);
-
pdfStamper = new PdfStamper(pdfReader, new FileStream(
-
newFile, FileMode.Create));
-
AcroFields pdfFormFields = pdfStamper.AcroFields;
-
foreach (KeyValuePair<string, string> de in dic)
-
{
-
pdfFormFields.SetField(de.Key, de.Value);
-
}
-
pdfStamper.FormFlattening = true;
-
}
-
finally
-
{
-
if (pdfReader != null)
-
{
-
pdfReader.Close();
-
}
-
if (pdfStamper != null)
-
{
-
pdfStamper.Close();
-
}
-
}
-
}