Java中如何进行读写Excel的操作


=Start=

缘由:

整理总结一下在Java中如何借助Apache POI实现Excel的读、写操作,方便有需要的时候参考和理解。

正文:

参考解答:

写Excel的基本步骤

  1. 创建一个 workbook
  2. 创建一个 sheet
  3. 重复如下步骤直到数据被写入完成:
    • 创建一个 row
    • 在 row 中创建 cells ,如果要设置格式的话可以用 CellStyle
  4. 将 workbook 写入 FileOutputStream
  5. 关闭 FileOutputStream
  6. 关闭 workbook
一个简单的写Excel的代码样例
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileOutputStream;
import java.io.IOException;

public class WriteExcel {
    public static void main(String[] args) {
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet sheet = workbook.createSheet("Java-Books");

        Object[][] bookData = {
                {"Head First Java", "Kathy Serria", 79},
                {"Effective Java", "Joshua Bloch", 36},
                {"Clean Code", "Robert martin", 42},
                {"Thinking in Java", "Bruce Eckel", 35},
        };

        int rowCount = 0;
        for (Object[] aBook : bookData) {
            Row row = sheet.createRow(rowCount++);

            int columnCount = 0;

            for (Object field : aBook) {
                Cell cell = row.createCell(columnCount++);
                if (field instanceof String) {
                    cell.setCellValue((String) field);
                } else if (field instanceof Integer) {
                    cell.setCellValue((Integer) field);
                }
            }

        }

        // 将 workbook 写入 FileOutputStream 存文件
        try (FileOutputStream outputStream = new FileOutputStream("JavaBooks.xlsx")) {
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        workbook.close();
    }
}
一个读Excel内容及其元信息的代码样例
import org.apache.poi.ooxml.POIXMLProperties;
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.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties;

import java.io.*;
import java.util.Iterator;

public class ReadExcel {
    public static void main(String[] args) {
        String excelFilePath = "JavaBooks.xlsx";
        
        try {
            FileInputStream inputStream = new FileInputStream(new File(excelFilePath));
            Workbook workbook = new XSSFWorkbook(inputStream);

            int sheetNum = workbook.getNumberOfSheets();
            System.out.println("Number of sheet: " + sheetNum);
            for (int i = 0; i < sheetNum; i++) {
                Sheet sheet = workbook.getSheetAt(i);
                System.out.println(sheet.getSheetName());
                Iterator<Row> iterator = sheet.iterator();

                while (iterator.hasNext()) {
                    Row nextRow = iterator.next();
                    Iterator<Cell> cellIterator = nextRow.cellIterator();

                    while (cellIterator.hasNext()) {
                        Cell cell = cellIterator.next();

                        switch (cell.getCellType()) {
                            case STRING:
                                System.out.print(cell.getStringCellValue());
                                break;
                            case BOOLEAN:
                                System.out.print(cell.getBooleanCellValue());
                                break;
                            case NUMERIC:
                                System.out.print(cell.getNumericCellValue());
                                break;
                        }
                        System.out.print(" - ");
                    }
                    System.out.println();
                }
                System.out.println();
            }
            System.out.println();

            /* Get properties info of excel */
            POIXMLProperties props = ((XSSFWorkbook) workbook).getProperties();

            /* Let us set some core properties now */
            POIXMLProperties.CoreProperties coreProp = props.getCoreProperties();
            System.out.println(coreProp.getCreator());
            System.out.println(coreProp.getCategory());
            coreProp.setCreator("zero"); // set document creator
            coreProp.setDescription("set Metadata via Apache POI in Java");
            coreProp.setCategory("Programming"); // category

            /* We can set some custom Properties now */
            POIXMLProperties.CustomProperties customProp = props.getCustomProperties();
            // java.lang.IllegalArgumentException: A property with this name already exists in the custom properties
            // addProperty() 不能对已有的 name 进行再次添加,否则会抛出异常
            customProp.addProperty("Author", "zero");// String
            customProp.addProperty("Year", 2020); // Number Property
            customProp.addProperty("Published", true); // Yes No Property
            customProp.addProperty("Typist", "zero");
            CTProperties ctProperties = customProp.getUnderlyingProperties();
            for (int i = 0; i < ctProperties.sizeOfPropertyArray(); i++) {
                System.out.print(i + "\t");
                System.out.println(ctProperties.getPropertyArray(i));
            }

            POIXMLProperties.ExtendedProperties extendedProp = props.getExtendedProperties();
            System.out.println(extendedProp.getCompany()); // null
            extendedProp.setCompany("test");
            System.out.println(extendedProp.getCompany()); // test

            /* Save modification to properties */
            FileOutputStream outputStream = new FileOutputStream(new File(excelFilePath));
            workbook.write(outputStream);
            outputStream.close();

            workbook.close();
            inputStream.close();

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

    }
}
参考链接:

How to Read Excel Files in Java using Apache POI
https://www.codejava.net/coding/how-to-read-excel-files-in-java-using-apache-poi

Java Example to Read Password-protected Excel Files Using Apache POI
https://www.codejava.net/coding/java-example-to-read-password-protected-excel-files-using-apache-poi

Java Example to Update Existing Excel Files Using Apache POI
https://www.codejava.net/coding/java-example-to-update-existing-excel-files-using-apache-poi

How to Write Excel Files in Java using Apache POI
https://www.codejava.net/coding/how-to-write-excel-files-in-java-using-apache-poi

https://mvnrepository.com/artifact/org.apache.poi/poi
https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml
https://mvnrepository.com/artifact/org.apache.commons/commons-compress

Java 使用 POI 操作 Excel
https://juejin.im/post/5c09e559e51d451da152df9c

POI核心类
https://www.yiibai.com/apache_poi/apache_poi_core_classes.html

java excel添加水印
https://www.jianshu.com/p/5ebf2217f0be

https://stackoverflow.com/questions/3454975/writing-to-excel-in-java

Java Code Examples for org.apache.poi.POIXMLProperties
https://www.programcreek.com/java-api-examples/?api=org.apache.poi.POIXMLProperties

Java Examples for org.apache.poi.POIXMLProperties
https://www.javatips.net/api/org.apache.poi.poixmlproperties

how to write metadata into Excel workbooks using Apache POI in Java
https://stackoverflow.com/questions/43796819/how-to-write-metadata-into-excel-workbooks-using-apache-poi-in-java

Read / Write Metadata – Excel POI Example
https://thinktibits.blogspot.com/2014/07/read-write-metadata-excel-poi-example.html

poi4.0.0读取excel文件时报java.lang.NoClassDefFoundError: org/apache/commons/compress/archivers/zip/ZipFile
https://blog.csdn.net/redsoft_mymuch/article/details/84099902

JAVA简单快速的读写Excel之EasyExcel
https://www.lifengdi.com/archives/article/1393
https://alibaba-easyexcel.github.io/index.html
https://github.com/alibaba/easyexcel

java excel添加水印
https://www.jianshu.com/p/5ebf2217f0be
https://juejin.im/post/5d1edde051882542cf1009dc

=END=


《 “Java中如何进行读写Excel的操作” 》 有 12 条评论

  1. Apache POI 的 设置单元格内容报错 java.lang.IllegalArgumentException: The maximum length of cell contents (text) is 32767 characters
    https://stackoverflow.com/questions/31935340/increase-the-maximum-length-of-hssfcell-in-java
    `
    # 简而言之就是——没有办法,32767个字符是Excel这类文件格式的限制,Apache POI仅仅是加强了这个限制的检查,并无法修改这个限制。
    Your only option is to switch file formats. There’s a hard limit in both the .xls and .xlsx file formats of 32,767 characters. Apache POI is simply enforcing the file format + Excel limit.
    `
    https://poi.apache.org/apidocs/dev/org/apache/poi/ss/SpreadsheetVersion.html

    [Apache POI] java.lang.IllegalArgumentException: The maximum length of cell contents (text) is 32,767 characters
    https://albert-kuo.blogspot.com/2016/12/apache-poi-javalangillegalargumentexcep.html
    https://blog.csdn.net/jiewenike/article/details/54907037

  2. Apache POI中的 setCellValue 操作出现NPE 异常
    `
    用Apache POI操作时,createCell 创建最多报 IllegalArgumentException 异常,不会有 NPE 异常,那个只会出现在 setCellValue 设置单元格内容时出现,原因就是设置的值类型为 null ,而且简单测可能还不容易发现,比如:

    JSONObject jsonObject = new JSONObject();

    Cell cell = row.createCell(columnCount++);
    System.out.println(jsonObject.getIntValue(“key1”));
    cell.setCellValue(jsonObject.getIntValue(“key1”)); // 正常,因为即便取不到key1的value会默认返回0

    String data = null;
    cell = row.createCell(columnCount++);
    cell.setCellValue(data); // 它说他对null做了容错处理,不会报 NPE 异常

    cell = row.createCell(columnCount++);
    System.out.println(jsonObject.getInteger(“key1”));
    cell.setCellValue(jsonObject.getInteger(“key1”)); // NPE
    `
    http://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/Row.html#createCell-int-
    http://apache-poi.1045710.n5.nabble.com/Bug-59199-New-setting-null-value-to-date-cell-leads-to-NPE-td5722365.html
    https://www.experts-exchange.com/questions/23180270/How-to-avoid-NullPointerException-in-excel-writing.html
    https://stackoverflow.com/questions/20694915/apachi-poi-cell-setcellvalue-thows-nullpointerexception

  3. Office文件追踪方案探索
    https://www.freebuf.com/articles/database/246984.html
    `
    # 背景
    office套件已经成为大家日常办公必不可少的工具,丰富的文字编辑、演示文稿以及数据处理能力,无一不展示其强大的功能。然后随着形式的多样性,文件的保存和传输让office成为共享、协同的常用方案,而对于一些包含敏感数据的文件,当文件被有意或无意泄漏,可能就会对企业造成无法挽回的损失。本文将对word和excel文件的追踪方案进行探索,通过对文件植入URL,当文件被打开时,即可自动触发HTTP请求,从而获取IP等定位信息,间接降低敏感数据恶意扩散传播的风险。

    # word文件追踪 -任意内容的docx文件嵌入
    office文件本质上是一个压缩包,是有很多xml和一些其他类型文件打包成的,所以该docx是可以解压缩的,至于如何解压缩,Windows上多数可以直接解压,Mac上可以改一下后缀为test.rar,然后解压。解压之后一般都会看_rels、[Content_Types].xml、docProps、word。 这里不对文件展开来介绍了,有兴趣的可以自行了解,前三个文件(夹)基本都是本身的全局配置,office系列的文件这些基本都一致,而word文件夹就是针对docx特有的了,主要包含了整个word内容;查看_rels文件夹中,会发现有一个叫做settings.xml.rels的文件。
    word/settings.xml文件

    # excel文件追踪 -任意内容的xlsx文件嵌入
    对于Excel的文件追踪方式,首先想到的是word版的方案,可惜的是,虽然同样可以按照模板创建文件,但是并不支持嵌入链接。那么有没有比较好的方案能够实现xlsx文件同样的效果呢?下面就介绍一个“不完美”的方案。
    解压xlsx文件,不出意外的话得到_rels、[Content_Types].xml、docProps、xl。这里可以看到,和docx文件唯一不同的就是xl文件夹,这里就是excel文件的核心内容。寻找线索之前,可以大体上能确定一个逻辑,就是应该存在两个关键配置文件,其中一个的内容引用了图片资源的位置,另一个文件则是引用了这个配置文件。根据这个思路,首先可以明确看到图片资源在media文件夹中,然后根据文件名搜索可以定位到drawings/_rels/drawing1.xml.rels文件中。
    不难想到,在Target=”../media/image1.png”这再追加一个属性TargetMode=”External”,代表外部链接,然后修改”../media/image1.png”为钓鱼URL,重新打包后就可以发现,实现了追踪效果。此时出现了同样的问题,如何在任何xlsx文件下都可以支持,并且多了一个问题,如何隐藏这个图片?

    # office文件暗水印
    有网络请求的地方,往往是不稳定的,所以除了能够追踪文件的打开路径,还需要配合暗水印来辅助溯源。对于office文件的暗水印,有很多种方式,根据前文说的方案思路,不难看出,在很多配置文件中,其实是可以插入字符串的,例如直接在插入的链接中追加参数用来标记;或者xlsx中的图片名称属性写入一串暗水印;或者直接在文件属性中添加字符串等等,这里先介绍下文件属性。

    # 总结
    office的文件追踪本质上就是利用office自身的特性来做文章,深入理解它的结构之后,能更好地实现方案。虽然本文的方案可以满足基本需求,但是仍然存在很多问题待解决,数据安全保护还需要大家持续去研究新的技术。
    `

  4. 解决Excel或者CSV数值精度缺失问题(科学记算法精度缺失问题)
    https://blog.csdn.net/weixin_42425365/article/details/111059168

    可否不以科学记数法的方式表示大于99999999999的数值?
    https://answers.microsoft.com/zh-hans/msoffice/forum/msoffice_excel-mso_winother-mso_2010/%E5%8F%AF%E5%90%A6%E4%B8%8D%E4%BB%A5%E7%A7%91/a5fc5065-eb17-4be7-9383-65b93896b724

    怎么让excel不转换为科学计数法?
    https://www.zhihu.com/question/20096750
    `
    大于15位的数字后面全部变为0
    `

    Excel粘贴长文本数字 精度丢失
    https://blog.csdn.net/zirufeng/article/details/54891651

    python csv文件使用excel打开数字丢失精度
    https://blog.csdn.net/leaves_story/article/details/102743622
    `
    解决办法可以是:
    对于长度超过 12/15 的数值,尽量还是用字符串类型吧。
    `

  5. Java读写Excel原来这么简单
    https://segmentfault.com/a/1190000038566393
    `
    # 前言
    相信现在很多搞后端的同学大部分做的都是后台管理系统,那么管理系统就肯定免不了 Excel 的导出导入功能,今天我们就来介绍一下 Java 如何实现 Excel 的导入导出功能。

    Java领域解析,生成Excel比较有名的框架有Apache poi,Jxl等,但他们都存在一个严重的问题就是非常的耗内存,如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc.

    EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单,节省内存著称,今天我们来使用阿里巴巴开源的EasyExcel框架来实现Excel的导入导出功能。

    本文主要有以下几个知识点:
    * 从Excel读取数据
    * 导出数据到Excel
    * Excel模板填充
    `

  6. 查看或更改 Office 文件的属性
    https://support.microsoft.com/zh-cn/office/%E6%9F%A5%E7%9C%8B%E6%88%96%E6%9B%B4%E6%94%B9-office-%E6%96%87%E4%BB%B6%E7%9A%84%E5%B1%9E%E6%80%A7-21d604c2-481e-4379-8e54-1dd4622c6b75
    `
    Windows系统上,打开word文档,点击“开始”-“信息”-“属性”-“高级属性”。

    macOS系统上,打开word文档,点击“文件”-“属性”-“自定义”。

    ==
    自定义属性是为文档定义的 Office 属性。 您可以向自定义属性分配文本、时间或数值,也可以向这些属性分配值“是”或“否”。 可以从推荐名称列表中进行选择,也可以定义您自己的属性。

    1. 单击“文件”选项卡。
    2. 单击“信息”。

    3. 单击页面顶部的“属性”,然后选择“高级属性”。注意:
    ___ * 在 Access 选择”查看和编辑数据库属性”
    ___ * 在 Project 选择”Project信息”
    ___ * 在 发布服务器 选择”出版物属性”
    ___ * 目前,无法查看或创建文件Visio 属性

    4. 单击“自定义”选项卡。
    ___ * 在“名称”框中,为自定义属性键入一个名称,或从列表中选择一个名称。
    ___ * 在“类型”列表中,选择要添加的属性的数据类型。
    ___ * 在“值”框中,键入属性的值。 键入的值必须与“类型”列表中的选项相匹配。 例如,如果您在“类型”列表中选择“数字”,则必须在“值”框中键入数字。 与属性类型不匹配的值将存储为文本。

    5. 单击“确定”。
    `

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注