Page 1 sur 1

Objet COM et problème excel.

Posté : 15 juin 2010, 10:00
par tortukitu
Bonjour à tous,
j'espère que je poste au bon endroit et que vous pourrez répondre à ma question.

Je cherche à modifier des feuilles excel en php. Les classeurs contiennent des macros VBA afin de les signer numériquement. Après m'être renseigné, j'ai appris que phpExcel ne gérait pas les macros vba lors de la manipulation des fichiers.
J'ai donc du me débrouiller avec l'objet COM.

Le souci: Le script fonctionne parfaitement sur une machine, mais plante sur l'autre. Vous trouverez ci dessous le message d'erreur et le code utilisé:

Message d'erreur:
Fatal error: Uncaught exception 'com_exception' with message '<b>Source:</b> Microsoft Office Excel<br/><b>Description:</b> Microsoft Office Excel ne peut accéder au fichier « C:\Program Files (x86)\xxx\www\documents\xlsTemplates\command.xls ». Plusieurs raisons possibles : • Le nom du fichier ou le chemin n'existe pas. • Ce fichier est actuellement utilisé par un autre programme. • Le classeur que vous essayez d'enregistrer porte le même nom qu'un classeur actuellement ouvert.' in C:\Program Files (x86)\xxx\www\xlsbParserMan.php:52 Stack trace: #0 C:\Program Files (x86)\xxx\www\xlsbParserMan.php(52): variant->Open('C:\Program File...') #1 C:\Program Files (x86)\xxx\www\xlsbParserMan.php(146): xlsbParserMan->parseXlsb2('239') #2 C:\Program Files (x86)\xxx\www\admin_actions.php(9608): xlsbParserMan->makeFile('239') #3 C:\Program Files (x86)\xxx\www\order_list_po.php(48): generate_po_form('239', 'xls.9', '', false) in C:\Program Files (x86)\xxx\www\xlsbParserMan.php on line 52
La classe qui plante:
class xlsbParserMan{
	// l'array de donnes a remplacer
	private $dataReplace;
	// le nom de fichier qui va bien
	private $fileName;
	// L'objet excel correspondant au template
	private $objPHPExcel;
	
	public function __construct($file, $dataReplace){	
		/** Error reporting */
		error_reporting(E_ALL);
		/** PHPExcel */
		require_once './Classes/PHPExcel.php';
		/** PHPExcel_IOFactory */
		require_once './Classes/PHPExcel/IOFactory.php';
		$this->fileName=$file;
		$this->dataReplace=$dataReplace;
		$this->keys=array_keys($dataReplace);
		}
	
	public function parseXlsb(){
	}	

	public function parseXlsb2($fileName2){
		$path=realpath('./');
		$path=preg_replace("/\//", "\\", $path);
		$this->fileName=preg_split("/\//", $this->fileName);
		$this->fileName=$this->fileName[3];
		$placedItem=-1;
		$excel_app=new COM("Excel.application");
		$excel_app->Workbooks->Close(); 
// PLANTAGE ICI:
		$Workbook = $excel_app->Workbooks->Open($path.'\\documents\\xlsTemplates\\'.$this->fileName) or Die('Did not open filename');
//
		$Worksheet = $Workbook->Worksheets('Labcollector');
		$Worksheet->activate;
		for($i=1;$i<100; $i++){
			for($j=65;$j<=90;$j++){
				$excel_cell=$Worksheet->Range(chr($j).$i);
				$excel_cell->activate;
				$cellValue=$excel_cell->value;
				if( in_array($cellValue, $this->keys)){
					if(preg_match("/##chem_ref##/",$cellValue)){
						$placedItem+=1;
						}
					if(preg_match("/##chem_ref##/",$cellValue) or preg_match("/##chem_name##/",$cellValue) or preg_match("/##qty##/",$cellValue) or preg_match("/##chem_seller_price##/",$cellValue) or preg_match("/##sequence##/",$cellValue) or preg_match("/##discount##/",$cellValue)){
						if($placedItem >= count($this->dataReplace[$cellValue])){
							$excel_cell->value="";	
							}else{
								$excel_cell->value=$this->dataReplace[$cellValue][$placedItem];
						}
					}else{
						//echo "REPLACING WITH ".$this->dataReplace[$cellValue];
						$excel_cell->value=$this->dataReplace[$cellValue];
					}
				}
			}
		}
		$fileName=$fileName2;
		if(file_exists($path."\\documents\\xlsForms\\".$fileName.".xls"))
		{
        	unlink($path."\\documents\\xlsForms\\".$fileName.".xls");
		}
		$Workbook->saveas($path."\\documents\\xlsForms\\".$fileName.".xls");
		$Workbook->Saved = true;
		$Workbook->Close;
		unset($Worksheet);
		unset($Workbook);
		
		$excel_app->Workbooks->Close();
		$excel_app->Quit();
		
		unset($excel_app);

	}

	public function parseXlsbNoVBA($sheetNumber, $sheetNumber2){
		$this->objPHPExcel = PHPExcel_IOFactory::load($this->fileName);
		$this->objPHPExcel->setActiveSheetIndex($sheetNumber2);
		$placedItem=-1;
		for($i=0;$i<100; $i++){
			for($j=65;$j<=90;$j++){
				$cellValue= $this->objPHPExcel->getSheetByName('Labcollector')->getCell(chr($j).$i)->getValue();
				if( in_array($cellValue, $this->keys)){
					$this->objPHPExcel->getSheetByName('Labcollector')->setCellValue(chr($j).$i,"");
					if(preg_match("/##chem_ref##/",$cellValue)){
						$placedItem+=1;
						}
					if(preg_match("/##chem_ref##/",$cellValue) or preg_match("/##chem_name##/",$cellValue) or preg_match("/##qty##/",$cellValue) or preg_match("/##chem_seller_price##/",$cellValue) or preg_match("/##sequence##/",$cellValue) or preg_match("/##discount##/",$cellValue)){
						if(!($placedItem >= count($this->dataReplace[$cellValue]))){
							$this->objPHPExcel->getSheetByName('Labcollector')->setCellValue(chr($j).$i,"");
							if(isset($this->dataReplace[$cellValue][$placedItem])){
							$this->objPHPExcel->getSheetByName('Labcollector')->setCellValue(chr($j).$i,$this->dataReplace[$cellValue][$placedItem]);
							}
						}
					}else{
						$this->objPHPExcel->getSheetByName('Labcollector')->setCellValue(chr($j).$i,"");
					}
				}
			}
		}
	}

	public function makeFileNoVBA($fileName){
		$this->objWriter = PHPExcel_IOFactory::createWriter($this->objPHPExcel, 'Excel2007');
		$this->objWriter->save("./documents/xlsForms/".$fileName.".xls");
		}


	public function makeFile($fileName){
		$this->parseXlsb2($fileName);
		}

	public function __destruct(){
	}
		
}
J'ai vérifié plusieurs fois, le fichier indiqué par le message d'erreur existe bel et bien et est accessible. Quand au classeur déjà ouvert, ça me paraît improbable, étant donné que je fais un Close() juste avant. Je suppose par conséquent qu'il pourrait s'agir d'un problème de permissions. [Je précise que j'ai testé sous Vista et Seven]

Est-ce que ça pourrait venir d'un problème de config de php.ini?
J'ai eu beau me renseigner à droite à gauche, je ne voît toujours pas la solution.

Voici ce que j'ai testé:
- Placer le fichier à la racine et mettre le chemin en dur dans le script: Même erreur.
- Changer les permissions en le mettant totalement accessible en lecture / écriture par tous: Même erreur.
- Vérifier ce qui se passe quand le fichier n'existe vraiment pas : J'obtiens alors un autre message d'erreur.

Peut-être ais-je fait une erreur quelque part dans mon code? Pourquoi dans ce cas, est-ce que ça marche sur une machine et pas sur l'autre? Est-ce que ça pourrait venir d'Excel (Excel 2007 v.12)?

Merci beaucoup d'avoir pris le temps de me lire.
J'attends vos suggestions.

La tortue.

Re: Objet COM et problème excel.

Posté : 16 juin 2010, 09:45
par tortukitu
Rebonjour,
je suis encore bloqué. La situation n'a pas évoluée d'un pouce aujourd'hui.

Je me permet de poster un code facile à tester afin d'observer le bug:

Code : Tout sélectionner

<?php // TEST PHP DE COM echo "RUNNING COM... "; flush(); if(file_exists('C:\xxx\command.xls')){ $excel_app=new COM("Excel.application"); $Workbook = $excel_app->Workbooks->Open('C:\xxx\command.xls') or Die('Did not open filename'); $excel_app->Workbooks->Close(); $excel_app->Quit(); unset($Workbook); unset($excel_app); echo "[OK]"; flush(); }else{ echo "[FAILED]"; } ?>



Je suis désespéré, j'ai tout essayé, je ne sais plus du tout quoi faire...

La tortue.

Re: Objet COM et problème excel.

Posté : 16 juin 2010, 10:07
par zeus
Est-ce que cette racine est identique sur les deux machine ?
C:\Program Files (x86)\

Re: Objet COM et problème excel.

Posté : 16 juin 2010, 15:12
par tortukitu
Non, (X86) n'est utilisé que pour la machine sur laquelle le script plante.

Des parenthèses dans le chemin pourraient faire rater COM?

La tortue.

Re: Objet COM et problème excel.

Posté : 16 juin 2010, 16:55
par zeus
C'est ce que je me demandais ...
Essaye de faire en sorte que le fichier que tu veux ouvrir disposes d'un chemin très simple "C:/tmp/classeur.xml"

Re: Objet COM et problème excel.

Posté : 17 juin 2010, 09:49
par tortukitu
Merci de ta réponse.

J'ai essayé de mettre le fichier dans une répertoire "tmp" directement à la racine.

Toujours la même erreur.

La tortue.

Re: Objet COM et problème excel.

Posté : 21 juin 2010, 12:49
par tortukitu
Je me permets un petit up.

Je bloque toujours sur le même problème malgré mes nombreuses tentatives. J'espère que quelqu'un me mettra sur la bonne piste.

La tortue.

Re: Objet COM et problème excel.

Posté : 21 juin 2010, 14:24
par tortukitu
Bon, j'avance un peu.

Le problème semble venir de Apache. Quand je lance mon script avec l'interpréteur en ligne de commande, tout marche nikel.

Par contre, j'ai toujours ce message avec Apache.

Est-ce que ça pourrait être du à une boite de dialogue qu'excel essayerai d'afficher? (Même quand je le met en Visible = 0 ?).

La tortue.