目录
需求
客户要求根据报告模板写报告内容,
需求功能:
1.根据报告文件生成报告模板XML(报告文件包括 PDF ,WORD)
2.向模板XML文件中添加内容(文字,表格)(可在xml文件中添加,或在程序中动态添加)
3.根据配置的模板XML生成报告文件(生成文件 PDF,WORD)
技术应用
框架
IText Pdf
1.Itex Pdf 写 Pdf 文件
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.lowagie.text.pdf.PdfTable;
import com.spasvo.export.handle.impl.PdfExportHandle;
import com.spasvo.export.node.INode;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class TestPdfWriter {
public static void main(String[] args) {
Document doc = new Document(PageSize.A4);
PdfWriter contentWriter = null;
try {
contentWriter = PdfWriter.getInstance(doc, new FileOutputStream("test.pdf"));
Font font = new Font( BaseFont.createFont("C:\\Windows\\Fonts\\simsun.ttc,0",
BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED), 12);
doc.open();
Paragraph paragraph = new Paragraph("第一章节",font);
Section chapter = new Chapter(paragraph,1);
chapter.add(new Paragraph("第一章节的内容",font));
Paragraph paragraph1 = new Paragraph("第二章节",font);
Section chapter1 = new Chapter(paragraph,2);
PdfPTable table = new PdfPTable(2);
table.addCell(new Paragraph("第一列",font));
table.addCell(new Paragraph("第二列",font));
table.addCell(new Paragraph("第一行第一列内容",font));
table.addCell(new Paragraph("第一行第二列内容",font));
chapter1.add(table);
chapter1.addSection(new Paragraph("第一小节",font),1);
doc.add(chapter);
doc.add(chapter1);
doc.close();
} catch (DocumentException | FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.输出结果
IText Rtf
利用RTF 生成docx 文件
import com.lowagie.text.*;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.rtf.RtfWriter2;
import com.spasvo.export.node.INode;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test5 {
public static void main(String[] args) {
Document doc = new Document(PageSize.A4);
RtfWriter2 contentWriter = null;
try {
contentWriter = RtfWriter2.getInstance(doc, new FileOutputStream("test.docx"));
Font font = new Font( BaseFont.createFont("C:\\Windows\\Fonts\\simsun.ttc,0",
BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED), 12);
font.setStyle(Font.NORMAL|Font.BOLD);
doc.open();
Paragraph paragraph = new Paragraph("第一章节",font);
Section chapter = new Chapter(paragraph,1);
chapter.add(new Paragraph("第一章节的内容",font));
Paragraph paragraph1 = new Paragraph("第二章节",font);
Section chapter1 = new Chapter(paragraph1,2);
Table table = new Table(2);
table.addCell(new Paragraph("第一列",font));
table.addCell(new Paragraph("第二列",font));
table.addCell(new Paragraph("第一行第一列内容",font));
table.addCell(new Paragraph("第一行第二列内容",font));
chapter.add(table);
Section section2 = chapter1.addSection(new Paragraph("第一小节",font),2);
Section section3 = section2.addSection(new Paragraph("第一小小节",font),3);
// chapter1.add(section2);
doc.add(chapter);
doc.add(chapter1);
doc.close();
} catch (DocumentException | IOException e) {
e.printStackTrace();
}
}
}
生成word 文件
POI
1.用到的类以及方法
类 XWPFDocument 这个是IBody 的实现类
java.util.List<IBodyElement>
getBodyElements()
返回所有的内容
java.util.Iterator<IBodyElement>
返回所有内容的迭代器
接口IBodyElement 实现类 XWPFParagraph, XWPFSDT, XWPFTable
IBody
getBody()
BodyElementType
getElementType()
POIXMLDocumentPart
getPart()
BodyType
getPartType()
接口 IBody 实现类 XWPFAbstractFootnoteEndnote, XWPFDocument, XWPFEndnote, XWPFFooter, XWPFFootnote, XWPFHeader, XWPFHeaderFooter, XWPFTableCell
java.util.List<IBodyElement>
getBodyElements()
返回一个带有段落和表格的迭代器,按照它们在文本中出现的顺序。
XWPFParagraph
getParagraph(org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP p)
如果在这个页眉或页脚的段落列表中,参数ctTable中有一个对应的XWPFParagraph,方法将返回这个段落。如果没有对应的XWPFParagraph,方法将返回null
XWPFParagraph
getParagraphArray(int pos)
返回位置为pos的段落
java.util.List<XWPFParagraph>
getParagraphs()
返回包含页眉或页脚文本的段落。
POIXMLDocumentPart
getPart()
返回主体所属的Part,在向其他部分添加关系时需要该Part ,比如XWPFTableCell
BodyType
getPartType()
获取主体的PartType,例如DOCUMENT, HEADER, FOOTER, FOOTNOTE,
XWPFTable
getTable(org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl ctTable)
如果在这个头的表列表中有参数ctTable对应的XWPFTable,方法将返回这个表,如果没有对应的XWPFTable,方法将返回null
XWPFTable
getTableArray(int pos)
返回pos位置的表
XWPFTableCell
getTableCell(org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc cell)
返回Table所属的TableCell
java.util.List<XWPFTable>
getTables()
对于不使用段落的复杂情况,返回保存IBodyPart文本的表。
XWPFDocument
getXWPFDocument()
Return XWPFDocument
XWPFParagraph
insertNewParagraph(org.apache.xmlbeans.XmlCursor cursor)
在光标的位置插入新的段落
XWPFTable
insertNewTbl(org.apache.xmlbeans.XmlCursor cursor)
在光标位置插入一个新的Table。
void
insertTable(int pos, XWPFTable table)
在pos位置插入一个新表
类 XWPFParagraph 是 IBodyElement 的一个实现类
ParagraphAlignment
getAlignment()
返回将应用于该段文本的段落对齐。
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP
getCTP()
OfficeOpenXML 的接口
int
getIndentationFirstLine()
指定附加的缩进,将应用于父段的第一行。首行缩进
int
getIndentationLeft()
指定在从左到右的段落中,该段的左文本距与该段内容的左边缘之间,以及在从右到左的段落中,该段的右文本距与该段文本的右边缘之间的缩进(左对齐)
int
getIndentationRight()
右对齐
java.util.List<XWPFRun>
getRuns()
获取run 的listp - 一个段落。
r - 一段连续文本。
t - 一个文本范围。
java.lang.String
getStyle()
返回Style 标识,可以用来判断是否为标题java.lang.String
getText()
返回段落的文本内容,包括来自图片的文本和其中的sdt元素。
类 XWPFRun
void
addBreak()
Specifies that a break shall be placed at the current location in the run content.
void
addBreak(BreakClear clear)
Specifies that a break shall be placed at the current location in the run content.
void
addBreak(BreakType type)
Specifies that a break shall be placed at the current location in the run content.
void
addCarriageReturn()
Specifies that a carriage return shall be placed at the current location in the run content.
org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline
addChart(java.lang.String chartRelId)
this method add chart template into document
XWPFPicture
addPicture(java.io.InputStream pictureData, int pictureType, java.lang.String filename, int width, int height)
Adds a picture to the run.
void
addTab()
指定在运行内容的当前位置放置一个选项卡。
int
getCharacterSpacing()
java.lang.String
getColor()
Get text color.
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR
getCTR()
Get the currently used CTR object,获取Run节点的 OpenXML 节点
XWPFDocument
getDocument()
java.util.List<XWPFPicture>
getEmbeddedPictures()
返回运行的嵌入图片。
org.openxmlformats.schemas.wordprocessingml.x2006.main.STEm.Enum
getEmphasisMark()
获取运行的重点标记值。
java.lang.String
getFontFamily()
获取应使用要显示此运行的文本内容的字体。.
java.lang.String
getFontFamily(XWPFRun.FontCharRange fcr)
Gets the font family for the specified font char range.
java.lang.String
getFontName()
Alias for getFontFamily()
int
getFontSize()
指定在显示此运行内容时应用于所有非复杂脚本字符的字体大小。
int
getKerning()
java.lang.String
getLang()
Get the language tag associated with this run, if any.
XWPFParagraph
getParagraph()
Deprecated.use getParent() instead
IRunBody
getParent()
Get the currently referenced paragraph/SDT object
java.lang.String
getPhonetic()
java.lang.String
getPictureText()
Returns text embedded in pictures
protected org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr
getRunProperties(boolean create)
Get the run properties for the run.
java.lang.String
getStyle()
返回这次运行的样式ID。
VerticalAlign
getSubscript()
Deprecated.use
XWPFRun.getVerticalAlignment
java.lang.String
getText(int pos)
Return the string content of this text run
org.openxmlformats.schemas.wordprocessingml.x2006.main.STHighlightColor.Enum
getTextHightlightColor()
Gets the highlight color for the run
int
getTextPosition()
This element specifies the amount by which text shall be raised or lowered for this run in relation to the default baseline of the surrounding non-positioned text.
int
getTextScale()
获取当前文本缩放值。
UnderlinePatterns
getUnderline()
获取运行所需的下划线设置。
java.lang.String
getUnderlineColor()
获取运行下划线的颜色(如果有的话)。
org.openxmlformats.schemas.wordprocessingml.x2006.main.STThemeColor.Enum
getUnderlineThemeColor()
获取运行的下划线主题颜色(如果有的话)。
org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalAlignRun.Enum
getVerticalAlignment()
获取垂直对齐值
boolean
isBold()
当在文档中显示时,粗体属性是否应用于本次运行的内容中的所有非复杂脚本字符
boolean
isCapitalized()
boolean
isDoubleStrikeThrough()
Specifies that the contents of this run shall be displayed with a double horizontal line through the center of the line.
boolean
isEmbossed()
boolean
isHighlighted()
boolean
isImprinted()
boolean
isItalic()
当在文档中显示时,斜体属性是否应应用于此运行的内容中的所有非复杂脚本字符。
boolean
isShadowed()
boolean
isSmallCaps()
boolean
isStrike()
Deprecated.
boolean
isStrikeThrough()
Specifies that the contents of this run shall be displayed with a single horizontal line through the center of the line.
boolean
isVanish()
Get the vanish (hidden text) value
void
removeBreak()
void
removeCarriageReturn()
void
removeTab()
void
setBold(boolean value)
Whether the bold property shall be applied to all non-complex script characters in the contents of this run when displayed in a document.
void
setCapitalized(boolean value)
void
setCharacterSpacing(int twips)
void
setColor(java.lang.String rgbStr)
Set text color.
void
setDoubleStrikethrough(boolean value)
Specifies that the contents of this run shall be displayed with a double horizontal line through the center of the line.
void
setEmbossed(boolean value)
void
setEmphasisMark(java.lang.String markType)
Set the emphasis mark for the run.
void
setFontFamily(java.lang.String fontFamily)
Specifies the fonts which shall be used to display the text contents of this run.
void
setFontFamily(java.lang.String fontFamily, XWPFRun.FontCharRange fcr)
Specifies the fonts which shall be used to display the text contents of this run.
void
setFontSize(int size)
Specifies the font size which shall be applied to all non complex script characters in the contents of this run when displayed.
void
setImprinted(boolean value)
void
setItalic(boolean value)
Whether the bold property shall be applied to all non-complex script characters in the contents of this run when displayed in a document
void
setKerning(int kern)
void
setLang(java.lang.String lang)
Set the language tag associated with this run.
void
setShadow(boolean value)
void
setSmallCaps(boolean value)
void
setStrike(boolean value)
Deprecated.
void
setStrikeThrough(boolean value)
Specifies that the contents of this run shall be displayed with a single horizontal line through the center of the line.
void
setStyle(java.lang.String styleId)
Set the style ID for the run.
void
setSubscript(VerticalAlign valign)
Specifies the alignment which shall be applied to the contents of this run in relation to the default appearance of the run's text.
void
setText(java.lang.String value)
Sets the text of this text run
void
setText(java.lang.String value, int pos)
Sets the text of this text run in the
void
setTextHighlightColor(java.lang.String colorName)
Set the highlight color for the run.
void
setTextPosition(int val)
This element specifies the amount by which text shall be raised or lowered for this run in relation to the default baseline of the surrounding non-positioned text.
void
setTextScale(int percentage)
Set the text expand/collapse scale value.
void
setUnderline(UnderlinePatterns value)
Specifies that the contents of this run should be displayed along with an underline appearing directly below the character height.
void
setUnderlineColor(java.lang.String color)
Set the underline color for the run's underline, if any.
void
setUnderlineThemeColor(java.lang.String themeColor)
Set the underline theme color for the run's underline, if any.
void
setVanish(boolean value)
The vanish (hidden text) property for the run.
void
setVerticalAlignment(java.lang.String verticalAlignment)
Set the vertical alignment of the run.
java.lang.String
text()
Returns the string version of the text, with tabs and carriage returns in place of their xml equivalents.
java.lang.String
toString()
Returns the string version of the text and the phonetic string
2.word 文档的格式
docx格式的word文件实际上是一个压缩包,通过修改后缀名为rar后可用winrar打开,里面实际上是xml文件
这是因为docx文件遵循了OfficeOpenXML规范,该规范内容很多,有兴趣的同学可以自行下载翻阅。打开上图的word文件夹
这里我们需要关注的是document.xml和numbering.xml
其中document.xml包含了文档的主要结构与主要文本内容,其形式有点像HTML语言
而numbering.xml与自动序号有关,由于非常复杂,文本暂不讨论,主要原因是自动序号实际上是在渲染时进行实时计算的,并且需要有不同的层次。
在开始使用Apache POI解析之前,我们需要了解一些关于docx文件结构的基本概念
整个文档是一个document,document的子元素为Paragraph(段落)和Table(表格)这和我们日常使用word的经验基本相符,Paragraph的子元素为Run,代表一段连续的相同样式的文本,一般来说,没有改过样式的一段纯中文或者纯英文就在一个Run内,而一旦对其中一个字改变了字号、颜色、粗细等样式,那么其本身及前后必然会被不同的Run分割。
在实际使用Apache POI中,又分为High Level和Low Level两种API,一般以XWPF作为前缀的是High Level API,以CT为前缀的是Low Level,High Level API使用更简单,比较容易理解,但是目前只有比较常见的元素有,例如XWPFParagraph、XWPFRun。Low Level API实际上是对xml文件中标签的简单封装,需要你对OfficeOpenXML规范有足够的了解,例如CTP(Paragraph)、CTR(Run)。当然,Low Level API也不一定能满足你的全部需求,这个时候你只能对着OfficeOpenXML文档自行解析XML了。High Level API可以获取到对应的Low Level API,例如,XWPFParagraph.getCTP()。
上图是High Level API的类的主要关系图,其中蓝色的是class,绿色的是interface
List<XWPFParagraph> paragraphs = document.getParagraphs();
for(XWPFParagraph paragraph:paragraphs){
List<XWPFRun> runs= paragraph.getRuns();
for(XWPFRun run:runs){
List<XWPFPicture> pictures=run.getEmbeddedPictures();
String text=run.text();
}
此部分摘自:https://blog.csdn.net/fatesunlove/article/details/107020537
3.demo 测试
测试Word 文档 (摘自 需求规格说明书模板部分内容)
测试代码
package com.spasvo.test;
import org.apache.poi.xwpf.usermodel.*;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import java.io.FileInputStream;
import java.util.List;
public class TestMain {
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument(new FileInputStream("zheng.docx")).getXWPFDocument();
XWPFStyles styles = document.getStyles();
List<IBodyElement> elements = document.getBodyElements();
for (IBodyElement element : elements) {
if (element instanceof XWPFParagraph) {
XWPFParagraph pf = (XWPFParagraph) element;
List<XWPFRun> runList = pf.getRuns();
System.out.println("对齐方式 :" + pf.getAlignment().getValue());
System.out.println("左间距 :" + pf.getIndentationLeft());
System.out.println("右间距 :" + pf.getIndentationRight());
System.out.println("首行缩进 :" + pf.getFirstLineIndent());
String paStyle = pf.getStyle();
if (styles.getStyle(paStyle) == null) {
System.out.println("文字格式 :" + "null");
} else {
System.out.println("文字格式 :" + styles.getStyle(paStyle).getCTStyle().getName().getVal());
}
System.out.println("run size " + runList.size());
if (runList.size() == 1) {
XWPFRun run = runList.get(0);
String FontFamily = run.getFontFamily(XWPFRun.FontCharRange.hAnsi);//字体
System.out.println("FontName :" + FontFamily);
System.out.println("fontSize :" + run.getFontSize());//字体大小
String str = run.getCTR().toString();
// System.out.println(str);
//将 Run 的 xml 转化为 dom4j 字符串处理
Document doc = DocumentHelper.parseText(str);
Element rootElement = doc.getRootElement();
List<Element> elements1 = rootElement.elements();
for (Element e1 : elements1) {
//System.out.println(e1.getName());
if (e1.getName().equals("t")) {
System.out.println("文字内容 :" + e1.getText().trim());
}else if(e1.getName().equals("drawing")){
System.out.println("图片 :");
}
}
}
}else if (element instanceof XWPFTable) {
System.out.println("表格................");
XWPFTable table = (XWPFTable) element;
List<XWPFTableRow> listRow = table.getRows();
for (XWPFTableRow row : listRow) {
System.out.println("---------------------------------------------------------------");
List<XWPFTableCell> cellList = row.getTableCells();
for (XWPFTableCell cell : cellList) {
//单元格里面的内容
List<XWPFParagraph> cellParagraphList = cell.getParagraphs();
for (XWPFParagraph phCell : cellParagraphList) {
System.out.print("" + phCell.getText() + "_Cell|");
}
System.out.println("..");
}
}
}
System.out.println("------------------------------一个Element-------------------------------------");
}
}
}
运行结果
对齐方式 :1
左间距 :420
右间距 :-1
首行缩进 :-1
文字格式 :heading 1
run size 1
FontName :null
fontSize :15
文字内容 :概述
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :-1
文字格式 :heading 2
run size 1
FontName :null
fontSize :14
文字内容 :编写目的
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :480
文字格式 :null
run size 1
FontName :Verdana
fontSize :12
文字内容 :编写本文档的目的是为了对薪酬管理系统建设项目进行明确的定义,详细说明应用系统的外部行为,包括业务功能需求、非功能性需求、接口细节、设计约束以及影响系统的其他因素。
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :480
文字格式 :样式 样式 样式 段前: 0.5 行 段后: 0.5 行 + 左侧: 2 字符 段前: 0.5 行 段后: 0.5 行 + 段...
run size 1
FontName :null
fontSize :-1
文字内容 :本需求说明书主要适合以下读者:
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :-1
文字格式 :样式 样式 样式 段前: 0.5 行 段后: 0.5 行 + 左侧: 2 字符 段前: 0.5 行 段后: 0.5 行 + 段...
run size 1
FontName :null
fontSize :-1
文字内容 :用户
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :-1
文字格式 :heading 2
run size 1
FontName :null
fontSize :14
文字内容 :适用范围
------------------------------一个Element-------------------------------------
对齐方式 :4
左间距 :-1
右间距 :-1
首行缩进 :480
文字格式 :l居中
run size 1
FontName :null
fontSize :12
文字内容 :需求规格说明书是适用于薪酬管理系统项目的过程。
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :425
文字格式 :null
run size 0
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :425
文字格式 :null
run size 1
FontName :null
fontSize :-1
文字内容 :被调研人列表
------------------------------一个Element-------------------------------------
表格................
---------------------------------------------------------------
部门_Cell|..
职位_Cell|..
需求确认范围_Cell|..
_Cell|..
---------------------------------------------------------------
客服部_Cell|..
大区经理,客服经理,客服主管,客服专员_Cell|..
税率,薪资项目,薪资模板,薪资计算_Cell|..
_Cell|..
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :425
文字格式 :null
run size 0
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :425
文字格式 :null
run size 1
FontName :null
fontSize :-1
文字内容 :用户列表
------------------------------一个Element-------------------------------------
表格................
---------------------------------------------------------------
部门_Cell|..
职位_Cell|..
_Cell|..
_Cell|..
---------------------------------------------------------------
客服部_Cell|..
客服经理,客服主管,客服专员_Cell|..
_Cell|..
_Cell|..
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :-1
文字格式 :null
run size 0
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :-1
文字格式 :heading 2
run size 1
FontName :null
fontSize :14
文字内容 :名词解释
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :426
右间距 :-1
首行缩进 :0
文字格式 :样式 infoblue + 小五 左侧: 0 厘米 段后: 0 磅 行距: 单倍行距
run size 1
FontName :null
fontSize :12
文字内容 :《XX系统设计说明书编制规范V1.1》
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :420
右间距 :-1
首行缩进 :-1
文字格式 :heading 1
run size 1
FontName :null
fontSize :15
文字内容 :系统综述
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :-1
文字格式 :heading 2
run size 1
FontName :null
fontSize :14
文字内容 :系统介绍
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :-1
文字格式 :null
run size 1
FontName :null
fontSize :-1
文字内容 :薪酬管理系统用来支持企业薪酬管理,包括组织结构定义、员工信息管理、薪酬模板管理、薪酬发放管理、薪酬报表。
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :-1
文字格式 :null
run size 1
FontName :null
fontSize :-1
文字内容 :薪酬管理系统是一个web应用形式,能够经过互联网进行访问。
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :-1
文字格式 :null
run size 0
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :-1
文字格式 :null
run size 1
FontName :null
fontSize :14
文字内容 :系统总体结构:
------------------------------一个Element-------------------------------------
对齐方式 :4
左间距 :-1
右间距 :-1
首行缩进 :-1
文字格式 :正文编号
run size 1
FontName :null
fontSize :12
图片 :
------------------------------一个Element-------------------------------------
对齐方式 :1
左间距 :-1
右间距 :-1
首行缩进 :-1
文字格式 :null
run size 0
------------------------------一个Element-------------------------------------
Process finished with exit code 0
设计
其中 Node 节点,xml 文件,word文件的章节节点 可以互相转化
Handle 类来处理Node 节点,向节点添加删除数据,添加删除节点,
ContentService 根据不同的需求生成不同的报告内容,并存入本地文件
实现
第一步:word节点 文件转化为 xml 配置文件
Word 中的节点结构
public static void main(String[] args) {
IExportHandle handle = new WordExportHandle();
handle.loadDocx("需求规格说明书");
handle.saveAsTemplateConfig(0,"需求规格说明书.xml");
}
public void loadDocx(String docxPath) {
//只读文字不读图片
try {
XWPFDocument document = new XWPFDocument(new FileInputStream(docxPath)).getXWPFDocument();
XWPFStyles styles = document.getStyles();
HashMap<String ,String> map = new HashMap<>();
List<IBodyElement> elements = document.getBodyElements();
for (IBodyElement element : elements) {
if (element instanceof XWPFParagraph) {
XWPFParagraph pf = (XWPFParagraph) element;
// List<XWPFRun> runList = pf.getRuns();
String paStyle = pf.getStyle();
if(paStyle == null){
System.out.println("TODO");
}else {
String styleVal = styles.getStyle(paStyle).getCTStyle().getName().getVal();
switch (styleVal) {
case "heading 1": {
INode node = new WordNode();
node.setName("chapter");
node.setFontSize(14f);
node.setTitle(pf.getText().trim());
node.setTitleFont("宋体");
node.setFontStyle("0,1");
rootNode.addChild(node);
map.put("heading 1", pf.getText().trim());
break;
}
case "heading 2": {
INode node2 = new WordNode();
node2.setName("chapter");
node2.setFontSize(12f);
node2.setTitle(pf.getText().trim());
node2.setTitleFont("宋体");
node2.setFontStyle("0,1");
addNodeByNodePath(map.get("heading 1"),node2);
map.put("heading 2", pf.getText().trim());
break;
}
case "heading 3": {
INode node3 = new WordNode();
node3.setName("chapter");
node3.setFontSize(10.5f);
node3.setTitle(pf.getText().trim());
node3.setTitleFont("宋体");
node3.setFontStyle("0,1");
addNodeByNodePath(map.get("heading 1") + "|" + map.get("heading 2"),node3);
map.put("heading 3", pf.getText().trim());
break;
}
case "heading 4": {
INode node4 = new WordNode();
node4.setName("chapter");
node4.setFontSize(10.5f);
node4.setTitle(pf.getText().trim());
node4.setTitleFont("宋体");
node4.setFontStyle("0,1");
addNodeByNodePath(map.get("heading 1") + "|" + map.get("heading 2") + "|" + map.get("heading 3"),node4);
map.put("heading 4", pf.getText().trim());
break;
}
}
}
} else if (element instanceof XWPFTable) {
// System.out.println("表格................");
XWPFTable table = (XWPFTable) element;
List<XWPFTableRow> listRow = table.getRows();
for (XWPFTableRow row : listRow) {
List<XWPFTableCell> cellList = row.getTableCells();
for (XWPFTableCell cell : cellList) {
//单元格里面的内容
List<XWPFParagraph> cellParagraphList = cell.getParagraphs();
for (XWPFParagraph phCell : cellParagraphList) {
// System.out.print("" + phCell.getText() + "_Cell|");
}
//System.out.println("..");
}
}
}
}
System.out.println("结束");
} catch (IOException e) {
e.printStackTrace();
}
}
public void saveAsTemplateConfig(int saveType,String configPath) {
//保存node 节点
org.dom4j.Document document = DocumentHelper.createDocument();// 建立document对象,用来操作xml文件
org.dom4j.Element rootElement = document.addElement("root");// 建立根节点
saveBfs(rootNode,rootElement);
try {
XMLWriter writer = new XMLWriter(new FileWriter(configPath));
writer.write(document);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
生成xml结构
<?xml version="1.0" encoding="utf-8"?>
<root>
<chapter title="概述" font="宋体" fontsize="14.0" fontstyle="0,1">
<chapter title="编写目的" font="宋体" fontsize="12.0" fontstyle="0,1"/>
<chapter title="适用范围" font="宋体" fontsize="12.0" fontstyle="0,1"/>
<chapter title="名词解释" font="宋体" fontsize="12.0" fontstyle="0,1"/>
<chapter title="参考资料" font="宋体" fontsize="12.0" fontstyle="0,1"/>
</chapter>
<chapter title="系统综述" font="宋体" fontsize="14.0" fontstyle="0,1">
<chapter title="系统介绍" font="宋体" fontsize="12.0" fontstyle="0,1">
<chapter title="关键业务流程" font="宋体" fontsize="10.5" fontstyle="0,1"/>
</chapter>
<chapter title="主要特征" font="宋体" fontsize="12.0" fontstyle="0,1"/>
<chapter title="产品/项目中的用户角色" font="宋体" fontsize="12.0" fontstyle="0,1"/>
</chapter>
<chapter title="功能性需求描述" font="宋体" fontsize="14.0" fontstyle="0,1"/>
<chapter title="需求功能列表" font="宋体" fontsize="14.0" fontstyle="0,1"/>
<chapter title="系统接口需求" font="宋体" fontsize="14.0" fontstyle="0,1">
<chapter title="外部接口" font="宋体" fontsize="12.0" fontstyle="0,1"/>
<chapter title="内部接口" font="宋体" fontsize="12.0" fontstyle="0,1"/>
</chapter>
<chapter title="系统的非功能性需求" font="宋体" fontsize="14.0" fontstyle="0,1">
<chapter title="稳定性" font="宋体" fontsize="12.0" fontstyle="0,1"/>
<chapter title="安全性" font="宋体" fontsize="12.0" fontstyle="0,1"/>
<chapter title="用户界面需求" font="宋体" fontsize="12.0" fontstyle="0,1">
<chapter title="操作简捷" font="宋体" fontsize="10.5" fontstyle="0,1"/>
<chapter title="用户界面友好" font="宋体" fontsize="10.5" fontstyle="0,1"/>
<chapter title="数据校验" font="宋体" fontsize="10.5" fontstyle="0,1"/>
</chapter>
<chapter title="运行需求" font="宋体" fontsize="12.0" fontstyle="0,1">
<chapter title="数据库要求" font="宋体" fontsize="10.5" fontstyle="0,1"/>
<chapter title="应用服务器要求" font="宋体" fontsize="10.5" fontstyle="0,1"/>
<chapter title="故障处理" font="宋体" fontsize="10.5" fontstyle="0,1"/>
<chapter title="用户文档" font="宋体" fontsize="10.5" fontstyle="0,1"/>
</chapter>
<chapter title="其它需求" font="宋体" fontsize="12.0" fontstyle="0,1">
<chapter title="支持软件环境" font="宋体" fontsize="10.5" fontstyle="0,1"/>
</chapter>
</chapter>
<chapter title="双方确认" font="宋体" fontsize="14.0" fontstyle="0,1"/>
</root>
第二步:向XML配置文件加入内容,或者通过Service类动态添加内容,内容包括文字和表格
1.修改XML文件生成pdf 或word 文件,向适用范围中添加段落和表格
<?xml version="1.0" encoding="utf-8"?>
<!--...fontstyle 0 标准,1 加粗, 2 斜体, 3 又粗又斜 ,4 带有下划线 ,8 带有删除线 ,多选,单选 -->
<!--...textstyle 0 靠左,1 居中,2 靠右 非必填 默认靠左-->
<!--...cell_text_style 单元格文字风格,0靠左,1居中,2靠右 非必填,默认居中 row_span.横向单元格跨度,col_span 垂直单元格跨度,默认1-->
<!--...title font fontsize 章节,段落,必填属性,firstLineIndent(首行缩进) indentationLeft(左侧对齐间距) indentationRight(右侧对齐间距) 非必填,默认为0 -->
<!--...表格与上一个段落的空白宽度 10f -->
<root>
<chapter title="概述" font="宋体" fontsize="14.0" fontstyle="0,1">
<chapter title="编写目的" font="宋体" fontsize="12.0" fontstyle="0,1"/>
<chapter title="适用范围" font="宋体" fontsize="12.0" fontstyle="0,1">
<paragraph font="宋体" fontsize="12" fontstyle="0,1" firstLineIndent="30" indentationLeft="20" indentationRight="20" textstyle="1">需求规格说明书是适用于薪酬管理系统项目的过程。</paragraph>
<table widths="0.1,0.5,0.1,0.1,0.1,0.1">-->
<cell><paragraph font="宋体" fontsize="10.5" fontstyle="1">部门</paragraph></cell>
<cell><paragraph font="宋体" fontsize="10.5" fontstyle="1">职位</paragraph></cell>
<cell><paragraph font="宋体" fontsize="10.5" fontstyle="1">需求确认范围</paragraph></cell>
<cell><paragraph font="宋体" fontsize="10.5" fontstyle="0">客服部</paragraph></cell>
<cell><paragraph font="宋体" fontsize="10.5" fontstyle="0">大区经理,客服经理,客服主管,客服专员</paragraph></cell>
<cell><paragraph font="宋体" fontsize="10.5" fontstyle="0">税率,薪资项目,薪资模板,薪资计算</paragraph></cell>
</table>
</chapter>
<chapter title="名词解释" font="宋体" fontsize="12.0" fontstyle="0,1"/>
<chapter title="参考资料" font="宋体" fontsize="12.0" fontstyle="0,1"/>
</chapter>
<chapter title="系统综述" font="宋体" fontsize="14.0" fontstyle="0,1">
<chapter title="系统介绍" font="宋体" fontsize="12.0" fontstyle="0,1">
<chapter title="关键业务流程" font="宋体" fontsize="10.5" fontstyle="0,1"/>
</chapter>
<chapter title="主要特征" font="宋体" fontsize="12.0" fontstyle="0,1"/>
<chapter title="产品/项目中的用户角色" font="宋体" fontsize="12.0" fontstyle="0,1"/>
</chapter>
<chapter title="功能性需求描述" font="宋体" fontsize="14.0" fontstyle="0,1"/>
<chapter title="需求功能列表" font="宋体" fontsize="14.0" fontstyle="0,1"/>
<chapter title="系统接口需求" font="宋体" fontsize="14.0" fontstyle="0,1">
<chapter title="外部接口" font="宋体" fontsize="12.0" fontstyle="0,1"/>
<chapter title="内部接口" font="宋体" fontsize="12.0" fontstyle="0,1"/>
</chapter>
<chapter title="系统的非功能性需求" font="宋体" fontsize="14.0" fontstyle="0,1">
<chapter title="稳定性" font="宋体" fontsize="12.0" fontstyle="0,1"/>
<chapter title="安全性" font="宋体" fontsize="12.0" fontstyle="0,1"/>
<chapter title="用户界面需求" font="宋体" fontsize="12.0" fontstyle="0,1">
<chapter title="操作简捷" font="宋体" fontsize="10.5" fontstyle="0,1"/>
<chapter title="用户界面友好" font="宋体" fontsize="10.5" fontstyle="0,1"/>
<chapter title="数据校验" font="宋体" fontsize="10.5" fontstyle="0,1"/>
</chapter>
<chapter title="运行需求" font="宋体" fontsize="12.0" fontstyle="0,1">
<chapter title="数据库要求" font="宋体" fontsize="10.5" fontstyle="0,1"/>
<chapter title="应用服务器要求" font="宋体" fontsize="10.5" fontstyle="0,1"/>
<chapter title="故障处理" font="宋体" fontsize="10.5" fontstyle="0,1"/>
<chapter title="用户文档" font="宋体" fontsize="10.5" fontstyle="0,1"/>
</chapter>
<chapter title="其它需求" font="宋体" fontsize="12.0" fontstyle="0,1">
<chapter title="支持软件环境" font="宋体" fontsize="10.5" fontstyle="0,1"/>
</chapter>
</chapter>
<chapter title="双方确认" font="宋体" fontsize="14.0" fontstyle="0,1"/>
</root>
修改main方法
package com.spasvo.test;
import com.spasvo.export.handle.IExportHandle;
import com.spasvo.export.handle.impl.PdfExportHandle;
public class Test4 {
public static void main(String[] args) {
IExportHandle handle1 = new PdfExportHandle();
handle1.loadConfig("需求规格说明书.xml");
handle1.writeExport("需求规格说明书.pdf");
}
}
执行结果
第三步:动态加入内容
package com.spasvo.test;
import com.spasvo.export.handle.IExportHandle;
import com.spasvo.export.handle.impl.PdfExportHandle;
import com.spasvo.export.service.DemandContentService;
import com.spasvo.export.service.impl.DemandContentServiceImpl;
import java.io.File;
public class Test4 {
public static void main(String[] args) {
IExportHandle handle1 = new PdfExportHandle();
handle1.loadConfig("需求规格说明书.xml");
DemandContentService service = new DemandContentServiceImpl(handle1);
//添加用户列表
service.setUseRange();
service.saveDemand("需求规格说明书.pdf");
}
}
动态添加内容 的方法
public void setUseRange() {
String nodePath = "概述|适用范围";
ContentConfigBean configBean = new ContentConfigBean();
if(handle instanceof PdfExportHandle){
com.itextpdf.text.Paragraph paragraph1 = new com.itextpdf.text.Paragraph("用户列表", PdfExportHandle.setFont(configBean.getParagraphFont(), configBean.getParagraphFontSize(), "0"));
paragraph1.setFirstLineIndent(configBean.getParagraphFirstLineIndent());
paragraph1.setIndentationLeft(configBean.getParagraphIndentationLeft());
handle.addPdfSectionContent(nodePath,paragraph1);
float [] widths = {0.5f,0.5f};
configBean.setTableWidths(widths);
ArrayList<String> tableHeaderList = new ArrayList<>(Arrays.asList("部门","职位"));
PdfPTable table = new PdfPTable(configBean.getTableWidths());
//表头
for(String strHeader :tableHeaderList){
Paragraph phHeader = new Paragraph(strHeader, PdfExportHandle.setFont(configBean.getCellParagraphFont(), configBean.getCellParagraphFontSize(), "0"));
PdfPCell cellHeader = new PdfPCell(phHeader);
cellHeader.setRowspan(configBean.getCell_row_span());
cellHeader.setColspan(configBean.getCell_col_span());
cellHeader.setHorizontalAlignment(configBean.getCell_text_style());
table.addCell(cellHeader);
}
class DemandUserListTable{
public DemandUserListTable(String depart, String position){
this.depart = depart;
this.position = position;
}
public String depart;
public String position;
}
ArrayList<DemandUserListTable> listuserTable = new ArrayList<>(Arrays.asList(new DemandUserListTable("客服部","客服经理,客服主管,客服专员")));
//表格内容
for(DemandUserListTable bean :listuserTable){
ArrayList<String> listRow = new ArrayList<>();
listRow.add(bean.depart);
listRow.add(bean.position);
for(String str : listRow){
Paragraph phCase = new Paragraph(str, PdfExportHandle.setFont(configBean.getCellParagraphFont(), configBean.getCellParagraphFontSize(), configBean.getCellParagraphFontStyle()));
PdfPCell cellCase = new PdfPCell(phCase);
cellCase.setRowspan(configBean.getCell_row_span());
cellCase.setColspan(configBean.getCell_col_span());
cellCase.setHorizontalAlignment(configBean.getCell_text_style());
table.addCell(cellCase);
}
}
handle.addPdfSectionContent(nodePath,table);
}
}
生成结果