利用DeepSeek辅助WPS电子表格ET格式分析

WPS ET格式与ZIP文件结构分析
部署运行你感兴趣的模型镜像

前面研究了电子表格的xlsx、xlsbODS格式,接下来研究WPS电子表格ET格式,这个格式网上的资料很少,WPS官方说 .et 格式是兼容 Xlsx 和 Xls 的。
然而,把它后缀改为xlsx,rust_sheet插件还是无法识别,报错

Binder Error:
Read spreadsheet failed: Invalid xlsx file format: File not found 'xl/_rels/workbook.xml.rels'

而把后缀改为xls,rust_sheet插件就能识别,怎么解释这样神奇的现象?

mv HelloWorld.et HelloWorld.et.xls

./duckdb132

D load rusty_sheet;
D from read_sheet('HelloWorld.et.xls');
┌─────────────┐
│ Hello World │
│   varchar   │
├─────────────┤
│   0 rows    │
└─────────────┘

这要从xls格式的来源说起,以下是DeepSeek的详细说明

Microsoft Excel 97-2003 (XLS) 文件格式详解

Excel 97-2003 使用的 XLS 格式(也称为 BIFF8 格式)是 Microsoft 的二进制文件格式,在 Excel 2007 之前一直是标准格式。以下是该格式的全面介绍:

一、基本结构

XLS 文件是基于 复合文件二进制格式(Compound File Binary Format,简称 CFBF)的结构化存储文件,也称为 OLE2 或 DOCFILE 格式。

1. 存储结构特点

  • 类似小型文件系统:包含"存储"(storages)和"流"(streams)
  • 扇区分配:数据被分成512字节的扇区
  • FAT表:文件分配表记录扇区链接关系
  • 目录结构:包含文件内各部分的层次关系

二、核心组成部分

1. 主要存储流

\Workbook       // 主工作簿数据
\SummaryInformation  // 文档摘要信息
\DocumentSummaryInformation // 文档统计信息

2. Workbook 流结构

Workbook 流由一系列 BIFF记录(Binary Interchange File Format)组成:

记录类型说明
BOF工作簿/工作表开始标记
EOF结束标记
SST共享字符串表
BoundSheet工作表信息
DIMENSIONS工作表尺寸
ROW行信息
CELL单元格数据
FORMULA公式
FONT字体定义
XF单元格格式
STYLE样式定义

三、关键记录详解

1. 单元格数据存储

  • 数字:直接以8字节双精度浮点存储
  • 字符串:引用SST表中的索引
  • 布尔值:0(FALSE)或1(TRUE)
  • 错误值:特定错误代码
  • 空白单元格:不存储,通过ROW记录推断

2. 共享字符串表(SST)

struct {
    uint16_t numStrings;      // 字符串总数
    uint16_t numUniqueStrings;// 唯一字符串数
    XLUnicodeString strings[];// 字符串数组
}

3. 公式存储

struct {
    uint16_t row;
    uint16_t col;
    uint16_t xfIndex;
    uint64_t value;  // 缓存的计算结果
    byte formula[];  // 公式的RPN表示
}

四、格式限制

项目限制
行数65,536 (2^16)
列数256 (2^8)
工作表数受内存限制
单元格样式4,000种左右
字符串长度32,767字符

五、与新版XLSX对比

特性XLSXLSX
格式类型二进制XML压缩包
文件大小相对较大较小
恢复能力
最大行数65,5361,048,576
扩展性有限良好
加密支持

六、编程处理

1. 使用Python读取

import xlrd

# 打开XLS文件
workbook = xlrd.open_workbook("example.xls")

# 获取第一个工作表
sheet = workbook.sheet_by_index(0)

# 读取单元格数据
print(sheet.cell_value(0, 0))  # 第一行第一列

2. 使用Python写入

import xlwt

# 创建工作簿
workbook = xlwt.Workbook()
sheet = workbook.add_sheet("Sheet1")

# 写入数据
sheet.write(0, 0, "Hello World")

# 保存文件
workbook.save("output.xls")

它的结构可以使用专业工具检查:

from olefile import OleFileIO

try:
    ole = OleFileIO("test.xls")
    print("有效的OLE结构:", ole.listdir())
except:
    print("不是完整的OLE文件")

我们用上述xlwt脚本生成一个HelloWorld.xls,用xlrt和olefile分别去读。

python3 xlrd2.py

Hello World

python3 ole2.py
有效的OLE结构: [['Workbook']]

然后用WPS打开HelloWorld.xls,再另存为HelloWorld.et,用xlrt和olefile分别去读。

python3 xlrd2.py

Hello World

python3 ole2.py
有效的OLE结构: [['\x05DocumentSummaryInformation'], ['\x05SummaryInformation'], ['ETExtData'], ['Workbook']]

可见,et格式是有效的OLE结构,但比标准xls格式多了3个额外的段,不影响读取。

那么它怎么又能兼容xlsx格式呢?问题就出在多出来的段上。

我们知道xlsx实际是zip格式,那ET也是zip格式吗,不完全是。
我用unzip工具去列出它包含的文件,结果是这样的。

unzip -l HelloWorld.et
存档文件:  HelloWorld.et
warning [HelloWorld.et]:  10223 extra bytes at beginning or within zipfile
  (attempting to process anyway)
  Length      Date    Time    Name
---------  ---------- -----   ----
      540  2012-07-02 09:52   [Content_Types].xml
        0  2012-07-02 09:52   _rels/
      310  2012-07-02 09:52   _rels/.rels
        0  2012-07-02 09:52   theme/
        0  2012-07-02 09:52   theme/theme/
        0  2012-07-02 09:52   theme/theme/_rels/
      283  2012-07-02 09:52   theme/theme/_rels/themeManager.xml.rels
     6432  2012-07-02 09:52   theme/theme/theme1.xml
      138  2012-07-02 09:52   theme/theme/themeManager.xml
---------                     -------
     7703                     9 files

unzip发现这个文件除了zip格式应该有的部分,还有10223个多余的字节,而且还能继续解压,但多余的字节解压不了,也就取不到真正的数据。
需要特别说明,WPS保存的xls格式并非标准xls格式,仅仅是改个后缀。它利用了OLE结构允许多个段,而读取xls格式的程序只去读’Workbook’段这个特点实现了“兼容”。本质上就是带有xls段和zip信息的混合格式。
再将它与xlsx格式比较,用WPS打开HelloWorld.et,再另存为HelloWorld.xlsx,用unzip工具去列出:

unzip -l HelloWorld.xlsx
存档文件:  HelloWorld.xlsx
  Length      Date    Time    Name
---------  ---------- -----   ----
     1293  2012-07-02 09:52   [Content_Types].xml
        0  2012-07-02 09:52   _rels/
      735  2012-07-02 09:52   _rels/.rels
        0  2012-07-02 09:52   docProps/
      564  2012-07-02 09:52   docProps/app.xml
      573  2012-07-02 09:52   docProps/core.xml
      526  2012-07-02 09:52   docProps/custom.xml
        0  2012-07-02 09:52   xl/
        0  2012-07-02 09:52   xl/_rels/
      698  2012-07-02 09:52   xl/_rels/workbook.xml.rels
      187  2012-07-02 09:52   xl/sharedStrings.xml
    20006  2012-07-02 09:52   xl/styles.xml
        0  2012-07-02 09:52   xl/theme/
     6432  2012-07-02 09:52   xl/theme/theme1.xml
      477  2012-07-02 09:52   xl/workbook.xml
        0  2012-07-02 09:52   xl/worksheets/
     1309  2012-07-02 09:52   xl/worksheets/sheet1.xml
---------                     -------
    32800                     17 files

可见,这个文件没有多余字节,真正的数据保存在sharedStrings.xml和xl/worksheets/sheet1.xml中,这在上文已经分析过了。

为什么WPS能这么干呢?因为zip格式是允许文件中间有多余部分的,以下是DeepSeek的详细解释。

ZIP 文件格式详解及安全修改指南

ZIP 文件格式基本结构

ZIP 文件是一种常见的归档文件格式,其基本结构如下:

1. 核心组成部分

[Local File Header 1]
[File Data 1]
[Local File Header 2]
[File Data 2]
...
[Central Directory]
[End of Central Directory Record]

2. 关键结构说明

  • Local File Header:每个文件的本地头,包含文件名、压缩方法等元数据

    • 签名:0x04034b50 (PK\x03\x04)
    • 结构:30字节固定部分 + 文件名 + 额外字段
  • File Data:实际压缩后的文件内容

  • Central Directory:中央目录,包含所有文件的索引信息

    • 签名:0x02014b50 (PK\x01\x02)
    • 包含所有文件的完整路径、压缩信息、偏移量等
  • End of Central Directory Record:目录结束标记

    • 签名:0x06054b50 (PK\x05\x06)
    • 包含中央目录的位置和文件总数

在ZIP中添加内容而不影响解压的方法

方法1:利用ZIP注释字段(推荐)

import zipfile

def add_to_zip_comment(zip_path, extra_data, output_path):
    with zipfile.ZipFile(zip_path, 'a') as zf:
        # 获取原注释
        orig_comment = zf.comment
        # 追加新数据
        new_comment = orig_comment + extra_data.encode('utf-8')
        # 创建新ZIP文件
        with zipfile.ZipFile(output_path, 'w') as new_zip:
            # 复制所有原文件
            for item in zf.infolist():
                with zf.open(item.filename) as f:
                    new_zip.writestr(item, f.read())
            # 设置新注释
            new_zip.comment = new_comment

# 使用示例
add_to_zip_comment('example.zip', '这是我的额外数据', 'modified.zip')

优点

  • 完全符合ZIP规范
  • 所有解压工具都能正常处理
  • 不会影响文件校验和

方法2:在Central Directory后添加数据(兼容性较好)

  1. 找到End of Central Directory Record的起始位置
  2. 在其前面插入额外数据
  3. 更新End of Central Directory Record中的偏移量
def append_after_central_dir(original_zip, extra_data, output_zip):
    with open(original_zip, 'rb') as f:
        data = f.read()
    
    # 查找End of Central Directory Record
    eocd_pos = data.rfind(b'PK\x05\x06')
    
    if eocd_pos == -1:
        raise ValueError("无效的ZIP文件")
    
    # 在EOCD前插入数据
    new_data = data[:eocd_pos] + extra_data.encode() + data[eocd_pos:]
    
    with open(output_zip, 'wb') as f:
        f.write(new_data)

方法3:利用Extra Field字段(针对特定文件)

def add_to_extra_field(zip_path, output_path):
    with zipfile.ZipFile(zip_path, 'a') as zf:
        # 获取第一个文件的信息
        file_list = zf.infolist()
        if not file_list:
            raise ValueError("ZIP文件为空")
        
        # 修改extra字段
        file_info = file_list[0]
        file_info.extra = b'MyExtraData\x00\x01' + file_info.extra
        
        # 创建新ZIP文件
        with zipfile.ZipFile(output_path, 'w') as new_zip:
            for item in file_list:
                with zf.open(item.filename) as f:
                    content = f.read()
                new_zip.writestr(item, content)

注意事项

  1. 签名冲突:确保添加的数据不包含PK\x03\x04、PK\x01\x02等ZIP魔术数字

  2. 文件校验:修改后建议验证ZIP文件完整性

    zipfile.is_zipfile('modified.zip')  # 验证ZIP有效性
    
  3. 大小限制

    • ZIP注释最大65535字节
    • Extra Field字段通常限制为65535字节
  4. 兼容性测试:建议在目标解压环境中测试修改后的文件

高级技巧:隐藏数据

对于需要隐蔽存储的场景,可以:

  1. 将数据加密后存入注释
  2. 使用StegZIP等工具在最低有效位(LSB)隐藏信息
  3. 利用ZIP64扩展存储大容量额外数据

以上方法都能确保标准解压工具正常解压原始内容,同时携带额外信息。

您可能感兴趣的与本文相关的镜像

Python3.9

Python3.9

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

### 使用 DeepSeekWPS 创建表格 #### 在 WPS 中创建表格 WPS Office 是一款功能强大的办公软件套件,其中包含了文字处理、电子表格以及演示文稿等多种工具。对于创建表格而言,在 WPS 表格中操作是最直接的方式。 打开 WPS 表格之后,可以通过点击菜单栏中的“插入”选项卡下的“表格”,来指定行列数快速建立一个新的空白表格[^1]。另外一种方法是在文档内通过鼠标拖拽绘制表格框架,随后调整各列宽度与行高至合适位置满足需求[^2]。 为了使表格更加美观易读,可以利用顶部的功能区设置边框样式、底纹颜色等属性;也可以为表头应用特殊格式以便区分数据区域[^3]。 ```python # 这里提供一段伪代码表示如何编程化地在支持 API 的环境下新建并填充简单表格 import wps_api # 假设存在这样的库用于调用 WPS 功能 doc = wps_api.new_document() table = doc.add_table(rows=5, cols=3) for i in range(5): table.cell(i, 0).text(f'Row {i}') table.cell(i, 1).text('Data A') table.cell(i, 2).text('Data B') doc.save_as('example.xlsx') ``` 需要注意的是上述 Python 代码仅为示意,并不适用于实际执行环境当中,因为当前版本的 WPS 并未公开完整的 Python SDK 接口供外部开发人员使用[^4]。 #### 结合 DeepSeek 提升效率 DeepSeek 可以为用户提供智能化的支持服务,当涉及到复杂的数据分析或是频繁重复性的任务时尤为有用。例如: - 自动生成报告摘要:基于已有的大量历史报表资料学习总结规律模式,帮助生成新的业务汇报材料; - 数据清洗预处理:自动识别错误条目提示修正建议,加快准备阶段的工作进度; - 查询推荐优化路径:针对特定应用场景给出最合适的函数组合或插件安装提议,提高工作效率减少摸索时间成本。 不过就单纯创建基础表格这一行为来说,主要还是依赖于 WPS 自身的操作界面完成,而 DeepSeek 更多体现在后续深入使用的辅助层面之上[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值