在這個.NET組件的介紹系列中,受到了很多園友的支持,一些園友(如:數(shù)據(jù)之巔、 [秦時明月]等等這些大神 )也給我提出了對應(yīng)的建議,我正在努力去改正,有不足之處還望大家多多包涵。在傳播一些簡單的知識的同時,我自己也得到了一些提升,這個是我感覺到的最大的益處。知識需要傳播,在傳播的過程中去讓學習的人去提升,在交流中的過程中去讓思考的人去展望,我希望我也能在這個傳播的過程中出一份力。由于自身能力有限,在編寫博文時出現(xiàn)的錯誤和一些不到位的講解,還望大家多多見諒。
上面賣完情懷,下面就該切入正題了。
提到打印,恐怕對于很多人都不會陌生,無論是開發(fā)者,還是非計算機專業(yè)的人員都會接觸到打印。對于項目開發(fā)中使用到打印的地方會非常多,在.NET項目中,選擇打印的方式比較多,例如原始的IE網(wǎng)頁打印、水晶報表、JS插件實現(xiàn)打印、導出文檔打印,以及今天提到的使用itextSharp組件實現(xiàn)PDF打印等等。
在.NET中實現(xiàn)PDF打印的組件比較多,例如PDFsharp、Report.NET、sharpPDF、itextSharp等等,今天主要簡單的介紹itextSharp組件。
一.itextSharp組件概述:
1.iText的是PDF庫,它允許你創(chuàng)建,調(diào)整,檢查和維護的可移植文檔格式文件(PDF):
(1).基于從XML文件或數(shù)據(jù)庫中的數(shù)據(jù)生成文件和報告。
(2).創(chuàng)建地圖和書籍,利用眾多的互動在PDF可用的功能。
(3).添加書簽,頁碼,水印等功能,以現(xiàn)有的PDF文件。
(4).從現(xiàn)有PDF文件拆分或連接頁面;填寫交互式表單。
(5).即成動態(tài)生成或操縱PDF文檔到Web瀏覽器。
iText所使用的的Java,.NET,Android和GAE開發(fā)人員加強與PDF功能的應(yīng)用程序。iTextSharp的是.NET端口。
2.itextSharp的一些特征:
(1).PDF生成。
(2).PDF操作(沖壓水印,合并/拆分PDF文件,...)。
(3).PDF表單填寫。
(4).XML功能。
(5).數(shù)字簽名。
以上是對itextSharp組件的一些特性的簡單介紹,如果需要更加深入的了解itextSharp組件的相關(guān)信息,可以細致的查看API文檔和itextSharp產(chǎn)品介紹。https://sourceforge.net/projects/itextsharp/#overview。
二.itextSharp組件核心類和方法:
談到打印,在我們的項目中需要首先考慮的是我們需要打印的東西是什么。在大腦里面應(yīng)該首先有一個文檔的概念,在我們編程的過程中,“文檔”這個詞無處不在,這個可以是一個寬泛的概念,也可以是一個狹窄的概念,寬泛的“文檔”是指容器,用以存放一些元素;狹窄的“文檔”是指實際的文件類型。
對于打印的“文檔”,具體看一下寬泛的概念,文檔包含元素和節(jié)點等等。在組織打印的時候,我們需要創(chuàng)建文檔,寫入元素和節(jié)點等信息,最后組合成為我們需要打印的內(nèi)容。itextSharp組件可以插入段落、表格、圖片等等信息,可以很方便的完成我們需要完成的功能。
Paragraph:報表中的文本;Image:報表中的圖片;PdfPTable:表格;PdfPCell:單元格。
1.Document類Open()方法:打開文檔對象。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public virtual void Open() { if (! this .close) { this .open = true ; } foreach (IDocListener listener in this .listeners) { listener.SetPageSize( this .pageSize); listener.SetMargins( this .marginLeft, this .marginRight, this .marginTop, this .marginBottom); listener.Open(); } } |
以上的代碼可以看到,我們在打開文檔的時候,會設(shè)置文檔大小,文檔頁邊距等信息。
2.Paragraph類Add()方法:向段落添加元素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
public override bool Add(IElement o) { if (o is List) { List element = (List) o; element.IndentationLeft += this .indentationLeft; element.IndentationRight = this .indentationRight; base .Add(element); return true ; } if (o is Image) { base .AddSpecial((Image) o); return true ; } if (o is Paragraph) { base .Add(o); IList<Chunk> chunks = this .Chunks; if (chunks.Count > 0) { Chunk chunk = chunks[chunks.Count - 1]; base .Add( new Chunk( "\n" , chunk.Font)); } else { base .Add(Chunk.NEWLINE); } return true ; } base .Add(o); return true ; } |
1
2
3
4
5
6
7
8
9
10
11
12
|
public interface IElement { // Methods bool IsContent(); bool IsNestable(); bool Process(IElementListener listener); string ToString(); // Properties IList<Chunk> Chunks { get ; } int Type { get ; } } |
以上的add()方法是向段落添加元素,我們可以看到參數(shù)是個接口“IElement”,我們接下來看一下這個接口,接口主要元素是塊。我們看到在向段落添加元素時,可以添加List,Image,Paragraph,Chunk。
3.Image.GetInstance()獲取圖片實例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
public static Image GetInstance(Image image) { if (image == null ) { return null ; } return (Image) image.GetType().GetConstructor(BindingFlags.Public | BindingFlags.Instance, null , new Type[] { typeof (Image) }, null ).Invoke( new object [] { image }); } public static Image GetInstance( byte [] imgb) { int num = imgb[0]; int num2 = imgb[1]; int num3 = imgb[2]; int num4 = imgb[3]; if (((num == 0x47) && (num2 == 0x49)) && (num3 == 70)) { GifImage image = new GifImage(imgb); return image.GetImage(1); } if ((num == 0xff) && (num2 == 0xd8)) { return new Jpeg(imgb); } if (((num == 0) && (num2 == 0)) && ((num3 == 0) && (num4 == 12))) { return new Jpeg2000(imgb); } if (((num == 0xff) && (num2 == 0x4f)) && ((num3 == 0xff) && (num4 == 0x51))) { return new Jpeg2000(imgb); } if (((num == PngImage.PNGID[0]) && (num2 == PngImage.PNGID[1])) && ((num3 == PngImage.PNGID[2]) && (num4 == PngImage.PNGID[3]))) { return PngImage.GetImage(imgb); } if ((num == 0xd7) && (num2 == 0xcd)) { return new ImgWMF(imgb); } if ((num == 0x42) && (num2 == 0x4d)) { return BmpImage.GetImage(imgb); } if ((((num == 0x4d) && (num2 == 0x4d)) && ((num3 == 0) && (num4 == 0x2a))) || (((num == 0x49) && (num2 == 0x49)) && ((num3 == 0x2a) && (num4 == 0)))) { RandomAccessFileOrArray s = null ; try { s = new RandomAccessFileOrArray(imgb); Image tiffImage = TiffImage.GetTiffImage(s, 1); if (tiffImage.OriginalData == null ) { tiffImage.OriginalData = imgb; } return tiffImage; } finally { if (s != null ) { s.Close(); } } } throw new IOException(MessageLocalization.GetComposedMessage( "the.byte.array.is.not.a.recognized.imageformat" )); } |
該方法根據(jù)參數(shù)獲取圖片實例的方式比較多,例如:Image,PdfTemplate,PRIndirectReference,byte[],Stream,string ,Uri等等,以上給出了根據(jù)Image和byte[]獲取ItextSharp的image實例。
4.Image的ScaleAbsolute():設(shè)置圖片信息。
1
2
3
4
5
6
7
8
9
|
public void ScaleAbsolute( float newWidth, float newHeight) { this .plainWidth = newWidth; this .plainHeight = newHeight; float [] matrix = this .Matrix; this .scaledWidth = matrix[6] - matrix[4]; this .scaledHeight = matrix[7] - matrix[5]; this .WidthPercentage = 0f; } |
以上代碼可以看出,設(shè)置圖片的信息主要包括高度、寬度、排列等信息。
5.Anchor類的Process()方法:重寫鏈接的處理方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public override bool Process(IElementListener listener) { try { bool flag = ( this .reference != null ) && this .reference.StartsWith( "#" ); bool flag2 = true ; foreach (Chunk chunk in this .Chunks) { if ((( this .name != null ) && flag2) && !chunk.IsEmpty()) { chunk.SetLocalDestination( this .name); flag2 = false ; } if (flag) { chunk.SetLocalGoto( this .reference.Substring(1)); } else if ( this .reference != null ) { chunk.SetAnchor( this .reference); } listener.Add(chunk); } return true ; } catch (DocumentException) { return false ; } } |
以上方法可以看到,該方法是在本類中被重寫,用以處理鏈接的相關(guān)信息。
6.PageSize:設(shè)置紙張的類型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
public class PageSize { // Fields public static readonly Rectangle _11X17; public static readonly Rectangle A0; public static readonly Rectangle A1; public static readonly Rectangle A10; public static readonly Rectangle A2; public static readonly Rectangle A3; public static readonly Rectangle A4; public static readonly Rectangle A4_LANDSCAPE; public static readonly Rectangle A5; public static readonly Rectangle A6; public static readonly Rectangle A7; public static readonly Rectangle A8; public static readonly Rectangle A9; public static readonly Rectangle ARCH_A; public static readonly Rectangle ARCH_B; public static readonly Rectangle ARCH_C; public static readonly Rectangle ARCH_D; public static readonly Rectangle ARCH_E; public static readonly Rectangle B0; public static readonly Rectangle B1; public static readonly Rectangle B10; public static readonly Rectangle B2; public static readonly Rectangle B3; public static readonly Rectangle B4; public static readonly Rectangle B5; public static readonly Rectangle B6; public static readonly Rectangle B7; public static readonly Rectangle B8; public static readonly Rectangle B9; public static readonly Rectangle CROWN_OCTAVO; public static readonly Rectangle CROWN_QUARTO; public static readonly Rectangle DEMY_OCTAVO; public static readonly Rectangle DEMY_QUARTO; public static readonly Rectangle EXECUTIVE; public static readonly Rectangle FLSA; public static readonly Rectangle FLSE; public static readonly Rectangle HALFLETTER; public static readonly Rectangle ID_1; public static readonly Rectangle ID_2; public static readonly Rectangle ID_3; public static readonly Rectangle LARGE_CROWN_OCTAVO; public static readonly Rectangle LARGE_CROWN_QUARTO; public static readonly Rectangle LEDGER; public static readonly Rectangle LEGAL; public static readonly Rectangle LEGAL_LANDSCAPE; public static readonly Rectangle LETTER; public static readonly Rectangle LETTER_LANDSCAPE; public static readonly Rectangle NOTE; public static readonly Rectangle PENGUIN_LARGE_PAPERBACK; public static readonly Rectangle PENGUIN_SMALL_PAPERBACK; public static readonly Rectangle POSTCARD; public static readonly Rectangle ROYAL_OCTAVO; public static readonly Rectangle ROYAL_QUARTO; public static readonly Rectangle SMALL_PAPERBACK; public static readonly Rectangle TABLOID; // Methods static PageSize(); public PageSize(); public static Rectangle GetRectangle( string name); } |
以上的類中,我們可以看到我們可以設(shè)置需要打印的紙張類型,根據(jù)實際情況可以選擇。在最下面我們看到了兩種方法,一個是PageSize()設(shè)置紙張大小,一個是GetRectangle()繪制矩形。
以上是對itextSharp組件的一些類和方法的簡單介紹,對于表格,單元格等等類的介紹就不再繼續(xù),有興趣的可以自己查看源代碼信息。
三.itextSharp組件實例:
上面介紹了itextSharp組件的背景、特性,以及組件的核心類和方法,在這里給出一個簡單的itextSharp組件操作的實例,這個實例只是一個簡單的介紹。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
|
/// <summary> /// 字體 /// </summary> private Font _font; /// <summary> /// 文檔大小 /// </summary> private Rectangle _rect; /// <summary> /// 文檔對象 /// </summary> private readonly Document _document; /// <summary> /// 基礎(chǔ)字體 /// </summary> private BaseFont _basefont; /// <summary> /// 構(gòu)造函數(shù) /// </summary> public PDFOperation() { _rect = PageSize.A4; _document = new Document(_rect); } /// <summary> /// 構(gòu)造函數(shù) /// </summary> /// <param name="type">頁面大小(如"A4")</param> public PDFOperation( string type) { if ( string .IsNullOrEmpty(type)) { throw new ArgumentNullException(type); } SetPageSize(type); _document = new Document(_rect); } /// <summary> /// 構(gòu)造函數(shù) /// </summary> /// <param name="type">頁面大小(如"A4")</param> /// <param name="marginLeft">內(nèi)容距左邊框距離</param> /// <param name="marginRight">內(nèi)容距右邊框距離</param> /// <param name="marginTop">內(nèi)容距上邊框距離</param> /// <param name="marginBottom">內(nèi)容距下邊框距離</param> public PDFOperation( string type, float marginLeft, float marginRight, float marginTop, float marginBottom) { if ( string .IsNullOrEmpty(type)) { throw new ArgumentNullException(type); } SetPageSize(type); _document = new Document(_rect, marginLeft, marginRight, marginTop, marginBottom); } /// <summary> /// 設(shè)置字體 /// </summary> public void SetBaseFont( string path) { if ( string .IsNullOrEmpty(path)) { throw new ArgumentNullException(path); } _basefont = BaseFont.CreateFont(path, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); } /// <summary> /// 設(shè)置字體 /// </summary> /// <param name="size">字體大小</param> public void SetFont( float size) { _font = new Font(_basefont, size); } /// <summary> /// 設(shè)置頁面大小 /// </summary> /// <param name="type">頁面大小(如"A4")</param> public void SetPageSize( string type) { if ( string .IsNullOrEmpty(type)) { throw new ArgumentNullException(type); } switch (type.Trim()) { //枚舉需要的文檔紙張大小 case "A3" : _rect = PageSize.A3; break ; case "A4" : _rect = PageSize.A4; break ; case "A8" : _rect = PageSize.A8; break ; } } /// <summary> /// 實例化文檔 /// </summary> /// <param name="os">文檔相關(guān)信息(如路徑,打開方式等)</param> public void GetInstance(Stream os) { if (os == null ) { throw new ArgumentNullException( "os" ); } PdfWriter.GetInstance(_document, os); } /// <summary> /// 打開文檔對象 /// </summary> /// <param name="os">文檔相關(guān)信息(如路徑,打開方式等)</param> public void Open(Stream os) { if (os == null ) { throw new ArgumentNullException( "os" ); } GetInstance(os); _document.Open(); } /// <summary> /// 關(guān)閉打開的文檔 /// </summary> public void Close() { _document.Close(); } /// <summary> /// 添加段落 /// </summary> /// <param name="content">內(nèi)容</param> /// <param name="fontsize">字體大小</param> public void AddParagraph( string content, float fontsize) { SetFont(fontsize); var pra = new Paragraph(content, _font); _document.Add(pra); } /// <summary> /// 添加段落 /// </summary> /// <param name="content">內(nèi)容</param> /// <param name="fontsize">字體大小</param> /// <param name="alignment">對齊方式(1為居中,0為居左,2為居右)</param> /// <param name="spacingAfter">段后空行數(shù)(0為默認值)</param> /// <param name="spacingBefore">段前空行數(shù)(0為默認值)</param> /// <param name="multipliedLeading">行間距(0為默認值)</param> public void AddParagraph( string content, float fontsize, int alignment, float spacingAfter, float spacingBefore, float multipliedLeading) { SetFont(fontsize); var pra = new Paragraph(content, _font) { Alignment = alignment }; if (spacingAfter != 0) { pra.SpacingAfter = spacingAfter; } if (spacingBefore != 0) { pra.SpacingBefore = spacingBefore; } if (multipliedLeading != 0) { pra.MultipliedLeading = multipliedLeading; } _document.Add(pra); } /// <summary> /// 添加圖片 /// </summary> /// <param name="path">圖片路徑</param> /// <param name="alignment">對齊方式(1為居中,0為居左,2為居右)</param> /// <param name="newWidth">圖片寬(0為默認值,如果寬度大于頁寬將按比率縮放)</param> /// <param name="newHeight">圖片高</param> public void AddImage( string path, int alignment, float newWidth, float newHeight) { if ( string .IsNullOrEmpty(path)) { throw new ArgumentNullException(path); } var img = Image.GetInstance(path); img.Alignment = alignment; // ReSharper disable once CompareOfFloatsByEqualityOperator if (newWidth != 0) { img.ScaleAbsolute(newWidth, newHeight); } else { if (img.Width > PageSize.A4.Width) { img.ScaleAbsolute(_rect.Width, img.Width * img.Height / _rect.Height); } } _document.Add(img); } /// <summary> /// 添加鏈接 /// </summary> /// <param name="content">鏈接文字</param> /// <param name="fontSize">字體大小</param> /// <param name="reference">鏈接地址</param> public void AddAnchorReference( string content, float fontSize, string reference) { if ( string .IsNullOrEmpty(content)) { throw new ArgumentNullException(content); } SetFont(fontSize); var auc = new Anchor(content, _font) { Reference = reference }; _document.Add(auc); } /// <summary> /// 添加鏈接點 /// </summary> /// <param name="content">鏈接文字</param> /// <param name="fontSize">字體大小</param> /// <param name="name">鏈接點名</param> public void AddAnchorName( string content, float fontSize, string name) { if ( string .IsNullOrEmpty(content)) { throw new ArgumentNullException(content); } SetFont(fontSize); var auc = new Anchor(content, _font) { Name = name }; _document.Add(auc); } |
以上的實例比較的簡單,主要是用作簡單介紹組件的用法。如果需要將組件設(shè)計的更加通用,我們可以將組件的相關(guān)類和方法重寫,并且可以開發(fā)一套cs或者bs程序,實現(xiàn)組件的圖形化操作,圖形化操作生成文件模板。文件模板可以將相關(guān)信息序列化(json或者二進制),在項目中直接加載模型,并將數(shù)據(jù)綁定在模板中,實現(xiàn)pdf打印的動態(tài)配置。
這個程序的開發(fā)難度一般,如果有興趣的可以自行開發(fā)一套工具,可以更好的實現(xiàn)我們的項目pdf打印功能。
四.總結(jié):
上面介紹了itextSharp組件的相關(guān)信息,在這個系列的組件介紹中,對于組件的介紹都是比較的簡單,旨在向大家介紹這個組件,在實際的開發(fā)中,我們可以根據(jù)實際情況自行選擇相應(yīng)的組件,組件沒有絕對的好壞,只有合適的場景。
以上講解若有錯誤和不足之處,希望大家多多見諒和多多提出意見和建議。也希望大家多多支持服務(wù)器之家。
原文鏈接:http://www.cnblogs.com/pengze0902/p/6178499.html