1、目标
在pdf中生成一个可变表头的表格,并向其中填充数据。通过泛型动态的生成表头,通过反射动态获取实体类(我这里是User)的get方法动态获得数据,从而达到动态生成表格。
每天生成一个文件夹存储生成的pdf文件(文件夹的命名是年月日时间戳),如:20151110
生成的文件可能在毫秒级别,故文件的命名规则是"到毫秒的时间戳-uuid",如:20151110100245690-ece540e5-7737-4ab7-b2d6-87bc23917c8c.pdf
通过读取properties文件动态获取文件存储的跟目录。
2、所需的jar
这里通过itex插件进行pdf的生成,需要的jar包括以下几个
3、编码实现
1)、实体类
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
|
package com.zcr.until; public class User { private String name; private int age ; private float height; private String adress; private String sex; private String jj; public String getJj() { return jj; } public void setJj(String jj) { this .jj = jj; } public User() { } public User(String name, int age, float height,String adress,String sex,String jj) { this .name = name; this .age = age; this .height = height; this .adress = adress; this .sex = sex; this .jj = jj; } public String getAdress() { return adress; } public void setAdress(String adress) { this .adress = adress; } public String getSex() { return sex; } public void setSex(String sex) { this .sex = sex; } public String getName() { return name; } public void setName(String name) { this .name = name; } public int getAge() { return age; } public void setAge( int age) { this .age = age; } public float getHeight() { return height; } public void setHeight( float height) { this .height = height; } } |
2)、properties文件
pdfPath=E\:/appDataPdf
3)、读取properties文件,获取pdf存储的路径
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
|
package com.zcr.until; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class GetFilePlace { /** * 读取文件,获取excel保存的根目录 * @return excel保存的根目录 */ public String getFilePath() { String dir = System.getProperty( "user.dir" ); //获得tomcat所在的工作路径 //获取到存储了文件存储位置的filedir.properties 文件路径 --->java Project的文件路径 String realDir = dir + File.separator + "src" + File.separator + "META-INF" + File.separator + "filedir.properties" ; //Web project存储路径 /*String realDir = dir.substring(0, dir.length()-4) + File.separator +"webapps" + File.separator + "generateExcels" + File.separator + "classes" + File.separator + "META-INF" + File.separator + "config" + File.separator + "filedir.properties"; */ return realDir; } /** * 获取filePath路径【properities文件】中key对应的值, * @param filePath properities文件路径【包含properities文件】 * @param key 要查找的key值 * @return key对应的value */ public String GetValueByKey(String filePath, String key) { Properties pps = new Properties(); try { InputStream in = new BufferedInputStream (new FileInputStream(filePath)); pps.load(in); String value = pps.getProperty(key); in.close(); return value; }catch (IOException e) { e.printStackTrace(); return null; } } /** * 查询properities文件中可以对应的存储地点 * @param key 查询主键 * @return key对应的存储地址 */ public String getFileDirFromProperties(String key) { return GetValueByKey(getFilePath(),key); } } |
4)、获取当天存在的文件路径,不存在则生成一个新的文件夹
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
|
package com.zcr.service; import java.io.File; import java.text.SimpleDateFormat; import java.util.Calendar; public class GenerateFold { /** * 查询当前生成的excel需要存在在哪个路径,如果存在则存储在相应的位置,否则生成改目录, 每天生成一个文件夹,文件夹的命名规则为 年月日的时间戳 * @param foldName 生成excel保存路径 * @return 现在的excel需要保存路径 */ public String getFold(String foldName) { SimpleDateFormat format = new SimpleDateFormat( "yyyyMMdd" ); String todayStr = format.format(Calendar.getInstance().getTime()); String foldPath = foldName + File.separator + todayStr; File file = new File(foldPath); if (!file.exists() && !file.isDirectory()) { System.out.println( "不存在" ); file.mkdirs(); } else { System.out.println( "存在" ); } return foldPath; } } |
5)、生成文件的名字
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
|
package com.zcr.until; import java.io.File; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.UUID; /** * 生成文件名字 * @author zcr * */ public class GenerateFileName { /** * 根据文件类别生成文件的名字,文件的命名规则是:文件目录/生成时间-uuid(全球唯一编码).文件类别 * @param fileDir 文件的存储路径 * @param fileType 文件的类别 * @return 文件的名字 */ public String generateFileName(String fileDir,String fileType) { String saveFileName = "" ; SimpleDateFormat format = new SimpleDateFormat( "yyyyMMddHHmmssSS" ); saveFileName += format.format(Calendar.getInstance().getTime()); UUID uuid = UUID.randomUUID(); //全球唯一编码 saveFileName += "-" + uuid.toString(); saveFileName += "." + fileType; saveFileName = fileDir + File.separator + saveFileName; return saveFileName; } } |
6)、生成pdf
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
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
|
package com.zcr.service; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import com.lowagie.text.Document; import com.lowagie.text.DocumentException; import com.lowagie.text.Element; import com.lowagie.text.Font; import com.lowagie.text.PageSize; import com.lowagie.text.Phrase; import com.lowagie.text.pdf.BaseFont; import com.lowagie.text.pdf.PdfPCell; import com.lowagie.text.pdf.PdfPTable; import com.lowagie.text.pdf.PdfWriter; import com.zcr.until.GenerateFileName; import com.zcr.until.GetFilePlace; import com.zcr.until.User; /** * 生成pdf * @author zcr * */ public class CreatePdf { Document document = new Document(); // 建立一个Document对象 private static Font headfont; // 设置字体大小 private static Font keyfont; // 设置字体大小 private static Font textfont; // 设置字体大小 static { //中文格式 BaseFont bfChinese; try { // 设置中文显示 bfChinese = BaseFont.createFont( "STSong-Light" , "UniGB-UCS2-H" ,BaseFont.NOT_EMBEDDED); headfont = new Font(bfChinese, 10 , Font.BOLD); // 设置字体大小 keyfont = new Font(bfChinese, 8 , Font.BOLD); // 设置字体大小 textfont = new Font(bfChinese, 8 , Font.NORMAL); // 设置字体大小 } catch (Exception e) { e.printStackTrace(); } } /** * 文成文件 * @param file 待生成的文件名 */ public CreatePdf(File file) { document.setPageSize(PageSize.A4); // 设置页面大小 try { PdfWriter.getInstance(document, new FileOutputStream(file)); document.open(); } catch (Exception e) { e.printStackTrace(); } } public CreatePdf() { } public void initFile(File file) { document.setPageSize(PageSize.A4); // 设置页面大小 try { PdfWriter.getInstance(document, new FileOutputStream(file)); document.open(); } catch (Exception e) { e.printStackTrace(); } } int maxWidth = 520 ; /** * 为表格添加一个内容 * @param value 值 * @param font 字体 * @param align 对齐方式 * @return 添加的文本框 */ public PdfPCell createCell(String value, Font font, int align) { PdfPCell cell = new PdfPCell(); cell.setVerticalAlignment(Element.ALIGN_MIDDLE); cell.setHorizontalAlignment(align); cell.setPhrase( new Phrase(value, font)); return cell; } /** * 为表格添加一个内容 * @param value 值 * @param font 字体 * @return 添加的文本框 */ public PdfPCell createCell(String value, Font font) { PdfPCell cell = new PdfPCell(); cell.setVerticalAlignment(Element.ALIGN_MIDDLE); cell.setHorizontalAlignment(Element.ALIGN_CENTER); cell.setPhrase( new Phrase(value, font)); return cell; } /** * 为表格添加一个内容 * @param value 值 * @param font 字体 * @param align 对齐方式 * @param colspan 占多少列 * @return 添加的文本框 */ public PdfPCell createCell(String value, Font font, int align, int colspan) { PdfPCell cell = new PdfPCell(); cell.setVerticalAlignment(Element.ALIGN_MIDDLE); cell.setHorizontalAlignment(align); cell.setColspan(colspan); cell.setPhrase( new Phrase(value, font)); return cell; } /** * 为表格添加一个内容 * @param value 值 * @param font 字体 * @param align 对齐方式 * @param colspan 占多少列 * @param boderFlag 是否有有边框 * @return 添加的文本框 */ public PdfPCell createCell(String value, Font font, int align, int colspan, boolean boderFlag) { PdfPCell cell = new PdfPCell(); cell.setVerticalAlignment(Element.ALIGN_MIDDLE); cell.setHorizontalAlignment(align); cell.setColspan(colspan); cell.setPhrase( new Phrase(value, font)); cell.setPadding( 3 .0f); if (!boderFlag) { cell.setBorder( 0 ); cell.setPaddingTop( 15 .0f); cell.setPaddingBottom( 8 .0f); } return cell; } /** * 创建一个表格对象 * @param colNumber 表格的列数 * @return 生成的表格对象 */ public PdfPTable createTable( int colNumber) { PdfPTable table = new PdfPTable(colNumber); try { table.setTotalWidth(maxWidth); table.setLockedWidth( true ); table.setHorizontalAlignment(Element.ALIGN_CENTER); table.getDefaultCell().setBorder( 1 ); } catch (Exception e) { e.printStackTrace(); } return table; } public PdfPTable createTable( float [] widths) { PdfPTable table = new PdfPTable(widths); try { table.setTotalWidth(maxWidth); table.setLockedWidth( true ); table.setHorizontalAlignment(Element.ALIGN_CENTER); table.getDefaultCell().setBorder( 1 ); } catch (Exception e) { e.printStackTrace(); } return table; } public PdfPTable createBlankTable() { PdfPTable table = new PdfPTable( 1 ); table.getDefaultCell().setBorder( 0 ); table.addCell(createCell( "" , keyfont)); table.setSpacingAfter( 20 .0f); table.setSpacingBefore( 20 .0f); return table; } public <T> void generatePDF(String [] head,List<T> list, int colNum) { Class classType = list.get( 0 ).getClass(); // 创建一个只有5列的表格 PdfPTable table = createTable(colNum); // 添加备注,靠左,不显示边框 table.addCell(createCell( "APP信息列表:" , keyfont, Element.ALIGN_LEFT, colNum, false )); //设置表头 for ( int i = 0 ; i < colNum ; i++) { table.addCell(createCell(head[i], keyfont, Element.ALIGN_CENTER)); } if ( null != list && list.size() > 0 ) { int size = list.size(); for ( int i = 0 ; i < size ; i++) { T t = list.get(i); for ( int j = 0 ; j < colNum ; j ++) { //获得首字母 String firstLetter = head[j].substring( 0 , 1 ).toUpperCase(); //获得get方法,getName,getAge等 String getMethodName = "get" + firstLetter + head[j].substring( 1 ); Method method; try { //通过反射获得相应的get方法,用于获得相应的属性值 method = classType.getMethod(getMethodName, new Class[]{}); try { System.out.print(getMethodName + ":" + method.invoke(t, new Class[]{}) + "," ); //添加数据 table.addCell(createCell(method.invoke(t, new Class[]{}).toString(), textfont)); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } System.out.println( "" ); } } try { //将表格添加到文档中 document.add(table); } catch (DocumentException e) { e.printStackTrace(); } //关闭流 document.close(); } /** * 提供外界调用的接口,生成以head为表头,list为数据的pdf * @param head //数据表头 * @param list //数据 * @return //excel所在的路径 */ public <T> String generatePDFs(String [] head,List<T> list) { final String FilePath = "pdfPath" ; String saveFilePathAndName = "" ; //获得存储的根目录 String savePath = new GetFilePlace().getFileDirFromProperties(FilePath); //获得当天存储的路径,不存在则生成当天的文件夹 String realSavePath = new GenerateFold().getFold(savePath); saveFilePathAndName = new GenerateFileName().generateFileName(realSavePath, "pdf" ); File file = new File(saveFilePathAndName); try { file.createNewFile(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } initFile(file); try { file.createNewFile(); //生成一个pdf文件 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } new CreatePdf(file).generatePDF(head,list,head.length); return saveFilePathAndName; } } |
7)、测评函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public static void main(String[] args) { System.out.println( "begin" ); String [] head = { "name" , "sex" , "adress" , "height" , "age" , "jj" }; List<User> list = new ArrayList<User>(); User user1 = new User( "zhangsan" , 1 , 1 .1f, "北京" , "男" , "AA" ); User user2 = new User( "lisi" , 22222 , 3 .2f, "上海" , "女" , "BB" ); list.add(user1); list.add(user2); String filePath = new CreatePdf().generatePDFs(head,list); System.out.println(filePath); System.out.println( "end" ); } |
8)、测试结果
9)、文件内容如下
4、其他相关链接
生成可变表头excel:http://www.cnblogs.com/0201zcr/p/4950619.html
java如何在pdf中生成表格,我相信通过这个简单实例演示有了大概的认识,大家可以动手去试验一下,看看会不会达到预想的效果。