Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。.NET的开发人员则可以利用NPOI (POI for .NET) 来存取 Microsoft Office文档的功能。
提示:下文代码示例有Java和Kotlin形式
PS: 目前不确定此库能否在Android平台上使用,但从Github上的搜索结果来看,应该需要移植
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格式档案的功能。
目前只研究了读写表格的相关操作,至于Word等其他文件还没有细致研究,之后有研究了再补充了..
读写Excel
首先,先引入依赖
<!--xls(03)--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.0.0</version> </dependency> <!--xlsx(07)--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.0.0</version> </dependency>
poi是只支持xls格式,而poi-ooxml则可以支持xlsx格式
1.读取excel文件数据
上面我们也是知道,由于存在两种格式,所以我们的写法上得注意一下
XSSFWorkbook对应xls文件HSSFWorkbook对应xlsx文件
由于XSSFWorkbook和HSSFWorkbook都是实现的Workbook接口,所以可利用到多态的原理来编写代码,达到兼容写法
fun main(args: Array<String>) { val file = File("D:\download\test.xlsx") var workbook: Workbook? = null if (file.extension.toLowerCase() == "xlsx") { //xlsx workbook = XSSFWorkbook(file) } if (file.extension.toLowerCase() == "xls") { //xls workbook = HSSFWorkbook(FileInputStream(file)) } workbook?.let { val sheet = workbook.getSheetAt(0) //读取第一行第一列单元格数据 val firstColumn = sheet.getRow(0).first() //需要判断一下但单元格的类型 if (firstColumn.cellType == CellType.STRING) { println(firstColumn.stringCellValue) } workbook.close() } }
PS:就是觉得有些神奇的是,XSSFWorkbook构造函数可以接收File类型的对象参数,而HSSFWorkbook只能接收FileInputSteam
2.创建execl文件数据
val file = File("D:\download\myoutput.xlsx") val workbook: Workbook = XSSFWorkbook() //val workbook: Workbook = HSSFWorkbook() val sheet = workbook.createSheet("sheet0") val row = sheet.createRow(0) val cell = row.createCell(0) cell.cellType = CellType.STRING cell.setCellValue("hello world") //输出到文件 workbook.write(FileOutputStream(file)) workbook.close()
效果:

读写Word
可以查看此教程Apache POI Word(docx) 入门示例教程
暂无需求,还没有细研究
除此之外,可以选择Word模板然后注入对应的数据进去,推荐使用Poi-tl Documentation
补充-EXCEL常用操作方法
1、得到Excel常用对象
POIFSFileSystem fs=newPOIFSFileSystem(new FileInputStream("d:/test.xls")); //得到Excel工作簿对象 HSSFWorkbook wb = new HSSFWorkbook(fs); //得到Excel工作表对象 HSSFSheet sheet = wb.getSheetAt(0); //得到Excel工作表的行 HSSFRow row = sheet.getRow(0); //得到Excel工作表指定行的单元格 HSSFCell cell = row.getCell(0); //得到单元格样式 cellStyle = cell.getCellStyle();
2、建立Excel常用对象
HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet("new sheet"); HSSFRow row = sheet.createRow((short)0); HSSFCell cell = sheet.createCell((short)0); cellStyle = wb.createCellStyle(); //指定单元格样式和值 cell.setCellStyle(cellStyle); cell.setCellValue(1);
3、sheet相关
//设置sheet名称 wb.setSheetName(0, "12" + "月合同到期"); //取得sheet的数目 wb.getNumberOfSheets(); //新建名称为Output的sheet HSSFSheet sheet = wb.createSheet("Output"); //根据index取得sheet对象 HSSFSheet sheet = wb.getSheetAt(0); //选中指定的工作表 sheet.setSelected(true);
4、有效的行,单元格个数
//取得有效的行数 int rowcount = sheet.getLastRowNum(); //取得一行的有效单元格个数 row.getLastCellNum();
5、单元格值类型读写
//根据单元格不同属性返回字符串数值 public String getCellStringValue(HSSFCell cell) { String cellValue = ""; switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_STRING://字符串类型 cellValue = cell.getStringCellValue(); if(cellValue.trim().equals("")||cellValue.trim().length()<=0) { cellValue=" "; } break; case HSSFCell.CELL_TYPE_NUMERIC: //数值类型 cellValue = String.valueOf(cell.getNumericCellValue()); break; case HSSFCell.CELL_TYPE_FORMULA: //公式 cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC); cellValue = String.valueOf(cell.getNumericCellValue()); break; case HSSFCell.CELL_TYPE_BLANK: cellValue=" "; break; case HSSFCell.CELL_TYPE_BOOLEAN: break; case HSSFCell.CELL_TYPE_ERROR: break; default: break; } return cellValue; } //设置单元格为STRING类型 cell.setCellType(HSSFCell.CELL_TYPE_STRING); //设置单元格的值---有重载 cell.setCellValue(value);

POI CellType类型有以下几种
| CellType类型 | 值 |
|---|---|
| CELL_TYPE_NUMERIC | 数值型 0 |
| CELL_TYPE_STRING | 字符串型 1 |
| CELL_TYPE_FORMULA | 公式型 2 |
| CELL_TYPE_BLANK | 空值 3 |
| CELL_TYPE_BOOLEAN | 布尔型 4 |
| CELL_TYPE_ERROR | 错误 5 |
使用POI读取单元格的数据有两种方式:
- 通过
setCellType将单元格类型设置为字符串,然后通过getRichStringCellValue读取该单元格数据,然后将读取到的字符串转换为对应的类型, - 通过
getCellType获取单元格类型,然后通过对应的getcellvalue方法读取该单元格数据,如:getNumericCellValue
6、设置列宽、行高
sheet.setColumnWidth((short)column,(short)width); row.setHeight((short)height);
//POI设置自适应列宽sheet.autoSizeColumn(i); (版本不能太老) sheet.autoSizeColumn(i, true);(合并的单元格使用) sheet.setColumnWidth(i, “列名”.getBytes().length*2*256);(中文适用) 公式单元格自适应的是公式,将值算出后再设置: HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet.getWorkbook()); CellValue cell71Val = evaluator.evaluate(cell71); cell71.setCellValue(cell71Val.getNumberValue());
//调整单元格宽度 sheet.setAutobreaks(true); sheet.setColumnWidth((short)i,colsWidth[i]); //设定单元格长度 sheet.autoSizeColumn((short) i);//自动根据长度调整单元格长度
7、添加区域,合并单元格
//合并从第rowFrom行columnFrom列 Region region = new Region((short)rowFrom,(short)columnFrom,(short)rowTo ,(short)columnTo); sheet.addMergedRegion(region);// 到rowTo行columnTo的区域 // 获得一个 sheet 中合并单元格的数量 int sheetmergerCount = sheet.getNumMergedRegions();
8、常用单元格边框格式
HSSFCellStyle style = wb.createCellStyle(); style.setBorderBottom(HSSFCellStyle.BORDER_DOTTED);//下边框 style.setBorderLeft(HSSFCellStyle.BORDER_DOTTED);//左边框 style.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框 style.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框

其中边框类型分为以下几种:
| 边框范例图 | 对应的静态值 |
|---|---|
![]() |
HSSFCellStyle. BORDER_DOTTED |
![]() |
HSSFCellStyle. BORDER_HAIR |
![]() |
HSSFCellStyle. BORDER_DASH_DOT_DOT |
![]() |
HSSFCellStyle. BORDER_DASH_DOT |
![]() |
HSSFCellStyle. BORDER_DASHED |
![]() |
HSSFCellStyle. BORDER_THIN |
![]() |
HSSFCellStyle. BORDER_MEDIUM_DASH_DOT_DOT |
![]() |
HSSFCellStyle. BORDER_SLANTED_DASH_DOT |
![]() |
HSSFCellStyle. BORDER_MEDIUM_DASH_DOT |
![]() |
HSSFCellStyle. BORDER_MEDIUM_DASHED |
![]() |
HSSFCellStyle. BORDER_MEDIUM |
![]() |
HSSFCellStyle. BORDER_THICK |
![]() |
HSSFCellStyle. BORDER_DOUBLE |
9、设置字体和内容位置
HSSFFont font = wb.createFont(); font.setFontName("华文行楷");//设置字体名称 font.setFontHeightInPoints((short) 11); //字号 font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL); //加粗 font.setColor(HSSFColor.RED.index); //设置字体颜色 font.setUnderline(FontFormatting.U_SINGLE); //设置下划线 font.setTypeOffset(FontFormatting.SS_SUPER);//设置上标下标 font.setStrikeout(true); //设置删除线 style.setFont(font); style.setAlignment(HSSFCellStyle.ALIGN_CENTER);//左右居中 style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//上下居中 style.setRotation(short rotation);//单元格内容的旋转的角度 Style.setWrapText(true); //设置excel单元格中的内容换行 HSSFDataFormat df = wb.createDataFormat(); style1.setDataFormat(df.getFormat("0.00%"));//设置单元格数据格式 cell.setCellStyle(style);
10、在工作单中清空行数据,调整行位置
HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet("row sheet"); // Create various cells and rows for spreadsheet. // Shift rows 6 - 11 on the spreadsheet to the top (rows 0 - 5) sheet.shiftRows(5, 10, -5);
11、填充和颜色设置
HSSFCellStyle style = wb.createCellStyle(); style.setFillBackgroundColor(HSSFColor.AQUA.index); style.setFillPattern(HSSFCellStyle.BIG_SPOTS); HSSFCell cell = row.createCell((short) 1); cell.setCellValue("X"); style = wb.createCellStyle(); style.setFillForegroundColor(HSSFColor.ORANGE.index); style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); cell.setCellStyle(style);
12、工作表的放大缩小
sheet.setZoom(1,2); // 50 percent magnification sheet.setZoom(75); //75% scale
13. 使用公式
cell.setCellType(XSSFCell.CELL_TYPE_FORMULA); cell.setCellFormula("SUM(C2:C3)" ); //给单元格设公式
14. 设置超链接
cell.setCellFormula("hyperlink("http://www.yiibai.com/testng/","testng")");
15、插入图片
public static void test1(){ FileOutputStream fileOut = null; BufferedImage bufferImg = null; try { ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); //加载图片 bufferImg = ImageIO.read(new File(picture)); ImageIO.write(bufferImg, "jpg", byteArrayOut); HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet("sheet1"); HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); HSSFClientAnchor anchor = new HSSFClientAnchor(0,0,1023,255,(short) 0,0,(short)4,37); //插入图片 1 patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG)); //图片2 anchor = new HSSFClientAnchor(500, 0, 0, 0,(short) 5, 1, (short) 9, 38); patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG)); fileOut = new FileOutputStream( filepath+"/excel.xls"); // 输出文件 wb.write(fileOut); System.out.println("test1"); } catch (Exception e) { e.printStackTrace(); } } public static void test3(){ FileOutputStream fileOut = null; BufferedImage bufferImg = null; try { ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); //加载图片 bufferImg = ImageIO.read(new File(picture)); ImageIO.write(bufferImg, "jpg", byteArrayOut); XSSFWorkbook wb = new XSSFWorkbook(); XSSFSheet sheet1 = wb.createSheet("sheet1"); XSSFDrawing drawing = sheet1.createDrawingPatriarch(); XSSFClientAnchor anchor = new XSSFClientAnchor(0,0,1023,255,(short) 0,0,(short)10,10); //插入图片 1 drawing.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG)); fileOut = new FileOutputStream( filepath+ "/excel2.xlsx"); // 输出文件 wb.write(fileOut); System.out.println("test3"); } catch (Exception e) { e.printStackTrace(); } }
16. 从Excel文件提取图片
public static void testread(){ InputStream inp; try { inp = new FileInputStream(filepath+"/excel.xls"); HSSFWorkbook workbook = new HSSFWorkbook(inp);//读取现有的Excel文件 List<HSSFPictureData> pictures = workbook.getAllPictures(); for(int i=0;i<pictures.size();i++){ HSSFPictureData pic=pictures.get(i); String ext = pic.suggestFileExtension(); if (ext.equals("jpeg"))//判断文件格式,依照实际图片格式设置 { FileOutputStream png=new FileOutputStream(filepath +"\Apache.jpg"); png.write(pic.getData()); png.close();//保存图片 System.out.println("test11"); } } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }