生成pdf文字和表格
先看效果
介绍
java项目,使用apache的pdfbox工具,可分页,自定义列
依赖
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.22</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>fontbox</artifactId>
<version>2.0.22</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>xmpbox</artifactId>
<version>2.0.22</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>preflight</artifactId>
<version>2.0.22</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
<version>2.0.22</version>
</dependency>
基本使用的api
创建一个页面
String filePath = "D:\\imgTest\\test.pdf";
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
document.save(new File(filePath));
执行后就可以在 D:\imgTest 目录下看到test.pdf 打开后有一个空白页
写入文字
PDDocument document = new PDDocument();
PDFont font = PDType0Font.load(document,new File("D://imgtest/font/simfang.ttf"));
PDPage page = new PDPage();
PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.beginText();
contentStream.setFont(font,20.0f);
contentStream.showText("写入文字");
contentStream.endText();
contentStream.close();
document.addPage(page);
document.save(new File(filePath));
但是可以看到文字在最后显示
文字从顶部写入
计算出page高度 文字高度 然后就得到了书写的位置
contentStream.newLineAtOffset(0,pageHeight - fontHeight);
PDDocument document = new PDDocument();
PDFont font = PDType0Font.load(document,new File("D://imgtest/font/simfang.ttf"));
PDPage page = new PDPage();
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
float fontSize = 20.0f;
float fontHeight = font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * fontSize;
float fontWidth = font.getAverageFontWidth() / 1000 * fontSize;
PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.beginText();
contentStream.setFont(font,fontSize);
contentStream.setLeading(10.0f);
contentStream.newLineAtOffset(0,pageHeight - fontHeight);
contentStream.showText("写入文字");
contentStream.endText();
contentStream.close();
document.addPage(page);
document.save(new File(filePath));
写入多行文字并自动换行
如果写入一段文字的时候,要自动换行,
现在我们知道一个文字的宽度,可以算出一行总共可以写多少文字,这样就知道多少行了然后每行写入就可以了
代码
PDDocument document = new PDDocument();
PDFont font = PDType0Font.load(document,new File("D://imgtest/font/simfang.ttf"));
PDPage page = new PDPage();
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
float fontSize = 20.0f;
float fontHeight = font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * fontSize;
float fontWidth = font.getAverageFontWidth() / 1000 * fontSize;
int lineNum = (int)Math.floor(pageWidth/fontWidth);
String text = "初升的太阳照耀大地,北部战区空军某雷达站营区披上了一层金色的外衣。祖国东极,一年中最冷的季节,这样的光,给人以希望和温暖。" +
" 6时55分,上等兵孙野推开雷达方舱的大门,揉了揉酸痛的双眼,沐浴着第一缕阳光,脑海中浮现一句熟悉的歌词:“我把太阳迎进祖国。”迎接阳光,这是雷达兵最自豪的时刻。\n" +
" 这一刻,一级军士长王传星带着“徒弟”走进方舱值班。在这位技术骨干心中,雷达兵的眼睛,就是祖国的眼睛,使命重如泰山,须臾不可懈怠。雷达屏幕上,闪烁的光标汇在一起,那是他和战友们心头永远的璀璨。\n" +
" 这一刻,驾驶员刘磊再次出发踏上征程。一次次驾车行驶在熟悉的山路上,他陪伴着战友,也了解了很多不为人知的故事。守护着他们的坚强与坚韧,见证着他们的笑与泪,这位老兵决心成为战友身边和煦的光。\n" +
" 这一刻,年轻骨干李航宇和李玉溪全副武装来到了曙光初照的训练场,备战即将来临的上级比武。为了心中的目标,他们把班长当作标杆;为了成为像班长那样的“光”,他们一往无前,奋力冲锋。\n" +
" “我把太阳迎进祖国,太阳把光热洒给万里山河,我持枪向太阳致以军礼,请它也带上我的光、我的热……”\n" +
" 新年来临,在这个边防雷达站,许多官兵都在守望中找到了属于自己的光。为梦想而追光,他们有怎样的收获和成长,又有怎样的期待和展望?请看来自祖国东极某雷达站的报道。\n" +
" 下连之初,班长就曾对孙野说,雷达站驻地太阳升起的时间,比他的家乡福建早了一个多小时。作为东极雷达兵,每当阳光照耀大地,他们感受更多的是肩头的责任。\n" +
" “阳光在哪里,坚守就在哪里。”在雷达站官兵心中,头上的阳光很暖,肩上的责任很重,脚下的路很长";
PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.beginText();
contentStream.setFont(font,fontSize);
contentStream.setLeading(fontHeight);
List<String> textList = handleText(text,lineNum);
contentStream.newLineAtOffset(0,pageHeight - fontHeight);
for(int i=0;i<textList.size();i++){
log.info(textList.get(i));
contentStream.showText(textList.get(i));
contentStream.newLine();
}
contentStream.endText();
contentStream.close();
document.addPage(page);
document.save(new File(filePath));
注意换行写入使用的方法
contentStream.beginText();
contentStream.setFont(font,fontSize);
contentStream.setLeading(fontHeight);
for ...{
contentStream.showText(内容);
contentStream.newLine();
}
文字内容基本就是这样了,可以根据自己的方式添加padding 和 margin 也就是在pageWidth pageHeight 上进行调整
自己可以试试
表格
画一条横线和竖线
PDDocument document = new PDDocument();
PDPage page = new PDPage();
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.moveTo(0, pageHeight/2);//横线
contentStream.lineTo(pageWidth, pageHeight/2);//横线
contentStream.stroke();//横线
contentStream.moveTo(pageWidth/2, pageHeight);//竖线
contentStream.lineTo(pageWidth/2, 0);//竖线
contentStream.stroke();//竖线
contentStream.close();
document.addPage(page);
document.save(new File(filePath));
画一个简单的表格(10 X 5 的表格)
11 条横线 6条数线
这个只是为了画格子,长度和宽度都是自定的,如果写入文字的话就得考虑文字超出的问题,格子的长度和高度就不能是自定义的了
PDDocument document = new PDDocument();
PDPage page = new PDPage();
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
PDPageContentStream contentStream = new PDPageContentStream(document, page);
float rowNum = (pageHeight - 20) / 10;
float colNum = (pageWidth - 20) / 6;
for (int i = 0; i <= 11; i++) {
float row = pageHeight - 10 - i * rowNum;
contentStream.moveTo(10, row);
contentStream.lineTo(pageWidth - 10, row);
contentStream.stroke();
}
for (int i = 0; i <= 6; i++) {
float col = pageWidth - 10 - i * colNum;
contentStream.moveTo(col, 10);
contentStream.lineTo(col, pageHeight - 10);
contentStream.stroke();
}
contentStream.close();
document.addPage(page);
document.save(new File(filePath));
表格中写入文字
考虑一个问题,先画表格还是先写文字
其实都可以
主要的问题是要考虑 一行中,每个列 文字的长度,如果换行的话 文字的高度和最高的那一列,找到这个最高值就知道这一行最下面边的位置了
完整代码
因为内容比较多,单独封装了一个类
@Slf4j
class Table {
private float fontWidth;
private float fontHeight;
private float pageHeight;
private float pageWidth;
private PDPageContentStream contentStream;
private PDFont font;
private float padding = 2f;
private float pageMargin = 10f;
private float fontSize = 20.0f;
private String[] header;
private int[] cellSpan;
private PDPage page;
private float courY;
private float leading = 20f;
private List<String[]> contexts;
private float[] cellWidth;
private float[] courXPosion;
public Table(PDPage page, PDPageContentStream contentStream, PDFont font, int[] cellSpan, String[] header, List<String[]> contexts) {
this.contentStream = contentStream;
this.page = page;
this.font = font;
this.pageWidth = this.page.getMediaBox().getWidth();
this.pageHeight = this.page.getMediaBox().getHeight();
this.fontHeight = font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000f * fontSize;
this.fontWidth = font.getAverageFontWidth() / 1000f * fontSize;
this.courY = pageHeight - pageMargin;
this.header = header;
this.cellSpan = cellSpan;
this.contexts = contexts;
courXPosion = new float[header.length + 1];
cellWidth = new float[header.length];
courXPosion[0] = pageMargin;
for (int i = 0; i < cellSpan.length; i++) {
float width = (pageWidth - pageMargin * 2) * (cellSpan[i] / 100f);
courXPosion[i + 1] = courXPosion[i] + width;
cellWidth[i] = width;
}
contexts.add(0, header);
}
public void createTable() throws IOException {
//画第一条横线
contentStream.moveTo(pageMargin, courY);
contentStream.lineTo(pageWidth - pageMargin, courY);
contentStream.stroke();
//填充内容
for (int i = 0; i < contexts.size(); i++) {
courY = courY - padding - fontHeight;
String[] rows = contexts.get(i);
handleData(rows);
}
//统一画竖线 最后画就可以
for (int i = 0; i < courXPosion.length; i++) {
contentStream.moveTo(courXPosion[i], pageHeight - pageMargin);
contentStream.lineTo(courXPosion[i], courY);
contentStream.stroke();
}
}
public void handleData(String[] data) throws IOException {
int maxLineNum = 1;
float courX = pageMargin + padding;
for (int i = 0; i < data.length; i++) {
int lineNum = writeText(data[i], cellWidth[i] - padding * 2, courX);
maxLineNum = lineNum > maxLineNum ? lineNum : maxLineNum;
courX = courX + cellWidth[i];
}
courY = courY - padding - fontHeight * (maxLineNum - 1 ) - leading * (20f / 72f);
contentStream.moveTo(pageMargin, courY);
contentStream.lineTo(pageWidth - pageMargin, courY);
contentStream.stroke();
}
public int writeText(String text, float cellWidth, float x) throws IOException {
int lineNum = (int) Math.floor(cellWidth / fontWidth);
List<String> textList = handleText(text, lineNum);
contentStream.beginText();
contentStream.setFont(font, fontSize);
contentStream.setLeading(leading);
contentStream.newLineAtOffset(x, courY);
for (int i = 0; i < textList.size(); i++) {
//log.info(textList.get(i));
contentStream.showText(textList.get(i));
contentStream.newLine();
}
contentStream.endText();
return textList.size();
}
public List<String> handleText(String text, int lineNum) {
text = text.replace("\n", "");
text = StringUtils.deleteWhitespace(text);
List<String> list = new ArrayList<>();
if (text.length() <= lineNum) {
list.add(text);
return list;
}
while (text.length() > lineNum) {
list.add(text.substring(0, lineNum));
text = text.substring(lineNum);
}
if (text.length() > 0) {
list.add(text);
}
return list;
}
}
测试调用
@Test
public void test6() throws IOException {
PDDocument document = new PDDocument();
PDPage page = new PDPage();
PDFont font = PDType0Font.load(document, new File("D://imgtest/font/simfang.ttf"));
PDPageContentStream contentStream = new PDPageContentStream(document, page);
//组装内容
String[] header = new String[]{"序号", "名称", "作者", "时间", "内容"};
List<String[]> listText =
IntStream.range(0, 2)
.mapToObj(row ->
new String[]{String.valueOf(row + 1),
"《沁园春·雪》",
"毛泽东",
"1936",
"北国风光,千里冰封,万里雪飘。望长城内外,惟余莽莽;大河上下,顿失滔滔。山舞银蛇,原驰蜡象,欲与天公试比高。须晴日,看红装素裹,分外妖娆。江山如此多娇,引无数英雄竞折腰。惜秦皇汉武,略输文采;唐宗宋祖,稍逊风骚。一代天骄,成吉思汗,只识弯弓射大雕。俱往矣,数风流人物,还看今朝。"}
).collect(Collectors.toList());
//提前设置好列比例,可以自己调整,只要保证最后是100就行
int[] cellSpan = {10, 25, 15, 15, 35};
Table table = new Table(page, contentStream, font, cellSpan, header, listText);
table.createTable();
contentStream.close();
document.addPage(page);
document.save(new File(filePath));
}
效果展示
最后
好了以上就是完整的代码和测试用例,当然还有比较多的问题
比如文章来源:https://www.toymoban.com/news/detail-802450.html
- 如果这一页满了该怎么办?
- 如果要水平和垂直居中
- 比如要插入图片
有需要的小伙伴可以私信讨论,或者回复索要代码文章来源地址https://www.toymoban.com/news/detail-802450.html
到了这里,关于最新 生成pdf文字和表格的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!