=Start=
缘由:
整理总结一下在Java中如何借助Apache POI实现Excel的读、写操作,方便有需要的时候参考和理解。
正文:
参考解答:
写Excel的基本步骤
- 创建一个 workbook
- 创建一个 sheet
- 重复如下步骤直到数据被写入完成:
- 创建一个 row
- 在 row 中创建 cells ,如果要设置格式的话可以用 CellStyle
- 将 workbook 写入 FileOutputStream
- 关闭 FileOutputStream
- 关闭 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 条评论
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
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
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自身的特性来做文章,深入理解它的结构之后,能更好地实现方案。虽然本文的方案可以满足基本需求,但是仍然存在很多问题待解决,数据安全保护还需要大家持续去研究新的技术。
`
Java Read CSV File Example
https://howtodoinjava.com/java/io/parse-csv-files-in-java/
`
1. OpenCSV Library
2. java.util.Scanner
3. String.split() function
`
浅谈 Word 文档结构
https://kodango.com/talking-about-the-structure-of-word-document
http://www.officeopenxml.com/
http://www.officeopenxml.com/anatomyofOOXML.php
https://github.com/plutext/docx4j
https://poi.apache.org/
解决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 的数值,尽量还是用字符串类型吧。
`
How to extract metadata from docx file – Python
https://stackoverflow.com/questions/61242017/how-to-extract-metadata-from-docx-file-python
`
$ pip install python-docx
>>> import docx
>>> doc = docx.Document(file_path)
>>> prop = doc.core_properties
>>> print(prop.author)
…
`
https://python-docx.readthedocs.io/en/latest/user/quickstart.html
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模板填充
`
查看或更改 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. 单击“确定”。
`
Microsoft Office 2016 添加自定义域
https://www.cnblogs.com/jiangxiong/p/10242562.html
`
1,打开word文档,点击“文件”-“信息”-“属性”-“高级属性”。
2,输入名称、取值,点击“添加”,即可。
`
Read & Write MS word document using custom properties?
https://stackoverflow.com/questions/52653973/read-write-ms-word-document-using-custom-properties
https://github.com/plutext/docx4j
Add, Read and Remove Document Properties in Word in Java
https://dev.to/eiceblue/add-read-and-remove-document-properties-in-word-in-java-2pod
https://www.e-iceblue.com/Tutorials/Licensing/How-to-install-Spire.PDF-for-Java-from-Maven-Repository.html
https://mvnrepository.com/search?q=spire&d=e-iceblue