C#匯出pdf檔案《一》
要用本文的方法生成PDF檔案,需要兩個控制元件:itextsharp.dll和ICSharpCode.SharpZipLib.dll,由於示例程式碼實在太多,我將程式碼全部整理出來,放在另外一個檔案“示例程式碼.doc”中,所有這些資源,我均放在了本人的ftp站點(ftp://202.107.251.26)上的“Pdf檔案製作全攻略”資料夾中(資料夾中另外兩個rar壓縮檔案為兩個控制元件的原始碼,供大家學習研究使用),你可以到這裡下載相應的資源,或者直接到原網站下載。
為便於除錯和敘述,所有例子均為DOS控制檯程式,windows程式使用方法完全一樣,按照下面的步驟建立一個可除錯的專案:
1、 開啟VS2003;
2、 單擊選單“檔案”→“新建”→“專案”,在專案型別中選擇“Visual C#專案”,在模板中選擇“控制檯應用程式”,輸入檔名稱如“MakePdf”,指定好存放路徑,然後點確定按鈕;
3、 在“解決方案資源管理器”中右鍵單擊“引用”,從彈出的選單中選擇“新增引用”,在“.NET”選項夾中選擇“瀏覽”,新增前面提到的兩個應用,如下圖:
4、 在程式碼視窗頂部新增兩個引用:
using iTextSharp.text;
using iTextSharp.text.pdf;
至此,準備工作完畢。
第一部分 iText的簡單應用
第一章 建立一個Document
利用iText五步建立一個PDF檔案:helloword。
第一步,建立一個 iTextSharp.text.Document物件的例項:
Document document = new Document();
第二步,為該Document建立一個Writer例項:
PdfWriter.getInstance(document, new FileStream("Chap0101.pdf", FileMode.Create));
第三步,開啟當前Document
document.Open();
第四步,為當前Document新增內容:
document.Add(new Paragraph("Hello World"));
第五步,關閉Document
document.Close();
完整的程式碼見示例程式碼0101。
在例中,不難看出,製作一個PDF檔案是非常簡單的。
注:如果你將例中“document.Add(new Paragraph("Hello World"));”中的字串“Hello Word”換成中文,如“這是我的第一個PDF檔案”,產生的結果一定讓你大失所望,因為生成的PDF檔案中並沒有將中文顯示出來,不要擔心,在第9章中要專門講解字型問題,中文顯示也就迎刃而解了,如果不能正確顯示中文,也就沒有必要翻譯本文了。
下面對這幾步做詳細介紹。
第一步 建立一個Document例項:
iTextSharp.text.Document-object共有三個建構函式:
public Document();
public Document(Rectangle pageSize);
public Document(Rectangle pageSize,
int marginLeft,
int marginRight,
int marginTop,
int marginBottom);
第一個建構函式以A4頁面作為引數呼叫第二個建構函式,第二個建構函式以每邊36磅頁邊距為引數呼叫第三個建構函式
u 頁面尺寸:
你可以通過指定的顏色和大小建立你自己的頁面,示例程式碼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。
u 頁邊距:
當建立一個檔案時,你還可以定義上、下、左、右頁邊距:
Document document = new Document(PageSize.A5, 36, 72, 108, 180);
在示例程式碼0104中你可以看到該文件有一個0.5英寸的左邊距和1英寸的右邊距,上邊距為1.5英寸,下邊距為2.5英寸。
說明:
當建立一個矩形或設定邊距時,你可能希望知道該用什麼度量單位:釐米、英寸或象素,事實上,預設的度量系統以排版單位磅為基礎得出其他單位的近似值,如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中測試這些程式碼。
第三步 開啟Document
u 摘要
在你寫入任何實際資料之前,你可能希望通過以下幾種方法寫入一些關於本文件的摘要:
public boolean addTitle(String title)
public boolean addSubject(String subject)
public boolean addKeywords(String keywords)
public boolean addAuthor(String author)
public boolean addCreator(String creator)
public boolean addProducer()
public boolean addCreationDate()
public boolean addHeader(String name, String content)
你可以選擇自己的標題、主題、關鍵字、作者、建立程式,但以下產品資訊將始終被新增:iTextSharp (或者iTextSharp的引用)和建立時間(實際上這兩種方法是自動呼叫的)。
你還可以將自定義的名稱新增為“報頭資訊”,但是這對於PdfWriter沒有任何作用,如果看看例項程式碼0101產生的pdf檔案的“文件屬性”,我們可以看到僅僅有PDF建立程式和產品日期,而示例程式碼0106的“文件屬性”框中有更多的資訊。
開啟document前要做的事:
你只能在Open方法呼叫之前新增摘要,這是iText開發工具提供的一個選擇。
在HTML中,報頭資訊被放在文件前面報頭標識中間,呼叫Open方法將導致報頭資訊寫入流,因而在Document被開啟後無法更改這些資料。
PDF報頭資訊不包括摘要,看起來有類似於:
%PDF-1.2
該行顯示生成的文件是一個版本為1.2的PDF格式的檔案,在PDF中,摘要儲存在PdfInfo物件中,當文件關閉時已經寫入PdfWriter中了,因此,沒有關於為什麼不能修改庫來滿足任何時候新增或更改摘要的技術原因
u 頁面初始化
Open方法在不同的Witer中同時會產生初始化事件,舉例來說,如果你需要一個水印或者頁首頁角物件出現在文件第一頁的開始處,你需要在開啟文件前新增這些,同樣的用於設定該文件其他頁水印、頁首、頁角、頁數和尺寸。
當呼叫下列方法:
public bool setPageSize(Rectangle pageSize)
public bool Add(Watermark watermark)
public void removeWatermark()
setting Header property
public void resetHeader()
setting Footer property
public void resetFooter()
public void resetPageCount()
setting PageCount property
產生的結果只能在下一個新頁中看到(當在本頁呼叫初始化方法時),程式碼見示例程式碼0107,你必須要準備一張名為watermark.jpg的圖片,如下圖:
u 閱讀器引數:
你可以通過下面的辦法為PDF檔案指定一些閱讀器 (如Adobe Reader) 引數:
public void setViewerPreferences(int preferences)
在示例程式碼0108中,指定了下面一些引數:
writerA.setViewerPreferences(PdfWriter.PageLayoutTwoColumnLeft);
writerB.setViewerPreferences(PdfWriter.HideMenubar | PdfWriter.HideToolbar);
writerC.setViewerPreferences(PdfWriter.PageLayoutTwoColumnLeft | PdfWriter.PageModeFullScreen | PdfWriter.NonFullScreenPageModeUseThumbs);
正如你所看到的,引數可以使用以下一些常量:
l 檔案被開啟時,頁面佈局用到下面的其中一個 :
PdfWriter.PageLayoutSinglePage – 同時只顯示一個頁面
PdfWriter.PageLayoutOneColumn –單列顯示
PdfWriter.PageLayoutTwoColumnLeft –雙列顯示,奇數頁在左
PdfWriter.PageLayoutTwoColumnRight -雙列顯示,奇數頁在右
l 檔案開啟時,頁面模式用到下面其中之一:
PdfWriter.PageModeUseNone – 既不顯示大鋼也不顯示縮圖
PdfWriter.PageModeUseOutlines – 顯示大綱
PdfWriter.PageModeUseThumbs – 顯示縮圖
PdfWriter.PageModeFullScreen – 全屏模式,沒有選單、windows控制元件或者其他任何windows可見控制元件
l PdfWriter.HideToolbar – 當文件啟用時,是否隱藏閱讀程式(如Adobe Reader)的工具條
l PdfWriter.HideMenubar -當文件啟用時,是否隱藏閱讀程式的選單.
l PdfWriter.HideWindowUI -當文件啟用時,是否隱藏閱讀程式的介面元素,如滾動條、導航條等,而僅僅保留文件顯示
l PdfWriter.FitWindow – 是否調整文件視窗尺寸以適合顯示第一頁。
l PdfWriter.CenterWindow – 是否將文件視窗放到螢幕中央
l 在全屏模式下,指定如何顯示介面元素(選擇一個)
PdfWriter.NonFullScreenPageModeUseNone -既不顯示大鋼也不顯示縮圖
PdfWriter.NonFullScreenPageModeUseOutlines – 顯示大鋼
PdfWriter.NonFullScreenPageModeUseThumbs – 顯示縮圖
說明:你只能在類PdfWriter中呼叫這些方法。
u 加密
開啟文件之前還要做的一件事情就是加密(如果你希望該文件加密),要達到這個目的,你可以使用下面的方法:
public void setEncryption(boolean strength, String userPassword, String ownerPassword, int permissions);
strength 是下面兩個常量之一:
PdfWriter.STRENGTH40BITS: 40 位
PdfWriter.STRENGTH128BITS: 128位 (Acrobat Reader 5.0及以上版本支援)
UserPassword和ownerPassword 可以為空或零長度, 這種情況下, ownerPassword 將被隨機的字串代替
Permissions 為下列常量之一:
PdfWriter.AllowPrinting
PdfWriter.AllowModifyContents
PdfWriter.AllowCopy
PdfWriter.AllowModifyAnnotations
PdfWriter.AllowFillIn
PdfWriter.AllowScreenReaders
PdfWriter.AllowAssembly
PdfWriter.AllowDegradedPrinting
該功能參見示例程式碼0109和示例程式碼0110。
writer.setEncryption(PdfWriter.STRENGTH40BITS, null, null, PdfWriter.AllowCopy);
示例程式碼0109產生的檔案能夠被開啟而無須密碼,但使用者不能列印、修改本文件。
writer.setEncryption(PdfWriter.STRENGTH128BITS, "userpass", "ownerpass", PdfWriter.AllowCopy | PdfWriter.AllowPrinting);
打你試圖開啟示例程式碼0110產生的檔案時,將要求輸入密碼('userpass'),因為添加了AllowPrinting引數,你可以列印該文件而不會發生任何問題。
第四步 新增內容
在解釋第一步到第三步的不同示例中,你可能已經遇到了一些物件如Phrase, Paragraph等 在接下來的幾章中,所有這些問題都將得到詳細解釋。
有時你可能想一個writer故意忽略document產生的行為,如示例程式碼0111:
當我們建立了兩個writer: writerA 和 writerB:
PdfWriter writerA = PdfWriter.getInstance(document, new FileStream("Chap0111a.pdf", FileMode.Create));
PdfWriter writerB = PdfWriter.getInstance(document, new FileStream("Chap0111b.pdf", FileMode.Create));
我們可以建立兩個有細微差別的文件:
writerA.Pause();
document.add(new Paragraph("This paragraph will only be added to Chap0111b.pdf, not to Chap0111a.pdf"));
writerA.resume();
你可以比較檔案: Chap0111a.pdf和Chap0111b.pdf的區別
第五步,關閉 document
關閉 document 非常重要, 因為它將關閉正在執行的Writer並將內容寫入檔案,該方法在最後被呼叫,你應該總是要關閉文件。
高階話題:閱讀PDF檔案
該部分內容介紹了iText只能產生PDF格式的檔案而不能解析PDF格式檔案,不再翻譯。
第二章 塊、短句和段落
塊
塊(Chunk)是能被新增到文件的文字的最小單位,塊可以用於構建其他基礎元素如短句、段落、錨點等,塊是一個有確定字型的字串,要新增塊到文件中時,其他所有佈局變數均要被定義。下面一行中,我們建立了一個內容為“hello World”、紅色、斜體、COURIER字型、尺寸20的一個塊:
Chunk chunk = new Chunk("Hello world", FontFactory.getFont(FontFactory.COURIER, 20, Font.ITALIC, new Color(255, 0, 0)));
u 典型字型1:
在本指南中,除了第九章外(你可以在這裡學會使用其他字型),我們將始終使用典型字型1,這些是不同的典型字型1:
· Courier (該字型定寬)
· Helvetica
· Times Roman
· Symbol
· ZapfDingbats
u 下劃線/刪除線
如果你希望一些塊有下劃線或刪除線,你可以通過改變字型風格簡單做到:
Chunk chunk1 = new Chunk("This text is underlined", FontFactory.getFont(FontFactory.HELVETICA, 12, Font.UNDERLINE));
Chunk chunk2 = new Chunk("This font is of type ITALIC | STRIKETHRU", FontFactory.getFont(FontFactory.HELVETICA, 12, Font.ITALIC | Font.STRIKETHRU));
u 上標/下標
在塊中有幾個方法可以呼叫,其中大部分將在接下來的章節中介紹,本章中只介紹一個方法 setTextRise(float f). 你可以使用該方法在上標或下標中寫塊。
u 塊的背景
如果你想改變塊的背景,你可以使用方法setBackground(Color color). 這將在塊文字的下面新增一個彩色矩形:
ck.setBackground(new Color(0xFF, 0xFF, 0x00));
在示例程式碼0101中,你可以概覽典型字型1和一個使用setTextRise, setBackground等方法的的例子。
短句
短句(Phrases)是一系列以特定間距(兩行之間的距離)作為引數的塊,一個短句有一個主字型,但短句中的一些塊具有不同於主字型的字型,你有更多的選擇去建立短句,一些具體使用參見程式碼0202。
u 古希臘語
因為古希臘語經常使用,在類Phrase的建構函式中有一個特徵:將一個字串作為引數(如果你想避免這種情況,你只能使用塊工作而不能使用字串),正如你在示例程式碼0203中看到的,這個特徵自動地將913至937(除903)和945至969(古希臘的ASCII值)範圍內的所有字型改為希臘符號。
u 非主要性
與其說這是一個特徵,不如說是一個缺陷,但無論如何,這使建立一個非主要性的短句或段落成為可能,這將產生一個由下向上書寫的臨時作用(參見示例程式碼0204)。如果你想在一頁中將一些位置移動到上面時可能有用。
說明,當你穿越上邊屆時無法檢查,也沒有辦法讓你回到前一頁。
段落
段落是一系列塊和(或)短句。同短句一樣,段落有確定的間距。使用者還可以指定縮排;在邊和(或)右邊保留一定空白,段落可以左對齊、右對齊和居中對齊。新增到文件中的每一個段落將自動另起一行。有幾種辦法建立一個段落,如:
Paragraph p1 = new Paragraph(new Chunk("This is my first paragraph.", FontFactory.getFont(FontFactory.HELVETICA, 12)));
Paragraph p2 = new Paragraph(new Phrase("This is my second paragraph.", FontFactory.getFont(FontFactory.HELVETICA, 12)));
Paragraph p3 = new Paragraph("This is my third paragraph.", FontFactory.getFont(FontFactory.HELVETICA, 12));
所有有些物件將被新增到段落中:
p1.add("you can add strings, "); p1.add(new Chunk("you can add chunks ")); p1.add(new Phrase("or you can add phrases."));
說明:一個段落有一個且僅有一個間距,如果你添加了一個不同字型的短句或塊,原來的間距仍然有效,你可以通過SetLeading來改變間距,但是段落中所有內容將使用新的中的間距。見示例程式碼0205。
u 保持段落的整體性
在示例程式碼0206中,我們使用了setKeepTogether(true)方法來試圖將一個段落放在同一頁中,該方法並不是始終有效,舉個例子,第一段不能剛好在一頁中,於是被分成了兩部分。第二段被放置在第二頁,但第三段順沿到了第三頁上。
字型的延續
你應該掌握字型延續的一些規則,這些規則的應用見示例程式碼0207,當我們將一些內容用指定的字型(非預設字型)建立一個短句或者段落後再新增更多內容時,初始物件的字型風格將被延續,請看“Hello 1!”和“Hello 2”:
Phrase myPhrase = new Phrase("Hello 2! ", new Font(Font.TIMES_NEW_ROMAN, 8, Font.BOLD));
myPhrase.Add(new Phrase("some other font ", new Font(Font.HELVETICA, 8, Font.ITALIC)));
myPhrase.Add(new Phrase("This is the end of the sentence.\n", new Font(Font.TIMES_NEW_ROMAN, 8, Font.ITALIC)));
document.Add(myPhrase);
我們由Times New Roman 粗體字開始,新增一些文字使用Helvetica字型而不指定風格,我們發現文字被改變成了粗體,當我們再加一些文字使用Times New Roman字型和斜體風格,結果變成了粗斜體。
如果我們使用FontFactory來建立字型,字型風格不會被延續,因為FontFactory使用了另外的技術構建一個字型:
myPhrase = new Phrase("Hello 1bis! ", FontFactory.getFont(FontFactory.TIMES_NEW_ROMAN, 8, Font.BOLD));
myPhrase.Add(new Phrase("some other font ", FontFactory.getFont(FontFactory.HELVETICA, 8, Font.ITALIC)));
myPhrase.Add(new Phrase("This is the end of the sentence.\n", FontFactory.getFont(FontFactory.TIMES_NEW_ROMAN, 8, Font.ITALIC)));
document.Add(myPhrase);
在上面的程式碼中,使用Helvetica字型的文字風字型沒有指定(既不是粗體也不是斜體)。採用Times New Roman的額外文字僅僅顯示為斜體。
你也看到我們添加了一個段落,新增該段落就如同一個短句。
Paragraph myParagraph = new Paragraph("Hello 1! ", new Font(Font.TIMES_NEW_ROMAN, 8, Font.BOLD));
myParagraph.Add(new Paragraph("This is the end of the sentence.",FontFactory.getFont(new Font.TIMES_NEW_ROMAN, 8)));
document.Add(myParagraph);
你可以不這樣做,但將失去字型風格的延續,首先不用任何字型建立段落(例中我們僅僅給字型出間距為1.5倍),然後新增內容的不同部分。
myParagraph = new Paragraph(12);
myParagraph.Add(new Paragraph("Hello 3! ", new Font(Font.TIMES_NEW_ROMAN, 8, Font.BOLD)));
myParagraph.Add(new Paragraph("This is the end of the sentence.", new Font(Font.TIMES_NEW_ROMAN, 8, Font.ITALIC)));
document.Add(myParagraph);
如果你使用了Phrase物件,你同樣會失去字型風格的延續:
myPhrase = new Phrase(12);
myPhrase.Add(new Phrase("Hello 4! ", new Font(Font.TIMES_NEW_ROMAN, 8, Font.BOLD)));
myPhrase.Add(new Phrase("This is the end of the sentence.", newFont(Font.TIMES_NEW_ROMAN, 8, Font.ITALIC)));
document.Add(myPhrase);
u 更改分割符
通常,當文字不能放在一行時,文字將被分割成不同的部分,iText首先會查詢分割符,如果沒有找到,文字將在行尾被截斷。有一些預定的分割符如“ ”空格和“-”連字元,但是你可以使用setSplitCharacter方法來覆蓋這些預設值。在示例程式碼0208中,你可以看到當到達行尾時一個塊是如何被分割的。然後分隔符被改成點“.”,該行在該字元處被分割。
第三章 錨點、列表和註釋
錨點
我們都知道HTML中的超文字連結,當我們點選某些語句,你能夠跳轉到網上的其他頁。在PDF中也可以實現這種功能。事實上,在第十一章整個章節中有關於PDF連結的介紹,但這是iText的更高階的應用,本章中我們處理簡單的iText。
如果你想在文件中新增一個外部連結(例如使用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";
這兩個連結的例子請見示例程式碼0301。
列表
通過類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"));
結果如下:
First line
The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?
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);
還可以使用setIndentationLeft和setIndentationRight方法設定縮排,列表符號的縮排在建構函式中設定。更多的例子請參見示例程式碼0302。
註釋
iText支援不同風格的註釋。
u 文字註釋:
你可以新增一小段文字到你的文件中,但它並非文件內容的一部分,註釋有標題和內容:
Annotation a = new Annotation(
"authors",
"Maybe it's because I wanted to be an author myself that I wrote iText.");
u 外部連結註釋:
你需要指定一個可點選的矩形和一個字串(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");
u 外部PDF檔案連結註釋:
你需要指定一個可點選的矩形和一個字串(檔名稱)和目的檔案或頁碼。
Annotation annot = new Annotation(100f, 700f, 200f, 800f, "other.pdf", "mark");
Annotation annot = new Annotation(100f, 700f, 200f, 800f, "other.pdf", 2);
u 指定行為連結註釋
你需要指定一個可點選的矩形和一個指定的行為:
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中,我們畫了一些正方形(使用的函式將在第十章中介紹),為每個正方形添加了一些連結註釋。
第四章 頁首頁尾、章節、區域和繪圖物件
使用在第三至第五章中描述的大量簡單iText物件可以避免更多的高階話題(第九至十二章),緊記這些簡單物件限制的功能,大量複雜的功能在第三部分。
頁首頁尾
HeaderFooter物件可以於為文件每頁新增頁首和頁尾。這樣一個頁首或頁尾包含一個標準的短句(如果需要)和當前頁碼,如果你需要更多複雜的頁首和頁尾(使用表格或者第幾頁共幾頁),請閱讀第十二章。
在示例程式碼0401中,你可以看到我們首先添加了一個包含頁碼沒有任何邊框的頁尾。
HeaderFooter footer = new HeaderFooter(new Phrase("This is page: "), true);
footer.Border = Rectangle.NO_BORDER;
document.Footer = footer
我們還可以使用下面的建構函式:
HeaderFooter footer = new HeaderFooter(new Phrase("This is page "), new Phrase("."));
建構函式知道你希望新增一個頁碼和將其放置在兩個短句間,如果你只是設定一個HeaderFooter而不改變邊框,頁首或頁尾的文字上下各有一條直線。
HeaderFooter header = new HeaderFooter(new Phrase("This is a header without a page number"), false);
document.Header = header;
章節和區域
在第十一章中將描述如何構建一個樹的外觀,如果你只需要一個簡單的章節和(子)區域,你可以用Chapter物件和Section物件自動構建一個樹:
Paragraph cTitle = new Paragraph("This is chapter 1", chapterFont);
Chapter chapter = new Chapter(cTitle, 1);
Paragraph sTitle = new Paragraph("This is section 1 in chapter 1", sectionFont);
Section section = chapter.addSection(sTitle, 1);
在示例程式碼0402中,我們添加了一系列的章節和子區域,你可以看到完整的樹形,樹形結構預設開啟,如果你希望部分節點關閉,你必須使用用BookmarkOpen屬性其值為false,詳見示例程式碼0403。
圖形
如果你想新增圖形,如直線、圓、幾何窗體,你應該閱讀讀十章,但如果你只需要一些有限的功能,你可以使用Graphic物件
Graphic grx = new Graphic();
//新增一個矩形
grx.rectangle(100, 700, 100, 100);
// 新增一條斜線
grx.moveTo(100, 700);
grx.lineTo(200, 800);
// 將圖形顯示出來
grx.stroke();
document.Add(grx);
完整的程式碼請見示例程式碼0404,如果想看到全部的方法,請參見PdfContentByte物件API。
當你想給頁面加一個邊框或者在文本當前位置畫一條水平線時,圖形物件非常有用。下面的方法用指定的寬度、間距(如果需要)和顏色畫一個邊框。
public void setBorder(float linewidth, float extraSpace);
public void setBorder(float linewidth, float extraSpace, Color color);
下面的方法用指定的寬度(如果需要)和顏色畫一條水平線,線的長度是指定兩邊緣間可用面積的的百分比。
public void setHorizontalLine(float linewidth, float percentage)
public void setHorizontalLine(float linewidth, float percentage, Color color)
示例程式碼5中,有一個離邊界5磅,線寬3磅的邊框,還有兩條水平線,一條為黑色,5磅寬,可用空間的100%,另外一條為紅色,線寬3磅,可用空間的80%。
第五章 表格
重點:如果你僅僅生成PDF檔案(沒有XML、HTML、RTF……),使用類pdfPTable代替類Table更好。
一些簡單的表格
一個表格是包含單元格排列成矩陣的矩形區域。表格的距陣並不要求是m×n的,它可以有空洞或者單元格比單個的要大。
建立一個表格最通用的辦法是預先知道有幾行幾列:
public Table(int columns, int rows);
在示例程式碼0501中,我們構建了一個簡單的表:
Table aTable = new Table(2,2);
aTable.addCell("0.0");
aTable.addCell("0.1");
aTable.addCell("1.0");
aTable.addCell("1.1");
該表格有兩行兩列,單元格被自動新增,從第一行第一列開始,然後是第二列,當一行滿後,下一單元格自動新增到下一行的第一列中。
也可以將單元格新增到表中指定的位置,如示例程式碼0502,別了要新增System.Drawing.dll引用,以獲得Point物件,我們建立了一個4行4列的表格然後新增一些單元格到隨機的位置上:
Table aTable = new Table(4,4);
aTable.AutoFillEmptyCells = true;
aTable.addCell("2.2", new Point(2,2));
aTable.addCell("3.3", new Point(3,3));
aTable.addCell("2.1", new Point(2,1));
aTable.addCell("1.3", new Point(1,3));
你可以看到我們將AutoFillEmptyCells屬性設定為true,這將自動、預設的單元格佈局填充空的單元格,如果我們忘記了這樣做(就象本例中第二個表格),將沒有額外的單元格新增,不包含任何單格的行也將被忽略,在本例中,第一行將不顯示,因為該行是空行。
經常用資料庫查詢結果來填充表格,大多數情況下,你預先並不知道到底需要多少行,這就是為什麼還有第二個建構函式的原因:
public Table(int columns);
iText根據需要自動新增行,在示例程式碼0503中,初始化了4行4列,當我們新增第6行和第7行的單元格時,iText自動增加行數到7。
增加列數也是可能的,但是有點麻煩,它不能自動生成,你必須使用addColumns方法並設定列寬,詳見示例程式碼0504。
一些表格引數
前面例子中的表格並不美觀,我們可以設定大量的引數來改變表格外觀。類Table和類Cell派生於類Rectangle,我們可以用大量典型的Rectangle方法,讓我們來看看示例程式碼0505。
Table table = new Table(3);
table.BorderWidth = 1;
table.BorderColor = new Color(0, 0, 255);
table.Cellpadding = 5;