实际开发过程中通常用到的就是从数据库导出EXCEL表格了,JXL可以这样做,其实POI也可以(关于JXL与POI的异同可访问我之前总结的文章),之前写过POI对七种文档(当然也包括EXCEL)的内容读取操作的文章,这次要写的就非常重要了,就是开发中经常会用到的POI读取数据库导出EXCEL的操作,所谓导出EXCEL也就是生成带数据内容的新的EXCEL文件
目前的POI版本是3.7
下载地址:/download.html#POI-3.7
必须包只有一个:poi-3.7-1029.jar
整理思路:1)数据库中的字段对应EXCEL的最顶层一行各个CELL名称[也就是上面图片中序号版本...的]
2)将每个数据一次插入到对应名称CELL的对应记录位置
3)为了方便操作,顶层的cell各个名称可以抽取出来成为一个单独类
具体代码
第一部分:单独的EXCEL表头类
public class Cachetable {
Java代码
//Fields
privateintrecnum;
privateStringdevIp;
privateStringsrcaddr;
privateStringdstaddr;
privateStringnexthop;
privateStringinput;
privateStringoutput;
privateStringdpkts;
privateStringdoctets;
privateStringsstart;
privateStringdstport;
privateStringprot;
privateStringtos;
privateStringsrcas;
privateStringdstas;
privateStringpduversion;
/**defaultconstructor*/
publicCachetable(){
}
/**fullconstructor*/
publicCachetable(intrecnum,StringdevIp,Stringsrcaddr,Stringdstaddr,Stringnexthop,Stringinput,Stringoutput,Stringdpkts,Stringdoctets,Stringsstart,Stringdstport,Stringprot,Stringtos,Stringsrcas,Stringdstas,Stringpduversion){
this.recnum=recnum;
this.devIp=devIp;
this.srcaddr=srcaddr;
this.dstaddr=dstaddr;
this.nexthop=nexthop;
this.input=input;
this.output=output;
this.dpkts=dpkts;
this.doctets=doctets;
this.sstart=sstart;
this.dstport=dstport;
this.prot=prot;
this.tos=tos;
this.srcas=srcas;
this.dstas=dstas;
this.pduversion=pduversion;
}
publicintgetRecnum(){
returnthis.recnum;
}
publicvoidsetRecnum(intrecnum){
this.recnum=recnum;
}
publicStringgetDevIp(){
returnthis.devIp;
}
publicvoidsetDevIp(StringdevIp){
this.devIp=devIp;
}
publicStringgetSrcaddr(){
returnthis.srcaddr;
}
publicvoidsetSrcaddr(Stringsrcaddr){
this.srcaddr=srcaddr;
}
publicStringgetDstaddr(){
returnthis.dstaddr;
}
publicvoidsetDstaddr(Stringdstaddr){
this.dstaddr=dstaddr;
}
publicStringgetNexthop(){
returnthis.nexthop;
}
publicvoidsetNexthop(Stringnexthop){
this.nexthop=nexthop;
}
publicStringgetInput(){
returnthis.input;
}
publicvoidsetInput(Stringinput){
this.input=input;
}
publicStringgetOutput(){
returnthis.output;
}
publicvoidsetOutput(Stringoutput){
this.output=output;
}
publicStringgetDpkts(){
returnthis.dpkts;
}
publicvoidsetDpkts(Stringdpkts){
this.dpkts=dpkts;
}
publicStringgetDoctets(){
returnthis.doctets;
}
publicvoidsetDoctets(Stringdoctets){
this.doctets=doctets;
}
publicStringgetSstart(){
returnthis.sstart;
}
publicvoidsetSstart(Stringsstart){
this.sstart=sstart;
}
publicStringgetDstport(){
returnthis.dstport;
}
publicvoidsetDstport(Stringdstport){
this.dstport=dstport;
}
publicStringgetProt(){
returnthis.prot;
}
publicvoidsetProt(Stringprot){
this.prot=prot;
}
publicStringgetTos(){
returnthis.tos;
}
publicvoidsetTos(Stringtos){
this.tos=tos;
}
publicStringgetSrcas(){
returnthis.srcas;
}
publicvoidsetSrcas(Stringsrcas){
this.srcas=srcas;
}
publicStringgetDstas(){
returnthis.dstas;
}
publicvoidsetDstas(Stringdstas){
this.dstas=dstas;
}
publicStringgetPduversion(){
returnthis.pduversion;
}
publicvoidsetPduversion(Stringpduversion){
this.pduversion=pduversion;
}
第二部分:具体的POI操作生成EXCEL类
【我这里只是个示例,没连数据库,直接运行即可,如果想连,稍微变动一点即可】
Java代码
packagecom.zkyy.flow.excel;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.OutputStream;
importjava.sql.SQLException;
importjava.util.ArrayList;
importjava.util.List;
importjavax.swing.JOptionPane;
importorg.apache.poi.hssf.usermodel.HSSFCell;
importorg.apache.poi.hssf.usermodel.HSSFCellStyle;
importorg.apache.poi.hssf.usermodel.HSSFDataFormat;
importorg.apache.poi.hssf.usermodel.HSSFFooter;
importorg.apache.poi.hssf.usermodel.HSSFHeader;
importorg.apache.poi.hssf.usermodel.HSSFRow;
importorg.apache.poi.hssf.usermodel.HSSFSheet;
importorg.apache.poi.hssf.usermodel.HSSFWorkbook;
importcom.kk.flow.webapp.util.Cachetable;
publicclassExcelOut{
//表头
publicstaticfinalString[]tableHeader={"序号","版本","接收时刻","设备","入接口","出接口",
"源IP","目的IP","下一跳","协议","端口","对端端口","TOS","源AS","目的AS","TCP_FLAG","pad1","pad2"};
//创建工作本TOS
publicstaticHSSFWorkbookdemoWorkBook=newHSSFWorkbook();
//创建表
publicstaticHSSFSheetdemoSheet=demoWorkBook.createSheet("TheWorld's500Enterprises");
//表头的单元格个数目
publicstaticfinalshortcellNumber=(short)tableHeader.length;
//数据库表的列数
publicstaticfinalintcolumNumber=1;
/**
*创建表头
*@return
*/
publicstaticvoidcreateTableHeader()
{
HSSFHeaderheader=demoSheet.getHeader();
header.setCenter("世界五百强企业名次表");
HSSFRowheaderRow=demoSheet.createRow((short)0);
for(inti=0;i
{
HSSFCellheaderCell=headerRow.createCell((short)i);
headerCell.setCellType(HSSFCell.CELL_TYPE_STRING);
headerCell.setCellValue(tableHeader[i]);
}
}
/**
*创建行
*@paramcells
*@paramrowIndex
*/
publicstaticvoidcreateTableRow(Listcells,shortrowIndex)
{
//创建第rowIndex行
HSSFRowrow=demoSheet.createRow((short)rowIndex);
for(inti=0;i
{
//创建第i个单元格
HSSFCellcell=row.createCell(i);
if(cell.getCellType()!=1){
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
}
//新增的四句话,设置CELL格式为文本格式
HSSFCellStylecellStyle2=demoWorkBook.createCellStyle();
HSSFDataFormatformat=demoWorkBook.createDataFormat();
cellStyle2.setDataFormat(format.getFormat("@"));
cell.setCellStyle(cellStyle2);
cell.setCellValue(cells.get(i));
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
}
}
/**
*USE:用于获取Cachetable的数据。。。假数据。到时候:你连接数据库的到List的数据就行了。共生成
*100条数据.相当于100行
*
*@return
*/
publicListgetDate(){
ListcacheList=newArrayList();
for(intj=0;j
Cachetabletb=newCachetable();
tb.setRecnum(j+1);
tb.setDevIp("JavaCrazyer");
tb.setSrcaddr("北京");
tb.setDstaddr("xxx");
tb.setNexthop("yy");
tb.setInput("123");
tb.setOutput("127.0.0.1");
tb.setDpkts("whatareyoudoing?");
tb.setDoctets("whoareyou?");
tb.setSstart("Ohsure!");
tb.setProt("One");
tb.setTos("two");
tb.setSrcas("three");
tb.setDstas("four");
tb.setPduversion("不知道");
cacheList.add(tb);
}
returncacheList;
}
/**
*创建整个Excel表
*@throwsSQLException
*
*/
publicvoidcreateExcelSheet()throwsSQLException{
createTableHeader();
introwIndex=1;
Listlist=getDate();
for(intj=0;j
ListlistRead=newArrayList();
for(inti=1;i<=columNumber;i++){
listRead.add(list.get(i).getDevIp());
listRead.add(list.get(i).getSrcaddr());
listRead.add(list.get(i).getDstaddr());
listRead.add(list.get(i).getNexthop());
listRead.add(list.get(i).getInput());
listRead.add(list.get(i).getOutput());
listRead.add(list.get(i).getDpkts());
listRead.add(list.get(i).getDoctets());
listRead.add(list.get(i).getSstart());
listRead.add(list.get(i).getProt());
listRead.add(list.get(i).getTos());
listRead.add(list.get(i).getSrcas());
listRead.add(list.get(i).getDstas());
listRead.add(list.get(i).getPduversion());
listRead.add(rowIndex+"");
}
createTableRow(listRead,(short)rowIndex);
rowIndex++;
}
}
/**
*导出表格
*@paramsheet
*@paramos
*@throwsIOException
*/
publicvoidexportExcel(HSSFSheetsheet,OutputStreamos)throwsIOException
{
sheet.setGridsPrinted(true);
HSSFFooterfooter=sheet.getFooter();
footer.setRight("Page"+HSSFFooter.page()+"of"+
HSSFFooter.numPages());
demoWorkBook.write(os);
}
publicstaticvoidmain(String[]args){
StringfileName="f:\\世界五百强企业名次表.xls";
FileOutputStreamfos=null;
try{
ExcelOutpd=newExcelOut();
pd.createExcelSheet();
fos=newFileOutputStream(fileName);
pd.exportExcel(demoSheet,fos);
JOptionPane.showMessageDialog(null,"表格已成功导出到:"+fileName);
}catch(Exceptione){
JOptionPane.showMessageDialog(null,"表格导出出错,错误信息:"+e+"\n错误原因可能是表格已经打开。");
e.printStackTrace();
}finally{
try{
fos.close();
}catch(Exceptione){
e.printStackTrace();
}
}
}
}
说明:
1)有关数据库连接,如果操作到数据库的话,在遍历数据库时用getDate这个方法遍历就可以啦,那么插入的数据就不是定值了,而是数据库中的值哦,具体操作数据库的步骤,我不用说,你懂得
2)有关涉及更改EXCEL的CELL格式为字符串,如图一般情况下大家导出的EXCEL表格CELL格式通常是常规的
这个问题,估计已经不止一两个朋友在网上问过,我至今没有看到一个满意的答案,通常大家都是想到既然是设置CELL格式肯定是通过cell.setCellType(HSSFCell.CELL_TYPE_STRING)然后插入数据再导出,诚然这种想法是对的,实际上不能起到任何作用,因为这个方法就是EXCEL默认的格式,写不写都一样(好多同学都不知道吧),再写出我的解决方案之前请大家参考下一段文字
第一段:Excel的单元格格式
图中的数据有数值、货币、时间、日期、文本等格式。这些数据格式在POI中的HSSFDataFormat类里都有相应的定义。
HSSFDataFormat是HSSF子项目里面定义的一个类。类HSSFDataFormat允许用户新建数据格式类型。HSSFDataFormat类包含静态方法static java.lang.String getBuiltinFormat(short index),它可以根据编号返回内置数据类型。另外static short getBuiltinFormat(java.lang.String format)方法则可以根据数据类型返回其编号,static java.util.List getBuiltinFormats()可以返回整个内置的数据格式列表。
在HSSFDataFormat里一共定义了49种内置的数据格式,如下面所示。
HSSFDataFormat的数据格式
内置数据类型
编号
"General"
0
"0"
1
"0.00"
2
"#,##0"
3
"#,##0.00"
4
"($#,##0_);($#,##0)"
5
"($#,##0_);[Red]($#,##0)"
6
"($#,##0.00);($#,##0.00)"
7
"($#,##0.00_);[Red]($#,##0.00)"
8
"0%"
9
"0.00%"
0xa
"0.00E+00"
0xb
"# ?/?"
0xc
"# ??/??"
0xd
"m/d/yy"
0xe
"d-mmm-yy"
0xf
"d-mmm"
0x10
"mmm-yy"
0x11
"h:mm AM/PM"
0x12
"h:mm:ss AM/PM"
0x13
"h:mm"
0x14
"h:mm:ss"
0x15
"m/d/yy h:mm"
0x16
保留为过国际化用
0x17 - 0x24
"(#,##0_);(#,##0)"
0x25
"(#,##0_);[Red](#,##0)"
0x26
"(#,##0.00_);(#,##0.00)"
0x27
"(#,##0.00_);[Red](#,##0.00)"
0x28
"_($*#,##0_);_($*(#,##0);_($* \"-\"_);_(@_)"
0x29
"_(*#,##0.00_);_(*(#,##0.00);_(*\"-\"??_);_(@_)"
0x2a
"_($*#,##0.00_);_($*(#,##0.00);_($*\"-\"??_);_(@_)"
0x2b
"_($*#,##0.00_);_($*(#,##0.00);_($*\"-\"??_);_(@_)"
0x2c
"mm:ss"
0x2d
"[h]:mm:ss"
0x2e
"mm:ss.0"
0x2f
"##0.0E+0"
0x30
"@" - This is text format
0x31
在上面表中,字符串类型所对应的是数据格式为"@"(最后一行),也就是HSSFDataFormat中定义的值为0x31(49)的那行。Date类型的值的范围是0xe-0x11,本例子中的Date格式为""m/d/yy"",在HSSFDataFormat定义的值为0xe(14)。
第二段:POI中Excel文件Cell的类型
在读取每一个Cell的值的时候,通过getCellType方法获得当前Cell的类型,在Excel中Cell有6种类型,如下面所示。
Cell的类型
CellType
说明
CELL_TYPE_BLANK
空值
CELL_TYPE_BOOLEAN
布尔型
CELL_TYPE_ERROR
错误
CELL_TYPE_FORMULA
公式型
CELL_TYPE_STRING
字符串型
CELL_TYPE_NUMERIC
数值型
一般都采用CELL_TYPE_STRING和CELL_TYPE_NUMERIC类型,因为在Excel文件中只有字符串和数字。如果Cell的Type为CELL_TYPE_NUMERIC时,还需要进一步判断该Cell的数据格式,因为它有可能是Date类型,在Excel中的Date类型也是以Double类型的数字存储的。Excel中的Date表示当前时间与1900年1月1日相隔的天数,所以需要调用HSSFDateUtil的isCellDateFormatted方法,判断该Cell的数据格式是否是Excel Date类型。如果是,则调用getDateCellValue方法,返回一个Java类型的Date。
好了读完上面两段文字我想大家关于CELL类型和格式应该清楚了,更应该清楚的是到底怎么才能将‘设置单元格格式’改成文本然后再导出
解决方案:就是上面代码中的ExcelOut类里面createTableRow方法中的一段代码
HSSFCellStyle cellStyle2 = demoWorkBook.createCellStyle();
HSSFDataFormat format = demoWorkBook.createDataFormat();
cellStyle2.setDataFormat(format.getFormat("@"));
cell.setCellStyle(cellStyle2);
看最终导出效果图吧,点击任何一个CELL右键设置单元格格式
3)JOptionPane.showMessageDialog(null, "表格已成功导出到 : "+fileName);这句话有点意思
看到没这就是javax.swing.JOptionPane类的有关消息输出的好处,很方便使用