phpSpreadSheet - how to save charts to separate .png files? - php

I'm using PHP spreadsheet class to successfully create an xlsx spreadsheet with several charts. The spreadsheet is written down to disk.
After that I would like to export these charts from spreadsheet to separate .png files. Based on documentation I tried to use the following code:
$inputFileType = \PhpOffice\PhpSpreadsheet\IOFactory::identify($XLSXfilepath);
$reader = IOFactory::createReader($inputFileType);
$reader->setIncludeCharts(true);
$spreadsheet = $reader->load($XLSXfilepath, $reader::LOAD_WITH_CHARTS);
$nr = 1;
foreach ($spreadsheet->getWorksheetIterator() as $worksheet) {
$chartNames = $worksheet->getChartNames();
foreach ($chartNames as $chartName) {
$chart = $worksheet->getChartByName($chartName);
try{
//the following code results false:
$res = $chart->render('temp/chart'.$nr.'.png');
} catch(Exception $e){
//this doesn't happen, which means then no exception is thrown:
print $e->getMessage();
}
$nr++;
}
}
The problem is that $chart->render results false with any error message and - of course - no .png file is saved on disk. But no exception is thrown.
I double-checked that I have full rights to save files to the selected location and of course, there is enough free space on disk...
I also checked that foreach loop properly finds all charts, which are saved in the .xlsx file.
Is there any way to find out why the charts are not rendered to files?

Related

Read an excel file stored in media folder

I'm developing a WordPress plugin that requires to upload an excel file and then read the data inside of it.
I'm using the function "media_handle_upload" to upload the excel file, then, when I try to use SpreadsheetReader to read the file there's an error saying that the file is not readable.
This is what I'm coding, (I know it's horrible coding, but I'm learning and this is just to get the plugin working)
if(isset($_FILES['test_upload_pdf'])){
$pdf = $_FILES['test_upload_pdf'];
// Use the wordpress function to upload
// test_upload_pdf corresponds to the position in the $_FILES array
// 0 means the content is not associated with any other posts
$uploaded=media_handle_upload('test_upload_pdf', 0);
// Error checking using WP functions
if(is_wp_error($uploaded)){
echo "Error uploading file: " . $uploaded->get_error_message();
}else{
echo $pdf."<br>";
$year = date('Y');
$month = date('m');
$targetPath = get_site_url()."/wp-content/uploads/".$year."/".$month."/".$_FILES['test_upload_pdf']['name'];
$targetPath2 = $_SERVER['DOCUMENT_ROOT']."/".$_SERVER["HTTP_HOST"]."/wp-content/uploads/".$year."/".$month."/".$_FILES['test_upload_pdf']['name'];
echo "<br>";
echo $targetPath2;
echo "<br>";
try
{
$Reader = new SpreadsheetReader($targetPath2);
}
catch (Exception $E)
{
echo $E -> getMessage();
}
I think the reader doesn't work because is trying to access "localhost" instead of the physical folder, for example, one of the $targetPath prints this:
http://127.0.0.1/wordpress/wp-content/uploads/2019/04/example.xlsx
So... My question is, there's a way to access the media files so I can open them with the reader?
Thanks.
Perhaps this helps:
https://developer.wordpress.org/reference/functions/wp_upload_dir/
Otherwise try to hardcode folder "/your/path/to/upload/folder/file.extension" and find out how to create this programmaticly

php getID3 returning the same info of an updated file?

I'm using the getID3 library to get the details of a remote video file. I'm trying to read a portion of the file to get the details of the file, however some videos don't have the full details at the start.
For these videos, I'm trying to download the full video, and then extract the relevant information. However, even after the video has downloaded completely, getID3->analyze($filename), returns the same erroneous file info.
But when I copy the video, and then run the function analyze($filename.'copied.mp4') on copied video, it returns the correct info even though the file contents are same. Perhaps getID3 isn't loading the video again, however, how can I fix this issue without copying the video.
Please find the code below.
if ($fp_remote = fopen($remotefilename, 'r')) {
echo 'conn opened';
$localtempfilename = tempnam('/home/xerox/abc', 'whateva').'.mp4';
if ($fp_local = fopen($localtempfilename, 'wb')) {
$count = 0;
$countExpiry = 8;
while ($buffer = fread($fp_remote, 8192)) {
$count++;
fwrite($fp_local, $buffer);
if ($count >= $countExpiry) {
fflush($fp_local);
$getID3 = new getID3;
$ThisFileInfo = $getID3->analyze($localtempfilename);
if ($ThisFileInfo["error"]){
print "problem encouterd";
$countExpiry += 1000;
} else {
break;}
}
}
fclose($fp_local);
$getID31 = new getID3;
copy ( $localtempfilename, $localtempfilename.'_copied.mp4' );
$ThisFileInfoz = $getID31->analyze($localtempfilename.'_copied.mp4');
// Delete temporary file
unlink($localtempfilename);
fclose($fp_remote);
var_dump($ThisFileInfoz);
}
}
A call to clearstatcache solved the problem for me,
since repeated calls to things like filesize will be cached by the
filesystem and getID3 won't read beyond end-of-file.
source: James Heinrich, developer of getID3.

how to convert page to pdf in php

I have an html page like JsFiddle and I want convert this in pdf, i can't create the line to line pdf because the page is dinamically create, I use php for calling a fiel that connect to mysql and fill a template file like.
$_POST['IdQuestionario']=5;
$_POST['IdUtente']=10001;
$_POST['Visualizza']=true;
$_POST['IdImpianto']=1;
$_POST['Stampa']=true;
$_POST['TipoImpianto']='grande';
ob_start();
ob_clean();
require_once 'intro.php';
$tbl=ob_get_clean();
$html.=$tbl;
I'm trying with tcpf, mpdf , jsPDF but i cant obtain a discrete output because I use colgroup for table. anyone say me a method for render the page,if is possible whitout install software on server.
There a few that i know of - some have problems with tables, I would avoid DOMPDF - known issues with tables.
There's one that's recommended from cvision; i don't have a code sample, but you can download it free and even sample it online.
There's also a php-pdf product available from muhimbi (a little lesser-known!, but i think it's free)
<?php
// Include the generated proxy classes
require_once "documentConverterServices.php";
// Check the uploaded file
if ($_FILES["file"]["error"] > 0)
{
echo "Error uploading file: " . $_FILES["file"]["error"];
}
else
{
// Get the uploaded file content
$sourceFile = file_get_contents($_FILES["file"]["tmp_name"]);
// Create OpenOptions
$openOptions = new OpenOptions();
// set file name and extension
$openOptions->FileExtension = pathinfo($_FILES["file"]["name"], PATHINFO_EXTENSION);
$openOptions->OriginalFileName = $_FILES["file"]["name"];
// Create conversionSettings
$conversionSettings = new ConversionSettings();
// Set the output format
if(isset($_POST["outputFormat"]))
{
$conversionSettings->Format = $_POST["outputFormat"];
} else {
$conversionSettings->Format = "PDF";
}
// Set fidelity
$conversionSettings->Fidelity = "Full";
// These values must be set to empty strings or actual passwords when converting to non PDF formats
$conversionSettings->OpenPassword="";
$conversionSettings->OwnerPassword="";
// Set some of the other conversion settings. Completely optional and just an example
$conversionSettings->StartPage = 0;
$conversionSettings->EndPage = 0;
$conversionSettings->Range = "VisibleDocuments";
$conversionSettings->Quality = "OptimizeForPrint";
$conversionSettings->PDFProfile = "PDF_1_5";
$conversionSettings->GenerateBookmarks = "Automatic";
$conversionSettings->PageOrientation="Default";
// Create the Convert parameter that is send to the server
$convert = new Convert($sourceFile, $openOptions, $conversionSettings);
// Create the service client and point it to the correct Conversion Service
$url = "http://localhost:41734/Muhimbi.DocumentConverter.WebService/?wsdl";
$serviceClient = new DocumentConverterService(array(), $url);
// If you are expecting long running operations then consider longer timeouts
ini_set('default_socket_timeout', 60);
try
{
// Execute the web service call
$result = $serviceClient->Convert($convert)->ConvertResult;
// Send the resulting file to the client.
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"convert." . $conversionSettings->Format . "\"");
echo $result;
}
catch (Exception $e)
{
print "Error converting document: ".$e->getMessage();
}
}
?>
Also, you could investigate 'Snappy' (has dependencies)
You can try WKHTMLTOPDF.
Here is a Stackoverflow Thread on how to use it with PHP.
How do I get WKHTMLTOPDF to execute via PHP?
And here is a wrapper for PHP
https://github.com/mikehaertl/phpwkhtmltopdf
MPDF one of best library to convert pdf, try it
MPDF link : http://www.mpdf1.com/mpdf/index.php
Example link : http://mpdf1.com/common/mpdf/examples/

Using XMLHttpRequest object to PHP, responseText is correct array, but 500 error thrown. Cannot identify cause of error

I've been working on reading an Excel file using PHPExcel and sending the contents of the active worksheet through a JSON encoded array back to the page. My code performs as I expect when I load a specific Excel file, in this case cookies, which lives in the path built below. However, if I change the file name (comment cookies and uncomment testLoadBook.xls), and nothing else, the PHP executes returning the correct array (indicating PHPExcel executed properly, seemingly anyway) but throws a 500 error.
<?php
spl_autoload_unregister(array('YiiBase','autoload'));
set_include_path(get_include_path() . PATH_SEPARATOR . Yii::app()->getBasePath().'/extensions/phpexcel/Classes/');
require_once('PHPExcel/IOFactory.php');
//$excelFile = dirname(__FILE__).'/'.'cookies.xls';
$excelFile = dirname(__FILE__).'/'.'testLoadBook.xls';
echo $excelFile;
//$objPHPExcel = PHPExcel_IOFactory::load($excelFile);
$excelReader = PHPExcel_IOFactory::createReader('Excel5'); //if file extension is .xls
//$excelReader->setReadDataOnly(true);
$excelObj = $excelReader->load($excelFile);
$response = array();
$worksheet = $excelObj->getActiveSheet();
$highestRow = $worksheet->getHighestRow(); // e.g. 10
$highestColumn = $worksheet->getHighestColumn(); // e.g 'F'
$highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumn);
$nrColumns = ord($highestColumn) - 64;
$response[] = array($highestRow,$highestColumnIndex);
for ($row = 1; $row <= $highestRow; $row++) {
for ($col = 0; $col < $highestColumnIndex; $col++) {
$cell = $worksheet->getCellByColumnAndRow($col, $row);
$val = $cell->getValue();
$dataType = PHPExcel_Cell_DataType::dataTypeForValue($val);
$response[] = array($row,$col,$val);
}
}
echo json_encode($response);
?>
Echoing the file path shows that the same exact directory is being referenced (both files exist there). The permissions on both files are the same. I've tried two different approaches to loading the workbook:
$objPHPExcel = PHPExcel_IOFactory::load($excelFile);
and
$excelReader = PHPExcel_IOFactory::createReader('Excel5'); //if file extension is .xls
$excelObj = $excelReader->load($excelFile);
$worksheet = $excelObj->getActiveSheet();
Both of these solutions execute properly without error on the cookies.xls workbook.
I apologize for the potentially confusing description, but I cannot think of any reason a 500 would be thrown while the expected output is also returned.
Thanks for anyone's help on this.
Greg
I was able to determine the problem that was occurring. Yii was looking for the CList.php file after the PHP script was done executing. Yii was unable to find the class file because Yii had been unregistered via:
spl_autoload_unregister(array('YiiBase','autoload'));
This allowed PHPExcel to properly execute and fill the httpRequest.responseText with the correct array of the specified file. The problem came when the PHP file had finished executing and returned to the JavaScript that had called it. At this point, Yii had been unregistered and never reloaded. The approach below must be used because PHPExcel has its own autoloader and will interfere with Yii.
The solution to the problem was fairly simple once I figured this out:
$phpExcelPath = Yii::getPathOfAlias('ext.phpexcel.Classes'); //get path for PHPExcel
spl_autoload_unregister(array('YiiBase','autoload')); //unload Yii
//include PHPExcel and autoloader will execute automatically
include($phpExcelPath . DIRECTORY_SEPARATOR . 'PHPExcel.php');
//do PHPExcel operations: load file, parse and create array, echo JSON array
spl_autoload_register(array('YiiBase','autoload')); //reload Yii before returning to page
REF:
http://www.ramirezcobos.com/2010/11/05/how-to-use-phpexcel-with-yii/
EDIT: Thanks to SilentSakky above for linking the reference that helped me solve this
The error seems like there is some file required which is not included, you can try this
spl_autoload_unregister(array('YiiBase','autoload'));
Yii::import('ext.PHPExcel.Classes.PHPExcel', true);
spl_autoload_register(array('YiiBase','autoload'));
Ref:
1) http://www.yiiframework.com/forum/index.php/topic/31998-problem-loading-phpexcel/

Creating zip archive makes multiple files appended with unpredictable strings

I'm trying to make a PDf downloader where the user can select a couple files and then download a zip of what they selected. I had it working on my personal server, but on the production server I get an odd error. The zip file is generated, but it's appended with a string of numbers eg;
zipfile.zip.a08752, zipfile.zip.b08752
Weirder still, if I delete the string off the end and download the file it expands properly.
I read in this topic PHP Zip Archive sporadically creating multiple files that it's an issue with the file attempting to close multiple times, failing and the retrying.
Heres the code for my zip function, though I suspect it's something to do with the configuration of the
function buildZip($params){
/* Generate unique Id */
$downloadid = uniqid();
/* Pull in the order.xml */
if(!empty($_REQUEST['downloadlink'])){
if( $params->usexml == true){
$xml = #simplexml_load_file($params->pdfolder.'/order.xml');
$order = $xml->children();
}else{
$order = $params->files;
}
/* Create the new Zip */
$zip = new ZipArchive();
if ($zip->open($params->zipname.'version'.$downloadid.'.zip', ZIPARCHIVE::CREATE) !== TRUE) {
die ("Could not open archive");
}
/* Generate the download link to output further down the page */
global $downloadLink;
$downloadLink = $params->zipname.'version'.$downloadid.'.zip';
/* Make selected variable available to build the listSelection function */
global $selected;
$selected = array();
$i = 0;
foreach($order as $el){
if (isset($_POST[$i]) == true){
//generate list of selected PDF's
array_push($selected, $el->name);
//grab selected pdf's and zip them.
echo $zip->addFile($params->pdfolder.'/'.$el->link);
$zip->addFile($params->pdfolder.'/'.$el->link) or die ("ERROR: Could not add file: pdf'.$i.'.html");
}
$i++;
}
$zip->close();
}
}
<code>
For Clarity, I'm pulling in an XML list called order.xml to pull in the array of possible files.
Try trimming the weird string of numbers after zipping is done
I just ran into the same problem. This is happening because the zip file fails to get created. It's failing because your files are too large. To fix the problem, I had to create multiple smaller zip files. I hope this helps.

Categories