PHPExcel not working perfectly - php

I use PHPExcel library from here to create an excel file extension .xlsx
for that i use php and mysql the data of this excel file is from mysql database.
After i create the code i receive this message:
Excel can't open the file because the file format or file extension is
not valid. Verify that the file has not been corrupted and that the
file extension matches the format of the file
To solve this problem i use:
ob_start(); ob_end_clean();
After that i download the file and try to open the excel file i have this message:
We found a problem with some content in your file.Do you want to us to
try to recover as much as we can?if you trust the source of this
workbook,click yes.
When i click yes i have this message:
Excel completed file level validation and repair. Some parts of this
workbook may have been repaired or discarded.
I click close the excel file open but inside this excel file i have some empty rows with my data.
This is my code to download an excel file using PHPExcel
ob_start();
include("includes/connect.php");
require_once'PHPExcel/Classes/PHPExcel.php';
//Create PHPExcel object
$excel=new PHPExcel();
//selecting active sheet
$excel->setActiveSheetIndex(0);
$row=21;
while($data=mysqli_fetch_object($query)){
$excel->getActiveSheet()->setCellvalue('A'.$row,$data->db_maid)
->setCellvalue('B'.$row,$data->db_date)
->setCellvalue('C'.$row,$data->db_client)
->setCellvalue('D'.$row,$data->db_esid)
->setCellvalue('E'.$row,$data->db_type)
->setCellvalue('F'.$row,$data->db_phone)
->setCellvalue('G'.$row,$data->db_mobile)
->setCellvalue('H'.$row,$data->db_contactperson)
->setCellvalue('I'.$row,$data->db_competetivecompany)
->setCellvalue('J'.$row,$data->db_category)
->setCellvalue('K'.$row,$data->db_process)
->setCellvalue('L'.$row,$data->db_status)
->setCellvalue('M'.$row,$data->db_rate)
->setCellvalue('N'.$row,$data->db_doc)
->setCellvalue('O'.$row,$data->nextDate)
->setCellvalue('P'.$row,$data->db_ndstatus)
->setCellvalue('Q'.$row,$data->db_pnote)
->setCellvalue('R'.$row,$data->meetingStatus)
->setCellvalue('S'.$row,$data->db_ncam)
->setCellvalue('T'.$row,$data->medit)
->setCellvalue('U'.$row,$data->name);
//incriment the row
$row++;
}
//set column width
$excel->getActiveSheet()->getColumnDimension('A')->setWidth(10);
$excel->getActiveSheet()->getColumnDimension('B')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('B')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('D')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('E')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('F')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('G')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('H')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('I')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('J')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('K')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('L')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('M')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('N')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('O')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('P')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('Q')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('R')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('S')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('T')->setWidth(20);
$excel->getActiveSheet()->getColumnDimension('U')->setWidth(20);
//make table headers
$excel->getActiveSheet()
->setCellValue('A1','List Of Marketing')
->setCellValue('A3','#')
->setCellValue('B3','Date')
->setCellValue('C3','Client')
->setCellValue('D3','ES')
->setCellValue('E3','Type')
->setCellValue('F3','Phone')
->setCellValue('G3','Mobile')
->setCellValue('H3','Contact Person')
->setCellValue('I3','Competetive Company')
->setCellValue('J3','Categoty')
->setCellValue('K3','Process')
->setCellValue('L3','Status')
->setCellValue('M3','Rate')
->setCellValue('N3','Date Of Calling')
->setCellValue('O3','Next Date')
->setCellValue('P3','Next Date Status')
->setCellValue('K3','Phone Note')
->setCellValue('R3','Meeting Status')
->setCellValue('S3','Next Call After Meeting')
->setCellValue('T3','Edit Date')
->setCellValue('U3','Staff');
//Margin The title
$excel->getActiveSheet()->mergeCells('A1:U1');
//aligning
$excel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal('center');
//styling
$excel->getActiveSheet()->getStyle('A1')->applyFromArray(
array(
'font'=>array(
'size'=>24,
)
)
);
$excel->getActiveSheet()->getStyle('A3:U3')->applyFromArray(
array(
'font'=>array(
'bold'=>true
),
'borders'=>array(
'allborders'=>array(
'style'=>PHPExcel_Style_Border::BORDER_THIN
)
)
)
);
//give border to data
$excel->getActiveSheet()->getStyle('A4:U'.($row-1))->applyFromArray(
array(
'borders'=>array(
'outline'=>array(
'style'=>PHPExcel_Style_Border::BORDER_THIN
),
'vertical'=>array(
'style'=>PHPExcel_Style_Border::BORDER_THIN
)
)
)
);
//write the result to a file
$file=PHPExcel_IOFactory::createWriter($excel,'Excel2007');
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment; filename="marketing.xlsx"');
header('Cache-Control:max-age=0');
ob_end_clean();
//output to php output instead of filename
$file->save('php://output');
My question is How to solve this problem i don't want this message appear also i don't want to have an empty rows in my excel also ob_end_clean() is a real solution for the first message because i saw a tutorial on the internet and his code work correctly without using the ob_end_clean() or the ob_start()?

You're doing it the other way around. The only part you need to get into the buffer is $file->save("php://output");. If for any reason simply exiting after saving to output is not enough for you, delete the first ob_start(); and last line and try this:
ob_start();
$file->save("php://output");
$content = ob_get_contents();
ob_end_clean();
die($content);

Try removing
break;
in libraries/PHPExcel/Calculation/Functions.php (line 1161)
in public static function TYPE($value = NULL){}
in elseif(is_array($value)) {}
It solved my problem.

Related

Filename being shortened by script

I have some php code that connects to a MSSQL, looks up some values and retrieves a file that is stored in binary format. The table has the filename, header and the binary data. Presently my code is downloading the file as expected however, if there is a space in the filename, the name is cut short, as if the space is acting as a delimeter. e.g. value in db "This is an example file.pdf" outputted filename "This" and the browser recognises the pdf type.
My somewhat functional code is below:
/* Retrieve and display the data.
The return data is retrieved as a binary stream. */
if ( sqlsrv_fetch( $stmt ) )
{
$noticeID = sqlsrv_get_field( $stmt, 0, SQLSRV_PHPTYPE_INT);
$filename = sqlsrv_get_field( $stmt, 1, SQLSRV_PHPTYPE_STRING("UTF-8"));
$header = sqlsrv_get_field( $stmt, 2, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY));
$download = sqlsrv_get_field( $stmt, 3, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY));
header('Content-Type: '.$header);
header("Content-Disposition: attachment; filename=$filename");
echo "Your file, $filename is ready for download";
fpassthru($download);
}
else
{
echo "Error in retrieving data.</br>";
print_r( sqlsrv_errors(), true);
}
I suspect that the issue is that the filename is stored as a VARCHAR(255) in the DB and somehow is breaking the "Content-Disposition" header line. Research brought me to this page but it isn't very clear on how to handle VARCHAR and when I try and "hack" it by guessing (see below) and get a filename "index.php" (although it does download the file)
$filename = sqlsrv_get_field( $stmt, 1, SQLSRV_PHPTYPE_VARCHAR);
I've also tried this in place of the faulty header line:
$filename = sqlsrv_get_field( $stmt, 1, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY)))
It still cuts off the filename. If there is no space in the filename, the code executes perfectly.
BONUS: does anyone know how I could save the file to the filesystem rather than having a download dialog? This code is proof of concept for a data migration script I'm writing and that would also be very helpful :)
Please try the following: concatenate the header as follows:
header('Content-Disposition: attachment; filename="'."$filename".'"');
And save the file via:
function file_put_contents()

Image from database into PDF using FPDF

I have an image that is sent from an iPad app to an SQL database. I can retrieve this image and display in a web page using the following php:
$img = base64_encode($row['photoData']);
echo "<img src=\"data:image/jpg;charset=utf8;base64, $img\"/>";
This displays fine. What I want to do now is put this image into a PDF document using FPDF however I am struggling to do this.
This:
$img = base64_encode($row['photoData']);
$pdf->Image($img);
give this error:
FPDF error: Image file has no extension and no type was specified:
So I tried this (although I realise I will then have to look at how to get the size of the image sorted):
$pdf->Image($img, 20, 20, 20, 20 'JPG');
which give me:
FPDF error: Missing or incorrect image file:
What is the correct way to do this?
Or would it be easier to temporarily save the image to the server and then place the saved image into the PDFdoc?
As mentioned in the comments above this is possible by using a stream ("data url") to hand over the image data to the fpdf library without writing physical files to disk:
<?php
// load the 'fpdf' extension
require('fpdf.php');
// just for demonstration purpose, the OP gets the content from a database instead
$h_img = fopen('img.jpg', "rb");
$img = fread($h_img, filesize('img.jpg'));
fclose($h_img);
// prepare a base64 encoded "data url"
$pic = 'data://text/plain;base64,' . base64_encode($img);
// extract dimensions from image
$info = getimagesize($pic);
// create a simple pdf document to prove this is very well possible:
$pdf = new FPDF();
$pdf->AddPage();
$pdf->SetFont('Arial','B',16);
$pdf->Cell(40,10,'Hello Image!');
$pdf->Image($pic, 10, 30, $info[0], $info[1], 'jpg');
$pdf->Output();
If this is a good advice is another question, this is merely meant to prove that this is possible...
According to the Docs FPDF::Image accepts a filename as the first argument, not a binary blob.
If you want to use FPDF specifically, save the image to a temporary file first, and then pass that to FPDF::Image.
To do that, something like this should work:
$tmpFile = tempnam(sys_get_temp_dir(), 'fpdfimg');
if (file_put_contents($tmpFile, $row['photoData'])) {
$fpdf->Image($tmpFile);
// save/display image
unlink($tmpFile);
}
Alternatively, if you want to just serve the image as a PDF (with no other content) you could use Imagick:
$im = new \Imagick();
$im->readImageBlob($row['photoData']);
$im->setImageFormat('pdf');
header('Content-Type: application/pdf');
echo $im;
Since FPDF cannot use base64 data to produce images on the PDF, I would recommend saving the file to the disk permanently as opposed to writing a temp file for every PDF operation.
This will save you a lot of I/O overhead.
Assuming your table has unique photo_id or photo_name to accompany photoData then you can use something like this to create your images and use them in FPDF.
I will also assume you have a last_update and photo_extension column.
<?php
$path = '/path/to/fpdf/images/';
$filename = $row['photo_id'].'.'.$row['photo_extension'];
$filepath = $path.$filename;
// If a physical file is not available then create it
// If the DB data is fresher than the file then make a new file
if(!is_file($filepath) || strtotime($row['last_update']) > filemtime($filepath))
{
$result = file_put_contents($filepath, $row['photoData']);
if($result === FALSE)
{
die(__FILE__.'<br>Error - Line #'.__LINE__.': Could not create '.$filepath);
}
}
$pdf->Image($filepath);
If you plan on updating the photoData which is stored in your DB then you will have to make sure to also have a timestamp column and compare that timestamp against the filemtime($filepath) of the image on your disk.
Another solution for this ;)
Make a new php by copying and pasting this (piece of fpdf's code edited):
require('fpdf.php');
class DATAIMAGE extends FPDF
{
protected function _parsedata($file)
{
// Extract info from a JPEG file
$a = getimagesizefromstring($file);
if(!$a)
$this->Error('Missing or incorrect image file: '.$file);
if($a[2]!=2)
$this->Error('Not a JPEG file: '.$file);
if(!isset($a['channels']) || $a['channels']==3)
$colspace = 'DeviceRGB';
elseif($a['channels']==4)
$colspace = 'DeviceCMYK';
else
$colspace = 'DeviceGray';
$bpc = isset($a['bits']) ? $a['bits'] : 8;
return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$file);
}
}
Then call this php instead of fpdf.php in your main php.
You'll now be able to display an image simply by adding 'data' to the end of the function:
$pdf->Image($mysqlrow["blob"],0,0,40,0,'data');

convert an EXCEL file to CSV file in PHP [duplicate]

This question already has answers here:
How to convert Excel XLS to CSV using PHP
(5 answers)
Closed 7 years ago.
I want to convert Excel files (.xls) into CSV file (.csv) with a script PHP ?
I tried many codes but it didn't work like this one !
No errors appear but it wont work Any idea or any other lines of codes that I can try ?
<?php
echo("it works");
require_once '../batchs/Classes/PHPExcel/IOFactory.php';
$inputFileType = 'Excel5';
$inputFileName = '../public/aixstream/stock.xls';
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
$objPHPExcelReader = $objReader->load($inputFileName);
$loadedSheetNames = $objPHPExcelReader->getSheetNames();
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcelReader, 'CSV');
foreach($loadedSheetNames as $sheetIndex => $loadedSheetName) {
$objWriter->setSheetIndex($sheetIndex);
$objWriter->save($loadedSheetName.'.csv');
}
?>
Thank you
As already stated in this answer, you can use the PHP-ExcelReader function to read the xls file. After that, you may easily convert it into CSV (or any other other format) using the following code, also available here.
Reading the xls file
//You will obviously need to import the function
//by downloading the file from the link above.
$reader=new Spreadsheet_Excel_Reader(); //Instantiate the function
$reader->setUTFEncoder('iconv'); // Set Encoder
$reader->setOutputEncoding('UTF-8'); // Set Output Encoding Type
$reader->read($filename); // Read the xls file
Data Output
/***
* Information about sheets is stored in boundsheets variable.
* This code displays each sheet's name.
***/
foreach ($reader->boundsheets as $k=>$sheet) //Run loop for all sheets in the file
{
echo "\n$k: $sheet";
}
//Now just save the data in the array as csv
/***
* Data of the sheets is stored in sheets variable.
* For every sheet, a two dimensional array holding table is created.
* This code saves all data to CSV file.
***/
foreach($reader->sheets as $k=>$data) // Run loop for all items.
{
echo "\n\n ".$reader->boundsheets[$k]."\n\n"; //Print Title
foreach($data['cells'] as $row) // Loop for all items
{
foreach($row as $cell) // Loop for every cell
{
echo "$cell".","; //Add a comma after each value
}
}
}
//It works! :D

PHP Converting CSV to XLS - phpExcel error

I have written an Export script that will export data from my database as a CSV or XLS file. The data from the database needs to be manipulated first. So far I have the CSV file working and am now trying to convert this CSV string to XLS. I want to use phpExcel but get the below error. Can anyone assist?
Fatal error: Class 'PHPExcel_Exception' not found in /var/www/leanne/api/library/PHPExcel/Exception.php on line 36
Code which is causing the error, all worked fine until I added the XLS stuff:
if($format == 'csv'){
//create and write to file for CSV
if(file_exists($file_location . $filename)){
unlink($file_location . $filename);
}
$fh = fopen($file_location . $filename , 'a');
fwrite($fh, $csv);
fclose($fh);
} else if($format == 'xls'){
//wite to file for XLS
include '../library/PHPExcel/IOFactory.php';
$objReader = PHPExcel_IOFactory::createReader('CSV');
$objReader->setDelimiter($separator);
$objReader->setEnclosure(" ");
$objReader->setLineEnding($endrow);
$objPHPExcel = $objReader->load($csv);
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
$objWriter->save($file_location . $filename);
}
NB: csv is a string containing comma separated and double quoted fields from the database. The lines end with '\n'.
Ive downloaded the files again and started from scratch and its working. Must have been something silly I had done, sorry for wasting your time and thanks for the help.

Export CSV from Mysql

I'm having a bit of trouble exporting a csv file that is created from one of my mysql tables using php.
The code I'm using prints the correct data, but I can't see how to download this data in a csv file, providing a download link to the created file. I thought the browser was supposed to automatically provide the file for download, but it doesn't. (Could it be because the below code is called using ajax?)
Any help greatly appreciated - code below, S.
include('../cofig/config.php'); //db connection settings
$query = "SELECT * FROM isregistered";
$export = mysql_query($query) or die("Sql error : " . mysql_error());
$fields = mysql_num_fields($export);
for ($i = 0; $i < $fields; $i++) {
$header .= mysql_field_name($export, $i) . "\t";
}
while ($row = mysql_fetch_row($export)) {
$line = '';
foreach ($row as $value) {
if ((!isset($value) ) || ( $value == "" )) {
$value = "\t";
} else {
$value = str_replace('"', '""', $value);
$value = '"' . $value . '"' . "\t";
}
$line .= $value;
}
$data .= trim($line) . "\n";
}
$data = str_replace("\r", "", $data);
if ($data == "") {
$data = "\n(0) Records Found!\n";
}
//header("Content-type: application/octet-stream"); //have tried all of these at sometime
//header("Content-type: text/x-csv");
header("Content-type: text/csv");
//header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=export.csv");
//header("Content-Disposition: attachment; filename=export.xls");
header("Pragma: no-cache");
header("Expires: 0");
echo 'Download Exported Data'; //want my link to go in here...
print "$header\n$data";
In essence, you can't output the CSV file and the link to it in one go. (You need to introduce the concept of a page "mode" and activate the download mode via a ...pagename.php?mode=download or similar. You could then use PHP's switch statement to switch on $_GET['mode'] in your script.)
That said, the text/csv content type header you were using is correct, although you may also want to output the Content-Length and Content-Disposition headers. After you've output the file data, also be sure to stop any additional script processing via PHP's exit function.
Additionally, it would probably be a lot less hassle (and will certainly be faster/more memory efficient) to use MySQL SELECT ... INTO OUTFILE facility (if you have the permissions) rather than use PHP to gather the data.
You can't have text and a download on the same page. You need to have a link to the download area, which could just be a GET parameter leading to a function, which then does all the processing, displays headers, and echoes the content of the CSV.
For example, you could have Click here to download CSV, then in your code have if ($_GET['action'] === 'download'), get the data from the database, format it, send the headers, and echo the data. And then die(), because that part of the script can accomplish no more.
You should not put the link in the same file that generates the csv, as the link will not be in the csv itself!
Do something like:
Download CSV
and it should work
Three things to consider:
You're sending headers indicating that the user is going to be downloading a CSV file, but then you send create a link to download it? This isn't correct, you should be linking to this page, and then only outputting the CSV data itself after the headers.
MySQL has the ability to generate CSV output, and you should definitely take advantage of this instead of trying to do it yourself. You can use SELECT INTO ... OUTFILE to do this.
If you must create the CSV using PHP, please use fputcsv to do so. This will handle all the complications of CSV such as escaping and proper formatting. Since fputcsv writes to a file, you could either write it to a temporary file and then output it after you send your headers, or use the following trick to output it directly:
Do this after sending headers:
$fp = fopen('php://output', 'w');
while( $row = mysql_fetch_row( $export ) ) {
fputcsv($fp, $row);
}
I think the mySQL => CSV is common problem which is part of each PHP forum.
I have try to solve this issue in a common way and implement an free export
lib for PHP which is very similar to the Google AppInventor philosophie.
DragDrop and hide the coding stuff.
Use the lib and create your Export via Click&Point.
Common Demos: http://www.freegroup.de/software/phpBlocks/demo.html
Link to editor: http://www.freegroup.de/test/editor/editor.php?xml=demo_sql.xml
worth a look
Greetings
Andreas

Categories