## 1 簡介
### 1.1 導出 ??
? ? ? 在實際的工作項目中,經常需要將一些重要的數據庫中存的數據導出成Excel,比如導出考勤報表,導出財務報表,導出業績報表,導出銷售報表等。CleverCode以前使用了兩年的PHPExcel來制作Excel導出數據,但發現用PHPExcel生成Excel實在是太麻煩了,特別是控制單元格的顏色,合并單元格,給單元格設置長度等。這些設計一個Excel通常會需要花費一天的時間。后來CleverCode發現了一個簡便的方法PHP導出xml格式的Excel,以前需要一天的工作量,現在半小時就搞定了,實在是事半功倍!
?
### 1.2 導入
? ? ? ?同時有的項目也需要,將一些Excel數據導入到數據庫中。比如銀行給的銀行流水,銷售報表導入的數據庫中。這個通常的做法都是使用PHPExcel。
? ? ? ? 雖然讀取xml格式的Excel可以使用Xml parser, SimpleXML, XMLReader, DOMDocument等方式,但是CleverCode嘗試過使用這些方式,發現太復雜,太費勁,沒有PHPExcel好使。
? ? ? ?所以當需要讀取Excel的時候(包括xml格式的),CleverCode推薦使用PHPExcel庫。
## 2 需求
? ? 某個集團需要各個地區的負責人將其負責的城市站的訂單和銷售額導入到數據庫。
? ? 1)網站提供一個導入的銷售報表模板。
? ? 2)每個負責人只能上傳與下載各自負責城市的數據(權限檢查)。
? ? 3)只用上傳生成當年,當日的擁有的所有季度。比如今天是2015-05-26。那么只有生成2015一季度,與二季度。
? ? ? ? 如果是2015-12-01。則需要生成2015一,二,三,四季度。
? ? 4)顯示本季度以前季度的數據。
? ? 5)本季度的數據默認全是0。
? ? 6)只能修改本季度的數據。
## 3 程序設計源碼下載
? ? ? ?[http://download.csdn.net/detail/clevercode/8750869](http://download.csdn.net/detail/clevercode/8750869)
## 4 設計網站頁面
### 4.1 顯示

### 4.2 display.php代碼
~~~
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk" />
<title>PHP導入與導出xml格式的Excel</title>
<style type="text/css">
body{ font-size:14px;}
input{ vertical-align:middle; margin:0; padding:0}
.file-box{ position:relative;width:340px}
.txt{ height:22px; border:1px solid #cdcdcd; width:180px;}
.btn{ background-color:#FFF; border:1px solid #CDCDCD;height:24px; width:70px;}
.file{ position:absolute; top:0; right:80px; height:24px; filter:alpha(opacity:0);
opacity: 0;width:260px }
</style>
</head>
<body>
<div class="file-box">
<form action="" method="post" enctype="multipart/form-data">
<input type='text' name='textfield' id='textfield' class='txt' />
<input type='button' class='btn' value='瀏覽...' />
<input type="file" name="fileField" class="file" id="fileField" size="28"
onchange="document.getElementById('textfield').value=this.value" />
<input type="submit" name="submit" class="btn" value="上傳" />
</form>
<a href="export.php">下載銷售報表模板</a>
</div>
</body>
</html>
~~~
??
## 5 PHP導出xml格式的Excel(導出銷售報表模板)
1)新建一個【銷售報表.xlsx】。設計如下。

2)將【銷售報表.xlsx】文件另存為【銷售報表.xml】


3)打開【銷售報表.xml】可以看到xml格式的數據。
4)找到table信息。刪除掉ss:ExpandedColumnCount="5" ss:ExpandedRowCount="6"。這個限制死了表格的長度和寬度,所以必須去掉。
? ?<Table ss:ExpandedColumnCount="5" ss:ExpandedRowCount="6" x:FullColumns="1"
? ?x:FullRows="1" ss:StyleID="s23" ss:DefaultColumnWidth="54"
? ?ss:DefaultRowHeight="18.75">
? 改成
? <Table ?x:FullColumns="1"
? ?x:FullRows="1" ss:StyleID="s23" ss:DefaultColumnWidth="54"
? ?ss:DefaultRowHeight="18.75">

5 PHP導出Excel業務邏輯代碼(Excel.php)
~~~
<?php
/**
* Excel.php
*
* Excel操作
*
* Copyright (c) 2015 http://blog.csdn.net/CleverCode
*
* modification history:
* --------------------
* 2015/5/14, by CleverCode, Create
*
*/
class Excel{
/**
* 導出excel
*
* @param int $userid 用戶編號
* @return string $xmlStr
*/
public static function export($userid){
// 根據不同用戶的權限,獲取不同的數據
$data = self::getExportData($personid);
// 獲取字符串,如果excel的列是固定的可以通過Smarty方式獲取
// 但是如果excel的列需要通過動態生成,則可以通過php組合字符串。
// $xmlStr = self::getXmlStrBySmarty($data);
// 這個需要根據當前日期動態的生成有幾個季度
$xmlStr = self::getXmlStrByPHP($data);
return $xmlStr;
}
/**
* 生成excel數據
*
* @param int $userid 用戶編號
* @return array 結果數據
*/
public static function getExportData($userid){
if (!is_int($userid)) {
return array();
}
$infoBJ = array(
'city' => '北京',
'order_1' => 100,
'money_1' => 10000,
'order_2' => 200,
'money_2' => 40000
);
$infoTJ = array(
'city' => '天津',
'order_1' => 50,
'money_1' => 1000,
'order_2' => 100,
'money_2' => 2000
);
$infoGZ = array(
'city' => '廣州',
'order_1' => 50,
'money_1' => 1000,
'order_2' => 100,
'money_2' => 2000
);
// 根據不同用戶的權限,獲取不同的數據
if (is_admin($userid)) {
$data[] = $infoBJ;
$data[] = $infoTJ;
$data[] = $infoGZ;
} else {
$data[] = $infoBJ;
}
return $data;
}
/**
* 通過Smarty方式獲取xml字符串
*
* @param array $data 結果集
* @return string $xmlStr
*/
public static function getXmlStrBySmarty($data){
require_once 'Smarty.class.php';
$smarty = new Smarty();
$tpl = 'file/export.tpl';
$smarty->assign('list', $data);
// capture the output
// 捕獲輸出
$xml = $smarty->fetch($tpl);
return $xml;
}
/**
* 通過PHP組合字符串方式獲取xml字符串(可以動態擴展列)
*
* @param array $data 結果集
* @return string $xmlStr
*/
public static function getXmlStrByPHP($data){
$xml = '
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
............
</Style>
</Styles>
<Worksheet ss:Name="Sheet1">
<Table x:FullColumns="1"
x:FullRows="1" ss:StyleID="s16" ss:DefaultColumnWidth="54"
ss:DefaultRowHeight="18.75">
';
//可以根據季度的多少動態擴展列,這里不做說明,請自行嘗試。
$xml. = '
<Row ss:AutoFitHeight="0">
<Cell ss:MergeDown="1" ss:StyleID="m42513364"><Data ss:Type="String">城市</Data></Cell>
<Cell ss:MergeAcross="1" ss:StyleID="s25"><Data ss:Type="String">2015一季度</Data></Cell>
<Cell ss:MergeAcross="1" ss:StyleID="m42513344"><Data ss:Type="String">2015二季度</Data></Cell>
</Row>
<Row ss:AutoFitHeight="0">
<Cell ss:Index="2" ss:StyleID="s17"><Data ss:Type="String">訂單</Data></Cell>
<Cell ss:StyleID="s17"><Data ss:Type="String">銷售額</Data></Cell>
<Cell ss:StyleID="s17"><Data ss:Type="String">訂單</Data></Cell>
<Cell ss:StyleID="s17"><Data ss:Type="String">銷售額</Data></Cell>
</Row>
';
// 輸出數據
foreach ( $data as $row ) {
$xml .= '
<Row ss:AutoFitHeight="0">
<Cell ss:StyleID="s18"><Data ss:Type="String">' . $row['city'] . '</Data></Cell>
<Cell ss:StyleID="s19"><Data ss:Type="Number">' . $row['order_1'] . '</Data></Cell>
<Cell ss:StyleID="s19"><Data ss:Type="Number">' . $row['money_1'] . '</Data></Cell>
<Cell ss:StyleID="s19"><Data ss:Type="Number">' . $row['order_2'] . '</Data></Cell>
<Cell ss:StyleID="s19"><Data ss:Type="Number">' . $row['money_2'] . '</Data></Cell>
</Row>
';
}
$xml .= '
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
...........
</Workbook>
';
return $xml;
}
}
~~~
6 PHP導出Excel客戶端代碼(export.php)
~~~
<?php
/**
* export.php
*
* 導出excel
*
* Copyright (c) 2015 http://blog.csdn.net/CleverCode
*
* modification history:
* --------------------
* 2015/5/14, by CleverCode, Create
*
*/
// Excel類
include_once ('Excel.php');
/*
* 客戶端類
* 讓客戶端和業務邏輯盡可能的分離,降低客戶端和業務邏輯算法的耦合,
* 使業務邏輯的算法更具有可移植性
*/
class Client{
public function main(){
// 獲取xml格式字符串
$xmlStr = Excel::export(1);
// 頭部
$filename = '銷售報表模板';
header("Content-Type: application/vnd.ms-excel; charset=UTF-8");
header("Content-Disposition: inline; filename=\"$filename.xls\"");
header("Content-Transfer-Encoding: binary");
header("Pragma: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
// 輸出字符串
echo $xmlStr;
exit();
}
}
/**
* 程序入口
*/
function start(){
$client = new Client();
$client->main();
}
start();
?>
~~~
## 6 PHP導入xml格式的Excel
1)下載銷售模板后,填寫其中的數據,然后點擊頁面中的上傳按鈕,上傳Excel數據。

2)?PHP導入的Excel業務邏輯代碼(Excel.php)。這里使用了PHPExcel庫。
~~~
<?php
/**
* Excel.php
*
* Excel操作
*
* Copyright (c) 2015 http://blog.csdn.net/CleverCode
*
* modification history:
* --------------------
* 2015/5/14, by CleverCode, Create
*
*/
class Excel{
/*
* 讀取Excel格式的數據(可以讀取xml格式數據)
*
* @param string $filename excel文件
* @param string $startRow 開始行
* @param string $endRow 結束行
* @param string $startColumn 開始列
* @param string $endColumn 結束列
* @return array excel結果集數據
*/
public static function read($filename, $startRow = 1, $endRow = null, $startColumn = 0, $endColumn = null){
$excelData = array();
if (!file_exists($filename)) {
return $excelData;
}
require_once 'PHPExcel/PHPExcel.php';
require_once 'PHPExcel/PHPExcel/IOFactory.php';
// 加載excel文件
$objPHPExcel = PHPExcel_IOFactory::load($filename);
// 獲取焦點Sheet
$objWorksheet = $objPHPExcel->getActiveSheet();
// 獲取總行
$totalRows = $objWorksheet->getHighestRow(); // 獲取總行數
// 獲取總列
$highestColumn = $objWorksheet->getHighestColumn();
$totalColumns = PHPExcel_Cell::columnIndexFromString($highestColumn);
// 開始行
if (!is_int($startRow) || $startRow < 1) {
$startRow = 1;
}
// 結束行
if ($endRow == null || !is_int($endRow) || $endRow > $totalRows) {
$endRow = $totalRows;
}
// 開始列
if (!is_int($startColumn) || $startColumn < 0) {
$startColumn = 0;
}
// 結束列
if ($endColumn == null || !is_int($endColumn) || $endColumn > $totalColumns) {
$endColumn = $totalColumns;
}
// 讀取數據
for($rowNum = $startRow; $rowNum <= $endRow; $rowNum++) {
for($colNum = $startColumn; $colNum < $endColumn; $colNum++) {
$item = $objWorksheet->getCellByColumnAndRow($colNum, $rowNum);
$exValue = trim($item->getValue());
$excelData[$rowNum][$colNum] = $exValue;
}
}
return $excelData;
}
}
~~~
3)?PHP導入的Excel客戶端代碼(import.php)
~~~
<?php
/**
* import.php
*
* 導入excel
*
* Copyright (c) 2015 http://blog.csdn.net/CleverCode
*
* modification history:
* --------------------
* 2015/5/14, by CleverCode, Create
*
*/
// Excel類
include_once ('Excel.php');
/*
* 客戶端類
* 讓客戶端和業務邏輯盡可能的分離,降低客戶端和業務邏輯算法的耦合,
* 使業務邏輯的算法更具有可移植性
*/
class Client{
public function main(){
if (!$_FILES['file']) {
exit();
}
// 從第3行開始讀取Excel數據
$datas = Excel::read($_FILES['file']['tmp_name'], 3);
// 將$datas保存到數據庫
// ....
}
}
/**
* 程序入口
*/
function start(){
$client = new Client();
$client->main();
}
start();
?>
~~~
**版權聲明:**
1)原創作品,出自"CleverCode的博客",轉載時請務必注明以下原創地址,否則追究版權法律責任。
2)原創地址:[http://blog.csdn.net/clevercode/article/details/46226461](http://blog.csdn.net/clevercode/article/details/46226461)(轉載務必注明該地址)。
3)分類地址(PHP程序員技術精粹):[http://blog.csdn.net/clevercode/article/category/3169943](http://blog.csdn.net/clevercode/article/category/3169943)(博客持續增加,關注請收藏)
4)歡迎大家關注我博客更多的精彩內容:[http://blog.csdn.net/CleverCode](http://blog.csdn.net/CleverCode)。