Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/6tail/dp2
a common data parser tool, support reading and writing xls, xlsx, doc, docx, csv.一个通用的表格数据读写工具,支持xls、xlsx、doc、docx、csv格式。
https://github.com/6tail/dp2
csv doc docx java xls xlsx
Last synced: about 8 hours ago
JSON representation
a common data parser tool, support reading and writing xls, xlsx, doc, docx, csv.一个通用的表格数据读写工具,支持xls、xlsx、doc、docx、csv格式。
- Host: GitHub
- URL: https://github.com/6tail/dp2
- Owner: 6tail
- License: mit
- Created: 2020-03-16T09:43:15.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2022-11-29T12:17:13.000Z (almost 2 years ago)
- Last Synced: 2023-03-01T10:41:54.475Z (over 1 year ago)
- Topics: csv, doc, docx, java, xls, xlsx
- Language: Java
- Homepage:
- Size: 137 KB
- Stars: 1
- Watchers: 2
- Forks: 2
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# dp2 [![License](https://img.shields.io/badge/license-MIT-4EB1BA.svg?style=flat-square)](https://github.com/6tail/dp2/blob/master/LICENSE)
一个通用的表格数据读写工具,支持xls、xlsx、doc、docx、csv格式。
> 支持在较低内存占用下完成超大xls和xlsx文件的解析。
> 支持直接生成新文件,也支持在模板文件中修改单元格数据并生成新的文件。
> 支持java1.5及以上版本。java1.5需额外引入javax包,否则解析xlsx会报错。
> xls和xlsx文件仅解析第一个Sheet。
> doc和docx文件仅解析第一个表格。
## 使用
通过maven引入或者[点此下载](https://github.com/6tail/dp2/releases)相应的jar。
```xml
cn.6tail
dp2
1.0.3```
## 示例
### 待解析excel内容
A
B
C
D
E
1
序号
姓名
性别
年龄
民族
2
1
张三
男
20
汉族
3
2
李四
女
18
汉族
4
3
王二
男
30
满族
### 自动读取示例
// 待解析文件
File file = new File("template.xls");
// 自动获取标记
List markers = SingleLineRepeatMarkerDetector.detect(file);
// 通过工厂获取解析器接口
IParser parser = ParserFactory.getParser(file);
// 获取节点读取器
INodeReader reader = parser.read(markers);
// 遍历所有找到的节点
while (reader.hasNext()) {
INode node = reader.next();
// 自动识别的标题以head作为标记名称,以body作为数据标记名称
if ("head".equals(node.getMarker().getName())) {
// 表头不处理
} else if ("body".equals(node.getMarker().getName())) {
for (INode child : node.getChildren()) {
// 自动识别的以列下标(从0开始)作为子项标记名称
// System.out.print(child.getMarker().getName() + "=");
System.out.print(child.getValue());
System.out.print("\t");
}
System.out.println("_____________________________________");
}
}### 手动读取示例
// 待解析文件
File file = new File("template.xls");
// 定义待解析的标记列表
List markers = new ArrayList();
// 标题只有一行,直接使用Marker,位于行0列0(如果不解析标题,则可以不定义)
Marker markerHead = new Marker("标题", 0, 0);
// 设置宽度为5列(高度默认为一行不用设置了)
markerHead.setWidth(5);
// 添加需要取的标题标记及位于父区域内的坐标
markerHead.addChild(new Marker("序号", 0, 0));
markerHead.addChild(new Marker("姓名", 0, 1));
markerHead.addChild(new Marker("性别", 0, 2));
markerHead.addChild(new Marker("年龄", 0, 3));
markerHead.addChild(new Marker("民族", 0, 4));
// 数据区域为重复性数据,使用RepeatedMarker,位于行1列0
Marker markerBody = new RepeatedMarker("数据", 1, 0);
// 设置宽度为5列(高度默认为一行不用设置了)
markerBody.setWidth(5);
// 添加需要取的数据标记及位于父区域内的坐标
markerBody.addChild(new Marker("序号", 0, 0));
markerBody.addChild(new Marker("姓名", 0, 1));
markerBody.addChild(new Marker("性别", 0, 2));
markerBody.addChild(new Marker("年龄", 0, 3));
markerBody.addChild(new Marker("民族", 0, 4));
// 添加要解析的标记
markers.add(markerHead);
markers.add(markerBody);
// 通过工厂获取解析器接口
IParser parser = ParserFactory.getParser(file);
// 获取节点读取器
INodeReader reader = parser.read(markers);
// 遍历所有找到的节点
while (reader.hasNext()) {
INode node = reader.next();
if ("标题".equals(node.getMarker().getName())) {
// 表头不处理
} else if ("数据".equals(node.getMarker().getName())) {
for (INode child : node.getChildren()) {
// 子项标记名称为前面定义的标记名称,如序号、姓名等
// System.out.print(child.getMarker().getName() + "=");
System.out.print(child.getValue());
System.out.print("\t");
}
System.out.println("_____________________________________");
}
}### 输出结果
1 张三 男 20 汉族
_____________________________________
2 李四 女 18 汉族
_____________________________________
3 王二 男 30 满族
_____________________________________### 生成文件示例
// 定义标记列表
List markers = new ArrayList();
// 标题只有一行,使用Marker,位于第0行第0列
Marker markerHead = new Marker("标题", 0, 0);
// 设置宽度为2列
markerHead.setWidth(2);
// 添加需要取的标题标记及位于父区域内的坐标
markerHead.addChild(new Marker("sn", 0, 0));
markerHead.addChild(new Marker("name", 0, 1));
// 数据区域为重复性数据,使用RepeatedMarker,位于第1行第0列
Marker markerBody = new RepeatedMarker("数据", 1, 0);
// 设置宽度为2列
markerBody.setWidth(2);
// 添加需要取的数据标记及位于父区域内的坐标
markerBody.addChild(new Marker("序号", 0, 0));
markerBody.addChild(new Marker("姓名", 0, 1));
// 添加标记
markers.add(markerHead);
markers.add(markerBody);
// 通过工厂获取xls解析接口
IParser parser = ParserFactory.getParser("xls");
// 获取节点写入接口
INodeWriter writer = parser.write(markers);
// 写标题
Node head = new Node("标题");
head.addChild(new Node("sn", "序号"));
head.addChild(new Node("name", "姓名"));
writer.add(head);
// 写数据
Node body = new Node("数据");
body.addChild(new Node("序号", "1"));
body.addChild(new Node("姓名", "张三"));
writer.add(body);
// 再写一行数据
body = new Node("数据");
body.addChild(new Node("序号", "2"));
body.addChild(new Node("姓名", "李四"));
writer.add(body);
// 待生成文件
File file = new File("template.xls");
// 输出
writer.save(file);## 解析机制
在一个表格中,指定横坐标、纵坐标、宽度(多少列),高度(多少行),你就能圈出一个区域。给这个区域贴上标签,你就能很容易的从表格中找到你感兴趣的内容,这个标签,也就是标记(Marker)。
标记可大可小,大到整个Sheet(当然这样没有实际意义),小到一个单元格。
标记支持层级,一个大的标记下,可以包含多个小的子标记(子标记的坐标以父标记为基准),这样就可以从大到小逐步锁定目标。
遍历读取的时候,仅遍历顶级的标记,子标记内容通过getChildren方法获取。
### 单一标记
单一标记(Marker)为不重复出现的标记。
以下图为例,通过"姓名"标记可直接读取到"六特尔",通过"email"标记可直接读取到"[email protected]",也可修改对应的值。
![单一标记示例](https://github.com/6tail/dp2/raw/master/samples/dp2-0.png)
### 重复标记
重复标记(RepeatedMarker)为重复出现的标记。
以下图为例,每一行数据为一个大的标记(取名为"名单",按行重复出现,因不确定有多少行数据,因此重复标记的坐标以第一次出现的坐标为准),大标记中包含两个子标记("姓名"和"性别")。
![重复标记示例](https://github.com/6tail/dp2/raw/master/samples/dp2-1.png)
### 组合标记
无论多复杂的表格,都可以拆分为单一标记与重复标记的组合,标记表格的方式也可以五花八门,你选择的标记方式将决定解析的效率。
![复杂标记示例](https://github.com/6tail/dp2/raw/master/samples/dp2-2.png)
以上图这个表格为例,如果我们需要读取主题和名单,可定义两个顶级标记,"主题"标记位于行1列1,"名单"标记位于行4列1,宽2高3。
其中"名单"中包含多个重复标记"人员",位于行0列0,宽2高1。
"人员"标记又包含"姓名"标记(位于行0列0,宽1高1)和"性别"标记(位于行0列1,宽1高1)。
## 注意
坐标均以父标记为基准,从0开始计。