使用POI对EXCEL进行单元格的合并

        前段时间我们老大交给我一任务,就是让我使用POI将EXCEL中的单元格进行合并,于是我就使用了sheet.addMergedRegion(new Region(1,(short)2,5,(short)9)),简单的合并了第2-5行,和第3-10列这个区域,可是我后来了解到他进而需要我能够动态的进行单元格的合并,即最后我们可以通过java类的调用,从而传入数据可以合并哪几列。我在网上差了很多的例子,都没有很好的范例,于是我就只找了CSDN中某位博主的导出EXCEL的例子,从而进行自己的优化。

       由于导出单元格的例子是在网上找的实例,所以此篇博文标志位转载的状态,但是其中的单元格合并属于个人的编写的代码,可以供需要的人进行参考。

     首先我们编写需要传入数据的java类,并拟写构造函数

     1.Student.java

   

package com.downpro;

import java.util.Date;

public class Student {
 //定义变量
  private long id;

    private String name;

    private int age;

    private boolean sex;

    private Date birthday;
    //此处为加入部分
    private String education;
   
    private String hobby;
   
    private int bestNum;
      
    private float salary;
   
    private int jobAge;
   
  
   
 
 //无参的构造函数
    public Student() {
            //调用父函数
       super();

       // TODO Auto-generated constructor stub

    }

 
          //有参的构造函数
    public Student(long id, String name, int age, boolean sex, Date birthday,
      String education,String hobby,int bestNum,float salary,int jobAge ) {

       super();

       this.id = id;

       this.name = name;

       this.age = age;

       this.sex = sex;

       this.birthday = birthday;
      
       //此处为添加部分
       this.education=education;
      
       this.hobby=hobby;
      
       this.bestNum=bestNum;
      
       this.salary=salary;
      
       this.jobAge=jobAge;

    }

 
          //得到set和get方法
    public long getId() {

       return id;

    }

 

    public void setId(long id) {

       this.id = id;

    }

 

    public String getName() {

       return name;

    }

 

    public void setName(String name) {

       this.name = name;

    }

 

    public int getAge() {

       return age;

    }

 

    public void setAge(int age) {

       this.age = age;

    }

 

    public boolean getSex() {

       return sex;

    }

 

    public void setSex(boolean sex) {

       this.sex = sex;

    }

 

    public Date getBirthday() {

       return birthday;

    }

 

    public void setBirthday(Date birthday) {

       this.birthday = birthday;

    }
   
    //此处为添加部分
    public String getEducation() {
   return education;
  }


     public void setEducation(String education) {
   this.education = education;
  }
    
     public String getHobby() {
    return hobby;
   }


   public void setHobby(String hobby) {
    this.hobby = hobby;
   }
   
    public int getBestNum() {
     return bestNum;
    }


   public void setBestNum(int bestNum) {
     this.bestNum = bestNum;
    }
   
   
   public float getSalary() {
    return salary;
   }


      public void setSalary(float salary) {
    this.salary = salary;
   }
 
     
   public int getJobAge() {
     return jobAge;
    }


   public void setJobAge(int jobAge) {
     this.jobAge = jobAge;
    }


   


}

  2.Test.java

  

package com.downpro;

import java.io.*;

import java.lang.reflect.*;

import java.util.*;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import java.text.SimpleDateFormat;

import javax.swing.JOptionPane;

import org.apache.poi.hssf.usermodel.*;

import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hssf.util.Region;

 

/**

 * 利用开源组件POI3.0.2动态导出EXCEL文档

 * 转载时请保留以下信息,注明出处!

 * @author leno

 * @version v1.0

 * @param <T> 应用泛型,代表任意一个符合javabean风格的类

 * 注意这里为了简单起见,boolean型的属性xxx的get器方式为getXxx(),而不是isXxx()

 * byte[]表jpg格式的图片数据

 */

public class Test<T> {

 

   public void exportExcel(Collection<T> dataset, OutputStream out) {

    //将文档导出来时表格的名字
      exportExcel("测试POI导出EXCEL文档", null, dataset, out, "yyyy-MM-dd");

   }

 

   public void exportExcel(String[] headers, Collection<T> dataset,

         OutputStream out) {

      exportExcel("测试POI导出EXCEL文档", headers, dataset, out, "yyyy-MM-dd");

   }

 

   public void exportExcel(String[] headers, Collection<T> dataset,

         OutputStream out, String pattern) {

      exportExcel("测试POI导出EXCEL文档", headers, dataset, out, pattern);

   }

 

   /**

    * 这是一个通用的方法,利用了JAVA的反射机制,可以将放置在JAVA集合中并且符号一定条件的数据以EXCEL 的形式输出到指定IO设备上

    *

    * @param title

    *            表格标题名

    * @param headers

    *            表格属性列名数组

    * @param dataset

    *            需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象。此方法支持的

    *            javabean属性的数据类型有基本数据类型及String,Date,byte[](图片数据)

    * @param out

    *            与输出设备关联的流对象,可以将EXCEL文档导出到本地文件或者网络中

    * @param pattern

    *            如果有时间数据,设定输出格式。默认为"yyy-MM-dd"

    */

   @SuppressWarnings("unchecked")

   public void exportExcel(String title, String[] headers,

         Collection<T> dataset, OutputStream out, String pattern) {

      // 声明一个工作薄

      HSSFWorkbook workbook = new HSSFWorkbook();

      // 生成一个表格

      HSSFSheet sheet = workbook.createSheet(title);

      // 设置表格默认列宽度为15个字节

      sheet.setDefaultColumnWidth((short) 15);

      // 生成一个样式

      HSSFCellStyle style = workbook.createCellStyle();

      // 设置这些样式

      style.setFillForegroundColor(HSSFColor.SEA_GREEN.index);

      style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);

      style.setBorderBottom(HSSFCellStyle.BORDER_THIN);

      style.setBorderLeft(HSSFCellStyle.BORDER_THIN);

      style.setBorderRight(HSSFCellStyle.BORDER_THIN);

      style.setBorderTop(HSSFCellStyle.BORDER_THIN);

      style.setAlignment(HSSFCellStyle.ALIGN_CENTER);

      // 生成一个字体

      HSSFFont font = workbook.createFont();

      font.setColor(HSSFColor.VIOLET.index);

      font.setFontHeightInPoints((short) 12);

      font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);

      // 把字体应用到当前的样式

      style.setFont(font);

      // 生成并设置另一个样式

      HSSFCellStyle style2 = workbook.createCellStyle();

      style2.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);

      style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);

      style2.setBorderBottom(HSSFCellStyle.BORDER_THIN);

      style2.setBorderLeft(HSSFCellStyle.BORDER_THIN);

      style2.setBorderRight(HSSFCellStyle.BORDER_THIN);

      style2.setBorderTop(HSSFCellStyle.BORDER_THIN);

      style2.setAlignment(HSSFCellStyle.ALIGN_CENTER);

      style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

      // 生成另一个字体

      HSSFFont font2 = workbook.createFont();

      font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);

      // 把字体应用到当前的样式

      style2.setFont(font2);

    

      // 声明一个画图的顶级管理器

      HSSFPatriarch patriarch = sheet.createDrawingPatriarch();

      // 定义注释的大小和位置,详见文档

      HSSFComment comment = patriarch.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short) 4, 2, (short) 6, 5));

      // 设置注释内容

      comment.setString(new HSSFRichTextString("可以在POI中添加注释!"));

      // 设置注释作者,当鼠标移动到单元格上是可以在状态栏中看到该内容.

      comment.setAuthor("leno");

 

      //产生表格标题行

      HSSFRow row = sheet.createRow(0);

      for (short i = 0; i < headers.length; i++) {

         HSSFCell cell = row.createCell(i);

         cell.setCellStyle(style);

         HSSFRichTextString text = new HSSFRichTextString(headers[i]);

         cell.setCellValue(text);

      }

 

      //遍历集合数据,产生数据行

      Iterator<T> it = dataset.iterator();

      int index = 0;

      while (it.hasNext()) {

         index++;

         row = sheet.createRow(index);

         T t = (T) it.next();

         //利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值

         Field[] fields = t.getClass().getDeclaredFields();

         for (short i = 0; i < fields.length; i++) {

            HSSFCell cell = row.createCell(i);

            cell.setCellStyle(style2);

            Field field = fields[i];

            String fieldName = field.getName();

            String getMethodName = "get"

                   + fieldName.substring(0, 1).toUpperCase()

                   + fieldName.substring(1);

            try {

                Class tCls = t.getClass();

                Method getMethod = tCls.getMethod(getMethodName,

                      new Class[] {});

                Object value = getMethod.invoke(t, new Object[] {});

                //判断值的类型后进行强制类型转换

                String textValue = null;

//              if (value instanceof Integer) {

//                 int intValue = (Integer) value;

//                 cell.setCellValue(intValue);

//              } else if (value instanceof Float) {

//                 float fValue = (Float) value;

//                 textValue = new HSSFRichTextString(

//                       String.valueOf(fValue));

//                 cell.setCellValue(textValue);

//              } else if (value instanceof Double) {

//                 double dValue = (Double) value;

//                 textValue = new HSSFRichTextString(

//                       String.valueOf(dValue));

//                 cell.setCellValue(textValue);

//              } else if (value instanceof Long) {

//                 long longValue = (Long) value;

//                 cell.setCellValue(longValue);

//              }

                if (value instanceof Boolean) {

                   boolean bValue = (Boolean) value;

                   textValue = "男";

                   if (!bValue) {

                      textValue ="女";

                   }

                } else if (value instanceof Date) {

                   Date date = (Date) value;

                   SimpleDateFormat sdf = new SimpleDateFormat(pattern);

                    textValue = sdf.format(date);

                }  else if (value instanceof byte[]) {

                   // 有图片时,设置行高为60px;

                   row.setHeightInPoints(60);

                   // 设置图片所在列宽度为80px,注意这里单位的一个换算

                   sheet.setColumnWidth(i, (short) (35.7 * 80));

                   // sheet.autoSizeColumn(i);

                   byte[] bsValue = (byte[]) value;

                   HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0,

                         1023, 255, (short) 6, index, (short) 6, index);

                   anchor.setAnchorType(2);

                   patriarch.createPicture(anchor, workbook.addPicture(

                         bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG));

                } else{

                   //其它数据类型都当作字符串简单处理

                   textValue = value.toString();

                }

                //如果不是图片数据,就利用正则表达式判断textValue是否全部由数字组成

                if(textValue!=null){

                   Pattern p = Pattern.compile("^//d+(//.//d+)?$"); 

                   Matcher matcher = p.matcher(textValue);

                   if(matcher.matches()){

                      //是数字当作double处理

                      cell.setCellValue(Double.parseDouble(textValue));

                   }else{

                      HSSFRichTextString richString = new HSSFRichTextString(textValue);

                      HSSFFont font3 = workbook.createFont();

                      font3.setColor(HSSFColor.BLUE.index);

                      richString.applyFont(font3);

                      cell.setCellValue(richString);

                   }

                }

            } catch (SecurityException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            } catch (NoSuchMethodException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            } catch (IllegalArgumentException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            } catch (IllegalAccessException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            } catch (InvocationTargetException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            } finally {

                //清理资源
            }
         }

      }
     
      //此部分为单元格合并部分
      //获得所有的行
      int rows=sheet.getPhysicalNumberOfRows();
      //获得所有行
      int cels=row.getPhysicalNumberOfCells();
      System.out.println("行数为:"+rows+"列数为:"+cels);
 
      List<Short> CellCompare=new ArrayList<Short>();
      CellCompare.add((short) 0);
      CellCompare.add((short) 3);
      CellCompare.add((short) 7);
      //创建一个对象进行调用
      MergeCell mergeCell=new MergeCell();
      mergeCell.mergeCell(sheet, rows, CellCompare);
    
    //for(int k=0;k<cels;k++)
    //{
//     for(int k=0;k<CellCompare.size();k++)
//   {
//      for(int j=0;j<rows;j++)
//      {
//            //获得第k列中第j行中的内容值
//        String cel1=sheet.getRow(j).getCell(CellCompare.get(k)).getStringCellValue();
//        //设置参数count用于计数,主要是用于比较当如果有相同的行值时,就进行计数
//        int count=0;
//        //进行for循环
//        for(int i=1;i<rows-j;i++)
//        {
//         //获得第k列中第j+i列中的内容值,即同一列中当前行和下一行值进行比较
//         String cel2=sheet.getRow(j+i).getCell(CellCompare.get(k)).getStringCellValue();
//         //把要比较的两行值进行比较
//         if(cel1.equals(cel2))
//         {
//          //如果两行值相同,那么就进行计数,并且继续判断
//          count++;
//         }else
//         {
//          //如果两行值不同,那么就停止比较
//          break;
//         }
//        }
//        //因为只有当两行值相同时,才会合并,而比较是当前行和下一行进行比较,如果出现相同的
//        //一行,那么计数就为1 ,表示有两行相同,可以合并,即只需要计数值count>0就可以合并单元格
//       
//       if(count>0)
//       {
//        //j表示当前行,j+count表示需要合并的结束行
//        sheet.addMergedRegion(new Region(j,(short)CellCompare.get(k),(j+count),(short)CellCompare.get(k)));
//       }
//      }
//    //}
//   }
    
    
     
      try {

         workbook.write(out);

      } catch (IOException e) {

         // TODO Auto-generated catch block

         e.printStackTrace();
      }

   }

   public static void main(String[] args) {

      // 测试学生

      Test<Student> ex = new Test<Student>();

      String[] headers = { "学号", "姓名", "年龄", "性别", "出生日期","学历","爱好","幸运数","工资","工作年限"};

      List<Student> dataset = new ArrayList<Student>();
   //for(int i=0;i<20;i++)
  //{
      dataset.add(new Student(10000001, "张三", 20, true, new Date(),"本科","听音乐",8,3000,1));
      dataset.add(new Student(10000001, "张四", 20, true, new Date(),"本科","看书",8,2000,2));
      dataset.add(new Student(10000001, "张五", 20, true, new Date(),"本科","看书",8,2000,2));

      dataset.add(new Student(20000002, "李四", 24, false, new Date(),"硕士","看书",3,3000,2));

      dataset.add(new Student(30000003, "王一", 22, true, new Date(),"硕士","听音乐",3,3000,2));
      dataset.add(new Student(30000003, "王2", 22, true, new Date(),"硕士","听音乐",8,3000,3));
      dataset.add(new Student(30000003, "王3", 22, true, new Date(),"本科","打篮球",6,4000,3));
      dataset.add(new Student(30000003, "王4", 22, true, new Date(),"本科","打篮球",6,3000,1));
      dataset.add(new Student(40000004, "钱晨", 40, false, new Date(),"博士","打篮球",6,9000,5));
      dataset.add(new Student(50000005, "王一", 35, true, new Date(),"博士","打篮球",8,9000,5));
  //}    
      try {

       //BufferedInputStream bis = new BufferedInputStream(

          //      new FileInputStream("book.jpg"));

         byte[] buf = new byte[0];

         OutputStream out = new FileOutputStream("E://a.xls");


         ex.exportExcel(headers, dataset, out);

         out.close();

         JOptionPane.showMessageDialog(null, "导出成功!");

         System.out.println("excel导出成功!");

      } catch (FileNotFoundException e) {

         // TODO Auto-generated catch block

         e.printStackTrace();

      } catch (IOException e) {

         // TODO Auto-generated catch block

         e.printStackTrace();

      }

   }

}

3.MergeCell.java

 

package com.downpro;
//这个类用于合并单元格(可以通过集合的方式进行特定列的合并)
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.Region;


public class MergeCell {

 public void mergeCell(HSSFSheet sheet,int r,List<Short> CellCompare)
 {
   for(int k=0;k<CellCompare.size();k++)
     {
        for(int j=0;j<r;j++)
        {
              //获得第k列中第j行中的内容值
          String cel1=sheet.getRow(j).getCell(CellCompare.get(k)).getStringCellValue();
          //设置参数count用于计数,主要是用于比较当如果有相同的行值时,就进行计数
          int count=0;
          //进行for循环
          for(int i=1;i<r-j;i++)
          {
           //获得第k列中第j+i列中的内容值,即同一列中当前行和下一行值进行比较
           String cel2=sheet.getRow(j+i).getCell(CellCompare.get(k)).getStringCellValue();
           //把要比较的两行值进行比较
           if(cel1.equals(cel2))
           {
            //如果两行值相同,那么就进行计数,并且继续判断
            count++;
           }else
           {
            //如果两行值不同,那么就停止比较
            break;
           }
          }
          //因为只有当两行值相同时,才会合并,而比较是当前行和下一行进行比较,如果出现相同的
          //一行,那么计数就为1 ,表示有两行相同,可以合并,即只需要计数值count>0就可以合并单元格
         
         if(count>0)
         {
          //j表示当前行,j+count表示需要合并的结束行
          sheet.addMergedRegion(new Region(j,(short)CellCompare.get(k),(j+count),(short)CellCompare.get(k)));
         }
        }
      //}
     }
 }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值