支持表格、饼图、折线、文字
public class PoiWordTools {
public void start(String tempPath, String resultPath) {
try (InputStream inputStream = this.getClass().getResourceAsStream(tempPath)) {
assert inputStream != null;
XWPFDocument doc = new XWPFDocument(inputStream);
//表格
List<List<String>> tableList = new ArrayList<List<String>>(){{
add(Arrays.asList("Java", "Jdk", "Jre", "12", "34"));
add(Arrays.asList("Java", "Jdk", "Jre", "12", "34"));
add(Arrays.asList("Java", "Jdk", "Jre", "12", "34"));
add(Arrays.asList("Java", "Jdk", "Jre", "12", "34"));
add(Arrays.asList("Java", "Jdk", "Jre", "12", "34"));
add(Arrays.asList("Java", "Jdk", "Jre", "12", "34"));
}};
this.drawWordTable(doc, 0, tableList);
//饼图
Map<String, Number> peiData = new HashMap<String, Number>(){{
put("英语", 66);
put("语文", 89);
put("数学", 99);
put("物理", 88);
put("化学", 70);
put("生物", 91);
put("音乐", 83);
put("美术", 60);
}};
this.drawPieChart(doc, 0, peiData, "标题");
File file = new File(resultPath);
if (file.exists()) {
file.delete();
}
// 保存结果文件
try (FileOutputStream fos = new FileOutputStream(resultPath)) {
doc.write(fos);
} catch (IOException e) {
e.printStackTrace();
}
doc.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 折线图Demo
* @param doc
* @throws IOException
* @throws InvalidFormatException
*/
public void doChartLine(XWPFDocument doc) throws IOException, InvalidFormatException {
String[] series1 = {"测试折线1","测试折线2","测试折线3"};//每条线的名称
String title1="测试折线图1";
//y轴
List<Number[]> value1 = new ArrayList<>();//每一条折现图,第一个表3条,需要和图中条数一样
//第一张图的y轴
Number[] n1={1,2,3,5};
Number[] n2={4,2,1,4};
Number[] n3={5.8,6.2,1,0.2};
value1.add(n1);
value1.add(n2);
value1.add(n3);
//x轴
String[] x1={"1","2","3","4"};
drawLineChart(doc, 0, series1, x1, value1, title1);
}
/**
* word中插入表格数据行
* @param doc 文档
* @param chartNum 处理第几个表格
* @param tableList 数据集合
*/
public void drawWordTable(XWPFDocument doc, int chartNum, List<List<String>> tableList) {
List<XWPFTable> tables = doc.getTables();
XWPFTable table = tables.get(chartNum);
//创建行,根据需要插入的数据添加新行,不处理表头
for (int i = 1; i <= tableList.size(); i++) {
XWPFTableRow row = table.getRow(i);
if (row == null) {
table.createRow();
}
}
//遍历表格插入数据
int rows = tableList.size() + 1;
for (int i = 1; i < rows; i++) {
List<XWPFTableCell> cells = table.getRow(i).getTableCells();
for (int j = 0; j < cells.size(); j++) {
XWPFTableCell cell = cells.get(j);
cell.setText(tableList.get(i - 1).get(j));
//表格样式一致-->没有此段表格会默认左对齐
//有此段会使表格格式一致
CTTc cttc = cell.getCTTc();
CTTcPr ctPr = cttc.addNewTcPr();
ctPr.addNewVAlign().setVal(STVerticalJc.CENTER);
cttc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
}
}
}
/**
* 饼图的生成
* @param doc 文档
* @param chartNum 处理第几个图
* @param KyeData 数据 <系列名, 数据>
* @param titleText 标题
* @throws IOException 异常
* @throws InvalidFormatException 异常
*/
public void drawPieChart(XWPFDocument doc, int chartNum, Map<String, Number> KyeData, String titleText) throws IOException, InvalidFormatException {
XWPFChart chart = doc.getCharts().get(chartNum);
XSSFWorkbook workbook = chart.getWorkbook();
XSSFSheet sheet = workbook.getSheetAt(0);
int i = 1;
for (Map.Entry<String, Number> item : KyeData.entrySet()) {
XSSFRow row = sheet.createRow(i++);
row.createCell(0).setCellValue(item.getKey());
row.createCell(1).setCellValue(item.getValue().doubleValue());
}
XDDFChartData chartData2 = chart.getChartSeries().get(0);
XDDFChartData.Series s2 = chartData2.getSeries().get(0);
XDDFDataSource<String> cat2 = XDDFDataSourcesFactory.fromStringCellRange(sheet,
new CellRangeAddress(1, KyeData.size(), 0, 0));
XDDFNumericalDataSource<Double> val2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
new CellRangeAddress(1,KyeData.size(),1,1));
s2.replaceData(cat2,val2);
chart.setTitleText(titleText);
chart.plot(chartData2);
}
/**
* 折线图的生成
* @param doc 文档
* @param chartNum 处理第几个图
* @param series 折线名称
* @param categories x轴数据
* @param values y轴数据
* @param chartTitle 图表的标题
*/
private void drawLineChart(XWPFDocument doc, int chartNum, String[] series, String[] categories, List<Number[]> values, String chartTitle) {
//获取第1个图表
XWPFChart chart = doc.getCharts().get(chartNum);
List<XDDFChartData> data = chart.getChartSeries();
//这里一般获取第一个,我们这里是折线图就是XDDFLineChartData
XDDFLineChartData line = (XDDFLineChartData) data.get(0);
int numOfPoints = categories.length;
String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
for (int i = 0; i < values.size(); i++) {
String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, i + 1, i + 1));
Number[] value = values.get(i);
XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(value, valuesDataRange, i + 1);
//图表中的系列
XDDFChartData.Series ser;
ser = line.getSeries().get(i);
ser.replaceData(categoriesData, valuesData);
//修改系列标题
CellReference cellReference = chart.setSheetTitle(series[i], 1);
ser.setTitle(series[i], cellReference);
}
chart.plot(line);
//折线图标题
chart.setTitleText(chartTitle);
chart.setTitleOverlay(false);
}
/**
* 替换word文档中的文字
* @param doc 文档
* @param dataMap 数据集合 <模板中的key, 要替换的内容>
*/
public void drawString(XWPFDocument doc, Map<String, String> dataMap) {
//获取word文档 每一段(词)的迭代器
Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
while(iterator.hasNext()){ //遍历迭代器 获取非表格中的每一个词对规定好的${}格式进行匹配
XWPFParagraph paragraph = iterator.next();
replaceCode(paragraph, dataMap);
}
//获取表格的迭代器
Iterator<XWPFTable> itTable = doc.getTablesIterator();
while(itTable.hasNext()){ //遍历迭代器以获取每个word中的表格
XWPFTable table = itTable.next(); //表格对象
int rcount = table.getNumberOfRows(); //获取表格的行总数
for(int i = 0;i < rcount;i++){
XWPFTableRow row = table.getRow(i); //读取表格中的每一行
List<XWPFTableCell> cells = row.getTableCells(); //获取一行中的所有单元格
for(XWPFTableCell cell : cells){ //遍历单元格
//单元格中有段落,要做段落处理
List<XWPFParagraph> paragraphs = cell.getParagraphs(); //获取单元格中的每一个单词 以进行匹配用来替换的数据Map集合
for(XWPFParagraph paragraph : paragraphs){
this.replaceCode(paragraph, dataMap);
}
}
}
}
}
/**
* 替换方法
* @param paragraph
* @param contentMap
*/
private void replaceCode(XWPFParagraph paragraph,Map<String,String> contentMap){
//获取一个词的操作对象 runs
List<XWPFRun> runs = paragraph.getRuns();
for(XWPFRun run:runs){
//通过操作对象runs获取该词中的文本
String oneParaString = run.getText(run.getTextPosition());
//如果是空字符串或者该词中不包括"$"符号则跳过本次循环
if(StrUtil.isBlank(oneParaString) || !oneParaString.contains("$")){
continue;
}
//该词中存在"$",将文本数据与替换的Map数据进行匹配,例(该词为${username},那么将替换为Ychiha)
for(Map.Entry<String,String> entry : contentMap.entrySet()){
oneParaString = oneParaString.replace("${" + entry.getKey() + "}", entry.getValue());
}
//操作对象替换数据
run.setText(oneParaString,0);
}
}
}