使用POI操作Word,实现数据的导出

时间:2021-12-25 06:22:18

  最近在做一个项目,因为项目需求,需要时常将数据导出到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文档模板:

  使用POI操作Word,实现数据的导出

使用POI操作Word,实现数据的导出使用POI操作Word,实现数据的导出