一.POI簡介 Jakarta POI 是apache的子項目,目標是處理ole2對象。它提供了一組操縱Windows文檔的Java API 目前比較成熟的是HSSF接口,處理MS Excel(97-2002)對象。它不象我們僅僅是用csv生成的沒有格式的可以由Excel轉(zhuǎn)換的東西,而是真正的Excel對象,你可以控制一些屬性如sheet,cell等等。 二.HSSF概況 HSSF 是Horrible SpreadSheet Format的縮寫,也即“討厭的電子表格格式”。也許HSSF的名字有點滑稽,就本質(zhì)而言它是一個非常嚴肅、正規(guī)的API。通過HSSF,你可以用純Java代碼來讀取、寫入、修改Excel文件。 HSSF 為讀取操作提供了兩類API:usermodel和eventusermodel,即“用戶模型”和“事件-用戶模型”。前者很好理解,后者比較抽象,但操作效率要高得多。 1 . 準備工作 要求:JDK 1.4+POI開發(fā)包 可以到 http://www.apache.org/dyn/closer.cgi/jakarta/poi/ 最新的POI工具包 2 . EXCEL 結(jié)構(gòu) HSSFWorkbook excell 文檔對象介紹 如何讀Excel 讀取Excel文件時,首先生成一個POIFSFileSystem對象,由POIFSFileSystem對象構(gòu)造一個HSSFWorkbook,該HSSFWorkbook對象就代表了Excel文檔。下面代碼讀取上面生成的Excel文件寫入的消息字串: 代碼
如何寫excel, 將excel的第一個表單第一行的第一個單元格的值寫成“a test”。 代碼
4 . 可參考文檔 POI 主頁:http://jakarta.apache.org/poi/, 初學者如何快速上手使用POI HSSF http://jakarta.apache.org/poi/hssf/quick-guide.html 。 代碼例子 http://blog.java-cn.com/user1/6749/archives/2005/18347.html 里面有很多例子代碼,可以很方便上手。 POI的中級應(yīng)該用 |
1、遍歷workbook
- //
load源文件 - POIFSFileSystem
fs new= POIFSFileSystem( newFileInputStream(filePath)); - HSSFWorkbook
wb new= HSSFWorkbook(fs); - for
( inti 0;= i < wb.getNumberOfSheets(); i++) { -
HSSFSheet sheet = wb.getSheetAt(i); -
( inti = sheet.getFirstRowNum(); i < sheet.getLastRowNum(); i ++) { -
HSSFRow row = sheet.getRow(i); -
(row null)!= { -
。。。操作} -
} -
} - //
目標文件 - FileOutputStream
fos new= FileOutputStream(objectPath); - //寫文件
- swb.write(fos);
- fos.close();
2、得到列和單元格
- HSSFRow
row = sheet.getRow(i); - HSSFCell
cell short)= row.getCell(( j);
3、設(shè)置sheet名稱和單元格內(nèi)容為中文
- wb.setSheetName(n,
"中文",HSSFCell.ENCODING_UTF_16); - cell.setEncoding((short)
1); - cell.setCellValue("中文");
4、單元格內(nèi)容未公式或數(shù)值,可以這樣讀寫
- cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
- cell.getNumericCellValue()
5、設(shè)置列寬、行高
- sheet.setColumnWidth((short)column,(short)width);
- row.setHeight((short)height);
6、添加區(qū)域,合并單元格
- Region
region new= Region(( short)rowFrom,(short)columnFrom,(short)rowTo,(short)columnTo); - sheet.addMergedRegion(region);
- //得到所有區(qū)域
- sheet.getNumMergedRegions()
7、常用方法
根據(jù)單元格不同屬性返回字符串數(shù)值
- public
String getCellStringValue(HSSFCell cell) { -
String cellValue = -
(cell.getCellType()) { -
HSSFCell.CELL_TYPE_STRING: -
cellValue = cell.getStringCellValue(); -
-
cellValue= " ; -
-
HSSFCell.CELL_TYPE_NUMERIC: -
cellValue = String.valueOf(cell.getNumericCellValue()); -
-
HSSFCell.CELL_TYPE_FORMULA: -
cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC); -
cellValue = String.valueOf(cell.getNumericCellValue()); -
-
HSSFCell.CELL_TYPE_BLANK: -
cellValue= " ; -
-
HSSFCell.CELL_TYPE_BOOLEAN: -
-
HSSFCell.CELL_TYPE_ERROR: -
-
-
-
} -
cellValue; -
}
8、常用單元格邊框格式
虛線HSSFCellStyle.BORDER_DOTTED
實線HSSFCellStyle.BORDER_THIN
- public
static HSSFCellStyle shortgetCellStyle( type) -
{ -
HSSFWorkbook wb = HSSFWorkbook(); -
HSSFCellStyle style = wb.createCellStyle(); -
style.setBorderBottom(type); -
style.setBorderLeft(type); -
style.setBorderRight(type); -
style.setBorderTop(type); -
style; -
}
9、設(shè)置字體和內(nèi)容位置
- HSSFFont
f = wb.createFont(); - f.setFontHeightInPoints((short)
11);//字號 - f.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);//加粗
- style.setFont(f);
- style.setAlignment(HSSFCellStyle.ALIGN_CENTER);//左右居中
- style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//上下居中
- style.setRotation(short
rotation); //單元格內(nèi)容的旋轉(zhuǎn)的角度 - HSSFDataFormat
df = wb.createDataFormat(); - style1.setDataFormat(df.getFormat("0.00%"));//設(shè)置單元格數(shù)據(jù)格式
- cell.setCellFormula(string);//給單元格設(shè)公式
- style.setRotation(short
rotation); //單元格內(nèi)容的旋轉(zhuǎn)的角度 - cell.setCellStyle(style);
10、插入圖片
論壇里看到的
- //先把讀進來的圖片放到一個ByteArrayOutputStream中,以便產(chǎn)生ByteArray
-
ByteArrayOutputStream byteArrayOut = ByteArrayOutputStream(); -
BufferedImage bufferImg = ImageIO.read( File( "ok.jpg")); -
ImageIO.write(bufferImg, - //讀進一個excel模版
- FileInputStream
fos new= FileInputStream(filePathName+ "/stencil.xlt"); - fs
= newPOIFSFileSystem(fos); - //創(chuàng)建一個工作薄
- HSSFWorkbook
wb new= HSSFWorkbook(fs); - HSSFSheet
sheet 0);= wb.getSheetAt( - HSSFPatriarch
patriarch = sheet.createDrawingPatriarch(); - HSSFClientAnchor
anchor new= HSSFClientAnchor( 0,0,1023,255,(short)0,0,(short)10,10); - patriarch.createPicture(anchor
, wb.addPicture(byteArrayOut.toByteArray(),HSSFWorkbook.PICTURE_TYPE_JPEG));
11、設(shè)置列自動換行
單元格拷貝示例:
package testpoi; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.apache.poi.hssf.usermodel.HSSFCell; 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.Region; import org.apache.poi.poifs.filesystem.POIFSFileSystem; /** * 將某SHEET頁中的某幾行復(fù)制到某SHEET頁的某幾行中。抱括被合并了的單元格。 */ public class RowCopy { /** * @param args * @throws IOException * @throws FileNotFoundException */ @SuppressWarnings("deprecation") public static void main(String[] args) { try { POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream( "d:\\exlsample.xls")); HSSFWorkbook wb = new HSSFWorkbook(fs); // source為源sheet 頁,target為目標sheet頁 copyRows(wb, "source", "target", 5, 6, 20); FileOutputStream fileOut = new FileOutputStream("d:\\exlsample.xls"); wb.write(fileOut); fileOut.flush(); fileOut.close(); System.out.println("Operation finished"); } catch (Exception e) { e.printStackTrace(); } } /** * @param wb HSSFWorkbook * @param pSourceSheetName 源sheet頁名稱 * @param pTargetSheetName 目標sheet頁名稱 * @param pStartRow 源sheet頁中的起始行 * @param pEndRow 源sheet頁中的結(jié)束行 * @param pPosition 目標sheet頁中的開始行 */ public static void copyRows(HSSFWorkbook wb, String pSourceSheetName, String pTargetSheetName, int intStartRow, int intEndRow, int intPosition) { // EXECL中的行是從1開始的,而POI中是從0開始的,所以這里要減1. int pStartRow = intStartRow - 1; int pEndRow = intEndRow - 1; int pPosition = intPosition - 1; HSSFRow sourceRow = null; HSSFRow targetRow = null; HSSFCell sourceCell = null; HSSFCell targetCell = null; HSSFSheet sourceSheet = null; HSSFSheet targetSheet = null; Region region = null; int cType; int i; int j; int targetRowFrom; int targetRowTo; if ((pStartRow == -1) || (pEndRow == -1)) { return; } sourceSheet = wb.getSheet(pSourceSheetName); targetSheet = wb.getSheet(pTargetSheetName); System.out.println(sourceSheet.getNumMergedRegions()); // 拷貝合并的單元格 for (i = 0; i < sourceSheet.getNumMergedRegions(); i++) { region = sourceSheet.getMergedRegionAt(i); if ((region.getRowFrom() >= pStartRow) && (region.getRowTo() <= pEndRow)) { targetRowFrom = region.getRowFrom() - pStartRow + pPosition; targetRowTo = region.getRowTo() - pStartRow + pPosition; region.setRowFrom(targetRowFrom); region.setRowTo(targetRowTo); targetSheet.addMergedRegion(region); } } // 設(shè)置列寬 for (i = pStartRow; i <= pEndRow; i++) { sourceRow = sourceSheet.getRow(i); if (sourceRow != null) { for (j = sourceRow.getLastCellNum(); j > sourceRow .getFirstCellNum(); j--) { targetSheet .setColumnWidth(j, sourceSheet.getColumnWidth(j)); targetSheet.setColumnHidden(j, false); } break; } } // 拷貝行并填充數(shù)據(jù) for (; i <= pEndRow; i++) { sourceRow = sourceSheet.getRow(i); if (sourceRow == null) { continue; } targetRow = targetSheet.createRow(i - pStartRow + pPosition); targetRow.setHeight(sourceRow.getHeight()); for (j = sourceRow.getFirstCellNum(); j < sourceRow .getPhysicalNumberOfCells(); j++) { sourceCell = sourceRow.getCell(j); if (sourceCell == null) { continue; } targetCell = targetRow.createCell(j); targetCell.setCellStyle(sourceCell.getCellStyle()); cType = sourceCell.getCellType(); targetCell.setCellType(cType); switch (cType) { case HSSFCell.CELL_TYPE_BOOLEAN: targetCell.setCellValue(sourceCell.getBooleanCellValue()); System.out.println("--------TYPE_BOOLEAN:" + targetCell.getBooleanCellValue()); break; case HSSFCell.CELL_TYPE_ERROR: targetCell .setCellErrorValue(sourceCell.getErrorCellValue()); System.out.println("--------TYPE_ERROR:" + targetCell.getErrorCellValue()); break; case HSSFCell.CELL_TYPE_FORMULA: // parseFormula這個函數(shù)的用途在后面說明 targetCell.setCellFormula(parseFormula(sourceCell .getCellFormula())); System.out.println("--------TYPE_FORMULA:" + targetCell.getCellFormula()); break; case HSSFCell.CELL_TYPE_NUMERIC: targetCell.setCellValue(sourceCell.getNumericCellValue()); System.out.println("--------TYPE_NUMERIC:" + targetCell.getNumericCellValue()); break; case HSSFCell.CELL_TYPE_STRING: targetCell .setCellValue(sourceCell.getRichStringCellValue()); System.out.println("--------TYPE_STRING:" + i + targetCell.getRichStringCellValue()); break; } } } } /** * POI對Excel公式的支持是相當好的,但是有一個問題,如果公式里面的函數(shù)不帶參數(shù),比如now()或today(), * 那么你通過getCellFormula()取出來的值就是now(ATTR(semiVolatile))和today(ATTR(semiVolatile)), * 這樣的值寫入Excel是會出錯的,這也是我上面copyRow的函數(shù)在寫入公式前要調(diào)用parseFormula的原因, * parseFormula這個函數(shù)的功能很簡單,就是把ATTR(semiVolatile)刪掉。 * @param pPOIFormula * @return */ private static String parseFormula(String pPOIFormula) { final String cstReplaceString = "ATTR(semiVolatile)"; //$NON-NLS-1$ StringBuffer result = null; int index; result = new StringBuffer(); index = pPOIFormula.indexOf(cstReplaceString); if (index >= 0) { result.append(pPOIFormula.substring(0, index)); result.append(pPOIFormula.substring(index + cstReplaceString.length())); } else { result.append(pPOIFormula); } return result.toString(); } }