功能:
文本、图表、文本框内容替换、表格动态增加内容、单元格合并
增加图表、替换图表内容
你能用到的word的功能这儿都有!
话不多说,直接上代码!
pom 引用:
// https://mvnrepository.com/artifact/org.apache.poi/poi
implementation 'org.apache.poi:poi:5.2.2'
// https://mvnrepository.com/artifact/com.deepoove/poi-tl
implementation 'com.deepoove:poi-tl:1.12.2'
// https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-full
implementation 'org.apache.poi:poi-ooxml-full:5.2.3'
// https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml
implementation 'org.apache.poi:poi-ooxml:5.2.2'
全量代码粘贴即用:
`
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.ChartMultiSeriesRenderData;
import com.deepoove.poi.data.Charts;
import com.deepoove.poi.util.TableTools;
import com.documents4j.api.DocumentType;
import com.documents4j.api.IConverter;
import com.documents4j.job.LocalConverter;
import com.zzys.qhyscredit.utils.DateUtil;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.chart.;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import java.io.;
import java.nio.file.Files;
import java.util.;
/**
-
@Author:Internet_worm
-
@Date:2024/7/26:09:59
-
@Description: word 操作工具类
*/
public class WordUtils {/***
- @Description :替换段落文本
- @param document docx解析对象
- @param textMap 需要替换的信息集合
- @return void
*/
public static void changeText(XWPFDocument document, Map<String, String> textMap) {
// 获取段落集合
Iteratoriterator = document.getParagraphsIterator();
XWPFParagraph paragraph = null;
while (iterator.hasNext()) {
paragraph = iterator.next();
// 判断此段落是否需要替换
if (checkText(paragraph.getText())) {
replaceValue(paragraph, textMap);
}
}
}
/***
- @Description :检查文本中是否包含指定的字符(此处为“$”)
- @param text
- @return boolean
*/
public static boolean checkText(String text) {
// System.out.println("paragraph text :"+text);
boolean check = false;
if (text.contains("$")) {
check = true;
}
return check;
}
/**
- 替换图片
- @param document
- @param picData
- @throws Exception
*/
public static void changePic(XWPFDocument document, Map<String, String> picData) throws Exception {
// 获取段落集合
Iteratoriterator = document.getParagraphsIterator();
XWPFParagraph paragraph;
while (iterator.hasNext()) {
paragraph = iterator.next();
// 判断此段落是否需要替换
String text = paragraph.getText();
if (checkText(text)) {
replacePicValue(paragraph, picData);
}
}
}/***
- @Description :替换表格内的文字
- @param document
- @param data
- @return void
*/
public static void changeTableText(XWPFDocument document, Map<String, String> data) {
// 获取文件的表格
IteratortableList = document.getTablesIterator();
XWPFTable table;
Listrows;
Listcells;
// 循环所有需要进行替换的文本,进行替换
while (tableList.hasNext()) {
table = tableList.next();
if (checkText(table.getText())) {
rows = table.getRows();
// 遍历表格,并替换模板
for (XWPFTableRow row : rows) {
cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
// 判断单元格是否需要替换
if (checkText(cell.getText())) {
Listparagraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
replaceValue(paragraph, data);
}
}
}
}
}
}
}
/***
- @Description :替换表格内图片
- @param document
- @param picData
- @return void
- @Date 2022/11/18 11:29
*/
public static void changeTablePic(XWPFDocument document, Map<String, String> picData) throws Exception {
// 获取文件的表格
IteratortableList = document.getTablesIterator();
XWPFTable table;
Listrows;
Listcells;
// 循环所有需要进行替换的文本,进行替换
while (tableList.hasNext()) {
table = tableList.next();
if (checkText(table.getText())) {
rows = table.getRows();
// 遍历表格,并替换模板
for (XWPFTableRow row : rows) {
cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
// 判断单元格是否需要替换
if (checkText(cell.getText())) {
Listparagraphs = cell.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
replacePicValue(paragraph, picData);
}
}
}
}
}
}
}
/***
- @Description :替换内容
- @param paragraph
- @param textMap
- @return void
- @Date 2022/11/18 11:33
*/
public static void replaceValue(XWPFParagraph paragraph, Map<String, String> textMap) {
XWPFRun run, nextRun;
String runsText;
Listruns = paragraph.getRuns();
for (int i = 0; i < runs.size(); i++) {
run = runs.get(i);
runsText = run.getText(0);
// System.out.println(runsText);
if (runsText.contains("${") || (runsText.contains("$") && runs.get(i + 1).getText(0).charAt(0) == '{')) {
while (!runsText.contains("}")) {
nextRun = runs.get(i + 1);
runsText = runsText + nextRun.getText(0);
//删除该节点下的数据
paragraph.removeRun(i + 1);
}
Object value = changeValue(runsText, textMap);
//判断key在Map中是否存在
if (textMap.containsKey(runsText)) {
run.setText(value.toString(), 0);
} else {
//如果匹配不到,则不修改
run.setText(runsText, 0);
}
}
}
}
/***
- @Description :替换图片内容
- @param paragraph
- @param picData
- @return void
- @Date 2022/11/18 11:33
*/
public static void replacePicValue(XWPFParagraph paragraph, Map<String, String> picData) throws Exception {
Listruns = paragraph.getRuns();
for (XWPFRun run : runs) {
Object value = changeValue(run.toString(), picData);
if (picData.containsKey(run.toString())) {
//清空内容
run.setText("", 0);
FileInputStream is = new FileInputStream((String) value);
//图片宽度、高度
int width = Units.toEMU(100), height = Units.toEMU(100);
//添加图片信息,段落高度需要在模板中自行调整
run.addPicture(is, XWPFDocument.PICTURE_TYPE_PNG, (String) value, width, height);
}
}
}
/***
- @Description :匹配参数
- @param value
- @param textMap
- @return java.lang.Object
- @Date 2022/11/18 11:33
*/
public static Object changeValue(String value, Map<String, String> textMap) {
Object valu = "";
for (Map.Entry<String, String> textSet : textMap.entrySet()) {
// 匹配模板与替换值 格式${key}
String key = textSet.getKey();
if (value.contains(key)) {
valu = textSet.getValue();
}
}
return valu;
}
public static void changeTextBox(XWPFDocument document, Map<String, String> textBoxData) throws XmlException {
for (XWPFParagraph paragraph : document.getParagraphs()) {
XmlCursor cursor = paragraph.getCTP().newCursor();
cursor.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//*/w:txbxContent/w:p/w:r");
Listctrsintxtbx = new ArrayList<>();
while(cursor.hasNextSelection()) {
cursor.toNextSelection();
XmlObject obj = cursor.getObject();
ctrsintxtbx.add(obj);
}
String replaceKey = "";
for (int i = 0; i < ctrsintxtbx.size(); i++) {
XmlObject obj = ctrsintxtbx.get(i);
CTR ctr = CTR.Factory.parse(obj.xmlText());
XWPFRun bufferrun = new XWPFRun(ctr, (IRunBody)paragraph);
String text = bufferrun.getText(0);System.out.println("text=="+text); if(text != null){ if(text.contains("${") || text.contains("$")){ replaceKey+=text; bufferrun.setText("",0); obj.set(bufferrun.getCTR()); }else { if(replaceKey.contains("${")||replaceKey.contains("$")){ if(text.contains("}")){ text = text.substring(0,text.indexOf("}")+1); } replaceKey += text; bufferrun.setText("",0); obj.set(bufferrun.getCTR()); } } } System.out.println(replaceKey); if(replaceKey.startsWith("${") && replaceKey.endsWith("}")){ for (Map.Entry<String, String> textSet : textBoxData.entrySet()) { // 匹配模板与替换值 格式key String key = textSet.getKey(); if (replaceKey.equals(key)) { text = textSet.getValue(); bufferrun.setText(text, 0); obj.set(bufferrun.getCTR()); } } replaceKey = ""; } } }
}
/**
- word 2 pdf
*/
public static void word2pdf(File inputWord,File outputFile) throws IOException {
InputStream docxInputStream=null; OutputStream outputStream = null; try { docxInputStream = Files.newInputStream(inputWord.toPath()); outputStream = Files.newOutputStream(outputFile.toPath()); IConverter converter = LocalConverter.builder().build(); converter.convert(docxInputStream).as(DocumentType.DOCX).to(outputStream).as(DocumentType.PDF).execute(); System.out.println("word 2 pdf success"); } catch (Exception e) { e.printStackTrace(); }finally { if(docxInputStream != null){ docxInputStream.close(); } if(outputStream != null){ outputStream.close(); } }
}
public static void operateWord( XWPFDocument document,Map<String, String> data, Map<String, String> picData,Map<String,String> textBoxData){
try {if (data.size() > 0) { // 替换掉表格之外的文本(仅限文本) changeText(document, data); // 替换表格内的文本对象 changeTableText(document, data); } if (picData.size() > 0) { // 替换内容图片 changePic(document, picData); // 替换表格内的图片对象 changeTablePic(document, picData); } if(textBoxData.size()>0){ changeTextBox(document,textBoxData); } } catch (Exception e) { e.printStackTrace(); }
}
/**
- 创建表格
- @param tableDataList
- @param riskFlag
- @throws IOException
*/
public static void createSummarizeTable(XWPFTable table,String riskFlag ,List<String[]> tableDataList) throws IOException {
// FileInputStream is = new FileInputStream("./pdftemplate/word-template.docx");
// XWPFDocument document = new XWPFDocument(is);
// Listtables = document.getTables();
// XWPFTable table = tables.get(0);
Listrows = table.getRows();
if(tableDataList.size()>0){
if(riskFlag.equals("0")){//高风险
insertRow(table,tableDataList);
}else if (riskFlag.equals("1")){//中风险
insertRow(table,tableDataList);
} else if (riskFlag.equals("2")) {//低风险
insertRow(table,tableDataList);
}
}
}
/**
- 插入行 并合并第一列
- @param table 表格
- @param tableList 数据
*/
private static void insertRow(XWPFTable table,List<String[]> tableList) {
int tableRowNum = table.getNumberOfRows();
if(tableList.size()>0){
for (int i = 0 ;i< tableList.size();i++){
XWPFTableRow targetRow = table.insertNewTableRow(table.getNumberOfRows());
for (int j = 0; j < 3; j++) {
XWPFTableCell cell = targetRow.createCell();
cell.setText(tableList.get(i)[j]);
}
}
}
TableTools.mergeCellsVertically(table,0,tableRowNum,tableRowNum+tableList.size()-1);
}
/**
-
生成图表 柱状图+折线+ 柱状折线组合
-
@param document 文档
-
@param chartForm 数据
-
@throws Exception
*/
public static void createBarLineCharts(XWPFDocument document, BarLineChartForm chartForm) throws Exception {
if (chartForm == null) {
throw new IllegalArgumentException("数据为空");
}
ListxData = chartForm.getXData();
if (xData == null) {
throw new IllegalArgumentException("X轴数据为空");
}
ListyBarData = chartForm.getYBarData();
ListyLintData = chartForm.getYLineData();
if (yBarData == null && yLintData == null) {
throw new IllegalArgumentException("柱状数据、折线数据为空");
}
XWPFChart chart = document.createChart(15 * Units.EMU_PER_CENTIMETER, 10 * Units.EMU_PER_CENTIMETER);
// 设置图例位置:上下左右
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP);
legend.setOverlay(false);
// 设置标题
chart.setTitleText(chartForm.getTitle());
//标题覆盖
chart.setTitleOverlay(false);
int numOfPoints = xData.size();
//初始化X轴数据
String[] categories = xData.toArray(new String[]{});
String cat = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
XDDFDataSourcecategoriesData = XDDFDataSourcesFactory.fromArray(categories, cat, 0);
//初始化X轴
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle(chartForm.getXTitle());
//初始化Y周
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle(chartForm.getYTitle());
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
int barSize = 0;
if (yBarData != null) {
System.out.println(">> 开始生成柱状图 ");
// 创建柱状图的类型
barSize = yBarData.size();
XDDFBarChartData barChart = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
barChart.setBarDirection(BarDirection.COL);
for (int i = 0; i < yBarData.size(); i++) {
int collIndex = i + 1;
String range = chart.formatRange(new CellRangeAddress(1, numOfPoints, collIndex, collIndex));
AxisYVal yVal = yBarData.get(i);
Number[] number = yVal.getVal();
XDDFNumericalDataSource<?> source = XDDFDataSourcesFactory.fromArray(number, range);
XDDFBarChartData.Series series = (XDDFBarChartData.Series) barChart.addSeries(categoriesData, source);
series.setTitle(yVal.getTitle(), setTitleInDataSheet(chart, yVal.getTitle(), collIndex));
}
if (yBarData.size() > 1) {
barChart.setBarGrouping(BarGrouping.CLUSTERED);
chart.getCTChart().getPlotArea().getBarChartArray(0).addNewOverlap().setVal((byte) 0);
}
chart.plot(barChart);
System.out.println(">> 生成柱状图 完毕 ");
}//********************* 折线图 *************************************************
if (yLintData != null) {
System.out.println(">> 开始生成折线图 ");
XDDFLineChartData lineChart = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
lineChart.setVaryColors(false);
for (int i = 0; i < yLintData.size(); i++) {
int collIndex = i + 1 + barSize;
String range = chart.formatRange(new CellRangeAddress(1, numOfPoints, collIndex, collIndex));
AxisYVal yVal = yLintData.get(i);
Number[] number = yVal.getVal();
XDDFNumericalDataSource<?> source = XDDFDataSourcesFactory.fromArray(number, range);
XDDFLineChartData.Series series = (XDDFLineChartData.Series) lineChart.addSeries(categoriesData, source);
series.setTitle(yVal.getTitle(), setTitleInDataSheet(chart, yVal.getTitle(), collIndex));
series.setMarkerStyle(MarkerStyle.DOT);
series.setSmooth(Boolean.FALSE);
}
chart.plot(lineChart);
System.out.println(">> 生成折线图 完毕");
}
}
private static CellReference setTitleInDataSheet(XWPFChart chart, String title, int column) throws Exception {
XSSFWorkbook workbook = chart.getWorkbook();
XSSFSheet sheet = workbook.getSheetAt(0);
XSSFRow row = sheet.getRow(0);
if (row == null) {
row = sheet.createRow(0);
}
XSSFCell cell = row.getCell(column);
if (cell == null) {
cell = row.createCell(column);
}
cell.setCellValue(title);
return new CellReference(sheet.getSheetName(), 0, column, true, true);
}
/**
- 替换多折线图对比图
- @param xLabels
- @param xData
- @param dataList
- @param replaceKey
- @param xTitle
- @param yTitle
- @param chartTitle
- @param sourceFilePath
- @param targetFilePath
- @throws IOException
*/
private static void replaceLineChart(String[]xLabels,String[]xData, List<Integer[]> dataList, String replaceKey, String xTitle, String yTitle, String chartTitle, String sourceFilePath, String targetFilePath) throws IOException {
Map<String,Object> dataMap = new HashMap<>();
Charts.ChartCombos chartCombos = Charts.ofComboSeries(chartTitle,xData);
for (int i = 0; i < xLabels.length; i++) {
chartCombos.addLineSeries( xLabels[i], dataList.get(i));
}
chartCombos.setxAsixTitle(xTitle);
chartCombos.setyAsixTitle(yTitle);
ChartMultiSeriesRenderData data = chartCombos.create();
dataMap.put(replaceKey,data);
XWPFTemplate.compile(sourceFilePath).render(dataMap).writeToFile(targetFilePath);
}
/**
*- @param xLabels
- @param xData
- @param dataList
- @param replaceKey 图表在Word模板中的名称
- @param xTitle
- @param yTitle
- @param chartTitle
- @param sourceFilePath
- @param targetFilePath
- @throws IOException
*/
private static void replaceHistograms(String[]xLabels,String[]xData, List<Integer[]> dataList, String replaceKey, String xTitle, String yTitle, String chartTitle, String sourceFilePath, String targetFilePath) throws IOException {
// 多柱状图
Map<String,Object> dataMap = new HashMap<>();
Charts.ChartCombos chartCombos = Charts.ofComboSeries(chartTitle,xData);
for (int i = 0; i < xLabels.length; i++) {
chartCombos.addBarSeries( xLabels[i], dataList.get(i));
}
chartCombos.setxAsixTitle(xTitle);
chartCombos.setyAsixTitle(yTitle);
ChartMultiSeriesRenderData data = chartCombos.create();
dataMap.put(replaceKey,data);
XWPFTemplate.compile(sourceFilePath).render(dataMap).writeToFile(targetFilePath);
}
/**
-
替换单体柱状图
-
@param xData
-
@param yData
-
@param replaceKey
-
@param xTitle
-
@param yTitle
*/
public static void replaceHistogram(String[] xData,Double[] yData,String replaceKey,String xTitle,String yTitle,String chartTitle,String sourceFilePath,String targetFilePath) throws IOException {if(xData.length == 0 ){
return;
}if(yData.length == 0){
return;
}
if(xData.length != yData.length){
return;
}
Map<String,Object> map = new HashMap<>();
Charts.ChartMultis chartMultis = Charts.ofBar(chartTitle, new String[]{chartTitle});
for (int i = 0; i < xData.length; i++) {
chartMultis.addSeries(xData[i],new Number[]{yData[i]});
}
chartMultis.setxAsixTitle(xTitle);
chartMultis.setyAsixTitle(yTitle);
ChartMultiSeriesRenderData data1 = chartMultis.create();
map.put(replaceKey,data1);
XWPFTemplate.compile(sourceFilePath).render(map).writeToFile(targetFilePath);
}
public static void main(String[] args) throws Exception {
FileInputStream is = new FileInputStream("./pdftemplate/word-template.docx");
XWPFDocument document = new XWPFDocument(is);
Map<String,String> dataMap = new HashMap<>();
dataMap.put("${checkCompanyName}","AAA");
dataMap.put("${checkCompanyName2}","BBBB");
dataMap.put("${Ltd}"," Ltd");
dataMap.put("${webAddress}","网址");
dataMap.put("${email}","邮箱");
dataMap.put("${companyName}","公司名称");
dataMap.put("${reportCreateTime}", DateUtil.getNowTime());
Map<String,String> checkBoxMap = new HashMap<>();
checkBoxMap.put("${risk}","47");
checkBoxMap.put("${hRisk}","10");
checkBoxMap.put("${mRisk}","20");
checkBoxMap.put("${lRisk}","17");
checkBoxMap.put("${round}","2019年01月01日-2024年07月31日");
checkBoxMap.put("${companyName}","ABCDEFG");
//替换数据
operateWord(document,dataMap,new HashMap<>(),checkBoxMap);//生成概述表格 List<String[]> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { list.add(new String[]{"A",String.valueOf(i), i +String.valueOf(i)}); } //增加并合并表格 createSummarizeTable(document.getTables().get(0),"0",list); createSummarizeTable(document.getTables().get(0),"1",list); createSummarizeTable(document.getTables().get(0),"2",list); FileOutputStream out = new FileOutputStream("./pdftemplate/word-template-out.docx"); document.write(out); //单柱状图
// File inputWord = new File("./pdftemplate/word-template-out-demo2.docx");
// File outputFile = new File("./pdftemplate/word-template-0726.pdf");
// word2pdf(inputWord,outputFile);
replaceHistogram(new String[]{"13","6"},new Double[]{35000d,9000d},"demo","税率(%)","开票额(元)","各税率销售、采购金额对比图","./pdftemplate/word-template.docx","./pdftemplate/word-template-out.docx");
//多柱状图
ArrayList<Integer[]> dataList = new ArrayList<>();
dataList.add(new Integer[]{35000,3000});
dataList.add(new Integer[]{9000,600});
replaceHistograms(new String[]{"进项","销项"},new String[]{"13","6"},dataList,"demo1","税率(%)","开票额(元)","各税率销售、采购金额对比图","./pdftemplate/word-template.docx","./pdftemplate/word-template-out.docx");
replaceLineChart(new String[]{"进项","销项"},new String[]{"13","6"},dataList,"demo2","税率(%)","开票额(元)","各税率销售、采购金额对比图","./pdftemplate/word-template.docx","./pdftemplate/word-template-out.docx");
//Word 转 PDF
// File inputWord = new File("./pdftemplate/word-template-out.docx");
// File outputFile = new File("./pdftemplate/word-template-0726.pdf");
// word2pdf(inputWord,outputFile);
}
}
`
部分较为复杂的方法使用案例:
WordUtil 替换柱状图
参数:
replaceHistogram(new String[]{"13","6"},new Double[]{35000d,9000d},"demo","税率(%)","开票额(元)","各税率销售、采购金额对比图","./pdftemplate/word-template.docx","./pdftemplate/word-template-out.docx");
WordUtil 替换多柱状图对比
参数:
ArrayList<Integer[]> dataList = new ArrayList<>();
dataList.add(new Integer[]{35000,3000});
dataList.add(new Integer[]{9000,600});
replaceHistograms(new String[]{"进项","销项"},new java.lang.String[]{"13","6"},dataList,"demo1","税率(%)","开票额(元)","各税率销售、采购金额对比图","./pdftemplate/word-template.docx","./pdftemplate/word-template-out.docx");
WordUtil替换折线图
参数:
ArrayList<Integer[]> dataList = new ArrayList<>();
dataList.add(new Integer[]{35000,3000});
dataList.add(new Integer[]{9000,600});
replaceLineChart(new String[]{"进项","销项"},new String[]{"13","6"},dataList,"demo2","税率(%)","开票额(元)","各税率销售、采购金额对比图","./pdftemplate/word-template.docx","./pdftemplate/word-template-out.docx");
Word模板中插入替换点:
1.在对应的位置添加一个图表
点击插入——图表——选择需要的图表格式点击确定按钮
2.设置替换的key,replaceKey
右键点击图表——设置图表区域格式——点击布局属性——在标题中输入替换key——保存模板
PS:部分代码来自于某些大神的博客,如有侵权问题,请联系删除!
QQ: 1575200647
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了