`
汾水边的意气少年
  • 浏览: 7956 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java读取Excel文件汇总

 
阅读更多

                                                      Java读取Excel文件汇总

 

         相信很多程序猿朋友碰到上传、读取Excel文件的问题,做个小结,权当是笔记收着吧。

         之前做金融报表,是把Excel内嵌到页面中的,技术上采用ZK结合POI读取和插入Excel数据,后台方法比较死,比较程式化。

         目前新需求是把Excel表格上传到服务器,读取到里边的数据做处理。

   一、首先上传Excel

   1、页面添加文件域

 

<form id="uploadExcel" action="/auth/user/toHandleBatchRobotExcel.do"
 enctype="multipart/form- data" method="POST" >
   <input type="file" id="excel" name="excelFile"/>
   <input type="button" id="uploadExcel" />
</form>

 

   2、使用ajax提交表单(需导入jquery.form.js)

 

var excel=$("#excel").val();
var location=$('#excel').val();
var point = location.lastIndexOf(".");
var type = location.substr(point);
//type是Excel表格的格式.xls\.xlsx
$("#uploadExcel").ajaxSubmit({
      data:{ext:type},
      success:function(data){
      var dataJson = eval("("+data+")");
      console.log(data);
      if(dataJson.code==100){
           alert(dataJson.message);
      }else{
           alert("成功上传"+dataJson.attribute.robotNum+"条记录");
      }
    }
 });

 

 

 二、后台读取

 

   我尝试了两种方式来读取,jxl和poi。

  1、jxl读取

   jxl操作也是比较方便的,上代码吧。

   Jar包:jxl-2.6.jar

   读取Excel:

@RequestMapping(value = UrlMappings.HANDLE_BATCH_ROBOT_EXCEL, method = RequestMethod.POST)
@ResponseBody
    public void handleExcel(HttpServletResponse response,
          MultipartHttpServletRequest request, String ext) {
              logger.info("处理Excel表格");
              logger.info("开始解析...");
              logger.info(ext);
     
MultipartFile fileFile = request.getFile("excelFile");
InputStream in = fileFile.getInputStream();
//获取Excel文件对象
Workbook wb = Workbook.getWorkbook(in);
//获取文件的指定工作表默认的第一个
Sheet sheet = wb.getSheet(0);
// 单元格
Cell cell;
//获取行数
Int rows = sheet.getRows();
Map<Integer, String> map = new HashMap<Integer, String>();
List<UserInfoVo> list = new LinkedList<UserInfoVo>();

if (rows.size() > 0 && rows!= null) {
   for (int i = 1; i < rows.size(); i++) {
      for (int j = 0; j < sheet.getColumns(); j++) {
         cell =sheet.getCell(j,i);
         map.put(j,cell.getContents());
      }
      //Excel数据对应的实体类,根据情况自己设定
      UserInfoVo userInfoVo = new UserInfoVo();
      userInfoVo.setNickName(map.get(1));
      userInfoVo.setGender(map.get(2).equals("男") ? 0 : 1);
      userInfoVo.setBirthday(sdf.parse(map.get(3)).getTime());
      userInfoVo.setRegisterDatetime(sdf.parse(map.get(4))
            .getTime());
      userInfoVo.setState(1);
      list.add(userInfoVo);
   }
}
}

    这样读取到的list中就包括了excel表中的各行数据。

    但是在使用过程中发现,有些用户上传2007版的Excel表格,这样的话就会出现读取错误的情况

    jxl.read.biff.BiffException: Unable to recognize OLE stream,这是因为jxl久未更新,没法读取新版本的         Excel,就是.xlsx格式的文件。

 

    于是,换种思路,使用兼容性更好的poi进行读取。

      

    2、poi读取

 

    poi是读取Excel最佳工具,功能丰富,对读取不同版本的excel都做了对应处理。

    jar包:

    poi-3.11.jar  针对03版excel,即后缀为.xls的文件。 

    poi-ooxml-3.11.jar  针对07版excel,即后缀为.xlsx的文件。

         

    读取Excel: 

@RequestMapping(value = UrlMappings.HANDLE_BATCH_ROBOT_EXCEL, method = RequestMethod.POST)
@ResponseBody
public void handleExcel(HttpServletResponse response,
      MultipartHttpServletRequest request, String ext) {
   logger.info("处理Excel表格");
   logger.info("开始解析...");
   //excel格式 .xls\.xlsx
   logger.info(ext);

    // 得到上传的文件
   MultipartFile fileFile = request.getFile("excelFile");
   try {
      // 转换成输入流
      InputStream in = fileFile.getInputStream();
      // 单元格
      Cell cell;
      List<Row> rsRows = new ExcelUtils().readExcel(ext, in);
      // 实例化对象
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
      Map<Integer, String> map = new HashMap<Integer, String>();
      List<UserInfoVo> list = new LinkedList<UserInfoVo>();

      if (rsRows.size() > 0 && rsRows != null) {
         for (int i = 1; i < rsRows.size(); i++) {
            for (int j = 0; j < rsRows.get(i).getLastCellNum(); j++) {
               cell = rsRows.get(i).getCell(j);
               map.put(j, new ExcelUtils().getCellValue(cell));
            }
            UserInfoVo userInfoVo = new UserInfoVo();
            userInfoVo.setNickName(map.get(1));
            userInfoVo.setGender(map.get(2).equals("男") ? 0 : 1);
            userInfoVo.setBirthday(sdf.parse(map.get(3)).getTime());
            userInfoVo.setRegisterDatetime(sdf.parse(map.get(4))
                  .getTime());
            userInfoVo.setState(1);
            list.add(userInfoVo);
         }
      }
}

 

    List中即是excel表中的数据。这其中要用到一个工具类ExcelUtils。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ExcelUtils {

   // %%%%%%%%-------常量部分 开始----------%%%%%%%%%
   /**
    * 默认的开始读取的行位置为第一行(索引值为0)
    */
   private final static int READ_START_POS = 0;

   /**
    * 默认结束读取的行位置为最后一行(索引值=0,用负数来表示倒数第n行)
    */
   private final static int READ_END_POS = 0;

   /**
    * 默认Excel内容的开始比较列位置为第一列(索引值为0)
    */
   private final static int COMPARE_POS = 0;

   /**
    * 默认多文件合并的时需要做内容比较(相同的内容不重复出现)
    */
   private final static boolean NEED_COMPARE = true;

   /**
    * 默认多文件合并的新文件遇到名称重复时,进行覆盖
    */
   private final static boolean NEED_OVERWRITE = true;

   /**
    * 默认只操作一个sheet
    */
   private final static boolean ONLY_ONE_SHEET = true;

   /**
    * 默认读取第一个sheet中(只有当ONLY_ONE_SHEET = true时有效)
    */
   private final static int SELECTED_SHEET = 0;

   /**
    * 默认从第一个sheet开始读取(索引值为0)
    */
   private final static int READ_START_SHEET = 0;

   /**
    * 默认在最后一个sheet结束读取(索引值=0,用负数来表示倒数第n行)
    */
   private final static int READ_END_SHEET = 0;

   /**
    * 默认打印各种信息
    */
   private final static boolean PRINT_MSG = true;

   // %%%%%%%%-------常量部分 结束----------%%%%%%%%%

   // %%%%%%%%-------字段部分 开始----------%%%%%%%%%
   /**
    * Excel文件路径
    */
   private String excelPath = "data.xlsx";

   /**
    * 设定开始读取的位置,默认为0
    */
   private int startReadPos = READ_START_POS;

   /**
    * 设定结束读取的位置,默认为0,用负数来表示倒数第n行
    */
   private int endReadPos = READ_END_POS;

   /**
    * 设定开始比较的列位置,默认为0
    */
   private int comparePos = COMPARE_POS;

   /**
    * 设定汇总的文件是否需要替换,默认为true
    */
   private boolean isOverWrite = NEED_OVERWRITE;

   /**
    * 设定是否需要比较,默认为true(仅当不覆写目标内容是有效,即isOverWrite=false时有效)
    */
   private boolean isNeedCompare = NEED_COMPARE;

   /**
    * 设定是否只操作第一个sheet
    */
   private boolean onlyReadOneSheet = ONLY_ONE_SHEET;

   /**
    * 设定操作的sheet在索引值
    */
   private int selectedSheetIdx = SELECTED_SHEET;

   /**
    * 设定操作的sheet的名称
    */
   private String selectedSheetName = "";

   /**
    * 设定开始读取的sheet,默认为0
    */
   private int startSheetIdx = READ_START_SHEET;

   /**
    * 设定结束读取的sheet,默认为0,用负数来表示倒数第n行
    */
   private int endSheetIdx = READ_END_SHEET;

   /**
    * 设定是否打印消息
    */
   private boolean printMsg = PRINT_MSG;

   // %%%%%%%%-------字段部分 结束----------%%%%%%%%%

   public ExcelUtils() {

   }

   public ExcelUtils(String excelPath) {
      this.excelPath = excelPath;
   }

   /**
    * 还原设定(其实是重新new一个新的对象并返回)
    * 
    * @return
    */
   public ExcelUtils RestoreSettings() {
      ExcelUtils instance = new ExcelUtils(this.excelPath);
      return instance;
   }

   /**
    * 自动根据文件扩展名,调用对应的读取方法
    * 
    * @Title: writeExcel
    * @Date : 2014-9-11 下午01:50:38
    * @throws IOException
    */
   public List<Row> readExcel() throws IOException {
      return readExcel(this.excelPath);
   }

   /**
    * 自动根据文件扩展名,调用对应的读取方法
    * 
    * @Title: writeExcel
    * @Date : 2014-9-11 下午01:50:38
    * @param xlsPath
    * @throws IOException
    */
   public List<Row> readExcel(String xlsPath) throws IOException {

      // 扩展名为空时,
      if (xlsPath.equals("")) {
         throw new IOException("文件路径不能为空!");
      } else {
         File file = new File(xlsPath);
         if (!file.exists()) {
            throw new IOException("文件不存在!");
         }
      }

      // 获取扩展名
      String ext = xlsPath.substring(xlsPath.lastIndexOf(".") + 1);

      try {

         if ("xls".equals(ext)) { // 使用xls方式读取
            return readExcel_xls(xlsPath);
         } else if ("xlsx".equals(ext)) { // 使用xlsx方式读取
            return readExcel_xlsx(xlsPath);
         } else { // 依次尝试xls、xlsx方式读取
            out("您要操作的文件没有扩展名,正在尝试以xls方式读取...");
            try {
               return readExcel_xls(xlsPath);
            } catch (IOException e1) {
               out("尝试以xls方式读取,结果失败!,正在尝试以xlsx方式读取...");
               try {
                  return readExcel_xlsx(xlsPath);
               } catch (IOException e2) {
                  out("尝试以xls方式读取,结果失败!\n请您确保您的文件是Excel文件,并且无损,然后再试。");
                  throw e2;
               }
            }
         }
      } catch (IOException e) {
         throw e;
      }
   }

   /**
    * 通过判断文件的扩展名,以不同的方式读取文件
    * 
    * @author wufei 2016年9月19日 上午10:41:27
    * @Method: readExcel
    * @Description: TODO
    * @param @param ext
    * @param @param in
    * @param @return
    * @param @throws IOException
    * @return List<Row>
    * @throws
    */
   public List<Row> readExcel(String ext, InputStream in) {

      try {
         if (".xls".equals(ext)) { // 使用xls方式读取
            return readExcel_xlsAsStream(in);
         } else if (".xlsx".equals(ext)) { // 使用xlsx方式读取
            return readExcel_xlsxAsStream(in);
         } else { // 依次尝试xls、xlsx方式读取
            out("您要操作的文件没有扩展名,正在尝试以xlsx方式读取...");
            try {
               return readExcel_xlsxAsStream(in);
            } catch (Exception e1) {
               out("尝试以xlsx方式读取,结果失败!,正在尝试以xls方式读取...");
               try {
                  return readExcel_xlsAsStream(in);
               } catch (IOException e2) {
                  out("尝试以xls方式读取,结果失败!\n请您确保您的文件是Excel文件,并且无损,然后再试。");
                  throw e2;
               }
            }
         }
      } catch (IOException e) {
         out(e.getMessage());
         return null;
      }
   }

   /**
    * 自动根据文件扩展名,调用对应的写入方法
    * 
    * @Title: writeExcel
    * @Date : 2014-9-11 下午01:50:38
    * @param rowList
    * @throws IOException
    */
   public void writeExcel(List<Row> rowList) throws IOException {
      writeExcel(rowList, excelPath);
   }

   /**
    * 自动根据文件扩展名,调用对应的写入方法
    * 
    * @Title: writeExcel
    * @Date : 2014-9-11 下午01:50:38
    * @param rowList
    * @param xlsPath
    * @throws IOException
    */
   public void writeExcel(List<Row> rowList, String xlsPath)
         throws IOException {

      // 扩展名为空时,
      if (xlsPath.equals("")) {
         throw new IOException("文件路径不能为空!");
      }

      // 获取扩展名
      String ext = xlsPath.substring(xlsPath.lastIndexOf(".") + 1);

      try {

         if ("xls".equals(ext)) { // 使用xls方式写入
            writeExcel_xls(rowList, xlsPath);
         } else if ("xlsx".equals(ext)) { // 使用xlsx方式写入
            writeExcel_xlsx(rowList, xlsPath);
         } else { // 依次尝试xls、xlsx方式写入
            out("您要操作的文件没有扩展名,正在尝试以xls方式写入...");
            try {
               writeExcel_xls(rowList, xlsPath);
            } catch (IOException e1) {
               out("尝试以xls方式写入,结果失败!,正在尝试以xlsx方式读取...");
               try {
                  writeExcel_xlsx(rowList, xlsPath);
               } catch (IOException e2) {
                  out("尝试以xls方式写入,结果失败!\n请您确保您的文件是Excel文件,并且无损,然后再试。");
                  throw e2;
               }
            }
         }
      } catch (IOException e) {
         throw e;
      }
   }

   /**
    * 修改Excel(97-03版,xls格式)
    * 
    * @Title: writeExcel_xls
    * @Date : 2014-9-11 下午01:50:38
    * @param rowList
    * @param dist_xlsPath
    * @throws IOException
    */
   public void writeExcel_xls(List<Row> rowList, String dist_xlsPath)
         throws IOException {
      writeExcel_xls(rowList, excelPath, dist_xlsPath);
   }

   /**
    * 修改Excel(97-03版,xls格式)
    * 
    * @Title: writeExcel_xls
    * @Date : 2014-9-11 下午01:50:38
    * @param rowList
    * @param src_xlsPath
    * @param dist_xlsPath
    * @throws IOException
    */
   public void writeExcel_xls(List<Row> rowList, String src_xlsPath,
         String dist_xlsPath) throws IOException {

      // 判断文件路径是否为空
      if (dist_xlsPath == null || dist_xlsPath.equals("")) {
         out("文件路径不能为空");
         throw new IOException("文件路径不能为空");
      }
      // 判断文件路径是否为空
      if (src_xlsPath == null || src_xlsPath.equals("")) {
         out("文件路径不能为空");
         throw new IOException("文件路径不能为空");
      }

      // 判断列表是否有数据,如果没有数据,则返回
      if (rowList == null || rowList.size() == 0) {
         out("文档为空");
         return;
      }

      try {
         HSSFWorkbook wb = null;

         // 判断文件是否存在
         File file = new File(dist_xlsPath);
         if (file.exists()) {
            // 如果复写,则删除后
            if (isOverWrite) {
               file.delete();
               // 如果文件不存在,则创建一个新的Excel
               // wb = new HSSFWorkbook();
               // wb.createSheet("Sheet1");
               wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
            } else {
               // 如果文件存在,则读取Excel
               wb = new HSSFWorkbook(new FileInputStream(file));
            }
         } else {
            // 如果文件不存在,则创建一个新的Excel
            // wb = new HSSFWorkbook();
            // wb.createSheet("Sheet1");
            wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
         }

         // 将rowlist的内容写到Excel中
         writeExcel(wb, rowList, dist_xlsPath);

      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   /**
    * 修改Excel(97-03版,xls格式)
    * 
    * @Title: writeExcel_xls
    * @Date : 2014-9-11 下午01:50:38
    * @param rowList
    * @param dist_xlsPath
    * @throws IOException
    */
   public void writeExcel_xlsx(List<Row> rowList, String dist_xlsPath)
         throws IOException {
      writeExcel_xls(rowList, excelPath, dist_xlsPath);
   }

   /**
    * 修改Excel(2007版,xlsx格式)
    * 
    * @Title: writeExcel_xlsx
    * @Date : 2014-9-11 下午01:50:38
    * @param rowList
    * @throws IOException
    */
   public void writeExcel_xlsx(List<Row> rowList, String src_xlsPath,
         String dist_xlsPath) throws IOException {

      // 判断文件路径是否为空
      if (dist_xlsPath == null || dist_xlsPath.equals("")) {
         out("文件路径不能为空");
         throw new IOException("文件路径不能为空");
      }
      // 判断文件路径是否为空
      if (src_xlsPath == null || src_xlsPath.equals("")) {
         out("文件路径不能为空");
         throw new IOException("文件路径不能为空");
      }

      // 判断列表是否有数据,如果没有数据,则返回
      if (rowList == null || rowList.size() == 0) {
         out("文档为空");
         return;
      }

      try {
         // 读取文档
         HSSFWorkbook wb = null;

         // 判断文件是否存在
         File file = new File(dist_xlsPath);
         if (file.exists()) {
            // 如果复写,则删除后
            if (isOverWrite) {
               file.delete();
               // 如果文件不存在,则创建一个新的Excel
               // wb = new XSSFWorkbook();
               // wb.createSheet("Sheet1");
               wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
            } else {
               // 如果文件存在,则读取Excel
               wb = new HSSFWorkbook(new FileInputStream(file));
            }
         } else {
            // 如果文件不存在,则创建一个新的Excel
            // wb = new XSSFWorkbook();
            // wb.createSheet("Sheet1");
            wb = new HSSFWorkbook(new FileInputStream(src_xlsPath));
         }
         // 将rowlist的内容添加到Excel中
         writeExcel(wb, rowList, dist_xlsPath);

      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   /**
    * //读取Excel 2007版,xlsx格式
    * 
    * @Title: readExcel_xlsx
    * @Date : 2014-9-11 上午11:43:11
    * @return
    * @throws IOException
    */
   public List<Row> readExcel_xlsx() throws IOException {
      return readExcel_xlsx(excelPath);
   }

   /**
    * //读取Excel 2007版,xlsx格式
    * 
    * @Title: readExcel_xlsx
    * @Date : 2014-9-11 上午11:43:11
    * @return
    * @throws Exception
    */
   public List<Row> readExcel_xlsx(String xlsPath) throws IOException {
      // 判断文件是否存在
      File file = new File(xlsPath);
      if (!file.exists()) {
         throw new IOException("文件名为" + file.getName() + "Excel文件不存在!");
      }

      XSSFWorkbook wb = null;
      List<Row> rowList = new ArrayList<Row>();
      try {
         FileInputStream fis = new FileInputStream(file);
         // 去读Excel
         wb = new XSSFWorkbook(fis);

         // 读取Excel 2007版,xlsx格式
         rowList = readExcel(wb);

      } catch (IOException e) {
         e.printStackTrace();
      }
      return rowList;
   }

   /**
    * 以流的形式读取excel文件 2007版xlsx
    * 
    * @author wufei 2016年9月19日 上午10:35:40
    * @Method: readExcel_xlsxAsStream
    * @Description: TODO
    * @param @param in
    * @param @return
    * @param @throws IOException
    * @return List<Row>
    * @throws
    */
   public List<Row> readExcel_xlsxAsStream(InputStream in) throws IOException {

      XSSFWorkbook wb = null;
      List<Row> rowList = new ArrayList<Row>();
      try {
         // 去读Excel
         wb = new XSSFWorkbook(in);

         // 读取Excel 2007版,xlsx格式
         rowList = readExcel(wb);

      } catch (IOException e) {
         e.printStackTrace();
      }
      return rowList;
   }

   /***
    * 读取Excel(97-03版,xls格式)
    * 
    * @throws IOException
    * 
    * @Title: readExcel
    * @Date : 2014-9-11 上午09:53:21
    */
   public List<Row> readExcel_xls() throws IOException {
      return readExcel_xls(excelPath);
   }

   /***
    * 读取Excel(97-03版,xls格式)
    * 
    * @throws Exception
    * 
    * @Title: readExcel
    * @Date : 2014-9-11 上午09:53:21
    */
   public List<Row> readExcel_xls(String xlsPath) throws IOException {

      // 判断文件是否存在
      File file = new File(xlsPath);
      if (!file.exists()) {
         throw new IOException("文件名为" + file.getName() + "Excel文件不存在!");
      }

      HSSFWorkbook wb = null;// 用于Workbook级的操作,创建、删除Excel
      List<Row> rowList = new ArrayList<Row>();

      try {
         // 读取Excel
         wb = new HSSFWorkbook(new FileInputStream(file));

         // 读取Excel 97-03版,xls格式
         rowList = readExcel(wb);

      } catch (IOException e) {
         e.printStackTrace();
      }
      return rowList;
   }

   /**
    * 以流的形式读取97-03版excel文件
    * 
    * @author wufei 2016年9月19日 上午10:33:25
    * @Method: readExcel_xlsAsStream
    * @Description: TODO
    * @param @param in
    * @param @return
    * @param @throws IOException
    * @return List<Row>
    * @throws
    */
   public List<Row> readExcel_xlsAsStream(InputStream in) throws IOException {

      HSSFWorkbook wb = null;// 用于Workbook级的操作,创建、删除Excel
      List<Row> rowList = new ArrayList<Row>();

      try {
         // 读取Excel
         wb = new HSSFWorkbook(in);

         // 读取Excel 97-03版,xls格式
         rowList = readExcel(wb);

      } catch (IOException e) {
         e.printStackTrace();
      }
      return rowList;
   }

   /***
    * 读取单元格的值
    * 
    * @Title: getCellValue
    * @Date : 2014-9-11 上午10:52:07
    * @param cell
    * @return
    */
   public String getCellValue(Cell cell) {
      Object result = "";
      if (cell != null) {
         switch (cell.getCellType()) {
         case Cell.CELL_TYPE_STRING:
            result = cell.getStringCellValue();
            break;
         case Cell.CELL_TYPE_NUMERIC:
            // 判断是否为日期
            if (HSSFDateUtil.isCellDateFormatted(cell)) {
               SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");
               Date date = HSSFDateUtil.getJavaDate(cell
                     .getNumericCellValue());
               result = df.format(date);
            } else {
               result = cell.getNumericCellValue();
            }
            break;
         case Cell.CELL_TYPE_BOOLEAN:
            result = cell.getBooleanCellValue();
            break;
         case Cell.CELL_TYPE_FORMULA:
            result = cell.getCellFormula();
            break;
         case Cell.CELL_TYPE_ERROR:
            result = cell.getErrorCellValue();
            break;
         case Cell.CELL_TYPE_BLANK:
            break;
         default:
            break;
         }
      }
      return result.toString();
   }

   /**
    * 通用读取Excel
    * 
    * @Title: readExcel
    * @Date : 2014-9-11 上午11:26:53
    * @param wb
    * @return
    */
   private List<Row> readExcel(Workbook wb) {
      List<Row> rowList = new ArrayList<Row>();

      int sheetCount = 1;// 需要操作的sheet数量

      Sheet sheet = null;
      if (onlyReadOneSheet) { // 只操作一个sheet
         // 获取设定操作的sheet(如果设定了名称,按名称查,否则按索引值查)
         sheet = selectedSheetName.equals("") ? wb
               .getSheetAt(selectedSheetIdx) : wb
               .getSheet(selectedSheetName);
      } else { // 操作多个sheet
         sheetCount = wb.getNumberOfSheets();// 获取可以操作的总数量
      }

      // 获取sheet数目
      for (int t = startSheetIdx; t < sheetCount + endSheetIdx; t++) {
         // 获取设定操作的sheet
         if (!onlyReadOneSheet) {
            sheet = wb.getSheetAt(t);
         }

         // 获取最后行号
         int lastRowNum = sheet.getLastRowNum();

         if (lastRowNum > 0) { // 如果>0,表示有数据
            out("\n开始读取名为【" + sheet.getSheetName() + "】的内容:");
         }

         Row row = null;
         // 循环读取
         for (int i = startReadPos; i <= lastRowNum + endReadPos; i++) {
            row = sheet.getRow(i);
            if (row != null) {
               rowList.add(row);
               out("第" + (i + 1) + "行:", false);
               // 获取每一单元格的值
               for (int j = 0; j < row.getLastCellNum(); j++) {
                  String value = getCellValue(row.getCell(j));
                  if (!value.equals("")) {
                     out(value + " | ", false);
                  }
               }
               out("");
            }
         }
      }
      return rowList;
   }

   /**
    * 修改Excel,并另存为
    * 
    * @Title: WriteExcel
    * @Date : 2014-9-11 下午01:33:59
    * @param wb
    * @param rowList
    * @param xlsPath
    */
   private void writeExcel(Workbook wb, List<Row> rowList, String xlsPath) {

      if (wb == null) {
         out("操作文档不能为空!");
         return;
      }

      Sheet sheet = wb.getSheetAt(0);// 修改第一个sheet中的值

      // 如果每次重写,那么则从开始读取的位置写,否则果获取源文件最新的行。
      int lastRowNum = isOverWrite ? startReadPos : sheet.getLastRowNum() + 1;
      int t = 0;// 记录最新添加的行数
      out("要添加的数据总条数为:" + rowList.size());
      for (Row row : rowList) {
         if (row == null)
            continue;
         // 判断是否已经存在该数据
         int pos = findInExcel(sheet, row);

         Row r = null;// 如果数据行已经存在,则获取后重写,否则自动创建新行。
         if (pos >= 0) {
            sheet.removeRow(sheet.getRow(pos));
            r = sheet.createRow(pos);
         } else {
            r = sheet.createRow(lastRowNum + t++);
         }

         // 用于设定单元格样式
         CellStyle newstyle = wb.createCellStyle();

         // 循环为新行创建单元格
         for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
            Cell cell = r.createCell(i);// 获取数据类型
            cell.setCellValue(getCellValue(row.getCell(i)));// 复制单元格的值到新的单元格
            // cell.setCellStyle(row.getCell(i).getCellStyle());//出错
            if (row.getCell(i) == null)
               continue;
            copyCellStyle(row.getCell(i).getCellStyle(), newstyle); // 获取原来的单元格样式
            cell.setCellStyle(newstyle);// 设置样式
            // sheet.autoSizeColumn(i);//自动跳转列宽度
         }
      }
      out("其中检测到重复条数为:" + (rowList.size() - t) + " ,追加条数为:" + t);

      // 统一设定合并单元格
      setMergedRegion(sheet);

      try {
         // 重新将数据写入Excel中
         FileOutputStream outputStream = new FileOutputStream(xlsPath);
         wb.write(outputStream);
         outputStream.flush();
         outputStream.close();
      } catch (Exception e) {
         out("写入Excel时发生错误! ");
         e.printStackTrace();
      }
   }

   /**
    * 查找某行数据是否在Excel表中存在,返回行数。
    * 
    * @Title: findInExcel
    * @Date : 2014-9-11 下午02:23:12
    * @param sheet
    * @param row
    * @return
    */
   private int findInExcel(Sheet sheet, Row row) {
      int pos = -1;

      try {
         // 如果覆写目标文件,或者不需要比较,则直接返回
         if (isOverWrite || !isNeedCompare) {
            return pos;
         }
         for (int i = startReadPos; i <= sheet.getLastRowNum() + endReadPos; i++) {
            Row r = sheet.getRow(i);
            if (r != null && row != null) {
               String v1 = getCellValue(r.getCell(comparePos));
               String v2 = getCellValue(row.getCell(comparePos));
               if (v1.equals(v2)) {
                  pos = i;
                  break;
               }
            }
         }
      } catch (Exception e) {
         e.printStackTrace();
      }
      return pos;
   }

   /**
    * 复制一个单元格样式到目的单元格样式
    * 
    * @param fromStyle
    * @param toStyle
    */
   public static void copyCellStyle(CellStyle fromStyle, CellStyle toStyle) {
      toStyle.setAlignment(fromStyle.getAlignment());
      // 边框和边框颜色
      toStyle.setBorderBottom(fromStyle.getBorderBottom());
      toStyle.setBorderLeft(fromStyle.getBorderLeft());
      toStyle.setBorderRight(fromStyle.getBorderRight());
      toStyle.setBorderTop(fromStyle.getBorderTop());
      toStyle.setTopBorderColor(fromStyle.getTopBorderColor());
      toStyle.setBottomBorderColor(fromStyle.getBottomBorderColor());
      toStyle.setRightBorderColor(fromStyle.getRightBorderColor());
      toStyle.setLeftBorderColor(fromStyle.getLeftBorderColor());

      // 背景和前景
      toStyle.setFillBackgroundColor(fromStyle.getFillBackgroundColor());
      toStyle.setFillForegroundColor(fromStyle.getFillForegroundColor());

      // 数据格式
      toStyle.setDataFormat(fromStyle.getDataFormat());
      toStyle.setFillPattern(fromStyle.getFillPattern());
      // toStyle.setFont(fromStyle.getFont(null));
      toStyle.setHidden(fromStyle.getHidden());
      toStyle.setIndention(fromStyle.getIndention());// 首行缩进
      toStyle.setLocked(fromStyle.getLocked());
      toStyle.setRotation(fromStyle.getRotation());// 旋转
      toStyle.setVerticalAlignment(fromStyle.getVerticalAlignment());
      toStyle.setWrapText(fromStyle.getWrapText());

   }

   /**
    * 获取合并单元格的值
    * 
    * @param sheet
    * @return
    */
   public void setMergedRegion(Sheet sheet) {
      int sheetMergeCount = sheet.getNumMergedRegions();

      for (int i = 0; i < sheetMergeCount; i++) {
         // 获取合并单元格位置
         CellRangeAddress ca = sheet.getMergedRegion(i);
         int firstRow = ca.getFirstRow();
         if (startReadPos - 1 > firstRow) {// 如果第一个合并单元格格式在正式数据的上面,则跳过。
            continue;
         }
         int lastRow = ca.getLastRow();
         int mergeRows = lastRow - firstRow;// 合并的行数
         int firstColumn = ca.getFirstColumn();
         int lastColumn = ca.getLastColumn();
         // 根据合并的单元格位置和大小,调整所有的数据行格式,
         for (int j = lastRow + 1; j <= sheet.getLastRowNum(); j++) {
            // 设定合并单元格
            sheet.addMergedRegion(new CellRangeAddress(j, j + mergeRows,
                  firstColumn, lastColumn));
            j = j + mergeRows;// 跳过已合并的行
         }

      }
   }

   /**
    * 打印消息,
    * 
    * @param msg
    *            消息内容 换行
    */
   private void out(String msg) {
      if (printMsg) {
         out(msg, true);
      }
   }

   /**
    * 打印消息,
    * 
    * @param msg
    *            消息内容
    * @param tr
    *            换行
    */
   private void out(String msg, boolean tr) {
      if (printMsg) {
         System.out.print(msg + (tr ? "\n" : ""));
      }
   }

   public String getExcelPath() {
      return this.excelPath;
   }

   public void setExcelPath(String excelPath) {
      this.excelPath = excelPath;
   }

   public boolean isNeedCompare() {
      return isNeedCompare;
   }

   public void setNeedCompare(boolean isNeedCompare) {
      this.isNeedCompare = isNeedCompare;
   }

   public int getComparePos() {
      return comparePos;
   }

   public void setComparePos(int comparePos) {
      this.comparePos = comparePos;
   }

   public int getStartReadPos() {
      return startReadPos;
   }

   public void setStartReadPos(int startReadPos) {
      this.startReadPos = startReadPos;
   }

   public int getEndReadPos() {
      return endReadPos;
   }

   public void setEndReadPos(int endReadPos) {
      this.endReadPos = endReadPos;
   }

   public boolean isOverWrite() {
      return isOverWrite;
   }

   public void setOverWrite(boolean isOverWrite) {
      this.isOverWrite = isOverWrite;
   }

   public boolean isOnlyReadOneSheet() {
      return onlyReadOneSheet;
   }

   public void setOnlyReadOneSheet(boolean onlyReadOneSheet) {
      this.onlyReadOneSheet = onlyReadOneSheet;
   }

   public int getSelectedSheetIdx() {
      return selectedSheetIdx;
   }

   public void setSelectedSheetIdx(int selectedSheetIdx) {
      this.selectedSheetIdx = selectedSheetIdx;
   }

   public String getSelectedSheetName() {
      return selectedSheetName;
   }

   public void setSelectedSheetName(String selectedSheetName) {
      this.selectedSheetName = selectedSheetName;
   }

   public int getStartSheetIdx() {
      return startSheetIdx;
   }

   public void setStartSheetIdx(int startSheetIdx) {
      this.startSheetIdx = startSheetIdx;
   }

   public int getEndSheetIdx() {
      return endSheetIdx;
   }

   public void setEndSheetIdx(int endSheetIdx) {
      this.endSheetIdx = endSheetIdx;
   }

   public boolean isPrintMsg() {
      return printMsg;
   }

   public void setPrintMsg(boolean printMsg) {
      this.printMsg = printMsg;
   }
}

    至此,读取完毕。

分享到:
评论

相关推荐

    java解析excel并做数据有效性校验

    在Java编程中,解析Excel文件是一项常见的任务,特别是在数据处理、报表生成或数据分析等领域。Excel文件格式主要有两种:老式的`.xls`(基于BIFF格式)和较新的`.xlsx`(基于Open XML标准)。本篇将详细介绍如何...

    Java通过POI读取Excel遍历数据,批量生成word文档

    接下来,我们需要创建一个Java程序来读取Excel文件。使用POI的`XSSFWorkbook`类打开Excel文件,然后通过` XSSFSheet `获取工作表,并使用` XSSFRow `和` XSSFCell `遍历单元格数据: ```java import org.apache.poi...

    读取Excel文件将数据存入map集合

    本篇文章介绍了一个方法,该方法能够读取Excel文件并将其中的数据存储到Java中的`Map`集合里,便于后续进行数据分析或处理。 #### 方法概述 方法签名如下: ```java public Map, Map, String&gt;&gt; importReportExcel...

    基于Java Excel API的excel文件的操纵技术及其应用.pdf

    在本文中,我们将详细介绍基于Java Excel API的excel文件的操纵技术,包括excel文件的读取和写入、excel文件的编辑和格式化、excel文件的打印和导出等内容。此外,我们还将提供一些实用的示例代码,以便读者更好地...

    Java对Excel表格的操作

    它提供了一组API,允许开发者在Java应用程序中读写Microsoft Office格式的文件,如Excel和Word文档。 - **特点**: - **广泛支持**:支持多种Office文件格式。 - **成熟稳定**:作为一个成熟的项目,POI在业界...

    java统计excel并生成新的excel

    这个场景下,我们需要使用Java来统计多个Excel文档中的数据,并根据月份进行分类统计,最后将结果汇总到一个新的Excel文件中。以下是一些相关的知识点和实现步骤: 1. **Java库的选择**: - Apache POI:这是一个...

    java_excel_api 一些常用的类库

    根据给定文件中的标题、描述、标签以及部分内容,可以总结并扩展出以下关于 Java Excel API 的相关知识点: ### Java Excel API 常用类库 #### jxl.jar `jxl.jar` 是一个用于处理 Excel 文件的 Java 库。它支持 ...

    java-excel导入导出注解版内用教程说明

    Apache POI 是一个流行的开源库,它允许Java开发者读写Microsoft Office格式的文件,包括Excel(.xlsx 和 .xls)。本教程将详细介绍如何使用Apache POI结合注解的方式进行Excel的导入与导出。 首先,导入Apache POI...

    java poi处理excel数据

    Java POI是Apache软件基金会下的一个开源项目,主要用于读写Microsoft Office格式的文件,特别是Excel。在Java开发中,当你需要处理Excel数据时,POI库是一个强大的工具。本压缩包包含了一些关键资源,帮助你理解和...

    poi excel 模板读取并导出带公式的excel文档

    利用Apache POI库能够实现这一功能,即可以通过Java程序操作Excel文件,包括读取、写入、以及处理Excel中的公式。 #### 二、关键技术点 1. **POI库简介**: - Apache POI是Apache软件基金会的Jakarta项目中的一个...

    EXcel汇总,支持Excel2003、Excel2007

    综上所述,"EXcel汇总"工具是一款针对Excel2003和Excel2007版本设计的文件合并工具,它利用Java编程语言实现跨平台运行,能有效整合格式相同或相近的Excel文件,提高数据处理效率,减少人为错误。通过理解并掌握这样...

    JAVA开源框架-汇总.doc

    - **概述**:OpenXML4J 是一个基于Java的开源库,它允许开发者轻松地创建、读取和修改Microsoft Office Open XML 格式的文档,如Word (.docx)、Excel (.xlsx) 和 PowerPoint (.pptx) 文件。 - **主要特性**: - ...

    将超大excel文件按sheet分成多个excel小文件

    这类工具通常能读取大文件,然后按每个工作表创建新的独立Excel文件。 3. 分割步骤: - 打开分割工具:运行`SplitExcel.exe`,根据工具的界面提示进行操作。 - 选择源文件:找到并加载你需要拆分的超大Excel文件...

    java工具类汇总

    - Apache POI:这是一个流行的Java API,用于读写Microsoft Office格式的文件,包括Excel。主要类有`XSSFWorkbook`(用于创建.xlsx文件)和`HSSFWorkbook`(用于创建.xls文件)。 - OpenCSV:虽然主要处理CSV文件...

    Java对xls文件进行读写操作示例代码

    以下是一个简单的示例,展示如何从多个xls文件中读取数据并将其汇总到一个新的文件中: 1. **准备工作**: - 将jxl.jar库添加到项目的构建路径或类路径中。 - 创建一个名为`RWExcel`的自定义类,用于封装xls文件...

    个人JAVA笔记汇总

    1. **JXL库**: JXL是Java的一个库,用于读写Excel文件。它允许开发者在Java程序中创建、修改和读取Excel工作簿。通过JXL,你可以创建新的工作表,设置单元格样式,读取数据,进行公式计算,并且处理图表,这对于数据...

    java文档读写处理

    在Java编程语言中,处理文档,尤其...综上所述,Java结合Apache POI库能够高效地进行Excel文档的读写操作,实现报表的统计与汇总。在实际开发中,根据需求选择合适的API,并注意性能优化,可以提高代码的稳定性和效率。

    “Java POI 模板”打造复杂Excel报表.pdf

    POI(Poor Obfuscation Implementation)是一个Java API,用于读取和写入Microsoft Office文件格式,包括Excel文件。 首先,需要设计Excel报表模板,并将其保存为report.xls文件。该报表模板具有复杂的表头,第四...

    excel lib

    另一种选择是使用EPPlus库,它可以处理.xlsx文件,并提供了一种轻量级的方式来读写Excel数据。 Excel Lib 还可能涉及到的数据处理概念包括: 1. 工作簿(Workbook):Excel文件中的最高级别容器,包含一个或多个...

    java excel 透视

    在Java中,我们可以利用Apache POI库来实现Excel文件的读取、写入和操作,包括创建透视表。Apache POI是一个开源项目,提供了API来处理Microsoft Office格式的文件,如XLS(Excel 97-2003)和XLSX(Excel 2007及以上...

Global site tag (gtag.js) - Google Analytics