How can I create a Gantt diagram with phpSpreadSheet? - php

I am using phpSpreadSheet to create a Gantt diagram from a template, but when I complete the template using this library the diagram appears empty. But if I complete the template manually, the diagram appears completed. I have downloaded the template from here
This is my code:
//For documentation creation
require_once '../../vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
//Excel
$inputFileType = 'Xlsx';
$inputFileName = 'files/Cronograma.xlsx';
/** Create a new Reader of the type defined in $inputFileType * */
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
/** Load $inputFileName to a Spreadsheet Object * */
$spreadsheet = $reader->load($inputFileName);
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('C5', 1);
$sheet->setCellValue('D5', 5);
$sheet->setCellValue('E5', 1);
$sheet->setCellValue('F5', 5);
$writer = new Xlsx($spreadsheet);
$excelName = 'test.xlsx';
$writer->save($excelName);
Data manually introduced:
Data introduced by code:

Some parts of the excel features aren't implemented (e.g. format as table, pivot tables).
It would not be so pretty, but you can color single cells/ cellranges in a specific color like
$spreadsheet->getActiveSheet()->getStyle('B3:B7')->getFill()
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
->getStartColor()->setARGB('FFFF0000');
for more information take a look to enter link description here

Related

How do i use Php Spreadsheet with Fat free to read and edit an excel file?

I need to edit a excel file in php. I've got a simple PHP Spreadsheet.
I use fat-free and the problem is
public function MakeExcel()
{
require 'vendor/autoload.php';
use \vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Spreadsheet ;
use \vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Writer\Xlsx ;
$Spreadsheet = new Spreadsheet();
$sheet = $Spreadsheet->getActiveSheet();
$sheet->setCellValue('A3', 'toto');
$writer = new Xlsx($Spreadsheet);
$writer->save("test.xlsx");
$f3->set('CONTENT','views/dashboard/dashboard_liste.html');
$f3->set('CONTENTJS','views/dashboard/dashboard_liste.js');
echo \Template::instance()->render('views/accueil/accueil.html','text/html');
$this->db = null;
}
use doesn't seem to exist in fat-free so i tried:
$f3->use(\vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Spreadsheet);
Or
$f3->use("\vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Spreadsheet");
and many other it return me the error :
ERROR 500 Call to a member function use() on null
Problem Solved thanks everyone :
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
class MakeExcel extends Controller {
public function MakeExcel(){
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', 'Hello World !');
$writer = new Xlsx($spreadsheet);
$writer->save('hello world.xlsx');
}
}
First of all seems you use Fat Free wrong. Because $f3 is null.
Second. Probably you are importing classes with wrong namespaces. You can read documentation of PhpSpreadsheet.
Right way:
require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
You can phisically find this classes and look on the namespace.
Put your import of composer autoload and use block outside of this function.
Make sure you ran composet install
Make your function work without PhpSpreadsheet. And after that try to add other functionality
You need to declare those files in php top area
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
Then in method create object for spreadsheet
$spreadsheet = new Spreadsheet();
Then you can define the border and alignment for xls file like that
$cell_st =[
'font' =>['bold' => true],
'alignment' =>['horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER],
'borders'=>['bottom' =>['style'=> \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN],'top' =>['style'=> \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN]]
];
To Define the Header you can use below code
$spreadsheet->setActiveSheetIndex(0)->mergeCells('A2:D2');
$spreadsheet->setActiveSheetIndex(0)->setCellValue('A2', "<YOUR HEADER>");
$spreadsheet->getActiveSheet()->getStyle('A2:D2')->applyFromArray($cell_st);
And Then define the column names
$spreadsheet->setActiveSheetIndex(0)
->setCellValue('A3', 'ID')
->setCellValue('B3', 'NAME')
->setCellValue('C3', 'CITY')
->setCellValue('D3', 'SALARY');
After all above code now you can start your content in loop like that
$rowcount = 4;
foreach($data_array as $key=>$value){
$spreadsheet->setActiveSheetIndex(0)
->setCellValue('A'.$rowcount, $value['id'])
->setCellValue('B'.$rowcount, $value['name'])
->setCellValue('C'.$rowcount, $value['city'])
->setCellValue('D'.$rowcount, $value['salary']);
$rowcount++;
}
and in last now make object of the Xlsx class to save the excel file
$writer = new Xlsx($spreadsheet);
$file_name = "report.xls';
$file_root_path = "assets/reports/xls/".$file_name;
$file_site_path = "localhost/xls_generate/assets/reports/xls/".$file_name;
$writer->save($file_root_path);
// final xls file path is here
echo $file_site_path;
That's all, Hope this work for you..

PhpSpreadSheet : Writing to a specific WorkSheet

I'm new to PhpSpreadSheet, and I'd like to know if there is a way to load a CSV into a specific WorkSheet ?
I tried the code bellow but it seems to keep loadind the CSVs into the first WorkSheet :/.
<?php
require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Reader\Csv;
$spreadsheet = new Spreadsheet();
$spreadsheet->setActiveSheetIndex(0);
$pathToCsv1 = 'files/csv_files/1.csv';
$pathToCsv2 = 'files/csv_files/2.csv';
$pathToCsv3 = 'files/csv_files/3.csv';
$pathToCsv4 = 'files/csv_files/4.csv';
$aCsvFiles = array($pathToCsv1, $pathToCsv2, $pathToCsv3, $pathToCsv4);
foreach ($aCsvFiles as $index => $csvFile) {
$reader = new Csv();
$reader->setDelimiter(';');
$reader->loadIntoExisting($csvFile, $spreadsheet);
$workSheet = $spreadsheet->createSheet();
$spreadsheet->setActiveSheetIndex($index + 1);
}
$writer = new Xlsx($spreadsheet);
$writer->save('files/xls_files/all.xlsx');
I only get 4.csv in all.xlsx but i have the created WorkSheets
Combining Multiple Files into a Single Spreadsheet Object
While you can limit the number of worksheets that are read from a
workbook file using the setLoadSheetsOnly() method, certain readers also
allow you to combine several individual "sheets" from different files
into a single Spreadsheet object, where each individual file is a
single worksheet within that workbook. For each file that you read, you
need to indicate which worksheet index it should be loaded into using
the setSheetIndex() method of the $reader, then use the
loadIntoExisting() method rather than the load() method to actually read
the file into that worksheet.
Example:
$inputFileType = 'Csv';
$inputFileNames = [
'./sampleData/example1.csv',
'./sampleData/example2.csv'
'./sampleData/example3.csv'
];
/** Create a new Reader of the type defined in $inputFileType **/
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
/** Extract the first named file from the array list **/
$inputFileName = array_shift($inputFileNames);
/** Load the initial file to the first worksheet in a `Spreadsheet` Object **/
$spreadsheet = $reader->load($inputFileName);
/** Set the worksheet title (to the filename that we've loaded) **/
$spreadsheet->getActiveSheet()
->setTitle(pathinfo($inputFileName,PATHINFO_BASENAME));
/** Loop through all the remaining files in the list **/
foreach($inputFileNames as $sheet => $inputFileName) {
/** Increment the worksheet index pointer for the Reader **/
$reader->setSheetIndex($sheet+1);
/** Load the current file into a new worksheet in Spreadsheet **/
$reader->loadIntoExisting($inputFileName,$spreadsheet);
/** Set the worksheet title (to the filename that we've loaded) **/
$spreadsheet->getActiveSheet()
->setTitle(pathinfo($inputFileName,PATHINFO_BASENAME));
}
Note that using the same sheet index for multiple sheets won't append files into the same sheet, but overwrite the results of the previous load. You cannot load multiple CSV files into the same worksheet.
https://phpspreadsheet.readthedocs.io/en/develop/topics/reading-files/#combining-multiple-files-into-a-single-spreadsheet-object

Unable to convert an excel to pdf using php

I have installed PhpSpreadsheet and dompdf successfully using composer.
My requirement is that I need to convert an excel sheet into pdf, I got it working using the default settings, this is the code I have used.
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Writer\Csv;
use PhpOffice\PhpSpreadsheet\Exception;
use PhpOffice\PhpSpreadsheet\IOFactory;
use \PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf;
$spreadsheet = new Spreadsheet();
try {
$sheet = $spreadsheet->getActiveSheet();
// code to fill in the data
$spreadsheet->getActiveSheet()->fromArray(
$data, // The data to set
NULL, // Array values with this value will not be set
'A2' // Top left coordinate of the worksheet range where
);
} catch (Exception $e) {
}
$writer = new Xlsx($spreadsheet);
try {
IOFactory::registerWriter("PDF", Dompdf::class);
$pdfwriter = IOFactory::createWriter($spreadsheet, 'PDF');
$pdfwriter->save($filepath . 'pdf_test.pdf');
} catch (\PhpOffice\PhpSpreadsheet\Writer\Exception $e) {
}
I have skipped out code for brevity, this code works fine and generates a pdf file, I require the pdf to be printed in landscape mode, for that the docs mention a Custom implementation or configuration of the pdf library, so I created a file called PDFBase_DOMPDF that looks like this
use Dompdf\Dompdf;
class PDFBase_DOMPDF extends Dompdf
{
}
And I have created a file called PDFBase_Writer that looks like this.
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf;
class PDFBase_Writer extends Dompdf
{
protected function createExternalWriterInstance()
{
$instance = new PDFBase_DOMPDF();
$instance->setPaper('A4', 'landscape');
return $instance;
}
}
I modified the original code to use the new pdf class so the line changed to this.
IOFactory::registerWriter("PDF", PDFBase_Writer::class);
The problem is I get an exception with the following error
Registered writers must implement PhpOffice\PhpSpreadsheet\Writer\IWriter
How exactly do I fix this?
Reading and writing to a persisted storage is not possible using the base PhpSpreadsheet classes. For this purpose, PhpSpreadsheet provides readers and writers, which are implementations of \PhpOffice\PhpSpreadsheet\Reader\IReader and \PhpOffice\PhpSpreadsheet\Writer\IWriter.
You must load the Excel file like this:
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
$reader->setReadDataOnly(true);
$spreadsheet = $reader->load("TestRead.xlsx");
Registered writers must implement PhpOffice\PhpSpreadsheet\Writer\IWriter
PHPSpreadsheet Writer classes must implement all the methods defined in the IWriter interface. You're creating a new Writer, so it needs to provide an implementation of all those methods:
interface IWriter
{
/**
* IWriter constructor.
*
* #param Spreadsheet $spreadsheet
*/
public function __construct(Spreadsheet $spreadsheet);
/**
* Save PhpSpreadsheet to file.
*
* #param string $pFilename Name of the file to save
*
* #throws \PhpOffice\PhpSpreadsheet\Writer\Exception
*/
public function save($pFilename);
}
So your Writer needs to implement a constructor that accepts a Spreadsheet object as an argument, and a save() method that accepts a filename (as a string) argument.

PHPExcel Reading CSV Reading values incorrectly, values having special characters

I am having hard time to read values form CSV correctly, the values are being fetched but the values contains special characters e. g �5�0�0�0�.
I have to perform some calculations on the values. Casting it to float/int didn't worked.
This is how i am doing it.
$inputFileName=$this->fileName;
/** Include PHPExcel_IOFactory */
$included=require_once __SITE_PATH.DS.'assets'.DS.'script'.DS.'PHPExcel'.DS.'PHPExcel'.DS.'IOFactory.php';
if( empty($included) )
{
header('HTTP/1.1 400 Bad Request',true,400);
echo 'xml lib not found';
return false;
}
/** Load $inputFileName to a PHPExcel Object **/
//$objPHPExcel = PHPExcel_IOFactory::load($inputFileName);
/** Identify the type of $inputFileName **/
$inputFileType = PHPExcel_IOFactory::identify($inputFileName);
/** Create a new Reader of the type that has been identified **/
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
/** Advise the Reader that we only want to load cell data **/
$objReader->setReadDataOnly(true);
/** Advise the Reader of which WorkSheets we want to load **/
//$objReader->setLoadSheetsOnly($sheetname);
/** Load $inputFileName to a PHPExcel Object **/
$this->fileHandler = $objReader->load($inputFileName);
/*get the worksheet*/
$objWorksheet = $this->fileHandler->getSheet(0);
$this->eXjobs=$objWorksheet->toArray(null,true,true,true);
Now when i loop $this->eXjobs & var_dump() the values i can see the special characters.
any help will be much appreciate.

how to speed up PHPExcel reader

HI all expert i am newbie in php.
can anyone tell me to speed up PHPExcel and this is my code ,it read 20000 rows with 4 columns . it take more than 15s. thank you so much
function upload_fl($FILES){
$file = $FILES['excel'];
//echo getcwd();
//print_r($file);
require 'phpexcel/PHPExcel.php';
if(move_uploaded_file($file['tmp_name'],'C:/wamp/www/datatable_017/php/upload/'.$file['name'])){
$data = '../php/upload/'.$file['name'];
$objPHPExcel = PHPExcel_IOFactory::load($data);
$sheetData = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
//var_dump($sheetData);
echo sizeof($sheetData);
//$writefile = fopen($FILES['excel']['name'].'.txt','w');
/*
foreach($sheetData as $row){
foreach($row as $col->$value){
//$value_inser = (is_numeric($value) == true ? ''number',''.$value.'',''':''text','',''.$value.''');
//fwrite($writefile,$cate_set_id[$col].','.$com_id.','.$year.','.$value_insert.'\n');
}
}
-->
fclose($writefile);
*/
return 'upload/'.$file['name'].'.txt';
}else{
return 'upload failed';
}
}//function
If you have multiple worksheets, but don't need to load all of them, then you can limit the worksheets that the Reader will load using the setLoadSheetsOnly() method. To load a single named worksheet:
$inputFileType = 'Excel5';
$inputFileName = './sampleData/example1.xls';
$sheetname = 'Data Sheet #2';
/** Create a new Reader of the type defined in $inputFileType **/
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
/** Advise the Reader of which WorkSheets we want to load **/
$objReader->setLoadSheetsOnly($sheetname);
/** Load $inputFileName to a PHPExcel Object **/
$objPHPExcel = $objReader->load($inputFileName);
Or you can specify several worksheets with one call to setLoadSheetsOnly() by passing an array of names:
$inputFileType = 'Excel5';
$inputFileName = './sampleData/example1.xls';
$sheetnames = array('Data Sheet #1','Data Sheet #3');
/** Create a new Reader of the type defined in $inputFileType **/
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
/** Advise the Reader of which WorkSheets we want to load **/
$objReader->setLoadSheetsOnly($sheetnames);
/** Load $inputFileName to a PHPExcel Object **/
$objPHPExcel = $objReader->load($inputFileName);
If you only need to access part of a worksheet, then you can define a Read Filter to identify just which cells you actually want to load:
$inputFileType = 'Excel5';
$inputFileName = './sampleData/example1.xls';
$sheetname = 'Data Sheet #3';
/** Define a Read Filter class implementing PHPExcel_Reader_IReadFilter */
class MyReadFilter implements PHPExcel_Reader_IReadFilter {
public function readCell($column, $row, $worksheetName = '') {
// Read rows 1 to 7 and columns A to E only
if ($row >= 1 && $row <= 7) {
if (in_array($column,range('A','E'))) {
return true;
}
}
return false;
}
}
/** Create an Instance of our Read Filter **/
$filterSubset = new MyReadFilter();
/** Create a new Reader of the type defined in $inputFileType **/
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
/** Advise the Reader of which WorkSheets we want to load
It's more efficient to limit sheet loading in this manner rather than coding it into a Read Filter **/
$objReader->setLoadSheetsOnly($sheetname);
echo 'Loading Sheet using filter';
/** Tell the Reader that we want to use the Read Filter that we've Instantiated **/
$objReader->setReadFilter($filterSubset);
/** Load only the rows and columns that match our filter from $inputFileName to a PHPExcel Object **/
$objPHPExcel = $objReader->load($inputFileName);
If you don't need to load formatting information, but only the worksheet data, then the setReadDataOnly() method will tell the reader only to load cell values, ignoring any cell formatting:
$inputFileType = 'Excel5';
$inputFileName = './sampleData/example1.xls';
/** Create a new Reader of the type defined in $inputFileType **/
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
/** Advise the Reader that we only want to load cell data, not formatting **/
$objReader->setReadDataOnly(true);
/** Load $inputFileName to a PHPExcel Object **/
$objPHPExcel = $objReader->load($inputFileName);
although note that reading only the raw data like this won't allow you to differentiate between date values and floats
If you want to work with large Excel files, don't build a large PHP array in memory by making that toArray() call, because that's a big overhead in memory usage, and there's also a big cost in performance with the constant need to allocate more and more memory as the array is built..... if you're going to process a row at a time, use the iterators built into PHPExcel, or just use a loop to access each individual row in turn.

Categories