I'm trying to export several tables from a database and creating a excel file for each table using PHP. The loop however is "bugged". Instead of creating a new file for each loop it just puts all data into the same file.
The code:
foreach ($pdo->query("SHOW TABLES;") as $allTables) {
$table = $allTables[0];
$allDataStmt = $pdo->prepare("SELECT * FROM $table;");
$allDataStmt->execute();
$fieldcount = $allDataStmt->columnCount();
$col_title = "";
$data = "";
for ($i = 0; $i < $fieldcount; $i++) {
$col = $allDataStmt->getColumnMeta($i);
$column = $col['name'];
$col_title .= '<Cell ss:StyleID="2"><Data ss:Type="String">' . $column . '</Data></Cell>';
}
$col_title = '<Row>' . $col_title . '</Row>';
while ($row = $allDataStmt->fetch(PDO::FETCH_NUM)) {
$line = '';
foreach ($row as $value) {
if ((!isset($value)) or ($value == "")) {
$value = '<Cell ss:StyleID="1"><Data ss:Type="String"></Data></Cell>\t';
} else {
$value = str_replace('"', '', $value);
$value = '<Cell ss:StyleID="1"><Data ss:Type="String">' . $value . '</Data></Cell>\t';
}
$line .= $value;
}
$data .= trim("<Row>" . $line . "</Row>") . "\n";
}
$data = str_replace("\r", "", $data);
header("Content-Type: application/vnd.ms-excel;");
header("Content-Disposition: attachment; filename=" . $table . ".xls");
header("Pragma: no-cache");
header("Expires: 0");
}
}
If I kill the loop after the first iteration it exports the data correctly from ONE table. If I let the loop run it just loads the same file with the data and the file becomes corrupted. I can't even open it in Excel.
What am I missing? Been stuck with this for hours.
Thank you!
What you are attempting with making multiple different attachments in the same HTTP request is not possible. The HTTP protocol does not have support for downloading multiple files. The most common workaround is to put the files in a zip archive for the client to download, so something like this:
$zip = new ZipArchive;
$zip_name = "excel_tables.zip";
if ($zip->open($zip_name, ZipArchive::CREATE|ZipArchive::OVERWRITE) === TRUE) {
foreach ($pdo->query("SHOW TABLES;") as $allTables) {
// (Your logic to build Excel file)
$file_content = $col_title . "\n" . $data;
$file_name = $table . ".xls";
file_put_contents($file_name, $file_content);
// Add file to the zip file
$zip->addFile($file_name);
}
$zip->close();
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename=' . $zip_name);
header("Content-Length: " . filesize($zip_name));
header("Pragma: no-cache");
header("Expires: 0");
ob_clean();
flush();
readfile(__DIR__ . "/" . $zip_name);
}
Related
I have a function in PHP that aims to download a csv file, but there is always a blank line at the start of the file
How to delete the blank line at the beginning of the file
this is my code
$name_file = 'ekspor-kag-bri-' . date('Ym', strtotime($data_pendukung['tgl_trf'])) . '.csv';
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="'.$name_file.'"');
$kata_header = "REKENING;NOMINAL;EMAIL"."\n";
$kata_header .= "tes";
$arr_isi_cell = [];
foreach ($dt_gaji as $row) {
$isi_cell = str_replace("-","",$row->norekening) . ';' . floatval($row->total_gaji) . ';' . 'inayohanes#gmail.com'."\n";
array_push($arr_isi_cell,$isi_cell);
}
$myfile = fopen("php://output", "wb");
fwrite($myfile,$kata_header);
foreach($arr_isi_cell as $line){
// fputcsv($myfile,explode(',',$line),",");
fwrite($myfile,$line);
}
fclose($myfile)
I'm working with Moodle api functions and I want to get all grades for enrolled users in a specific course. The purpose is to print all grades in an excel file. I tried to get the data from gradereport_user_get_grade_items but its not working here is my php code.
<?php
require_once('./curl.php');
$course_id=4;
$domainname = '........'; //paste your domain here
$wstoken = 'e521817f5cf9798926e0563d452b7975';//here paste your getgradetoken
$wsfunctionname = 'gradereport_user_get_grade_items';
$restformat='xml';//REST returned values format
$grade = array( 'courseid' => $course_id , 'user_id'=> $user_id );
$user_grades = array($grade);
$params = array('user_grades' => $user_grades);
//REST CALL
header('Content-Type: text/plain');
$serverurl = $domainname . "/webservice/rest/server.php?wstoken=" . $wstoken . "&wsfunction=" . $wsfunctionname;
$curl = new curl;
//if rest format == 'xml', then we do not add the param for backwardcompatibility with Moodle < 2.2
$restformat = ($restformat == 'json')?'&moodlewsrestformat=' . $restformat:'';
$resp = $curl->post($serverurl . $restformat, $params);
print_r($resp);
//EXCEL
header("Content-Disposition: attachment; filename=\"gradereport.xls\"");
header("Content-Type: application/vnd.ms-excel;");
header("Pragma: no-cache");
header("Expires: 0");
$out = fopen("php://output", 'w');
foreach ($params as $data)
{
if (is_array($data)){
foreach ($data as $v) {
fputcsv($out, $v,"\t");
}
}
}
fclose($out);
?>
Below is my code. I'm getting the data as a string with 2 parts. First part is all about headers for an excel sheet. And the 2nd part is about the actual data. They are separated by a special delimiter.
Again the second part (actual data) is separated with '\n' for each row with each column again divided with delimiter '|'.
Now if i click on download, the excel is being generated after 1 min 20 secs.. Please help me finding the culprit as I'm new to php.
Im using PHPExcel_IOFactory plugin here..
if (!empty($json_decodeArr))
$dataExists = 1;
else
$dataExists = 0;
$service_name = $params['service_name'];
$company_name = $params["company_name"];
$language = $params["language"];
$cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp;
$cacheSettings = array(' memoryCacheSize ' => '32MB');
PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);
// Create new PHPExcel object
$objPHPExcel = new PHPExcel();
if (isset($GLOBALS[$service_name]["TEMPLATE_NAME"]) && $GLOBALS[$service_name]["TEMPLATE_NAME"] != '') {
$template = $GLOBALS[$service_name]["TEMPLATE_NAME"];
$ext = $GLOBALS[$service_name]["TEMPLATE_NAME_EXT"];
$path = $GLOBALS[$service_name]["TEMPLATE_PATH"];
$filepath = $path . $template.$language . "." . $ext;
try {
//load Excel template file
$objPHPExcel = PHPExcel_IOFactory::load($filepath);
} catch(Exception $e) {
die('Error loading file ' . $e -> getMessage());
}
} else {
$template = $GLOBALS["TEMPLATE_BLANK"];
$ext = $GLOBALS[$service_name]["TEMPLATE_BLANK_EXT"];
$path = $GLOBALS["TEMPLATE_BLANKPATH"];
$filepath = $path . $template . "." . $ext;
try {
//load Excel template file
$objPHPExcel = PHPExcel_IOFactory::load($filepath);
} catch(Exception $e) {
die('Error loading file ' . $e -> getMessage());
}
}
$temp_array = array();
//Named Configuration XLS Generation
//Writing Values into the excel sheet
$counter = 0;
$objPHPExcel -> setActiveSheetIndex(1);
$currentSheet = $objPHPExcel -> getActiveSheet();
foreach ($json_decodeArr as $key => $value) {
if ($key == 0) {
$headerNamesArr = explode("|",$GLOBALS[$service_name][$template][0]["HeaderNames"]);
$headerExcelPositionArr = explode("|",$GLOBALS[$service_name][$template][0]["HeaderExcelPosition"]);
$headerDataArr = explode("|",$value);
foreach ($headerNamesArr as $headerName) {
$headerData = getHeaderValue($headerName,$headerDataArr);
$currentSheet -> setCellValue(getHeaderValue($headerName,$headerExcelPositionArr), $headerData);
}
//file_put_contents("testResponse.txt", getHeaderValue('daysleft:',$headerDataArr));
} else {
//$activeWS = "B";
$index = $GLOBALS[$service_name][$template][0]["ROW_START"];
//file_put_contents("testResponse.txt", $GLOBALS[$service_name][$template][0]["COL_START"]);
$rows = explode("\n", $value);
foreach ($rows as $values1) {
$activeWS = $GLOBALS[$service_name][$template][0]["COL_START"];
$rowData = explode("|", $values1);
//file_put_contents("testResponse.txt",$rowData);
foreach ($rowData as $vals) {
$WSName = $activeWS . $index;
$currentSheet -> setCellValue($WSName, $vals);
$activeWS++;
}
$index++;
}
$counter++;
}
}
//$objPHPExcel->removeSheetByIndex($rowStart);
$objPHPExcel -> setActiveSheetIndex(0);
// Redirect output to a client.s web browser (Excel5)
header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
header("Content-Disposition: attachment;filename=" . $filename . ".xlsx");
header("Cache-Control: max-age=0");
// If you"re serving to IE 9, then the following may be needed
header("Cache-Control: max-age=1");
// If you"re serving to IE over SSL, then the following may be needed
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
// Date in the past
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
// always modified
header("Cache-Control: cache, must-revalidate");
// HTTP/1.1
header("Pragma: public");
// HTTP/1.0
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, "Excel2007");
unset($objPHPExcel);
ob_start();
$objWriter -> save("php://output");
ob_flush();
exit ;
For example: Input from user in text area will be as below:
123111_Testingzone
123222_Testinghouse
123333_Testingcity
Output should be in downloaded_file.txt and it should look like as below;
My testname is 123111
My testname is 123222
My testname is 123333
My process:
I try to take multiple input in each line in one textarea in html form. Trying to explode it in PHP and loop it to use it with predefined text and output as file.
HTML CODE:
<!DOCTYPE html>
<html>
<head>
<title>Test/title>
</head>
<header>
<h1>Test_Page</h1>
</header>
<body>
<form action="abc.php" method="post">
<h3>Option1</h3>
Test Name: <textarea name="testname1"></textarea>
<input type="submit" value="Download">
</form>
</body>
</html>
For PHP code, I want only first 6 letters of each line in text area and repeat it as many text enter and output in one file.
PHP CODE:
<?php
$testname = $_POST["testname1"];
$array = explode('\n',$testname);
$filename = "downloaded_file.txt";
$testid = substr("{$array}",0,6);
foreach ($testid as $content)
{
$contenter = "My test name is {$content}";
}
$f = fopen($filename, 'w');
fwrite($f, $contenter);
fclose($f);
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Length: ". filesize("$filename").";");
header("Content-Disposition: attachment; filename=$filename");
header("Content-Type: application/octet-stream; ");
header("Content-Transfer-Encoding: binary");
readfile($filename);
?>
I dont know where my code is wrong and how to correct it? Please help.
The corrected version of your code. Comments inline.
<?php
// Initial input
$testname = $_POST["testname1"];
// Split on newline. You need double quotes here, as escape sequences for special characters like \n are not
// interpreted in single quoted strings
$array = explode("\n",$testname);
// Declare contenter string, outside foreach loop
$contenter = "";
// For each line
foreach ($array as $line)
{
// Take the first 6 characters
$testid = substr($line,0,6);
// Put testid in string, and append it to the $contenter string.
$contenter .= "My test name is {$testid}\n";
}
// Write the whole thing to the file
$filename = "downloaded_file.txt";
$f = fopen($filename, 'w');
fwrite($f, $contenter);
fclose($f);
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Length: ". filesize("$filename").";");
header("Content-Disposition: attachment; filename=$filename");
header("Content-Type: text/plain; ");
readfile($filename);
?>
Use this code for the required result
foreach ($array as $lines) {
$testid = substr($lines,0,6);
$contenter .= "My test name is {$testid}\n";
}
Instead of the following code
$testid = substr("{$array}",0,6);
foreach ($testid as $content)
{
$contenter = "My test name is {$content}";
}
Instead of fopen, fclose, fwrite, I use file_put_contents, as I personally have had issues with fwrite before.
Therefore, this should work;
<?php
$testname = $_POST["testname1"];
$array = explode(PHP_EOL,$testname);
$filename = "downloaded_file.txt";
$testid = substr("{$array}",0,6);
foreach ($array as $val)
{
$arr_contents = explode('_', $val);
$content .= "My " . $arr_contents[1] . " is " . $arr_contents[0] . "\n";
// \n is a newline char.
}
$filename = "downloaded_file.txt";
file_put_contents($filename, $content);
// write to file
?>
$value = $request->get('testname1');
$skuList = explode(PHP_EOL, $value);
foreach ($skuList as $row)
{
$testid = substr("{$row}",0,6);
$contenter = "My testname is {$testid}";
}
Try following code for array loop
foreach ($array as $content) {
$contenter.= "My test name is ".substr($content, 0, 6)."\n";
}
First you split the content:
$array = explode(PHP_EOL,$testname);
Then you loop through it:
foreach($array as $value){
echo $value . '<br>';
}
Now you will see:
123111_Testingzone
123222_Testinghouse
123333_Testingcity
Within the loop, you should split by a delimiter "_".
foreach($array as $key => $value){
$data = explode("_", $value);
if(sizeof($data) == 1){ // make sure the delimiter is found and match the amount of splits, that should be 2 id:name -1.
echo $data[0] . " is the number and " . $data[1] . " is the name<br>";
} else {
die("user did not post data on line '". $key+1 ."' properly.");
}
}
Now you have all the data to store it in your file. And for the complete code:
<?php
$testname = $_POST["testname1"];
$filename = "downloaded_file.txt";
$array = explode('\n',$testname);
$f = fopen($filename, 'w');
foreach($array as $key => $value){
$data = explode("_", $value);
if(sizeof($data) == 1){ // make sure the delimiter is found and match the amount of splits, that should be 2 id:name -1.
fwrite($fh, "My testname is {$data[1]} and the id is {$data[0]}");
} else {
die("user did not post data on line '". $key+1 ."' properly.");
}
}
fclose($fh);
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Length: ". filesize($filename).";");
header("Content-Disposition: attachment; filename=$filename");
header("Content-Type: application/octet-stream; ");
header("Content-Transfer-Encoding: binary");
readfile($filename);
?>
However, you can also just echo the data, instead of saving it to a file and then output it. It is the same, only you dont have to hassle with files. If you do this, make sure the headers are known before the output.
I want to create a CSV file from my data. This is my loop:
foreach($animals as $row) {
$row['species'];
$row['name'];
$row['size']
}
This is how I create my CSV. So far this works:
$country = 'africa';
$newFileName = './files/'.$country.".csv";
$newFileContent = 'here should be my content';
if(file_put_contents($newFileName,$newFileContent)!=false) {
echo "File created (".basename($newFileName).")";
} else {
echo "Cannot create file (".basename($newFileName).")";
}
But I have a problem to create from my loop in a proper CSV format.
With the help of a tutorial I tried this:
$country = 'africa';
$newFileName = './files/'.$country.".csv";
$newFileContent = $animals;
foreach ($animals as $line) {
fputcsv($newFileName,explode(',',$line));
}
if(file_put_contents($newFileName,$newFileContent)!=false) {
echo "File created (".basename($newFileName).")";
} else {
echo "Cannot create file (".basename($newFileName).")";
}
But this is not working.
You need to open your file for writing first and grab the file handle:
$country = 'africa';
$newFileName = "./files/" . $country . ".csv";
$fileHandle = fopen($newFileName,"w"); // Open file for writing
foreach ($animals as $line){
fputcsv($fileHandle, explode(',',$line));
}
fclose($fileHandle); // Make sure we close file after finishing writing to it
Regarding the first foreach loop in your question $animals is an array containing arrays with keys species, name and size.
So you have to change
foreach ($animals as $line){
fputcsv($newFileName,explode(',',$line));
}
to
foreach ($animals as $line){
fputcsv($newFileName, array($line['species'], $line['name'], $line['size']));
}
because $line is already an array and should be exploded.
This is how I've always done it in the past.
$country = 'africa';
$fileName = "./files/" . $country . ".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' );
$headerDisplayed = false;
foreach ( $animals as $line ) {
// Add a header row if it hasn't been added yet
if ( !$headerDisplayed ) {
// Use the keys from $line as the titles
fputcsv($fh, array_keys($line));
$headerDisplayed = true;
}
// Put the data into the stream
fputcsv($fh, $line);
}
// Close the file
fclose($fh);
// Make sure nothing else is sent, our file is done
exit;