日常開發(fā)工作中,我們時常會有一些管理系統(tǒng)相關(guān)的需求,例如在做一些窗口柜臺效率提升的項目時,就時常會有需求在線上通過表單的形式填寫,直接生成已填寫好的合同、文件、表格等。
今天我們主要來描述一下,通過java如何實現(xiàn)這種方式?
1、首先,我們java項目無論是javaweb還是springboot,抑或是springCloud項目,我們都必須在業(yè)務(wù)實現(xiàn)的模塊引入對應(yīng)的jar包
<!-- poi-tl模板填充工具 -->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.2</version>
</dependency>
2、其次,我們需要調(diào)整項目的poi的版本,調(diào)整到與poi-tl剛好適合的版本
比如:是滿足要求的。
<poi.version>5.2.5</poi.version>
3、我們將需要填充的文件放置到項目可以讀取到的路徑下:
這里我們?yōu)榱朔奖阊菔揪椭苯訉⑽谋痉胖迷陧椖康膔esource路徑之下了:

76ae2f21-9981-4630-963e-2eccf532ebcd.png
4、我們打開該文件看一下:

8decbd95-164f-4a70-bb35-071fc0ba9813.png
紅色框住的部分是一個Excel的表格,可以按照自己書寫內(nèi)容的多少進行增加減少。
5、編寫接口代碼:
此處為了方便大家清晰的使用,我將整個Controller復(fù)制過來了:
@RestController
@RequestMapping("/files")
public class FilesController {
private static final Logger log = LoggerFactory.getLogger(FilesController.class);
@PostMapping("/filing")
public void downloadWordTemplateFillData(HttpServletResponse response, @RequestBody ParamEntity entity) throws Exception {
if (null == entity) {
throw new ServiceException("數(shù)據(jù)不能不能為空!");
}
if (StringUtils.isEmpty(entity.getFileType())) {
throw new ServiceException("名稱類型不能為空!");
}
String parentPath = System.getProperty("user.dir") + File.separator + "temp" + File.separator;
File file = new File(parentPath);
if (!file.exists()) {
file.mkdirs();
}
// 暫放于此
String outPath = "";
String fileName = "";
if (entity.getFileType().equals("excel")){
outPath = parentPath + "templateNew" + ".xlsx";
}else{
outPath = parentPath + "templateNew" + ".docx";
}
File excelFile = new File(outPath);
if (excelFile.exists()) {
excelFile.delete();
}
FileInputStream in = null;
OutputStream outs = null;
Map<String, Object> sourceTextMap = (Map<String, Object>) entity.getEntity();
try {
if (entity.getFileType().equals("word")){
Map<String, Object> templateData = new HashMap<String, Object>() {{
put("dept", null == sourceTextMap.get("dept") ? "" : sourceTextMap.get("dept").toString());
put("name", null == sourceTextMap.get("name") ? "" : sourceTextMap.get("name").toString());
put("startTime", null == sourceTextMap.get("startTime") ? "" : sourceTextMap.get("startTime").toString());
put("endTime", null == sourceTextMap.get("endTime") ? "" : sourceTextMap.get("endTime").toString());
put("a1", new HashMap<String, Object>() {{
put("one", null == sourceTextMap.get("one") ? "" : sourceTextMap.get("one").toString());
put("two", null == sourceTextMap.get("two") ? "" : sourceTextMap.get("two").toString());
put("three", null == sourceTextMap.get("three") ? "" : sourceTextMap.get("three").toString());
put("four", null == sourceTextMap.get("four") ? "" : sourceTextMap.get("four").toString());
put("five", null == sourceTextMap.get("five") ? "" : sourceTextMap.get("five").toString());
}});
}};
// 讀取模板文件
try (InputStream templateIn = FilesController.class.getResourceAsStream("/template/template.docx")) {
// 生成模板文件
assert templateIn != null;
XWPFTemplate template = XWPFTemplate.compile(templateIn).render(templateData);
template.writeAndClose(Files.newOutputStream(Paths.get(outPath)));
// 這個目的是:生成文件之后調(diào)用 cmd 打開本地文件,實際生產(chǎn)不需要該操作
Runtime.getRuntime().exec(String.format("cmd /c %s", outPath));
} catch (IOException e) {
log.error("導(dǎo)出異常:" + e);
}
}
}
catch (Exception e){
log.error("導(dǎo)出異常:" + e);
} finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(outs);
}
}
}
6、構(gòu)造填充部分的實體類:
public class ParamEntity {
private Object entity;
private String fileType;
public Object getEntity() {
return entity;
}
public void setEntity(Object entity) {
this.entity = entity;
}
public String getFileType() {
return fileType;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
@Override
public String toString() {
return "ParamEntity{" +
"entity=" + entity +
", fileType='" + fileType + '\'' +
'}';
}
}
7、核心代碼講解:寫入操作:
FileInputStream in = null;
OutputStream outs = null;
Map<String, Object> sourceTextMap = (Map<String, Object>) entity.getEntity();
try {
if (entity.getFileType().equals("word")){
Map<String, Object> templateData = new HashMap<String, Object>() {{
put("dept", null == sourceTextMap.get("dept") ? "" : sourceTextMap.get("dept").toString());
put("name", null == sourceTextMap.get("name") ? "" : sourceTextMap.get("name").toString());
put("startTime", null == sourceTextMap.get("startTime") ? "" : sourceTextMap.get("startTime").toString());
put("endTime", null == sourceTextMap.get("endTime") ? "" : sourceTextMap.get("endTime").toString());
put("a1", new HashMap<String, Object>() {{
put("one", null == sourceTextMap.get("one") ? "" : sourceTextMap.get("one").toString());
put("two", null == sourceTextMap.get("two") ? "" : sourceTextMap.get("two").toString());
put("three", null == sourceTextMap.get("three") ? "" : sourceTextMap.get("three").toString());
put("four", null == sourceTextMap.get("four") ? "" : sourceTextMap.get("four").toString());
put("five", null == sourceTextMap.get("five") ? "" : sourceTextMap.get("five").toString());
}});
}};
// 讀取模板文件
try (InputStream templateIn = FilesController.class.getResourceAsStream("/template/template.docx")) {
// 生成模板文件
assert templateIn != null;
XWPFTemplate template = XWPFTemplate.compile(templateIn).render(templateData);
template.writeAndClose(Files.newOutputStream(Paths.get(outPath)));
// 這個目的是:生成文件之后調(diào)用 cmd 打開本地文件,實際生產(chǎn)不需要該操作
Runtime.getRuntime().exec(String.format("cmd /c %s", outPath));
} catch (IOException e) {
log.error("導(dǎo)出異常:" + e);
}
}
}
8、測試效果:apiPost測試:

b210d10d-2008-48de-82a0-224fa2a964d6.png
根據(jù)測試得到的文件如圖:

c3da32cf-3492-401d-b54e-43aaf4baf667.png
這樣我們基本就完成了通過java代碼實現(xiàn)文本文件的填充了,當(dāng)然Excel及其他可支持的文件形式也是如此。