diff --git a/Classes/PHPExcel/Reader/Excel2007.php b/Classes/PHPExcel/Reader/Excel2007.php index 94655a0e..fc055992 100644 --- a/Classes/PHPExcel/Reader/Excel2007.php +++ b/Classes/PHPExcel/Reader/Excel2007.php @@ -1193,7 +1193,6 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } } - 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 cb7a1680..f5a48cd9 100644 --- a/Classes/PHPExcel/Worksheet/AutoFilter.php +++ b/Classes/PHPExcel/Worksheet/AutoFilter.php @@ -239,6 +239,264 @@ class PHPExcel_Worksheet_AutoFilter return $this; } + private static function _filterTestInSimpleDataSet($cellValue,$dataSet) + { + $dataSetValues = $dataSet['filterValues']; + $blanks = $dataSet['blanks']; + if (($cellValue == '') || ($cellValue === NULL)) { + return $blanks; + } + return in_array($cellValue,$dataSetValues); + } + + private static function _filterTestInDateGroupSet($cellValue,$dataSet) + { + $dateSet = $dataSet['filterValues']; + $blanks = $dataSet['blanks']; + if (($cellValue == '') || ($cellValue === NULL)) { + return $blanks; + } + if (is_numeric($cellValue)) { + $dateValue = PHPExcel_Shared_Date::ExcelToPHP($cellValue); + if ($cellValue < 1) { + // Just the time part + $dtVal = date('His',$dateValue); + $dateSet = $dateSet['time']; + } elseif($cellValue == floor($cellValue)) { + // Just the date part + $dtVal = date('Ymd',$dateValue); + $dateSet = $dateSet['date']; + } else { + // date and time parts + $dtVal = date('YmdHis',$dateValue); + $dateSet = $dateSet['dateTime']; + } + foreach($dateSet as $dateValue) { + // Use of substr to extract value at the appropriate group level + if (substr($dtVal,0,strlen($dateValue)) == $dateValue) + return TRUE; + } + } + + return FALSE; + } + + private static function _filterTypeCustomFilters($cellValue,$ruleSet) + { + $dataSet = $ruleSet['filterRules']; + $join = $ruleSet['join']; + + $returnVal = ($join == PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_ANDOR_AND); + foreach($dataSet as $rule) { + if (is_numeric($rule['value'])) { + // Numeric values are tested using the appropriate operator + switch ($rule['operator']) { + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL : + $retVal = ($cellValue == $rule['value']); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL : + $retVal = ($cellValue != $rule['value']); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN : + $retVal = ($cellValue > $rule['value']); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL : + $retVal = ($cellValue >= $rule['value']); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN : + $retVal = ($cellValue < $rule['value']); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL : + $retVal = ($cellValue <= $rule['value']); + break; + } + } else { + // String values are always tested for equality + $retVal = preg_match('/^'.$rule['value'].'$/',$cellValue); + } + // If there are multiple conditions, then we need to test both using the appropriate join operator + switch ($join) { + case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_ANDOR_OR : + $returnVal = $returnVal || $retVal; + // Break as soon as we have a match for OR joins + if ($returnVal) + return $returnVal; + break; + case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_ANDOR_AND : + $returnVal = $returnVal && $retVal; + break; + } + } + + return $returnVal; + } + + private static function _filterTypeDynamicFilters($cellValue,$testSet) + { + return TRUE; + } + + private static function _filterTypeTopTenFilters($cellValue,$testSet) + { + return TRUE; + } + + private static $_fromReplace = array('\*', '\?', '~~', '~.*', '~.?'); + private static $_toReplace = array('.*', '.', '~', '\*', '\?'); + + /** + * Apply the AutoFilter rules to the AutoFilter Range + * + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter + */ + public function showHideRows() + { + list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->_range); + + // The heading row should always be visible + echo 'AutoFilter Heading Row ',$rangeStart[1],' is always SHOWN',PHP_EOL; + $this->_workSheet->getRowDimension($rangeStart[1])->setVisible(TRUE); + + $columnFilterTests = array(); + foreach($this->_columns as $columnID => $filterColumn) { + $rules = $filterColumn->getRules(); + switch ($filterColumn->getFilterType()) { + case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_FILTER : + $ruleValues = array(); + // Build a list of the filter value selections + foreach($rules as $rule) { + $ruleType = $rule->getRuleType(); + $ruleValues[] = $rule->getValue(); + } + // Test if we want to include blanks in our filter criteria + $blanks = FALSE; + $ruleDataSet = array_filter($ruleValues); + if (count($ruleValues) != count($ruleDataSet)) + $blanks = TRUE; + if ($ruleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_FILTER) { + // Filter on absolute values + $columnFilterTests[$columnID] = array( + 'method' => '_filterTestInSimpleDataSet', + 'arguments' => array( 'filterValues' => $ruleDataSet, + 'blanks' => $blanks + ) + ); + } else { + // Filter on date group values + $arguments = array(); + foreach($ruleDataSet as $ruleValue) { + $date = $time = ''; + if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR])) && + ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR] !== '')) + $date .= sprintf('%04d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR]); + if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH])) && + ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH] != '')) + $date .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH]); + if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY])) && + ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY] !== '')) + $date .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY]); + if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR])) && + ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR] !== '')) + $time .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR]); + if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE])) && + ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE] !== '')) + $time .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE]); + if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND])) && + ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND] !== '')) + $time .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND]); + $dateTime = $date . $time; + $arguments['date'][] = $date; + $arguments['time'][] = $time; + $arguments['dateTime'][] = $dateTime; + } + // Remove empty elements + $arguments['date'] = array_filter($arguments['date']); + $arguments['time'] = array_filter($arguments['time']); + $arguments['dateTime'] = array_filter($arguments['dateTime']); + $columnFilterTests[$columnID] = array( + 'method' => '_filterTestInDateGroupSet', + 'arguments' => array( 'filterValues' => $arguments, + 'blanks' => $blanks + ) + ); + } + break; + case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER : + $ruleValues = array(); + // Build a list of the filter value selections + foreach($rules as $rule) { + $ruleType = $rule->getRuleType(); + $ruleValue = $rule->getValue(); + if (!is_numeric($ruleValue)) { + // Convert to a regexp allowing for regexp reserved characters, wildcards and escaped wildcards +var_dump($ruleValue); +echo ' = > '; + $ruleValue = preg_quote($ruleValue); +var_dump($ruleValue); +echo ' = > '; + $ruleValue = str_replace(self::$_fromReplace,self::$_toReplace,$ruleValue); +var_dump($ruleValue); + } + $ruleValues[] = array( 'operator' => $rule->getOperator(), + 'value' => $ruleValue + ); + } + $join = $filterColumn->getAndOr(); + $columnFilterTests[$columnID] = array( + 'method' => '_filterTypeCustomFilters', + 'arguments' => array( 'filterRules' => $ruleValues, + 'join' => $join + ) + ); + break; + case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER : + $columnFilterTests[$columnID] = array( + 'method' => '_filterTypeDynamicFilters', + 'arguments' => $ruleValues + ); + break; + case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER : + $columnFilterTests[$columnID] = array( + 'method' => '_filterTypeTopTenFilters', + 'arguments' => $ruleValues + ); + break; + } + } + + echo 'Column Filter Test CRITERIA',PHP_EOL; + var_dump($columnFilterTests); + + for ($row = $rangeStart[1]+1; $row <= $rangeEnd[1]; ++$row) { + echo 'Testing Row = ',$row,PHP_EOL; + $result = TRUE; + foreach($columnFilterTests as $columnID => $columnFilterTest) { + echo 'Testing cell ',$columnID.$row,PHP_EOL; + $cellValue = $this->_workSheet->getCell($columnID.$row)->getCalculatedValue(); + echo 'Value is ',$cellValue,PHP_EOL; + // Execute the filter test + $result = $result && + call_user_func_array( + array('PHPExcel_Worksheet_AutoFilter',$columnFilterTest['method']), + array( + $cellValue, + $columnFilterTest['arguments'] + ) + ); + echo (($result) ? 'VALID' : 'INVALID'),PHP_EOL; + // If filter test has resulted in FALSE, exit straightaway rather than running any more tests + if (!$result) + break; + } + echo (($result) ? 'SHOW' : 'HIDE'),PHP_EOL; + $this->_workSheet->getRowDimension($row)->setVisible($result); + } + + return $this; + } + + /** * Implement PHP __clone to create a deep clone, not just a shallow copy. */ diff --git a/Classes/PHPExcel/Worksheet/AutoFilter/Column.php b/Classes/PHPExcel/Worksheet/AutoFilter/Column.php index c4b003b2..faf823ce 100644 --- a/Classes/PHPExcel/Worksheet/AutoFilter/Column.php +++ b/Classes/PHPExcel/Worksheet/AutoFilter/Column.php @@ -49,7 +49,6 @@ class PHPExcel_Worksheet_AutoFilter_Column // colorFilter // extLst // iconFilter - // topTen self::AUTOFILTER_FILTERTYPE_FILTER, self::AUTOFILTER_FILTERTYPE_CUSTOMFILTER, self::AUTOFILTER_FILTERTYPE_DYNAMICFILTER, @@ -60,7 +59,7 @@ class PHPExcel_Worksheet_AutoFilter_Column const AUTOFILTER_COLUMN_ANDOR_AND = 'and'; const AUTOFILTER_COLUMN_ANDOR_OR = 'or'; - private static $_ruleConnections = array( + private static $_ruleJoin = array( self::AUTOFILTER_COLUMN_ANDOR_AND, self::AUTOFILTER_COLUMN_ANDOR_OR, ); @@ -208,7 +207,7 @@ class PHPExcel_Worksheet_AutoFilter_Column public function setAndOr($pAndOr = self::AUTOFILTER_COLUMN_ANDOR_OR) { // Lowercase And/Or $pAndOr = strtolower($pAndOr); - if (!in_array($pAndOr,self::$_ruleConnections)) { + if (!in_array($pAndOr,self::$_ruleJoin)) { throw new PHPExcel_Exception('Invalid rule connection for column AutoFilter.'); } diff --git a/Classes/PHPExcel/Writer/Excel2007/Workbook.php b/Classes/PHPExcel/Writer/Excel2007/Workbook.php index 59622fde..eefe7f10 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Workbook.php +++ b/Classes/PHPExcel/Writer/Excel2007/Workbook.php @@ -347,14 +347,15 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write private function _writeDefinedNameForAutofilter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0) { // definedName for autoFilter - if ($pSheet->getAutoFilter()->getRange() !== '') { + $autoFilterRange = $pSheet->getAutoFilter()->getRange(); + if (!empty($autoFilterRange)) { $objWriter->startElement('definedName'); $objWriter->writeAttribute('name', '_xlnm._FilterDatabase'); $objWriter->writeAttribute('localSheetId', $pSheetId); $objWriter->writeAttribute('hidden', '1'); // Create absolute coordinate and write as raw text - $range = PHPExcel_Cell::splitRange($pSheet->getAutoFilter()->getRange()); + $range = PHPExcel_Cell::splitRange($autoFilterRange); $range = $range[0]; // Strip any worksheet ref so we can make the cell ref absolute if (strpos($range[0],'!') !== false) { diff --git a/Classes/PHPExcel/Writer/Excel2007/Worksheet.php b/Classes/PHPExcel/Writer/Excel2007/Worksheet.php index 80934372..770bff1b 100644 --- a/Classes/PHPExcel/Writer/Excel2007/Worksheet.php +++ b/Classes/PHPExcel/Writer/Excel2007/Worksheet.php @@ -148,9 +148,10 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ // sheetPr $objWriter->startElement('sheetPr'); //$objWriter->writeAttribute('codeName', $pSheet->getTitle()); - - if ($pSheet->getAutoFilter()->getRange() !== '') { + $autoFilterRange = $pSheet->getAutoFilter()->getRange(); + if (!empty($autoFilterRange)) { $objWriter->writeAttribute('filterMode', 1); +// $pSheet->getAutoFilter()->showHideRows(); } // tabColor @@ -734,12 +735,13 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ */ private function _writeAutoFilter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { - if ($pSheet->getAutoFilter()->getRange() !== '') { + $autoFilterRange = $pSheet->getAutoFilter()->getRange(); + if (!empty($autoFilterRange)) { // autoFilter $objWriter->startElement('autoFilter'); // Strip any worksheet reference from the filter coordinates - $range = PHPExcel_Cell::splitRange($pSheet->getAutoFilter()->getRange()); + $range = PHPExcel_Cell::splitRange($autoFilterRange); $range = $range[0]; // Strip any worksheet ref if (strpos($range[0],'!') !== false) { diff --git a/Classes/PHPExcel/Writer/Excel5.php b/Classes/PHPExcel/Writer/Excel5.php index 6eb69943..c2f78cc6 100644 --- a/Classes/PHPExcel/Writer/Excel5.php +++ b/Classes/PHPExcel/Writer/Excel5.php @@ -274,6 +274,8 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter { // 1-based index to BstoreContainer $blipIndex = 0; + $lastReducedSpId = 0; + $lastSpId = 0; foreach ($this->_phpExcel->getAllsheets() as $sheet) { // sheet index @@ -282,7 +284,8 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter $escher = null; // check if there are any shapes for this sheet - if (count($sheet->getDrawingCollection()) == 0 && $sheet->getAutoFilter()->getRange() === '') { + $filterRange = $sheet->getAutoFilter()->getRange(); + if (count($sheet->getDrawingCollection()) == 0 && empty($filterRange)) { continue; } @@ -360,8 +363,8 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter } // AutoFilters - if($sheet->getAutoFilter()->getRange() !== ''){ - $rangeBounds = PHPExcel_Cell::rangeBoundaries($sheet->getAutoFilter()->getRange()); + if(!empty($filterRange)){ + $rangeBounds = PHPExcel_Cell::rangeBoundaries($filterRange); $iNumColStart = $rangeBounds[0][0]; $iNumColEnd = $rangeBounds[1][0]; diff --git a/Classes/PHPExcel/Writer/Excel5/Workbook.php b/Classes/PHPExcel/Writer/Excel5/Workbook.php index 4fdcada2..fb0a67c4 100644 --- a/Classes/PHPExcel/Writer/Excel5/Workbook.php +++ b/Classes/PHPExcel/Writer/Excel5/Workbook.php @@ -783,8 +783,9 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter // write autofilters, if any for ($i = 0; $i < $total_worksheets; ++$i) { $sheetAutoFilter = $this->_phpExcel->getSheet($i)->getAutoFilter(); - if($sheetAutoFilter->getRange() !== ''){ - $rangeBounds = PHPExcel_Cell::rangeBoundaries($sheetAutoFilter->getRange()); + $autoFilterRange = $sheetAutoFilter->getRange(); + if(!empty($autoFilterRange)) { + $rangeBounds = PHPExcel_Cell::rangeBoundaries($autoFilterRange); //Autofilter built in name $name = pack('C', 0x0D); diff --git a/Classes/PHPExcel/Writer/Excel5/Worksheet.php b/Classes/PHPExcel/Writer/Excel5/Worksheet.php index b079da58..d6d6c214 100644 --- a/Classes/PHPExcel/Writer/Excel5/Worksheet.php +++ b/Classes/PHPExcel/Writer/Excel5/Worksheet.php @@ -390,8 +390,8 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $this->_writeColinfo($this->_colinfo[$i]); } } - - if ($_phpSheet->getAutoFilter()->getRange() !== '') { + $autoFilterRange = $_phpSheet->getAutoFilter()->getRange(); + if (!empty($autoFilterRange)) { // Write AUTOFILTERINFO $this->_writeAutoFilterInfo(); } diff --git a/Classes/PHPExcel/Writer/HTML.php b/Classes/PHPExcel/Writer/HTML.php index 5ce2b8c4..68c25f98 100644 --- a/Classes/PHPExcel/Writer/HTML.php +++ b/Classes/PHPExcel/Writer/HTML.php @@ -782,7 +782,8 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $css['vertical-align'] = $this->_mapVAlign($pStyle->getVertical()); if ($textAlign = $this->_mapHAlign($pStyle->getHorizontal())) { $css['text-align'] = $textAlign; - if(in_array($textAlign,array('left','right'))) $css['padding-'.$textAlign] = (string)((int)$pStyle->getIndent() * 9).'px'; + if(in_array($textAlign,array('left','right'))) + $css['padding-'.$textAlign] = (string)((int)$pStyle->getIndent() * 9).'px'; } // Return diff --git a/Documentation/PHPExcel developer documentation.doc b/Documentation/PHPExcel developer documentation.doc index c89a6aa2..31ff50a7 100644 Binary files a/Documentation/PHPExcel developer documentation.doc and b/Documentation/PHPExcel developer documentation.doc differ