ADDED : Implement support for AutoFilter in PHPExcel_Writer_Excel5

This commit is contained in:
Progi1984 2012-07-13 18:20:06 +02:00
parent 2cbc3d24ab
commit e1104f1862
6 changed files with 225 additions and 19 deletions

View File

@ -55,6 +55,13 @@ class PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer
*/ */
private $_spType; private $_spType;
/**
* Shape flag
*
* @var int
*/
private $_spFlag;
/** /**
* Shape index (usually group shape has index 0, and the rest: 1,2,3...) * Shape index (usually group shape has index 0, and the rest: 1,2,3...)
* *
@ -171,6 +178,26 @@ class PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer
return $this->_spType; return $this->_spType;
} }
/**
* Set the shape flag
*
* @param int $value
*/
public function setSpFlag($value)
{
$this->_spFlag = $value;
}
/**
* Get the shape flag
*
* @return int
*/
public function getSpFlag()
{
return $this->_spFlag;
}
/** /**
* Set the shape index * Set the shape index
* *

View File

@ -282,7 +282,7 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter
$escher = null; $escher = null;
// check if there are any shapes for this sheet // check if there are any shapes for this sheet
if (count($sheet->getDrawingCollection()) == 0) { if (count($sheet->getDrawingCollection()) == 0 && $sheet->getAutoFilter() == '') {
continue; continue;
} }
@ -322,6 +322,8 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter
// set the shape type // set the shape type
$spContainer->setSpType(0x004B); $spContainer->setSpType(0x004B);
// set the shape flag
$spContainer->setSpFlag(0x02);
// set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index) // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
$reducedSpId = $countShapes[$sheetIndex]; $reducedSpId = $countShapes[$sheetIndex];
@ -357,6 +359,64 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter
$spgrContainer->addChild($spContainer); $spgrContainer->addChild($spContainer);
} }
// AutoFilters
if($sheet->getAutoFilter() != ''){
$rangeBounds = PHPExcel_Cell::rangeBoundaries($sheet->getAutoFilter());
$iNumColStart = $rangeBounds[0][0];
$iNumColEnd = $rangeBounds[1][0];
$iInc = $iNumColStart;
while($iInc <= $iNumColEnd){
++$countShapes[$sheetIndex];
// create an Drawing Object for the dropdown
$oDrawing = new PHPExcel_Worksheet_BaseDrawing();
// get the coordinates of drawing
$cDrawing = PHPExcel_Cell::stringFromColumnIndex($iInc - 1) . $rangeBounds[0][1];
$oDrawing->setCoordinates($cDrawing);
$oDrawing->setWorksheet($sheet);
// add the shape
$spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer();
// set the shape type
$spContainer->setSpType(0x00C9);
// set the shape flag
$spContainer->setSpFlag(0x01);
// set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
$reducedSpId = $countShapes[$sheetIndex];
$spId = $reducedSpId
| ($sheet->getParent()->getIndex($sheet) + 1) << 10;
$spContainer->setSpId($spId);
// keep track of last reducedSpId
$lastReducedSpId = $reducedSpId;
// keep track of last spId
$lastSpId = $spId;
$spContainer->setOPT(0x007F, 0x01040104); // Protection -> fLockAgainstGrouping
$spContainer->setOPT(0x00BF, 0x00080008); // Text -> fFitTextToShape
$spContainer->setOPT(0x01BF, 0x00010000); // Fill Style -> fNoFillHitTest
$spContainer->setOPT(0x01FF, 0x00080000); // Line Style -> fNoLineDrawDash
$spContainer->setOPT(0x03BF, 0x000A0000); // Group Shape -> fPrint
// set coordinates and offsets, client anchor
$endCoordinates = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::stringFromColumnIndex($iInc - 1));
$endCoordinates .= $rangeBounds[0][1] + 1;
$spContainer->setStartCoordinates($cDrawing);
$spContainer->setStartOffsetX(0);
$spContainer->setStartOffsetY(0);
$spContainer->setEndCoordinates($endCoordinates);
$spContainer->setEndOffsetX(0);
$spContainer->setEndOffsetY(0);
$spgrContainer->addChild($spContainer);
$iInc++;
}
}
// identifier clusters, used for workbook Escher object // identifier clusters, used for workbook Escher object
$this->_IDCLs[$dgId] = $lastReducedSpId; $this->_IDCLs[$dgId] = $lastReducedSpId;

View File

@ -52,6 +52,12 @@ class PHPExcel_Writer_Excel5_Escher
*/ */
private $_spOffsets; private $_spOffsets;
/**
* Shape types.
*
* @var array
*/
private $_spTypes;
/** /**
* Constructor * Constructor
@ -81,6 +87,7 @@ class PHPExcel_Writer_Excel5_Escher
$writer = new PHPExcel_Writer_Excel5_Escher($dgContainer); $writer = new PHPExcel_Writer_Excel5_Escher($dgContainer);
$this->_data = $writer->close(); $this->_data = $writer->close();
$this->_spOffsets = $writer->getSpOffsets(); $this->_spOffsets = $writer->getSpOffsets();
$this->_spTypes = $writer->getSpTypes();
} }
break; break;
@ -307,6 +314,7 @@ class PHPExcel_Writer_Excel5_Escher
// get the shape offsets relative to the spgrContainer record // get the shape offsets relative to the spgrContainer record
$spOffsets = $writer->getSpOffsets(); $spOffsets = $writer->getSpOffsets();
$spTypes = $writer->getSpTypes();
// save the shape offsets relative to dgContainer // save the shape offsets relative to dgContainer
foreach ($spOffsets as & $spOffset) { foreach ($spOffsets as & $spOffset) {
@ -314,6 +322,7 @@ class PHPExcel_Writer_Excel5_Escher
} }
$this->_spOffsets = $spOffsets; $this->_spOffsets = $spOffsets;
$this->_spTypes = $spTypes;
} }
// write the record // write the record
@ -339,6 +348,7 @@ class PHPExcel_Writer_Excel5_Escher
// initialize spape offsets // initialize spape offsets
$totalSize = 8; $totalSize = 8;
$spOffsets = array(); $spOffsets = array();
$spTypes = array();
// treat the inner data // treat the inner data
foreach ($this->_object->getChildren() as $spContainer) { foreach ($this->_object->getChildren() as $spContainer) {
@ -349,6 +359,8 @@ class PHPExcel_Writer_Excel5_Escher
// save the shape offsets (where new shape records begin) // save the shape offsets (where new shape records begin)
$totalSize += strlen($spData); $totalSize += strlen($spData);
$spOffsets[] = $totalSize; $spOffsets[] = $totalSize;
$spTypes = array_merge($spTypes, $writer->getSpTypes());
} }
// write the record // write the record
@ -364,6 +376,7 @@ class PHPExcel_Writer_Excel5_Escher
$this->_data = $header . $innerData; $this->_data = $header . $innerData;
$this->_spOffsets = $spOffsets; $this->_spOffsets = $spOffsets;
$this->_spTypes = $spTypes;
break; break;
case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer': case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer':
@ -386,6 +399,7 @@ class PHPExcel_Writer_Excel5_Escher
$data .= $header . pack('VVVV', 0,0,0,0); $data .= $header . pack('VVVV', 0,0,0,0);
} }
$this->_spTypes[] = ($this->_object->getSpType());
// write the shape record // write the shape record
$recVer = 0x2; $recVer = 0x2;
@ -450,7 +464,7 @@ class PHPExcel_Writer_Excel5_Escher
// end offsetY // end offsetY
$endOffsetY = $this->_object->getEndOffsetY(); $endOffsetY = $this->_object->getEndOffsetY();
$clientAnchorData = pack('vvvvvvvvv', 0x02, $clientAnchorData = pack('vvvvvvvvv', $this->_object->getSpFlag(),
$c1, $startOffsetX, $r1, $startOffsetY, $c1, $startOffsetX, $r1, $startOffsetY,
$c2, $endOffsetX, $r2, $endOffsetY); $c2, $endOffsetX, $r2, $endOffsetY);
@ -509,4 +523,15 @@ class PHPExcel_Writer_Excel5_Escher
return $this->_spOffsets; return $this->_spOffsets;
} }
/**
* Gets the shape types
*
* @return array
*/
public function getSpTypes()
{
return $this->_spTypes;
}
} }

View File

@ -780,6 +780,19 @@ 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 != ''){
$rangeBounds = PHPExcel_Cell::rangeBoundaries($sheetAutoFilter);
//Autofilter built in name
$name = pack('C', 0x0D);
$chunk .= $this->writeData($this->_writeShortNameBiff8($name, $i + 1, $rangeBounds, true));
}
}
return $chunk; return $chunk;
} }
@ -818,6 +831,42 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter
return $header . $data; return $header . $data;
} }
/**
* Write a short NAME record
*
* @param string $name
* @param string $sheetIndex 1-based sheet index the defined name applies to. 0 = global
* @param int[][] $range rangeboundaries
* @param bool $isHidden
* @return string Complete binary record data
* */
private function _writeShortNameBiff8($name, $sheetIndex = 0, $rangeBounds, $isHidden = false){
$record = 0x0018;
// option flags
$options = ($isHidden ? 0x21 : 0x00);
$extra = pack('Cvvvvv',
0x3B,
$sheetIndex - 1,
$rangeBounds[0][1] - 1,
$rangeBounds[1][1] - 1,
$rangeBounds[0][0] - 1,
$rangeBounds[1][0] - 1);
// size of the formula (in bytes)
$sz = strlen($extra);
// combine the parts
$data = pack('vCCvvvCCCCC', $options, 0, 1, $sz, 0, $sheetIndex, 0, 0, 0, 0, 0)
. $name . $extra;
$length = strlen($data);
$header = pack('vv', $record, $length);
return $header . $data;
}
/** /**
* Stores the CODEPAGE biff record. * Stores the CODEPAGE biff record.
*/ */

View File

@ -391,6 +391,11 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter
} }
} }
if ($_phpSheet->getAutoFilter() != '') {
// Write AUTOFILTERINFO
$this->_writeAutoFilterInfo();
}
// Write sheet dimensions // Write sheet dimensions
$this->_writeDimensions(); $this->_writeDimensions();
@ -2017,7 +2022,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter
$fPrintGrid = $this->_phpSheet->getPrintGridlines() ? 1 : 0; // Boolean flag $fPrintGrid = $this->_phpSheet->getPrintGridlines() ? 1 : 0; // Boolean flag
$header = pack("vv", $record, $length); $header = pack("vv", $record, $length);
$data = pack("v", $fPrintGrid); $data = pack("v", $fPrintGrid);
$this->_append($header . $data); $this->_append($header . $data);
} }
@ -2037,6 +2042,21 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter
$this->_append($header . $data); $this->_append($header . $data);
} }
/**
* Write the AUTOFILTERINFO BIFF record. This is used to configure the number of autofilter select used in the sheet.
*/
private function _writeAutoFilterInfo(){
$record = 0x009D; // Record identifier
$length = 0x0002; // Bytes to follow
$rangeBounds = PHPExcel_Cell::rangeBoundaries($this->_phpSheet->getAutoFilter());
$iNumFilters = 1 + $rangeBounds[1][0] - $rangeBounds[0][0];
$header = pack("vv", $record, $length);
$data = pack("v", $iNumFilters);
$this->_append($header . $data);
}
/** /**
* Write the GUTS BIFF record. This is used to configure the gutter margins * Write the GUTS BIFF record. This is used to configure the gutter margins
* where Excel outline symbols are displayed. The visibility of the gutters is * where Excel outline symbols are displayed. The visibility of the gutters is
@ -2681,7 +2701,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter
$writer = new PHPExcel_Writer_Excel5_Escher($this->_escher); $writer = new PHPExcel_Writer_Excel5_Escher($this->_escher);
$data = $writer->close(); $data = $writer->close();
$spOffsets = $writer->getSpOffsets(); $spOffsets = $writer->getSpOffsets();
$spTypes = $writer->getSpTypes();
// write the neccesary MSODRAWING, OBJ records // write the neccesary MSODRAWING, OBJ records
// split the Escher stream // split the Escher stream
@ -2692,7 +2712,6 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter
$record = 0x00EC; // Record identifier $record = 0x00EC; // Record identifier
// chunk of Escher stream for one shape // chunk of Escher stream for one shape
$dataChunk = substr($data, $spOffsets[$i -1], $spOffsets[$i] - $spOffsets[$i - 1]); $dataChunk = substr($data, $spOffsets[$i -1], $spOffsets[$i] - $spOffsets[$i - 1]);
$length = strlen($dataChunk); $length = strlen($dataChunk);
@ -2705,17 +2724,42 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter
$objData = ''; $objData = '';
// ftCmo // ftCmo
$objData .= if($spTypes[$i] == 0x00C9){
pack('vvvvvVVV' // Add ftCmo (common object data) subobject
, 0x0015 // 0x0015 = ftCmo $objData .=
, 0x0012 // length of ftCmo data pack('vvvvvVVV'
, 0x0008 // object type, 0x0008 = picture , 0x0015 // 0x0015 = ftCmo
, $i // object id number, Excel seems to use 1-based index, local for the sheet , 0x0012 // length of ftCmo data
, 0x6011 // option flags, 0x6011 is what OpenOffice.org uses , 0x0014 // object type, 0x0014 = filter
, 0 // reserved , $i // object id number, Excel seems to use 1-based index, local for the sheet
, 0 // reserved , 0x2101 // option flags, 0x2001 is what OpenOffice.org uses
, 0 // reserved , 0 // reserved
); , 0 // reserved
, 0 // reserved
);
// Add ftSbs Scroll bar subobject
$objData .= pack('vv', 0x00C, 0x0014);
$objData .= pack('H*', '0000000000000000640001000A00000010000100');
// Add ftLbsData (List box data) subobject
$objData .= pack('vv', 0x0013, 0x1FEE);
$objData .= pack('H*', '00000000010001030000020008005700');
}
else {
// Add ftCmo (common object data) subobject
$objData .=
pack('vvvvvVVV'
, 0x0015 // 0x0015 = ftCmo
, 0x0012 // length of ftCmo data
, 0x0008 // object type, 0x0008 = picture
, $i // object id number, Excel seems to use 1-based index, local for the sheet
, 0x6011 // option flags, 0x6011 is what OpenOffice.org uses
, 0 // reserved
, 0 // reserved
, 0 // reserved
);
}
// ftEnd // ftEnd
$objData .= $objData .=
pack('vv' pack('vv'

View File

@ -29,6 +29,7 @@ Fixed in develop branch:
Current options are tcPDF, mPDF, DomPDF Current options are tcPDF, mPDF, DomPDF
tcPDF Library has now been removed from the deployment bundle tcPDF Library has now been removed from the deployment bundle
- Feature: (MBaker) Initial version of HTML Reader - Feature: (MBaker) Initial version of HTML Reader
- Feature: (Progi1984) & (blazzy) Work items 9605 - Implement support for AutoFilter in PHPExcel_Writer_Excel5
- Bugfix: (cyberconte) Patch 12318 - OOCalc cells containing <text:span> inside the <text:p> tag - Bugfix: (cyberconte) Patch 12318 - OOCalc cells containing <text:span> inside the <text:p> tag
- Bugfix: (schir1964) Fix to listWorksheetInfo() method for OOCalc Reader - Bugfix: (schir1964) Fix to listWorksheetInfo() method for OOCalc Reader
- Bugfix: (MBaker) Support for "e" (epoch) date format mask - Bugfix: (MBaker) Support for "e" (epoch) date format mask