我以一种快速的、有点吝啬的方式实现了这一点——因为它冗长而曲折,我只会用概念而不是代码来解释它。
XLSX 遵循 ISO 29500,如果您想在 php 中彻底操作文档,该标准是公开的。否则,请意识到 xlsx 文件是一堆 xml 文件的压缩档案。
制作一个你想要的模板,比如它具有不同类型样式的交替行,在 excel 或某种描述的打开的 xml 编辑器中制作。确保将一些数据放在那里,并确保一些字段相等(仅用于学习目的)。
然后将文件另存为 xlsx,将其重命名为 .zip,或在存档提取器中打开并观察其内容。
首先,请注意 [Content_Types].xml 文件,它描述了存档中主要文件的位置以及它本身遵循的标准以及这些文件的内容类型。
文件夹外的所有xl/
内容实际上都只是元数据。但是观察docProps/core.xml
包含作者、修改和时间戳信息 - 当您重新创建此文件时,您可以在 php 中替换它们。此外,所指出的所有内容都docProps/core.xml
可以根据您的口味重命名,[Content_Types].xml
但不能。
好的,现在您了解了这一点,您将开始观察该地点周围的 id。他们喜欢在文件格式中使用它,所有内容都通过其在特定 xml 属性列表或类似列表中的索引来引用其他所有内容。它们通常还描述此类列表中的项目数量。
在xl/
你会看到themes.xml, styles.xml, workbook.xml, sharedStrings.xml, _rels/, worksheets/
。
样式将被大量不必要的样式夸大,如果您使用它,Excel 默认会构建这些样式。但是您应该能够看到这些样式是如何工作的,以便您可以自定义自己的样式。
主题对我来说毫无意义,所以我删除了它及其引用的 ID。
接下来您将看到工作簿,该文件包含有关电子表格文档内部工作表的信息,因为您显然可以拥有超过 1 个。它还包含一些工作表元数据,例如其大小等。
现在是你遇到的第一个大花。sharedStrings.xml
是一个奇怪的文件,它存储了将插入到静态电子表格中的单元格中的所有信息。它们被编入索引,但读取文档的引擎会计算出它们的索引是什么。任何重复的内容都可以在工作表本身(工作表文件夹内)中引用回其旧索引,以节省具有重复值的大型文档中的文件大小。不是元素中的属性count
和它们显然意味着什么。uniquecount
sst
这是 php 中的阶段,您可以在其中填充包含工作表中所需内容的数据数组,并将其转储到 xml 格式的列表中,例如出现此文件。另请注意,这些文件不需要在没有换行符或换行符的情况下被卡住,因为有或没有仍然是有效的 xml,并且无论如何它们都可以在阅读器中工作。
查看 _rels 文件夹,它再次相当明显。
最后是表本身。此处字段中的数字是指字符串在 中的索引位置sharedStrings.xml
。属性 s 是样式,t 是字段中数据的类型。R 是单元格的位置,尽管当它真的很容易弄清楚时,它为什么需要它超出了我的范围。
用 php 生成这个文件也不应该太难。只需使用用于制作sharedStrings.xml
文件的数据数组中的索引即可。
哦,表格中还有列宽信息,您可以根据您使用的字体计算出它们,如果需要,也可以在 php 中自动调整它们的大小。
最后是用 php 打包它。
我的代码在一个类中,它接收我用 excel 创建的数据和特定保存的文件,以保持简单。
$this->folder_structure_simple = Array(
"_rels/.rels" => "_rels__rels",
"docProps/app.xml" => "docProps_app_xml",
"docProps/core.xml" => "docProps_core_xml",
"xl/_rels/workbook.xml.rels",
"xl/theme/theme1.xml",
"xl/worksheets/sheet1.xml",
"xl/sharedStrings.xml",
"xl/styles.xml",
"xl/workbook.xml",
"[Content_Types].xml" => "Content_Types_xml"
);
$zip = new ZipArchive;
$res = $zip->open($this->file_name, ZipArchive::CREATE);
if($res === TRUE){
foreach($this->folder_structure_simple as $file => $function){
$zip->addFromString($file, $this->$funtion);
}
$zip->close();
echo 'ok';
}else{
return FALSE;
}
函数产生所需的数据。非常快,不是很灵活。