POI事件驱动模式读写Excel
目前处理Excel的开源javaAPI主要有两种,一是Jxl(Java Excel API),Jxl只支持Excel2003以下的版本。另外一种是Apache的Jakarta POI,相比于Jxl,POI对微软办公文档的支持更加强大,但是它使用复杂,上手慢。POI可支持更高的Excel版本2007。对Excel的读取,POI有两种模式,一是用户模式,这种方式同Jxl的使用很类似,使用简单,都是将文件一次性读到内存,文件小的时候,没有什么问题,当文件大的时候,就会出现OutOfMemory的内存溢出问题。第二种是事件驱动模式,拿Excel2007来说,其内容采用XML的格式来存储,所以处理excel就是解析XML,而目前使用事件驱动模式解析XML的API是SAX(Simple API for XML),这种模型在读取XML文档时,并没有将整个文档读入内存,而是按顺序将整个文档解析完,在解析过程中,会主动产生事件交给程序中相应的处理函数来处理当前内容。因此这种方式对系统资源要求不高,可以处理海量数据。笔者曾经做过测试,这种方法处理一千万条,每条五列的数据花费大约11分钟。可见处理海量数据的文件事件驱动是一个很好的方式。而本文中用到的AbstractExcel2003Reader、AbstractExcel2007Reader对Excel的读取都是采用这种POI的事件驱动模式。至于Excel的写操作,对较高版本的Excel2007,POI提供了很好的支持,主要流程是第一步构建工作薄和电子表格对象,第二步在一个流中构建文本文件,第三步使用流中产生的数据替换模板中的电子表格。这种方式也可以处理海量数据文件。AbstractExcel2007Writer就是使用这种方式进行写操作。对于写入较低版本的Excel2003,POI使用了用户模式来处理,就是将整个文档加载进内存,如果数据量大的话就会出现内存溢出的问题,Excel2003Writer就是使用这种方式。据笔者的测试,如果数据量大于3万条,每条8列的话,就会报OutOfMemory的错误。Excel2003中每个电子表格的记录数必须在65536以下,否则就会发生异常。目前还没有好的解决方案,建议对于海量数据写入操作,尽量使用Excel2007。
/**
* 抽象Excel2003读取器,通过实现HSSFListener监听器,采用事件驱动模式解析excel2003
* 中的内容,遇到特定事件才会触发,大大减少了内存的使用。
* 注意Excel2003Reader类中引用的Record类在hssf包下
*/
public class Excel2003Reader implements HSSFListener{
private int minColumns = -1;
private POIFSFileSystem fs;
private int lastRowNumber;
private int lastColumnNumber;
/** Should we output the formula, or the value it has? */
private boolean outputFormulaValues = true;
/** For parsing Formulas */
private SheetRecordCollectingListener workbookBuildingListener;
//excel2003工作薄
private HSSFWorkbook stubWorkbook;
// Records we pick up as we process
private SSTRecord sstRecord;
private FormatTrackingHSSFListener formatListener;
//表索引
private int sheetIndex = -1;
private BoundSheetRecord[] orderedBSRs;
@SuppressWarnings("unchecked")
private ArrayList boundSheetRecords = new ArrayList();
// For handling formulas with string results
private int nextRow;
private int nextColumn;
private boolean outputNextStringRecord;
//当前行
private int curRow = 0;
//存储行记录的容器
private List<String> rowlist = new ArrayList<String>();;
@SuppressWarnings( "unused")
private String sheetName;
private IRowReader rowReader;
public void setRowReader(IRowReader rowReader){
this.rowReader = rowReader;
}
/**
* 遍历excel下所有的sheet
* @throws IOException
*/
public void process(String fileName) throws IOException {
this.fs = new POIFSFileSystem(new FileInputStream(fileName));
MissingRecordAwareHSSFListener listener = new MissingRecordAwareHSSFListener(
this);
formatListener = new FormatTrackingHSSFListener(listener);
HSSFEventFactory factory = new HSSFEventFactory();
HSSFRequest request = new HSSFRequest();
if (outputFormulaValues) {
request.addListenerForAllRecords(formatListener);
} else {
workbookBuildingListener = new SheetRecordCollectingListener(
formatListener);
request.addListenerForAllRecords(workbookBuildingListener);
}
factory.processWorkbookEvents(request, fs);
}
/**
* HSSFListener 监听方法,处理 Record
*/
@SuppressWarnings("unchecked")
public void processRecord(Record record) {
int thisRow = -1;
int thisColumn = -1;
String thisStr = null;
String value = null;
switch (record.getSid()) {
case BoundSheetRecord.sid:
boundSheetRecords.add(record);
break;
case BOFRecord.sid:
BOFRecord br = (BOFRecord) record;
if (br.getType() == BOFRecord.TYPE_WORKSHEET) {
// 如果有需要,则建立子工作薄
if (workbookBuildingListener != null && stubWorkbook == null) {
stubWorkbook = workbookBuildingListener
.getStubHSSFWorkbook();
}
sheetIndex++;
if (orderedBSRs == null) {
orderedBSRs = BoundSheetRecord
.orderByBofPosition(boundSheetRecords);
}
sheetName = orderedBSRs[sheetIndex].getSheetname();
}
break;
case SSTRecord.sid:
sstRecord = (SSTRecord) record;
break;
case BlankRecord.sid:
BlankRecord brec = (BlankRecord) record;
thisRow = brec.getRow();
thisColumn = brec.getColumn();
thisStr = "";
rowlist.add(thisColumn, thisStr);
break;
case BoolErrRecord.sid: //单元格为布尔类型
BoolErrRecord berec = (BoolErrRecord) record;
thisRow = berec.getRow();
thisColumn = berec.getColumn();
thisStr = berec.getBooleanValue()+"";
rowlist.add(thisColumn, thisStr);
break;
case FormulaRecord.sid: //单元格为公式类型
FormulaRecord frec = (FormulaRecord) record;
thisRow = frec.getRow();
thisColumn = frec.getColumn();
if (outputFormulaValues) {
if (Double.isNaN(frec.getValue())) {
// Formula result is a string
// This is stored in the next record
outputNextStringRecord = true;
nextRow = frec.getRow();
nextColumn = frec.getColumn();
} else {
thisStr = formatListener.formatNumberDateCell(frec);
}
} else {
thisStr = '"' + HSSFFormulaParser.toFormulaString(stubWorkbook,
frec.getParsedExpression()) + '"';
}
rowlist.add(thisColumn,thisStr);
break;
case StringRecord.sid://单元格中公式的字符串
if (outputNextStringRecord) {
// String for formula
StringRecord srec = (StringRecord) record;
thisStr = srec.getString();
thisRow = nextRow;
thisColumn = nextColumn;
outputNextStringRecord = false;
}
break;
case LabelRecord.sid:
LabelRecord lrec = (LabelRecord) record;
curRow = thisRow = lrec.getRow();
thisColumn = lrec.getColumn();
value = lrec.getValue().trim();
value = value.equals("")?" ":value;
this.rowlist.add(thisColumn, value);
break;
case LabelSSTRecord.sid: //单元格为字符串类型
LabelSSTRecord lsrec = (LabelSSTRecord) record;
curRow = thisRow = lsrec.getRow();
thisColumn = lsrec.getColumn();
if (sstRecord == null) {
rowlist.add(thisColumn, " ");
} else {
value = sstRecord
.getString(lsrec.getSSTIndex()).toString().trim();
value = value.equals("")?" ":value;
rowlist.add(thisColumn,value);
}
break;
case NumberRecord.sid: //单元格为数字类型
NumberRecord numrec = (NumberRecord) record;
curRow = thisRow = numrec.getRow();
thisColumn = numrec.getColumn();
value = formatListener.formatNumberDateCell(numrec).trim();
value = value.equals("")?" ":value;
// 向容器加入列值
rowlist.add(thisColumn, value);
break;
default:
break;
}
// 遇到新行的操作
if (thisRow != -1 && thisRow != lastRowNumber) {
lastColumnNumber = -1;
}
// 空值的操作
if (record instanceof MissingCellDummyRecord) {
MissingCellDummyRecord mc = (MissingCellDummyRecord) record;
curRow = thisRow = mc.getRow();
thisColumn = mc.getColumn();
rowlist.add(thisColumn," ");
}
// 更新行和列的值
if (thisRow > -1)
lastRowNumber = thisRow;
if (thisColumn > -1)
lastColumnNumber = thisColumn;
// 行结束时的操作
if (record instanceof LastCellOfRowDummyRecord) {
if (minColumns > 0) {
// 列值重新置空
if (lastColumnNumber == -1) {
lastColumnNumber = 0;
}
}
lastColumnNumber = -1;
// 每行结束时, 调用getRows() 方法
rowReader.getRows(sheetIndex,curRow, rowlist);
// 清空容器
rowlist.clear();
}
}
/**
* 遍历工作簿中所有的电子表格
* @param filename
* @throws Exception
*/
public void process(String filename) throws Exception {
OPCPackage pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader(pkg);
SharedStringsTable sst = r.getSharedStringsTable();
XMLReader parser = fetchSheetParser(sst);
Iterator<InputStream> sheets = r.getSheetsData();
while (sheets.hasNext()) {
curRow = 0;
sheetIndex++;
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
}
}
public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException { XMLReader parser = XMLReaderFactory .createXMLReader("org.apache.xerces.parsers.SAXParser"); this.sst = sst; parser.setContentHandler(this); return parser; }
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { // c => 单元格 if ("c".equals(name)) { // 如果下一个元素是 SST 的索引,则将nextIsString标记为true String cellType = attributes.getValue("t"); if ("s".equals(cellType)) { nextIsString = true; } else { nextIsString = false; } //日期格式 String cellDateType = attributes.getValue("s"); if ("1".equals(cellDateType)){ dateFlag = true; } else { dateFlag = false; } String cellNumberType = attributes.getValue("s"); if("2".equals(cellNumberType)){ numberFlag = true; } else { numberFlag = false; } } //当元素为t时 if("t".equals(name)){ isTElement = true; } else { isTElement = false; } // 置空 lastContents = ""; }
public void endElement(String uri, String localName, String name) throws SAXException { // 根据SST的索引值的到单元格的真正要存储的字符串 // 这时characters()方法可能会被调用多次 if (nextIsString) { try { int idx = Integer.parseInt(lastContents); lastContents = new XSSFRichTextString(sst.getEntryAt(idx)) .toString(); } catch (Exception e) {
} } //t元素也包含字符串 if(isTElement){ String value = lastContents.trim(); rowlist.add(curCol, value); curCol++; isTElement = false; // v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引 // 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符 } else if ("v".equals(name)) { String value = lastContents.trim(); value = value.equals("")?" ":value; //日期格式处理 if(dateFlag){ Date date = HSSFDateUtil.getJavaDate(Double.valueOf(value)); SimpleDateFormat dateFormat = new SimpleDateFormat( "dd/MM/yyyy"); value = dateFormat.format(date); } //数字类型处理 if(numberFlag){ BigDecimal bd = new BigDecimal(value); value = bd.setScale(3,BigDecimal.ROUND_UP).toString(); } rowlist.add(curCol, value); curCol++; }else { //如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法 if (name.equals("row")) { rowReader.getRows(sheetIndex,curRow,rowlist); rowlist.clear(); curRow++; curCol = 0; } } }
public void characters(char[] ch, int start, int length) throws SAXException { //得到单元格内容的值 lastContents += new String(ch, start, length); } }
读取Excel文件,可能是03也可能是07版本
public class ExcelReaderUtil { //excel2003扩展名 public static final String EXCEL03_EXTENSION = ".xls"; //excel2007扩展名 public static final String EXCEL07_EXTENSION = ".xlsx"; /** * 读取Excel文件,可能是03也可能是07版本 * @param excel03 * @param excel07 * @param fileName * @throws Exception */ public static void readExcel(IRowReader reader,String fileName) throws Exception{ // 处理excel2003文件 if (fileName.endsWith(EXCEL03_EXTENSION)){ Excel2003Reader excel03 = new Excel2003Reader(); excel03.setRowReader(reader); excel03.process(fileName); // 处理excel2007文件 } else if (fileName.endsWith(EXCEL07_EXTENSION)){ Excel2007Reader excel07 = new Excel2007Reader(); excel07.setRowReader(reader); excel07.process(fileName); } else { throw new Exception("文件格式错误,fileName的扩展名只能是xls或xlsx。"); } }} public interface IRowReader { /**业务逻辑实现方法 * @param sheetIndex * @param curRow * @param rowlist */ public void getRows(int sheetIndex,int curRow, List<String> rowlist);}public class RowReader implements IRowReader{ /* 业务逻辑实现方法 * @see com.eprosun.util.excel.IRowReader#getRows(int, int, java.util.List) */ public void getRows(int sheetIndex, int curRow, List<String> rowlist) { // TODO Auto-generated method stub System.out.print(curRow+" "); for (int i = 0; i < rowlist.size(); i++) { System.out.print(rowlist.get(i) + " "); } System.out.println(); }}
public class Main {
public static void main(String[] args) throws Exception {
IRowReader reader = new RowReader();
//ExcelReaderUtil.readExcel(reader, "F://te2003.xls");
ExcelReaderUtil.readExcel(reader, "F://test2007.xlsx");
}
}
/**
* 注意Excel2003Writer类中引用的Sheet在poi.ss.usermodel包下.
*/
public class Excel2003Writer {
/**
* @param args
*/
public static void main(String[] args) {
try{
System.out.println("开始写入excel2003....");
writeExcel("tes2003.xls");
System.out.println("写完xcel2003");
} catch (IOException e) {
}
}
/**
* 写入excel并填充内容,一个sheet只能写65536行以下,超出会报异常,写入时建议使用AbstractExcel2007Writer
* @param fileName
* @throws IOException
*/
public static void writeExcel(String fileName) throws IOException{
// 创建excel2003对象
Workbook wb = new HSSFWorkbook();
// 设置文件放置路径和文件名
FileOutputStream fileOut = new FileOutputStream(fileName);
// 创建新的表单
Sheet sheet = wb.createSheet("newsheet");
// 创建新行
for(int i=0;i<20000;i++){
Row row = sheet.createRow(i);
// 创建单元格
Cell cell = row.createCell(0);
// 设置单元格值
cell.setCellValue(1);
row.createCell(1).setCellValue(1+i);
row.createCell(2).setCellValue(true);
row.createCell(3).setCellValue(0.43d);
row.createCell(4).setCellValue('d');
row.createCell(5).setCellValue("");
row.createCell(6).setCellValue("第七列"+i);
row.createCell(7).setCellValue("第八列"+i);
}
wb.write(fileOut);
fileOut.close();
}
}
/**
* 抽象excel2007读入器,先构建.xlsx一张模板,改写模板中的sheet.xml,使用这种方法
* 写入.xlsx文件,不需要太大的内存
* 注意AbstractExcel2007Writer类中引用的CellReference在org.apache.poi.ss.util/org.apache.poi.hssf.util包下需确认下
*/
public abstract class AbstractExcel2007Writer {
private SpreadsheetWriter sw;
/**
* 写入电子表格的主要流程
* @param fileName
* @throws Exception
*/
public void process(String fileName) throws Exception{
// 建立工作簿和电子表格对象
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet("sheet1");
// 持有电子表格数据的xml文件名 例如 /xl/worksheets/sheet1.xml
String sheetRef = sheet.getPackagePart().getPartName().getName();
// 保存模板
FileOutputStream os = new FileOutputStream("template.xlsx");
wb.write(os);
os.close();
// 生成xml文件
File tmp = File.createTempFile("sheet", ".xml");
Writer fw = new FileWriter(tmp);
sw = new SpreadsheetWriter(fw);
generate();
fw.close();
// 使用产生的数据替换模板
File templateFile = new File("template.xlsx");
FileOutputStream out = new FileOutputStream(fileName);
substitute(templateFile, tmp, sheetRef.substring(1), out);
out.close();
//删除文件之前调用一下垃圾回收器,否则无法删除模板文件
System.gc();
// 删除临时模板文件
if (templateFile.isFile()&&templateFile.exists()){
templateFile.delete();
}
}
/**
* 类使用者应该使用此方法进行写操作
* @throws Exception
*/
public abstract void generate() throws Exception;
public void beginSheet() throws IOException {
sw.beginSheet();
}
public void insertRow(int rowNum) throws IOException {
sw.insertRow(rowNum);
}
public void createCell(int columnIndex, String value) throws IOException {
sw.createCell(columnIndex, value, -1);
}
public void createCell(int columnIndex, double value) throws IOException {
sw.createCell(columnIndex, value, -1);
}
public void endRow() throws IOException {
sw.endRow();
}
public void endSheet() throws IOException {
sw.endSheet();
}
/**
*
* @param zipfile the template file
* @param tmpfile the XML file with the sheet data
* @param entry the name of the sheet entry to substitute, e.g. xl/worksheets/sheet1.xml
* @param out the stream to write the result to
*/
private static void substitute(File zipfile, File tmpfile, String entry,
OutputStream out) throws IOException {
ZipFile zip = new ZipFile(zipfile);
ZipOutputStream zos = new ZipOutputStream(out);
@SuppressWarnings("unchecked")
Enumeration<ZipEntry> en = (Enumeration<ZipEntry>) zip.entries();
while (en.hasMoreElements()) {
ZipEntry ze = en.nextElement();
if (!ze.getName().equals(entry)) {
zos.putNextEntry(new ZipEntry(ze.getName()));
InputStream is = zip.getInputStream(ze);
copyStream(is, zos);
is.close();
}
}
zos.putNextEntry(new ZipEntry(entry));
InputStream is = new FileInputStream(tmpfile);
copyStream(is, zos);
is.close();
zos.close();
}
private static void copyStream(InputStream in, OutputStream out)
throws IOException {
byte[] chunk = new byte[1024];
int count;
while ((count = in.read(chunk)) >= 0) {
out.write(chunk, 0, count);
}
}
/**
* 在写入器中写入电子表格
*
*/
public static class SpreadsheetWriter {
private final Writer _out;
private int _rownum;
private static String LINE_SEPARATOR = System.getProperty("line.separator");
public SpreadsheetWriter(Writer out) {
_out = out;
}
public void beginSheet() throws IOException {
_out.write("<?xml version=\"1.0\" encoding=\"GB2312\"?>"
+ "<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">");
_out.write("<sheetData>"+LINE_SEPARATOR);
}
public void endSheet() throws IOException {
_out.write("</sheetData>");
_out.write("</worksheet>");
}
/**
* 插入新行
*
* @param rownum 以0开始
*/
public void insertRow(int rownum) throws IOException {
_out.write("<row r=\"" + (rownum + 1) + "\">"+LINE_SEPARATOR);
this._rownum = rownum;
}
/**
* 插入行结束标志
*/
public void endRow() throws IOException {
_out.write("</row>"+LINE_SEPARATOR);
}
/**
* 插入新列
* @param columnIndex
* @param value
* @param styleIndex
* @throws IOException
*/
public void createCell(int columnIndex, String value, int styleIndex)
throws IOException {
String ref = new CellReference(_rownum, columnIndex)
.formatAsString();
_out.write("<c r=\"" + ref + "\" t=\"inlineStr\"");
if (styleIndex != -1)
_out.write(" s=\"" + styleIndex + "\"");
_out.write(">");
_out.write("<is><t>"+XMLEncoder.encode(value)+"</t></is>");
_out.write("</c>");
}
public void createCell(int columnIndex, String value)
throws IOException {
createCell(columnIndex, value, -1);
}
public void createCell(int columnIndex, double value, int styleIndex)
throws IOException {
String ref = new CellReference(_rownum, columnIndex)
.formatAsString();
_out.write("<c r=\"" + ref + "\" t=\"n\"");
if (styleIndex != -1)
_out.write(" s=\"" + styleIndex + "\"");
_out.write(">");
_out.write("<v>" + value + "</v>");
_out.write("</c>");
}
public void createCell(int columnIndex, double value)
throws IOException {
createCell(columnIndex, value, -1);
}
public void createCell(int columnIndex, Calendar value, int styleIndex)
throws IOException {
createCell(columnIndex, DateUtil.getExcelDate(value, false),
styleIndex);
}
}
}
public class Excel2007WriterImpl extends AbstractExcel2007Writer{
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
System.out.println("............................");
long start = System.currentTimeMillis();
//构建excel2007写入器
AbstractExcel2007Writer excel07Writer = new Excel2007WriterImpl();
//调用处理方法
excel07Writer.process("F://test07.xlsx");
long end = System.currentTimeMillis();
System.out.println("....................."+(end-start)/1000);
}
/*
* 可根据需求重写此方法,对于单元格的小数或者日期格式,会出现精度问题或者日期格式转化问题,建议使用字符串插入方法
* @see com.excel.ver2.AbstractExcel2007Writer#generate()
*/
@Override
public void generate()throws Exception {
//电子表格开始
beginSheet();
for (int rownum = 0; rownum < 100; rownum++) {
//插入新行
insertRow(rownum);
//建立新单元格,索引值从0开始,表示第一列
createCell(0, "中国<" + rownum + "!");
createCell(1, 34343.123456789);
createCell(2, "23.67%");
createCell(3, "12:12:23");
createCell(4, "2010-10-11 12:12:23");
createCell(5, "true");
createCell(6, "false");
//结束行
endRow();
}
//电子表格结束
endSheet();
}
}
public class XMLEncoder {
private static final String[] xmlCode = new String[256];
static {
// Special characters
xmlCode['\''] = "'";
xmlCode['\"'] = "\""; // double quote
xmlCode['&'] = "&"; // ampersand
xmlCode['<'] = "<"; // lower than
xmlCode['>'] = ">"; // greater than
}
/**
* <p>
* Encode the given text into xml.
* </p>
*
* @param string the text to encode
* @return the encoded string
*/
public static String encode(String string) {
if (string == null) return "";
int n = string.length();
char character;
String xmlchar;
StringBuffer buffer = new StringBuffer();
// loop over all the characters of the String.
for (int i = 0; i < n; i++) {
character = string.charAt(i);
// the xmlcode of these characters are added to a StringBuffer one by one
try {
xmlchar = xmlCode[character];
if (xmlchar == null) {
buffer.append(character);
} else {
buffer.append(xmlCode[character]);
}
} catch (ArrayIndexOutOfBoundsException aioobe) {
buffer.append(character);
}
}
return buffer.toString();
}
}
需要导入的jar包参考如下:
注意以上程序还需要引入以下jar包
xmlbeans_2.3.0.jar,dom4j.jar,xercesImpl.jar
WorkbookFactory 找不到类问题
在最近的POI版本中,poi-3.7.jar包中找不到WorkbookFactory这个类,该类在创建一个存在的Excel文件并读取内容时会用到,而这个类存在于:poi-ooxml-3.7.jar中,因此如果在apapche网站下载poi包时,需要引入这两个jar包;
POI导入导出Excel数据简单例子
一、准备
笔者使用:JDK1.5 + POI 3.6,本代码既支持Excel2003又支持Excel2007。
POI 3.6 可以从 http://poi.apache.org/ 下载
需要导入的jar包:
Excel 数据文件:
二、代码
Bean:
创建bean对象,bean对象保存数据。
package com.test;
/**
*
* Student Bean
*
*/
public class Student
{
private String name;
private String sex;
private String age;
private String country;
private String studentID;
private String specialty;
private String admissionTime;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getSex()
{
return sex;
}
public void setSex(String sex)
{
this.sex = sex;
}
public String getAge()
{
return age;
}
public void setAge(String age)
{
this.age = age;
}
public String getCountry()
{
return country;
}
public void setCountry(String country)
{
this.country = country;
}
public String getStudentID()
{
return studentID;
}
public void setStudentID(String studentID)
{
this.studentID = studentID;
}
public String getSpecialty()
{
return specialty;
}
public void setSpecialty(String specialty)
{
this.specialty = specialty;
}
public String getAdmissionTime()
{
return admissionTime;
}
public void setAdmissionTime(String admissionTime)
{
this.admissionTime = admissionTime;
}
@Override
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append("[name=" + this.name + "]")
.append(",")
.append("[sex=" + this.sex + "]")
.append(",")
.append("[age=" + this.age + "]")
.append(",")
.append("[country=" + this.country + "]")
.append(",")
.append("[studentID=" + this.studentID + "]")
.append(",")
.append("[specialty=" + this.specialty + "]")
.append(",")
.append("[admissionTime=" + this.admissionTime + "]");
return sb.toString();
}
}
package com.test;
/**
*
* Student Bean
*
*/
public class Student
{
private String name;
private String sex;
private String age;
private String country;
private String studentID;
private String specialty;
private String admissionTime;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getSex()
{
return sex;
}
public void setSex(String sex)
{
this.sex = sex;
}
public String getAge()
{
return age;
}
public void setAge(String age)
{
this.age = age;
}
public String getCountry()
{
return country;
}
public void setCountry(String country)
{
this.country = country;
}
public String getStudentID()
{
return studentID;
}
public void setStudentID(String studentID)
{
this.studentID = studentID;
}
public String getSpecialty()
{
return specialty;
}
public void setSpecialty(String specialty)
{
this.specialty = specialty;
}
public String getAdmissionTime()
{
return admissionTime;
}
public void setAdmissionTime(String admissionTime)
{
this.admissionTime = admissionTime;
}
@Override
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append("[name=" + this.name + "]")
.append(",")
.append("[sex=" + this.sex + "]")
.append(",")
.append("[age=" + this.age + "]")
.append(",")
.append("[country=" + this.country + "]")
.append(",")
.append("[studentID=" + this.studentID + "]")
.append(",")
.append("[specialty=" + this.specialty + "]")
.append(",")
.append("[admissionTime=" + this.admissionTime + "]");
return sb.toString();
}
}
导入操作类:
1、使用WorkbookFactory.create方法将Excel数据文件加载到工厂中,根据不同的文件类型(2007还是2003)得到不同的Workbook。
2、调用Workbook.getSheetAt(0),获取第一个工作簿。
3、获取总行数,根据总行数迭代获取每一行(Row表示行)的数据。
4、使用Row的getCell获取数据,获取数据时需要注意获取的每一列的数据类型,根据不同的数据类型转换成字符串。
5、将列中数据一一对应封装到bean对象中。
package com.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
/**
*
* 操作Excel表格的功能类
*
*/
public final class ExcelReader
{
/**
* 读取Excel数据内容
* @param excelDataFile 待解析的文件
* @return List<Student> 学生集合
*/
public static List<Student> readExcelContent(File excelDataFile)
{
List<Student> students = new ArrayList<Student>();
Workbook workbook = null;
// Partner Excel 数据文件流
InputStream inputStream = null;
try
{
inputStream = new FileInputStream(excelDataFile);
workbook = WorkbookFactory.create(inputStream);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (InvalidFormatException e)
{
e.printStackTrace();
}
finally
{
try
{
if (null != inputStream)
{
inputStream.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
// 获取第一个工作簿
Sheet sheet = workbook.getSheetAt(0);
//得到总行数
int rowNum = sheet.getLastRowNum();
// 数据行
Row row = null;
//正文内容应该从第二行开始,第一行为表头的标题
for (int i = 1; i <= rowNum; i++)
{
// 获取第二行(内容行)
row = sheet.getRow(i);
if (null != row)
{
students.add(buildStudent(row));
}
}
return students;
}
/**
* 构建Partner对象
* @param row Excel数据行
* @return 构建好的Student对象
* @see [类、类#方法、类#成员]
*/
private static Student buildStudent(Row row)
{
Student student = new Student();
// 获取每一列的数据
// i < 7 表示只读取7列数据,如果想动态获取列数,则获取表头的列数即可,调用 HSSFRow 的getPhysicalNumberOfCells()。
// for (int i = 0; i < 7; i++)
// {
// getStringCellValue(row.getCell(i));
// }
// 获取每一列
student.setName(getStringCellValue(row.getCell(0)));
student.setSex(getStringCellValue(row.getCell(1)));
student.setCountry(getStringCellValue(row.getCell(2)));
student.setStudentID(getStringCellValue(row.getCell(3)));
student.setAge(getStringCellValue(row.getCell(4)));
student.setSpecialty(getStringCellValue(row.getCell(5)));
student.setAdmissionTime(getStringCellValue(row.getCell(6)));
return student;
}
/**
* 根据不同的类型获取Excel单元格中的数据
* @param cell Excel单元格
* @return String 单元格数据内容
*/
private static String getStringCellValue(Cell cell)
{
String strCell = "";
if (null != cell)
{
switch (cell.getCellType())
{
case HSSFCell.CELL_TYPE_STRING:
strCell = cell.getStringCellValue();
break;
case HSSFCell.CELL_TYPE_NUMERIC:
// true:日期类型;false:数字类型
if (DateUtil.isCellDateFormatted(cell))
{
Date date = cell.getDateCellValue();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
strCell = dateFormat.format(date);
}
else
{
Double doubleValue = cell.getNumericCellValue();
strCell = String.valueOf(doubleValue.longValue());
}
break;
case HSSFCell.CELL_TYPE_BOOLEAN:
strCell = String.valueOf(cell.getBooleanCellValue());
break;
default:
break;
}
}
return strCell;
}
public static void main(String[] args)
{
// Excel 2003
String excelFilePath = "D://student.xls";
// Excel 2007
//String excelFilePath = "D://student.xlsx";
//对读取Excel表格内容测试
List<Student> students =
ExcelReader.readExcelContent(new File(excelFilePath));
System.out.println("获得Excel表格的内容:");
for (Student student : students)
{
System.out.println(student);
}
}
}
package com.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
/**
*
* 操作Excel表格的功能类
*
*/
public final class ExcelReader
{
/**
* 读取Excel数据内容
* @param excelDataFile 待解析的文件
* @return List<Student> 学生集合
*/
public static List<Student> readExcelContent(File excelDataFile)
{
List<Student> students = new ArrayList<Student>();
Workbook workbook = null;
// Partner Excel 数据文件流
InputStream inputStream = null;
try
{
inputStream = new FileInputStream(excelDataFile);
workbook = WorkbookFactory.create(inputStream);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (InvalidFormatException e)
{
e.printStackTrace();
}
finally
{
try
{
if (null != inputStream)
{
inputStream.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
// 获取第一个工作簿
Sheet sheet = workbook.getSheetAt(0);
//得到总行数
int rowNum = sheet.getLastRowNum();
// 数据行
Row row = null;
//正文内容应该从第二行开始,第一行为表头的标题
for (int i = 1; i <= rowNum; i++)
{
// 获取第二行(内容行)
row = sheet.getRow(i);
if (null != row)
{
students.add(buildStudent(row));
}
}
return students;
}
/**
* 构建Partner对象
* @param row Excel数据行
* @return 构建好的Student对象
* @see [类、类#方法、类#成员]
*/
private static Student buildStudent(Row row)
{
Student student = new Student();
// 获取每一列的数据
// i < 7 表示只读取7列数据,如果想动态获取列数,则获取表头的列数即可,调用 HSSFRow 的getPhysicalNumberOfCells()。
// for (int i = 0; i < 7; i++)
// {
// getStringCellValue(row.getCell(i));
// }
// 获取每一列
student.setName(getStringCellValue(row.getCell(0)));
student.setSex(getStringCellValue(row.getCell(1)));
student.setCountry(getStringCellValue(row.getCell(2)));
student.setStudentID(getStringCellValue(row.getCell(3)));
student.setAge(getStringCellValue(row.getCell(4)));
student.setSpecialty(getStringCellValue(row.getCell(5)));
student.setAdmissionTime(getStringCellValue(row.getCell(6)));
return student;
}
/**
* 根据不同的类型获取Excel单元格中的数据
* @param cell Excel单元格
* @return String 单元格数据内容
*/
private static String getStringCellValue(Cell cell)
{
String strCell = "";
if (null != cell)
{
switch (cell.getCellType())
{
case HSSFCell.CELL_TYPE_STRING:
strCell = cell.getStringCellValue();
break;
case HSSFCell.CELL_TYPE_NUMERIC:
// true:日期类型;false:数字类型
if (DateUtil.isCellDateFormatted(cell))
{
Date date = cell.getDateCellValue();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
strCell = dateFormat.format(date);
}
else
{
Double doubleValue = cell.getNumericCellValue();
strCell = String.valueOf(doubleValue.longValue());
}
break;
case HSSFCell.CELL_TYPE_BOOLEAN:
strCell = String.valueOf(cell.getBooleanCellValue());
break;
default:
break;
}
}
return strCell;
}
public static void main(String[] args)
{
// Excel 2003
String excelFilePath = "D://student.xls";
// Excel 2007
//String excelFilePath = "D://student.xlsx";
//对读取Excel表格内容测试
List<Student> students =
ExcelReader.readExcelContent(new File(excelFilePath));
System.out.println("获得Excel表格的内容:");
for (Student student : students)
{
System.out.println(student);
}
}
}
导入测试结果:
导出操作类:
1、new HSSFWorkbook 或者 new XSSFWorkbook。
2、创建Sheet并设置标题,Workbook 的 createSheet 方法。
3、创建表头,Sheet.createRow(0),0 表示第一行,一般第一行都作为表头标题。
4、循环读取集合中的数据。此处注意要从1(数据行)开始,因为0为表头,Sheet.createRow(1),以此类推,集合中有多少条记录,则创建多少行。
5、创建新行的每一列并将数据赋值到对应的列中Row.createCell(0),0表示第一列,以此类推,然后调用Cell的setCellValue方法赋值。
6、创建文件流,然后调用Workbook的write写入到文件流中,关闭流,注意导出的文件名称。
package com.test;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
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.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
*
* 操作Excel表格的功能类
* 支持2007和2003
*
*/
public final class ExcelExport
{
/**
* 将数据导出到Excel中
* @param students 数据集合
* @param filePath 导出文件路径及文件名称
*/
public static void exportExcel(List<Student> students, String filePath)
{
// 创建一个工作簿
// Excel 2003
//Workbook workbook = new HSSFWorkbook();
// Excel 2007
Workbook workbook = new XSSFWorkbook();
// 创建Sheet并设置标题
Sheet sheet = workbook.createSheet("基本信息");
// 创建表头
Row headRow = sheet.createRow(0);
headRow.createCell(0).setCellValue("姓名");
headRow.createCell(1).setCellValue("性别");
headRow.createCell(2).setCellValue("国籍");
headRow.createCell(3).setCellValue("学号");
headRow.createCell(4).setCellValue("年龄");
headRow.createCell(5).setCellValue("专业");
headRow.createCell(6).setCellValue("入学日期");
// 读取集合中的数据,此处注意要从1(数据行)开始,因为0为表头
for (int i = 1; i <= students.size(); i++)
{
// 获取一条数据
Student student = students.get(i - 1);
// 创建新行
Row row = sheet.createRow(i);
// 创建新行的每一列并将数据赋值到对应的列中
row.createCell(0).setCellValue(student.getName());
row.createCell(1).setCellValue(student.getSex());
row.createCell(2).setCellValue(student.getCountry());
row.createCell(3).setCellValue(student.getStudentID());
row.createCell(4).setCellValue(student.getAge());
row.createCell(5).setCellValue(student.getSpecialty());
row.createCell(6).setCellValue(student.getAdmissionTime());
}
FileOutputStream outputStream = null;
try
{
// 输出的文件路径及名称
outputStream = new FileOutputStream(filePath);
// 将数据写入工作簿中
workbook.write(outputStream);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
// 关闭流
if (null != outputStream)
{
outputStream.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
public static void main(String[] args)
{
// 数据集合
List<Student> students = new ArrayList<Student>();
// 待导出的数据
students.add(new Student("陈美嘉", "女 ", "中国", "05412578", "24", "计算机科学与技术", "2009/9/1"));
students.add(new Student("陆展博", "男", "中国", "05412579", "24", "计算机科学与技术", "2009/9/2"));
students.add(new Student("关谷神奇", "男", "日本", "05412580", "24", "计算机科学与技术", "009/9/3"));
// Excel 2003
//String excelFilePath = "D:\\学生信息.xls";
// Excel 2007
String excelFilePath = "D:\\学生信息.xlsx";
// 导出
ExcelExport.exportExcel(students, excelFilePath);
System.out.println("导出成功!");
}
}
package com.test;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
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.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
*
* 操作Excel表格的功能类
* 支持2007和2003
*
*/
public final class ExcelExport
{
/**
* 将数据导出到Excel中
* @param students 数据集合
* @param filePath 导出文件路径及文件名称
*/
public static void exportExcel(List<Student> students, String filePath)
{
// 创建一个工作簿
// Excel 2003
//Workbook workbook = new HSSFWorkbook();
// Excel 2007
Workbook workbook = new XSSFWorkbook();
// 创建Sheet并设置标题
Sheet sheet = workbook.createSheet("基本信息");
// 创建表头
Row headRow = sheet.createRow(0);
headRow.createCell(0).setCellValue("姓名");
headRow.createCell(1).setCellValue("性别");
headRow.createCell(2).setCellValue("国籍");
headRow.createCell(3).setCellValue("学号");
headRow.createCell(4).setCellValue("年龄");
headRow.createCell(5).setCellValue("专业");
headRow.createCell(6).setCellValue("入学日期");
// 读取集合中的数据,此处注意要从1(数据行)开始,因为0为表头
for (int i = 1; i <= students.size(); i++)
{
// 获取一条数据
Student student = students.get(i - 1);
// 创建新行
Row row = sheet.createRow(i);
// 创建新行的每一列并将数据赋值到对应的列中
row.createCell(0).setCellValue(student.getName());
row.createCell(1).setCellValue(student.getSex());
row.createCell(2).setCellValue(student.getCountry());
row.createCell(3).setCellValue(student.getStudentID());
row.createCell(4).setCellValue(student.getAge());
row.createCell(5).setCellValue(student.getSpecialty());
row.createCell(6).setCellValue(student.getAdmissionTime());
}
FileOutputStream outputStream = null;
try
{
// 输出的文件路径及名称
outputStream = new FileOutputStream(filePath);
// 将数据写入工作簿中
workbook.write(outputStream);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
// 关闭流
if (null != outputStream)
{
outputStream.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
public static void main(String[] args)
{
// 数据集合
List<Student> students = new ArrayList<Student>();
// 待导出的数据
students.add(new Student("陈美嘉", "女 ", "中国", "05412578", "24", "计算机科学与技术", "2009/9/1"));
students.add(new Student("陆展博", "男", "中国", "05412579", "24", "计算机科学与技术", "2009/9/2"));
students.add(new Student("关谷神奇", "男", "日本", "05412580", "24", "计算机科学与技术", "009/9/3"));
// Excel 2003
//String excelFilePath = "D:\\学生信息.xls";
// Excel 2007
String excelFilePath = "D:\\学生信息.xlsx";
// 导出
ExcelExport.exportExcel(students, excelFilePath);
System.out.println("导出成功!");
}
}
导出测试结果:
POI设置EXCEL单元格格式
开发中经常会用到的POI读取数据库导出EXCEL的操作,所谓导出EXCEL也就是生成带数据内容的新的EXCEL文件
目前的POI版本是3.7
下载地址:http://poi.apache.org/download.html#POI-3.7
必须包只有一个:poi-3.7-20101029.jar
整理思路:1)数据库中的字段对应EXCEL的最顶层一行各个CELL名称[也就是上面图片中序号版本...的]
2)将每个数据一次插入到对应名称CELL的对应记录位置
3)为了方便操作,顶层的cell各个名称可以抽取出来成为一个单独类
具体代码
第一部分:单独的EXCEL表头类
public class Cachetable {
Java代码
// Fields
private int recnum;
private String devIp;
private String srcaddr;
private String dstaddr;
private String nexthop;
private String input;
private String output;
private String dpkts;
private String doctets;
private String sstart;
private String dstport;
private String prot;
private String tos;
private String srcas;
private String dstas;
private String pduversion;
/** default constructor */
public Cachetable() {
}
/** full constructor */
public Cachetable(int recnum, String devIp, String srcaddr, String dstaddr, String nexthop, String input, String output, String dpkts, String doctets, String sstart, String dstport, String prot, String tos, String srcas, String dstas,String pduversion) {
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;
}
public int getRecnum() {
return this.recnum;
}
public void setRecnum(int recnum) {
this.recnum= recnum;
}
public String getDevIp() {
return this.devIp;
}
public void setDevIp(String devIp) {
this.devIp = devIp;
}
public String getSrcaddr() {
return this.srcaddr;
}
public void setSrcaddr(String srcaddr) {
this.srcaddr = srcaddr;
}
public String getDstaddr() {
return this.dstaddr;
}
public void setDstaddr(String dstaddr) {
this.dstaddr = dstaddr;
}
public String getNexthop() {
return this.nexthop;
}
public void setNexthop(String nexthop) {
this.nexthop = nexthop;
}
public String getInput() {
return this.input;
}
public void setInput(String input) {
this.input = input;
}
public String getOutput() {
return this.output;
}
public void setOutput(String output) {
this.output = output;
}
public String getDpkts() {
return this.dpkts;
}
public void setDpkts(String dpkts) {
this.dpkts = dpkts;
}
public String getDoctets() {
return this.doctets;
}
public void setDoctets(String doctets) {
this.doctets = doctets;
}
public String getSstart() {
return this.sstart;
}
public void setSstart(String sstart) {
this.sstart = sstart;
}
public String getDstport() {
return this.dstport;
}
public void setDstport(String dstport) {
this.dstport = dstport;
}
public String getProt() {
return this.prot;
}
public void setProt(String prot) {
this.prot = prot;
}
public String getTos() {
return this.tos;
}
public void setTos(String tos) {
this.tos = tos;
}
public String getSrcas() {
return this.srcas;
}
public void setSrcas(String srcas) {
this.srcas = srcas;
}
public String getDstas() {
return this.dstas;
}
public void setDstas(String dstas) {
this.dstas = dstas;
}
public String getPduversion() {
return this.pduversion;
}
public void setPduversion(String pduversion) {
this.pduversion = pduversion;
}
// Fields
private int recnum;
private String devIp;
private String srcaddr;
private String dstaddr;
private String nexthop;
private String input;
private String output;
private String dpkts;
private String doctets;
private String sstart;
private String dstport;
private String prot;
private String tos;
private String srcas;
private String dstas;
private String pduversion;
/** default constructor */
public Cachetable() {
}
/** full constructor */
public Cachetable(int recnum, String devIp, String srcaddr, String dstaddr, String nexthop, String input, String output, String dpkts, String doctets, String sstart, String dstport, String prot, String tos, String srcas, String dstas,String pduversion) {
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;
}
public int getRecnum() {
return this.recnum;
}
public void setRecnum(int recnum) {
this.recnum= recnum;
}
public String getDevIp() {
return this.devIp;
}
public void setDevIp(String devIp) {
this.devIp = devIp;
}
public String getSrcaddr() {
return this.srcaddr;
}
public void setSrcaddr(String srcaddr) {
this.srcaddr = srcaddr;
}
public String getDstaddr() {
return this.dstaddr;
}
public void setDstaddr(String dstaddr) {
this.dstaddr = dstaddr;
}
public String getNexthop() {
return this.nexthop;
}
public void setNexthop(String nexthop) {
this.nexthop = nexthop;
}
public String getInput() {
return this.input;
}
public void setInput(String input) {
this.input = input;
}
public String getOutput() {
return this.output;
}
public void setOutput(String output) {
this.output = output;
}
public String getDpkts() {
return this.dpkts;
}
public void setDpkts(String dpkts) {
this.dpkts = dpkts;
}
public String getDoctets() {
return this.doctets;
}
public void setDoctets(String doctets) {
this.doctets = doctets;
}
public String getSstart() {
return this.sstart;
}
public void setSstart(String sstart) {
this.sstart = sstart;
}
public String getDstport() {
return this.dstport;
}
public void setDstport(String dstport) {
this.dstport = dstport;
}
public String getProt() {
return this.prot;
}
public void setProt(String prot) {
this.prot = prot;
}
public String getTos() {
return this.tos;
}
public void setTos(String tos) {
this.tos = tos;
}
public String getSrcas() {
return this.srcas;
}
public void setSrcas(String srcas) {
this.srcas = srcas;
}
public String getDstas() {
return this.dstas;
}
public void setDstas(String dstas) {
this.dstas = dstas;
}
public String getPduversion() {
return this.pduversion;
}
public void setPduversion(String pduversion) {
this.pduversion = pduversion;
}
}
第二部分:具体的POI操作生成EXCEL类
【我这里只是个示例,没连数据库,直接运行即可,如果想连,稍微变动一点即可】
Java代码
package com.zkyy.flow.excel;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFFooter;
import org.apache.poi.hssf.usermodel.HSSFHeader;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import com.kk.flow.webapp.util.Cachetable;
public class ExcelOut {
//表头
public static final String[] tableHeader = {"序号","版本","接收时刻","设备","入接口","出接口",
"源IP","目的IP","下一跳","协议","端口","对端端口","TOS","源AS","目的AS","TCP_FLAG","pad1","pad2"};
//创建工作本 TOS
public static HSSFWorkbook demoWorkBook = new HSSFWorkbook();
//创建表
public static HSSFSheet demoSheet = demoWorkBook.createSheet("The World's 500 Enterprises");
//表头的单元格个数目
public static final short cellNumber = (short)tableHeader.length;
//数据库表的列数
public static final int columNumber = 1;
/**
* 创建表头
* @return
*/
public static void createTableHeader()
{
HSSFHeader header = demoSheet.getHeader();
header.setCenter("世界五百强企业名次表");
HSSFRow headerRow = demoSheet.createRow((short) 0);
for(int i = 0;i < cellNumber;i++)
{
HSSFCell headerCell = headerRow.createCell((short) i);
headerCell.setCellType(HSSFCell.CELL_TYPE_STRING);
headerCell.setCellValue(tableHeader[i]);
}
}
/**
* 创建行
* @param cells
* @param rowIndex
*/
public static void createTableRow(List<String> cells,short rowIndex)
{
//创建第rowIndex行
HSSFRow row = demoSheet.createRow((short) rowIndex);
for(int i = 0;i < cells.size();i++)
{
//创建第i个单元格
HSSFCell cell = row.createCell(i);
if(cell.getCellType()!=1){
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
}
//新增的四句话,设置CELL格式为文本格式
HSSFCellStyle cellStyle2 = demoWorkBook.createCellStyle();
HSSFDataFormat format = demoWorkBook.createDataFormat();
cellStyle2.setDataFormat(format.getFormat("@"));
cell.setCellStyle(cellStyle2);
cell.setCellValue(cells.get(i));
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
}
}
/**
* USE:用于获取Cachetable的数据。。。假数据。到时候:你连接数据库的到List<Cachetable>的数据就行了。 共生成
* 100条数据.相当于100行
*
* @return
*/
public List<Cachetable> getDate() {
List<Cachetable> cacheList = new ArrayList<Cachetable>();
for (int j = 0; j < 300; j++) {
Cachetable tb = new Cachetable();
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("what are you doing?");
tb.setDoctets("who are you?");
tb.setSstart("Oh sure!");
tb.setProt("One");
tb.setTos("two");
tb.setSrcas("three");
tb.setDstas("four");
tb.setPduversion("不知道");
cacheList.add(tb);
}
return cacheList;
}
/**
* 创建整个Excel表
* @throws SQLException
*
*/
public void createExcelSheet() throws SQLException{
createTableHeader();
int rowIndex=1;
List<Cachetable> list=getDate();
for(int j=0;j<list.size();j++){
List<String> listRead=new ArrayList<String>();
for(int i=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++;
}
}
/**
* 导出表格
* @param sheet
* @param os
* @throws IOException
*/
public void exportExcel(HSSFSheet sheet,OutputStream os) throws IOException
{
sheet.setGridsPrinted(true);
HSSFFooter footer = sheet.getFooter();
footer.setRight("Page " + HSSFFooter.page() + " of " +
HSSFFooter.numPages());
demoWorkBook.write(os);
}
public static void main(String[] args) {
String fileName = "f:\\世界五百强企业名次表.xls";
FileOutputStream fos = null;
try {
ExcelOut pd = new ExcelOut();
pd.createExcelSheet();
fos = new FileOutputStream(fileName);
pd.exportExcel(demoSheet,fos);
JOptionPane.showMessageDialog(null, "表格已成功导出到 : "+fileName);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "表格导出出错,错误信息 :"+e+"\n错误原因可能是表格已经打开。");
e.printStackTrace();
} finally {
try {
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
package com.zkyy.flow.excel;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFFooter;
import org.apache.poi.hssf.usermodel.HSSFHeader;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import com.kk.flow.webapp.util.Cachetable;
public class ExcelOut {
//表头
public static final String[] tableHeader = {"序号","版本","接收时刻","设备","入接口","出接口",
"源IP","目的IP","下一跳","协议","端口","对端端口","TOS","源AS","目的AS","TCP_FLAG","pad1","pad2"};
//创建工作本 TOS
public static HSSFWorkbook demoWorkBook = new HSSFWorkbook();
//创建表
public static HSSFSheet demoSheet = demoWorkBook.createSheet("The World's 500 Enterprises");
//表头的单元格个数目
public static final short cellNumber = (short)tableHeader.length;
//数据库表的列数
public static final int columNumber = 1;
/**
* 创建表头
* @return
*/
public static void createTableHeader()
{
HSSFHeader header = demoSheet.getHeader();
header.setCenter("世界五百强企业名次表");
HSSFRow headerRow = demoSheet.createRow((short) 0);
for(int i = 0;i < cellNumber;i++)
{
HSSFCell headerCell = headerRow.createCell((short) i);
headerCell.setCellType(HSSFCell.CELL_TYPE_STRING);
headerCell.setCellValue(tableHeader[i]);
}
}
/**
* 创建行
* @param cells
* @param rowIndex
*/
public static void createTableRow(List<String> cells,short rowIndex)
{
//创建第rowIndex行
HSSFRow row = demoSheet.createRow((short) rowIndex);
for(int i = 0;i < cells.size();i++)
{
//创建第i个单元格
HSSFCell cell = row.createCell(i);
if(cell.getCellType()!=1){
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
}
//新增的四句话,设置CELL格式为文本格式
HSSFCellStyle cellStyle2 = demoWorkBook.createCellStyle();
HSSFDataFormat format = demoWorkBook.createDataFormat();
cellStyle2.setDataFormat(format.getFormat("@"));
cell.setCellStyle(cellStyle2);
cell.setCellValue(cells.get(i));
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
}
}
/**
* USE:用于获取Cachetable的数据。。。假数据。到时候:你连接数据库的到List<Cachetable>的数据就行了。 共生成
* 100条数据.相当于100行
*
* @return
*/
public List<Cachetable> getDate() {
List<Cachetable> cacheList = new ArrayList<Cachetable>();
for (int j = 0; j < 300; j++) {
Cachetable tb = new Cachetable();
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("what are you doing?");
tb.setDoctets("who are you?");
tb.setSstart("Oh sure!");
tb.setProt("One");
tb.setTos("two");
tb.setSrcas("three");
tb.setDstas("four");
tb.setPduversion("不知道");
cacheList.add(tb);
}
return cacheList;
}
/**
* 创建整个Excel表
* @throws SQLException
*
*/
public void createExcelSheet() throws SQLException{
createTableHeader();
int rowIndex=1;
List<Cachetable> list=getDate();
for(int j=0;j<list.size();j++){
List<String> listRead=new ArrayList<String>();
for(int i=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++;
}
}
/**
* 导出表格
* @param sheet
* @param os
* @throws IOException
*/
public void exportExcel(HSSFSheet sheet,OutputStream os) throws IOException
{
sheet.setGridsPrinted(true);
HSSFFooter footer = sheet.getFooter();
footer.setRight("Page " + HSSFFooter.page() + " of " +
HSSFFooter.numPages());
demoWorkBook.write(os);
}
public static void main(String[] args) {
String fileName = "f:\\世界五百强企业名次表.xls";
FileOutputStream fos = null;
try {
ExcelOut pd = new ExcelOut();
pd.createExcelSheet();
fos = new FileOutputStream(fileName);
pd.exportExcel(demoSheet,fos);
JOptionPane.showMessageDialog(null, "表格已成功导出到 : "+fileName);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "表格导出出错,错误信息 :"+e+"\n错误原因可能是表格已经打开。");
e.printStackTrace();
} finally {
try {
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
说明:
1)有关数据库连接,如果操作到数据库的话,在遍历数据库时用getDate这个方法遍历就可以啦,那么插入的数据就不是定值了,而是数据库中的值哦,具体操作数据库的步骤,我不用说,你懂得
2)有关涉及更改EXCEL的CELL格式为字符串,如图一般情况下大家导出的EXCEL表格CELL格式通常是常规的
![](https://i-blog.csdnimg.cn/blog_migrate/fdea315e1d4cbfe450ffee9e5caf0814.png)
这个问题,估计已经不止一两个朋友在网上问过,我至今没有看到一个满意的答案,通常大家都是想到既然是设置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("@"));
//HSSFDataFormat.getBuiltinFormat("text"));--这也可以设置为文本格式
cell.setCellStyle(cellStyle2);
看最终导出效果图吧,点击任何一个CELL右键设置单元格格式
![](https://i-blog.csdnimg.cn/blog_migrate/122e917c85319f80a99aba31e47e1e77.png)
JOptionPane.showMessageDialog(null, "表格已成功导出到 : "+fileName);这句话有点意思
剩下的设置小数、百分比、货币、日期、科学计数法和中文大写这些将在下面一一写出
以下将要介绍的每一种都会用到这三行中的变量
HSSFWorkbook demoWorkBook = new HSSFWorkbook();
HSSFSheet demoSheet = demoWorkBook.createSheet("The World's 500 Enterprises");
HSSFCell cell = demoSheet.createRow(0).createCell(0);
第一种:日期格式
cell.setCellValue(new Date(2008,5,5));
//set date format
HSSFCellStyle cellStyle = demoWorkBook.createCellStyle();
HSSFDataFormat format= demoWorkBook.createDataFormat();
cellStyle.setDataFormat(format.getFormat("yyyy年m月d日"));
cell.setCellStyle(cellStyle);
第二种:保留两位小数格式
cell.setCellValue(1.2);
HSSFCellStyle cellStyle = demoWorkBook.createCellStyle();
cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00"));
cell.setCellStyle(cellStyle);
这里与上面有所不同,用的是HSSFDataFormat.getBuiltinFormat()方法,之所以用这个,是因为0.00是Excel内嵌的格式,完整的Excel内嵌格式列表大家可以看这个窗口中的自定义列表:
这里就不一一列出了
第三种:货币格式
cell.setCellValue(20000);
HSSFCellStyle cellStyle = demoWorkBook.createCellStyle();
HSSFDataFormat format= demoWorkBook.createDataFormat();
cellStyle.setDataFormat(format.getFormat("¥#,##0"));
cell.setCellStyle(cellStyle);
第四种:百分比格式
cell.setCellValue(20);
HSSFCellStyle cellStyle = demoWorkBook.createCellStyle();
cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00%"));
cell.setCellStyle(cellStyle);
此种情况跟第二种一样
第五种:中文大写格式
cell.setCellValue(20000);
HSSFCellStyle cellStyle = demoWorkBook.createCellStyle();
HSSFDataFormat format= demoWorkBook.createDataFormat();
cellStyle.setDataFormat(format.getFormat("[DbNum2][$-804]0"));
cell.setCellStyle(cellStyle);
第六种:科学计数法格式
cell.setCellValue(20000);
HSSFCellStyle cellStyle = demoWorkBook.createCellStyle();
cellStyle.setDataFormat( HSSFDataFormat.getBuiltinFormat("0.00E+00"));
cell.setCellStyle(cellStyle);
此种情况也与第二种情况一样
java.lang.ClassNotFoundException:org.apache.xerces.parsers.SAXParser
转自http://blog.csdn.net/luka2008/article/details/8203915
用SAX解析XML.
String vendorParserClass= "org.apache.xerces.parsers.SAXParser";
XMLReader reader = XMLReaderFactory.createXMLReader(vendorParserClass);
抛出异常:java.lang.ClassNotFoundException:org.apache.xerces.parsers.SAXParser
原因:未在classpath中加入xercesImpl.jar.
但如果改为:XMLReader reader = XMLReaderFactory.createXMLReader();
程序能正常运行。此时程序创建的是一个默认的XMLReader。
如果系统的org.xml.sax.driver i没有被指定为特定的service API:org.xml.sax.driver , org.xml.sax.helpers.此时XMLReaderFactory.createXMLReader 将会使用由SAX Parser指定的默认的XMLReader class (在SUN JDK5, 默认的类是com.sun.org.apache.xerces.internal.parsers.SAXParser.)因此,如果应用程序改变了系统的 org.xml.sax.driver 属性,指向了org.apache.xerces.parsers.SAXParser, 将会产生ClassNotFoundException.
如果不添加xercesImpl.jar的解决方法是:在程序中如果要获取 XMLReader,则不要设定系统的org.xml.sax.driver 属性,或者使用如下的回退机制:
catch (Exception e) {
try {
// If unable to create an instance, let's try to use
// the XMLReader from JAXP
if (m_parserFactory == null) {
m_parserFactory = SAXParserFactory.newInstance();
m_parserFactory.setNamespaceAware(true);
}
reader = m_parserFactory.newSAXParser().getXMLReader();
Note :that it is generally not a good idea to hard code a reference com.sun.org.apache.xerces.internal.parsers.SAXParser in your application, because the class might not be available when JDK upgrades or in other distributions of JDK .
poi 写大数据库zip bomb异常解决
ZipSecureFile.setMinInflateRatio(0.001)