乐趣区

关于java:Java实现文件批量导入导出实践兼容xlsxlsx

小 Hub 领读:

应用 poi 导入导出 xls 文件还是比拟容易的,有残缺的我的项目代码,能够 clone 下来好好钻研哈!


  • 作者:小卖铺的老爷爷
  • https://cnblogs.com/laoyeye/p…
  • https://github.com/allanzhuo/…

1、介绍

java 实现文件的导入导出数据库,目前在大部分零碎中是比拟常见的性能了,明天写个小 demo 来了解其原理,没接触过的同学也能够看看参考下。

目前我所接触过的导入导出技术次要有 POI 和 iReport,poi 次要作为一些数据批量导入数据库,iReport 做报表导出。另外还有 jxl 相似 poi 的形式,不过貌似很久没跟新了,2007 之后的 office 如同也不反对,这里就不说了。

2、POI 应用详解

2.1 什么是 Apache POI?

Apache POI 是 Apache 软件基金会的开放源码函式库,POI 提供 API 给 Java 程序对 Microsoft Office 格局档案读和写的性能。

2.2 POI 的 jar 包导入

本次解说应用 maven 工程,jar 包版本应用 poi-3.14 和 poi-ooxml-3.14。目前最新的版本是 3.16。因为 3.15 当前相干 api 有更新,局部操作可能不一样,大家留神下。

<!-- poi 的包 3.15 版本后单元格类型获取形式有调整 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.14</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.14</version>
        </dependency>

2.3 POI 的 API 解说

2.3.1 构造

HSSF - 提供读写 Microsoft Excel 格局档案的性能。
XSSF - 提供读写 Microsoft Excel OOXML 格局档案的性能。
HWPF - 提供读写 Microsoft Word 格局档案的性能。
HSLF - 提供读写 Microsoft PowerPoint 格局档案的性能。
HDGF - 提供读写 Microsoft Visio 格局档案的性能。

2.3.2 对象

本文次要介绍 HSSF 和 XSSF 两种组件,简略的讲 HSSF 用来操作 Office 2007 版本前 excel.xls 文件,XSSF 用来操作 Office 2007 版本后的 excel.xlsx 文件,留神二者的后缀是不一样的。

HSSF 在 org.apache.poi.hssf.usermodel 包中。它实现了 Workbook 接口,用于 Excel 文件中的. xls 格局

罕用组件:

HSSFWorkbook : excel 的文档对象
HSSFSheet : excel 的表单
HSSFRow : excel 的行
HSSFCell : excel 的格子单元
HSSFFont : excel 字体
HSSFDataFormat: 日期格局
HSSFHeader : sheet 头
HSSFFooter : sheet 尾(只有打印的时候能力看到成果)

款式:

HSSFCellStyle : cell 款式

辅助操作包含:

HSSFDateUtil : 日期
HSSFPrintSetup : 打印
HSSFErrorConstants : 错误信息表

XSSF 在 org.apache.xssf.usemodel 包,并实现 Workbook 接口,用于 Excel 文件中的. xlsx 格局

罕用组件:

XSSFWorkbook : excel 的文档对象
XSSFSheet: excel 的表单
XSSFRow: excel 的行
XSSFCell: excel 的格子单元
XSSFFont: excel 字体
XSSFDataFormat : 日期格局

和 HSSF 相似;

2.3.3 两个组件独特的字段类型形容

其实两个组件就是针对 excel 的两种格局,大部分的操作都是雷同的。

 单元格类型                        形容
CELL_TYPE_BLANK          代表空白单元格
CELL_TYPE_BOOLEAN        代表布尔单元(true 或 false)CELL_TYPE_ERROR          示意在单元的误差值
CELL_TYPE_FORMULA        示意一个单元格公式的后果
CELL_TYPE_NUMERIC        示意对一个单元的数字数据
CELL_TYPE_STRING         示意对一个单元串(文本)

2.3.4 操作步骤

以 HSSF 为例,XSSF 操作雷同。

首先,了解一下一个 Excel 的文件的组织模式,一个 Excel 文件对应于一个 workbook(HSSFWorkbook),一个 workbook 能够有多个 sheet(HSSFSheet)组成,一个 sheet 是由多个 row(HSSFRow)组成,一个 row 是由多个 cell(HSSFCell)组成。

1、用 HSSFWorkbook 关上或者创立“Excel 文件对象”

2、用 HSSFWorkbook 对象返回或者创立 Sheet 对象

3、用 Sheet 对象返回行对象,用行对象失去 Cell 对象

4、对 Cell 对象读写。

3、代码操作

3.1 效果图

常规,贴代码前先看效果图

Excel 文件两种格局各一个:

代码构造:

导入后:(我导入了两遍,没做校验)

导出成果:

3.2 代码详解

这里我以 Spring+SpringMVC+Mybatis 为根底

Controller:

package com.allan.controller;

import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.ss.formula.functions.Mode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.allan.pojo.Student;
import com.allan.service.StudentService;
/**
 * 
 * @author 小卖铺的老爷爷
 *
 */
@Controller
public class StudentController {
    @Autowired
    private StudentService studentService;
    /**
     * 批量导入表单数据
     * 
     * @param request
     * @param myfile
     * @return
     */

    @RequestMapping(value="/importExcel",method=RequestMethod.POST)
    public String importExcel(@RequestParam("myfile") MultipartFile myFile) {ModelAndView modelAndView = new ModelAndView();
        try {Integer num = studentService.importExcel(myFile);
        } catch (Exception e) {modelAndView.addObject("msg", e.getMessage());
            return "index";
        }
        modelAndView.addObject("msg", "数据导入胜利");

        return "index";
    }

    @RequestMapping(value="/exportExcel",method=RequestMethod.GET)
    public void exportExcel(HttpServletResponse response) {    
        try {studentService.exportExcel(response);
        } catch (Exception e) {e.printStackTrace();
        }
    }



}

Service

package com.allan.service.impl;

import java.io.OutputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
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.ss.usermodel.Cell;
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.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.allan.mapper.StudentMapper;
import com.allan.pojo.Student;
import com.allan.service.StudentService;
/**
 * 
 * @author 小卖铺的老爷爷
 *
 */
@Service
public class StudentServiceImpl implements StudentService{
    private final static String XLS = "xls";  
    private final static String XLSX = "xlsx"; 
    @Autowired
    private StudentMapper studentMapper;
    /**
     * 导入 Excel,兼容 xls 和 xlsx
     */
    @SuppressWarnings("resource")
    public Integer importExcel(MultipartFile myFile) throws Exception {
        //        1、用 HSSFWorkbook 关上或者创立“Excel 文件对象”//
        //        2、用 HSSFWorkbook 对象返回或者创立 Sheet 对象
        //
        //        3、用 Sheet 对象返回行对象,用行对象失去 Cell 对象
        //
        //        4、对 Cell 对象读写。// 取得文件名  
        Workbook workbook = null ;
        String fileName = myFile.getOriginalFilename(); 
        if(fileName.endsWith(XLS)){  
            //2003  
            workbook = new HSSFWorkbook(myFile.getInputStream());  
        }else if(fileName.endsWith(XLSX)){  
            //2007  
            workbook = new XSSFWorkbook(myFile.getInputStream());  
        }else{throw new Exception("文件不是 Excel 文件");
        }

        Sheet sheet = workbook.getSheet("Sheet1");
        int rows = sheet.getLastRowNum();// 指的行数,一共有多少行 +
        if(rows==0){throw new Exception("请填写数据");
        }
        for (int i = 1; i <= rows+1; i++) {
            // 读取左上端单元格
            Row row = sheet.getRow(i);
            // 行不为空
            if (row != null) {
                // ** 读取 cell**
                Student student = new Student();
                // 姓名
                String name = getCellValue(row.getCell(0));
                student.setName(name);
                // 班级
                String classes = getCellValue(row.getCell(1));
                student.setClasses(classes);
                // 分数
                String scoreString = getCellValue(row.getCell(2));
                if (!StringUtils.isEmpty(scoreString)) {Integer score = Integer.parseInt(scoreString);
                    student.setScore(score);
                }
                // 考试工夫
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");// 小写的 mm 示意的是分钟  
                String dateString = getCellValue(row.getCell(3));  
                if (!StringUtils.isEmpty(dateString)) {Date date=sdf.parse(dateString);  
                    student.setTime(date);
                }
                studentMapper.insert(student);
            }
        }
        return rows-1;
    }

    /**
     * 取得 Cell 内容
     * 
     * @param cell
     * @return
     */
    public String getCellValue(Cell cell) {
        String value = "";
        if (cell != null) {
            // 以下是判断数据的类型
            switch (cell.getCellType()) {
            case HSSFCell.CELL_TYPE_NUMERIC: // 数字
                value = cell.getNumericCellValue() + "";
                if (HSSFDateUtil.isCellDateFormatted(cell)) {Date date = cell.getDateCellValue();
                    if (date != null) {value = new SimpleDateFormat("yyyy-MM-dd").format(date);
                    } else {value = "";}
                } else {value = new DecimalFormat("0").format(cell.getNumericCellValue());
                }
                break;
            case HSSFCell.CELL_TYPE_STRING: // 字符串
                value = cell.getStringCellValue();
                break;
            case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean
                value = cell.getBooleanCellValue() + "";
                break;
            case HSSFCell.CELL_TYPE_FORMULA: // 公式
                value = cell.getCellFormula() + "";
                break;
            case HSSFCell.CELL_TYPE_BLANK: // 空值
                value = "";
                break;
            case HSSFCell.CELL_TYPE_ERROR: // 故障
                value = "非法字符";
                break;
            default:
                value = "未知类型";
                break;
            }
        }
        return value.trim();}
    /**
     * 导出 excel 文件
     */
    public void exportExcel(HttpServletResponse response) throws Exception {
        // 第一步,创立一个 webbook,对应一个 Excel 文件  
        HSSFWorkbook wb = new HSSFWorkbook();  
        // 第二步,在 webbook 中增加一个 sheet, 对应 Excel 文件中的 sheet  
        HSSFSheet sheet = wb.createSheet("Sheet1");  
        // 第三步,在 sheet 中增加表头第 0 行, 留神老版本 poi 对 Excel 的行数列数有限度 short  
        HSSFRow row = sheet.createRow(0);  
        // 第四步,创立单元格,并设置值表头 设置表头居中  
        HSSFCellStyle style = wb.createCellStyle();  
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 创立一个居中格局  

        HSSFCell cell = row.createCell(0);
        cell.setCellValue("姓名");  
        cell.setCellStyle(style);  
        cell = row.createCell(1);  
        cell.setCellValue("班级");  
        cell.setCellStyle(style);  
        cell = row.createCell(2);  
        cell.setCellValue("分数");  
        cell.setCellStyle(style);  
        cell = row.createCell(3);  
        cell.setCellValue("工夫");  
        cell.setCellStyle(style);  

        // 第五步,写入实体数据 理论利用中这些数据从数据库失去,List<Student> list = studentMapper.selectAll();  

        for (int i = 0; i < list.size(); i++){row = sheet.createRow(i + 1);  
            Student stu = list.get(i);  
            // 第四步,创立单元格,并设置值  
            row.createCell(0).setCellValue(stu.getName());  
            row.createCell(1).setCellValue(stu.getClasses());  
            row.createCell(2).setCellValue(stu.getScore());  
            cell = row.createCell(3);  
            cell.setCellValue(new SimpleDateFormat("yyyy-MM-dd").format(stu.getTime()));  
        }          
        // 第六步, 输入 Excel 文件
        OutputStream output=response.getOutputStream();
        response.reset();
        long filename = System.currentTimeMillis();
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");// 设置日期格局
        String fileName = df.format(new Date());// new Date() 为获取以后零碎工夫
        response.setHeader("Content-disposition", "attachment; file);
        response.setContentType("application/msexcel");        
        wb.write(output);
        output.close();}  

}

3.3 导出文件 api 补充

大家能够看到下面 service 的代码只是最根本的导出。

在理论利用中导出的 Excel 文件往往须要浏览和打印的,这就须要对输入的 Excel 文档进行排版和款式的设置,次要操作有合并单元格、设置单元格款式、设置字体款式等。

3.3.1 单元格合并

应用 HSSFSheet 的 addMergedRegion() 办法

public int addMergedRegion(CellRangeAddress region)

参数 CellRangeAddress 示意合并的区域,构造方法如下:顺次示意起始行,截至行,起始列,截至列

CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol)

3.3.2 设置单元格的行高和列宽

HSSFSheet sheet=wb.createSheet();
sheet.setDefaultRowHeightInPoints(10);// 设置缺省列高 sheet.setDefaultColumnWidth(20);// 设置缺省列宽
// 设置指定列的列宽,256 * 50 这种写法是因为 width 参数单位是单个字符的 256 分之一
sheet.setColumnWidth(cell.getColumnIndex(), 256 * 50);

3.3.3 设置单元格款式

1、创立 HSSFCellStyle

HSSFCellStyle cellStyle=wkb.createCellStyle()

2、设置款式

// 设置单元格的横向和纵向对齐形式,具体参数就不列了,参考 HSSFCellStyle
  cellStyle.setAlignment(HSSFCellStyle.ALIGN_JUSTIFY);
  cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
  /* 设置单元格的填充形式,以及前景色彩和背景色彩
   三点留神:1. 如果须要前景色彩或背景色彩,肯定要指定填充形式,两者程序无所谓;2. 如果同时存在前景色彩和背景色彩,前景色彩的设置要写在后面;3. 前景色彩不是字体色彩。*/
  // 设置填充形式 (填充图案)
  cellStyle.setFillPattern(HSSFCellStyle.DIAMONDS);
  // 设置前景色
  cellStyle.setFillForegroundColor(HSSFColor.RED.index);
  // 设置背景色彩
  cellStyle.setFillBackgroundColor(HSSFColor.LIGHT_YELLOW.index);
  // 设置单元格底部的边框及其款式和色彩
  // 这里仅设置了底边边框,左边框、左边框和顶边框同理可设
  cellStyle.setBorderBottom(HSSFCellStyle.BORDER_SLANTED_DASH_DOT);
  cellStyle.setBottomBorderColor(HSSFColor.DARK_RED.index);
  // 设置日期型数据的显示款式
  cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm"));

3、将款式利用于单元格

  cell.setCellStyle(cellStyle);
  // 将款式利用到行,但有些款式只对单元格起作用
  row.setRowStyle(cellStyle);

3.3.4 设置字体款式

1、创立 HSSFFont 对象(调用 HSSFWorkbook 的 createFont 办法)

HSSFWorkbook wb=new HSSFWorkbook();
HSSFFont  fontStyle=wb.createFont();
HSSFWorkbook wb=new HSSFWorkbook ();

2、设置字体各种款式

// 设置字体款式
  fontStyle.setFontName("宋体");  
  // 设置字体高度
  fontStyle.setFontHeightInPoints((short)20);  
  // 设置字体色彩
  font.setColor(HSSFColor.BLUE.index);
  // 设置粗体
  fontStyle.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
  // 设置斜体
  font.setItalic(true);
  // 设置下划线
  font.setUnderline(HSSFFont.U_SINGLE);

3、将字体设置到单元格款式

// 字体也是单元格格局的一部分,所以从属于 HSSFCellStyle
// 将字体对象赋值给单元格款式对象
cellStyle.setFont(font);
// 将单元格款式利用于单元格
cell.setCellStyle(cellStyle);

大家能够看出用 poi 导出文件还是比拟麻烦的,等下次在为大家介绍下 irport 的办法。

导出的 api 基本上就是这些,最初也心愿上文对大家能有所帮忙。

源码地址:https://github.com/allanzhuo/…

(完)

举荐浏览

太赞了,这个 Java 网站,什么我的项目都有!https://markerhub.com

这个 B 站的 UP 主,讲的 java 真不错!

太赞了!最新版 Java 编程思维能够在线看了!

退出移动版