php根据xml生成带格式的EXCEL

Posted in PHP by neemem on 06-17-2008.

工作中的一点心得,拿出来分享一下。

生成 文件早已不是什么难题了,但若生成的 文件没有格式(边框线、居中、字体等),其实就是生成文本文件再用 打开而已。
平台下,可能用 COM 组件可以做到这点,但在 Unix 类系统环境下就没这么幸运了。

首先看一下当时这个新闻吧:
http://bbs.chinaunix.net/viewthread.?tid=204738&highlight= [微软发Office免费许可 开放其文件格式]
基本上还是要感谢微软,否则白搭。
我做的也就是使用其 格式。注意:也就是说,这种方法生成的文件可能只对 Office 2003 有效。

至于 格式,各位可以自己仔细研究,新建一个工作簿,然后简单的设置一些单元格,输入一些内容,然后选择另存为,保存类型选择“表格”即可。
用文本编辑器打开刚才那个 文件,看看它是怎么描述一个单元格的格式的。它也是用 <> 标记,分配不同的 id 值,然后在下面进行任意调用。

我这里介绍一个模板的应用,就是先做好 样表(因为大多数应用都是输出的文件事先已设计好格式了),然后存成“表格”格式文件,再用 配合 Smarty 来输出。
先看模板文件(.tpl)(注意,我用的标记是“<{”和“}>”)
在这个例子中,关键就是把循环显示员工信息部分用 <{section}> 来处理。

CODE:

<? version=”1.0″?>
<?mso-application progid=”.Sheet”?>
<Workbook xmlns=”urn:schemas--com:office:spreadsheet”
xmlns:o=”urn:schemas--com:office:office”
xmlns:x=”urn:schemas--com:office:
xmlns:ss=”urn:schemas--com:office:spreadsheet”
xmlns:=”http://www.w3.org/TR/REC-html40″>
<DocumentProperties xmlns=”urn:schemas--com:office:office”>
<Author>Diana</Author>
<LastAuthor>Diana</LastAuthor>
<Created>2006-04-25T11:58:52Z</Created>
<LastSaved>2006-04-25T13:10:20Z</LastSaved>
<Version>11.5606</Version>
</DocumentProperties>
<ExcelWorkbook xmlns=”urn:schemas--com:office:”>
<WindowHeight>12495</WindowHeight>
<WindowWidth>16035</WindowWidth>
<WindowTopX>0</WindowTopX>
<WindowTopY>105</WindowTopY>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
<Styles>
< ss:ID=”Default” ss:Name=”Normal”>
<Alignment ss:Vertical=”Center”/>
<Borders/>
<Font ss:FontName=”宋体” x:CharSet=”134″ ss:Size=”12″/>
<Interior/>
<NumberFormat/>
<Protection/>
</>
< ss:ID=”s21″>
<Font ss:FontName=”宋体” x:CharSet=”134″ ss:Size=”18″ ss:Bold=”1″/>
</>
< ss:ID=”s29″>
<Alignment ss:Horizontal=”Center” ss:Vertical=”Center”/>
<Borders>
<Border ss:Position=”Bottom” ss:LineStyle=”Continuous” ss:Weight=”1″/>
<Border ss:Position=”Left” ss:LineStyle=”Continuous” ss:Weight=”1″/>
<Border ss:Position=”Right” ss:LineStyle=”Continuous” ss:Weight=”1″/>
<Border ss:Position=”Top” ss:LineStyle=”Continuous” ss:Weight=”1″/>
</Borders>
</>
< ss:ID=”s35″>
<Alignment ss:Horizontal=”Center” ss:Vertical=”Center”/>
<Borders>
<Border ss:Position=”Bottom” ss:LineStyle=”Continuous” ss:Weight=”1″/>
<Border ss:Position=”Left” ss:LineStyle=”Continuous” ss:Weight=”1″/>
<Border ss:Position=”Right” ss:LineStyle=”Continuous” ss:Weight=”1″/>
<Border ss:Position=”Top” ss:LineStyle=”Continuous” ss:Weight=”1″/>
</Borders>
<NumberFormat ss:Format=”@”/>
</>
</Styles>
<Worksheet ss:Name=”Sheet1″>
<Table ss:ExpandedColumnCount=”5″ ss:ExpandedRowCount=”21″ x:FullColumns=”1″
x:FullRows=”1″ ss:DefaultColumnWidth=”54″ ss:DefaultRowHeight=”17.25″>
<Column ss:AutoFitWidth=”0″ ss:Width=”36″/>
<Column ss:AutoFitWidth=”0″ ss:Width=”69″/>
<Column ss:AutoFitWidth=”0″ ss:Width=”78.75″/>
<Row ss:Height=”22.5″>
<Cell ss:StyleID=”s21″><Data ss:Type=”String”>员工信息表</Data></Cell>
</Row>
<Row ss:AutoFitHeight=”0″/>
<Row ss:AutoFitHeight=”0″>
<Cell ss:StyleID=”s29″><Data ss:Type=”String”>序号</Data></Cell>
<Cell ss:StyleID=”s29″><Data ss:Type=”String”>工号</Data></Cell>
<Cell ss:StyleID=”s29″><Data ss:Type=”String”>姓名</Data></Cell>
<Cell ss:StyleID=”s29″><Data ss:Type=”String”>性别</Data></Cell>
<Cell ss:StyleID=”s29″><Data ss:Type=”String”>年龄</Data></Cell>
</Row>

<{* 在这里对要循环输出的数据使用 section 处理。*}>
<{section name=list loop=$Emps}>
<Row ss:AutoFitHeight=”0″>
<Cell ss:StyleID=”s29″><Data ss:Type=”Number”><{$smarty.section.customer.rownum}></Data></Cell>
<Cell ss:StyleID=”s35″><Data ss:Type=”String”><{$Emps[list].id}></Data></Cell>
<Cell ss:StyleID=”s29″><Data ss:Type=”String”><{$Emps[list].name}></Data></Cell>
<Cell ss:StyleID=”s29″><Data ss:Type=”String”><{$Emps[list].sexual}></Data></Cell>
<Cell ss:StyleID=”s29″><Data ss:Type=”Number”><{$Emps[list].age}></Data></Cell>
</Row>
<{/section}>

</Table>
</Worksheet>
</Workbook>

不一定要和我上面这个一模一样,以上我经过少许删减,比如我把最后的 <WorksheetOptions> 段给删掉了。

CODE:

<?
// 实验资料,实际作业中,这里应该是从数据库取得资料
$emps[0]['id'] = ‘00001′;
$emps[0]['name'] = ‘ABC’;
$emps[0]['sexual'] = ‘男’;
$emps[0]['age'] = 28;

$emps[1]['id'] = ‘00002′;
$emps[1]['name'] = ‘BBC’;
$emps[1]['sexual'] = ‘男’;
$emps[1]['age'] = 23;

$emps[2]['id'] = ‘00003′;
$emps[2]['name'] = ‘CBA’;
$emps[2]['sexual'] = ‘女’;
$emps[2]['age'] = 20;

ini_set(’include_path’, ‘/data/website/htdocs/includes’);
require_once(’class.Smarty.’);
$smarty = new mySmarty();

$smarty->assign(’Emps’, $emps);

// 输出文件头,表明是要输出 文件
header(”Content-type: application/vnd.ms-”);
header(”Content-Disposition: attachment; filename=test.”); //<—– 这里,改成 test.xls 也可以,这样就可以直接用 打开了。不过本质还是 ,用记事本打开就知道了。所以打开后,再另存一下,存为真正的 xls 格式。

$smarty->display(’.tpl’);
?>

完工,放到服务器上跑一下吧。
麻烦的地方,就是 样表转换成 并修改成 Smarty 模板那一步。
我上面那个例子相对来说简单,因为格式比较单一。更复杂点的报表就要麻烦点了,要在模板中一个个单元格自己去放置 StyleID 值了。
不过,总算能输出一份漂亮的带格式的 了,这点辛苦还是值得的。

上面那个例子的效果图

Related posts:
牙疼不是病.痛起来真要命呀.后悔了 传内地3GiPhone渠道价约4000至4500元

Leave a Reply