2013-03-01 27 views
2

我有我的CakePHP應用程序中實現PHPExcel,這是我的助手:CakePHP的 - PHP EXCEL保存爲html的

<?php 
App::uses('AppHelper', 'Helper'); 

/** 
* Helper for working with PHPExcel class. 
* PHPExcel has to be in the vendors directory. 
*/ 

class PhpExcelHelper extends AppHelper { 
    /** 
    * Instance of PHPExcel class 
    * @var object 
    */ 
    public $xls; 
    /** 
    * Pointer to actual row 
    * @var int 
    */ 
    protected $row = 1; 
    /** 
    * Internal table params 
    * @var array 
    */ 
    protected $tableParams; 

    /** 
    * Constructor 
    */ 
    public function __construct(View $view, $settings = array()) { 
     parent::__construct($view, $settings); 
    } 

    /** 
    * Create new worksheet 
    */ 
    public function createWorksheet() { 
    $this->loadEssentials(); 
    $this->xls = new PHPExcel(); 
    } 

    /** 
    * Create new worksheet from existing file 
    */ 
    public function loadWorksheet($path) { 
    $this->loadEssentials(); 
    $this->xls = PHPExcel_IOFactory::load($path); 
    } 

    /** 
    * Set row pointer 
    */ 
    public function setRow($to) { 
    $this->row = (int)$to; 
    } 

    /** 
    * Set default font 
    */ 
    public function setDefaultFont($name, $size) { 
    $this->xls->getDefaultStyle()->getFont()->setName($name); 
    $this->xls->getDefaultStyle()->getFont()->setSize($size); 
    } 

    /** 
    * Start table 
    * inserts table header and sets table params 
    * Possible keys for data: 
    * label - table heading 
    * width - "auto" or units 
    * filter - true to set excel filter for column 
    * wrap - true to wrap text in column 
    * Possible keys for params: 
    * offset - column offset (numeric or text) 
    * font - font name 
    * size - font size 
    * bold - true for bold text 
    * italic - true for italic text 
    * 
    */ 
    public function addTableHeader($data, $params = array()) { 
    // offset 
    if (array_key_exists('offset', $params)) 
     $offset = is_numeric($params['offset']) ? (int)$params['offset'] : PHPExcel_Cell::columnIndexFromString($params['offset']); 
    // font name 
    if (array_key_exists('font', $params)) 
     $this->xls->getActiveSheet()->getStyle($this->row)->getFont()->setName($params['font_name']); 
    // font size 
    if (array_key_exists('size', $params)) 
     $this->xls->getActiveSheet()->getStyle($this->row)->getFont()->setSize($params['font_size']); 
    // bold 
    if (array_key_exists('bold', $params)) 
     $this->xls->getActiveSheet()->getStyle($this->row)->getFont()->setBold($params['bold']); 
    // italic 
    if (array_key_exists('italic', $params)) 
     $this->xls->getActiveSheet()->getStyle($this->row)->getFont()->setItalic($params['italic']); 

    // set internal params that need to be processed after data are inserted 
    $this->tableParams = array(
     'header_row' => $this->row, 
     'offset' => $offset, 
     'row_count' => 0, 
     'auto_width' => array(), 
     'filter' => array(), 
     'wrap' => array() 
    ); 

    foreach ($data as $d) { 
     // set label 
     $this->xls->getActiveSheet()->setCellValueByColumnAndRow($offset, $this->row, $d['label']); 
     // set width 
     if (array_key_exists('width', $d)) { 
     if ($d['width'] == 'auto') 
      $this->tableParams['auto_width'][] = $offset; 
     else 
      $this->xls->getActiveSheet()->getColumnDimensionByColumn($offset)->setWidth((float)$d['width']); 
     } 
     // filter 
     if (array_key_exists('filter', $d) && $d['filter']) 
     $this->tableParams['filter'][] = $offset; 
     // wrap 
     if (array_key_exists('wrap', $d) && $d['wrap']) 
     $this->tableParams['wrap'][] = $offset; 

     $offset++; 
    } 
    $this->row++; 
    } 

    /** 
    * Write array of data to actual row 
    */ 
    public function addTableRow($data) { 
    $offset = $this->tableParams['offset']; 

    foreach ($data as $d) { 
     $this->xls->getActiveSheet()->setCellValueByColumnAndRow($offset++, $this->row, $d); 
    } 
    $this->row++; 
    $this->tableParams['row_count']++; 
    } 

    /** 
    * End table 
    * sets params and styles that required data to be inserted 
    */ 
    public function addTableFooter() { 
    // auto width 
    foreach ($this->tableParams['auto_width'] as $col) 
     $this->xls->getActiveSheet()->getColumnDimensionByColumn($col)->setAutoSize(true); 
    // filter (has to be set for whole range) 
    if (count($this->tableParams['filter'])) 
     $this->xls->getActiveSheet()->setAutoFilter(PHPExcel_Cell::stringFromColumnIndex($this->tableParams['filter'][0]).($this->tableParams['header_row']).':'.PHPExcel_Cell::stringFromColumnIndex($this->tableParams['filter'][count($this->tableParams['filter']) - 1]).($this->tableParams['header_row'] + $this->tableParams['row_count'])); 
    // wrap 
    foreach ($this->tableParams['wrap'] as $col) 
     $this->xls->getActiveSheet()->getStyle(PHPExcel_Cell::stringFromColumnIndex($col).($this->tableParams['header_row'] + 1).':'.PHPExcel_Cell::stringFromColumnIndex($col).($this->tableParams['header_row'] + $this->tableParams['row_count']))->getAlignment()->setWrapText(true); 
    } 

    /** 
    * Write array of data to actual row starting from column defined by offset 
    * Offset can be textual or numeric representation 
    */ 
    public function addData($data, $offset = 0) { 
    // solve textual representation 
    if (!is_numeric($offset)) 
     $offset = PHPExcel_Cell::columnIndexFromString($offset); 

    foreach ($data as $d) { 
     $this->xls->getActiveSheet()->setCellValueByColumnAndRow($offset++, $this->row, $d); 
    } 
    $this->row++; 
    } 

    /** 
    * Output file to browser 
    */ 
    public function output($filename = 'export.xlsx') { 
    // set layout 
    $this->View->layout = ''; 
    // headers 
    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); 
    header('Content-Disposition: attachment;filename="'.$filename.'"'); 
    header('Cache-Control: max-age=0'); 
    // writer 
    $objWriter = PHPExcel_IOFactory::createWriter($this->xls, 'Excel2007'); 
    $objWriter->save('php://output'); 
    // clear memory 
    $this->xls->disconnectWorksheets(); 
    } 

    /** 
    * Load vendor classes 
    */ 
    protected function loadEssentials() { 
    // load vendor class 
    App::import('Vendor', 'PHPExcel/Classes/PHPExcel'); 
    if (!class_exists('PHPExcel')) { 
     throw new CakeException('Vendor class PHPExcel not found!'); 
    } 
    } 
} 

這是我的控制器:

public $helpers = array('PhpExcel'); 
    ... 
    public function excel() { 
     $this->set('participants', $this->Participant->find('all')); 
    } 

這是我的看法:

<?php 
    $this->PhpExcel->createWorksheet(); 
    $this->PhpExcel->setDefaultFont('Calibri', 12); 

    // define table cells 
    $table = array(
     array('label' => __('id'), 'width' => 'auto', 'filter' => true), 
     array('label' => __('Förnamn'), 'width' => 'auto', 'filter' => true), 
     array('label' => __('Efternamn'), 'width' => 'auto', 'filter' => true), 
     array('label' => __('E-postadress'), 'width' => 'auto', 'filter' => true), 
     array('label' => __('Mobiltelefon'), 'width' => 'auto', 'filter' => true), 
     array('label' => __('Specialkost'), 'width' => 'auto', 'filter' => true), 
     array('label' => __('Enhet'), 'width' => 'auto', 'filter' => true), 
     array('label' => __('Seminarium'), 'width' => 'auto', 'filter' => true), 
     array('label' => __('Utanför Stockholm'), 'width' => 'auto', 'filter' => true), 
     array('label' => __('Dela rum'), 'width' => 'auto', 'filter' => true), 
     array('label' => __('Transfer'), 'width' => 'auto', 'filter' => true), 
     array('label' => __('Bara där på dagen'), 'width' => 'auto', 'filter' => true), 
     array('label' => __('Låt'), 'width' => 'auto', 'filter' => true), 
     array('label' => __('Lärare som blivit hyllad'), 'width' => 'auto', 'filter' => true), 
     array('label' => __('Kommentar'), 'width' => 'auto', 'filter' => true), 
    ); 

    // heading 
    $this->PhpExcel->addTableHeader($table, array('name' => 'Cambria', 'bold' => true)); 

    foreach ($participants as $d) { 
     $this->PhpExcel->addTableRow(array(
      $d['Participant']['id'], 
      $d['Participant']['f_name'], 
      $d['Participant']['l_name'], 
      $d['Participant']['email'], 
      $d['Participant']['mobile_phone'], 
      $d['Participant']['special'], 
      $d['Participant']['school'], 
      $d['Participant']['seminarium_id'], 
      $d['Participant']['outside_sthlm'], 
      $d['Participant']['share_room'], 
      $d['Participant']['transfer'], 
      $d['Participant']['only_day'], 
      $d['Participant']['song'], 
      $d['Participant']['teacher'], 
      $d['Participant']['comments'] 
     )); 
    } 

    $this->PhpExcel->addTableFooter(); 
    $this->PhpExcel->output(); 
    $this->PhpExcel->exit(); 
?> 

當我嘗試在Firefox中下載此我得到正確的文件擴展名,XLSX,但試圖與SAFA下載時它給我report.xlsx.html?和文件變得沒用,除非你把它重命名爲report.xlsx,怎麼回事?

回答

2

首先,你應該將'layout'設置爲'false',以防止視圖被加載到你的網站的默認(HTML)佈局中。

還設置響應型爲Excel的類型(如其他人所說的,你可以通過響應對象這樣做(http://book.cakephp.org/2.0/en/controllers/request-response.html#dealing-with-content-types

最後,在你的助手不exit();。如果你」再沒有渲染視圖中的佈局,你沒有把結果輸出

在控制器後退出;

public $helpers = array('PhpExcel'); 
... 
public function excel() { 
    // disable the layout 
    $this->layout = false; 

    // Add/define XLS contenttype 
    $this->response->type(array('xls' => 'application/vnd.ms-excel')); 

    // Set the response Content-Type to xls 
    $this->response->type('xls'); 

    $this->set('participants', $this->Participant->find('all')); 
} 

正如Mark Ba​​ker所提到的,XLS和XLSX使用不同的MIME類型,我的示例使用MIME類型作爲'classic'XLS,如果要輸出XLSX,請相應地修改MIME類型

+0

感謝您爲我的問題提供了一個很好的解釋和解決方案! – Philip 2013-03-02 14:36:03

+0

很高興我可以幫助,並感謝@MarkBaker和Salgua尋找正確的Mime類型,他們很難記住:) – thaJeztah 2013-03-02 15:31:18

0

您可以嘗試

header('Content-type: application/ms-excel'); 
+0

正確的MIME類型是application/vnd.ms-excel for .xls文件或application/vnd.openxmlformats-officedocument.spreadsheetml.sheet for .xlsx文件 – 2013-03-01 14:18:30

1

一個可能的解決方案,我就發現another site說來

$this->render(false); 

添加到您的控制器,以防止從CakePHP的發送自己的頭/響應,可能會覆蓋你自己的