一.POI簡(jiǎn)介 Jakarta POI 是apache的子項(xiàng)目,目標(biāo)是處理ole2對(duì)象。它提供了一組操縱Windows文檔的Java API 目前比較成熟的是HSSF接口,處理MS Excel(97-2002)對(duì)象。它不象我們僅僅是用csv生成的沒(méi)有格式的可以由Excel轉(zhuǎn)換的東西,而是真正的Excel對(duì)象,你可以控制一些屬性如sheet,cell等等。 二.HSSF概況 HSSF 是Horrible SpreadSheet Format的縮寫,也即“討厭的電子表格格式”。也許HSSF的名字有點(diǎn)滑稽,就本質(zhì)而言它是一個(gè)非常嚴(yán)肅、正規(guī)的API。通過(guò)HSSF,你可以用純Java代碼來(lái)讀取、寫入、修改Excel文件。 HSSF 為讀取操作提供了兩類API:usermodel和eventusermodel,即“用戶模型”和“事件-用戶模型”。前者很好理解,后者比較抽象,但操作效率要高得多。 三.開(kāi)始編碼 1 . 準(zhǔn)備工作 要求:JDK 1.4+POI開(kāi)發(fā)包 可以到 http://www./dyn/closer.cgi/jakarta/poi/ 最新的POI工具包 2 . EXCEL 結(jié)構(gòu) HSSFWorkbook excell 文檔對(duì)象介紹 3 .具體用法實(shí)例 (采用 usermodel ) 如何讀Excel 讀取Excel文件時(shí),首先生成一個(gè)POIFSFileSystem對(duì)象,由POIFSFileSystem對(duì)象構(gòu)造一個(gè)HSSFWorkbook,該HSSFWorkbook對(duì)象就代表了Excel文檔。下面代碼讀取上面生成的Excel文件寫入的消息字串:
將excel的第一個(gè)表單第一行的第一個(gè)單元格的值寫成“a test”。 代碼 POI 主頁(yè):http://jakarta./poi/, 初學(xué)者如何快速上手使用POI HSSF http://jakarta./poi/hssf/quick-guide.html 。 代碼例子 http://blog./user1/6749/archives/2005/18347.html 里面有很多例子代碼,可以很方便上手。
POI的中級(jí)應(yīng)該用 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);沖突 只會(huì)換行 不會(huì)設(shè)置列寬 package testpoi; imp imp imp imp imp imp imp imp /** * 將某SHEET頁(yè)中的某幾行復(fù)制到某SHEET頁(yè)的某幾行中。抱括被合并了的單元格。 */ 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頁(yè)名稱 * @param pTargetSheetName 目標(biāo)sheet頁(yè)名稱 * @param pStartRow 源sheet頁(yè)中的起始行 * @param pEndRow 源sheet頁(yè)中的結(jié)束行 * @param pPosition 目標(biāo)sheet頁(yè)中的開(kāi)始行 */ public static void copyRows(HSSFWorkbook wb, String pSourceSheetName, String pTargetSheetName, int intStartRow, int intEndRow, int intPosition) { // EXECL中的行是從1開(kāi)始的,而POI中是從0開(kāi)始的,所以這里要減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這個(gè)函數(shù)的用途在后面說(shuō)明 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對(duì)Excel公式的支持是相當(dāng)好的,但是有一個(gè)問(wèn)題,如果公式里面的函數(shù)不帶參數(shù),比如now()或today(), * 那么你通過(guò)getCellFormula()取出來(lái)的值就是now(ATTR(semiVolatile))和today(ATTR(semiVolatile)), * 這樣的值寫入Excel是會(huì)出錯(cuò)的,這也是我上面copyRow的函數(shù)在寫入公式前要調(diào)用parseFormula的原因, * parseFormula這個(gè)函數(shù)的功能很簡(jiǎn)單,就是把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); } } |
|