Checkbox processing with PHPexcel Output - php

This my script...
$students=isset ($_POST['students']) ? $_POST['students'] : '';
for($i = 1; $i <= $students; $i++)
{
$student = isset ($_POST['student'.$i]) ? $_POST['student'.$i]: '';
$nilai= mysql_query ("SELECT * FROM student,s_semester where
student.id=s_semester.student_id_fk AND student.id='$student' GROUP by student.id");
$rowNya = 2;
$no = 0;
while ($data=mysql_fetch_array($nilai)) {
$no = $no +1;
$objPHPExcel->setActiveSheetIndex(0)
->setCellValue("A$rowNya", $no)
->setCellValue("B$rowNya", $student)
->setCellValue("C$rowNya", $data['idcard'])
->setCellValue("D$rowNya", $data['status']);
$rowNya = $rowNya + 1;
}
// Rename sheet
$objPHPExcel->getActiveSheet()->setTitle('Simple');
}
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="database_anggota.xls"');
header('Cache-Control: max-age=0');
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
$objWriter->save('php://output');
exit;
And my problem is, the excel output only one record of data that appears, i use checkbox before.. I check 3/4/5 or etc only 1 appears... If the output pdf and i use FPDF this script runnning well..
please help me...

Move $rowNya = 2; to before the for loop, otherwise it's being reset for each student id... otherwise you're resetting it to 2 after each student, so it'll overwrite the previous student details

Related

PhpSpreadsheet - Download file instead of saving it

I need to generate an excel file (xls) and trigger the download after it is generated.
I found this example in the documentation.
<?php
require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', 'Hello World !');
$writer = new Xlsx($spreadsheet);
$writer->save('hello world.xlsx');
It shows how to create a excel file and save it on the server.
How can I serve the result to the client instead and "force" him to download it?
I need to get the data of the $writer somehow.
I am currently solving it without PhpSpreadsheet:
// Excel Export
$filename = 'export_'.date('d-m-y').'.xls';
$filename = $validator->removeWhitespace($filename);
header('Content-type: application/ms-excel');
header('Content-Disposition: attachment; filename='.$filename);
exit($response["output"]); // <-- contains excel file content
But it is not working with my delimiter (semicolon). The semicolon is not getting interpreted and everything is getting written into one column.
If I export it as .csv, then it works. But I need it as .xls or .xlsx
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
class DownloadExcel
{
public static function createExcel(array $data, array $headers = [],
$fileName = 'data.xlsx')
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
for ($i = 0, $l = sizeof($headers); $i < $l; $i++) {
$sheet->setCellValueByColumnAndRow($i + 1, 1, $headers[$i]);
}
for ($i = 0, $l = sizeof($data); $i < $l; $i++) { // row $i
$j = 0;
foreach ($data[$i] as $k => $v) { // column $j
$sheet->setCellValueByColumnAndRow($j + 1, ($i + 1 + 1), $v);
$j++;
}
}
$writer = new Xlsx($spreadsheet);
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment; filename="'. urlencode($fileName).'"');
$writer->save('php://output');
}
}
This is what I use to create a spreadsheet with PhpSpreadsheet and output directly to php://output for download.
I had the same problem and found a solution here : https://github.com/PHPOffice/PhpSpreadsheet/issues/217
I ended my method with $writer->save('php://output'); then exit()
My answer :
PHP:
$writer = new Xlsx($spreadsheet);
ob_start();
$writer->save('php://output');
$ret['data'] = base64_encode(ob_get_contents());
ob_end_clean();
JS:
var linkSource = 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,'+ response.data ;
var downloadLink = document.createElement("a");
var fileName = 'clients.' + format;
downloadLink.href = linkSource;
downloadLink.download = fileName;
downloadLink.click();
I solved it with a workaround. I temporarily save the file on the server, then I load the content into a variable and serve it as a download file. Then I delete the file from the server.
Workaround:
$date = date('d-m-y-'.substr((string)microtime(), 1, 8));
$date = str_replace(".", "", $date);
$filename = "export_".$date.".xlsx";
try {
$writer = new Xlsx($response["spreadsheet"]);
$writer->save($filename);
$content = file_get_contents($filename);
} catch(Exception $e) {
exit($e->getMessage());
}
header("Content-Disposition: attachment; filename=".$filename);
unlink($filename);
exit($content);
call ob_end_clean(); just before the $writer->save('php://output').
ob_end_clean();
$writer->save('php://output');
This worked for me:
$excel = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$sheet = $excel->getActiveSheet();
$sheet->setTitle('This is a test', true);
ob_end_clean();
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="filename_' . time() . '.xlsx"');
header('Cache-Control: max-age=0');
$xlsxWriter = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($excel, 'Xlsx');
$xlsxWriter = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($excel);
exit($xlsxWriter->save('php://output'));
If you have problems where the files download corrupted, it is always good to check if there is any extra whitespace at the top of your file output. If your PHP files have blank white lines, whilst HTML won't have a problem, your phpspreadsheet file will. Spent a good chunk of time trying to fix these issues but the problem was with the whitespace!

PHPExcel Blank Screen

A lot of posts have been made on this particular case, I've gone through post on stackoverflow to ascertain why PHPExcel doesn't show a download dialog after exporting database data with the given code as shown:
// PHPExcel Code
$query = $this->reports_m->payreport_yr($yr,true);
if(!$query)return false;
$fields = $query->list_fields();
$this->excel->getProperties()->setTitle("Excel Export")->setDescription("Payment Report Excel Document");
$this->excel->getActiveSheet()->mergeCells('A1:D1');
//$this->excel->setActiveSheetIndex(0)->mergeCells('A1:D1');
//$this->excel->getActiveSheet()->getCell('A1')->setValue('This is the text that I want to see in the merged cells');
//$this->excel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
//activate worksheet number 1
$this->excel->setActiveSheetIndex(0);
$col = 0;
foreach ($fields as $field)
{
$this->excel->getActiveSheet()->setCellValueByColumnAndRow($col, 1, $headers[$field]);
$col++;
}
$first_letter = PHPExcel_Cell::stringFromColumnIndex(0);
$last_letter = PHPExcel_Cell::stringFromColumnIndex(count($fields)-1);
$header_range = "{$first_letter}1:{$last_letter}1";
$this->excel->getActiveSheet()->getStyle($header_range)->getFont()->setBold(true);
$this->excel->getActiveSheet()->getStyle($header_range)->getFont()->setSize(16);
// Fetching the table data
$row = 2;
foreach($query->result() as $data){
$col = 0;
foreach ($fields as $field)
{
$this->excel->getActiveSheet()->setCellValueByColumnAndRow($col, $row, $data->$field);
$col++;
}
$row++;
}
$this->excel->setActiveSheetIndex(0);
$filename=$yr.'taxPaymentReport.xlsx'; //Save The worksheet With This File Name
header('Content-Type: application/vnd.ms-excel'); //Mime Type For Excel2005
header('Content-Disposition: attachment;filename="'.$filename.'"');
header('Cache-Control: max-age=0'); //no cache
$objWriter = PHPExcel_IOFactory::createWriter($this->excel, 'Excel2007');
$objWriter->save('php://output');
I have tried changing the headers to see if i could get results but to no avail. Can someone with a better understanding tell me what am doind wrong?

PHPExcel Clone Worksheet - Efficient use of memory

I need to clone the first worksheet a few times, accordingly to the amount of rows, but something may be wrong.
The code is:
public function downloadFile()
{
date_default_timezone_set('America/Sao_Paulo');
if(file_exists("xpto.xlsx")){
$objPHPExcel = PHPExcel_IOFactory::load("xpto.xlsx");
$sheets = 3;//3 is enough to throw the error
for($i = 0; $i<$sheets; $i++){
$objClonedWorksheet = clone $objPHPExcel->getSheet(0);
$objClonedWorksheet->setTitle('Sheet ' . $i);
$objClonedWorksheet->setCellValue('A1', 'Test ' . $i);
$objPHPExcel->addSheet($objClonedWorksheet);
}
$objPHPExcel->setActiveSheetIndex(0);
$filename = 'file.xlsx';
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="'.$filename.'"');
header('Cache-Control: max-age=0');
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
ob_end_clean();
$ret = $objWriter->save('php://output');
exit;
}
}
But I got an exhausted memory error. Than I tried the most commented solution (that is actually an workaround) that is to add
ini_set('memory_limit', '-1');
I added this line just after the load function and it worked, but I don't think it is a good solution to use on a SaaS application. I don't even think most hosts (AWS, for example) will allow me to use that.
I also tried to clone the sheet before the for loop, but when use addSheet, I realized that this function doesn't create a new object and when I change the name of the sheet (by the second iteration of the for loop), it changes the last sheet created, throwing an "already existing sheet with the same name" error.
Trying to use one of the links #rhazen listed, I changed the for loop to:
$objFromSheet = $objPHPExcel->getSheet(0);
$sheets = 3;
for($i = 1; $i<=$sheets; $i++){
$objToSheet = $objPHPExcel->createSheet($i);
foreach($objFromSheet->getRowIterator() as $row){
$cellIterator = $row->getCellIterator();
$cellFrom = $cellIterator->current();
$cellTo = $objToSheet->getCell($cellFrom->getCoordinate());
$cellTo->setXfIndex($cellFrom->getXfIndex());
$cellTo->setValue($cellFrom->getValue());
}
}
But it seems not to work either. Is there a misunderstanding about Iterator or XfIndex?
The solution is in the edited question. Thanks for those who helped.

phpexcel getattribute node no longer exists

I have the following script
$this->load->library('excel');
$filename = FCPATH.'assets/template/monthly_report.xlsx';
$filetype = PHPExcel_IOFactory::identify($filename);
$objReader = PHPExcel_IOFactory::createReader($filetype);
$objReader->setIncludeCharts(TRUE);
$this->objExcel = $objReader->load($filename);
$this->objExcel->setActiveSheetIndex(0);
$sheet = $this->objExcel->getActiveSheet();
$sheet->setCellValue('A3', $process->process_name);
$last_num = 2; // row terakhir
$last_num_counter = 2; // row terakhir untuk counter
for($i = 4; $i <= $date_max + 3; $i++){
$cell = $this->translate_cell($i);
$sheet->setCellValue($cell.'2', date(($i - 3).'-M'));
}
foreach($schedules as $schedule){
}
$filename='Laporan Bulanan.xlsx';
header('Content-Type: application/vnd.ms-excel'); //mime type
header('Content-Disposition: attachment;filename="'.$filename.'"'); //tell browser what's the file name
header('Cache-Control: max-age=0'); //no cache
// PHPExcel_Settings::setZipClass(PHPExcel_Settings::PCLZIP);
$objWriter = PHPExcel_IOFactory::createWriter($this->objExcel, $filetype); //Excel2007
$objWriter->setIncludeCharts(TRUE);
$objWriter->save('php://output');
the script is loading an xlsx file as a template, the template itself contain a graph/chart. so, all I have to do is replace data in cells and then save it, without any touch to the chart stuff and then save it. but, it produce error in the begining of the generated xlsx file, it said
<p>Severity: Warning</p>
<p>Message: PHPExcel_Reader_Excel2007_Chart::getAttribute(): Node no longer exists</p>
<p>Filename: Excel2007/Chart.php</p>
<p>Line Number: 40</p>
I have no idea about that error, please somebody save my day.

PHPExcel Set cell with variable

I have this test script that is acting just like my production script except production script pulls from a SQL db. I want to set the cell placement using a variable based off the count of an array. In the script below, (which you can copy and run as an example) I want to set the cell number based off how many of the same car that is in an array. So for an example there are 7 BMW's listed in the array. So I want the Comments: data copied to cell A12 using the code $num=$no+5; $cell='A'.$num;
The problem I am having is it does place it on that line but it also places it 7 more times about it. If there are 4 cars of that type it would place it on the right line but also place it 3 times above it. I just want it to place it once at the desired location. Any help would be great. Here is the code:
<?PHP
require_once 'Classes/PHPExcel.php';
include 'Classes/PHPExcel/Writer/Excel2007.php';
$dataArray= array();
$cars=array("Versa","Volt","Volt","Volt","Volt","Volkswagen","Bentley","Benz","BMW","BMW","BMW","BMW","BMW","BMW","BMW","Cobra","Cord","Daewoo","Datsun","Dodge","Dodge","Dixi");
$objPHPExcel = new PHPExcel();
$objPHPExcel->setActiveSheetIndex(0);
while (list($var, $val) = each($cars)) {
if ($val!=$id){
$dataArray = array();
$objWorksheet = new PHPExcel_Worksheet($objPHPExcel);
$objPHPExcel->addSheet($objWorksheet);
$objWorksheet->setTitle(''. $val);
$row_array[$val] = $val;
array_push($dataArray,$row_array);
$no = count($dataArray);
$num=$no+5;
$cell='A'.$num;
$objWorksheet->setCellValue('A1' , $no);
$objWorksheet->setCellValue('A2' , $val);
$objWorksheet->setCellValue($cell , 'Comments:');
$id = $val;
}
else {
$row_array[$val] = $val;
$count=count($cars);
$count2=count($loc);
array_push($dataArray,$row_array);
$no = count($dataArray);
$num=$no+5;
$cell='A'.$num;
$objWorksheet->setCellValue('A2' , $no);
$objWorksheet->setCellValue('A3' , $val);
$objWorksheet->setCellValue($cell , 'Comments:');
$id = $val;
}
}
// Save Excel 2007 file
#echo date('H:i:s') . " Write to Excel2007 format\n";
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
ob_end_clean();
// We'll be outputting an excel file
header('Content-type: application/vnd.ms-excel');
// It will be called file.xls
header('Content-Disposition: attachment; filename="cars.xlsx"');
$objWriter->save('php://output');
Exit;
?>
This fixes the problem.
<?PHP
require_once 'Excel/PHPExcel.php';//path for my config, rewrite for yours
//include 'Classes/PHPExcel/Writer/Excel2007.php'; // not needed, lazy loader job
$cars=array("Versa","Volt","Volt","Volt","Volt","Volkswagen","Bentley","Benz","BMW","BMW","BMW","BMW","BMW","BMW","BMW","Cobra","Cord","Daewoo","Datsun","Dodge","Dodge","Dixi");
$objPHPExcel = new PHPExcel();
$objWorksheet=$objPHPExcel->setActiveSheetIndex(0);
$id='';
$countRows=0;
while (list($var, $val) = each($cars)) {
if ($val!=$id && $id!=''){
$objWorksheet->setTitle($id);
$num=$countRows+5;
$cell='A'.$num;
$objWorksheet->setCellValue($cell , 'Comments:');
$objWorksheet = new PHPExcel_Worksheet($objPHPExcel);
$objPHPExcel->addSheet($objWorksheet);
$id = $val;
$countRows=0;
}//end if
if($id=='') $id=$val;//the first car
$no = ++$countRows;
$objWorksheet->setCellValue('A'.$no , $no);
$objWorksheet->setCellValue('B'.$no , $id);//Versa, Volt, ...
}
if($countRows>0 && $id!=''){// the last car - if $id=='' the workbook is empty
$objWorksheet->setTitle($id);
$num=$countRows+5;
$cell='A'.$num;
$objWorksheet->setCellValue($cell , 'Comments:');
}//end if
// Save Excel 2007 file
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
ob_end_clean();
// We'll be outputting an excel file
header('Content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); // note : use correct mime type (not xls for xlsx)
// It will be called cars.xlsx
header('Content-Disposition: attachment; filename="cars.xlsx"');
$objWriter->save('php://output');
Exit;
?>

Categories