Skip to content
This repository was archived by the owner on Jan 2, 2019. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
254 changes: 245 additions & 9 deletions Classes/PHPExcel.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,254 @@ class PHPExcel
*/
private $_cellStyleXfCollection = array();

/**
* Create a new PHPExcel with one Worksheet
/**
* _hasMacros : this workbook have macros ?
*
* @var bool
*/
private $_hasMacros = FALSE;

/**
* _macrosCode : all macros code (the vbaProject.bin file, this include form, code, etc.), NULL if no macro
*
* @var binary
*/
private $_macrosCode=NULL;
/**
* _macrosCertificate : if macros are signed, contains vbaProjectSignature.bin file, NULL if not signed
*
* @var binary
*/
private $_macrosCertificate=NULL;

/**
* _ribbonXMLData : NULL if workbook is'nt Excel 2007 or not contain a customized UI
*
* @var NULL|string
*/
private $_ribbonXMLData=NULL;

/**
* _ribbonBinObjects : NULL if workbook is'nt Excel 2007 or not contain embedded objects (picture(s)) for Ribbon Elements
* ignored if $_ribbonXMLData is null
*
* @var NULL|array
*/
private $_ribbonBinObjects=NULL;

/**
* The workbook has macros ?
*
* @return true if workbook has macros, false if not
*/
public function hasMacros(){
return $this->_hasMacros;
}

/**
* Define if a workbook has macros
*
* @param true|false
*/
public function setHasMacros($hasMacros=false){
$this->_hasMacros=(bool)$hasMacros;
}

/**
* Set the macros code
*
* @param binary string|null
*/
public function setMacrosCode($MacrosCode){
$this->_macrosCode=$MacrosCode;
$this->setHasMacros(!is_null($MacrosCode));
}

/**
* Return the macros code
*
* @return binary|null
*/
public function getMacrosCode(){
return $this->_macrosCode;
}

/**
* Set the macros certificate
*
* @param binary|null
*/
public function setMacrosCertificate($Certificate=NULL){
$this->_macrosCertificate=$Certificate;
}

/**
* Is the project signed ?
*
* @return true|false
*/
public function hasMacrosCertificate(){
return !is_null($this->_macrosCertificate);
}

/**
* Return the macros certificate
*
* @return binary|null
*/
public function getMacrosCertificate(){
return $this->_macrosCertificate;
}

/**
* Remove all macros, certificate from spreadsheet
*
* @param none
* @return void
*/
public function discardMacros(){
$this->_hasMacros=false;
$this->_macrosCode=NULL;
$this->_macrosCertificate=NULL;
}

/**
* set ribbon XML data
*
*/
public function setRibbonXMLData($Target=NULL, $XMLData=NULL){
if(!is_null($Target) && !is_null($XMLData)){
$this->_ribbonXMLData=array('target'=>$Target, 'data'=>$XMLData);
}else{
$this->_ribbonXMLData=NULL;
}
}

/**
* retrieve ribbon XML Data
*
* return string|null|array
*/
public function getRibbonXMLData($What='all'){//we need some constants here...
$ReturnData=NULL;
$What=strtolower($What);
switch($What){
case 'all':
$ReturnData=$this->_ribbonXMLData;
break;
case 'target':
case 'data':
if(is_array($this->_ribbonXMLData) && array_key_exists($What,$this->_ribbonXMLData)){
$ReturnData=$this->_ribbonXMLData[$What];
}//else $ReturnData stay at null
break;
}//default: $ReturnData at null
return $ReturnData;
}

/**
* store binaries ribbon objects (pictures)
*
*/
public function setRibbonBinObjects($BinObjectsNames=NULL, $BinObjectsData=NULL){
if(!is_null($BinObjectsNames) && !is_null($BinObjectsData)){
$this->_ribbonBinObjects=array('names'=>$BinObjectsNames, 'data'=>$BinObjectsData);
}else{
$this->_ribbonBinObjects=NULL;
}
}
/**
* return the extension of a filename. Internal use for a array_map callback (php<5.3 don't like lambda function)
*
*/
private function _getExtensionOnly($ThePath){
return pathinfo($ThePath, PATHINFO_EXTENSION);
}

/**
* retrieve Binaries Ribbon Objects
*
*/
public function getRibbonBinObjects($What='all'){
$ReturnData=NULL;
$What=strtolower($What);
switch($What){
case 'all':
return $this->_ribbonBinObjects;
break;
case 'names':
case 'data':
if(is_array($this->_ribbonBinObjects) && array_key_exists($What, $this->_ribbonBinObjects)){
$ReturnData=$this->_ribbonBinObjects[$What];
}
break;
case 'types':
if(is_array($this->_ribbonBinObjects) && array_key_exists('data', $this->_ribbonBinObjects) && is_array($this->_ribbonBinObjects['data'])){
$tmpTypes=array_keys($this->_ribbonBinObjects['data']);
$ReturnData=array_unique(array_map(array($this,'_getExtensionOnly'), $tmpTypes));
}else
$ReturnData=array();//the caller want an array... not null if empty
break;
}
return $ReturnData;
}

/**
* This workbook have a custom UI ?
*
* @return true|false
*/
public function hasRibbon(){
return !is_null($this->_ribbonXMLData);
}

/**
* This workbook have additionnal object for the ribbon ?
*
* @return true|false
*/
public function hasRibbonBinObjects(){
return !is_null($this->_ribbonBinObjects);
}

/**
* Check if a sheet with a specified code name already exists
*
* @param string $pSheetCodeName Name of the worksheet to check
* @return boolean
*/
public function __construct()
public function sheetCodeNameExists($pSheetCodeName)
{
$this->_uniqueID = uniqid();
$this->_calculationEngine = PHPExcel_Calculation::getInstance($this);
return ($this->getSheetByCodeName($pSheetCodeName) !== NULL);
}

// Initialise worksheet collection and add one worksheet
$this->_workSheetCollection = array();
$this->_workSheetCollection[] = new PHPExcel_Worksheet($this);
$this->_activeSheetIndex = 0;
/**
* Get sheet by code name. Warning : sheet don't have always a code name !
*
* @param string $pName Sheet name
* @return PHPExcel_Worksheet
*/
public function getSheetByCodeName($pName = '')
{
$worksheetCount = count($this->_workSheetCollection);
for ($i = 0; $i < $worksheetCount; ++$i) {
if ($this->_workSheetCollection[$i]->getCodeName() == $pName) {
return $this->_workSheetCollection[$i];
}
}

return null;
}

/**
* Create a new PHPExcel with one Worksheet
*/
public function __construct()
{
// Initialise worksheet collection and add one worksheet
$this->_workSheetCollection = array();
$this->_workSheetCollection[] = new PHPExcel_Worksheet($this);
$this->_activeSheetIndex = 0;

// Create document properties
$this->_properties = new PHPExcel_DocumentProperties();
Expand Down
65 changes: 60 additions & 5 deletions Classes/PHPExcel/Reader/Excel2007.php
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,13 @@ public function load($pFilename)
}
}
break;

//Ribbon
case "http://schemas.microsoft.com/office/2006/relationships/ui/extensibility":
$customUI=$rel['Target'];
if(!is_null($customUI)){
$this->_readRibbon($excel, $customUI, $zip);
}
break;
case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument":
$dir = dirname($rel["Target"]);
$relsWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships");
Expand All @@ -461,13 +467,30 @@ public function load($pFilename)
}
}

$worksheets = array();
$worksheets = array(); $macros=NULL; $customUI=NULL;
foreach ($relsWorkbook->Relationship as $ele) {
if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet") {
switch($ele['Type']){
case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet":
$worksheets[(string) $ele["Id"]] = $ele["Target"];
break;
// a vbaProject ? (: some macros)
case "http://schemas.microsoft.com/office/2006/relationships/vbaProject":
$macros=$ele["Target"];
break;
}
}

if(!is_null($macros)){
$macrosCode=$this->_getFromZipArchive($zip, 'xl/vbaProject.bin');//vbaProject.bin always in 'xl' dir and always named vbaProject.bin
if($macrosCode!==false){
$excel->setMacrosCode($macrosCode);
$excel->setHasMacros(true);
//short-circuit : not reading vbaProject.bin.rel to get Signature =>allways vbaProjectSignature.bin in 'xl' dir
$Certificate=$this->_getFromZipArchive($zip, 'xl/vbaProjectSignature.bin');
if($Certificate!==false)
$excel->setMacrosCertificate($Certificate);
}
}
$styles = array();
$cellStyles = array();
$xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']"));
Expand Down Expand Up @@ -686,7 +709,9 @@ public function load($pFilename)
$docSheet->getTabColor()->setARGB( (string)$xmlSheet->sheetPr->tabColor['rgb'] );
}
}

if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr['codeName'])) {
$docSheet->setCodeName((string) $xmlSheet->sheetPr['codeName']);
}
if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) {
if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) &&
!self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryRight'])) {
Expand Down Expand Up @@ -1942,7 +1967,37 @@ private function _parseRichText($is = null) {
return $value;
}


private function _readRibbon($excel, $customUITarget, $zip){
$baseDir=dirname($customUITarget);
$nameCustomUI=basename($customUITarget);
$localRibbon=$this->_getFromZipArchive($zip, $customUITarget);//get the xml file (ribbon)
$customUIImagesNames=array(); $customUIImagesBinaries=array();
$pathRels=$baseDir.'/_rels/'.$nameCustomUI.'.rels';//something like customUI/_rels/customUI.xml.rels
$dataRels=$this->_getFromZipArchive($zip, $pathRels);
if($dataRels){//exists and not empty if the ribbon have some pictures (other than internal MSO)
$UIRels=simplexml_load_string($dataRels);
if($UIRels){
//we need to save id and target to avoid parsing customUI.xml and "guess" if it's a pseudo callback who load the image
foreach ($UIRels->Relationship as $ele) {
if ($ele["Type"] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {// an image ?
$customUIImagesNames[(string) $ele['Id']] = (string)$ele['Target'];
$customUIImagesBinaries[(string)$ele['Target']]=$this->_getFromZipArchive($zip, $baseDir.'/'.(string)$ele['Target']);
}
}
}
}
if($localRibbon){
$excel->setRibbonXMLData($customUITarget, $localRibbon);
if(count($customUIImagesNames)>0 && count($customUIImagesBinaries)>0){
$excel->setRibbonBinObjects($customUIImagesNames, $customUIImagesBinaries);
}else{
$excel->setRibbonBinObjects(NULL);
}
}else{
$excel->setRibbonXMLData(NULL);
$excel->setRibbonBinObjects(NULL);
}
}
private static function array_item($array, $key = 0) {
return (isset($array[$key]) ? $array[$key] : null);
}
Expand Down
Loading