java如何写入excel?java写excel文件心得

在进行java项目开发的时候,我们经常会用到excel,有时候会进行excel的读取或者写入的工作,可是对于新手来说这不是一件容易的事情,那下面我们就给大家讲解一下java写excel文件心得!

1. 准备工作

1.1 在项目中引入Apache POI相关类库

引入 Apache POI 和 Apache POI-OOXML 这两个类库,Maven坐标如下:

<dependency>
 <groupId>org.apache.poi</groupId>
 <artifactId>poi</artifactId>
 <version>4.0.1</version>
 </dependency> <
 dependency >
     <groupId>org.apache.poi</groupId> <
     artifactId > poi - ooxml < /artifactId> <
     version > 4.0 .1 < /version> <
     /dependency>

2. 读取或写入Excel数据

2.1 示例程序结构说明

简单说明一下示例程序的整体结构:

ExcelReader.java是实现读取Excel数据功能的类;

ExcelWriter.java是创建新的Excel并向其中写入数据的类;

ExcelDataVO.java封装了读取或写入时每一“行”的数据;

MainTest.java是示例程序的入口类,其中演示了读取和写入Excel数据的整个过程;

2.2 读取数据

示例程序需要从桌面读取 readExample.xlsx 内的数据,readExample.xlsx 的内容如下:

java如何写入excel?java写excel文件心得.jpg

读取Excel时主要调用ExcelReader.java类来读取和解析Excel的具体内容,这里以读取系统文件的形式演示读取过程:(兼容 xls 和 xlsx)

2.2.1 主程序入口类代码:

/**
 * Author: Dreamer-1
 * Date: 2019-03-01
 * Time: 10:13
 * Description: 示例程序入口类
 */
public class MainTest
{
    public static void main(String[] args)
    {
        // 设定Excel文件所在路径
        String excelFileName = "/Users/Dreamer-1/Desktop/myBlog/java解析Excel/readExample.xlsx";
        // 读取Excel文件内容
        List < ExcelDataVO > readResult = ExcelReader.readExcel(excelFileName);
        // todo 进行业务操作
    }
}

读取和写入时封装每一“行”数据的ExcelDataVO.java代码如下:

/**
 * Author: Dreamer-1
 * Date: 2019-03-01
 * Time: 11:33
 * Description: 读取Excel时,封装读取的每一行的数据
 */
public class ExcelDataVO
{
    /**
     * 姓名
     */
    private String name;
    /**
     * 年龄
     */
    private Integer age;
    /**
     * 居住地
     */
    private String location;
    /**
     * 职业
     */
    private String job;
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public Integer getAge()
    {
        return age;
    }
    public void setAge(Integer age)
    {
        this.age = age;
    }
    public String getLocation()
    {
        return location;
    }
    public void setLocation(String location)
    {
        this.location = location;
    }
    public String getJob()
    {
        return job;
    }
    public void setJob(String job)
    {
        this.job = job;
    }
}

2.2.2 Excel解析类的代码:

/**
 * Author: Dreamer-1
 * Date: 2019-03-01
 * Time: 10:21
 * Description: 读取Excel内容
 */
public class ExcelReader
{
    private static Logger logger = Logger.getLogger(ExcelReader.class.getName()); // 日志打印类
    private static final String XLS = "xls";
    private static final String XLSX = "xlsx";
    /**
     * 根据文件后缀名类型获取对应的工作簿对象
     * @param inputStream 读取文件的输入流
     * @param fileType 文件后缀名类型(xls或xlsx)
     * @return 包含文件数据的工作簿对象
     * @throws IOException
     */
    public static Workbook getWorkbook(InputStream inputStream, String fileType) throws IOException
    {
        Workbook workbook = null;
        if (fileType.equalsIgnoreCase(XLS))
        {
            workbook = new HSSFWorkbook(inputStream);
        }
        else if (fileType.equalsIgnoreCase(XLSX))
        {
            workbook = new XSSFWorkbook(inputStream);
        }
        return workbook;
    }
    /**
     * 读取Excel文件内容
     * @param fileName 要读取的Excel文件所在路径
     * @return 读取结果列表,读取失败时返回null
     */
    public static List < ExcelDataVO > readExcel(String fileName)
    {
        Workbook workbook = null;
        FileInputStream inputStream = null;
        try
        {
            // 获取Excel后缀名
            String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
            // 获取Excel文件
            File excelFile = new File(fileName);
            if (!excelFile.exists())
            {
                logger.warning("指定的Excel文件不存在!");
                return null;
            }
            // 获取Excel工作簿
            inputStream = new FileInputStream(excelFile);
            workbook = getWorkbook(inputStream, fileType);
            // 读取excel中的数据
            List < ExcelDataVO > resultDataList = parseExcel(workbook);
            return resultDataList;
        }
        catch (Exception e)
        {
            logger.warning("解析Excel失败,文件名:" + fileName + " 错误信息:" + e.getMessage());
            return null;
        }
        finally
        {
            try
            {
                if (null != workbook)
                {
                    workbook.close();
                }
                if (null != inputStream)
                {
                    inputStream.close();
                }
            }
            catch (Exception e)
            {
                logger.warning("关闭数据流出错!错误信息:" + e.getMessage());
                return null;
            }
        }
    }
    /**
     * 解析Excel数据
     * @param workbook Excel工作簿对象
     * @return 解析结果
     */
    private static List < ExcelDataVO > parseExcel(Workbook workbook)
    {
        List < ExcelDataVO > resultDataList = new ArrayList < > ();
        // 解析sheet
        for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++)
        {
            Sheet sheet = workbook.getSheetAt(sheetNum);
            // 校验sheet是否合法
            if (sheet == null)
            {
                continue;
            }
            // 获取第一行数据
            int firstRowNum = sheet.getFirstRowNum();
            Row firstRow = sheet.getRow(firstRowNum);
            if (null == firstRow)
            {
                logger.warning("解析Excel失败,在第一行没有读取到任何数据!");
            }
            // 解析每一行的数据,构造数据对象
            int rowStart = firstRowNum + 1;
            int rowEnd = sheet.getPhysicalNumberOfRows();
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++)
            {
                Row row = sheet.getRow(rowNum);
                if (null == row)
                {
                    continue;
                }
                ExcelDataVO resultData = convertRowToData(row);
                if (null == resultData)
                {
                    logger.warning("第 " + row.getRowNum() + "行数据不合法,已忽略!");
                    continue;
                }
                resultDataList.add(resultData);
            }
        }
        return resultDataList;
    }
    /**
     * 将单元格内容转换为字符串
     * @param cell
     * @return
     */
    private static String convertCellValueToString(Cell cell)
    {
        if (cell == null)
        {
            return null;
        }
        String returnValue = null;
        switch (cell.getCellType())
        {
        case NUMERIC: //数字
            Double doubleValue = cell.getNumericCellValue();
            // 格式化科学计数法,取一位整数
            DecimalFormat df = new DecimalFormat("0");
            returnValue = df.format(doubleValue);
            break;
        case STRING: //字符串
            returnValue = cell.getStringCellValue();
            break;
        case BOOLEAN: //布尔
            Boolean booleanValue = cell.getBooleanCellValue();
            returnValue = booleanValue.toString();
            break;
        case BLANK: // 空值
            break;
        case FORMULA: // 公式
            returnValue = cell.getCellFormula();
            break;
        case ERROR: // 故障
            break;
        default:
            break;
        }
        return returnValue;
    }
    /**
     * 提取每一行中需要的数据,构造成为一个结果数据对象
     *
     * 当该行中有单元格的数据为空或不合法时,忽略该行的数据
     *
     * @param row 行数据
     * @return 解析后的行数据对象,行数据错误时返回null
     */
    private static ExcelDataVO convertRowToData(Row row)
    {
        ExcelDataVO resultData = new ExcelDataVO();
        Cell cell;
        int cellNum = 0;
        // 获取姓名
        cell = row.getCell(cellNum++);
        String name = convertCellValueToString(cell);
        resultData.setName(name);
        // 获取年龄
        cell = row.getCell(cellNum++);
        String ageStr = convertCellValueToString(cell);
        if (null == ageStr || "".equals(ageStr))
        {
            // 年龄为空
            resultData.setAge(null);
        }
        else
        {
            resultData.setAge(Integer.parseInt(ageStr));
        }
        // 获取居住地
        cell = row.getCell(cellNum++);
        String location = convertCellValueToString(cell);
        resultData.setLocation(location);
        // 获取职业
        cell = row.getCell(cellNum++);
        String job = convertCellValueToString(cell);
        resultData.setJob(job);
        return resultData;
    }
}

2.2.3 应用场景补充

一般我们会有这样的应用场景,即:在前台页面的文件上传入口上传本地的Excel文件到后台,后台收到Excel文件后进行解析并做对应的业务操作;

这里假设前台已经有了上传文件的入口,再简单贴一下后台的解析代码;

后台接收前台数据的Controller层代码示例:

@PostMapping("/uploadExcel")
 public ResponseEntity < ? > uploadImage(MultipartFile file)
 {
     // 检查前台数据合法性
     if (null == file || file.isEmpty())
     {
         logger.warning("上传的Excel商品数据文件为空!上传时间:" + new Date());
         return new ResponseEntity < > (HttpStatus.BAD_REQUEST);
     }
     try
     {
         // 解析Excel
         List < ExcelDataVO > parsedResult = ExcelReader.readExcel(file);
         // todo 进行业务操作
         return new ResponseEntity < > (HttpStatus.OK);
     }
     catch (Exception e)
     {
         logger.warning("上传的Excel商品数据文件为空!上传时间:" + new Date());
         return new ResponseEntity < > (HttpStatus.BAD_REQUEST);
     }
 }

ExcelReader.java中的 readExcel() 方法需要做一定的修改,代码如下:

/**
  * 读取Excel文件内容
  * @param file 上传的Excel文件
  * @return 读取结果列表,读取失败时返回null
  */
 public static List < ExcelDataVO > readExcel(MultipartFile file)
 {
     Workbook workbook = null;
     try
     {
         // 获取Excel后缀名
         String fileName = file.getOriginalFilename();
         if (fileName == null || fileName.isEmpty() || fileName.lastIndexOf(".") < 0)
         {
             logger.warning("解析Excel失败,因为获取到的Excel文件名非法!");
             return null;
         }
         String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
         // 获取Excel工作簿
         workbook = getWorkbook(file.getInputStream(), fileType);
         // 读取excel中的数据
         List < ExcelDataVO > resultDataList = parseExcel(workbook);
         return resultDataList;
     }
     catch (Exception e)
     {
         logger.warning("解析Excel失败,文件名:" + file.getOriginalFilename() + " 错误信息:" + e.getMessage());
         return null;
     }
     finally
     {
         try
         {
             if (null != workbook)
             {
                 workbook.close();
             }
         }
         catch (Exception e)
         {
             logger.warning("关闭数据流出错!错误信息:" + e.getMessage());
             return null;
         }
     }
 }

2.3 写入数据

写入数据时主要调用ExcelWriter.java来创建Excel工作簿对象并写入数据,这里以写入系统文件数据为例演示写入的过程:

2.3.1 主程序入口类代码

/**
 * Author: Dreamer-1
 * Date: 2019-03-01
 * Time: 10:13
 * Description: 示例程序入口类
 */
public class MainTest
{
    private static Logger logger = Logger.getLogger(MainTest.class.getName());
    public static void main(String[] args)
    {
        // 创建需要写入的数据列表
        List < ExcelDataVO > dataVOList = new ArrayList < > (2);
        ExcelDataVO dataVO = new ExcelDataVO();
        dataVO.setName("小明");
        dataVO.setAge(18);
        dataVO.setLocation("广州");
        dataVO.setJob("大学生");
        ExcelDataVO dataVO2 = new ExcelDataVO();
        dataVO2.setName("小花");
        dataVO2.setAge(19);
        dataVO2.setLocation("深圳");
        dataVO2.setJob("大学生");
        dataVOList.add(dataVO);
        dataVOList.add(dataVO2);
        // 写入数据到工作簿对象内
        Workbook workbook = ExcelWriter.exportData(dataVOList);
        // 以文件的形式输出工作簿对象
        FileOutputStream fileOut = null;
        try
        {
            String exportFilePath = "/Users/Dreamer-1/Desktop/myBlog/java解析Excel/writeExample.xlsx";
            File exportFile = new File(exportFilePath);
            if (!exportFile.exists())
            {
                exportFile.createNewFile();
            }
            fileOut = new FileOutputStream(exportFilePath);
            workbook.write(fileOut);
            fileOut.flush();
        }
        catch (Exception e)
        {
            logger.warning("输出Excel时发生错误,错误原因:" + e.getMessage());
        }
        finally
        {
            try
            {
                if (null != fileOut)
                {
                    fileOut.close();
                }
                if (null != workbook)
                {
                    workbook.close();
                }
            }
            catch (IOException e)
            {
                logger.warning("关闭输出流时发生错误,错误原因:" + e.getMessage());
            }
        }
    }
}

2.3.2 写入Excel类的代码

ExcelWriter.java类中,你可以根据实际需要替换 CELL_HEADS 列头的信息,然后重写 convertDataToRow 方法,转换你自己的行数据;

/**
 * Author: Dreamer-1
 * Date: 2019-03-01
 * Time: 11:09
 * Description: 生成Excel并写入数据
 */
public class ExcelWriter
{
    private static List < String > CELL_HEADS; //列头
    static
    {
        // 类装载时就载入指定好的列头信息,如有需要,可以考虑做成动态生成的列头
        CELL_HEADS = new ArrayList < > ();
        CELL_HEADS.add("姓名");
        CELL_HEADS.add("年龄");
        CELL_HEADS.add("居住城市");
        CELL_HEADS.add("职业");
    }
    /**
     * 生成Excel并写入数据信息
     * @param dataList 数据列表
     * @return 写入数据后的工作簿对象
     */
    public static Workbook exportData(List < ExcelDataVO > dataList)
    {
        // 生成xlsx的Excel
        Workbook workbook = new SXSSFWorkbook();
        // 如需生成xls的Excel,请使用下面的工作簿对象,注意后续输出时文件后缀名也需更改为xls
        //Workbook workbook = new HSSFWorkbook();
        // 生成Sheet表,写入第一行的列头
        Sheet sheet = buildDataSheet(workbook);
        //构建每行的数据内容
        int rowNum = 1;
        for (Iterator < ExcelDataVO > it = dataList.iterator(); it.hasNext();)
        {
            ExcelDataVO data = it.next();
            if (data == null)
            {
                continue;
            }
            //输出行数据
            Row row = sheet.createRow(rowNum++);
            convertDataToRow(data, row);
        }
        return workbook;
    }
    /**
     * 生成sheet表,并写入第一行数据(列头)
     * @param workbook 工作簿对象
     * @return 已经写入列头的Sheet
     */
    private static Sheet buildDataSheet(Workbook workbook)
    {
        Sheet sheet = workbook.createSheet();
        // 设置列头宽度
        for (int i = 0; i < CELL_HEADS.size(); i++)
        {
            sheet.setColumnWidth(i, 4000);
        }
        // 设置默认行高
        sheet.setDefaultRowHeight((short) 400);
        // 构建头单元格样式
        CellStyle cellStyle = buildHeadCellStyle(sheet.getWorkbook());
        // 写入第一行各列的数据
        Row head = sheet.createRow(0);
        for (int i = 0; i < CELL_HEADS.size(); i++)
        {
            Cell cell = head.createCell(i);
            cell.setCellValue(CELL_HEADS.get(i));
            cell.setCellStyle(cellStyle);
        }
        return sheet;
    }
    /**
     * 设置第一行列头的样式
     * @param workbook 工作簿对象
     * @return 单元格样式对象
     */
    private static CellStyle buildHeadCellStyle(Workbook workbook)
    {
        CellStyle style = workbook.createCellStyle();
        //对齐方式设置
        style.setAlignment(HorizontalAlignment.CENTER);
        //边框颜色和宽度设置
        style.setBorderBottom(BorderStyle.THIN);
        style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); // 下边框
        style.setBorderLeft(BorderStyle.THIN);
        style.setLeftBorderColor(IndexedColors.BLACK.getIndex()); // 左边框
        style.setBorderRight(BorderStyle.THIN);
        style.setRightBorderColor(IndexedColors.BLACK.getIndex()); // 右边框
        style.setBorderTop(BorderStyle.THIN);
        style.setTopBorderColor(IndexedColors.BLACK.getIndex()); // 上边框
        //设置背景颜色
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        //粗体字设置
        Font font = workbook.createFont();
        font.setBold(true);
        style.setFont(font);
        return style;
    }
    /**
     * 将数据转换成行
     * @param data 源数据
     * @param row 行对象
     * @return
     */
    private static void convertDataToRow(ExcelDataVO data, Row row)
    {
        int cellNum = 0;
        Cell cell;
        // 姓名
        cell = row.createCell(cellNum++);
        cell.setCellValue(null == data.getName() ? "" : data.getName());
        // 年龄
        cell = row.createCell(cellNum++);
        if (null != data.getAge())
        {
            cell.setCellValue(data.getAge());
        }
        else
        {
            cell.setCellValue("");
        }
        // 所在城市
        cell = row.createCell(cellNum++);
        cell.setCellValue(null == data.getLocation() ? "" : data.getLocation());
        // 职业
        cell = row.createCell(cellNum++);
        cell.setCellValue(null == data.getJob() ? "" : data.getJob());
    }
}

示例程序运行后将会在指定的系统路径下生成 writeExample.xlsx文件,其内容如下:

1.jpg

2.3.3 应用场景补充

一般写入Excel时会有这样的场景:前台页面上有一个导出按钮,点击后将后台某张表里的数据以Excel的形式导出,导出的Excel文件通过浏览器下载到用户系统中;

这里默认前台页面已经有相应的按钮功能,给出对应的Controller层代码供参考:

@GetMapping("/exportExcel")
 public void exportExcel(HttpServletRequest request, HttpServletResponse response)
 {
     Workbook workbook = null;
     OutputStream out = null;
     try
     {
         // todo 根据业务需求获取需要写入Excel的数据列表 dataList
         // 生成Excel工作簿对象并写入数据
         workbook = ExcelWriter.exportData(dataList);
         // 写入Excel文件到前端
         if (null != workbook)
         {
             String excelName = "示例Excel导出";
             String fileName = excelName + DateUtil.format(new Date(), DateUtil.SHORT_DATE) + ".xlsx";
             fileName = new String(fileName.getBytes("UTF-8"), "iso8859-1");
             response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
             response.setContentType("application/x-download");
             response.setCharacterEncoding("UTF-8");
             response.addHeader("Pargam", "no-cache");
             response.addHeader("Cache-Control", "no-cache");
             response.flushBuffer();
             out = response.getOutputStream();
             workbook.write(out);
             out.flush();
         }
     }
     catch (Exception e)
     {
         logger.WARNING("写入Excel过程出错!错误原因:" + e.getMessage());
     }
     finally
     {
         try
         {
             if (null != workbook)
             {
                 workbook.close();
             }
             if (null != out)
             {
                 out.close();
             }
         }
         catch (IOException e)
         {
             logger.WARNING("关闭workbook或outputStream出错!");
         }
     }
 }
// 前台页面发送请求到后台Controller时的JS代码可参考:
var url = "/exportExcel";
window.location = url;

这样我们就完成了java写excel的方法步骤,虽然看起来步骤有些长,不过都是一些流程性的步骤,只要我们掌握了就好了!最后大家如果想要了解更多java实例知识,敬请关注奇Q工具网。

推荐阅读:

JAVA写程序怎么在手机上运行?Java程序如何执行?

java反射机制有什么用?Java远程如何调用反射机制?

程序员面试自我介绍怎么说?如何做好自我介绍?