box / spout - 冻结电子表格的第一行(窗格)

时间:2017-06-01 15:24:53

标签: php excel spreadsheet

是否可以使用box / spout冻结电子表格的第一行(冻结窗格)?

使用PHPexcel我喜欢这样:

$objPHPExcel=new PHPExcel();
$ActiveSheet=$objPHPExcel->getActiveSheet();
$ActiveSheet->freezePane('A2');

无法使用PHPexcel,因为我正在使用大文件。

3 个答案:

答案 0 :(得分:0)

用Spout冻结窗格是不可能的。但你总是可以分叉回购并实现这个功能:)

答案 1 :(得分:0)

<?php 
/**
 * 
 * Inspired by: https://github.com/box/spout/issues/368
 *
 * Simple helper class for Spout - to return rows indexed by the header in the sheet
 *
 * Author: Jaspal Singh - https://github.com/jaspal747
 * Feel free to make any edits as needed. Cheers!
 *
 */
class SpoutHelper {

    private $rawHeadersArray = []; //Local array to hold the Raw Headers for performance
    private $formattedHeadersArray = []; //Local array to hold the Formatted Headers for performance
    private $headerRowNumber; //Row number where the header col is located in the file
    /**
     * Initialize on a per sheet basis
     *  Allow users to mention which row number contains the headers
     */
    public function __construct($sheet, $headerRowNumber = 1) {
        $this->flushHeaders();
        $this->headerRowNumber = $headerRowNumber;
        $this->getFormattedHeaders($sheet);//Since this also calls the getRawHeaders, we will have both the arrays set at once
    }
    /**
     * 
     * Set the rawHeadersArray by getting the raw headers from the headerRowNumber or the 1st row 
     *  Once done, set them to a local variable for being reused later
     *
     */
    public function getRawHeaders($sheet) {
        if (empty($this->rawHeadersArray)) {
            /**
             * first get column headers
             */
            foreach ($sheet->getRowIterator() as $key => $row) {
                if ($key == $this->headerRowNumber) {
                    /**
                     * iterate once to get the column headers
                     */
                    $this->rawHeadersArray = $row->toArray();
                    break;
                }
            }


        } else {
            /**
             * From local cache
             */
        }

        return $this->rawHeadersArray;
    }
    /**
     * 
     * Set the formattedHeadersArray by getting the raw headers and the parsing them
     *  Once done, set them to a local variable for being reused later
     *
     */
    public function getFormattedHeaders($sheet) {
        if (empty($this->formattedHeadersArray)) {
            $this->formattedHeadersArray = $this->getRawHeaders($sheet);
            /**
             * Now format them
             */
            foreach ($this->formattedHeadersArray as $key => $value) {
                if (is_a($value, 'DateTime')) { //Somehow instanceOf does not work well with DateTime, hence using is_a -- ?
                    $this->formattedHeadersArray[$key] = $value->format('Y-m-d');//Since the dates in headers are avilable as DateTime Objects
                } else {


                    $this->formattedHeadersArray[$key] = strtolower(str_replace(' ' , '_', trim($value)));
                }
                /**
                 * Add more rules here as needed
                 */
            }
        } else {
            /**
             * Return from local cache
             */
        }
        return $this->formattedHeadersArray;
    }
    /**
     * Return row with Raw Headers
     */
    public function rowWithRawHeaders($rowArray) {
        return $this->returnRowWithHeaderAsKeys($this->rawHeadersArray, $rowArray);
    }
    /**
     * Return row with Formatted Headers
     */
    public function rowWithFormattedHeaders($rowArray) {
        return $this->returnRowWithHeaderAsKeys($this->formattedHeadersArray, $rowArray);
    }
    /**
     * Set the headers to keys and row as values
     */
    private function returnRowWithHeaderAsKeys($headers, $rowArray) {

        $headerColCount = count($headers);
        $rowColCount = count($rowArray);
        $colCountDiff = $headerColCount - $rowColCount;
        if ($colCountDiff > 0) {
            //Pad the rowArray with empty values 
            $rowArray = array_pad($rowArray, $headerColCount, '');
        }
        return array_combine($headers, $rowArray);
    }
    /**
     * Flush local caches before each sheet
     */
    public function flushHeaders() {
        $this->formattedHeadersArray = [];
        $this->rawHeadersArray = [];
    }

}

然后在您的主文件中可以执行以下操作:

$reader = ReaderEntityFactory::createReaderFromFile($filePath);
$reader->open($filePath);

/**
 * Now get the data
 */
foreach ($reader->getSheetIterator() as $sheet) {

    $spoutHelper = new SpoutHelper($sheet, 1); //Initialize SpoutHelper with the current Sheet and the row number which contains the header

        foreach ($sheet->getRowIterator() as $key => $row) {

            if ($key == 1) {
                //echo "Skipping Headers row";
                continue;
            }

            //Get the indexed array with col name as key and col val as value`
            $rowWithHeaderKeys = $spoutHelper->rowWithFormattedHeaders($row->toArray());                   
      }
 }

来源:https://gist.github.com/jaspal747/2bd515f9e318b0331f3ca3d2297742c5

答案 2 :(得分:0)

发现了添加此功能的黑客。

在Spout \ Writer \ XLSX \ Manager \ WorksheetManager.php中:函数startSheet

此行之后

.encodeSerializable(Body.serializer(), body)

添加此行

fwrite($sheetFilePointer, self::SHEET_XML_FILE_HEADER);