導出數據到Excel的實用方案

處理前-庫的選擇

實際工作場景中,經常需要將系統中數據導出爲Excel,便於產品和運營查閱和二次處理。本文詳細介紹了使用PHP導出數據的方法。

PHP操作Excel主要有兩個第三方庫,一個是PHPExcel,另外一個是PhpSpreadsheet。其中PhpSpreadsheet是PHPExcel的升級版本。

PHPExcel本身支持超鏈接、樣式設置(字體、顏色、邊框線、對齊等)、行高列寬設置、表格凍結、公式、合併單元格、多表格等特性。從官方文檔得知,PHPExcel支持PHP5.2版本,代碼質量和性能會低於PhpSpreadsheet。另外PHPExcel從2015年便不再維護,因此很難從社區增加新特性和處理歷史缺陷。PHPExcel支持xls和xlsx兩種格式,xls是Microsoft Excel 2003以下版本支持的文件,xlsx是Microsoft Excel 2007以後開始的。

PhpSpreadsheet是下一代的PHPExcel,支持PHP5.6及以上,可以處理Microsoft Excel和LibreOffice Calc。PhpSpreadsheet作爲下一代的PHPExcel,目前得到社區持續維護。

基於本身業務特點,以及疑難問題的快速處理,最終選擇了PHPExcel作爲導出的基礎庫,並且採用xls文件格式。PHPExcel庫因爲歷史久遠,積累了很多其他用戶踩過的坑,也便於我們處理類似疑難問題。

下文所述的方法是將內容導出爲xls文件格式。

處理中-內容的處理

處理多sheet

  • 核心方法:objphpexcel>createSheet(obj_phpexcel->createSheet(i);
$obj_phpexcel = new PHPExcel();
$sheet_datas;//實際數據
$sheet_name = 'test';
foreach($sheet_datas as $i => $sheet_data) {
	$obj_phpexcel->createSheet($i);
	$obj_phpexcel->setActiveSheetIndex($sheet_index);
	$obj_phpexcel->getActiveSheet()->setTitle($sheet_name);
}

處理樣式

  • 核心方法: objphpexcel>getActiveSheet()>getStyle(A1)>applyFromArray(obj_phpexcel->getActiveSheet()->getStyle('A1')->applyFromArray(style_array);
    getStyle的參數爲實際座標,比如A1,代表A列的第1行的單元格。applyFromArray的參數爲樣式配置。
//樣式配置
$style_array = array(
    'alignment' => array(
        'horizontal' =>
            PHPExcel_Style_Alignment::HORIZONTAL_GENERAL           = 'general'
            PHPExcel_Style_Alignment::HORIZONTAL_LEFT              = 'left'
            PHPExcel_Style_Alignment::HORIZONTAL_RIGHT             = 'right'
            PHPExcel_Style_Alignment::HORIZONTAL_CENTER            = 'center'
            PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS = 'centerContinuous'
            PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY           = 'justify'
        'vertical' =>
            PHPExcel_Style_Alignment::VERTICAL_BOTTOM  = 'bottom'
            PHPExcel_Style_Alignment::VERTICAL_TOP     = 'top'
            PHPExcel_Style_Alignment::VERTICAL_CENTER  = 'center'
            PHPExcel_Style_Alignment::VERTICAL_JUSTIFY = 'justify'
        'rotation' => (int)
        'wrap' => (boolean)
        'shrinkToFit' => (boolean)
        'indent' => (int)
    )
    'borders' => array(
        'allborders' => array(
            'style' => 
                PHPExcel_Style_Border::BORDER_NONE               = 'none';
                PHPExcel_Style_Border::BORDER_DASHDOT            = 'dashDot';
                PHPExcel_Style_Border::BORDER_DASHDOTDOT         = 'dashDotDot';
                PHPExcel_Style_Border::BORDER_DASHED             = 'dashed';
                PHPExcel_Style_Border::BORDER_DOTTED             = 'dotted';
                PHPExcel_Style_Border::BORDER_DOUBLE             = 'double';
                PHPExcel_Style_Border::BORDER_HAIR               = 'hair';
                PHPExcel_Style_Border::BORDER_MEDIUM             = 'medium';
                PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT      = 'mediumDashDot';
                PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT   = 'mediumDashDotDot';
                PHPExcel_Style_Border::BORDER_MEDIUMDASHED       = 'mediumDashed';
                PHPExcel_Style_Border::BORDER_SLANTDASHDOT       = 'slantDashDot';
                PHPExcel_Style_Border::BORDER_THICK              = 'thick';
                PHPExcel_Style_Border::BORDER_THIN               = 'thin';
            'color' => array(
                'rgb' =>
                    PHPExcel_Style_Color::COLOR_BLACK            = 'FF000000';
                    PHPExcel_Style_Color::COLOR_WHITE            = 'FFFFFFFF';
                    PHPExcel_Style_Color::COLOR_RED              = 'FFFF0000';
                    PHPExcel_Style_Color::COLOR_DARKRED          = 'FF800000';
                    PHPExcel_Style_Color::COLOR_BLUE             = 'FF0000FF';
                    PHPExcel_Style_Color::COLOR_DARKBLUE         = 'FF000080';
                    PHPExcel_Style_Color::COLOR_GREEN            = 'FF00FF00';
                    PHPExcel_Style_Color::COLOR_DARKGREEN        = 'FF008000';
                    PHPExcel_Style_Color::COLOR_YELLOW           = 'FFFFFF00';
                    PHPExcel_Style_Color::COLOR_DARKYELLOW       = 'FF808000';
            )

        )
        'left' => // See 'allborders'
        'top' => // See 'allborders'
        'right' => // See 'allborders'
        'bottom' => // See 'allborders'
        'diagonal' =>
        'diagonaldirection' => 
    )
    'fill' => array(
        'type' =>
            PHPExcel_Style_Fill::FILL_NONE                         = 'none';
            PHPExcel_Style_Fill::FILL_SOLID                        = 'solid';
            PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR              = 'linear';
            PHPExcel_Style_Fill::FILL_GRADIENT_PATH                = 'path';
            PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN             = 'darkDown';
            PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY             = 'darkGray';
            PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID             = 'darkGrid';
            PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL       = 'darkHorizontal';
            PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS          = 'darkTrellis';
            PHPExcel_Style_Fill::FILL_PATTERN_DARKUP               = 'darkUp';
            PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL         = 'darkVertical';
            PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625             = 'gray0625';
            PHPExcel_Style_Fill::FILL_PATTERN_GRAY125              = 'gray125';
            PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN            = 'lightDown';
            PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY            = 'lightGray';
            PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID            = 'lightGrid';
            PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL      = 'lightHorizontal';
            PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS         = 'lightTrellis';
            PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP              = 'lightUp';
            PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL        = 'lightVertical';
            PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY           = 'mediumGray';
        'rotation' => (double)
        'startcolor' => // See 'borders' => 'allborders' => 'color'
        'endcolor' => // See 'borders' => 'allborders' => 'color'
        'color' => // See 'borders' => 'allborders' => 'color'
    ) 
    'font' => array(
        'name' =>
            'Arial'
            'Calibri'
            // etc.
        'bold' => (boolean)
        'italic' => (boolean)
        'superScript' => (boolean)
        'subScript' => (boolean)
        'underline' => (boolean)
        'strike' => (boolean)
        'size' => (float)
        'color' => // See 'borders' => 'allborders' => 'color'
    )
    'numberformat' =>
    'protection' =>
)

寫入數據

  • 核心方法:$obj_phpexcel->getActiveSheet()->setCellValueExplicit(‘A1’, $value, $dtype);
    dtype區分不同的數據類型,定義見PHPExcel\Cell\DataType.php
/* Data types */
const TYPE_STRING2  = 'str';
const TYPE_STRING   = 's';
const TYPE_FORMULA  = 'f';
const TYPE_NUMERIC  = 'n';
const TYPE_BOOL     = 'b';
const TYPE_NULL     = 'null';
const TYPE_INLINE   = 'inlineStr';
const TYPE_ERROR    = 'e';

處理超鏈接

核心方法:objphpexcel>getActiveSheet()>getCell(A1)>getHyperlink()>setUrl(obj_phpexcel->getActiveSheet()->getCell('A1')->getHyperlink()->setUrl(URL);

處理公式

核心方法:$obj_phpexcel->getActiveSheet()->setCellValue(‘A1’, ‘=SUM(A10:E9)’);

合併單元格

核心方法:$obj_phpexcel->getActiveSheet()->mergeCells(‘A1:C1’);

列寬和行高

//列寬
$obj_phpexcel->getActiveSheet()->getColumnDimension($column_label)->setWidth($value);
//行高
$obj_phpexcel->getActiveSheet()->getRowDimension($key)->setRowHeight($value);

表格凍結

核心方法:$obj_phpexcel->getActiveSheet()->freezePane(‘D2’);

其他問題

實際值、像素值隱射

PHPExcel沒辦法將像素值,轉化爲Microsoft Excel實際的寬度和高度值。如果直接將像素值設置爲Excel的實際值,會導致內容存在差異。經過測試得知,Excel實際值和像素值之間滿足線性關係。知道問題原因,處理起來便很簡單。

 private function _get_excel_real_width($value) {
 	return $value/7;
 }

橫座標處理

Excel的橫座標爲A、B…、AA、AB類型,需要將PHP數組下標轉化爲Excel的橫座標。

private function _get_sheet_col_label($index) {

	if (isset($this->_col_label_map[$index])) {
		return $this->_col_label_map[$index];
	}
	$abc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
	for ($i=0; $i < 600; $i++) { //最高支持600列
		$a = (int)($i / 26);
		$b = $i % 26;
		$column_label = '';
		if ($a == 0) {
			$column_label = $column_label . substr($abc, $b, 1);
		} else {
			$a = $a -1;
			$column_label = substr($abc, $a, 1) . substr($abc, $b, 1); 
		}
		$this->_col_label_map[($i)] = $column_label; 
	}
	return $this->_col_label_map[$index];
}

默認的樣式處理

Excel本身的表格框線無法通過PHPExcel設置,需要trick處理。另外Excel的樣式屬性與css樣式屬性也會有差異,需要注意下。

//設置Excel默認框線
 $style_array = array(
      'borders' => array(
          'allborders' => array(
                'style' => PHPExcel_Style_Border::BORDER_THIN,
    			'color' => array('rgb' => 'DDDDDD')
          )
      )
  );

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章