Convert csv to xls before streaming to xls - php

I'm outputting a custom WordPress posttype to CSV. Works fine... Now I have to output to xls... I want to use PHPExcel... I have no idea how to implement this because my code streams a (csv) file. How can I convert the csv and stream the resulting xls... My code so far:
// create a new array of values that reorganizes them in a new multidimensional array where each sub-array contains all of the values for one custom post instance
$ccsve_generate_value_arr_new = array();
foreach($ccsve_generate_value_arr as $value) {
$i = 0;
while ($i <= ($ccsve_count_posts-1)) {
$ccsve_generate_value_arr_new[$i][] = $value[$i];
$i++;
}
}
// build a filename
// $ccsve_generate_csv_filename = $ccsve_generate_post_type.'-'.date('Ymd_His').'-export.csv';
$ccsve_generate_csv_filename = 'WPhonden.csv';
//output the headers for the CSV file
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Description: File Transfer');
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename={$ccsve_generate_csv_filename}");
header("Expires: 0");
header("Pragma: public");
//open the file stream
$fh = #fopen( 'php://output', 'w' );
$headerDisplayed = false;
foreach ( $ccsve_generate_value_arr_new as $data ) {
// Add a header row if it hasn't been added yet -- using custom field keys from first array
if ( !$headerDisplayed ) {
fputcsv($fh, array_keys($ccsve_generate_value_arr));
$headerDisplayed = true;
}
// Put the data from the new multi-dimensional array into the stream
fputcsv($fh, $data);
}
// Close the file stream
fclose($fh);
// Make sure nothing else is sent, our file is done
exit;
}
Here is the PHPExcel code:
include 'PHPExcel/IOFactory.php';
$objReader = PHPExcel_IOFactory::createReader('CSV');
// If the files uses a delimiter other than a comma (e.g. a tab), then tell the reader
$objReader->setDelimiter("\t");
// If the files uses an encoding other than UTF-8 or ASCII, then tell the reader
$objReader->setInputEncoding('UTF-16LE');
$objPHPExcel = $objReader->load('MyCSVFile.csv');
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
$objWriter->save('MyExcelFile.xls');

Related

Writing to csv file from PHP array displaying code instead of array values

I'm trying to input data from csv to a php array, do some calculations and sort the data then write the new output back into csv from the array ready to go from a download button.
Here's what I've got:
f(isset($_POST["download_csv"])){
$fileName = 'csv-report.csv';
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Description: File Transfer');
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename={$fileName}");
header("Expires: 0");
header("Pragma: public");
$fh = #fopen( 'php://output', 'w' );
foreach ( $table as $subids => $values ) {
// Put the data into the stream
fputcsv($fh, $values);
}
// Close the file
fclose($fh);
// Make sure nothing else is sent, our file is done
exit;
}
For some reason, it's giving me code in the csv file that downloads and no values. It's confusing because when I use just this part written this way to write to a csv file in the root directory it works just fine and gives expected output:
$fh = #fopen( 'csv-report.csv', 'w' );
foreach ( $table as $subids => $values ) {
// Put the data into the stream
fputcsv($fh, $values);
}
// Close the file
fclose($fh);
Any help would be greatly appreciated
EDIT1:
this is what I mean by its giving me code in the csv output instead of the array values. When I remove the post check it's giving me the values properly but it's now in the middle of a bunch of html.

Read and write using fgetcsv and fputcsv

I have a 3rd party source from where I am getting "csv" file. I wrote it inside a quote because it says it's a csv file but basically it's not.
So I am taking that main source file then reading and putting the data in a "PROPER" csv file.
The read and write is fine but the problem is when it saves the properly quoted data is writing on the script file itself.For example if the my php file name is "fixcsv.php" then I am getting the downloadable file as "fixcsv.php".
My code
$headings = array('HID');
$handle = fopen("MonC1.csv", "r");
$data = fgetcsv($handle, 0, ";",'"');
$fh = fopen('php://output', 'w');
ob_start();
fputcsv($fh, $headings);
// Loop over the * to export
if (! empty($data)) {
foreach ($data as $item) {
// echo $item;
fputcsv($fh, array($item));
}
}
$string = ob_get_clean();
$filename = 'csv_' . date('Ymd') .'_' . date('His');
// Output CSV-specific headers
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment filename=\"$filename.csv\";" );
header("Content-Transfer-Encoding: binary");
exit($string);
Any help is highly appreciated. Thanks in advance.
Your Content-Disposition has a semi-colon in the wrong place (per the spec). Should be:
header("Content-Disposition: attachment; filename=\"$filename.csv\" );

Why the extra information getting added to the Excel file which is to be downloaded using PHP headers?

I'm writing PHP array data to the excel file using some library. When I write the data to the excel file and echo some success message, it works fine. No other data than the intended array gets added to the file.
But when I use headers to make the download of same file functionality workable some additional information present on page (like header menu, some heading, copyright line at bottom of page, etc.)gets added to the file. How to avoid adding this extra information to the excel file? Following is my code:
<?php
require_once( CORE_PATH."/libs/excelwriter.inc.php" );
$objRebateReports = new RebateReports();
if($_POST['btnDownload']!='') {
$rebate_ret = $objRebateReports->GetRebateReport($_POST);
$rebate_data = $objRebateReports->GetResponse();
$t=time();
$fileName = ADMIN_ROOT."modules/rebates/rebate_report_".$t.".xls";
$excel = new ExcelWriter($fileName);
if($excel==false) {
echo $excel->error;
die;
}
$myArr = array('Sr. No.', 'Product','Manufacturer','User Name','Date','Status','Transaction Date');
$excel->writeLine($myArr, array('text-align'=>'center', 'color'=> 'red'));
$id=1;
foreach ($rebate_data as $value) {
$temp_rebate_data =array();
$temp_rebate_data['id'] = $id;
$temp_rebate_data['product'] = "";
$temp_rebate_data['manufacturer'] = "";
$temp_rebate_data['user_name'] = $value['customer_first_name']."".$value['customer_last_name'];
$temp_rebate_data['date'] = $value['created_at'];
$temp_rebate_data['status'] = $value['request_status'];
$temp_rebate_data['transaction_date'] = "";
$row = $temp_rebate_data;
$excel->writeLine($row, array());
$id++;
}
$excel->close();
//Following is the header information in order to download the excel file
header("Content-Type: application/vnd.ms-excel; charset=utf-8");
header("Content-Disposition: attachment; filename=".$fileName);
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
//Below is the success message after printing the data successfully to the file
//echo "Data written to file $fileName Successfully.";
}
?>
You should use output buffering for this.
//start of the page
ob_start();
//ur code
//headers
ob_clean();
flush();
readfile($file);
exit;
I think this will solve your problem

File download for csv works in local host but not when live

I am creating a csv file from nested array and it works fine with a download link to the csv file in the localhost, but on live host it won't download. This is what is in my php file:
The headers declared:
/**
* Declare headers for CSV
*/
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=registration.csv");
header("Pragma: no-cache");
header("Expires: 0");
The Function that outputs the csv file:
/**
* Function will output the scsv file
* #param the csv $data in nested array form array(array("","",""),array("",""...)...)
*/
function outputCSV($data) {
$outstream = fopen("php://output", "w");
function __outputCSV(&$vals, $key, $filehandler) {
fputcsv($filehandler, $vals); // add parameters if you want
}
array_walk($data, "__outputCSV", $outstream);
fclose($outstream);
}
The link that I used in local:
Download CSV
Won't work on Live site. Instead of downloading it just takes me to the csv.php page and outputs the array in a string like this.
...ID,"Coach One","Coach Two",Work,Cell,Email,...
Try hardcoding the csv into the code. Replace these lines with the ones you have to see if your data being passed has bad characters. Maybe specifying the charset will help.
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=data.csv');
$output = fopen('php://output', 'w');
fputcsv($output, array('Column 1', 'Column 2', 'Column 3'));
As described here:
http://code.stephenmorley.org/php/creating-downloadable-csv-files/
I'm not setup to really debug your code. You can try this though if you like. I know it works.
$out = fopen("php://temp", 'r+');
while (($row = $res->fetch(Zend_Db::FETCH_NUM)) != false) {
fputcsv($out, $row, ',', '"');
}
rewind($out);
$csv = stream_get_contents($out);
header("Content-Type: application/csv;");
header("Content-Disposition: attachment; filename=\"foo.csv\"");
header("Pragma: no-cache");
header("Expires: 0");
echo $csv;
exit(0);
Adjust the loop as needed to iterate on your results.

phpExcell generating extra worksheets

I'm trying to use phpExell in my Zend application to print out a Excel file with multiple work sheets.
In my controller class I have the following global variable...
public $objPHPExcel;
which is initialized in an action function like so...
$this->objPHPExcel = new PHPExcel();
The action then iterates through some database calls, building a report. On each iteration, it calls the following function, passing in the index of the worksheet as an integer, an array of data to be printed out, and a string containing the name of the worksheet.
protected function buildWorksheet($index, $report, $repName) {
//build new worksheet after default
if($index > 0) {
$objWorksheet = $this->objPHPExcel->createSheet();
$this->objPHPExcel->addSheet($objWorksheet);
} else {
$this->objPHPExcel->setActiveSheetIndex($index);
$objWorksheet = $this->objPHPExcel->getActiveSheet();
}
//write the worksheet
$col = 0;
$row = 1;
foreach($report as $entry) {
foreach($entry as $key => $value) {
$objWorksheet->setCellValueByColumnAndRow($col, $row, $value);
$col++;
}
$row++;
$col = 0;
}
$objWorksheet->setTitle($repName);
}
Then, back in the action I print out the excel file...
$objWriter = PHPExcel_IOFactory::createWriter($this->objPHPExcel, 'Excel5');
ob_start();
if ( headers_sent() ) die("**Error: headers sent");
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header('Content-Disposition: attachment;filename="simple.xls"');
header("Content-Transfer-Encoding: binary");
ob_clean();
$objWriter->save('php://output');
exit();
When I open the file in Excel, I get the following message...
Excel found unreadable content in 'simple.xls'. Do you want to recover the contents of this workbook?
I click yes. Then get two "Renamed invalid sheet name.' repair error messages. The file contains a worksheet for each iteration, but for everyone after the default sheet, it adds an extra sheet. Why is it creating the extra spreadsheet?
/**
* Create sheet __and add it to this workbook__
*
* #param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
* #return PHPExcel_Worksheet
* #throws Exception
*/
public function createSheet($iSheetIndex = null)
Turns out you don't need the call to addSheet. createSheet() automatically does this for you.
I removed
$this->objPHPExcel->addSheet($objWorksheet);
and it works fine now.

Categories