1.模板采用word 域方式定制模板
字段:插入 域名:邮件合并 域代码 MERGEFIELD buildUnit
列表:插入 域名 :邮件合并
头: MERGEFIELD TableStart:PrjDatasuppersFileinfo
中间字段 MERGEFIELD xuhao
尾: MERGEFIELD TableEnd:PrjDatasuppersFileinfo
模板效果
模板中的域名可以删减字段 不影响使用 只要更新域就会回来
话不多说 上代码
前端 jsp
<jsp:attribute name="button">
<a id="" href="javascript:void(0);"
class="easyui-linkbutton"
data-options="iconCls:'',plain:true"
style="display: none; width:100px"
data-bind="visible:true,click: event.exportXSWPZLS">导出</a>
</jsp:attribute>
$(function () {
viewModel.event.exportXSWPZLS=function(){
window.location.href="${contextPath}/inner/PrjProgramRegistration/exportXSWPZLS?prjId="+viewModel.data.form.prjids()+"&auditId="+viewModel.data.form.id();
}
});
写一个导出的按钮 前端 直接调后台的方法 后台方法如下
@SuppressWarnings({ "rawtypes" })
@RequestMapping("/exportXSWPZLS")
public void exportXSWPZLS(@RequestParam Map<String, Object> map, HttpServletRequest request,
HttpServletResponse response) throws GeneralException, IOException, TemplateException {
Map<String, Object> dataMap = new HashMap<String, Object>();
String prjId = (String) map.get("prjId");
PrjBudgets prjBudgets = prjProgramRegistrationService.findOneByHql("from PrjBudgets where id=?", prjId);
Map<String, List<Map>> dataSet = new HashMap<String, List<Map>>();
if (prjBudgets != null) {
String projectName = "xx";
String projectType = "xx";
String totalFun = "xx";
projectName = prjBudgets.getProjectname();
projectType = prjBudgets.getUrgencyDegree();
totalFun = prjBudgets.getTotalFun().toString();
String buildUnit = prjBudgets.getBuildunit();
dataMap.put("projectName", projectName);
dataMap.put("projectType", projectType);
dataMap.put("totalFun", totalFun);
dataMap.put("buildUnit", buildUnit);
String bianhao = "LCST移2020" + getRandomString(4);
dataMap.put("bianhao", bianhao);
PrjBudgetAssistUnits assistUnits = prjBudgetService
.findOneByHql(" from PrjBudgetAssistUnits where prjId=? ", prjId);
dataMap.put("assistUnitsName", assistUnits != null ? assistUnits.getAssistUnitName() : "");
List<Map> PrjDatasuppersFileinfo = prjBudgetService.getFileDataDetail1(map);
dataSet.put("PrjDatasuppersFileinfo", PrjDatasuppersFileinfo);
/** 获取模板文件位置 **/
String fileDirectory = "";
if (StringUtils.isBlank(fileDirectory)) {
fileDirectory = this.getClass().getResource("/").getPath().replace("/classes", "").replace("/WEB-INF",
"") + "resources/templateFiles/aspose/";
}
fileDirectory = URLDecoder.decode(fileDirectory, "utf-8");
java.io.File file = new java.io.File(fileDirectory + "/委托协审资料交接清单.doc");
// 保存路径
String fileName = UUID.randomUUID().toString();
String fileSavePath = ManagerFactory.getSettingManager().getGlobalSettingValue("global_fileSavePath");
// 获取文件时间分割方式
String fileFolderType = ManagerFactory.getSettingManager().getGlobalSettingValue("global_fileFolderType");
String fileSaveFolder = DateUtils.getCurrentTimeStr(fileFolderType);
// 文件全称
String fileAbsolutePath = fileSavePath + "/" + fileSaveFolder + "/";
// 文件存储路径
java.io.File dir = new java.io.File(fileAbsolutePath);
if (!dir.exists()) {
dir.mkdir();
}
String fullSavePath = dir.getPath() + "/" + fileName;
boolean state = AsposeWordUtils.createWord(dataMap, dataSet, file.getPath(), fullSavePath);
if (state) {// 下载
// 设置输出的格式
response.reset();
response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
response.addHeader("content-disposition",
"attachment; filename=" + URLEncoder.encode("委托协审资料交接清单.doc", "utf-8"));
InputStream inStream = new FileInputStream(fullSavePath);// 文件的存放路径
// 循环取出流中的数据
byte[] bytes = new byte[100];
int len;
try {
while ((len = inStream.read(bytes)) > 0)
response.getOutputStream().write(bytes, 0, len);
inStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
后台通用的AsposeWordUtils类如下
package com.thsware.inner.util.Aspose;
import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.MailMerge;
import com.aspose.words.SaveFormat;
import com.aspose.words.net.System.Data.*;
import com.sun.xml.bind.v2.util.QNameMap;
import com.thsware.framework.util.StringUtils;
import com.thsware.framework.web.bean.Result;
import javax.activation.MimetypesFileTypeMap;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
public class AsposeWordUtils {
private static License license = null;
private static InputStream getWordLicense() {
try {
InputStream is = MergeDataSource.class.
getClassLoader().getResourceAsStream("license/wordLicense.xml");
return is;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static boolean getLicense() {
boolean result = true;
try {
InputStream is = getWordLicense();
if (license == null && is != null) {
license = new License();
license.setLicense(getWordLicense());
}
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 获取license
*
* @return
*/
// private static boolean getLicense() {
// boolean result = false;
// try {
// // 凭证
// String licenseStr = "<License>\n" + " <Data>\n" + " <Products>\n"
// + " <Product>Aspose.Total for Java</Product>\n"
// + " <Product>Aspose.Words for Java</Product>\n" + " </Products>\n"
// + " <EditionType>Enterprise</EditionType>\n"
// + " <SubscriptionExpiry>20991231</SubscriptionExpiry>\n"
// + " <LicenseExpiry>20991231</LicenseExpiry>\n"
// + " <SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>\n" + " </Data>\n"
// + " <Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>\n"
// + "</License>";
// InputStream license = new ByteArrayInputStream(licenseStr.getBytes("UTF-8"));
// License asposeLic = new License();
// asposeLic.setLicense(license);
// result = true;
// } catch (Exception e) {
LOG.error("error:", e);
// }
// return result;
// }
public static void printUtil(HttpServletResponse response, String[] name, Object[] value, String modelPath, String wordname) {
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream out = null;
try {
bufferedInputStream = new BufferedInputStream(new MergeDataSource().load(name, value, modelPath));
//设置文件MIME类型
response.setContentType(new MimetypesFileTypeMap().getContentType(modelPath));
//设置Content-Disposition
response.addHeader("Content-Disposition", "attachment;filename=" + new String(wordname.getBytes("gb2312"), "ISO8859-1"));
response.setContentType("application/octet-stream");
response.setCharacterEncoding("UTF-8");
out = new BufferedOutputStream(response.getOutputStream());
int b;
byte[] bytes = new byte[1024 * 1024];
while ((b = bufferedInputStream.read(bytes, 0, bytes.length)) != -1) {
out.write(bytes, 0, b);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void printUtil(HttpServletResponse response, String[] name, String[] value, String modelPath, List<Map<String, Object>> dataList, String wordname) {
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream out = null;
try {
bufferedInputStream = new BufferedInputStream(new MergeDataSource().load(name, value, modelPath, dataList));
//设置文件MIME类型
response.setContentType(new MimetypesFileTypeMap().getContentType(modelPath));
//设置Content-Disposition
response.addHeader("Content-Disposition", "attachment;filename=" + new String(wordname.getBytes("gb2312"), "ISO8859-1"));
response.setContentType("application/octet-stream");
response.setCharacterEncoding("UTF-8");
out = new BufferedOutputStream(response.getOutputStream());
int b;
byte[] bytes = new byte[1024 * 1024];
while ((b = bufferedInputStream.read(bytes, 0, bytes.length)) != -1) {
out.write(bytes, 0, b);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static boolean createWord(Map<String, Object> param, String modelPath, String savePath) {
return createWord(param, new HashMap<>(), modelPath, savePath);
}
public static boolean createWord(Map<String, Object> param,Map<String,List<Map>> dataSet, String modelPath, String savePath) {
if (!getLicense()) {//必须要验证, 否则有水印
return false;
}
try {
File modelFile = new File(modelPath);
if (!modelFile.exists()) {
System.out.println("--模板文件不存在--");
return false;
}
Document doc = new Document(modelPath);
MailMerge merge = doc.getMailMerge();
List<String> names = new LinkedList<>();
List<Object> values = new LinkedList<>();
//获取普通数据参数
if (param != null) {
for (Map.Entry<String, Object> vo : param.entrySet()) {
names.add(vo.getKey());
values.add(vo.getValue());
}
merge.execute(names.stream().toArray(String[]::new), values.toArray());
}
//Map<String,List<Map>> 集合转DataTable
if (dataSet != null) {
DataTable dataTable=null;
DataRow dataRow=null;
List<Map> mapList=null;
for (Map.Entry<String, List<Map>> ds : dataSet.entrySet()) {
dataTable=new DataTable();
dataTable.setTableName(ds.getKey());//与模板里面的TableStart:xx(名称对应)
mapList=ds.getValue();
if (mapList!=null&&mapList.size()>0){
for (int i = 0; i < mapList.size(); i++) {
//初始化DataColumn
if (i==0){
for (Object mp : mapList.get(0).keySet()) {
dataTable.getColumns().add(StringUtils.getString(mp));
}
}
dataRow=dataTable.newRow();
for (DataColumn dc:dataTable.getColumns()) {
if (mapList.get(i).containsKey(dc.getColumnName()))
dataRow.set(dc.getColumnName(), mapList.get(i).get(dc.getColumnName()));
}
dataTable.getRows().add(dataRow);
}
}
//
merge.executeWithRegions(dataTable);
}
}
doc.save(savePath, SaveFormat.DOCX);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public static String createWord(String names[], String values, List<Map> mapList, String modelPath, String savePath) {
return savePath;
}
}
额外赠送两个类哈
package com.thsware.inner.util.Aspose;
import com.aspose.words.IMailMergeDataSource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class MapMailMergeDataSource implements IMailMergeDataSource {
private List<Map<String, Object>> dataList;
private int index;
/**
* word模板中的?TableStart:tableName??TableEnd:tableName?对应
*/
private String tableName = null;
/**
* @param dataList 数据集
* @param tableName 与模板中的Name对应
*/
public MapMailMergeDataSource(List<Map<String, Object>> dataList, String tableName) {
this.dataList = dataList;
this.tableName = tableName;
index = -1;
}
/**
* @param data 单个数据集
* @param tableName 与模板中的Name对应
*/
public MapMailMergeDataSource(Map<String, Object> data, String tableName) {
if (this.dataList == null) {
this.dataList = new ArrayList<Map<String, Object>>();
this.dataList.add(data);
}
this.tableName = tableName;
index = -1;
}
/**
* 获取结果集总数
*
* @return
*/
private int getCount() {
return this.dataList.size();
}
@Override
public IMailMergeDataSource getChildDataSource(String arg0)
throws Exception {
return null;
}
@Override
public String getTableName() throws Exception {
return this.tableName;
}
/**
* 实现接口
* 获取当前index指向数据行的数据
* 将数据存入args数组中即可
*
* @return ***返回false则不绑定数据***
*/
@Override
public boolean getValue(String key, Object[] args) throws Exception {
if (index < 0 || index >= this.getCount()) {
return false;
}
if (args != null && args.length > 0) {
args[0] = this.dataList.get(index).get(key);
return true;
} else {
return false;
}
}
/**
* 实现接口
* 判断是否还有下一条记录
*/
@Override
public boolean moveNext() throws Exception {
index += 1;
if (index >= this.getCount()) {
return false;
}
return true;
}
}
package com.thsware.inner.util.Aspose;
import com.aspose.words.*;
import com.thsware.inner.util.OfficeUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
public class MergeDataSource {
private static License license = null;
private InputStream getWordLicense() {
try {
InputStream is = MergeDataSource.class.getClassLoader().getResourceAsStream("license/wordLicense.xml");
return is;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private boolean getLicense() {
boolean result = true;
try {
InputStream is = getWordLicense();
if (license == null && is != null) {
license = new License();
license.setLicense(getWordLicense());
}
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public ByteArrayInputStream load(String[] name, Object[] value, String modelPath) throws Exception {
if (!getLicense()) {
return null;
}
Document doc = new Document(modelPath);
DocumentBuilder builder = new DocumentBuilder(doc);
builder.moveToMergeField("caseCause"); //变量名称
builder.getFont().setName("Wingdings 2"); //字体
builder.getFont().setSize(20);//字体大小
builder.getFont().setItalic(true); //字体是斜体
// builder.write("R"); //代表 方框里有对勾
builder.write("*"); //代表 方框里无对勾
//word里多个特殊符号
builder.moveToMergeField("sendOwner");
builder.getFont().setName("Wingdings 2");
builder.getFont().setSize(20);
builder.write("*");
MailMerge merge = doc.getMailMerge();
merge.execute(name, value);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
doc.save(bos, SaveFormat.DOC);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
return bis;
}
/**
* 这个方法为word 里有循环的表格
* @param name
* @param value
* @param modelPath
* @param dataList
* @return
* @throws Exception
*/
public ByteArrayInputStream load(String[] name, String[] value, String modelPath, List<Map<String, Object>> dataList) throws Exception {
if (!getLicense()) {
return null;
}
Document doc = new Document(modelPath);
MailMerge merge = doc.getMailMerge();
doc.getMailMerge().executeWithRegions(new MapMailMergeDataSource(dataList, "List1"));
doc.getMailMerge().executeWithRegions(new MapMailMergeDataSource(dataList, "List1"));
merge.execute(name, value);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
doc.save(bos,SaveFormat.DOC);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
return bis;
}
}
在src/main/resources文件夹下加一个文件夹叫license 里面放两个xml文件用于去除水印验证用的 文件如下
文件名 cell.xml
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
<Product>Aspose.Words for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>20991231</SubscriptionExpiry>
<LicenseExpiry>20991231</LicenseExpiry>
<SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
</Data>
<Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
</License>
文件名 wordLicense.xml
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
<Product>Aspose.Words for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>20991231</SubscriptionExpiry>
<LicenseExpiry>20991231</LicenseExpiry>
<SerialNumber>23dcc79f-44ec-4a23-be3a-03c1632404e9</SerialNumber>
</Data>
<Signature>0nRuwNEddXwLfXB7pw66G71MS93gW8mNzJ7vuh3Sf4VAEOBfpxtHLCotymv1PoeukxYe31K441Ivq0Pkvx1yZZG4O1KCv3Omdbs7uqzUB4xXHlOub4VsTODzDJ5MWHqlRCB1HHcGjlyT2sVGiovLt0Grvqw5+QXBuinoBY0suX0=</Signature>
</License>
另外最关键的 需要引入aspose-cell-19.2.jar
aspose-words-15.8.0-jdk16.jar
引入这两个jar包才可以使用aspose
引入就不在叙述了 自己可以百度 我简单说一下
先将这两个jar包放在src/main/webapp/WEB-INF/lib 下 然后 sts软件上 右键项目 -build path 然后选 add External Archives 然后选择这两个jar包 确认就引入了 idea 自行百度哈 都差不多
https://download.csdn.net/download/weixin_45447370/18468787 jar包在这 需要自取