java poi word 表格 重复_java使用poi操作word, 支持动态的行(一个占位符插入多条)和表格中动态行, 支持图片...

news/2024/11/23 9:46:35/

依赖

org.apache.poi

poi

3.17

org.apache.poi

poi-ooxml

3.17

org.apache.poi

poi-ooxml-schemas

3.17

核心工具类

package com.dist.web.util.poiword;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;

import org.apache.poi.openxml4j.opc.OPCPackage;

import org.apache.poi.xwpf.usermodel.*;

import org.apache.xmlbeans.XmlCursor;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.util.Assert;

import org.springframework.util.ResourceUtils;

import java.io.*;

import java.util.*;

/**

* Create by IntelliJ Idea 2018.2

*

* @author: qyp

* Date: 2019-10-25 14:48

*/

public class DynWordUtils {

private final Logger logger = LoggerFactory.getLogger(DynWordUtils.class);

/**

* 被list替换的段落 被替换的都是oldParagraph

*/

private XWPFParagraph oldParagraph;

/**

* 参数

*/

private Map paramMap;

/**

* 当前元素的位置

*/

int n = 0;

/**

* 判断当前是否是遍历的表格

*/

boolean isTable = false;

/**

* 模板对象

*/

XWPFDocument templateDoc;

/**

* 默认字体的大小

*/

final int DEFAULT_FONT_SIZE = 10;

/**

* 重复模式的占位符所在的行索引

*/

private int currentRowIndex;

/**

* 入口

*

* @param paramMap 模板中使用的参数

* @param templatePaht 模板全路径

* @param outPath 生成的文件存放的本地全路径

*/

public static void process(Map paramMap, String templatePaht, String outPath) {

DynWordUtils dynWordUtils = new DynWordUtils();

dynWordUtils.setParamMap(paramMap);

dynWordUtils.createWord(templatePaht, outPath);

}

/**

* 生成动态的word

* @param templatePath

* @param outPath

*/

public void createWord(String templatePath, String outPath) {

try (FileOutputStream outStream = new FileOutputStream(outPath)) {

InputStream inputStream = new FileInputStream(ResourceUtils.getFile(templatePath));

templateDoc = new XWPFDocument(OPCPackage.open(inputStream));

parseTemplateWord();

templateDoc.write(outStream);

} catch (Exception e) {

StackTraceElement[] stackTrace = e.getStackTrace();

String className = stackTrace[0].getClassName();

String methodName = stackTrace[0].getMethodName();

int lineNumber = stackTrace[0].getLineNumber();

logger.error("错误:第:{}行, 类名:{}, 方法名:{}", lineNumber, className, methodName);

throw new RuntimeException(e.getCause().getMessage());

}

}

/**

* 解析word模板

*/

public void parseTemplateWord() throws Exception {

List elements = templateDoc.getBodyElements();

for (; n < elements.size(); n++) {

IBodyElement element = elements.get(n);

// 普通段落

if (element instanceof XWPFParagraph) {

XWPFParagraph paragraph = (XWPFParagraph) element;

oldParagraph = paragraph;

if (paragraph.getParagraphText().isEmpty()) {

continue;

}

delParagraph(paragraph);

} else if (element instanceof XWPFTable) {

// 表格

isTable = true;

XWPFTable table = (XWPFTable) element;

delTable(table, paramMap);

isTable = false;

}

}

}

/**

* 处理段落

*/

private void delParagraph(XWPFParagraph paragraph) throws Exception {

List runs = oldParagraph.getRuns();

StringBuilder sb = new StringBuilder();

for (XWPFRun run : runs) {

String text = run.getText(0);

if (text == null) {

continue;

}

sb.append(text);

run.setText("", 0);

}

Placeholder(paragraph, runs, sb);

}

/**

* 匹配传入信息集合与模板

*

* @param placeholder 模板需要替换的区域()

* @param paramMap 传入信息集合

* @return 模板需要替换区域信息集合对应值

*/

public void changeValue(XWPFRun currRun, String placeholder, Map paramMap) throws Exception {

String placeholderValue = placeholder;

if (paramMap == null || paramMap.isEmpty()) {

return;

}

Set> textSets = paramMap.entrySet();

for (Map.Entry textSet : textSets) {

//匹配模板与替换值 格式${key}

String mapKey = textSet.getKey();

String docKey = PoiWordUtils.getDocKey(mapKey);

if (placeholderValue.indexOf(docKey) != -1) {

Object obj = textSet.getValue();

// 需要添加一个list

if (obj instanceof List) {

placeholderValue = delDynList(placeholder, (List) obj);

} else {

placeholderValue = placeholderValue.replaceAll(

PoiWordUtils.getPlaceholderReg(mapKey)

, String.valueOf(obj));

}

}

}

currRun.setText(placeholderValue, 0);

}

/**

* 处理的动态的段落(参数为list)

*

* @param placeholder 段落占位符

* @param obj

* @return

*/

private String delDynList(String placeholder, List obj) {

String placeholderValue = placeholder;

List dataList = obj;

Collections.reverse(dataList);

for (int i = 0, size = dataList.size(); i < size; i++) {

Object text = dataList.get(i);

// 占位符的那行, 不用重新创建新的行

if (i == 0) {

placeholderValue = String.valueOf(text);

} else {

XWPFParagraph paragraph = createParagraph(String.valueOf(text));

if (paragraph != null) {

oldParagraph = paragraph;

}

// 增加段落后doc文档的element的size会随着增加(在当前行的上面添加

// 这里减操作是回退并解析新增的行(因为可能新增的带有占位符,这里为了支持图片和表格)

if (!isTable) {

n--;

}

}

}

return placeholderValue;

}

/**

* 创建段落

*

* @param texts

*/

public XWPFParagraph createParagraph(String... texts) {

// 使用游标创建一个新行

XmlCursor cursor = oldParagraph.getCTP().newCursor();

XWPFParagraph newPar = templateDoc.insertNewParagraph(cursor);

// 设置段落样式

newPar.getCTP().setPPr(oldParagraph.getCTP().getPPr());

copyParagraph(oldParagraph, newPar, texts);

return newPar;

}

/**

* 处理表格(遍历)

*

* @param table 表格

* @param paramMap 需要替换的信息集合

*/

public void delTable(XWPFTable table, Map paramMap) throws Exception {

List rows = table.getRows();

for (int i = 0, size = rows.size(); i < size; i++) {

XWPFTableRow row = rows.get(i);

currentRowIndex = i;

// 如果是动态添加行 直接处理后终止

if (delAndJudgeRow(table, paramMap, row)) {

return;

}

}

}

/**

* 判断并且是否是动态行,并且处理表格占位符

* @param table 表格对象

* @param paramMap 参数map

* @param row 当前行

* @return

* @throws Exception

*/

private boolean delAndJudgeRow(XWPFTable table, Map paramMap, XWPFTableRow row) throws Exception {

// 当前行是动态行标志

if (PoiWordUtils.isAddRow(row)) {

List xwpfTableRows = addAndGetRows(table, row, paramMap);

// 回溯添加的行,这里是试图处理动态添加的图片

for (XWPFTableRow tbRow : xwpfTableRows) {

delAndJudgeRow(table, paramMap, tbRow);

}

return true;

}

// 如果是重复添加的行

if (PoiWordUtils.isAddRowRepeat(row)) {

List xwpfTableRows = addAndGetRepeatRows(table, row, paramMap);

/*// 回溯添加的行,这里是试图处理动态添加的图片

for (XWPFTableRow tbRow : xwpfTableRows) {

delAndJudgeRow(table, paramMap, tbRow);

}*/

return true;

}

// 当前行非动态行标签

List cells = row.getTableCells();

for (XWPFTableCell cell : cells) {

//判断单元格是否需要替换

if (PoiWordUtils.checkText(cell.getText())) {

List paragraphs = cell.getParagraphs();

for (XWPFParagraph paragraph : paragraphs) {

List runs = paragraph.getRuns();

StringBuilder sb = new StringBuilder();

for (XWPFRun run : runs) {

sb.append(run.toString());

run.setText("", 0);

}

Placeholder(paragraph, runs, sb);

}

}

}

return false;

}

/**

* 处理占位符

* @param runs 当前段的runs

* @param sb 当前段的内容

* @throws Exception

*/

private void Placeholder(XWPFParagraph currentPar, List runs, StringBuilder sb) throws Exception {

if (runs.size() > 0) {

String text = sb.toString();

XWPFRun currRun = runs.get(0);

if (PoiWordUtils.isPicture(text)) {

// 该段落是图片占位符

ImageEntity imageEntity = (ImageEntity) PoiWordUtils.getValueByPlaceholder(paramMap, text);

int indentationFirstLine = currentPar.getIndentationFirstLine();

// 清除段落的格式,否则图片的缩进有问题

currentPar.getCTP().setPPr(null);

//设置缩进

currentPar.setIndentationFirstLine(indentationFirstLine);

addPicture(currRun, imageEntity);

} else {

changeValue(currRun, text, paramMap);

}

}

}

/**

* 添加图片

* @param currRun 当前run

* @param imageEntity 图片对象

* @throws InvalidFormatException

* @throws FileNotFoundException

*/

private void addPicture(XWPFRun currRun, ImageEntity imageEntity) throws InvalidFormatException, FileNotFoundException {

Integer typeId = imageEntity.getTypeId().getTypeId();

String picId = currRun.getDocument().addPictureData(new FileInputStream(imageEntity.getUrl()), typeId);

ImageUtils.createPicture(currRun, picId, templateDoc.getNextPicNameNumber(typeId),

imageEntity.getWidth(), imageEntity.getHeight());

}

/**

* 添加行 标签行不是新创建的

*

* @param table

* @param flagRow flagRow 表有标签的行

* @param paramMap 参数

*/

private List addAndGetRows(XWPFTable table, XWPFTableRow flagRow, Map paramMap) throws Exception {

List flagRowCells = flagRow.getTableCells();

XWPFTableCell flagCell = flagRowCells.get(0);

String text = flagCell.getText();

List> dataList = (List>) PoiWordUtils.getValueByPlaceholder(paramMap, text);

// 新添加的行

List newRows = new ArrayList<>(dataList.size());

if (dataList == null || dataList.size() <= 0) {

return newRows;

}

XWPFTableRow currentRow = flagRow;

int cellSize = flagRow.getTableCells().size();

for (int i = 0, size = dataList.size(); i < size; i++) {

if (i != 0) {

currentRow = table.createRow();

// 复制样式

if (flagRow.getCtRow() != null) {

currentRow.getCtRow().setTrPr(flagRow.getCtRow().getTrPr());

}

}

addRow(flagCell, currentRow, cellSize, dataList.get(i));

newRows.add(currentRow);

}

return newRows;

}

/**

* 添加重复多行 动态行 每一行都是新创建的

* @param table

* @param flagRow

* @param paramMap

* @return

* @throws Exception

*/

private List addAndGetRepeatRows(XWPFTable table, XWPFTableRow flagRow, Map paramMap) throws Exception {

List flagRowCells = flagRow.getTableCells();

XWPFTableCell flagCell = flagRowCells.get(0);

String text = flagCell.getText();

List> dataList = (List>) PoiWordUtils.getValueByPlaceholder(paramMap, text);

String tbRepeatMatrix = PoiWordUtils.getTbRepeatMatrix(text);

Assert.notNull(tbRepeatMatrix, "模板矩阵不能为空");

// 新添加的行

List newRows = new ArrayList<>(dataList.size());

if (dataList == null || dataList.size() <= 0) {

return newRows;

}

String[] split = tbRepeatMatrix.split(PoiWordUtils.tbRepeatMatrixSeparator);

int startRow = Integer.parseInt(split[0]);

int endRow = Integer.parseInt(split[1]);

int startCell = Integer.parseInt(split[2]);

int endCell = Integer.parseInt(split[3]);

XWPFTableRow currentRow;

for (int i = 0, size = dataList.size(); i < size; i++) {

int flagRowIndex = i % (endRow - startRow + 1);

XWPFTableRow repeatFlagRow = table.getRow(flagRowIndex);

// 清除占位符那行

if (i == 0) {

table.removeRow(currentRowIndex);

}

currentRow = table.createRow();

// 复制样式

if (repeatFlagRow.getCtRow() != null) {

currentRow.getCtRow().setTrPr(repeatFlagRow.getCtRow().getTrPr());

}

addRowRepeat(startCell, endCell, currentRow, repeatFlagRow, dataList.get(i));

// 处理新生成的那行是否有占位符需要处理

delAndJudgeRow(table, paramMap, currentRow);

newRows.add(currentRow);

}

deleteTemplateRow(startRow, endRow, table);

return newRows;

}

/**

* 删除模板行

*/

private void deleteTemplateRow(int startRowIdx, int endRowIdx, XWPFTable table) {

for (;startRowIdx <= endRowIdx; startRowIdx++) {

table.removeRow(0);

}

}

/**

* 根据模板cell添加新行

*

* @param flagCell 模板列(标记占位符的那个cell)

* @param row 新增的行

* @param cellSize 每行的列数量(用来补列补足的情况)

* @param rowDataList 每行的数据

*/

private void addRow(XWPFTableCell flagCell, XWPFTableRow row, int cellSize, List rowDataList) {

for (int i = 0; i < cellSize; i++) {

XWPFTableCell cell = row.getCell(i);

cell = cell == null ? row.createCell() : row.getCell(i);

if (i < rowDataList.size()) {

PoiWordUtils.copyCellAndSetValue(flagCell, cell, rowDataList.get(i));

} else {

// 数据不满整行时,添加空列

PoiWordUtils.copyCellAndSetValue(flagCell, cell, "");

}

}

}

/**

* 根据模板cell 添加重复行

* @param startCell 模板列的开始位置

* @param endCell 模板列的结束位置

* @param currentRow 创建的新行

* @param repeatFlagRow 模板列所在的行

* @param rowDataList 每行的数据

*/

private void addRowRepeat(int startCell, int endCell, XWPFTableRow currentRow, XWPFTableRow repeatFlagRow, List rowDataList) {

int cellSize = repeatFlagRow.getTableCells().size();

for (int i = 0; i < cellSize; i++) {

XWPFTableCell cell = currentRow.getCell(i);

cell = cell == null ? currentRow.createCell() : currentRow.getCell(i);

int flagCellIndex = i % (endCell - startCell + 1);

XWPFTableCell repeatFlagCell = repeatFlagRow.getCell(flagCellIndex);

if (i < rowDataList.size()) {

PoiWordUtils.copyCellAndSetValue(repeatFlagCell, cell, rowDataList.get(i));

} else {

// 数据不满整行时,添加空列

PoiWordUtils.copyCellAndSetValue(repeatFlagCell, cell, "");

}

}

}

/**

* 复制段落

*

* @param sourcePar 原段落

* @param targetPar

* @param texts

*/

private void copyParagraph(XWPFParagraph sourcePar, XWPFParagraph targetPar, String... texts) {

targetPar.setAlignment(sourcePar.getAlignment());

targetPar.setVerticalAlignment(sourcePar.getVerticalAlignment());

// 设置布局

targetPar.setAlignment(sourcePar.getAlignment());

targetPar.setVerticalAlignment(sourcePar.getVerticalAlignment());

if (texts != null && texts.length > 0) {

String[] arr = texts;

XWPFRun xwpfRun = sourcePar.getRuns().size() > 0 ? sourcePar.getRuns().get(0) : null;

for (int i = 0, len = texts.length; i < len; i++) {

String text = arr[i];

XWPFRun run = targetPar.createRun();

run.setText(text);

run.setFontFamily(xwpfRun.getFontFamily());

int fontSize = xwpfRun.getFontSize();

run.setFontSize((fontSize == -1) ? DEFAULT_FONT_SIZE : fontSize);

run.setBold(xwpfRun.isBold());

run.setItalic(xwpfRun.isItalic());

}

}

}

public void setParamMap(Map paramMap) {

this.paramMap = paramMap;

}

}

poi工具类

PoiWordUtils

package com.dist.web.util.poiword;

import org.apache.poi.xwpf.usermodel.*;

import org.springframework.util.Assert;

import java.util.List;

import java.util.Map;

import java.util.Optional;

/**

* Create by IntelliJ Idea 2018.2

*

* @author: qyp

* Date: 2019-10-26 2:12

*/

public class PoiWordUtils {

/**

* 占位符第一个字符

*/

public static final String PREFIX_FIRST = "$";

/**

* 占位符第二个字符

*/

public static final String PREFIX_SECOND = "{";

/**

* 占位符的前缀

*/

public static final String PLACEHOLDER_PREFIX = PREFIX_FIRST + PREFIX_SECOND;

/**

* 占位符后缀

*/

public static final String PLACEHOLDER_END = "}";

/**

* 表格中需要动态添加行的独特标记

*/

public static final String addRowText = "tbAddRow:";

public static final String addRowRepeatText = "tbAddRowRepeat:";

/**

* 表格中占位符的开头 ${tbAddRow: 例如${tbAddRow:tb1}

*/

public static final String addRowFlag = PLACEHOLDER_PREFIX + addRowText;

/**

* 表格中占位符的开头 ${tbAddRowRepeat: 例如 ${tbAddRowRepeat:0,2,0,1} 第0行到第2行,第0列到第1列 为模板样式

*/

public static final String addRowRepeatFlag = PLACEHOLDER_PREFIX + addRowRepeatText;

/**

* 重复矩阵的分隔符 比如:${tbAddRowRepeat:0,2,0,1} 分隔符为 ,

*/

public static final String tbRepeatMatrixSeparator = ",";

/**

* 占位符的后缀

*/

public static final String PLACEHOLDER_SUFFIX = "}";

/**

* 图片占位符的前缀

*/

public static final String PICTURE_PREFIX = PLACEHOLDER_PREFIX + "image:";

/**

* 判断当前行是不是标志表格中需要添加行

*

* @param row

* @return

*/

public static boolean isAddRow(XWPFTableRow row) {

return isDynRow(row, addRowFlag);

}

/**

* 添加重复模板动态行(以多行为模板)

* @param row

* @return

*/

public static boolean isAddRowRepeat(XWPFTableRow row) {

return isDynRow(row, addRowRepeatFlag);

}

private static boolean isDynRow(XWPFTableRow row, String dynFlag) {

if (row == null) {

return false;

}

List tableCells = row.getTableCells();

if (tableCells != null) {

XWPFTableCell cell = tableCells.get(0);

if (cell != null) {

String text = cell.getText();

return text != null && text.startsWith(dynFlag);

}

}

return false;

}

/**

* 从参数map中获取占位符对应的值

*

* @param paramMap

* @param key

* @return

*/

public static Object getValueByPlaceholder(Map paramMap, String key) {

if (paramMap != null) {

if (key != null) {

return paramMap.get(getKeyFromPlaceholder(key));

}

}

return null;

}

/**

* 后去占位符的重复行列矩阵

* @param key 占位符

* @return {0,2,0,1}

*/

public static String getTbRepeatMatrix(String key) {

Assert.notNull(key, "占位符为空");

String $1 = key.replaceAll("\\" + PREFIX_FIRST + "\\" + PREFIX_SECOND + addRowRepeatText + "(.*:)(.*)" + "\\" + PLACEHOLDER_SUFFIX, "$2");

return $1;

}

/**

* 从占位符中获取key

*

* @return

*/

public static String getKeyFromPlaceholder(String placeholder) {

return Optional.ofNullable(placeholder).map(p -> p.replaceAll("[\\$\\{\\}]", "")).get();

}

public static void main(String[] args) {

String s = "${aa}";

s = s.replaceAll(PLACEHOLDER_PREFIX + PLACEHOLDER_SUFFIX , "");

System.out.println(s);

// String keyFromPlaceholder = getKeyFromPlaceholder("${tbAddRow:tb1}");

// System.out.println(keyFromPlaceholder);

}

/**

* 复制列的样式,并且设置值

* @param sourceCell

* @param targetCell

* @param text

*/

public static void copyCellAndSetValue(XWPFTableCell sourceCell, XWPFTableCell targetCell, String text) {

//段落属性

List sourceCellParagraphs = sourceCell.getParagraphs();

if (sourceCellParagraphs == null || sourceCellParagraphs.size() <= 0) {

return;

}

XWPFParagraph sourcePar = sourceCellParagraphs.get(0);

XWPFParagraph targetPar = targetCell.getParagraphs().get(0);

// 设置段落的样式

targetPar.getCTP().setPPr(sourcePar.getCTP().getPPr());

List sourceParRuns = sourcePar.getRuns();

if (sourceParRuns != null && sourceParRuns.size() > 0) {

// 如果当前cell中有run

List runs = targetPar.getRuns();

Optional.ofNullable(runs).ifPresent(rs -> rs.stream().forEach(r -> r.setText("", 0)));

if (runs != null && runs.size() > 0) {

runs.get(0).setText(text, 0);

} else {

XWPFRun cellR = targetPar.createRun();

cellR.setText(text, 0);

// 设置列的样式位模板的样式

targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());

}

setTypeface(sourcePar, targetPar);

} else {

// targetCell.setText(text);

List runs = targetPar.getRuns();

if (runs != null && runs.size() > 0) {

runs.get(0).setText(text, 0);

} else {

XWPFRun newRun = targetPar.createRun();

newRun.setText(text, 0);

}

}

}

/**

* 复制字体

*/

private static void setTypeface(XWPFParagraph sourcePar, XWPFParagraph targetPar) {

XWPFRun sourceRun = sourcePar.getRuns().get(0);

String fontFamily = sourceRun.getFontFamily();

//int fontSize = sourceRun.getFontSize();

String color = sourceRun.getColor();

// String fontName = sourceRun.getFontName();

boolean bold = sourceRun.isBold();

boolean italic = sourceRun.isItalic();

int kerning = sourceRun.getKerning();

// String style = sourcePar.getStyle();

UnderlinePatterns underline = sourceRun.getUnderline();

XWPFRun targetRun = targetPar.getRuns().get(0);

targetRun.setFontFamily(fontFamily);

// targetRun.setFontSize(fontSize == -1 ? 10 : fontSize);

targetRun.setBold(bold);

targetRun.setColor(color);

targetRun.setItalic(italic);

targetRun.setKerning(kerning);

targetRun.setUnderline(underline);

//targetRun.setFontSize(fontSize);

}

/**

* 判断文本中时候包含$

* @param text 文本

* @return 包含返回true,不包含返回false

*/

public static boolean checkText(String text){

boolean check = false;

if(text.indexOf(PLACEHOLDER_PREFIX)!= -1){

check = true;

}

return check;

}

/**

* 获得占位符替换的正则表达式

* @return

*/

public static String getPlaceholderReg(String text) {

return "\\" + PREFIX_FIRST + "\\" + PREFIX_SECOND + text + "\\" + PLACEHOLDER_SUFFIX;

}

public static String getDocKey(String mapKey) {

return PLACEHOLDER_PREFIX + mapKey + PLACEHOLDER_SUFFIX;

}

/**

* 判断当前占位符是不是一个图片占位符

* @param text

* @return

*/

public static boolean isPicture(String text) {

return text.startsWith(PICTURE_PREFIX);

}

/**

* 删除一行的列

* @param row

*/

public static void removeCells(XWPFTableRow row) {

int size = row.getTableCells().size();

try {

for (int i = 0; i < size; i++) {

row.removeCell(i);

}

} catch (Exception e) {

}

}

}

对图片的支持

ImageEntity

package per.qiao.utils.hutool.poi;

import static per.qiao.utils.hutool.poi.ImageUtils.ImageType.PNG;

/**

* Create by IntelliJ Idea 2018.2

*

* 图片实体对象

*

* @author: qyp

* Date: 2019-10-26 21:52

*/

public class ImageEntity {

/**

* 图片宽度

*/

private int width = 400;

/**

* 图片高度

*/

private int height = 300;

/**

* 图片地址

*/

private String url;

/**

* 图片类型

* @see ImageUtils.ImageType

*/

private ImageUtils.ImageType typeId = PNG;

public int getWidth() {

return width;

}

public void setWidth(int width) {

this.width = width;

}

public int getHeight() {

return height;

}

public void setHeight(int height) {

this.height = height;

}

public String getUrl() {

return url;

}

public void setUrl(String url) {

this.url = url;

}

public ImageUtils.ImageType getTypeId() {

return typeId;

}

public void setTypeId(ImageUtils.ImageType typeId) {

this.typeId = typeId;

}

}

图片工具类

ImageUtils

package per.qiao.utils.hutool.poi;

import org.apache.poi.xwpf.usermodel.XWPFDocument;

import org.apache.poi.xwpf.usermodel.XWPFRun;

import org.apache.xmlbeans.XmlException;

import org.apache.xmlbeans.XmlToken;

import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;

import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;

import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;

/**

* Create by IntelliJ Idea 2018.2

*

* @author: qyp

* Date: 2019-10-26 21:55

*/

public class ImageUtils {

/**

* 图片类型枚举

*/

enum ImageType {

/**

* 支持四种类型 JPG/JPEG, GIT, BMP, PNG

*/

JPG("JPG", XWPFDocument.PICTURE_TYPE_JPEG),

JPEG("JPEG", XWPFDocument.PICTURE_TYPE_JPEG),

GIF("GIF", XWPFDocument.PICTURE_TYPE_GIF),

BMP("BMP", XWPFDocument.PICTURE_TYPE_GIF),

PNG("PNG", XWPFDocument.PICTURE_TYPE_PNG)

;

private String name;

private Integer typeId;

ImageType(String name, Integer type) {

this.name = name;

this.typeId = type;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Integer getTypeId() {

return typeId;

}

public void setTypeId(Integer typeId) {

this.typeId = typeId;

}

}

public static void createPicture(XWPFRun run, String blipId, int id, int width, int height) {

final int EMU = 9525;

width *= EMU;

height *= EMU;

CTInline inline = run.getCTR().addNewDrawing().addNewInline();

String picXml = "" +

"" +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

" " +

"";

XmlToken xmlToken = null;

try {

xmlToken = XmlToken.Factory.parse(picXml);

} catch(XmlException xe) {

xe.printStackTrace();

}

inline.set(xmlToken);

inline.setDistT(0);

inline.setDistB(0);

inline.setDistL(0);

inline.setDistR(0);

CTPositiveSize2D extent = inline.addNewExtent();

extent.setCx(width);

extent.setCy(height);

CTNonVisualDrawingProps docPr = inline.addNewDocPr();

docPr.setId(id);

docPr.setName("Picture " + id);

docPr.setDescr("Generated");

}

}

测试类

package com.dist.web.util.poiword;

import java.util.*;

/**

* Create by IntelliJ Idea 2018.2

*

* @author: qyp

* Date: 2019-10-26 17:34

*/

public class DynWordUtilsTest {

/**

* 说明 普通占位符位${field}格式

* 表格中的占位符为${tbAddRow:tb1} tb1为唯一标识符

* @param args

* @throws Exception

*/

public static void main(String[] args) {

// 模板全的路径

String templatePaht = "E:\\Java4IDEA\\comm_test\\commutil\\src\\main\\resources\\wordtemplate\\审查报告模板1023体检表.docx";

// 输出位置

String outPath = "e:\\22.docx";

Map paramMap = new HashMap<>(16);

// 普通的占位符示例 参数数据结构 {str,str}

paramMap.put("title", "德玛西亚");

paramMap.put("startYear", "2010");

paramMap.put("endYear", "2020");

paramMap.put("currentYear", "2019");

paramMap.put("currentMonth", "10");

paramMap.put("currentDate", "26");

paramMap.put("name", "黑色玫瑰");

// 段落中的动态段示例 [str], 支持动态行中添加图片

List list1 = new ArrayList<>(Arrays.asList("2、list1_11111", "3、list1_2222", "${image:image0}"));

ImageEntity imgEntity = new ImageEntity();

imgEntity.setHeight(200);

imgEntity.setWidth(300);

imgEntity.setUrl("E:\\Java4IDEA\\comm_test\\commutil\\src\\main\\resources\\wordtemplate\\image1.jpg");

imgEntity.setTypeId(ImageUtils.ImageType.JPG);

paramMap.put("image:image0", imgEntity);

paramMap.put("list1", list1);

List list2 = new ArrayList<>(Arrays.asList("2、list2_11111", "3、list2_2222"));

paramMap.put("list2", list2);

// 表格中的参数示例 参数数据结构 [[str]]

List> tbRow1 = new ArrayList<>();

List tbRow1_row1 = new ArrayList<>(Arrays.asList("1、模块一", "分类1"));

List tbRow1_row2 = new ArrayList<>(Arrays.asList("2、模块二", "分类2"));

tbRow1.add(tbRow1_row1);

tbRow1.add(tbRow1_row2);

paramMap.put(PoiWordUtils.addRowText + "tb1", tbRow1);

List> tbRow2 = new ArrayList<>();

List tbRow2_row1 = new ArrayList<>(Arrays.asList("指标c", "指标c的意见"));

List tbRow2_row2 = new ArrayList<>(Arrays.asList("指标d", "指标d的意见"));

tbRow2.add(tbRow2_row1);

tbRow2.add(tbRow2_row2);

paramMap.put(PoiWordUtils.addRowText + "tb2", tbRow2);

List> tbRow3 = new ArrayList<>();

List tbRow3_row1 = new ArrayList<>(Arrays.asList("3", "耕地估值"));

List tbRow3_row2 = new ArrayList<>(Arrays.asList("4", "耕地归属", "平方公里"));

tbRow3.add(tbRow3_row1);

tbRow3.add(tbRow3_row2);

paramMap.put(PoiWordUtils.addRowText + "tb3", tbRow3);

// 支持在表格中动态添加图片

List> tbRow4 = new ArrayList<>();

List tbRow4_row1 = new ArrayList<>(Arrays.asList("03", "旅游用地", "18.8m2"));

List tbRow4_row2 = new ArrayList<>(Arrays.asList("04", "建筑用地"));

List tbRow4_row3 = new ArrayList<>(Arrays.asList("04", "${image:image3}"));

tbRow4.add(tbRow4_row3);

tbRow4.add(tbRow4_row1);

tbRow4.add(tbRow4_row2);

// 支持在表格中添加重复模板的行

List> tbRow5 = new ArrayList<>();

List tbRow5_row1 = new ArrayList<>(Arrays.asList("欢乐喜剧人"));

List tbRow5_row2 = new ArrayList<>(Arrays.asList("常远", "艾伦"));

List tbRow5_row3 = new ArrayList<>(Arrays.asList("${tbAddRow:tb5}", ""));

List> tb5List = new ArrayList<>();

List tb5Row1 = new ArrayList<>(Arrays.asList("岳云鹏", "孙悦"));

List tb5Row2 = new ArrayList<>(Arrays.asList("小沈阳", "宋小宝"));

List tb5Row3 = new ArrayList<>(Arrays.asList("张云雷", "严鹤翔"));

tb5List.add(tb5Row1);

tb5List.add(tb5Row2);

tb5List.add(tb5Row3);

paramMap.put("tbAddRow:tb5", tb5List);

List tbRow5_row4 = new ArrayList<>(Arrays.asList("诺克萨斯"));

List tbRow5_row5 = new ArrayList<>(Arrays.asList("德莱文", "诺手"));

List tbRow5_row6 = new ArrayList<>(Arrays.asList("男枪", "卡特琳娜"));

tbRow5.add(tbRow5_row1);

tbRow5.add(tbRow5_row2);

tbRow5.add(tbRow5_row3);

tbRow5.add(tbRow5_row4);

tbRow5.add(tbRow5_row5);

tbRow5.add(tbRow5_row6);

paramMap.put("tbAddRowRepeat:tb5:0,2,0,1", tbRow5);

ImageEntity imgEntity3 = new ImageEntity();

imgEntity3.setHeight(100);

imgEntity3.setWidth(100);

imgEntity3.setUrl("E:\\Java4IDEA\\comm_test\\commutil\\src\\main\\resources\\wordtemplate\\image1.jpg");

imgEntity3.setTypeId(ImageUtils.ImageType.JPG);

paramMap.put(PoiWordUtils.addRowText + "tb4", tbRow4);

paramMap.put("image:image3", imgEntity3);

// 图片占位符示例 ${image:imageid} 比如 ${image:image1}, ImageEntity中的值就为image:image1

// 段落中的图片

ImageEntity imgEntity1 = new ImageEntity();

imgEntity1.setHeight(500);

imgEntity1.setWidth(400);

imgEntity1.setUrl("E:\\Java4IDEA\\comm_test\\commutil\\src\\main\\resources\\wordtemplate\\image1.jpg");

imgEntity1.setTypeId(ImageUtils.ImageType.JPG);

paramMap.put("image:image1", imgEntity1);

// 表格中的图片

ImageEntity imgEntity2 = new ImageEntity();

imgEntity2.setHeight(200);

imgEntity2.setWidth(100);

imgEntity2.setUrl("E:\\Java4IDEA\\comm_test\\commutil\\src\\main\\resources\\wordtemplate\\image1.jpg");

imgEntity2.setTypeId(ImageUtils.ImageType.JPG);

paramMap.put("image:image2", imgEntity2);

DynWordUtils.process(paramMap, templatePaht, outPath);

}

}

模板图

9ce3de5115a9721cc145adc3dc53b291.png

效果图

378079ef3d3a0324bd583a928c7ca62c.png

部分参考了easypoi源码


http://www.ppmy.cn/news/834894.html

相关文章

word表格删除空白行java_在Word中怎样批量删除空行,这些点主要注意

在工作中经常接触的办公软件就是Word了&#xff0c;熟练使用Word中的技能是准时下班的保证。这就要求我们对Word中的各项技能都熟练于心&#xff0c;很多朋友诉苦Word中的排版不熟悉&#xff0c;每次写一篇文章排版都要花费很多心思。 针对大家的问题&#xff0c;今天对Word中常…

计算机考试成表格,2010年职称计算机考试:Word创建表格

创建表格 1、插入表格&#xff1a;定位插入点&#xff0c;单击[表格]/[插入]/[表格]&#xff0c;在弹出[插入表格]对话框中输入行数和列数&#xff0c;并选择表格性质&#xff0c;单击[确定]。 2、绘制表格&#xff1a; ◆打开[表格和边框]工具栏&#xff1a;单击[视图]/[工具栏…

html中怎么给表格增加序号,如何给word表格中添加编号

在Word中制作表格时都希望在表格的第一列增加一个序号&#xff0c;其作用可以标识行或统计行数。例如从1开始&#xff0c;一直到80、100甚至更多。那么怎么添加呢&#xff1f;采用手工进行编辑还是其他的&#xff1f;手工编辑显然是一件不可能的事&#xff0c;不仅费时费力而且…

Word中表格相关的操作

清除表格中的内容 选中需要清除的文字&#xff0c;按Delete键 表格中列的对齐方式 快捷键&#xff1a;Alt鼠标拉动对齐位置 tips&#xff1a; 如果发现用上述快捷键也比较难对齐&#xff0c;就把表格放大&#xff0c;这样就很容易对齐了。 对齐之前的表格&#xff1a; 对齐之…

Python:用【Win32】模块,结合Word通配符替换,将Word文档表格的部分内容替换为加粗

目录 一、思路 1.遍历表格&#xff0c;根据需要&#xff0c;如果只设置某一个表格&#xff0c;指定即可&#xff08;具体代码注释有&#xff09; 2.对表格区域查找替换 二、代码 三、执行结果 1.执行前 2.执行后 一、思路 1.遍历表格&#xff0c;根据需要&#xff0c;如…

计算机如何取消左缩进,Word中怎么去掉表格的缩进

回答&#xff1a; 1.打开要调整行高的Word文档&#xff0c;如下&#xff1a; 2.从上图中看出&#xff0c;由于表格数据较多&#xff0c;内容已经排到第二页了&#xff01;而想只打印一张就将表格所有内容包括。可以这么做&#xff0c;具体如下&#xff1a; 翻到最前面&#xff…

POI Word表格删除行removeRow()

1 pom.xml(Maven依赖文件) <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.17</version></dependency><dependency><groupId>org.apache.poi</groupId><artifac…

SpringBoot使用Word导出表格

有这样的需要&#xff0c;客户需要把表单信息导出&#xff0c;上级签字&#xff0c;这个涉及多行记录&#xff0c;需要导出word表格 找了很多方法&#xff0c;没有实现&#xff0c;现在将实现的方法分享出来 只有两个工具类&#xff0c;自带导出测试方法&#xff0c;根据自己…