From ef2de9cc5e80dd9943fd9408fbd4860bb02b3232 Mon Sep 17 00:00:00 2001 From: Mark Baker Date: Tue, 21 Aug 2012 22:32:16 +0100 Subject: [PATCH] Github Issue #32 - Insert column VS autofilter --- Classes/PHPExcel/ReferenceHelper.php | 57 ++++++++++++++++++++++- Classes/PHPExcel/Worksheet/AutoFilter.php | 45 +++++++++++++++++- 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/Classes/PHPExcel/ReferenceHelper.php b/Classes/PHPExcel/ReferenceHelper.php index c7b9e65..4110851 100644 --- a/Classes/PHPExcel/ReferenceHelper.php +++ b/Classes/PHPExcel/ReferenceHelper.php @@ -312,8 +312,61 @@ class PHPExcel_ReferenceHelper // Update worksheet: autofilter - if ($pSheet->getAutoFilter()->getRange() !== '') { - $pSheet->setAutoFilter( $this->updateCellReference($pSheet->getAutoFilter()->getRange(), $pBefore, $pNumCols, $pNumRows) ); + $autoFilter = $pSheet->getAutoFilter(); + $autoFilterRange = $autoFilter->getRange(); + if (!empty($autoFilterRange)) { + if ($pNumCols != 0) { + $autoFilterColumns = array_keys($autoFilter->getColumns()); + if (count($autoFilterColumns) > 0) { + list($column,$row) = sscanf($pBefore,'%[A-Z]%d'); + $columnIndex = PHPExcel_Cell::columnIndexFromString($column); + list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($autoFilterRange); + if ($columnIndex <= $rangeEnd[0]) { + if ($pNumCols < 0) { + // If we're actually deleting any columns that fall within the autofilter range, + // then we delete any rules for those columns + $deleteColumn = $columnIndex + $pNumCols - 1; + $deleteCount = abs($pNumCols); + for ($i = 1; $i <= $deleteCount; ++$i) { + if (in_array(PHPExcel_Cell::stringFromColumnIndex($deleteColumn),$autoFilterColumns)) { + $autoFilter->clearColumn(PHPExcel_Cell::stringFromColumnIndex($deleteColumn)); + } + ++$deleteColumn; + } + } + $startCol = ($columnIndex > $rangeStart[0]) ? $columnIndex : $rangeStart[0]; + + // Shuffle columns in autofilter range + if ($pNumCols > 0) { + // For insert, we shuffle from end to beginning to avoid overwriting + $startColID = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $toColID = PHPExcel_Cell::stringFromColumnIndex($startCol+$pNumCols-1); + $endColID = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]); + + $startColRef = $startCol; + $endColRef = $rangeEnd[0]; + $toColRef = $rangeEnd[0]+$pNumCols; + + do { + $autoFilter->shiftColumn(PHPExcel_Cell::stringFromColumnIndex($endColRef-1),PHPExcel_Cell::stringFromColumnIndex($toColRef-1)); + --$endColRef; + --$toColRef; + } while ($startColRef <= $endColRef); + } else { + // For delete, we shuffle from beginning to end to avoid overwriting + $startColID = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $toColID = PHPExcel_Cell::stringFromColumnIndex($startCol+$pNumCols-1); + $endColID = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]); + do { + $autoFilter->shiftColumn($startColID,$toColID); + ++$startColID; + ++$toColID; + } while ($startColID != $endColID); + } + } + } + } + $pSheet->setAutoFilter( $this->updateCellReference($autoFilterRange, $pBefore, $pNumCols, $pNumRows) ); } diff --git a/Classes/PHPExcel/Worksheet/AutoFilter.php b/Classes/PHPExcel/Worksheet/AutoFilter.php index 07e79b8..56c0ac7 100644 --- a/Classes/PHPExcel/Worksheet/AutoFilter.php +++ b/Classes/PHPExcel/Worksheet/AutoFilter.php @@ -150,7 +150,7 @@ class PHPExcel_Worksheet_AutoFilter /** * Validate that the specified column is in the AutoFilter range * - * @param string $column Column name (e.g. A) + * @param string $column Column name (e.g. A) * @throws PHPExcel_Exception * @return integer The column offset within the autofilter range */ @@ -239,6 +239,49 @@ class PHPExcel_Worksheet_AutoFilter return $this; } + /** + * Clear a specified AutoFilter Column + * + * @param string $pColumn Column name (e.g. A) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter + */ + public function clearColumn($pColumn) { + $this->testColumnInRange($pColumn); + + if (isset($this->_columns[$pColumn])) { + unset($this->_columns[$pColumn]); + } + + return $this; + } + + /** + * Shift an AutoFilter Column Rule to a different column + * + * Note: This method bypasses validation of the destination column to ensure it is within this AutoFilter range. + * Nor does it verify whether any column rule already exists at $toColumn, but will simply overrideany existing value. + * Use with caution. + * + * @param string $fromColumn Column name (e.g. A) + * @param string $toColumn Column name (e.g. B) + * @return PHPExcel_Worksheet_AutoFilter + */ + public function shiftColumn($fromColumn=NULL,$toColumn=NULL) { + $fromColumn = strtoupper($fromColumn); + $toColumn = strtoupper($toColumn); + + if (($fromColumn !== NULL) && (isset($this->_columns[$fromColumn])) && ($toColumn !== NULL)) { + $this->_columns[$fromColumn]->setParent(); + $this->_columns[$fromColumn]->setColumnIndex($toColumn); + $this->_columns[$toColumn] = $this->_columns[$fromColumn]; + $this->_columns[$toColumn]->setParent($this); + unset($this->_columns[$fromColumn]); + } + + return $this; + } + /** * Test if cell value is in the defined set of values