`

导出数据到Excel表中--用Apache的POI实现简单封装

阅读更多
使用Apache的POI 实现对数据导出到EXCEL表中进行了一个简单的封装,可以通过XML配置文件配置你想导出的信息,以下是这个小工具的代码:

DataImportAndExportTool.java   代码:


package nhu.drugstore.uitl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class DataImportAndExportTool
{
private class Entiy
{
  String name;
  String text;
  String type;
}
private static DataImportAndExportTool tool=new DataImportAndExportTool();
/**
  * 空的构造方法
  */
private DataImportAndExportTool()
{
  //do nothing
}
/**
  * 
  * 以一个数组方式创建一个标题行 
  * @param row
  * @param title
  */
private void createTitleRow(HSSFWorkbook workbook,HSSFRow row,String[] title)
{
  int length=title.length;
  HSSFCellStyle style=workbook.createCellStyle();
  HSSFFont font=workbook.createFont();
  font.setColor(HSSFColor.BLUE.index);
  font.setFontHeightInPoints((short)14);
  font.setBoldweight((short)24);
  style.setFont(font);
  style.setFillBackgroundColor(HSSFColor.YELLOW.index);
  for(int i=0;i<length;i++)
  {
   HSSFCell cell=row.createCell(i);
   cell.setCellValue(title);
   cell.setCellStyle(style);
  }
}
/**
  * 解析XML文件
  * @param className
  * @return
  * @throws ParserConfigurationException 
  * @throws IOException 
  * @throws SAXException 
  */
private List<Entiy> parseXML(String className) throws Exception
{
  List<Entiy> list=new ArrayList<Entiy>();
  Document doc=DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(this.getClass().getClassLoader().getResourceAsStream("/"+className+".xml"));
  NodeList nodeList=doc.getElementsByTagName("property");
  Element element;
  for(int i=0;i<nodeList.getLength();i++)
  {
   element=(Element)nodeList.item(i);
   Entiy e=new Entiy();
   e.name=element.getAttribute("name");
   e.text=element.getAttribute("text");
   e.type=element.getAttribute("type");
   list.add(e);
  }
  return list;
}
/**
  * 创建工作表的标题行
  * @param workbook
  * @param row
  * @param list
  */
private  void createTitleRow(HSSFWorkbook workbook,HSSFRow row,List<Entiy> list)
{
  HSSFCellStyle style=workbook.createCellStyle();
  HSSFFont font=workbook.createFont();
  font.setColor(HSSFColor.BLUE.index);
  font.setFontHeightInPoints((short)14);
  font.setBoldweight((short)24);
  style.setFont(font);
  style.setFillBackgroundColor(HSSFColor.YELLOW.index);
  int i=0;
  for(Entiy e:list)
  {
   HSSFCell cell=row.createCell(i++);
   cell.setCellValue(e.text);
   cell.setCellStyle(style);
  }
}
/**
  * 从一个列表中创建出一个工作空间
  * @param list
  * @param sheetName
  * @return
  * @throws Exception
  */
public static HSSFWorkbook ExportToExcel(List list,String sheetName) throws Exception
{
  Class c=list.get(0).getClass();
  String className=c.getSimpleName();
  //解析XML文件中的信息到一个列表中
  List<Entiy> entiyList=tool.parseXML(className);
  //创建一个空工作空间
  HSSFWorkbook workbook=new HSSFWorkbook();
  //创建一个表
  HSSFSheet sheet=workbook.createSheet(sheetName);
  //创建标题行
  HSSFRow titleRow=sheet.createRow(0);
  tool.createTitleRow(workbook, titleRow,entiyList);
  /*
   * 创建表中的信息
   */
  int rowNum=1;
  for(int i=0;i<list.size();i++)
  {
   HSSFRow row=sheet.createRow(rowNum++);
   int colNum=0;
   for(Entiy e:entiyList)
   {
    if(e.type.endsWith("String"))
    {
     row.createCell(colNum++).setCellValue((String)MethodTool.excuteMethod(list.get(i),MethodTool.returnGetMethodName(e.name)));
    }
    else if("int".equals(e.type)||"java.lang.Integer".equals(e.type))
    {
     row.createCell(colNum++).setCellValue((Integer)MethodTool.excuteMethod(list.get(i),MethodTool.returnGetMethodName(e.name)));
    }
    else if("double".equals(e.type)||"java.lang.Double".equals(e.type))
    {
     row.createCell(colNum++).setCellValue((Double)MethodTool.excuteMethod(list.get(i),MethodTool.returnGetMethodName(e.name)));
    }
    else if(e.type.endsWith("Date"))
    {
     row.createCell(colNum++).setCellValue((Date)MethodTool.excuteMethod(list.get(i),MethodTool.returnGetMethodName(e.name)));
    }
    else if(e.type.endsWith("Calendar"))
    {
     row.createCell(colNum++).setCellValue((Calendar)MethodTool.excuteMethod(list.get(i),MethodTool.returnGetMethodName(e.name)));
    }
    else if("boolean".equals(e.type)||"java.lang.Boolean".equals(e.type))
    {
     row.createCell(colNum++).setCellValue((Double)MethodTool.excuteMethod(list.get(i),MethodTool.returnGetMethodName(e.name)));
    }
    else
    {
     throw new Exception("数据类型错误");
    }
   }
  }
  return workbook;
}

}


MethodTool.java  代码:

package nhu.drugstore.uitl;
import java.lang.reflect.Method;
/**
* 这是一个用于方法反射的工具类
* 这将运用JDK的反射机制
* @author strive
*
*/
public class MethodTool
{
/**
  * 反转一个有返回值的无参方法
  * @param object
  * @param methodName
  * @return
  * @throws Exception
  */
public static Object excuteMethod(Object object,String methodName) throws Exception
{
  Class c=object.getClass();
  Method m=c.getMethod(methodName);
  return m.invoke(object);
}
/**
  * 反转一个没有返回值的有一个参数的方法
  * @param object
  * @param methodName
  * @param parameter
  * @throws Exception
  */
public static void excuteMethod(Object object,String methodName,Object parameter) throws Exception
{
  Class c=object.getClass();
  Method m=c.getDeclaredMethod(methodName, parameter.getClass());
  m.invoke(object,parameter);
}
/**
  * 执行一个参数为boolean类型的方法
  * @param object
  * @param methodName
  * @param parameter
  * @throws Exception
  */
public static void excuteBoolMethod(Object object,String methodName,boolean parameter) throws Exception
{
  Class c=object.getClass();
  Method m=c.getDeclaredMethod(methodName,boolean.class);
  m.invoke(object,parameter);
}
/**
  * 获得一个属性的set方法名
  * @param property
  * @return
  */
public static String returnSetMethodName(String property)
{
  return "set"+Character.toUpperCase(property.charAt(0))+property.substring(1);
}
/**
  * 获得一个属性的get方法名
  * @param property
  * @return
  */
public static String returnGetMethodName(String property)
{
  return "get"+Character.toUpperCase(property.charAt(0))+property.substring(1);
}
}




现在做一个测试:



下面是一个hibernate 实体映射类


/

package nhu.drugstore.bean;

/**
*  this is a class description a  model of Medicine
*  only some geter and seter method
* @author strive
* @hibernate.class
*/
public class Medicine
{
/**
  * 主键
  * @hibernate.id generator-class="native"
  */
private int id;
/**
  * 药品名称
  * @hibernate.property
  * unique="true"
  */
private String name;
/**
  * 放药药框
  * @hibernate.property
  */
private String ark;
/**
  * 条形码
  * @hibernate.property
  * 
  */
private String barCode;
/**
  * 功效描述
  * @hibernate.property
  */
private String efficacy;
/**
  * 进货价格
  * @hibernate.property
  */
private double buyPrice;
/**
  * 出售价格
  * @hibernate.property
  */
private double sellPrice;
/**
  * 库存量
  * @hibernate.property
  */
private double stockpile;
/**
  * 库存不足提示数量
  * @hibernate.property
  */
private double cueNumber;
/**
  * 打折百分比
  * @hibernate.property
  */
private double rebate;
/**
  * 提成百分比
  * @hibernate.property
  */
private double rakeOff;
/**
  * 拼音简查码
  * @hibernate.property
  */
private String spellShort;
/**
  * 数字简查码
  * @hibernate.property
  */
private String numberShort;
public int getId()
{
  return id;
}
public void setId(int id)
{
  this.id = id;
}
public String getName()
{
  return name;
}
public void setName(String name)
{
  this.name = name;
}
public String getArk()
{
  return ark;
}
public void setArk(String ark)
{
  this.ark = ark;
}
public String getBarCode()
{
  return barCode;
}
public void setBarCode(String barCode)
{
  this.barCode = barCode;
}
public String getEfficacy()
{
  return efficacy;
}
public void setEfficacy(String efficacy)
{
  this.efficacy = efficacy;
}
public double getBuyPrice()
{
  return buyPrice;
}
public void setBuyPrice(double buyPrice)
{
  this.buyPrice = buyPrice;
}
public double getSellPrice()
{
  return sellPrice;
}
public void setSellPrice(double sellPrice)
{
  this.sellPrice = sellPrice;
}
public double getStockpile()
{
  return stockpile;
}
public void setStockpile(double stockpile)
{
  this.stockpile = stockpile;
}
public double getCueNumber()
{
  return cueNumber;
}
public void setCueNumber(double cueNumber)
{
  this.cueNumber = cueNumber;
}
public double getRebate()
{
  return rebate;
}
public void setRebate(double rebate)
{
  this.rebate = rebate;
}
public double getRakeOff()
{
  return rakeOff;
}
public void setRakeOff(double rakeOff)
{
  this.rakeOff = rakeOff;
}
public String getSpellShort()
{
  return spellShort;
}
public void setSpellShort(String spellShort)
{
  this.spellShort = spellShort;
}
public String getNumberShort()
{
  return numberShort;
}
public void setNumberShort(String numberShort)
{
  this.numberShort = numberShort;
}
}



只要在classPath下建一个文件:
里面配置你想导出的字段


Medicine.xml

<?xml version="1.0" encoding="UTF-8"?>
<bean class="nhu.drugstore.bean.Medicine">
<property name="name" text="药品名称" type="String"/>
<property name="ark" text="放药药框" type="String"/>
<property name="barCode" text="条形码" type="String"/>
<property name="buyPrice" text="进货价格" type="double"/>
<property name="stockpile" text="库存量" type="double"/>
<property name="sellPrice" text="出售价格" type="double"/>
<property name="rebate" text="打折百分比" type="double"/>
<property name="efficacy" text="功效描述" type="String"/>
</bean>



就可以导出数据了:

以下是导出数据到EXCEL的应用;
File outputFile=new File("C:/");
OutputStream fOut = new PrintStream(outputFile);
   // 把相应的Excel 工作簿存盘
DataImportAndExportTool.ExportToExcel(medicineDao.getAllMedicine(),"药材信息表").write(fOut);
   fOut.flush();
   // 操作结束,关闭文件
   fOut.close();


这样就可以一个Excel表了
 
分享到:
评论
5 楼 Wuaner 2010-07-14  
<div class="quote_title">ilove2009 写道</div>
<div class="quote_div">
<div class="quote_title">qtalen 写道</div>
<div class="quote_div">
<div class="quote_title">qtalen 写道</div>
<div class="quote_div">
<p>LZ好,你这个挺好用的,不过我在项目搞了一些改造:</p>
<p>首先加了一个annotation:</p>
<pre name="code" class="java">@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Cell {
/**
* 该字段对应的表格头
*/
public String title();
}</pre>
<p> 接着在ExportTool里增加一个方法来解析annotation:</p>
<pre name="code" class="java">/**
* 解析出元数据信息,初始化excel导出
*
* @param className
* @return
* @throws ClassNotFoundException
*/
private List&lt;Entity&gt; parseAnnotation(Class clazz)
throws ClassNotFoundException {
List&lt;Entity&gt; entities = new ArrayList&lt;Entity&gt;();
Field[] fields = clazz.getDeclaredFields();

for (Field field : fields) {
Entity e = new Entity();
boolean hasAnnotation = field.isAnnotationPresent(Cell.class);

if (hasAnnotation) {
Cell annotation = field.getAnnotation(Cell.class);
e.title = annotation.title();
e.type = field.getType().getName();
e.name = field.getName();

entities.add(e);
}
}

return entities;
}</pre>
<p> 其他的变动不大,对于需要导出的值对象,用annotation标注一下就可以了:</p>
<pre name="code" class="java">public class Student {
    @Cell(title = "学号")
    private long serialNumber;
   
    @Cell(title = "姓名")
    private String name;
   
    @Cell(title = "性别")
    private String sexual;
   
    @Cell(title = "分数")
    private Long score;

}
</pre>
 
<p> </p>
<p> </p>
<p> </p>
</div>
<br>就是不知道这么大量的使用反射会不会性能有问题</div>
<p><br>1、把配置写到java里,要是需求改变,是不是重新编译代码</p>
<p>2、to LZ:如果用户对数据格式有要求,不如日期有yyyyMMdd或者yyyy-MM-dd不同需要,好像不能满足。</p>
</div>
<p> </p>
<p> </p>
<p>使用注解的方式确实得重新编译,这点比不上使用xml的方式啊;</p>
<p>日期的格式,为方法多加个日期格式的参数,呵呵。</p>
4 楼 ilove2009 2010-01-04  
<div class="quote_title">qtalen 写道</div>
<div class="quote_div">
<div class="quote_title">qtalen 写道</div>
<div class="quote_div">
<p>LZ好,你这个挺好用的,不过我在项目搞了一些改造:</p>
<p>首先加了一个annotation:</p>
<pre name="code" class="java">@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Cell {
/**
* 该字段对应的表格头
*/
public String title();
}</pre>
<p> 接着在ExportTool里增加一个方法来解析annotation:</p>
<pre name="code" class="java">/**
* 解析出元数据信息,初始化excel导出
*
* @param className
* @return
* @throws ClassNotFoundException
*/
private List&lt;Entity&gt; parseAnnotation(Class clazz)
throws ClassNotFoundException {
List&lt;Entity&gt; entities = new ArrayList&lt;Entity&gt;();
Field[] fields = clazz.getDeclaredFields();

for (Field field : fields) {
Entity e = new Entity();
boolean hasAnnotation = field.isAnnotationPresent(Cell.class);

if (hasAnnotation) {
Cell annotation = field.getAnnotation(Cell.class);
e.title = annotation.title();
e.type = field.getType().getName();
e.name = field.getName();

entities.add(e);
}
}

return entities;
}</pre>
<p> 其他的变动不大,对于需要导出的值对象,用annotation标注一下就可以了:</p>
<pre name="code" class="java">public class Student {
    @Cell(title = "学号")
    private long serialNumber;
   
    @Cell(title = "姓名")
    private String name;
   
    @Cell(title = "性别")
    private String sexual;
   
    @Cell(title = "分数")
    private Long score;

}
</pre>
 
<p> </p>
<p> </p>
<p> </p>
</div>
<br>就是不知道这么大量的使用反射会不会性能有问题</div>
<p><br>1、把配置写到java里,要是需求改变,是不是重新编译代码</p>
<p>2、to LZ:如果用户对数据格式有要求,不如日期有yyyyMMdd或者yyyy-MM-dd不同需要,好像不能满足。</p>
3 楼 qtalen 2010-01-04  
<div class="quote_title">qtalen 写道</div><div class="quote_div"><p>LZ好,你这个挺好用的,不过我在项目搞了一些改造:</p>
<p>首先加了一个annotation:</p>
<pre name="code" class="java">@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Cell {
/**
* 该字段对应的表格头
*/
public String title();
}</pre>
<p> 接着在ExportTool里增加一个方法来解析annotation:</p>
<pre name="code" class="java">/**
* 解析出元数据信息,初始化excel导出
*
* @param className
* @return
* @throws ClassNotFoundException
*/
private List&lt;Entity&gt; parseAnnotation(Class clazz)
throws ClassNotFoundException {
List&lt;Entity&gt; entities = new ArrayList&lt;Entity&gt;();
Field[] fields = clazz.getDeclaredFields();

for (Field field : fields) {
Entity e = new Entity();
boolean hasAnnotation = field.isAnnotationPresent(Cell.class);

if (hasAnnotation) {
Cell annotation = field.getAnnotation(Cell.class);
e.title = annotation.title();
e.type = field.getType().getName();
e.name = field.getName();

entities.add(e);
}
}

return entities;
}</pre>
<p> 其他的变动不大,对于需要导出的值对象,用annotation标注一下就可以了:</p>
<pre name="code" class="java">public class Student {
    @Cell(title = "学号")
    private long serialNumber;
   
    @Cell(title = "姓名")
    private String name;
   
    @Cell(title = "性别")
    private String sexual;
   
    @Cell(title = "分数")
    private Long score;

}
</pre>
 
<p> </p>
<p> </p>
<p> </p></div><br/>就是不知道这么大量的使用反射会不会性能有问题
2 楼 qtalen 2009-12-30  
<p>LZ好,你这个挺好用的,不过我在项目搞了一些改造:</p>
<p>首先加了一个annotation:</p>
<pre name="code" class="java">@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Cell {
/**
* 该字段对应的表格头
*/
public String title();
}</pre>
<p> 接着在ExportTool里增加一个方法来解析annotation:</p>
<pre name="code" class="java">/**
* 解析出元数据信息,初始化excel导出
*
* @param className
* @return
* @throws ClassNotFoundException
*/
private List&lt;Entity&gt; parseAnnotation(Class clazz)
throws ClassNotFoundException {
List&lt;Entity&gt; entities = new ArrayList&lt;Entity&gt;();
Field[] fields = clazz.getDeclaredFields();

for (Field field : fields) {
Entity e = new Entity();
boolean hasAnnotation = field.isAnnotationPresent(Cell.class);

if (hasAnnotation) {
Cell annotation = field.getAnnotation(Cell.class);
e.title = annotation.title();
e.type = field.getType().getName();
e.name = field.getName();

entities.add(e);
}
}

return entities;
}</pre>
<p> 其他的变动不大,对于需要导出的值对象,用annotation标注一下就可以了:</p>
<pre name="code" class="java">public class Student {
    @Cell(title = "学号")
    private long serialNumber;
   
    @Cell(title = "姓名")
    private String name;
   
    @Cell(title = "性别")
    private String sexual;
   
    @Cell(title = "分数")
    private Long score;

}
</pre>
 
<p> </p>
<p> </p>
<p> </p>
1 楼 studyoo 2009-09-21  
是POI不是PIO。

相关推荐

    基于poi的excel导入导出工具类

    基于poi的excel导入导出封装,poi版本 &lt;groupId&gt;org.apache.poi &lt;artifactId&gt;poi &lt;version&gt;4.1.0 &lt;groupId&gt;org.apache.poi &lt;artifactId&gt;poi-ooxml &lt;version&gt;4.1.0 &lt;/dependency&gt;

    基于poi的excel导入导出封装

    基于注解,ExcelExport.java将list集合导出到excel,支持多sheet导出 ExcelImport将excel导入到集合,支持多sheet导入 用法参见个人博客

    Apache POI 导出Excel工具类的实现,超简单实用

    Apache POI 导出EXCEL的封装实现工具类,超简单的调用方式,有说明文档示例参考,一看便懂,将繁琐变为简单,是我们一直追求的脚步……

    POI百万级excel导出开箱即用项目

    【标题】企业级POI百万数据导出 支持以下特性 (1)使用spring boot搭建项目,【特点】开箱即用,mybatis-plus持久化框架访问数据库,支持mysql,...(4)面向对象做了封装ExcelService,【特点】使用简单,代码简洁

    easyexcel4j:基于Apache POI的海量数据导入和简单导出的Excel工具

    easyexcel4j基于Apache POI的海量数据导入和简单导出的Excel工具快速使用1. 导入使用需要添加maven依赖&lt;!-- https://mvnrepository.com/artifact/com.github.ldzzdl/easyexcel4j --&gt;&lt;dependency&gt; &lt;groupId&gt;...

    POI海量数据大数据文件生成SXSSFWorkbook使用简介.pdf

    上⾯两个类导出excel的时候数据会驻留在内存中,所以当数据量⼤的时候容易造成内存溢出。SXSSFWorkbook是⽤来⽣成海 量excel数据⽂件,主要原理是借助临时存储空间⽣成excel。POI要求3.8以上,⽣成的⽂件格式要求是07...

    阿里EasyExcel的操作.pdf

    easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便

    EasyPOI操作Excel从零入门-视频课程资源网盘链接提取码下载 .txt

    导入导出解析等等,java中比较流行的用poi,但是每次都要写大段工具类来搞定这事儿,此处推荐一个别人造好的轮子,EasyPOI封装了Apache的POI技术,实现了基本的Excel导入、导出从此不再为Excel操作头疼~ 课程大小:...

    EXCEL导出组件(内含源码&测试类&测试文件)

    使用apache的poi再封装的一套excel导出组件,支持带模板execl的导出,省去了使用java代码绘制表格的过程,附件包含:源码+测试类+测试文件+导出结果文件,API使用文档参见我的另一篇博客:...

    easyexcel:快速,简单避免OOM的java处理Excel工具

    在上层的模型转换的封装,让使用者更简单方便64M内存1分钟内读取75M(46W行25列)的Excel当然还有急速模式能恢复,但是内存占用会在100M多一点相关文档维护者玉霄,庄家钜,怀宇快速开始读Excel 演示地址: : /** * ...

    毕业设计基于Java的直播数据可视化系统前后端源码+项目部署说明.zip

    5. 基于Apache POI与iText实现直播数据的报表统计与导出 6. 主播管理、用户管理等基础功能模块 这是一个基于Spring Boot + Vue的直播数据可视化系统,实现了直播数据的可视化展示、分级权限管理、警报数据流处理、...

    word模板导出demo

    基于Apache POI封装后的Word文档打印工具类。免责申明:仅学习参考使用,请勿用于商业用途。如果您在使用本工具作为商业用途的过程中,发生了严重的BUG,作者不承担任何责任。下载了该工具的用户默认已知晓上述内容...

Global site tag (gtag.js) - Google Analytics