## 依賴庫
大名鼎鼎的phpexcel
<http://phpexcel.codeplex.com>
## 效果





是用方法就是后臺初始化report數據庫后,然后自己建好數據表。
然后新建模板->上傳一個excel模板,指定好查詢的數據,和填充的開始項。然后數據隨便后臺操作數據庫。前臺就是把excel報表顯示輸出來即可。
感謝寫好這個系統的吳學海同學。其實數據填充那步相當于excel軟件導入的數據源。
這套模板管理系統支持多子excel和對應多數據源。組合起來不是特別復雜的excel報表都能滿足。
像第一個簽到模板,我的excel模板,excel中的豎線自己設格式。
然后我的數據源,
就是序列化字段里的那個 select name,time from sign limit 10。然后開始位置是每行的第一個單元格德位置如 A2 表示第二行第一列。
要更完善的話,就是數據源支持選api就更好了。配置最好用json 可讀性更高
## 實現
隨書項目yang_book/examples/excel里。
我們只看excel的相關代碼:
前臺具體顯示某一個模板的excel
~~~
/**
* 查詢數據庫填充excel并展示為html。
* @throws \PHPExcel_Exception
* @throws \PHPExcel_Reader_Exception
* @throws \PHPExcel_Writer_Exception
*/
public function showReport(){
//是否導出
$export = I('export',0,'int');
$id = I('report_id',0,'int');
if(!$id){
$this->error('參數有誤');
}
$reportInfo = M('report')->where(array('id'=>$id))->find();
//導入第三方類
import("Vendor.PHPExcel");
import("Vendor.PHPExcel.Reader.Excel2007");
import("Vendor.PHPExcel.Reader.Excel5");
import("Vendor.PHPExcel.Reader.HTML");
import("Vendor.PHPExcel.Writer.Excel2007");
import("Vendor.PHPExcel.Writer.CSV");
import("Vendor.PHPExcel.IOFactory");
$totalPHPExcel = [];
$tempInfo = unserialize($reportInfo['tempinfo']);
foreach($tempInfo as $k=>$va){
$PHPReader = new \PHPExcel_Reader_Excel2007();
if(!$PHPReader->canRead('./Uploads/template'.$va['path'])){
$PHPReader = new \PHPExcel_Reader_Excel5();
if(!$PHPReader->canRead('./Uploads/template'.$va['path'])){
$this->error('該excel模板無法讀取。請聯系管理員');
return ;
}
}
//讀取模板
$PHPExcel = $PHPReader->load('./Uploads/template'.$va['path']);
$currentSheet = $PHPExcel->getSheet(0);
foreach($va['config'] as $cnf){
//根據配置信息,查詢數據
$sql = $cnf['sql'];
$start_x = preg_split("/([a-zA-Z]+)/", $cnf['start_x'], 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
if(empty($sql)){
break;
$this->error('sql錯誤');
}
$data = M()->query($sql);
//row坐標計數器
$i = 0;
foreach($data as $v){
if(is_array($v) && !empty($v)){
$AZ = strtoupper($start_x[0]);
//循環填充數據
foreach($v as $value){
$currentSheet->setCellValue($AZ.($start_x[1]+$i),$value);
$objStyleA1 = $currentSheet->getStyle($AZ.($start_x[1]+$i));
$objAlignA1 = $objStyleA1->getAlignment();
$objAlignA1->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
$AZ = $this->nextAZ($AZ);
if(!$AZ){
$this->error('A-Z超值,請聯系管理員');
}
}
}
$i++;
}
}
if(!$export){
//顯示模板
$objWriteHTML =new \PHPExcel_Writer_HTML($PHPExcel);
$objWriteHTML->save("php://output");
}else{
$objWrite = new \PHPExcel_Writer_Excel2007($PHPExcel);
$objWrite->save ($k.'.xls');
$totalPHPExcel[] = $k.'.xls';
}
}
//excel文件導出,所有模板打包一起下載
if($export){
@unlink(iconv("UTF-8","gbk//TRANSLIT",$reportInfo['name'].'.zip'));
$zip = new \ZipArchive();
if($zip->open(iconv("UTF-8","gbk//TRANSLIT",$reportInfo['name'].'.zip'),\ZipArchive::OVERWRITE) === true){
foreach($totalPHPExcel as $v){
$zip->addFile($v);
}
}
$zip->close();
//下面是輸出下載;
header ( "Cache-Control: max-age=0" );
header ( "Content-Description: File Transfer" );
header ( 'Content-disposition: attachment; filename=' . basename (iconv("UTF-8","gbk//TRANSLIT",$reportInfo['name'].'.zip')) ); // 文件名
header ( "Content-Type: application/zip" ); // zip格式的
header ( "Content-Transfer-Encoding: binary" );
header ( 'Content-Length: ' . filesize (iconv("UTF-8","gbk//TRANSLIT",$reportInfo['name'].'.zip') ) ); // 告訴瀏覽器,文件大小
@readfile ( iconv("UTF-8","gbk//TRANSLIT",$reportInfo['name'].'.zip'));//輸出文件;
}
}
~~~
類私有方法nextAZ:
~~~
/**
* 返回下一個字母
* @param $currAZ
* @return bool
*/
private function nextAZ($currAZ){
$defaultAZ = array(
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
);
$countLength = count($currAZ);
if($countLength > 1){
//TODO:大于1位未實現
substr($currAZ,-1,1);
return false;
}else{
if($currAZ != 'Z'){
$index = array_search($currAZ,$defaultAZ);
return $defaultAZ[$index+1];
}else{
//TODO:超過Z未實現
return false;
}
}
}
~~~
大家具體看看 主要是用了excel的打開模板`$PHPReader->load`、遍歷填值`$currentSheet->setCellValue($AZ.($start_x[1]+$i),$value);` 還有下載文件和壓縮下載
## 參考
<http://www.seo0395.com/archives-211>介紹的比較全,英文不好的可以看看,好的直接看官方文檔 <https://github.com/PHPOffice/PHPExcel/wiki/User%20Documentation>
- 序
- 前言
- 內容簡介
- 目錄
- 基礎知識
- 起步
- 控制器
- 模型
- 模板
- 命名空間
- 進階知識
- 路由
- 配置
- 緩存
- 權限
- 擴展
- 國際化
- 安全
- 單元測試
- 拿來主義
- 調試方法
- 調試的步驟
- 調試工具
- 顯示trace信息
- 開啟調試和關閉調試的區別
- netbeans+xdebug
- Socketlog
- PHP常見錯誤
- 小黃鴨調試法,每個程序員都要知道的
- 應用場景
- 第三方登錄
- 圖片處理
- 博客
- SAE
- REST實踐
- Cli
- ajax分頁
- barcode條形碼
- excel
- 發郵件
- 漢字轉全拼和首字母,支持帶聲調
- 中文分詞
- 瀏覽器useragent解析
- freelog項目實戰
- 需求分析
- 數據庫設計
- 編碼實踐
- 前端實現
- rest接口
- 文章發布
- 文件上傳
- 視頻播放
- 音樂播放
- 圖片幻燈片展示
- 注冊和登錄
- 個人資料更新
- 第三方登錄的使用
- 后臺
- 微信的開發
- 首頁及個人主頁
- 列表
- 歸檔
- 搜索
- 分頁
- 總結經驗
- 自我提升
- 進行小項目的鍛煉
- 對現有輪子的重構和移植
- 寫技術博客
- 制作視頻教程
- 學習PHP的知識和新特性
- 和同行直接溝通、交流
- 學好英語,走向國際
- 如何參與
- 瀏覽官網和極思維還有看云
- 回答ThinkPHP新手的問題
- 嘗試發現ThinkPHP的bug,告訴官方人員或者push request
- 開發能提高效率的ThinkPHP工具
- 嘗試翻譯官方文檔
- 幫新手入門
- 創造基于ThinkPHP的產品,進行連帶推廣
- 展望未來
- OneThink
- ThinkPHP4
- 附錄