I have a question about exporting dojo data grid to excel file. I have made it work with csv file using the dojo exporter and some php code. However, how do I make it to save as excel file. I now about pear and some other libraries, but there has to be similar solution to the one I am using for the csv. Also, when I create my own exporter in dojo, does it need to have something more specific then the code I am using for the csv exporter. Also, what do I need to change in the php code to make it save as xls. The code is below. Thanks a lot in advance.
My dojo exporter:
function exportCsv(){
var g = dijit.byId("grid");
g.exportGrid("csv",{
writerArgs: {
separator: ","
}
}, function(str){
var form = document.createElement('form');
dojo.attr(form, 'method', 'POST');
document.body.appendChild(form);
dojo.io.iframe.send({
url: "csv.php",
form: form,
method: "POST",
content: {exp: str},
timeout: 15000
});
document.body.removeChild(form);
});
}
My php code working with csv:
<?
$time = time();
header("Pragma: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=\"grid_$time.csv\"");
$exportedData = $_POST['exp'];
echo stripslashes($exportedData);
exit;
?>
Here is a nice PHP tool, well suited for the purpose.
http://www.phpclasses.org/package/1919-PHP-Stream-wrapper-to-read-and-write-MS-Excel-files.html
The setup is quite simple, you have most of it setup to passthrough the .csv file as download attachment allready, try the following code.
Conversion of CSV to XLS
First setup files csv-data and classes
require_once "excel.php";
define('_CSV_SEPARATOR_', ',');
// the excel class setsup xlsfile stream writer, point it to a tmp file
$export_file = "xlsfile://tmp/example.xls";
// the csv-contents must be put into an array,
// serialized and sent to the stream
$import_file = "/path/to/CSV_FILE.csv";
$import=explode("\n", file_get_contents($import_file));
// column names should be first line
$header = array_shift($import);
Making sure, everything is looking nicely
$header = explode(_CSV_SEPARATOR_, $header);
for($i = 0; $i < count($header); $i++)
$header[$i] = trim($header[$i]);
Looping lines in remaining contents of csv-data
// rest of text is data, split em up and list them with array indices,
// and associative names as key in the rowdata
$assocData = array();
foreach($import as $line) {
$row = explode(_CSV_SEPARATOR_, $line);
$rowData = array();
$unknowncount = 0;
for($i = 0; $i < count($row); $i++) {
if(!empty($header[$i])) $column = $header[$i];
else $column = 'UNK'.$unknowncount++;
$rowData[$column] = trim($row[$i]);
}
$assocData[]=$rowData;
}
Now, we write data to the export tmp-file and conversion is done
$fp = fopen($export_file, "wb");
if (!is_resource($fp))
{
die("Cannot open $export_file");
}
fwrite($fp, serialize($assocData));
fclose($fp);
Throughputting the outputted tmp-file to client
$export_file = "xlsfile://tmp/example.xls";
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header ("Last-Modified: " . gmdate("D,d M YH:i:s") . " GMT");
header ("Cache-Control: no-cache, must-revalidate");
header ("Pragma: no-cache");
header ("Content-type: application/x-msexcel");
header ("Content-Disposition: attachment; filename=\"" . basename($export_file) . "\"" );
header ("Content-Description: PHP/INTERBASE Generated Data" );
readfile($export_file);
exit;
Good luck and enjoy :D
Related
I am trying to export and download a csv file through php. I have done exactly what was suggested in Export to CSV via PHP
I can see my array dump in the response but the csv file is just not downloading. Please Help.
Here is my code:
function download_send_headers($filename) {
// disable caching
$now = gmdate("D, d M Y H:i:s");
header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
header("Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate");
header("Last-Modified: {$now} GMT");
// force download
Header('Content-Description: File Transfer');
header("Content-Type: application/force-download");
// header("Content-Type: application/octet-stream");
// header("Content-Type: application/download");
// disposition / encoding on response body
header("Content-Disposition: attachment;filename={$filename}");
header("Content-Transfer-Encoding: binary");
}
function array2csv(array &$array)
{
// if (count($array) == 0) {
// return null;
// }
ob_start();
$df = fopen("php://output", 'w');
fputcsv($df, array_keys(reset($array)));
foreach ($array as $row) {
fputcsv($df, $row);
}
fclose($df);
return ob_get_clean();
}
Here is how im using it:
download_send_headers("data_export_" . date("Y-m-d") . ".csv");
echo array2csv($modsucc);
die();
This is javascript function:
function exporttocsv(filter){
var fd = new FormData();
fd.append('filter', filter);
fd.append("form", "export_to_csv");
$.ajax({
url: getBaseURL()+'assets/handler/OrderManagementHandler.php',
type: 'POST',
data: fd,
enctype: 'multipart/form-data',
processData: false,
contentType: false,
})
.done(function(res) {
})
.fail(function() {
});
}
Handler:
case 'export_to_csv':
$controller->exportToCSV($_POST);
break;
Controller:
public function exportToCSV($data){
$filter = $data['filter'];
$mod = new OrderManagementModel();
$modsucc = $mod->exportToCSV($filter);
if($modsucc){
// var_dump(ini_get('output_buffering'));
//var_dump($modsucc);
download_send_headers("data_export_" . date("Y-m-d") . ".csv");
echo array2csv($modsucc);
die();
}
}
Your code not work because you use ajax and you cant download files with ajax itself, simple way is this:
...
if($modsucc){
$file = /* directory */"data_export_" . date("Y-m-d") . ".csv";
$df = fopen(file, 'w');
fputcsv($df, array_keys(reset($array)));
foreach ($array as $row) {
fputcsv($df, $row);
}
fclose($df);
echo $file;
}
...
this will save file, and in your ajax done function:
window.open(res);
this will open new window with address to previously saved file or
window.location.href = res;
this will redirect you to address where the file was saved
to force download you could do it like this:
//force-download.php
if(file_exists($_GET['file'])){
download_send_headers("data_export_" . date("Y-m-d") . ".csv");
echo file_get_contents($_GET['file']); // warning: unsafe !! session for example will be better
}
this will send headers for force download and read data from disk where data was previosly saved and echo them
and in your ajax done function:
window.open('force-download.php?file=' + res);
or
window.location.href = 'force-download.php?file=' + res;
this use address where force download headers will be sent
Another possibility is, change $_POST to $_GET and instead of using ajax just redirect to url and it will work with your old code
Your code work, only think what could be wrong is if your server dont have enabled output buffering and you output something before calling function download_send_headers
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');
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
I can't get the browser to prompt for download. The output gets displayed on the screen instead. I've tried so many other threads regarding this topic on this site but to no avail. I could change the fopen("php://output","w") to fopen("export.csv","w") but that will save a copy of the export.csv file on the server, which I don't want. I want the file to be downloaded on the client without it being saved on the server. Here's my code:
$sql = mysql_query($_SESSION["export-query"]);
$fields = mysql_num_fields($sql);
$header = array();
for ($i = 0; $i < $fields; $i++) {
$header[] = mysql_field_name($sql, $i);
}
$f = fopen("php://output","w");
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename=export.csv');
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate');
fputcsv($f, $header);
while ($row = mysql_fetch_row($sql)) {
fputcsv($f, $row);
}
fclose($f);
Please help! Much appreciated.
Your code is really close to mine, but I have this
header("Content-type: application/vnd.ms-excel");
for the content type. I think this works because browsers know how to handle text/csv but they don't know how to handle excel. It will prompt to download because it doesn't open this type of file itself.
I also don't have "must-revalidate," but I don't think that makes a difference.
EDIT:
Here are my full headers, which have worked 100% of the time. There are minor differences from yours, so maybe one of them is the reason.
header("Content-type: application/vnd.ms-excel");
header("Content-disposition: attachment; filename=".$filename.".csv");
header("Pragma: no-cache");
header("Expires: 0");
EDIT 2:
Judging from your comment on your answer, you are putting all of this code as an ajax call inside a div. The reason that doesn't work is that you can only set headers on the initial call to a page. Setting headers on an ajax call will be ignored.
Here is how my system handles csv generation. Because I needed specific information that could vary between different csv files, I put the name of the generator file into the "action" of a form and provided a submit button:
<form action="thegeneratorpage.php" method="get"><fieldset>
<p>Download [...] in .csv (Excel) form. You can narrow by [...].</p>
<!-- code here that allows users to narrow down what is in the csv -->
<input type="submit" value="Download" />
</fieldset></form>
If the information doesn't vary, you can just do this:
Download CSV
All the code we have been discussing would be on thegeneratorpage.php.
Rather than using the fputcsv function, I would suggest just echoing the rows of the CSV file like so (note that the headers I use are slightly different from yours):
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}");
header("Content-Transfer-Encoding: binary");
while ($row = mysql_fetch_row($sql)) {
// optionally enclose data if necessary
foreach ($row as $k => $v) {
if (strpos($v, ',') !== false) {
$row[$k] = '"' . $v . '"';
}
}
echo implode(',', array_values($row));
}
i have developed reporting system for one website.i have developed script such that my client can export sales data in XLS file with all detail, every thing was working fine, but now i noticed that every generating xls file has blank row at the top,i have not make any change in code, before few days it was not happening. how to remove that blank line from the top
i am using following code to generate xls file:
$str = "No\tOrderId\tFirst Name\tLast Name\tOrder Date\tTime\tAddress\tCity\tState\tZip\tCountry\tPhone\tEmail\tProductId\tProductName\tProductQty\t";
$output = array();
$output[] = $str;
while($row = $res->fetch())
{
$datetime = new DateTime($row['DateTime']);
$date = $datetime->format('Y-m-d');
$time = $datetime->format('H:i:s');
$Country = getCountryName($row['Country']);
$stroutput= $cnt."\t".$row['OrderId']."\t".stripslashes($row['FirstName'])."\t".stripslashes($row['LastName'])."\t".$date."\t".$time."\t".$row['Address1']."\t".$row['City']."\t".$row['State']."\t".$row['Zip']."\t".$Country."\t".$row['Phone']."\t".$row['Email']."\t".$row['ProductId']."\t".$row['ProductName']."\t".$row['ProductQty']."\t";
$output[]=$stroutput;
$cnt++;
}
$filename="CustomReport_".$date33."_".$date55."_".date("mdy-His");
$data = implode("\n", $output);
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$filename.".xls;");
header("Content-Type: application/ms-excel");
header("Pragma: no-cache");
header("Expires: 0");
print "$header\n$data";