模板文档
首先,需要创建一个word模板,我的模板例子如下:
动态生成的文档
根据java代码动态的修改模板生成自己想要的文档,结果如下:
具体代码
代码操作如下:其中进行了文本的替换,图片的插入,以及表格的操作。
引入依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
java代码
工具类FileUtil,OfficeUtil,CustomXWPFDocument的下载
提取码: x9dd
注:CustomXWPFDocument是继承XWPFDocument的重写的工具类
@RestController
@CrossOrigin
@RequestMapping("Download")
@Slf4j
public class DownloadWordController {
@RequestMapping("Word")
@ResponseBody
public ResponseEntity<ByteArrayResource> downLoadReport(HttpServletRequest request, HttpServletResponse response) {
try {
String img1="D://file//图片1.png";
//复制模板1给模板2,之后操作模板2,为了防止模板1的变动,之后动态修改模板2
FileUtil.fileChannelCopy("D://file//模板1.docx", "D://file//模板2.docx");
Map<String,Object> param = new HashMap<String, Object>();
param.put("Hi", "你好!");
param.put("Welcome", "欢迎!");
/*指定模板位置pg_gyscpzlgksppg的位置替换为图片
Map<String,Object> header = new HashMap<String, Object>();
header.put("width", 100);
header.put("height", 100);
header.put("type", "png");
header.put("content", image2Bytes("D:\\test\\upload\\img\\a.png"));
param.put("我的图片",header);*/
//根据工具类将param中的要替换的内容替换到模板2中
CustomXWPFDocument doc = OfficeUtil.generateWord(param, "D://file//模板2.docx");
//遍历word文档的所有段落,向指定位置添加图片和操作指定表格
for (XWPFParagraph p : doc.getParagraphs()) {
List<XWPFRun> runs = p.getRuns();
if (runs != null) {
for (XWPFRun r : runs) {
//需要替换的文本
String text = "图片1";
String tableName = "我的表格";
String text2 = r.getText(0);
//向指定位置添加图片
if (text != null && text2 != null && text2.contains(text)) {
//从0开始替换文本为“”
r.setText("图片1如下:", 0);
r.addBreak();//换行
r.setText(" ");
//设置图片(图片流,图片格式,图片名称,图片宽,图片高)
r.addPicture(new FileInputStream(img1), XWPFDocument.PICTURE_TYPE_PNG, new File(img1).getName(), Units.toEMU(200), Units.toEMU(100));
r.addBreak();//换行
r.setText(" 图片1");
r.addBreak();//换行
r.setText(" ");
}
//操作指定表格
if (text2 != null && text2.contains(tableName)) {
//获取模板中的第1个表格
XWPFTable table = doc.getTables().get(0);
//给此表格添加三行
addRows(table, 2, 3);
//删除第2行和第3行原有的的第一个单元格的第一段数据
//table.getRow(1).getCell(0).removeParagraph(0);
//table.getRow(2).getCell(0).removeParagraph(0);
//开始为表格添加数据
for (int i = 1; i <= 5; i++) {
XWPFTableRow row = table.getRow(i);
int index=0;
row.getCell(index).removeParagraph(0);
row.getCell(index++).setText(String.valueOf(i));//设置序号
row.getCell(index++).setText("五年2班");//设置班级
row.getCell(index++).setText("李雷");//设置姓名
row.getCell(index++).setText("90");//设置语文
row.getCell(index++).setText("95");//设置数学
}
//合并单元格
mergeCellsVertically(table, 1, 1, 5);
}
}
}
}
//将修改后的模板2文档写入最终文档final.docx
FileOutputStream fopts = new FileOutputStream("D:\\test\\wordFile\\final.docx");
doc.write(fopts);
fopts.close();
doc.close();
//设备供应商
String fileName = "最终文档";
File file = new File("D:\\test\\wordFile\\final.docx");
ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(Paths.get(file.getAbsolutePath())));
return ResponseEntity.ok().header("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + ".docx", "UTF-8"))
.header("FileName", URLEncoder.encode(fileName + ".docx", "UTF-8"))
.header("Access-Control-Expose-Headers", "FileName")
.contentLength(file.length()).contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"))
.body(resource);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* author:wangzhiming
* date:2022-01-18
* des:表末尾添加行(表下标,要复制样式的行,添加行数),此方法先添加行之后再操作表格较好
* @param table
* @param source
* @param rows
*/
public void addRows(XWPFTable table, int source, int rows){
try{
int index = table.getNumberOfRows();
for(int i=1;i<=rows;i++) {
XWPFTableRow sourceRow = table.getRow(source);
XWPFTableRow targetRow = table.insertNewTableRow(index++);
targetRow.getCtRow().setTrPr(sourceRow.getCtRow().getTrPr());
List<XWPFTableCell> sourceCells = sourceRow.getTableCells();
for (XWPFTableCell sourceCell : sourceCells) {
XWPFTableCell newCell = targetRow.addNewTableCell();
newCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());
List<XWPFParagraph> sourceParagraphs = sourceCell.getParagraphs();
if (StringUtils.isEmpty(sourceCell.getText())) {
continue;
}
XWPFParagraph sourceParagraph = sourceParagraphs.get(0);
List<XWPFParagraph> targetParagraphs = newCell.getParagraphs();
if (StringUtils.isEmpty(newCell.getText())) {
XWPFParagraph ph = newCell.addParagraph();
ph.getCTP().setPPr(sourceParagraph.getCTP().getPPr());
XWPFRun run = ph.getRuns().isEmpty() ? ph.createRun() : ph.getRuns().get(0);
if(sourceParagraph.getRuns().size()>0)
run.setFontFamily(sourceParagraph.getRuns().get(0).getFontFamily());
} else {
XWPFParagraph ph = targetParagraphs.get(0);
ph.getCTP().setPPr(sourceParagraph.getCTP().getPPr());
XWPFRun run = ph.getRuns().isEmpty() ? ph.createRun() : ph.getRuns().get(0);
if(sourceParagraph.getRuns().size()>0)
run.setFontFamily(sourceParagraph.getRuns().get(0).getFontFamily());
}
}
}
}catch (Exception e){
log.error(e.getMessage(),e);
}
}
/**
* author:wangzhiming
* date:2022-01-18
* des:word跨行并单元格(表,合并哪一列,开始合并的行,合并结束的行)
* @param table
* @param col
* @param fromRow
* @param toRow
*/
public void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) {
/*for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
if ( rowIndex == fromRow ) {
// The first merged cell is set with RESTART merge value
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
} else {
// Cells which join (merge) the first one, are set with CONTINUE
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
}
}*/
for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++)
{
XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
CTTc ctTc = cell.getCTTc();
if (ctTc.getTcPr() == null)
{
ctTc.addNewTcPr();
}
//第一个合并单元格用重启合并值设置
if (rowIndex == fromRow)
{
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
}
else
{
//合并第一个单元格的单元被设置为“继续”
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
}
}
}
}