最近在做一个项目,因为项目需求,需要时常将数据导出到Word文档,经过查阅一些资料,和一些自己的实践,终于实现了。为了以后使用方便,所以将这个帮助类记录下来。在使用之前需要导入相关POI的jar包,下载地址为(http://poi.apache.org/download.html)。
package cn.sh.bzt.kwj.uitl;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.imageio.stream.FileImageInputStream;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
/**
* 使用POI操作word工具类
*
* @author hy
*
*/
public class WordUtil {
/**
* 根据指定的参数值、模板,生成 word 文档
*
* @param param
* 需要替换的变量
* @param template
* 模板
*/
public static CustomXWPFDocument generateWord(Map<String, Object> param, String template) {
CustomXWPFDocument doc = null;
try {
OPCPackage pack = POIXMLDocument.openPackage(template);
doc = new CustomXWPFDocument(pack);
if (param != null && param.size() > 0) {
// 处理段落
List<XWPFParagraph> paragraphList = doc.getParagraphs();
processParagraphs(paragraphList, param, doc);
// 处理表格
Iterator<XWPFTable> it = doc.getTablesIterator();
while (it.hasNext()) {
XWPFTable table = it.next();
List<XWPFTableRow> rows = table.getRows();
for (XWPFTableRow row : rows) {
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
System.out.println(cell.getText());
List<XWPFParagraph> paragraphListTable = cell.getParagraphs();
processParagraphs(paragraphListTable, param, doc);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return doc;
}
public static CustomXWPFDocument readWord(Map<String, Object> param, String template) {
CustomXWPFDocument doc = null;
try {
OPCPackage pack = POIXMLDocument.openPackage(template);
doc = new CustomXWPFDocument(pack);
// 处理段落
List<XWPFParagraph> paragraphList = doc.getParagraphs();
processParagraphs(paragraphList, param, doc);
// 处理表格
Iterator<XWPFTable> it = doc.getTablesIterator();
while (it.hasNext()) {
XWPFTable table = it.next();
List<XWPFTableRow> rows = table.getRows();
System.out.println("现在表格的长度是1:"+rows.size());
for (int i=rows.size()-1;i>=0;i--) {
System.out.println("现在表格的长度是2:"+rows.size());
XWPFTableRow row =rows.get(i);
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
System.out.println(i+":"+cell.getText()+";");
if("".equals(cell.getText().trim())){
table.removeRow(i);
// row.getTable().removeRow(i);
}/*else{
System.out.println(cell.getText());
List<XWPFParagraph> paragraphListTable = cell.getParagraphs();
processParagraphs(paragraphListTable, param, doc);
}*/
}
}
System.out.println("现在表格的长度是:"+rows.size());
/* for (int i=0;i<rows.size();i++) {
XWPFTableRow row =rows.get(i);
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
System.out.println(cell.getText()+";");
if("".equals(cell.getText().trim())||cell.getText().trim()==null){
table.removeRow(i);
row.getTable().removeRow(i);
}
}
}
System.out.println("现在表格的长度是:"+rows.size());
for (int i=0;i<rows.size();i++) {
XWPFTableRow row =rows.get(i);
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
System.out.println(cell.getText()+";");
if("".equals(cell.getText().trim())||cell.getText().trim()==null){
table.removeRow(i);
row.getTable().removeRow(i);
}
}
}
System.out.println("现在表格的长度是:"+rows.size());
for (int i=0;i<rows.size();i++) {
XWPFTableRow row =rows.get(i);
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
System.out.println(cell.getText()+";");
if("".equals(cell.getText().trim())||cell.getText().trim()==null){
table.removeRow(i);
row.getTable().removeRow(i);
}
}
}
System.out.println("现在表格的长度是:"+rows.size());*/
}
} catch (Exception e) {
e.printStackTrace();
}
return doc;
}
/**
* 处理段落
*
* @param paragraphList
*/
public static void processParagraphs(List<XWPFParagraph> paragraphList, Map<String, Object> param, CustomXWPFDocument doc) {
if (paragraphList != null && paragraphList.size() > 0) {
for (XWPFParagraph paragraph : paragraphList) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
String text = run.getText(0);
if (text != null) {
boolean isSetText = false;
for (Entry<String, Object> entry : param.entrySet()) {
String key = entry.getKey();
if (text.indexOf(key) != -1) {
isSetText = true;
Object value = entry.getValue();
if (value instanceof String) {// 文本替换
text = text.replace(key, value.toString());
} else if (value instanceof Map) {// 图片替换
text = text.replace(key, "");
Map pic = (Map) value;
int width = Integer.parseInt(pic.get("width").toString());
int height = Integer.parseInt(pic.get("height").toString());
int picType = getPictureType(pic.get("type").toString());
byte[] byteArray = (byte[]) pic.get("content");
ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray);
try {
String ind = doc.addPictureData(byteInputStream, picType);
doc.createPicture(doc.getAllPictures().size()-1, width, height, paragraph);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
if (isSetText) {
run.setText(text, 0);
}
}
}
}
}
}
/**
* 根据图片类型,取得对应的图片类型代码
*
* @param picType
* @return int
*/
public static int getPictureType(String picType) {
int res = Document.PICTURE_TYPE_PICT;
if (picType != null) {
if (picType.equalsIgnoreCase("png")) {
res = Document.PICTURE_TYPE_PNG;
} else if (picType.equalsIgnoreCase("dib")) {
res = Document.PICTURE_TYPE_DIB;
} else if (picType.equalsIgnoreCase("emf")) {
res = Document.PICTURE_TYPE_EMF;
} else if (picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")) {
res = Document.PICTURE_TYPE_JPEG;
} else if (picType.equalsIgnoreCase("wmf")) {
res = Document.PICTURE_TYPE_WMF;
}
}
return res;
}
/**
* 将输入流中的数据写入字节数组
*
* @param in
* @return
*/
public static byte[] inputStream2ByteArray(InputStream in, boolean isClose) {
byte[] byteArray = null;
try {
int total = in.available();
byteArray = new byte[total];
in.read(byteArray);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (isClose) {
try {
in.close();
} catch (Exception e2) {
System.out.println("关闭流失败");
}
}
}
return byteArray;
}
/**实例*/
public static void main(String[] args) throws Exception {
Map<String, Object> param = new HashMap<String, Object>();
Map<String, Object> header = new HashMap<String, Object>();
header.put("width", 100);
header.put("height", 150);
header.put("type", "gif");
header.put("content", WordUtil.inputStream2ByteArray(new FileInputStream("E://小狗子.png"), true));
param.put("${img}", header);
CustomXWPFDocument doc = WordUtil.generateWord(param, "E://2.docx");
FileOutputStream fopts = new FileOutputStream("E://1.docx");
doc.write(fopts);
fopts.close();
}
public static byte[] image2byte(String path){
byte[] data = null;
FileImageInputStream input = null;
try {
input = new FileImageInputStream(new File(path));
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int numBytesRead = 0;
while ((numBytesRead = input.read(buf)) != -1) {
output.write(buf, 0, numBytesRead);
}
data = output.toByteArray();
output.close();
input.close();
}
catch (FileNotFoundException ex1) {
ex1.printStackTrace();
}
catch (IOException ex1) {
ex1.printStackTrace();
}
return data;
}
}
/*================================================================================*/
这部分为如何实现将数据存放在word文档中。
/**
* 导出数据为docx文档
* @return
* @throws IOException
* @throws KwjException
*/
public String exportToDocx(){
System.out.println("进入exportToDocx.action------------->");
try {
list = new ArrayList<Object>();
TUser user = (TUser) request.getSession().getAttribute("USER_IN_SESSION");
request.setAttribute("userLoginName", user.getUserLoginName());
TOrgnization toi=new TOrgnization();
Integer orgId=user.getTOrgnization().getOrgId();
if(orgId!=null){
toi=userService.getAllOrgList(orgId);
}
String orgName = toi.getOrgName();
request.setAttribute("orgName", orgName);
String CurrentClassFilePath =this.getClass().getResource("").getPath();
int lastpath=CurrentClassFilePath.lastIndexOf("WEB-INF/classes/");
String basePath=CurrentClassFilePath.substring(0,lastpath);
String templatePath =basePath +"zs/上海局口岸卫生监督信息月报表模板.docx";
System.out.println(basePath);
String wjj=basePath+"zs/统计报表/";
File cmfile=new File(wjj);
if(!cmfile.exists()){
cmfile.mkdirs();
}
String endPath=wjj+"上海局口岸卫生监督信息月报表.docx";
/****************************************解析*.docx模版并替换*********************************************/
Map<String, Object> params = new HashMap<String, Object>();
List tList = (List) request.getSession().getAttribute("ALL_Total_LIST");
// System.out.println(tList.get(0));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");//设置日期格式
String tbDate = sdf.format(new Date());//填报日期
params.put("${X}", orgName);//直属局
params.put("${Z}", tbDate); //填报日期
Integer airFoodNum = portFoodSupervisonService.getOrgCount("1");//计算航食配餐企业数
Integer airFoodJgTime = portFoodSupervisonService.getJgTimes("1");//计算航食配餐企业监管次数
params.put("${G}", airFoodNum.toString());
params.put("${H}", airFoodJgTime.toString());
Integer resFoodNum = portFoodSupervisonService.getOrgCount("3");//计算餐饮单位数
Integer resFoodJgTime = portFoodSupervisonService.getJgTimes("3");//计算餐饮单位监管次数
params.put("${I}", resFoodNum.toString());
params.put("${J}", resFoodJgTime.toString());
Integer supTypeCount1 = portFoodSupervisonService.getSupTypeCount();//食品投诉事件次数
System.out.println("食品投诉事件次数(1)-------->"+supTypeCount1);
if(supTypeCount1!=0||supTypeCount1!=null){
params.put("${R}", "有");
}else{
params.put("${R}", "无");
}
String filingdate1 = (String) request.getSession().getAttribute("stDate");
String filingdate2 = (String) request.getSession().getAttribute("endDate");
String items = (String) request.getSession().getAttribute("items");
SimpleDateFormat sdf2 = new SimpleDateFormat("yy/MM");
Date d1 = new SimpleDateFormat("yyyy-MM-dd").parse(filingdate1);
Date d2 = new SimpleDateFormat("yyyy-MM-dd").parse(filingdate2);
String date1 = sdf2.format(d1);
String date2 = sdf2.format(d2);
params.put("${Y}", date1+"~"+date2);
request.setAttribute("stDate", filingdate1);
request.setAttribute("endDate", filingdate2);
request.setAttribute("items", items);
quickCheck.setFilingdate1(filingdate1);
quickCheck.setFilingdate2(filingdate2);
quickCheck.setItem(items);
//快速检测情况
int j=1;
for(int i=0;i<=item.length-1;i++){
Integer itemcount1 = portFoodSupervisonService.getSampleCount(item[i],quickCheck);
Integer itemcount2 = portFoodSupervisonService.getItemUnqualified(item[i],quickCheck);
if(itemcount1==null||itemcount1==0){
params.put("${A"+j+"}", "0");
}else{
params.put("${A"+j+"}", itemcount1.toString());
}
if(itemcount2==null||itemcount2==0){
params.put("${B"+j+"}", "0");
}else{
params.put("${B"+j+"}", itemcount2.toString());
}
j++;
}
list = (List) request.getAttribute("ALL_Total_LIST");
request.setAttribute("ALL_Total_LIST", list);
Integer sampleColNum = (Integer) request.getSession().getAttribute("sampleColNum");//样品总数
Integer unqualified = (Integer) request.getSession().getAttribute("unqualified");//不合格样品总数
params.put("${E}", sampleColNum.toString());
params.put("${F}", unqualified.toString());
String userName = user.getUserName();//填报人
String userMobile = user.getUserTelephone();//填报人手机
params.put("${T}", userName);
if(userMobile==null||"".equals(userMobile)){
params.put("${U}", "");
}else{
params.put("${U}", userMobile);
}
//调用工具类
CustomXWPFDocument doc = WordUtil.generateWord(params,templatePath);
FileOutputStream fopts = new FileOutputStream(endPath);
doc.write(fopts);
fopts.close();
return SUCCESS;
} catch (Exception e) {
e.printStackTrace();
return ERROR;
}
}
上面对快速检测处理时,存放数据有技巧,有时候客户给的模板是要求不变的,而我们获取的数据确可能是变化了,所以在定义word模板时,需要有技巧。
/*=========================================================================*/
下面为word文档模板: