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;
/**
* Shape flag
*
* @var int
*/
private $_spFlag;
/**
* 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;
}
/**
* 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
*

View File

@ -282,7 +282,7 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter
$escher = null;
// check if there are any shapes for this sheet
if (count($sheet->getDrawingCollection()) == 0) {
if (count($sheet->getDrawingCollection()) == 0 && $sheet->getAutoFilter() == '') {
continue;
}
@ -322,6 +322,8 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter
// set the shape type
$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)
$reducedSpId = $countShapes[$sheetIndex];
@ -356,6 +358,64 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter
$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
$this->_IDCLs[$dgId] = $lastReducedSpId;

View File

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

View File

@ -779,6 +779,19 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter
$chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C', 0x06), $formulaData, $i + 1, true));
}
}
// 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;
}
@ -817,6 +830,42 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter
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.

View File

@ -390,6 +390,11 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter
$this->_writeColinfo($this->_colinfo[$i]);
}
}
if ($_phpSheet->getAutoFilter() != '') {
// Write AUTOFILTERINFO
$this->_writeAutoFilterInfo();
}
// Write sheet dimensions
$this->_writeDimensions();
@ -2017,7 +2022,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter
$fPrintGrid = $this->_phpSheet->getPrintGridlines() ? 1 : 0; // Boolean flag
$header = pack("vv", $record, $length);
$data = pack("v", $fPrintGrid);
$data = pack("v", $fPrintGrid);
$this->_append($header . $data);
}
@ -2037,6 +2042,21 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter
$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
* 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);
$data = $writer->close();
$spOffsets = $writer->getSpOffsets();
$spTypes = $writer->getSpTypes();
// write the neccesary MSODRAWING, OBJ records
// split the Escher stream
@ -2692,7 +2712,6 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter
$record = 0x00EC; // Record identifier
// chunk of Escher stream for one shape
$dataChunk = substr($data, $spOffsets[$i -1], $spOffsets[$i] - $spOffsets[$i - 1]);
$length = strlen($dataChunk);
@ -2705,17 +2724,42 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter
$objData = '';
// ftCmo
$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
);
if($spTypes[$i] == 0x00C9){
// Add ftCmo (common object data) subobject
$objData .=
pack('vvvvvVVV'
, 0x0015 // 0x0015 = ftCmo
, 0x0012 // length of ftCmo data
, 0x0014 // object type, 0x0014 = filter
, $i // object id number, Excel seems to use 1-based index, local for the sheet
, 0x2101 // option flags, 0x2001 is what OpenOffice.org uses
, 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
$objData .=
pack('vv'

View File

@ -29,6 +29,7 @@ Fixed in develop branch:
Current options are tcPDF, mPDF, DomPDF
tcPDF Library has now been removed from the deployment bundle
- 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: (schir1964) Fix to listWorksheetInfo() method for OOCalc Reader
- Bugfix: (MBaker) Support for "e" (epoch) date format mask