如何导出漂亮的 Excel 报表
将数据导出为 Excel 报表一直以来都是个麻烦事。我后来在网上偶然看到有人这样做:
首先用 Excel 设计报表模板,然后把需要替换的位置填入特定的标记,接下来选择“另存为”,文件格式保存为“XML 文档”。
这时得到的 Excel 文件就是一个 .xml 的纯文本文件。接下来要做的事情就简单了:在 php 里面查询数据,然后读取这个 .xml 到一个变量,替换特定标记后输出。
实际输出效果(还是有点小毛病,数量一栏的格式设置错了。不过客户没发现,也懒得改了)
==============================
XML 源文件的核心部分:
这里我在 .xml 里面插入了 Smarty 标记,所以就可以很方便的用 Smarty 来解析这个 .xml 文件,生成最后的结果了。
如果输出的报表带有公式,一定要注意公式是以相对位置来计算单元格的。
例如 .xml 源文件中的:
.xml 源文件
order_template.xml (7.29 KB)
=============================
在程序里面输出的代码如下:
前面几行是获取数据,两个 header() 指示要输出的内容的类型,最后通过 $smarty 载入 .xml 输出报表。
转自:FleaPHP论坛
首先用 Excel 设计报表模板,然后把需要替换的位置填入特定的标记,接下来选择“另存为”,文件格式保存为“XML 文档”。
这时得到的 Excel 文件就是一个 .xml 的纯文本文件。接下来要做的事情就简单了:在 php 里面查询数据,然后读取这个 .xml 到一个变量,替换特定标记后输出。
实际输出效果(还是有点小毛病,数量一栏的格式设置错了。不过客户没发现,也懒得改了)
==============================
XML 源文件的核心部分:
CODE:
....
<Row ss:AutoFitHeight="0" ss:Height="20.25">
<Cell ss:Index="2" ss:StyleID="s63"><Data ss:Type="String">商品名称</Data></Cell>
<Cell ss:StyleID="s63"><Data ss:Type="String">商品编号</Data></Cell>
<Cell ss:StyleID="s63"><Data ss:Type="String">购买价</Data></Cell>
<Cell ss:StyleID="s63"><Data ss:Type="String">数量</Data></Cell>
<Cell ss:StyleID="s63"><Data ss:Type="String">小计</Data></Cell>
<Cell ss:StyleID="s63"><Data ss:Type="String">备注</Data></Cell>
</Row>
{{ section name=row loop=$items }}
<Row ss:AutoFitHeight="0" ss:Height="20.25">
<Cell ss:Index="2" ss:StyleID="s101"><Data ss:Type="String">{{$items[row].product.name|escape}}</Data></Cell>
<Cell ss:StyleID="s101"><Data ss:Type="String">{{$items[row].product.code|escape}}</Data></Cell>
<Cell ss:StyleID="s99"><Data ss:Type="Number">{{$items[row].price}}</Data></Cell>
<Cell ss:StyleID="s100"><Data ss:Type="Number">{{$items[row].quantity}}</Data></Cell>
<Cell ss:StyleID="s99" ss:Formula="=RC[-2]*RC[-1]"><Data ss:Type="Number">00</Data></Cell>
<Cell ss:StyleID="s101"><Data ss:Type="String">{{$items[row].comment|escape}}</Data></Cell>
</Row>
{{ /section }}
<Row ss:AutoFitHeight="0" ss:Height="23.25">
<Cell ss:Index="2" ss:StyleID="s69"><Data ss:Type="String">汇总</Data></Cell>
<Cell ss:StyleID="s69"/>
<Cell ss:StyleID="s69"/>
<Cell ss:StyleID="s69" ss:Formula="=SUM(R[-{{$items_count}}]C:R[-1]C)"><Data ss:Type="Number">34</Data></Cell>
<Cell ss:StyleID="s70" ss:Formula="=SUM(R[-{{$items_count}}]C:R[-1]C)"><Data ss:Type="Number">44</Data></Cell>
<Cell ss:StyleID="s69"/>
</Row>
....
<Row ss:AutoFitHeight="0" ss:Height="20.25">
<Cell ss:Index="2" ss:StyleID="s63"><Data ss:Type="String">商品名称</Data></Cell>
<Cell ss:StyleID="s63"><Data ss:Type="String">商品编号</Data></Cell>
<Cell ss:StyleID="s63"><Data ss:Type="String">购买价</Data></Cell>
<Cell ss:StyleID="s63"><Data ss:Type="String">数量</Data></Cell>
<Cell ss:StyleID="s63"><Data ss:Type="String">小计</Data></Cell>
<Cell ss:StyleID="s63"><Data ss:Type="String">备注</Data></Cell>
</Row>
{{ section name=row loop=$items }}
<Row ss:AutoFitHeight="0" ss:Height="20.25">
<Cell ss:Index="2" ss:StyleID="s101"><Data ss:Type="String">{{$items[row].product.name|escape}}</Data></Cell>
<Cell ss:StyleID="s101"><Data ss:Type="String">{{$items[row].product.code|escape}}</Data></Cell>
<Cell ss:StyleID="s99"><Data ss:Type="Number">{{$items[row].price}}</Data></Cell>
<Cell ss:StyleID="s100"><Data ss:Type="Number">{{$items[row].quantity}}</Data></Cell>
<Cell ss:StyleID="s99" ss:Formula="=RC[-2]*RC[-1]"><Data ss:Type="Number">00</Data></Cell>
<Cell ss:StyleID="s101"><Data ss:Type="String">{{$items[row].comment|escape}}</Data></Cell>
</Row>
{{ /section }}
<Row ss:AutoFitHeight="0" ss:Height="23.25">
<Cell ss:Index="2" ss:StyleID="s69"><Data ss:Type="String">汇总</Data></Cell>
<Cell ss:StyleID="s69"/>
<Cell ss:StyleID="s69"/>
<Cell ss:StyleID="s69" ss:Formula="=SUM(R[-{{$items_count}}]C:R[-1]C)"><Data ss:Type="Number">34</Data></Cell>
<Cell ss:StyleID="s70" ss:Formula="=SUM(R[-{{$items_count}}]C:R[-1]C)"><Data ss:Type="Number">44</Data></Cell>
<Cell ss:StyleID="s69"/>
</Row>
....
这里我在 .xml 里面插入了 Smarty 标记,所以就可以很方便的用 Smarty 来解析这个 .xml 文件,生成最后的结果了。
如果输出的报表带有公式,一定要注意公式是以相对位置来计算单元格的。
例如 .xml 源文件中的:
CODE:
<Cell ss:StyleID="s69"
ss:Formula="=SUM(R[-{{$items_count}}]C:R[-1]C)"><Data
ss:Type="Number">34</Data></Cell>
.xml 源文件
order_template.xml (7.29 KB)
=============================
在程序里面输出的代码如下:
CODE:
function actionExport()
{
$id = (int)$_GET['order_id'];
$viewdata = array(
'order' => $this->_tableOrders->find($id, null, '*', false),
'items' => $this->_tableOrders->fetchOrderItems($id),
);
$viewdata['items_count'] = count($viewdata['items']) + 1;
header("Content-type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=order_{$id}.xml");
$this->_executeView('order_template.xml', $viewdata);
}
{
$id = (int)$_GET['order_id'];
$viewdata = array(
'order' => $this->_tableOrders->find($id, null, '*', false),
'items' => $this->_tableOrders->fetchOrderItems($id),
);
$viewdata['items_count'] = count($viewdata['items']) + 1;
header("Content-type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=order_{$id}.xml");
$this->_executeView('order_template.xml', $viewdata);
}
前面几行是获取数据,两个 header() 指示要输出的内容的类型,最后通过 $smarty 载入 .xml 输出报表。
转自:FleaPHP论坛