<?php |
/** |
* @desc excel接口 |
* @author mengdejun |
*/ |
interface IExcel |
{ |
//导入excel |
public function import( $fileName , $convert_callback_function =null); |
//导出excel |
public function export( $fileName = "excel" ); |
//添加行 |
public function addRow( array $array , $sheet = "sheet1" ); |
//添加表头 |
public function addHead( array $array , $sheet = "sheet1" ); |
//添加工作簿 |
public function addSheet( $sheet ); |
//释放资源 |
public function release(); |
} |
?> |
<?php |
include_once ( 'IExcel.php' ); |
/** |
* @desc php生成excel类函数 |
* @author mengdejun |
* @date 20100806 |
* @version 1.1.2 |
*/ |
class HtmlExcel implements IExcel |
{ |
private $_line = array (); |
private $isHeader =false; |
private $convert =false; |
public function __construct(){} |
/** |
* @desc 添加表头信息,注:表头仅可添加一次,若无表头则将内容行的第一行作为表头 |
* @param array $array |
* @param unknown_type $sheet |
*/ |
public function addHead( array $array , $sheet = "sheet1" ) |
{ |
if (! $this ->isHeader) |
$this ->_line[]= $this ->getLine( $array ); |
$this ->isHeader=true; |
} |
/** |
* @desc 添加自定义字符转换或过滤函数 |
* @param unknown_type $functionName 回调函数名 |
*/ |
public function addConvert( $functionName = "convert" ) |
{ |
$this ->convert= $functionName ; |
} |
protected function getLine( array $array , $sheet = 'sheet1' ) |
{ |
$_temp = "" ; |
$_count =sizeof( $array ); |
$index =0; |
foreach ( $array as $value ): |
$_temp .= $this ->convert( $value ); |
if ( $index == $_count -1): |
$_temp .= "\t\n" ; |
else : |
$_temp .= "\t" ; |
endif ; |
$index ++; |
endforeach ; |
return $_temp ; |
} |
/** |
* @desc 添加excel行,若没有设置表头则将该数组的第一个元素作为表头 |
* @param array $array |
* @param unknown_type $sheet |
*/ |
public function addRow( array $array , $sheet = "sheet1" ) |
{ |
$this ->_line[]= $this ->getLine( $array , $sheet ); |
return $this ->_line; |
} |
/** |
* @desc 嵌套添加excel行,若没有设置表头则将该数组的第一个元素作为表头 |
* @param array $array |
* @param unknown_type $sheet |
*/ |
public function addRows( array $array , $sheet = "sheet1" ) |
{ |
foreach ( $array as $value ): |
if ( is_array ( $value )): |
$this ->addRow( $value ); |
else : |
$this ->addRow( $array ); |
endif ; |
endforeach ; |
} |
/** |
* @desc 添加工作簿,暂不支持V1.0 |
* @deprecated |
* @param array $array |
*/ |
public function addSheet( $sheet ) { return ;} |
/** |
* @desc 返回excel表行数 |
*/ |
public function getRows() |
{ |
return sizeof( $this ->_line); |
} |
/** |
* @desc 返回excel内容 |
*/ |
public function getBody() |
{ |
return $this ->_line; |
} |
/** |
* @desc 导出excel文件 |
* @param unknown_type $fileName 导出文件名 |
*/ |
public function export( $fileName = "excel" ) |
{ |
header( "Content-Type: application/vnd.ms-excel;" ); |
header( "Content-Disposition:filename={$fileName}.xls" ); |
for ( $index =0; $index <sizeof( $this ->_line); $index ++): |
echo $this ->_line[ $index ]; |
endfor ; |
} |
/** |
* @desc 用户自定义编码转化以及数据筛选函数 |
* @param unknown_type $str |
*/ |
protected function convert( $str ) |
{ |
if (function_exists( $this ->convert)): |
return call_user_func( $this ->convert, $str ); |
else : |
return $str ; |
endif ; |
} |
/** |
* @desc 设置表格内容 |
* @param unknown_type $array |
*/ |
public function setBody( $array ) |
{ |
$this ->_line= $array ; |
} |
/** |
* @desc 释放资源 |
*/ |
public function release() |
{ |
unset( $this ->_line); |
} |
public function import( $fileName , $convert_callback_function =null){} |
} |
?> |
<?php |
include_once ( 'IExcel.php' ); |
/** |
* @desc php生成excel类函数 支持导入 导出 多工作薄(数据分卷技术) |
* @filesource XmlExcel.php |
* @author mengdejun |
* @date 20100801 |
* @version 1.8.1 |
*/ |
if (!defined( "CHARSET" )):define( "CHARSET" , "UTF-8" ); endif ; |
if (!defined( "VERSION" )):define( "VERSION" , "12.00" ); endif ; |
if (!defined( "THIS_VERSION" )):define( "THIS_VERSION" , "1.8.1" ); endif ; |
if (!defined( "NULL" )):define( "NULL" ,null); endif ; |
class XmlExcel implements IExcel |
{ |
private $header = "<?xml version=\"1.0\" encoding=\"%s\"?>\n<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:x=\"urn:schemas-microsoft-com:office:excel\" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\" xmlns:html=\"http://www.w3.org/TR/REC-html40\">" ; |
private $documentInfo = "<DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\"><Author>{author}</Author><Created>{time}</Created><Company>{company}</Company><Version>{version}</Version></DocumentProperties>" ; |
private $footer = "</Workbook>" ; |
private $align_left = "<Style ss:ID=\"s62\"><Alignment ss:Horizontal=\"Left\" ss:Vertical=\"Center\"/></Style>" ; |
private $align_center = "<Style ss:ID=\"s63\"><Alignment ss:Horizontal=\"Center\" ss:Vertical=\"Center\"/></Style>" ; |
private $align_right = "<Style ss:ID=\"s64\"><Alignment ss:Horizontal=\"Right\" ss:Vertical=\"Center\"/></Style>" ; |
private $align_bold = "<Style ss:ID=\"s65\"><Alignment ss:Horizontal=\"Center\" ss:Vertical=\"Center\"/><Font ss:FontName=\"宋体\" x:CharSet=\"134\" ss:Size=\"12\" ss:Color=\"#000000\" ss:Bold=\"1\"/></Style>" ; |
private $align_default = "<Style ss:ID=\"Default\" ss:Name=\"Normal\"><Alignment ss:Horizontal=\"%s\" ss:Vertical=\"Center\"/><Borders/><Font ss:FontName=\"宋体\" x:CharSet=\"134\" ss:Size=\"11\" ss:Color=\"#000000\"/><Interior/><NumberFormat/><Protection/></Style>" ; |
private $charset =CHARSET; |
private $convert = "convert" ; |
private static $pre_workBook =NULL; |
private $_line =NULL; |
private $_column =NULL; |
private $_columnType =NULL; |
private $_styles =NULL; |
private $_style =NULL; |
private $_title =NULL; |
private $_align = "Left" ; |
private $defaultHeight =13.5; |
private $defaultWidth =54; |
private $_sheets =NULL; |
private $_heads =NULL; |
/** |
* @desc 构造方法 PHP5.X |
* @param string $charset 字符编码 |
*/ |
public function __construct( $charset = 'UTF-8' ) |
{ |
$this ->charset= $charset ; |
} |
/** |
* @desc 构造方法 PHP4.X |
* @param string $charset 字符编码 |
*/ |
public function XmlExcel( $charset = 'UTF-8' ) |
{ |
$this ->charset= $charset ; |
} |
/** |
* @desc 析构方法 |
*/ |
public function __destruct(){} |
/** |
* @desc 释放可用资源 |
* @return null |
*/ |
public function release() |
{ |
unset( $this ->_line, $this ->_column, $this ->_heads, $this ->_sheets, $this ->_styles, $this ->_style, $this ->_title,self:: $pre_workBook ); |
} |
/** |
* @desc 数组行转换函数 |
* @param array $array |
*/ |
protected function getLine( array $array ) |
{ |
$_temp = "<Row ss:AutoFitHeight=\"0\">" ; |
foreach ( $array as $key => $val ): |
#读取指定数据类型,默认String |
$_type =! empty ( $this ->_columnType)&&isset( $this ->_columnType)?! empty ( $this ->_columnType[ $key ])&&isset( $this ->_columnType)? $this ->_columnType[ $key ]: "String" : "String" ; |
$_temp .= "<Cell><Data ss:Type=\"{$_type}\">{$this->convert($val)}</Data></Cell>" ; |
endforeach ; |
$_temp .= "</Row>" ; |
return $_temp ; |
} |
/** |
* @desc 添加表格头,默认的第一个数组将作为表头 |
* @param array $array |
* @param string $sheet 工作表名 |
* @exception $array 不能为空 |
*/ |
public function addHead( array $array , $sheet = "sheet1" ) |
{ |
$this ->_line[ $sheet ][0]= $this ->getLine( $array ); |
$this ->_title[ $sheet ][ 'width' ]= count ( $array )-1; |
$this ->_sheets[]= $sheet ; |
$this ->_heads[ $sheet ][0]= $array ; |
} |
/** |
* @desc 添加行 |
* @param array $array |
* @param string $sheet |
*/ |
public function addRow( array $array , $sheet = "sheet1" , $isErrorReport =true) |
{ |
if ( $isErrorReport ): |
if ( empty ( $array )||!isset( $array )|| count ( $array )==0): |
exit ( "data can't null'" ); |
else : |
$this ->_line[ $sheet ][]= $this ->getLine( $array ); |
endif ; |
else : |
$this ->_line[ $sheet ][]= $this ->getLine( $array ); |
endif ; |
} |
/** |
* @desc 设置工作簿的表头对象 |
* @param $head 表头数据 |
* @param $sheet 工作簿名称 |
*/ |
public function setSheetHead( array $head , $sheet = "Sheet1" ) |
{ |
$this ->_line[ $sheet ][]= $this ->getLine( $head ); |
} |
/** |
* @desc 添加多行 支持嵌套数组 |
* @param array $array |
* @param unknown_type $sheet |
*/ |
public function addRows( array $array , $sheet = "Sheet1" ) |
{ |
foreach ( $array as $value ): |
if ( is_array ( $value )): |
$this ->addRow( $value , $sheet ); |
else : |
$this ->addRow( $array , $sheet ); |
endif ; |
endforeach ; |
} |
/** |
* @desc 获取制定工作薄的列宽度 |
* @param @sheet 工作薄名称 |
*/ |
public function getColumnLength( $sheet = "Sheet1" ) |
{ |
return $this ->_title[ $sheet ][ 'width' ]; |
} |
/** |
* @desc 添加工作薄 |
* @param unknown_type unknown_type $sheet |
*/ |
public function addSheet( $sheet , $array = array ()) |
{ |
$this ->_line[ $sheet ][]= $array ; |
} |
/** |
* @desc 工作薄添加标题 |
* @param string $str 标题 |
* @param string $sheet 工作薄名 |
*/ |
public function addTitle( $str , $sheet = "Sheet1" ) |
{ |
$str = $this ->convert( $str ); |
$this ->_title[ $sheet ][ 'title' ]= "<Row ss:AutoFitHeight=\"0\" ss:StyleID=\"s65\"><Cell ss:MergeAcross=\"{num}\"><Data ss:Type=\"String\">{$str}</Data></Cell></Row>" ; |
} |
/** |
* @desc excel导出 |
* @param string $fileName 导出的文件名 |
*/ |
public function export( $fileName = "excel" , $isConvert =false) |
{ |
if ( $isConvert ): |
$fileName = $this ->getConvertString( $fileName ); |
endif ; |
header( "Content-Type: application/vnd.ms-excel; charset=" . $this ->charset); |
header( "Content-Disposition:attachment; filename=\"{$fileName}.xls\"" ); |
echo stripslashes (sprintf( $this ->header, $this ->charset)); |
echo str_replace ( "{company}" , "xiao meng online" , str_replace ( "{time}" , date ( "Y-m-dH:i:s" ,time()), str_replace ( "{author}" , "mengdejun" , str_replace ( "{version}" ,VERSION, $this ->documentInfo)))); |
echo "<Styles>" ; |
echo stripslashes (sprintf( $this ->align_default, $this ->_align)); |
echo $this ->align_left; |
echo $this ->align_right; |
echo $this ->align_center; |
echo $this ->align_bold; |
echo "</Styles>" ; |
$_hasData = count ( $this ->_line)==0?false:true; |
if ( $_hasData ): |
#有数据,解析数组对象到excel表格 |
foreach ( $this ->_line as $key => $value ): |
echo "<Worksheet ss:Name=\"{$this->convert($key)}\"><Table ss:DefaultColumnWidth=\"{$this->defaultWidth}\" ss:DefaultRowHeight=\"{$this->defaultHeight}\">" ; |
#列样式和宽度 |
if (isset( $this ->_column[ $key ][ 'style_width' ])): |
foreach ( $this ->_column[ $key ][ 'style_width' ] as $s_key => $s_value ): |
echo "<Column ss:Index=\"{$s_key}\" ss:AutoFitWidth=\"1\" ss:Width=\"$s_value\"/>" ; |
endforeach ; |
endif ; |
#表格标题 |
if (! empty ( $this ->_title[ $key ][ 'title' ])): |
echo str_replace ( "{num}" , $this ->_title[ $key ][ 'width' ], $this ->_title[ $key ][ 'title' ]); |
endif ; |
#单元格 |
foreach ( $value as $_v ): |
echo $_v ; |
endforeach ; |
echo "</Table></Worksheet>" ; |
endforeach ; |
#加载标准工作薄(默认三个工作簿) |
$length = count ( $this ->_line); |
while ( $length <3): |
$length ++; |
echo "<Worksheet ss:Name=\"Sheet{$length}\"><Table></Table></Worksheet>" ; |
endwhile ; |
else : |
#无数据,添加默认工作簿和数据支持(错误处理:文件读取失败) |
for ( $index =1; $index <=3; $index ++): |
echo "<Worksheet ss:Name=\"Sheet{$index}\"><Table></Table></Worksheet>" ; |
endfor ; |
endif ; |
echo $this ->footer; |
} |
/** |
* @desc excel导入函数,注该函数的文件名必须是非中文 |
* @param unknown_type $fileName 导入的文件 |
* @param unknown_type $convert_callback_function 回调函数 支持编码转换,需返回转换后的字符串 |
* @return 三维数组,分别对应 工作薄/行/单元格 |
*/ |
public function import( $fileName , $convert_callback_function =null) |
{ |
$xls =simplexml_load_file( $fileName ); |
$is_convert =! empty ( $convert_callback_function )&&function_exists( $convert_callback_function ); |
$index =0; |
$_ra = array (); |
foreach ( $xls ->Worksheet as $worksheet ):#循环工作薄 |
$index_i =1; |
foreach ( $worksheet ->Table->Row as $cells ):#循环行 |
if ( $index_i !==1): |
foreach ( $cells as $cell ):#循环单元格 |
$_ra [ $index ][ $index_i ][]= $is_convert ?call_user_func( $convert_callback_function , $cell ->Data): $cell ->Data; |
endforeach ; |
endif ; |
$index_i ++; |
endforeach ; |
$index ++; |
endforeach ; |
return $_ra ; |
} |
/** |
* @desc 设置字符编码 |
* @param string $charset 设置导出文件的编码 |
*/ |
public function setCharset( $charset = "GBK" ) |
{ |
$this ->charset = $charset ; |
} |
/** |
* 设置工作薄的列的宽度 array(1=>10,2=>23,3=>23,4=>213,5=>asd) 重复设置该值 将覆盖前一次操作的结果 |
* @param string $sheet 工作薄名 |
* @param array $array 列数组 |
*/ |
public function setColumnWidth( $sheet = "sheet1" , $array ) |
{ |
if (! empty ( $this ->_column[ $sheet ][ 'style_width' ])&&isset( $this ->_column[ $sheet ][ 'style_width' ])): |
unset( $this ->_column[ $sheet ][ 'style_width' ]); |
endif ; |
$this ->_column[ $sheet ][ 'style_width' ]= $array ; |
} |
/** |
* @desc 设置所有工作薄的列宽度 |
* @param array $array 列宽度 |
*/ |
public function setAllColumnWidth( array $array ) |
{ |
$_temp = $this ->getAllSheetNames(); |
foreach ( $_temp as $value ): |
$this ->setColumnWidth( $value , $array ); |
endforeach ; |
} |
/** |
* @desc 设置默认行高 |
* @param integer $height |
*/ |
public function setDefaultRowHeight( $height = "54" ) |
{ |
$this ->defaultHeight= $height ; |
} |
/** |
* 设置字符编码转换函数(回调函数) |
* @param string $convert 设置转换函数 默认名称为convert |
*/ |
public function addConvert( $convert = "convert" ) |
{ |
$this ->convert = $convert ; |
} |
/** |
* @desc 内部回调函数,完成字符编码的转化 |
* @param unknown_type $str |
*/ |
protected function convert( $str ) |
{ |
if (function_exists( $this ->convert)): |
return call_user_func( $this ->convert, $str ); |
else : |
return $str ; |
endif ; |
} |
/** |
* 获取工作薄个数 |
* @param int $sheet 获取工作薄的个数 |
* @return integer |
*/ |
public function getSheets() |
{ |
return sizeof( $this ->_line); |
} |
/** |
* 获取工作薄表格行数 |
* @param String $sheet 工作薄名 |
* @return integer |
*/ |
public function getRows( $sheet ) |
{ |
return sizeof( $this ->_line[ $sheet ]); |
} |
/** |
* @desc 获取指定工作薄的表头信息 |
* @param string $sheet 工作薄名称 |
*/ |
public function getHead( $sheet ) |
{ |
return $this ->_heads[ $sheet ][0]; |
} |
/** |
* @desc 设置默认行高度 |
* @param integer $defaultHeight 行的默认高度 无默认值 |
*/ |
public function setDefaultHeight( $defaultHeight ) { |
$this ->defaultHeight = $defaultHeight ; |
} |
/** |
* @desc 设置默认的列宽度 |
* @param integer $defaultWidth 列的默认宽度 无默认值 |
*/ |
public function setDefaultWidth( $defaultWidth ) { |
$this ->defaultWidth = $defaultWidth ; |
} |
/** |
* @desc 当前工作薄可用行数 |
*/ |
public function currentSheetsLength() |
{ |
return sizeof( $this ->_line)+1; |
} |
/** |
* @desc 设置默认的居中方式 |
* @param string $_align 可选值 Left(left),Center(center),Right(right) |
*/ |
public function setDefaultAlign( $_align ) |
{ |
$this ->_align = ucfirst( $_align ); |
} |
/** |
* @desc 自动创建工作薄,支持自动分卷技术,该方法与addHead冲突,使用该方法时请勿调用addHead,否则将添加一个空白的工作薄 |
* @param array $head 表头 |
* @param array $data 数据 |
* @param int $pageSize 页面行数 默认60000,excel最大支持65536 |
* @param string $defaultName 工作薄名,工作簿不能重名 |
*/ |
public function addPageRow( array $head , array $data , $pageSize =60000, $defaultName = "Sheet" ) |
{ |
if (!isset( $defaultName )|| $defaultName == "Sheet" ) $defaultName = "Sheet" .( $this ->getSheets()+1); |
if ( empty (self:: $pre_workBook )): |
self:: $pre_workBook = $defaultName ; |
if (!isset( $this ->_heads[self:: $pre_workBook ][0])) |
$this ->addHead( $head ,self:: $pre_workBook ); |
$this ->addRow( $data ,self:: $pre_workBook ); |
else : |
if ( $this ->getRows(self:: $pre_workBook )>=( $pageSize +1)): |
$this ->addHead( $head , $defaultName ); |
$this ->addRow( $data , $defaultName ); |
self:: $pre_workBook = $defaultName ; |
else : |
$this ->addRow( $data ,self:: $pre_workBook ); |
endif ; |
endif ; |
} |
/** |
* @desc 返回所有工作薄名 |
* @param null |
*/ |
public function getAllSheetNames() |
{ |
return $this ->_sheets; |
} |
/** |
* @desc 设置所有表格标题(分卷) 默认为合并当前工作薄的所有列,并居中显示(粗体) 该方法必须在工作簿存在的情况下调用. |
* @param string $title 标题 |
*/ |
public function setAllTitle( $title ) |
{ |
$_temp = $this ->getAllSheetNames(); |
foreach ( $_temp as $value ): |
$this ->addTitle( $title , $value ); |
endforeach ; |
} |
/** |
* @desc 编码转换函数 |
* @param string $str 转换的字符串 |
* @param string $source_code 原编码 默认UTF-8 |
* @param string $target_code 目标编码 默认GBK |
*/ |
protected function getConvertString( $str , $source_code = 'UTF-8' , $target_code = 'GBK' ) |
{ |
return ! empty ( $str )&& is_string ( $str )?iconv( $source_code , $target_code , $str ): $str ; |
} |
/** |
* @desc 打印调试信息 |
* @param null |
*/ |
public function debug( $out =true) |
{ |
if ( $out ): |
var_dump( $this ->_line); |
else : |
return $this ->_line; |
endif ; |
} |
/** |
* @desc 工作薄命名后缀 调用此方法将生成全局唯一工作薄名 |
* @param $name 自定义工作薄名 |
*/ |
public function uniqueName( $name ) |
{ |
$size = $this ->getSheets(); |
if ( $size ==0) return $name ; |
else return $name . $size ; |
} |
/**设置单位格数据类型,该方法需在填充数据前完成 数据类型参照指定版本的excel |
* @param $_columnType the $_columnType to set array 指定的键值对数组 |
*/ |
public function set_columnType( $_columnType ) |
{ |
$this ->_columnType = $_columnType ; |
} |
} |
?> |
<?php |
include 'lib/XmlExcel.php' ; |
$xls = new XmlExcel; |
$xls ->setDefaultWidth(80); |
$xls ->setDefaultAlign( "center" ); |
$xls ->setDefaultHeight(18); |
$xls ->addHead( array ( "title1" , "title2" , "title3" , "title4" , "title5" , "title6" ), "demo1" ); |
for ( $ind =0; $ind <10; $ind ++): |
$xls ->addRow( array ( $ind , $ind , $ind , $ind , $ind , $ind ), "demo1" ); |
endfor ; |
$xls ->export( "demo1" ); |
?> |
<?php |
include 'lib/XmlExcel.php' ; |
$xls = new XmlExcel; |
$xls ->setDefaultWidth(80); |
$xls ->setDefaultAlign( "center" ); |
$xls ->setDefaultHeight(18); |
for ( $ind =0; $ind <50; $ind ++): |
$xls ->addPageRow( array ( "title1" , "title2" , "title3" , "title4" , "title5" , "title6" ), array ( $ind , $ind , $ind , $ind , $ind , $ind ),10, $xls ->uniqueName( "demo" )); |
endfor ; |
$xls ->export( "demo2" ); |
?> |