Merge in excel with phpSpreadSheet - php

I want to merge 2 or more excel with PhpSpreadsheet. I'm trying to keep the styles for each sheet, this is my code:
<?php
require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
$inputFileType = 'Xlsx';
$inputFileNames = [
'a.xlsx',
'b.xlsx',
'c.xlsx'
];
$sheetnames = [
'Worksheet',
'Worksheet1',
'Worksheet2'
];
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
$reader->setLoadSheetsOnly($sheetnames);
$inputFileName = array_shift($inputFileNames);
$spreadsheetMain = $reader->load($inputFileName);
$spreadsheetMain->getActiveSheet()->setTitle('page0');
$contador = 1;
foreach ($inputFileNames as $book => $inputFileName) {
echo ('$inputFileName: ' . $inputFileName) . '</br>';
$spreadsheet = $reader->load($inputFileName);
$clonedWorksheet = clone $spreadsheet->getActiveSheet()->setTitle($inputFileName[0]);
$clonedWorksheet->setTitle('page' . $contador);
$spreadsheetMain->addSheet($clonedWorksheet);
$contador++;
}
$writer = new Xlsx($spreadsheetMain);
$writer->save('prueba1.xlsx');
to do what I want, I need to change this
$spreadsheetMain->addSheet($clonedWorksheet);
for that $spreadsheetMain->addExternalSheet($clonedWorksheet);
But when I execute that code I get the error: 'Sheet does not exist'
I tought it's not still implemented, but is here in the documentation page: https://phpspreadsheet.readthedocs.io/en/develop/topics/worksheets/#copying-worksheets
Here you can download my excels and code for try if you want:
https://drive.google.com/open?id=1qkI8jdYDuA6e5CW6z3k0r_7j1pTvW_6D

The problem with addExternalSheet was that I needed to name both sheets (the original that I load and the cloned Sheet) with the same name. (All files are here : https://drive.google.com/open?id=1qkI8jdYDuA6e5CW6z3k0r_7j1pTvW_6D, mergeSolved is the correct file) This is the code with the solution:
require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
$inputFileType = 'Xlsx';
$inputFileNames = [
'a.xlsx',
'b.xlsx',
'c.xlsx'
];
$sheetnames = [
'Worksheet',
'Worksheet1',
'Worksheet2'
];
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
$reader->setLoadSheetsOnly($sheetnames);
$inputFileName = array_shift($inputFileNames);
$spreadsheetMain = $reader->load($inputFileName);
$spreadsheetMain->getActiveSheet()->setTitle('page0');
$contador = 1;
foreach ($inputFileNames as $book => $inputFileName) {
echo ('$inputFileName: ' . $inputFileName) . '</br>';
$spreadsheet = $reader->load($inputFileName);
$clonedWorksheet = clone $spreadsheet->getSheetByName('Worksheet'.$contador);
$clonedWorksheet->setTitle('Worksheet'.$contador);
$spreadsheetMain->addExternalSheet($clonedWorksheet);
$contador++;
}
$writer = new Xlsx($spreadsheetMain);
$writer->save('prueba1.xlsx');`

require 'vendor/autoload.php';
$lists = [
'flie_01.xlsx',
'flie_02.xlsx'
];
$outfile='/tmp/merge.xlsx';
$merge_spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$merge_spreadsheet->getProperties()->setCreator("act");
foreach($lists as $file){
if(!file_exists($file)){
continue;
}
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader("Xlsx");
$reader->setReadDataOnly(true);
$spreadsheet = $reader->load($file);
foreach($spreadsheet->getSheetNames() as $sheet_name ){
$clonedWorksheet = clone $spreadsheet->getSheetByName($sheet_name);
$clonedWorksheet->setTitle($sheet_name);
$merge_spreadsheet->addSheet($clonedWorksheet);
}
}
$merge_spreadsheet->removeSheetByIndex(0);
$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet,'Xlsx');
$writer->save($outfile);

Related

How to write only active sheet of xlsx file PHPSpreadsheet

i want to show the xlsx file as html, but it always return the first sheet of the file. What i want is to get the writer to show the one active sheet only if there are multiple sheets (name and order of sheet are random).
here is my code :
public function view_excel($path){
$file = realpath(FCPATH)."/uploads/PKB/".$path;
$reader = IOFactory::createReader('Xlsx');
$spreadsheet = $reader->load($file);
// $spreadsheet = $spreadsheet->getActiveSheet();
$writer = IOFactory::createWriter($spreadsheet, 'Html');
$message = $writer->save('php://output');
}
is there a way to do this ? Thanks
i managed to do this :
public function view_excel($path){
$file = realpath(FCPATH)."/uploads/PKB/".$path;
$reader = IOFactory::createReader('Xlsx');
$spreadsheet = $reader->load($file);
$active_sheet = $spreadsheet->getActiveSheet()->getTitle();
$reader->setLoadSheetsOnly($active_sheet); //only load active sheet
$worksheet = $reader->load($file);
$writer = IOFactory::createWriter($worksheet, 'Html');
$message = $writer->save('php://output');
}
had to load the file twice
Here you go!
public function view_excel($path){
$file = realpath(FCPATH)."/uploads/PKB/".$path;
$reader = IOFactory::createReader('Xlsx');
$spreadsheet = $reader->load($file);
$writer = IOFactory::createWriter($spreadsheet, 'Html');
-> $writer->setSheetIndex($spreadsheet->getActiveSheetIndex());
$message = $writer->save('php://output');
}

How to remove all merged cells from an Excel file in php?

I have a Excel file like this:
I wrote a code that allows me to extract all the photos from the xlsx file and insert them in a folder.
There are several merged cells in the file and before processing I would like to remove all the merged cells from the Excel file. I tried with $objPHPExcel->setActiveSheetIndex("0")->unmergeCells(); but it doesn't work.
How can I solve my problem?
<?php
//uploaded xlsx file recovery
$xlsx="C:/wamp64/www/Extract_pictures_Excel/xlsx_files/".date('Y_m_d H-i-s')."_file.xlsx";
move_uploaded_file($_FILES["mon_fichier"]["tmp_name"],$xlsx);
require_once 'PHPExcel/Classes/PHPExcel/IOFactory.php';
$objPHPExcel = PHPExcel_IOFactory::load($xlsx);
//Unique name folder for the pictures
$dirname = uniqid();
mkdir("C:/wamp64/www/Extract_pictures_Excel/pictures_folders/$dirname/");
$sheet = $objPHPExcel->getActiveSheet();
//Unmerge all cells
foreach($sheet->getMergeCells() as $cells)
{
$sheet->unmergeCells($cells);
// var_dump($cells);
}
$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel);
$objWriter->save('./unmerged_files/unmerged.xlsx');
//reading the xlsx file
foreach ($sheet->getDrawingCollection() as $drawing ) {
if ($drawing instanceof PHPExcel_Worksheet_MemoryDrawing) {
ob_start();
call_user_func(
$drawing->getRenderingFunction(),
$drawing->getImageResource()
);
$imageContents = ob_get_contents();
ob_end_clean();
switch ($drawing->getMimeType()) {
case PHPExcel_Worksheet_MemoryDrawing::MIMETYPE_PNG :
$extension = 'png'; break;
case PHPExcel_Worksheet_MemoryDrawing::MIMETYPE_GIF:
$extension = 'gif'; break;
case PHPExcel_Worksheet_MemoryDrawing::MIMETYPE_JPEG :
$extension = 'jpg'; break;
}
} else {
$zipReader = fopen($drawing->getPath(),'r');
$imageContents = '';
while (!feof($zipReader)) {
$imageContents .= fread($zipReader,1024);
}
fclose($zipReader);
$extension = $drawing->getExtension();
$chemin = "C:/wamp64/www/Extract_pictures_Excel/pictures_folders/$dirname/";
}
//retrieving cell values for the images name
$row = (int) substr($drawing->getCoordinates(), 1);
//Condition to read merged cell
$stylecode = $sheet->getCell('H'.$row)->getValue();
$colorcode = $sheet->getCell('E'.$row)->getValue();
$finalname = $stylecode.'_'.$colorcode;
$myFileName = $chemin.$finalname.'.'.$extension;
file_put_contents($myFileName, $imageContents);
}
?>
I have changed the library to PhpOffice\PhpSpreadsheet because PHPExcel is outdated.
require_once './vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
$xlsx = './test/catalogmtnwr2021202009210323241.xlsx';
$spreadsheet = IOFactory::load($xlsx);
$sheet = $spreadsheet->getActiveSheet();
Now I am testing what is merged and unmerge it
echo 'before unmerge: ', count($sheet->getMergeCells()), PHP_EOL;
foreach($sheet->getMergeCells() as $cells)
$sheet->unmergeCells($cells);
echo 'after unmerge: ', count($sheet->getMergeCells()), PHP_EOL;
before unmerge: 678
after unmerge: 0
And at last write back into file
$writer = new Xlsx($spreadsheet);
$writer->save('./test/unmerged.xlsx');
This unmerged the cells as expected

PHPEXCel Read only one sheet to Array

I am using PHPExcel to only read values from excel sheets
if i use this code , it works fine without no problem:
function ReadUploadedFile($Uploadedfile,$fileExtension)
{
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<=100) {
if (in_array($column,range('A','Z'))) {
return true;
}
}
return false;
}
}
}
$filterSubset = new MyReadFilter();
$inputFileType="";
$inputFileType = 'Excel5';
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
$objReader->setReadFilter($filterSubset);
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load('myExcelsheet.xls');
$sheetData = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
$sheetData now is an array and i can use it with no problem.
what if i have many worksheets ,and i need to specify only one , as per documentation from PHPEXCEL , they say to use setLoadSheetsOnly()
i try the code blow but it doesn't work.
$inputFileType = 'Excel2007';
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
$objReader->setReadFilter($filterSubset);
$objReader->setReadDataOnly(true);
$objReader->setLoadSheetsOnly("Summary"); //my worksheet name is Summary
$objPHPExcel = $objReader->load('myExcelsheet.xlsx');
so what should i write after the above line to convert this object to Array
i try this
$sheetData = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
but it gives this error
Call to a member function cellExists() on a non-object
and when i try this
$sheetData = $objPHPExcel->toArray(null,true,true,true);
Call to undefined method PHPExcel::toArray()
/** Here is my code work: */
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '<br/>');
/** PHPExcel_IOFactory */
require_once dirname(__FILE__) . '/../Classes/PHPExcel/IOFactory.php';
$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$inputFileType = 'Excel2007';
$inputFileName = 'file.xlsx';
$sheetname = 'mysheey'; // I DON'T WANT TO USE SHEET NAME HERE
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
$objReader->setLoadSheetsOnly($sheetname);
$objPHPExcel = $objReader->load($inputFileName);
$sheetData = $objPHPExcel->getActiveSheet()->toArray(null, true, true, true);
echo ' Highest Column ' . $getHighestColumn = $objPHPExcel->setActiveSheetIndex()->getHighestColumn(); // Get Highest Column
echo ' Get Highest Row ' . $getHighestRow = $objPHPExcel->setActiveSheetIndex()->getHighestRow(); // Get Highest Row
echo "<pre>";
print_r($sheetData);
echo "</pre>";
Work for me.
I'm using: rangeToArray();
"phpoffice/phpspreadsheet": "^1.3"
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
$spreadsheet = $reader->load('report.xlsx');
$worksheet = $spreadsheet->setActiveSheetIndex(0);
$highestRow = $worksheet->getHighestRow();
$highestCol = $worksheet->getHighestColumn();
print_r($worksheet->rangeToArray("A4:$highestCol$highestRow", null, true, false, false));
// If you want to format data e.g. 2450 to 2,450
// You could set rangeToArray parameter at 4 = true

Update .xlsx file

I am using PHPExcel_1.8.0.
I have many input files and I want to read each file and to save them run time into a single output file.
I have tried but the output file is overwriting for each file.
Let me explain in brief:
I have 5 files having records of 5 different employees and I want to put these records in a single file through php. I have set a loop, so the output file is saving only the last employee record due to overwriting.
I want something like append in php.
Here is my code:
<?php
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '<br />');
date_default_timezone_set('Europe/London');
require_once 'index.php';
require_once dirname(__FILE__) . '/Classes/PHPExcel.php';
$dirlist = dirToArray('input');
foreach ($dirlist AS $value) {
$info = new SplFileInfo($value);
$vFileExtension = $info->getExtension();
if ($vFileExtension == 'xlsx' || $vFileExtension == 'xls') {
$inputFileName = "input/".$value;
$objReader = new PHPExcel_Reader_Excel5();
$objPHPExcel = $objReader->load($inputFileName);
$sheetData = $objPHPExcel->getActiveSheet()->toArray(null, true, true, true);
$objPHPExcel = new PHPExcel();
$i = 1;
foreach ($sheetData AS $key => $row) {
foreach ($row AS $index => $rec) {
$objPHPExcel->getActiveSheet()->setCellValue($index . $i, $newtext);
}
$i++;
}
$objDrawing = new PHPExcel_Worksheet_HeaderFooterDrawing();
$objDrawing->setName('PHPExcel logo');
$objDrawing->setPath('./images/phpexcel_logo.gif');
$objDrawing->setHeight(36);
$objPHPExcel->getActiveSheet()->getHeaderFooter()->addImage($objDrawing, PHPExcel_Worksheet_HeaderFooter::IMAGE_HEADER_LEFT);
$objPHPExcel->getActiveSheet()->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE);
$objPHPExcel->getActiveSheet()->getPageSetup()->setPaperSize(PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4);
$objPHPExcel->getActiveSheet()->setTitle('Data');
$objPHPExcel->setActiveSheetIndex(0);
$callStartTime = microtime(true);
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->save("output/result.xlsx");
$callEndTime = microtime(true);
$callTime = $callEndTime - $callStartTime;
$callStartTime = microtime(true);
echo $value . ' has been generated!' . EOL;
}
}
?>

Read only specific sheet

I am trying to read just one sheet from an xls document and I have this:
$objPHPExcel = $objReader->load('daily/' . $fisierInbound);
$objWorksheet = $objPHPExcel->setActiveSheetIndex(0);
foreach ($objPHPExcel->getWorksheetIterator() as $worksheet) {
$worksheetTitle = $worksheet->getTitle();
$highestRow = $worksheet->getHighestRow(); // e.g. 10
$highestColumn = $worksheet->getHighestColumn(); // e.g 'F'
$highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumn);
$dataCalls = $worksheet->getCellByColumnAndRow(2, 2)->getValue();
$dataSubstr = substr($dataCalls, 53);
}
The problem is that it reads all the sheets of the file.
Any ideas?
As described in the PHPExcel User Documentation - Reading Spreadsheet Files document in the /Documentation folder (section 5.2. entitled"Reading Only Named WorkSheets from a File"):
If you know the name of the sheet that you want to read.
$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);
If you don't know the name of the worksheet in advance, you can get a list of all worksheets before loading the file
$inputFileType = 'Excel5';
$inputFileName = './sampleData/example1.xls';
/** Create a new Reader of the type defined in $inputFileType **/
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
/** Read the list of worksheet names and select the one that we want to load **/
$worksheetList = $objReader->listWorksheetNames($inputFileName)
$sheetname = $worksheetList[0];
/** Advise the Reader of which WorkSheets we want to load **/
$objReader->setLoadSheetsOnly($sheetname);
/** Load $inputFileName to a PHPExcel Object **/
$objPHPExcel = $objReader->load($inputFileName);
You can do it easier than getting list of worksheet names:
$objPHPExcel->setActiveSheetIndex(2);
$worksheet = $objPHPExcel->getActiveSheet();
Loads #2 (third) worksheet.
An easiest way for those who is still struggling with this -
//include library
include('path/to/PHPExcel/IOFactory.php');
//load the file
$objPHPExcel = PHPExcel_IOFactory::load('your/path/for/excel/file');
//get the worksheet of your choice by its name
$worksheet = $objPHPExcel->getSheetByName('Name of sheet');
#and your work goes here...
//load library - EXCEL
$this->load->library('excel');
$objPHPExcel = PHPExcel_IOFactory::load('./folder/exceldata.xls');
Individual worksheets can be accessed by name, or by their index position in the workbook. The index position represents the order that each worksheet "tab" is shown when the workbook is opened in MS Excel (or other appropriate Spreadsheet program).
To access a sheet by name, use the getSheetByName() method, specifying the name of the worksheet that you want to access.
//Retrieve the worksheet called 'Worksheet 1'
$objPHPExcel->getSheetByName('Worksheet 1');
To access a sheet by its index, use the getSheet() method.
Note that sheets are indexed from 0.
//Retrieve the **1st 'tab' worksheet** e.g. called 'Sheet 1'
$worksheet = $objPHPExcel->getSheet(0);
//Retrieve the **2nd 'tab' worksheet** e.g. called 'Sheet 2'
$worksheet = $objPHPExcel->getSheet(1);
This all can be achieved by help of #Mark Baker 's PHPExcel Library. Thanks.
// In CodeIgniter Version - 3.1.11
public function upload(){
ini_set('MAX_EXECUTION_TIME', -1);
ini_set('memory_limit', '-1');
if(isset($_FILES["file_upload"]["name"]))
{
require 'vendor/autoload.php';
$path = $_FILES["file_upload"]["tmp_name"];
$object = PHPExcel_IOFactory::load($path);
$db_flag = true;
foreach($object->getWorksheetIterator() as $worksheet)
{
$highestRow = $worksheet->getHighestRow();
$highestColumn = $worksheet->getHighestColumn();
$sheetname = $worksheet->getTitle();
$sheetname = trim($sheetname);
if ($sheetname == "Asset Wise & Location Wise")
{
$db_flag = false;
$db_count = 0;
$this->db->truncate("fi_asset_wise");
$this->load->helper('dt_helper');
$this->db->trans_start();
// get data from excel
for($row=5; $row<=$highestRow; $row++)
{
$asst_categ = trim($worksheet->getCellByColumnAndRow(0, $row)->getCalculatedValue());
if(empty($asst_categ) || strpos(strtoupper($asst_categ), "TOTAL") !== FALSE )
{
continue;
}
$descrip = trim($worksheet->getCellByColumnAndRow(1, $row)->getCalculatedValue());
$rate = trim($worksheet->getCellByColumnAndRow(2, $row)->getCalculatedValue());
$main_head = trim($worksheet->getCellByColumnAndRow(3, $row)->getCalculatedValue());
$sub_head = trim($worksheet->getCellByColumnAndRow(4, $row)->getCalculatedValue());
$gl_code = trim($worksheet->getCellByColumnAndRow(5, $row)->getCalculatedValue());
$asset_code = trim($worksheet->getCellByColumnAndRow(6, $row)->getCalculatedValue());
if(empty($dt_of_sale)) {
$dt_of_sale = null;
}else{
$db_udt = ($dt_of_sale- 25569) * 86400;
$date=date("d-m-Y", $db_udt);
$dt_of_sale = check_format_method($date);
}
$no_of_days = trim($worksheet->getCellByColumnAndRow(26, $row)->getCalculatedValue());
$insert_arr = array(
'asst_categ' => $asst_categ,
'descrip' => $descrip,
'rate' => $rate,
'main_head' => $main_head,
'sub_head' => $sub_head,
'gl_code' => $gl_code,
'asset_code' => $asset_code,
'dt_of_sale' => $dt_of_sale,
'no_of_days' => ($no_of_days >= 0.00 )?$no_of_days:0.00,
'status' => 1,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
);
if(!empty($insert_arr))
{
$this->ass_model->insertData($insert_arr);
++$db_count;
}
}
$this->db->trans_complete();
// Running Transactions Manually
if ($this->db->trans_status() === FALSE){
$this->db->trans_rollback();
} else {
$this->db->trans_commit();
}
}
}
if($db_flag === true)
{
$this->session->set_flashdata('db_error', 'Error !! Invalid Sheet Name. Please enter correct sheetname.');
redirect(site_url('fixed-asset/fixed-asset-register'));
}
if($db_count > 0)
{
$this->session->set_flashdata('db_success', 'Success - Data Inserted Successfully');
redirect(site_url('fixed-asset/fixed-asset-register'));
}
}
}

Categories