1. 生成 WORD
1.1 maven 依赖
<!-- Word 模板引擎 -->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.10.5</version>
</dependency>
<!-- Aspose Word文档控件 -->
<dependency>
<groupId>com.luhuiguo</groupId>
<artifactId>aspose-words</artifactId>
<version>23.1</version>
</dependency>1.2 Word 工具类
import com.aspose.words.*;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.deepoove.poi.util.PoitlIOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* Word工具类
*
* @author mobingc
* @date 2024-04-18
*/
@SuppressWarnings("unused")
public class WordUtils {
private static final Logger log = LoggerFactory.getLogger(WordUtils.class);
/**
* 生成 Word 输入流
*
* @param templateClassPath Word 模板文件路径
* @param model 需要填充的数据映射模型
* @return Excel 输入流
*/
public static InputStream generate2Input(String templateClassPath, Object model) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = WordUtils.generate(templateClassPath, model);
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
}
/**
* 生成 Word 输入流
*
* @param templateInput Word 模板输入流
* @param model 需要填充的数据映射模型
* @return Excel 输入流
*/
public static InputStream generate2Input(InputStream templateInput, Object model) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = WordUtils.generate(templateInput, model);
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
}
/**
* 生成 Word 输入流
*
* @param templateClassPath Word 模板文件路径
* @param config 配置
* @param model 需要填充的数据映射模型
* @return Excel 输入流
*/
public static InputStream generate2Input(String templateClassPath, Configure config, Object model) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = WordUtils.generate(templateClassPath, config, model);
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
}
/**
* 生成 Word 输入流
*
* @param templateInput Word 模板输入流
* @param config 配置
* @param model 需要填充的数据映射模型
* @return Excel 输入流
*/
public static InputStream generate2Input(InputStream templateInput, Configure config, Object model) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = WordUtils.generate(templateInput, config, model);
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
}
/**
* 生成 Word 字节输出流
*
* @param templateClassPath Word 模板文件路径
* @param model 需要填充的数据映射模型
* @return Word 字节输出流
*/
public static ByteArrayOutputStream generate(String templateClassPath, Object model) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
WordUtils.generate(templateClassPath, byteArrayOutputStream, null, model);
return byteArrayOutputStream;
}
/**
* 生成 Word 字节输出流
*
* @param templateInput Word 模板输入流
* @param model 需要填充的数据映射模型
* @return Word 字节输出流
*/
public static ByteArrayOutputStream generate(InputStream templateInput, Object model) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
WordUtils.generate(templateInput, byteArrayOutputStream, null, model);
return byteArrayOutputStream;
}
/**
* 生成 Word 字节输出流
*
* @param templateClassPath Word 模板文件路径
* @param config 配置
* @param model 需要填充的数据映射模型
* @return Word 字节输出流
*/
public static ByteArrayOutputStream generate(String templateClassPath, Configure config, Object model) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
WordUtils.generate(templateClassPath, byteArrayOutputStream, config, model);
return byteArrayOutputStream;
}
/**
* 生成 Word 字节输出流
*
* @param templateInput Word 模板输入流
* @param model 需要填充的数据映射模型
* @return Word 字节输出流
*/
public static ByteArrayOutputStream generate(InputStream templateInput, Configure config, Object model) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
WordUtils.generate(templateInput, byteArrayOutputStream, config, model);
return byteArrayOutputStream;
}
/**
* 生成 Word
*
* @param templateClassPath Word 模板文件路径
* @param output Word 输出流
* @param model 需要填充的数据映射模型
*/
public static void generate(String templateClassPath, OutputStream output, Object model) throws IOException {
WordUtils.generate(templateClassPath, output, null, model);
}
/**
* 生成 Word
*
* @param templateInput Word 模板输入流
* @param output Word 输出流
* @param model 需要填充的数据映射模型
*/
public static void generate(InputStream templateInput, OutputStream output, Object model) throws IOException {
WordUtils.generate(templateInput, output, null, model);
}
/**
* 生成 Word
*
* @param templateClassPath Word 模板文件路径
* @param output Word 输出流
* @param config 配置
* @param model 需要填充的数据映射模型
*/
public static void generate(String templateClassPath, OutputStream output, Configure config, Object model) throws IOException {
InputStream templateInputStream = WordUtils.class.getClassLoader().getResourceAsStream(templateClassPath);
WordUtils.generate(templateInputStream, output, config, model);
PoitlIOUtils.closeQuietly(templateInputStream);
}
/**
* 生成 Word
*
* @param templateInput Word 模板输入流
* @param output Word 输出流
* @param config 配置
* @param model 需要填充的数据映射模型
*/
public static void generate(InputStream templateInput, OutputStream output, Configure config, Object model) throws IOException {
try (XWPFTemplate template = (config == null) ? XWPFTemplate.compile(templateInput) : XWPFTemplate.compile(templateInput, config)) {
template.render(model).writeAndClose(output);
}
}
/**
* 合并 word
*
* @param inputStreamList word 文件输入流集合
* @param outputStream 输出的 word 文件数据流
*/
public static void appendMerge(List<InputStream> inputStreamList, OutputStream outputStream) throws Exception {
log.info("合并 word 文件...");
long startTime = System.currentTimeMillis();
Document document = new Document();
DocumentBuilder documentBuilder = new DocumentBuilder(document);
for (int i = 0; i < inputStreamList.size(); i++) {
Document sourceDocument = new Document(inputStreamList.get(i));
documentBuilder.moveToDocumentEnd();
documentBuilder.insertDocument(sourceDocument, ImportFormatMode.KEEP_SOURCE_FORMATTING);
log.info("合并 word 文件:{}/{}", i + 1, inputStreamList.size());
}
log.info("合并 word 完成,耗时:{}ms", System.currentTimeMillis() - startTime);
document.save(outputStream, SaveFormat.DOCX);
}
/**
* word 转换为 pdf
*
* @param wordInput word 文件输入流
* @param pdfOutput pdf 文件输出流
*/
public static void wordToPDF(InputStream wordInput, OutputStream pdfOutput) throws Exception {
log.info("开始转换 word 文件为 pdf 文件...");
long startTime = System.currentTimeMillis();
Document wordDoc = new Document(wordInput);
PdfSaveOptions pso = new PdfSaveOptions();
wordDoc.save(pdfOutput, pso);
log.info("转换完成,耗时:{}ms", System.currentTimeMillis() - startTime);
}
/**
* 模板 word 转换为 pdf
*
* @param templateClassPath 模板文件 classpath
* @param pdfOutput 输出的 pdf 数据流
* @param config 配置
* @param model 需要替换的数据映射模型
*/
public static void templateWordToPDF(String templateClassPath, OutputStream pdfOutput, Configure config, Object model) throws Exception {
InputStream inputStream = WordUtils.generate2Input(templateClassPath, config, model);
WordUtils.wordToPDF(inputStream, pdfOutput);
PoitlIOUtils.closeQuietly(inputStream);
}
/**
* 获取列表配置
*
* @return 列表配置
*/
public static Configure getConfigureByList(Object model) throws Exception {
ConfigureBuilder configureBuilder = Configure.builder();
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
if (model instanceof Map) {
Map<?, ?> modelMap = (Map<?, ?>) model;
if (!modelMap.isEmpty()) {
for (Map.Entry<?, ?> entry : modelMap.entrySet()) {
Object value = entry.getValue();
if (!(value instanceof Collection)) {
continue;
}
Collection<?> collection = (Collection<?>) value;
if (!collection.isEmpty() && isBaseTypeCollection(collection)) {
continue;
}
configureBuilder.bind(entry.getKey().toString(), policy);
}
}
} else {
Class<?> clazz = model.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
Class<?> type = field.getType();
if (Collection.class.isAssignableFrom(type)) {
Method method = clazz.getMethod("get" + StringUtils.capitalize(field.getName()));
Collection<?> collection = (Collection<?>) method.invoke(model);
if (collection != null && !collection.isEmpty() && isBaseTypeCollection(collection)) {
continue;
}
configureBuilder.bind(field.getName(), policy);
}
}
}
return configureBuilder.build();
}
/**
* 判断集合类型是否为基础类型
*
* @param collection 集合
*/
private static boolean isBaseTypeCollection(Collection<?> collection) {
Object item = collection.iterator().next();
Class<?> itemClass = item.getClass();
String itemTypeName = itemClass.getTypeName();
return itemTypeName.startsWith("java.lang.");
}
}1.3 基本用法
1.3.1 配置模板
标签,以
{{开头,以}}结尾日期:{{date}}列表,在列表表头加上列表数据标签,次行以
[开头,以]结尾表示属性
1.3.2 生成文件
public static void main(String[] args) throws Exception {
// 创建文件获取文件输出流
String rootDir = System.getProperty("user.dir");
File file = new File(rootDir + "/output/test.docx");
if (file.createNewFile()) {
System.out.println("创建文件成功");
}
OutputStream outputStream = new FileOutputStream(file);
// 构造数据
Map<String, Object> data = new HashMap<>();
data.put("date", "2024-07-29");
Map<String, Object> user = new HashMap<>();
user.put("name", "张三");
user.put("sex", "男");
user.put("age", 20);
data.put("users", Collections.singletonList(user));
// 获取列表配置(若数据中不包含列表可省略)
Configure config = WordUtils.getConfigureByList(data);
// 模板路径(resource目录下)
String templateClassPath = "template/测试.docx";
// 生成 word
WordUtils.generate(templateClassPath, outputStream, config, data);
// 多个 Word 合并
//List<InputStream> list = new ArrayList<>();
//WordUtils.appendMerge(list, outputStream);
}2. 生成 PDF
通过生成 Word 的方法生成 Word
将 Word 转化为 pdf
public static void main(String[] args) throws Exception {
// 创建文件获取文件输出流
String rootDir = System.getProperty("user.dir");
File file = new File(rootDir + "/output/test.pdf");
if (file.createNewFile()) {
System.out.println("创建文件成功");
}
OutputStream outputStream = new FileOutputStream(file);
// 构造数据
Map<String, Object> data = new HashMap<>();
data.put("date", "2024-07-29");
Map<String, Object> user = new HashMap<>();
user.put("name", "张三");
user.put("sex", "男");
user.put("age", 20);
data.put("users", Collections.singletonList(user));
// 获取列表配置(若数据中不包含列表可省略)
Configure config = WordUtils.getConfigureByList(data);
// 生成 word 并转化为 pdf
InputStream inputStream = WordUtils.generate2Input("template/测试.docx", config, data);
WordUtils.wordToPDF(inputStream, outputStream);
}3. 生成 EXCEL
3.1 maven 依赖
<!-- EasyExcel 工具 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.3</version>
</dependency>
<!-- Aspose Excel表格控件 -->
<dependency>
<groupId>com.luhuiguo</groupId>
<artifactId>aspose-cells</artifactId>
<version>23.1</version>
</dependency>3.2 Excel 工具类
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.aspose.cells.*;
import com.deepoove.poi.util.PoitlIOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Excel 工具类
*
* @author mobingc
* @date 2024-04-18
*/
@SuppressWarnings("unused")
public class ExcelUtils {
private static final Logger log = LoggerFactory.getLogger(ExcelUtils.class);
/**
* 生成 Excel 输入流
*
* @param templateClassPath Excel 模板文件路径
* @param data Excel 模板填充数据
* @return Excel 输入流
*/
public static InputStream generate2Input(String templateClassPath, Map<String, Object> data) {
ByteArrayOutputStream byteArrayOutputStream = ExcelUtils.generate(templateClassPath, data);
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
}
/**
* 生成 Excel 输入流
*
* @param templateInput Excel 模板输入流
* @param data Excel 模板填充数据
* @return Excel 输入流
*/
public static InputStream generate2Input(InputStream templateInput, Map<String, Object> data) {
ByteArrayOutputStream byteArrayOutputStream = ExcelUtils.generate(templateInput, data);
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
}
/**
* 生成 Excel 字节输出流
*
* @param templateClassPath Excel 模板文件路径
* @param data Excel 模板填充数据
* @return Excel 字节输出流
*/
public static ByteArrayOutputStream generate(String templateClassPath, Map<String, Object> data) {
InputStream templateInputStream = ExcelUtils.class.getClassLoader().getResourceAsStream(templateClassPath);
ByteArrayOutputStream byteArrayOutputStream = generate(templateInputStream, data);
PoitlIOUtils.closeQuietly(templateInputStream);
return byteArrayOutputStream;
}
/**
* 生成 Excel 字节输出流
*
* @param templateInput Excel 模板输入流
* @param data Excel 模板填充数据
* @return Excel 字节输出流
*/
public static ByteArrayOutputStream generate(InputStream templateInput, Map<String, Object> data) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ExcelUtils.generate(templateInput, byteArrayOutputStream, data);
return byteArrayOutputStream;
}
/**
* 生成 Excel
*
* @param templateClassPath Excel 模板文件路径
* @param output Excel 输出流
* @param data Excel 模板填充数据
*/
public static void generate(String templateClassPath, OutputStream output, Map<String, Object> data) {
InputStream templateInputStream = ExcelUtils.class.getClassLoader().getResourceAsStream(templateClassPath);
ExcelUtils.generate(templateInputStream, output, data);
PoitlIOUtils.closeQuietly(templateInputStream);
}
/**
* 生成 Excel
*
* @param templateInput Excel 模板输入流
* @param output Excel 输出流
* @param data Excel 模板填充数据
*/
public static void generate(InputStream templateInput, OutputStream output, Map<String, Object> data) {
try (ExcelWriter excelWriter = EasyExcel
.write(output)
.withTemplate(templateInput)
.build()) {
log.info("生成 excel 文件...");
long startTime = System.currentTimeMillis();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
Map<String, Object> baseData = new HashMap<>();
for (Map.Entry<String, Object> entry : data.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value instanceof List) {
excelWriter.fill(new FillWrapper(key, (List<?>) value), writeSheet);
continue;
}
baseData.put(key, value);
}
excelWriter.fill(baseData, writeSheet);
excelWriter.finish();
log.info("生成 excel 完成,耗时:{}ms", System.currentTimeMillis() - startTime);
}
}
/**
* 合并 Excel
*
* @param inputList Excel 输入流列表
* @param output Excel 输出流
*/
public static void merge(List<InputStream> inputList, OutputStream output) throws Exception {
log.info("合并 excel 文件...");
long startTime = System.currentTimeMillis();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
Workbook workbook = new Workbook(inputList.get(0));
Worksheet workSheet = workbook.getWorksheets().get(0);
Cells workSheetCells = workSheet.getCells();
int totalRowCount = workSheetCells.getMaxDisplayRange().getRowCount();
for (int i = 1; i < inputList.size(); ++i) {
Workbook tmpWorkbook = new Workbook(inputList.get(i));
Worksheet tmpSheet = tmpWorkbook.getWorksheets().get(0);
Range sourceRange = tmpSheet.getCells().getMaxDisplayRange();
int sourceFirstRow = sourceRange.getFirstRow() + totalRowCount;
int sourceFirstColumn = sourceRange.getFirstColumn();
int sourceTotalRows = sourceRange.getRowCount();
int sourceTotalColumns = sourceRange.getColumnCount();
Range destRange = workSheetCells.createRange(sourceFirstRow, sourceFirstColumn, sourceTotalRows, sourceTotalColumns);
destRange.copy(sourceRange);
totalRowCount += sourceRange.getRowCount();
log.info("合并 excel 文件:{}/{}", i + 1, inputList.size());
}
log.info("合并 excel 完成,耗时:{}ms", System.currentTimeMillis() - startTime);
workbook.save(output, new XlsSaveOptions(SaveFormat.XLSX));
}
}3.3 基本用法
3.3.1 配置模板
标签,以
{开头,以}结尾日期:{date}列表,以
{开头, 以}结尾,中间为列表名.+属性名更多:https://easyexcel.opensource.alibaba.com/docs/current/quickstart/fill
3.3.2 生成文件
public static void main(String[] args) throws Exception {
// 创建文件获取文件输出流
String rootDir = System.getProperty("user.dir");
File file = new File(rootDir + "/output/test.xlsx");
if (file.createNewFile()) {
System.out.println("创建文件成功");
}
OutputStream outputStream = new FileOutputStream(file);
// 构造数据
Map<String, Object> data = new HashMap<>();
data.put("date", "2024-07-29");
Map<String, Object> user = new HashMap<>();
user.put("name", "张三");
user.put("sex", "男");
user.put("age", 20);
data.put("users", Collections.singletonList(user));
// 模板路径(resource目录下)
String templateClassPath = "template/测试.xlsx";
// 生成 excel
ExcelUtils.generate(templateClassPath, outputStream, data);
// 多个 Excel 合并
//List<InputStream> list = new ArrayList<>();
//ExcelUtils.merge(list, outputStream);
}