From 303a6443ed7963ed5e75f72c35d8fc52391e35bd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 9 Aug 2012 21:26:33 +0100 Subject: [PATCH] Initial Writer code for autofilter selections --- Classes/PHPExcel/Reader/Excel2007.php | 21 ++++- Classes/PHPExcel/Worksheet/AutoFilter.php | 2 +- .../PHPExcel/Worksheet/AutoFilter/Column.php | 91 ++++++++++--------- .../PHPExcel/Writer/Excel2007/Worksheet.php | 33 +++++++ 4 files changed, 101 insertions(+), 46 deletions(-) diff --git a/Classes/PHPExcel/Reader/Excel2007.php b/Classes/PHPExcel/Reader/Excel2007.php index 2e49ef5..137df9b 100644 --- a/Classes/PHPExcel/Reader/Excel2007.php +++ b/Classes/PHPExcel/Reader/Excel2007.php @@ -1107,8 +1107,9 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader foreach ($xmlSheet->autoFilter->filterColumn as $filterColumn) { $column = $autoFilter->getColumnByOffset((integer) $filterColumn["colId"]); if ($filterColumn->filters) { + $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_FILTER); $filters = $filterColumn->filters; - // Standard filters are always an OR join + // Standard filters are always an OR join, so no join rule needed foreach ($filters->filter as $filterRule) { $column->createRule()->setRule( (string) $filterRule["operator"], @@ -1116,20 +1117,32 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader ); } } + if ($filterColumn->dynamicFilter) { + $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER); + // We should only ever have one dynamic filter + foreach ($filterColumn->dynamicFilter as $filterRule) { + $column->createRule()->setRule( + (string) $filterRule["operator"], + (string) $filterRule["val"] + ); + } + } if ($filterColumn->customFilters) { + $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER); $customFilters = $filterColumn->customFilters; // Custom filters can an AND or an OR join if ((isset($customFilters["and"])) && ($customFilters["and"] == 1)) { $column->setAndOr(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_ANDOR_AND); } - foreach ($customFilters->customFilter as $customFilterRule) { + foreach ($customFilters->customFilter as $filterRule) { $column->createRule()->setRule( - (string) $customFilterRule["operator"], - (string) $customFilterRule["val"] + (string) $filterRule["operator"], + (string) $filterRule["val"] ); } } } + var_dump($autoFilter); } if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->_readDataOnly) { diff --git a/Classes/PHPExcel/Worksheet/AutoFilter.php b/Classes/PHPExcel/Worksheet/AutoFilter.php index ada60bb..cb7a168 100644 --- a/Classes/PHPExcel/Worksheet/AutoFilter.php +++ b/Classes/PHPExcel/Worksheet/AutoFilter.php @@ -271,7 +271,7 @@ class PHPExcel_Worksheet_AutoFilter * referenced as a property of its parent. */ public function __toString() { - return $this->_range; + return (string) $this->_range; } } diff --git a/Classes/PHPExcel/Worksheet/AutoFilter/Column.php b/Classes/PHPExcel/Worksheet/AutoFilter/Column.php index 1cfd474..ceac93f 100644 --- a/Classes/PHPExcel/Worksheet/AutoFilter/Column.php +++ b/Classes/PHPExcel/Worksheet/AutoFilter/Column.php @@ -35,15 +35,23 @@ */ class PHPExcel_Worksheet_AutoFilter_Column { - /* Column Datatypes */ - const AUTOFILTER_COLUMN_DATATYPE_STRING = 's'; - const AUTOFILTER_COLUMN_DATATYPE_NUMBER = 'n'; - const AUTOFILTER_COLUMN_DATATYPE_DATE = 'd'; + const AUTOFILTER_FILTERTYPE_FILTER = 'filter'; + const AUTOFILTER_FILTERTYPE_CUSTOMFILTER = 'customFilter'; + // Supports no more than 2 rules, with an And/Or join criteria + // if more than 1 rule is defined + const AUTOFILTER_FILTERTYPE_DYNAMICFILTER = 'dynamicFilter'; + // Even though the filter rule is constant, the filtered data can vary + // e.g. filtered by date = TODAY - private static $_dataTypes = array( - self::AUTOFILTER_COLUMN_DATATYPE_STRING, - self::AUTOFILTER_COLUMN_DATATYPE_NUMBER, - self::AUTOFILTER_COLUMN_DATATYPE_DATE, + private static $_filterTypes = array( + // Currently we're not handling + // colorFilter + // extLst + // iconFilter + // topTen + self::AUTOFILTER_FILTERTYPE_FILTER, + self::AUTOFILTER_FILTERTYPE_CUSTOMFILTER, + self::AUTOFILTER_FILTERTYPE_DYNAMICFILTER, ); /* Multiple Rule Connections */ @@ -72,11 +80,11 @@ class PHPExcel_Worksheet_AutoFilter_Column /** - * Autofilter Column DataType + * Autofilter Column Filter Type * * @var string */ - private $_dataType = NULL; + private $_filterType = self::AUTOFILTER_FILTERTYPE_FILTER; /** @@ -153,6 +161,32 @@ class PHPExcel_Worksheet_AutoFilter_Column return $this; } + /** + * Get AutoFilter Type + * + * @return string + */ + public function getFilterType() { + return $this->_filterType; + } + + /** + * Set AutoFilter Type + * + * @param string $pfilterType + * @throws Exception + * @return PHPExcel_Worksheet_AutoFilter_Column + */ + public function setFilterType($pfilterType = self::AUTOFILTER_FILTERTYPE_FILTER) { + if (!in_array($pfilterType,self::$_filterTypes)) { + throw new PHPExcel_Exception('Invalid filter type for column AutoFilter.'); + } + + $this->_filterType = $pfilterType; + + return $this; + } + /** * Get AutoFilter Multiple Rules And/Or * @@ -181,37 +215,6 @@ class PHPExcel_Worksheet_AutoFilter_Column return $this; } - /** - * Get AutoFilter Column Data Type - * - * @return string - */ - public function getDataType() { - if ($this->_dataType === NULL) { - } - - return $this->_dataType; - } - - /** - * Set AutoFilter Column Data Type - * - * @param string $pDataType Data Type - * @throws Exception - * @return PHPExcel_Worksheet_AutoFilter_Column - */ - public function setDataType($pDataType = self::AUTOFILTER_COLUMN_DATATYPE_STRING) { - // Lowercase datatype - $pDataType = strtolower($pDataType); - if (!in_array($pDataType,self::$_dataTypes)) { - throw new PHPExcel_Exception('Invalid datatype for column AutoFilter.'); - } - - $this->_dataType = $pDataType; - - return $this; - } - /** * Get all AutoFilter Column Rules * @@ -262,6 +265,7 @@ class PHPExcel_Worksheet_AutoFilter_Column /** * Delete a specified AutoFilter Column Rule + * If the number of rules is reduced to 1, then we reset And/Or logic to Or * * @param integer $pIndex Rule index in the ruleset array * @return PHPExcel_Worksheet_AutoFilter_Column @@ -269,7 +273,12 @@ class PHPExcel_Worksheet_AutoFilter_Column public function deleteRule($pIndex) { if (isset($this->_ruleset[$pIndex])) { unset($this->_ruleset[$pIndex]); + // If we've just deleted down to a single rule, then reset And/Or joining to Or + if (count($this->_ruleset) <= 1) { + $this->setAndOr(self::AUTOFILTER_COLUMN_ANDOR_OR); + } } + return $this; } diff --git a/Classes/PHPExcel/Writer/Excel2007/Worksheet.php b/Classes/PHPExcel/Writer/Excel2007/Worksheet.php index 29d6f62..883f4e0 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Worksheet.php +++ b/Classes/PHPExcel/Writer/Excel2007/Worksheet.php @@ -744,6 +744,39 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $range = implode(':', $range); $objWriter->writeAttribute('ref', str_replace('$','',$range)); + + $columns = $pSheet->getAutoFilter()->getColumns(); + if (count($columns > 0)) { + foreach($columns as $columnID => $column) { + $rules = $column->getRules(); + if (count($rules > 0)) { + $objWriter->startElement('filterColumn'); + $objWriter->writeAttribute('colId', $pSheet->getAutoFilter()->getColumnOffset($columnID)); + + // We'll keep things simple and always group our filters, even if there's only one + $objWriter->startElement( $column->getFilterType() . 's'); + if ($column->getAndOr() == PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_ANDOR_AND) { + $objWriter->writeAttribute('and', 1); + } + + foreach ($rules as $rule) { + $objWriter->startElement($column->getFilterType()); + + if ($rule->getOperator() !== PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL) { + $objWriter->writeAttribute('operator', $rule->getOperator()); + } + $objWriter->writeAttribute('val', $rule->getValue()); + + $objWriter->endElement(); + } + + $objWriter->endElement(); + + $objWriter->endElement(); + } + } + } + $objWriter->endElement(); } }