一.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./dyn/closer.cgi/jakarta/poi/ 最新的POI工具包 2 . EXCEL 結(jié)構(gòu) HSSFWorkbook excell 文檔對象介紹 3 .具體用法實例 (采用 usermodel ) 如何讀Excel 讀取Excel文件時,首先生成一個POIFSFileSystem對象,由POIFSFileSystem對象構(gòu)造一個HSSFWorkbook,該HSSFWorkbook對象就代表了Excel文檔。下面代碼讀取上面生成的Excel文件寫入的消息字串:
將excel的第一個表單第一行的第一個單元格的值寫成“a test”。 代碼 POI 主頁:http://jakarta./poi/, 初學者如何快速上手使用POI HSSF http://jakarta./poi/hssf/quick-guide.html 。 代碼例子 http://blog./user1/6749/archives/2005/18347.html 里面有很多例子代碼,可以很方便上手。
POI的中級應該用 1、遍歷workbook 5、設(shè)置列寬、行高 6、添加區(qū)域,合并單元格
代碼
代碼 HSSFCellStyle cellStyle = workbook.createCellStyle(); 設(shè)置列的寬度 sheet.setColumnWidth((short)0,(short)9000); sheet.setDefaultColumnStyle((short)0, cellStyle); 與 sheet.setDefaultColumnWidth((short)70);沖突 只會換行 不會設(shè)置列寬 package testpoi; imp imp imp imp imp imp imp imp /** * 將某SHEET頁中的某幾行復制到某SHEET頁的某幾行中。抱括被合并了的單元格。 */ public class RowCopy { * @param args * @throws IOException * @throws FileNotFoundException */ public static void main(String[] args) { try { POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream( "d:\\exlsample.xls")); HSSFWorkbook wb = new HSSFWorkbook(fs); 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; 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;
index = pPOIFormula.indexOf(cstReplaceString); if (index >= 0) { result.append(pPOIFormula.substring(0, index)); result.append(pPOIFormula.substring(index + cstReplaceString.length())); } else { result.append(pPOIFormula); } } |
|