zoukankan      html  css  js  c++  java
  • poi 详细讲解

    一.POI简介

    Jakarta POI 是apache的子项目,目标是处理ole2对象。它提供了一组操纵Windows文档的Java API

    目前比较成熟的是HSSF接口,处理MS Excel(97-2002)对象。它不象我们仅仅是用csv生成的没有格式的可以由Excel转换的东西,而是真正的Excel对象,你可以控制一些属性如sheet,cell等等。

    二.HSSF概况

    HSSF 是Horrible SpreadSheet Format的缩写,也即“讨厌的电子表格格式”。也许HSSF的名字有点滑稽,就本质而言它是一个非常严肃、正规的API。通过HSSF,你可以用纯Java代码来读取、写入、修改Excel文件。

    HSSF 为读取操作提供了两类API:usermodel和eventusermodel,即“用户模型”和“事件-用户模型”。前者很好理解,后者比较抽象,但操作效率要高得多。

    三.开始编码

    1 . 准备工作

    要求:JDK 1.4+POI开发包

    可以到 http://www.apache.org/dyn/closer.cgi/jakarta/poi/ 最新的POI工具包

    2 . EXCEL 结构

    HSSFWorkbook excell 文档对象介绍
    HSSFSheet excell的表单
    HSSFRow excell的行
    HSSFCell excell的格子单元
    HSSFFont excell字体
    HSSFName 名称
    HSSFDataFormat 日期格式
    在poi1.7中才有以下2项:
    HSSFHeader sheet头
    HSSFFooter sheet尾
    和这个样式
    HSSFCellStyle cell样式
    辅助操作包括
    HSSFDateUtil 日期
    HSSFPrintSetup 打印
    HSSFErrorConstants 错误信息表

    3 .具体用法实例 (采用 usermodel )

    如何读Excel

    读取Excel文件时,首先生成一个POIFSFileSystem对象,由POIFSFileSystem对象构造一个HSSFWorkbook,该HSSFWorkbook对象就代表了Excel文档。下面代码读取上面生成的Excel文件写入的消息字串:


    代码
    POIFSFileSystem fs=newPOIFSFileSystem(new FileInputStream("d:/test.xls"));    
    HSSFWorkbook  wb = new HSSFWorkbook(fs);    
      } catch (IOException e) {    
      e.printStackTrace();    
      }    
      HSSFSheet sheet = wb.getSheetAt(0);    
      HSSFRow row = sheet.getRow(0);    
      HSSFCell cell = row.getCell((short) 0);    
      String msg = cell.getStringCellValue();  
    POIFSFileSystem fs=newPOIFSFileSystem(new FileInputStream("d:/test.xls"));    
    HSSFWorkbook  wb = new HSSFWorkbook(fs);    
      } catch (IOException e) {    
      e.printStackTrace();    
      }    
      HSSFSheet sheet = wb.getSheetAt(0);    
      HSSFRow row = sheet.getRow(0);    
      HSSFCell cell = row.getCell((short) 0);    
      String msg = cell.getStringCellValue();  
    如何写excel,

    将excel的第一个表单第一行的第一个单元格的值写成“a test”。

    代码
    POIFSFileSystem fs =new POIFSFileSystem(new FileInputStream("workbook.xls"));    
      
        HSSFWorkbook wb = new HSSFWorkbook(fs);    
      
        HSSFSheet sheet = wb.getSheetAt(0);    
      
        HSSFRow row = sheet.getRow(0);    
      
        HSSFCell cell = row.getCell((short)0);    
      
        cell.setCellValue("a test");    
      
        // Write the output to a file    
      
        FileOutputStream fileOut = new FileOutputStream("workbook.xls");    
      
        wb.write(fileOut);    
      
    fileOut.close();  
    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的中级应该用
     

    1、遍历workbook
    代码
    // load源文件   
    POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(filePath));   
    HSSFWorkbook wb = new HSSFWorkbook(fs);   
    for (int i = 0; i < wb.getNumberOfSheets(); i++) {   
        HSSFSheet sheet = wb.getSheetAt(i);   
        for (int i = sheet.getFirstRowNum(); i < sheet.getLastRowNum(); i ++) {   
        HSSFRow row = sheet.getRow(i);   
                if (row != null) {   
            。。。操作}   
           }   
         }   
    // 目标文件   
    FileOutputStream fos = new FileOutputStream(objectPath);   
    //写文件   
    swb.write(fos);   
    fos.close(); 
    2、得到列和单元格
    代码
    HSSFRow row = sheet.getRow(i);   
    HSSFCell cell = row.getCell((short) j); 
    3、设置sheet名称和单元格内容为中文
    代码
    wb.setSheetName(n, "中文",HSSFCell.ENCODING_UTF_16);       
    cell.setEncoding((short) 1);   
    cell.setCellValue("中文"); 
    4、单元格内容未公式或数值,可以这样读写
    代码
    cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);   
    cell.getNumericCellValue() 

    5、设置列宽、行高
    代码
    sheet.setColumnWidth((short)column,(short)width);   
    row.setHeight((short)height); 

    6、添加区域,合并单元格
    代码
    Region region = new Region((short)rowFrom,(short)columnFrom,(short)rowTo,(short)columnTo);   
    sheet.addMergedRegion(region);   
    //得到所有区域   
    sheet.getNumMergedRegions() 
    7、常用方法
    根据单元格不同属性返回字符串数值
    代码
    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;   
        } 


    8、常用单元格边框格式
    虚线HSSFCellStyle.BORDER_DOTTED
    实线HSSFCellStyle.BORDER_THIN
    代码
    public static HSSFCellStyle getCellStyle(short type)   
        {      
           HSSFWorkbook wb = new HSSFWorkbook();   
           HSSFCellStyle style = wb.createCellStyle();   
           style.setBorderBottom(type);//下边框    
            style.setBorderLeft(type);//左边框    
            style.setBorderRight(type);//右边框    
            style.setBorderTop(type);//上边框    
           return style;   
        } 


    9、设置字体和内容位置

    代码
    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);//单元格内容的旋转的角度   
    HSSFDataFormat df = wb.createDataFormat();   
    style1.setDataFormat(df.getFormat("0.00%"));//设置单元格数据格式   
    cell.setCellFormula(string);//给单元格设公式   
    style.setRotation(short rotation);//单元格内容的旋转的角度   
    cell.setCellStyle(style);  


    10、插入图片
    论坛里看到的

    代码
    //先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray   
          ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();   
          BufferedImage bufferImg = ImageIO.read(new File("ok.jpg"));   
          ImageIO.write(bufferImg,"jpg",byteArrayOut);   
    //读进一个excel模版   
    FileInputStream fos = new FileInputStream(filePathName+"/stencil.xlt");    
    fs = new POIFSFileSystem(fos);   
    //创建一个工作薄   
    HSSFWorkbook wb = new HSSFWorkbook(fs);   
    HSSFSheet sheet = wb.getSheetAt(0);   
    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、设置列自动换行

       HSSFCellStyle cellStyle =  workbook.createCellStyle();
       cellStyle.setWrapText(true);
       sheet.setDefaultColumnStyle((short)0, cellStyle);

        设置列的宽度

       sheet.setColumnWidth((short)0,(short)9000);

      sheet.setDefaultColumnStyle((short)0, cellStyle);

      与

      sheet.setDefaultColumnWidth((short)70);冲突

      只会换行 不会设置列宽

     
    单元格拷贝示例:

    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页中的某几行复制到某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页中的结束行

    * @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);

    }

    }

    // 设置列宽

    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;

    }

    }

    // 拷贝行并填充数据

    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这个函数的用途在后面说明

    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公式的支持是相当好的,但是有一个问题,如果公式里面的函数不带参数,比如now()或today(),

    * 那么你通过getCellFormula()取出来的值就是now(ATTR(semiVolatile))和today(ATTR(semiVolatile)),

    * 这样的值写入Excel是会出错的,这也是我上面copyRow的函数在写入公式前要调用parseFormula的原因,

    * parseFormula这个函数的功能很简单,就是把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();

    }
    }

    public void exportToExcel() {
      try {
       
       ArrayList list = this.getSelectedCourseStudentsTableData();
       System.out.println("=============size:" + list.size());
       if (list != null && list.size() > 0) {

        Long tp = new Long(System.currentTimeMillis());
        String path = getApplicationBean().getFilePath()
          + "printfiles/" + tp.toString() + ".xls";
        String name=path.substring(path.lastIndexOf('/')+1,path.length());
        
        OutputStream outf = new FileOutputStream(path);
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet("StudentCource");
        sheet.setColumnWidth((short)0,(short)4000);  //设置单元格的长度
        sheet.setColumnWidth((short)3,(short)4000); 
        sheet.setColumnWidth((short)5,(short)6000); 
        sheet.setColumnWidth((short)6,(short)6000); 
        sheet.setHorizontallyCenter(true);

        HSSFRow row1 = sheet.createRow(0);

        HSSFCell cell1 = row1.createCell((short) 0);
        cell1.setEncoding(HSSFCell.ENCODING_UTF_16);// 设置编码
        cell1.setCellValue("学号");
        
        cell1 = row1.createCell((short) 1);
        cell1.setEncoding(HSSFCell.ENCODING_UTF_16);// 设置编码
        cell1.setCellValue("姓名");
        
        cell1 = row1.createCell((short) 2);
        cell1.setEncoding(HSSFCell.ENCODING_UTF_16);// 设置编码
        cell1.setCellValue("性别");
        
        cell1 = row1.createCell((short) 3);
        cell1.setEncoding(HSSFCell.ENCODING_UTF_16);// 设置编码
        cell1.setCellValue("学生类别");
        
        cell1 = row1.createCell((short) 4);
        cell1.setEncoding(HSSFCell.ENCODING_UTF_16);// 设置编码
        cell1.setCellValue("年级");
        
        cell1 = row1.createCell((short) 5);
        cell1.setEncoding(HSSFCell.ENCODING_UTF_16);// 设置编码
        cell1.setCellValue("所属学院");
        
        cell1 = row1.createCell((short) 6);
        cell1.setEncoding(HSSFCell.ENCODING_UTF_16);// 设置编码
        cell1.setCellValue("所学专业");

        ArrayList selectedCourseStudentslist = this
          .getSelectedCourseStudentsTableData();
        for (int i = 0; i < selectedCourseStudentslist.size(); i++) {
         HSSFRow row = sheet.createRow(i+1);
         PgtStatusInfo pgtStatusInfo = (PgtStatusInfo) selectedCourseStudentslist
           .get(i);
         HSSFCell cell = row.createCell((short) 0);
         cell.setCellValue(pgtStatusInfo.getStudentNo());
         cell = row.createCell((short) 1);
         cell.setEncoding(HSSFCell.ENCODING_UTF_16);
         cell.setCellValue(pgtStatusInfo.getName());
         cell = row.createCell((short) 2);
         cell.setEncoding(HSSFCell.ENCODING_UTF_16);
         cell.setCellValue(pgtStatusInfo.getSexCn());
         cell = row.createCell((short) 3);
         cell.setEncoding(HSSFCell.ENCODING_UTF_16);
         cell.setCellValue(pgtStatusInfo.getPgtTypeCn());
         cell = row.createCell((short) 4);
         cell.setEncoding(HSSFCell.ENCODING_UTF_16);
         cell.setCellValue(pgtStatusInfo.getGradeCn());
         cell = row.createCell((short) 5);
         cell.setEncoding(HSSFCell.ENCODING_UTF_16);
         cell.setCellValue(pgtStatusInfo.getBelongDeptCn());
         cell = row.createCell((short) 6);
         cell.setEncoding(HSSFCell.ENCODING_UTF_16);
         cell.setCellValue(pgtStatusInfo.getSpeCn());
        }
        wb.write(outf);
        outf.close();

        this.excelLink ="./files/printfiles/" + name;
        this.excelFileLinkVisible = true;
        this.outputFileLinkVisible = false;
       } else {
        getApplicationBean().addMessage(FacesMessage.SEVERITY_INFO,
          "导出excel内容为空!", null);
       }

      } catch (Exception e) {
       getApplicationBean().addMessage(FacesMessage.SEVERITY_ERROR,
         "导出excel操作失败!", e.getMessage());
      }
     }

  • 相关阅读:
    LINQ查询表达式(1)
    JSON是什么
    .net序列化
    wampserver
    JQuery系列(1)
    c# 数据类型转换
    并不对劲的uoj311.[UNR #2]积劳成疾
    并不对劲的uoj308.[UNR #2]UOJ拯救计划
    并不对劲的CF1349B&C:Game of Median Life
    并不对劲的复健训练-CF1329B&C:Heap Sequences
  • 原文地址:https://www.cnblogs.com/lcuzhanglei/p/2872778.html
Copyright © 2011-2022 走看看