poi简介:
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程式对Microsoft Office格式档案读和写的功能。 .NET的开发人员则可以利用NPOI (POI for .NET) 来存取 POI 的功能。
结构
- HSSF - 提供读写Microsoft Excel XLS格式档案的功能。
- XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。
- HWPF - 提供读写Microsoft Word DOC格式档案的功能。
- HSLF - 提供读写Microsoft PowerPoint格式档案的功能。
- HDGF - 提供读Microsoft Visio格式档案的功能。
- HPBF - 提供读Microsoft Publisher格式档案的功能。
- HSMF - 提供读Microsoft Outlook格式档案
操纵excel2003的类大多在hssf包中。
由于poi只提供了复制sheet的方法没有提供复制row的方法,在这里先贴出复制row的方法,以便今后查阅使用。
1 /** 2 * 复制行 ,在poi中excel的sheet,row,cell都从0开始 3 * 4 * @param startRowIndex 5 * 起始行 6 * @param endRowIndex 7 * 结束行 8 * @param rowNum 9 * 移动行数,大于0为向下复制,小于0为向上复制 10 */ 11 private static void copyRows(HSSFSheet sheet,int startRow, int endRow, int rowNum) { 12 int pStartRow = startRow ; 13 int pEndRow = endRow ; 14 int targetRowFrom; 15 int targetRowTo; 16 int columnCount; 17 CellRangeAddress region = null; 18 int i; 19 int j; 20 21 if (pStartRow < 0 && pEndRow < 0) { 22 return; 23 } else if (pStartRow < 0) { 24 pStartRow = 0; 25 } else if (pEndRow < 0) { 26 pEndRow = 0; 27 } 28 if (pStartRow>pEndRow) { 29 int x = pEndRow; 30 pEndRow = pStartRow; 31 pStartRow = x; 32 } 33 34 for (i = sheet.getNumMergedRegions()-1 ; i >=0 ; i--) { 35 region = sheet.getMergedRegion(i); 36 if ((region.getFirstRow() >= pStartRow) && (region.getLastRow() <= pEndRow)) { 37 targetRowFrom = region.getFirstRow() + rowNum; 38 targetRowTo = region.getLastRow() + rowNum; 39 CellRangeAddress newRegion = region.copy(); 40 newRegion.setFirstRow(targetRowFrom); 41 newRegion.setFirstColumn(region.getFirstColumn()); 42 newRegion.setLastRow(targetRowTo); 43 newRegion.setLastColumn(region.getLastColumn()); 44 sheet.addMergedRegion(newRegion); 45 } 46 } 47 for (i = pEndRow; i >= pStartRow; i--) { 48 HSSFRow sourceRow = sheet.getRow(i); 49 columnCount = sourceRow.getLastCellNum(); 50 if (sourceRow != null) { 51 HSSFRow newRow = sheet.createRow(i + rowNum); 52 newRow.setHeight(sourceRow.getHeight()); 53 for (j = 0; j < columnCount; j++) { 54 HSSFCell templateCell = sourceRow.getCell(j); 55 if (templateCell != null) { 56 HSSFCell newCell = newRow.createCell(j); 57 copyCell(templateCell, newCell); 58 } 59 } 60 } 61 } 62 } 63 64 private static void copyCell(HSSFCell srcCell, HSSFCell distCell) { 65 distCell.setCellStyle(srcCell.getCellStyle()); 66 if (srcCell.getCellComment() != null) { 67 distCell.setCellComment(srcCell.getCellComment()); 68 } 69 int srcCellType = srcCell.getCellType(); 70 distCell.setCellType(srcCellType); 71 if (srcCellType == HSSFCell.CELL_TYPE_NUMERIC) { 72 if (HSSFDateUtil.isCellDateFormatted(srcCell)) { 73 distCell.setCellValue(srcCell.getDateCellValue()); 74 } else { 75 distCell.setCellValue(srcCell.getNumericCellValue()); 76 } 77 } else if (srcCellType == HSSFCell.CELL_TYPE_STRING) { 78 distCell.setCellValue(srcCell.getRichStringCellValue()); 79 } else if (srcCellType == HSSFCell.CELL_TYPE_BLANK) { 80 // nothing21 81 } else if (srcCellType == HSSFCell.CELL_TYPE_BOOLEAN) { 82 distCell.setCellValue(srcCell.getBooleanCellValue()); 83 } else if (srcCellType == HSSFCell.CELL_TYPE_ERROR) { 84 distCell.setCellErrorValue(srcCell.getErrorCellValue()); 85 } else if (srcCellType == HSSFCell.CELL_TYPE_FORMULA) { 86 distCell.setCellFormula(srcCell.getCellFormula()); 87 } else { // nothing29 88 89 } 90 }
sheet.shiftRows(int startRow, int endRow, int n); //startRow与endRow用于选定移动区域,n用于指定向上(负数)或向下移动的行数,目标区域将被覆盖,原区域将清空。
excel中的样式使用起来有些问题:
1、最多创建3954个HSSFCellStyle对象
2、HSSFCellStyle对象无法复用,多个cell引用同一个style,这些cell就是相同的style。
cell.setCellStyle(style)后,若改变style的值,cell的样式会相应改变。
在做项目中,HSSFCellStyle对象的个数过多,于是想到复用,结果所有的单元格都是相同的背景色。
1 //在D盘新建一个excel2003文件aaa.xls,给sheet1中的单元格填值,最好从A到H列的1到10行单元格都填入如下公式:=COLUMN()+8*(ROW()-1) 2 public static void main(String[] args) throws IOException { 3 File file1 = new File("D:\\aaa.xls"); 4 File file2= new File("D:\\bbb.xls"); 5 InputStream is = new FileInputStream(file1); 6 OutputStream os = new FileOutputStream(file2);// 取得输出流 7 HSSFWorkbook wb = new HSSFWorkbook(is); 8 is.close(); 9 HSSFSheet sheet; 10 HSSFRow row; 11 HSSFCell cell; 12 sheet=wb.getSheetAt(0); 13 int lastRowNum; 14 short x = 0; 15 if (sheet!=null) { 16 lastRowNum=sheet.getLastRowNum(); 17 for (int rowIndex = 0; rowIndex <= lastRowNum; rowIndex++) { 18 row= sheet.getRow(rowIndex); 19 if (row!=null) { 20 short lastCellNum = row.getLastCellNum(); 21 for (int celIndex = 0; celIndex <= lastCellNum; celIndex++) { 22 cell = row.getCell(celIndex); 23 if (cell!=null) { 24 HSSFCellStyle style = wb.createCellStyle();//最多3954个HSSFCellStyle对象 25 style.setFillForegroundColor(x); 26 cell.setCellValue(x); 27 x++; 28 style.setFillPattern((short) 1); 29 cell.setCellStyle(style); 30 } 31 } 32 } 33 } 34 } 35 wb.write(os); 36 os.flush(); 37 os.close(); 38 } 39 //HSSFWorkbook,HSSFSheet,HSSFRow,HSSFCell的getxxx方法,都相应有createxxx方法 40 //HSSFWorkbook,HSSFSheet有相应的构造方法
运行这段代码你会发现,x从8到65才是真正的有用值,从8开始前几个是常用颜色,65是无颜色。
将代码:HSSFCellStyle style = wb.createCellStyle();移动到for循环之前,你会发现都是一样的颜色了。
字体颜色是一样的,加上如下代码你会发现字都没了,不是没了,只是字体颜色和背景色一样罢了。
Font font = wb.createFont();
font.setColor(x);
style.setFont(font);
1 //获取单元格一般样式的方法: 2 HSSFCellStyle cellstyle ; //单元格样式 3 cellstyle = cell.getCellStyle(); //获取cellstyle 4 short borderBottom = cellstyle.getBorderBottom(); //下边框 5 short borderLeft = cellstyle.getBorderLeft(); //左边框 6 short borderRight = cellstyle.getBorderRight(); //右边框 7 short borderTop = cellstyle.getBorderTop(); //上边框 8 short background = cellstyle.getFillBackgroundColor(); //背景色 9 short foreground = cellstyle.getFillForegroundColor(); //前景色 10 short alignment = cellstyle.getAlignment(); //水平对齐 11 short verAlignment = cellstyle.getVerticalAlignment(); //垂直对齐 12 boolean wrapText = cellstyle.getWrapText(); //自动换行 13 HSSFFont font = cellstyle.getFont(wb); //Font 14 short color = font.getColor(); //颜色 15 String fontName = font.getFontName(); //字体 16 short fontHeight = font.getFontHeightInPoints(); //字号 17 short boldWeight = font.getBoldweight(); //字形 18 //对应的有相同的set方法
你也许在复制行的代码中注意到了,
在excel中日期也是以数字形式存储,
需要借助于HSSFDateUtil.isCellDateFormatted(cell)判断是否为日期型。
然后通过cell.getDateCellValue()来获取日期单元格的日期
如果你需要将excel的信息都存入数据库中,你也许需要将Date转成String:
Date D_temp = cell.getDateCellValue();
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS",java.util.Locale.US);//"yyyy-MM-dd HH:mm:ss SSS"可自行修改
String cellValue = sdf.format(D_temp);
回转:
Date D_temp = sdf.parse(cellValue);
有时需要获取行高和列宽:
row.getHeightInPoints(); //Excel获取行高所使用单位为Point(点)
sheet.getColumnWidth(colIndex); //列宽使用单位为Character(字符)的1/256
关于点,字符,像素的换算关系,本人没有弄透。
行高对应像素:Row Height(point)=Height Pixels * 0.75
在复制行的方法中,对于合并单元格应该很好理解。
合并单元格看做一个方形区域,用CellRangeAddress对象表示,它有4个属性:FirstRow,LastRow,FirstColumn,LastColumn
构造方法:CellRangeAddress cra = new CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol);