xlsx/pptx/docx文件数据格式解析-帮你搞懂数据到底存在哪

2023-11-22 07:59

本文主要是介绍xlsx/pptx/docx文件数据格式解析-帮你搞懂数据到底存在哪,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

序言

在开发过程中经常遇到office文件相关的问题,比如将数据导出成Excel、自动生成报表、自动生成填充合同模板、转pdf等。UOffice是一个为解决这类Office文件问题的项目,里面记录了到目前为止,笔者遇到的相关问题的解决方案。笔者希望UOffice能称为一个完善的集合,但是靠一个人很难做到完善,所以这个项目后续会公开到github上,希望能为大家提供便利,也希望大家共同完善功能,使之更加健壮。

(.xlsx、.docx、.pptx)文件解析

.xlsx、.docx、.pptx是ooxml格式的office文件,简单了来说就是(压缩+xml)的格式。也就说你可以用压缩工具(比如7zip)将一个xlsx(或docx、pptx)文件解压。以xlsx为例,其他文件格式类似。
xlsx文件
xlsx内容

xlsx解压完后
下面详细介绍下主要的几个部分的作用。

xl/sharedStrings.xml

此文件主要保本excel中各个单元格文本的内容。

<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="2" uniqueCount="2">
<si>
<t>我是</t>
<phoneticPr fontId="1" type="noConversion"/>
</si>
<si>
<t>Uoffice</t>
<phoneticPr fontId="1" type="noConversion"/>
</si>
</sst>

其中内容是去重的,相同的内容只能存一份。count代表总数,uniqueCount是去重后的数量。

xl/styles.xml

此文件主要存单元格的格式信息

<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" mc:Ignorable="x14ac">
<fonts count="2" x14ac:knownFonts="1">
<font>
<sz val="11"/>
<color theme="1"/>
<name val="宋体"/>
<charset val="134"/>
<scheme val="minor"/>
</font>
<font>
<sz val="9"/>
<name val="宋体"/>
<charset val="134"/>
<scheme val="minor"/>
</font>
</fonts>
<fills count="2">
<fill>
<patternFill patternType="none"/>
</fill>
<fill>
<patternFill patternType="gray125"/>
</fill>
</fills>
<borders count="1">
<border>
<left/>
<right/>
<top/>
<bottom/>
<diagonal/>
</border>
</borders>
<cellStyleXfs count="1">
<xf numFmtId="0" fontId="0" fillId="0" borderId="0">
<alignment vertical="center"/>
</xf>
</cellStyleXfs>
<cellXfs count="1">
<xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0">
<alignment vertical="center"/>
</xf>
</cellXfs>
<cellStyles count="1">
<cellStyle name="常规" xfId="0" builtinId="0"/>
</cellStyles>
<dxfs count="0"/>
<tableStyles count="0" defaultTableStyle="TableStyleMedium2" defaultPivotStyle="PivotStyleLight16"/>
<extLst>
<ext xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" uri="{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}">
<x14:slicerStyles defaultSlicerStyle="SlicerStyleLight1"/>
</ext>
<ext xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main" uri="{9260A510-F301-46a8-8635-F512D64BE5F5}">
<x15:timelineStyles defaultTimelineStyle="TimeSlicerStyleLight1"/>
</ext>
</extLst>
</styleSheet>

<fonts/>标签存放了xlsx中的字体信息,<fills/>标签存放了xlsx的单元格填充信息,标签存放了单元格边框信息,最重要的是** <cellXfs> **标签,里面综合了单元格的配置信息。

xl/worksheets/sheet1.xml

此文件中主要存放了每个单元格的具体信息

<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" mc:Ignorable="x14ac">
<dimension ref="A1:B1"/>
<sheetViews>
<sheetView tabSelected="1" workbookViewId="0">
<selection activeCell="B1" sqref="B1"/>
</sheetView>
</sheetViews>
<sheetFormatPr defaultColWidth="9" defaultRowHeight="14.4" x14ac:dyDescent="0.25"/>
<sheetData>
<row r="1" spans="1:2" x14ac:dyDescent="0.25">
<c r="A1" t="s">
<v>0</v>
</c>
<c r="B1" t="s">
<v>1</v>
</c>
</row>
</sheetData>
<phoneticPr fontId="1" type="noConversion"/>
<pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75" header="0.3" footer="0.3"/>
<pageSetup paperSize="9" orientation="portrait"/>
</worksheet>

<sheetData>标签中的row标签代表了每一行,row中的c标签单表了一行中的每一个单元格,c标签中的t="s"表示该单元格为文字,通过v标签标记的索引在sharedStrings.xml中查找。如果c标签中没有t变量,表示单元格为数字,此时v标签内的内容即为单元格内容。c标签中还有一个s变量,s变量指向styles.xml中的cellXfs标签,此处s变量未声明,默认应用cellXfs中的第一个。

总结

ooxml的格式大致如上所示,如果文件中有图像、引用等特殊元素,也是通过不同xml去表示的。
最后放上UOffice中解压文件和聚合文件的代码

protected void initTemplate(InputStream inputStream) {String path = File.separator + UUID.randomUUID().toString();try (ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {ZipEntry nextEntry;while ((nextEntry = zipInputStream.getNextEntry()) != null) {if (nextEntry.isDirectory()) {String tempPath = path + File.separator + nextEntry.getName();File tempFile = new File(tempPath);if (!tempFile.exists()) {if (!tempFile.mkdirs()) {throw new UOfficeException("创建{}失败", tempFile.getAbsolutePath());}}} else {String tempPath = path + File.separator + nextEntry.getName();File tempFile = new File(tempPath);FileOutputStream fileOutputStream = new FileOutputStream(tempFile);byte[] buffer = new byte[1024];int read = 0;while ((read = zipInputStream.read(buffer)) != -1) {fileOutputStream.write(buffer, 0, read);}fileOutputStream.close();}zipInputStream.closeEntry();}templatePath = path;} catch (Exception e) {PathUtils.deleteAllDir(path);}}
public void writeToStream(OutputStream outputStream) {List<PathEntry> pathEntries = PathUtils.pathWalk(templatePath);if (ObjectUtils.isNotEmpty(outputStream)) {try (ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream)) {for (PathEntry p : pathEntries) {ZipEntry zipEntry = new ZipEntry(p.getName());zipOutputStream.putNextEntry(zipEntry);if (!p.isWhetherDir()) {String s = templatePath + File.separator + p.getName();FileInputStream fileInputStream = new FileInputStream(new File(s));byte[] buffer = new byte[1024];int read = 0;while ((read = fileInputStream.read(buffer)) != -1) {zipOutputStream.write(buffer, 0, read);}fileInputStream.close();}zipOutputStream.closeEntry();}} catch (IOException e) {e.printStackTrace();}}}

最后限于本人能力的原因,难免有错误或遗漏之处,请大家多多指正。前两天发起了一个投票“做一个自动填充数据生成xlsx文件功能的价值”,共三人(包括我自己)投票表示很有价值,所以下一篇介绍如何去自动填充数据。

这篇关于xlsx/pptx/docx文件数据格式解析-帮你搞懂数据到底存在哪的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/408671

相关文章

SQL中如何添加数据(常见方法及示例)

《SQL中如何添加数据(常见方法及示例)》SQL全称为StructuredQueryLanguage,是一种用于管理关系数据库的标准编程语言,下面给大家介绍SQL中如何添加数据,感兴趣的朋友一起看看吧... 目录在mysql中,有多种方法可以添加数据。以下是一些常见的方法及其示例。1. 使用INSERT I

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

PostgreSQL的扩展dict_int应用案例解析

《PostgreSQL的扩展dict_int应用案例解析》dict_int扩展为PostgreSQL提供了专业的整数文本处理能力,特别适合需要精确处理数字内容的搜索场景,本文给大家介绍PostgreS... 目录PostgreSQL的扩展dict_int一、扩展概述二、核心功能三、安装与启用四、字典配置方法

MySQL 删除数据详解(最新整理)

《MySQL删除数据详解(最新整理)》:本文主要介绍MySQL删除数据的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、前言二、mysql 中的三种删除方式1.DELETE语句✅ 基本语法: 示例:2.TRUNCATE语句✅ 基本语

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

MyBatisPlus如何优化千万级数据的CRUD

《MyBatisPlus如何优化千万级数据的CRUD》最近负责的一个项目,数据库表量级破千万,每次执行CRUD都像走钢丝,稍有不慎就引起数据库报警,本文就结合这个项目的实战经验,聊聊MyBatisPl... 目录背景一、MyBATis Plus 简介二、千万级数据的挑战三、优化 CRUD 的关键策略1. 查

python实现对数据公钥加密与私钥解密

《python实现对数据公钥加密与私钥解密》这篇文章主要为大家详细介绍了如何使用python实现对数据公钥加密与私钥解密,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录公钥私钥的生成使用公钥加密使用私钥解密公钥私钥的生成这一部分,使用python生成公钥与私钥,然后保存在两个文

mysql中的数据目录用法及说明

《mysql中的数据目录用法及说明》:本文主要介绍mysql中的数据目录用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、版本3、数据目录4、总结1、背景安装mysql之后,在安装目录下会有一个data目录,我们创建的数据库、创建的表、插入的