Is it possible to import each line of an XLSX file to a row in a PHP array?
You can use PHPExcel which is available here: https://phpexcel.codeplex.com/releases/view/119187
Here is what I use to read either xls or xlsx to an array:
require_once('/path/to/PHPExcel.php');
$filename = "example.xlsx";
$type = PHPExcel_IOFactory::identify($filename);
$objReader = PHPExcel_IOFactory::createReader($type);
$objPHPExcel = $objReader->load($filename);
foreach ($objPHPExcel->getWorksheetIterator() as $worksheet) {
$worksheets[$worksheet->getTitle()] = $worksheet->toArray();
}
print_r($worksheets);
UPDATE / 2022-02-13:
PhpSpreadsheet has been available for a few years now and has replaced PHPExcel. The following code is more or less the same as above with a couple small improvements:
Converted code to a function or method.
Auto detect filetype.
Added ability to specify how null values, formatting and formulas are handled.
Most importantly, call the destructor and clear memory. Without this last step I was running out of memory all the time after loading large files.
/**
* Create a multidimensional array of worksheets from a filename.
*
* #param mixed $nullValue Value returned in the array entry if a cell doesn't exist
* #param bool $calculateFormulas Should formulas be calculated?
* #param bool $formatData Should formatting be applied to cell values?
*
* #return array
*/
function spreadsheet_to_array($nullValue = null, $calculateFormulas = true, $formatData = false) {
$results = [];
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file);
foreach ($spreadsheet->getWorksheetIterator() as $worksheet) {
$results[$worksheet->getTitle()] = $worksheet->toArray($nullValue, $calculateFormulas, $formatData);
}
// save memory
$spreadsheet->__destruct();
$spreadsheet = NULL;
unset($spreadsheet);
return $results;
}
I use this:
include 'simplexlsx.class.php';
$xlsx = #(new SimpleXLSX('myFile.xlsx'));
$data = $xlsx->rows();
You can simplexslx from here.
UPDATE
Apparently the link above doesn't work anymore. You can now use this. (Thanks #Basti)
Problem can be solved using PHPExcel library:
$data = [];
$type = PHPExcel_IOFactory::identify($filepath);
$objReader = PHPExcel_IOFactory::createReader($type);
$objPHPExcel = $objReader->load($filepath);
$rowIterator = $objPHPExcel->getActiveSheet()->getRowIterator();
foreach($rowIterator as $row){
$cellIterator = $row->getCellIterator();
foreach ($cellIterator as $cell) {
$data[$row->getRowIndex()][$cell->getColumn()] = $cell->getCalculatedValue();
}
}
where $filepath - path to your xls or xlsx file.
Yes with phpspreadsheet :
include 'vendor/autoload.php';
if($_FILES["import_excel"]["name"] != '')
{
$allowed_extension = array('xls', 'csv', 'xlsx');
$file_array = explode(".", $_FILES["import_excel"]["name"]);
$file_extension = end($file_array);
if(in_array($file_extension, $allowed_extension))
{
$file_name = time() . '.' . $file_extension;
move_uploaded_file($_FILES['import_excel']['tmp_name'], $file_name);
$file_type = \PhpOffice\PhpSpreadsheet\IOFactory::identify($file_name);
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($file_type);
$spreadsheet = $reader->load($file_name);
unlink($file_name);
$data = $spreadsheet->getActiveSheet()->toArray();
foreach($data as $row)
{
$insert_data = array(
':test1' => $row[0],
':test2' => $row[1],
':test3' => $row[2],
':test4' => $row[3]
);
};
$query = "
INSERT INTO post
( test1, test2, test3, test4)
VALUES
( :test1, :test2, :test3, :test4)
";
$statement = $connect->prepare($query);
$statement->execute($insert_data);
}
echo "succes";
}else{
echo "only xls,csv,xlsx are allowed";
}
With the new version of PHPSpreadSheet you can simply do that :
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
/*...*/
$reader = new Xlsx();
$reader->setReadDataOnly(true);
$spreadsheet = $reader->load('upload/file.xls');
$sheet = $spreadsheet->getSheet($spreadsheet->getFirstSheetIndex());
$data = $sheet->toArray();
Just be careful, you have all cells as value. For exemple, date is converted to int so you need to convert it
You can use NumberFormat to see all converter.
Exemple to convert an int cell to date :
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
/*....*/
//$value is an integer of a cell value
$value = 44823
$stringDate = NumberFormat::toFormattedString($value, 'YYYY-MM-DD');
// 2022-09-19 is displayed
echo $stringDate;
Found here : https://blog.programster.org/phpspreadsheet-read-excel-file-to-array
More information in the documentation : https://phpspreadsheet.readthedocs.io/en/latest/topics/reading-files/ https://phpspreadsheet.readthedocs.io/en/latest/
Source code of NumberFormat : https://phpoffice.github.io/PhpSpreadsheet/classes/PhpOffice-PhpSpreadsheet-Style-NumberFormat.html
<?php
require_once 'SimpleXLSX.php';
if ( $xlsx = SimpleXLSX::parse('pricelist.xlsx') ) {
print_r( $xlsx->rows() );
} else {
echo SimpleXLSX::parseError();
}
?>
SimpleXLSX
Related
I have an Excel file (xlsx) with several pictures
And I have this php script that allows me to extract the photos contained in it, insert them in a folder and rename them according to the name of the cells in front of each photo.
The script works but I would like to start reading the lines from line 5. I tried with $i <= 3 to skip the first 4 lines but this causes a shift in the picture names. How can I solve my problem?
<?php
require_once 'PHPExcel/Classes/PHPExcel/IOFactory.php';
$path = 'C:/wamp64/www/Extract_pictures_Excel/imagetest.xlsx';
$objPHPExcel = PHPExcel_IOFactory::load($path);
$i = 0;
foreach ($objPHPExcel->getActiveSheet()->getDrawingCollection() as $drawing ) {
$i++;
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/images/';
}
$sheet = $objPHPExcel->getActiveSheet();
foreach ($sheet->getDrawingCollection() as $drawing) {
$row = (int)substr($drawing->getCoordinates(), 1);
// retrieve the image data anyway you like
$stylecode = $sheet->getCell('B'.$row)->getValue();
$colorcode = $sheet->getCell('C'.$row)->getValue();
$finalname = $stylecode.'_'.$colorcode;
$myFileName = $chemin.$finalname.'.'.$extension;
file_put_contents($myFileName,$imageContents);
}
}
?>
I think getDrawingCollection() gives you a list of all the drawings on the active sheet, but this list is not directly related to cell coordinates. So skipping some items of this list is not the same as skipping rows.
Not sure how this goes with the old PHPExcel libs, but with current PhpOffice\PhpSpreadsheet, a Drawing or BaseDrawing objects should have their $coordinates property.
Example:
$sheet = $objPHPExcel->getActiveSheet();
foreach ($sheet->getDrawingCollection() as $drawing) {
$row = (int)substr($drawing->getCoordinates(), 1);
// retrieve the image data anyway you like
$stylecode = $sheet->getCell('B'.$row)->getValue();
$colorcode = $sheet->getCell('C'.$row)->getValue();
$finalname = $stylecode.'_'.$colorcode;
...
}
You should parse the $drawing->coordinates in order to retrieve values of it's neighbouring cells.
I am trying to read an excel file that has 03/05/2008 kind of format, but when I read using PhpSpreadsheet, it returns me 2008.0.
Is there a way to get the raw string format of columns instead of converting to float?
try {
$inputFileType = IOFactory::identify($path);
try {
$reader = IOFactory::createReader($inputFileType);
$reader->setReadDataOnly(true);
$valuesSpreadsheet = $reader->load($path);
try {
$spreadsheetArr = $valuesSpreadsheet->getActiveSheet()->toArray();
dd($spreadsheetArr);
}
}
}
Edit: I don't want to get a specific cell and convert it to timestamp like the comments below. I want to get as array ->toArray() but getting all raw string formats.
Take out the $reader->setReadDataOnly(true) line prior to loading the data and the values should be displayed properly. If not you can also try the following code.
$path = 'yourPath';
try {
$inputFileType = \PhpOffice\PhpSpreadsheet\IOFactory::identify($path);
try {
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
$valuesSpreadsheet = $reader->load($path);
try {
$spreadsheetArr = $valuesSpreadsheet->getActiveSheet()->toArray(null, null, true, true);
print '<pre>' . print_r($spreadsheetArr, 1) . '</pre>';
} catch (Exception $e) {
echo $e . PHP_EOL;
}
} catch (Exception $e) {
echo 'Unable to load file ' . $path . PHP_EOL;
echo $e . PHP_EOL;
}
} catch (Exception $e) {
echo 'Unable to locate file ' . $path . PHP_EOL;
echo $e . PHP_EOL;
}
toArray() has a parameter to return the cell values formatted as they are in the spreadsheet. Try calling it like this:
$spreadsheetArr = $valuesSpreadsheet->getActiveSheet()->toArray(null, true, true, true);
About 80% of the way down this page is documentation for the toArray() function.
In short, toArray() can accept 4 parameters:
whatever value you want empty cells to return
(boolean) do formulas need to be calculated?
(boolean) does cell formatting matter?
(boolean) do you want the array indexed by the spreadsheet's column and row?
You should use getRowIterator() and getCellIterator() functions to loop through all cells. In the code below, all cells will be returned as raw values.
try {
$inputFileType = IOFactory::identify($path);
try {
$reader = IOFactory::createReader($inputFileType);
$reader->setReadDataOnly(true);
$spreadsheet = $reader->load($path);
$worksheet = $spreadsheet->getActiveSheet();\
foreach ($worksheet->getRowIterator() as $index => $row) {
$cellIterator = $row->getCellIterator();
$cellIterator->setIterateOnlyExistingCells(FALSE); //This loops through all cells
$cells = [];
foreach ($cellIterator as $cell) {
$cells[] = $cell->getValue();
}
$rows[] = $cells;
print_r($rows);
}
}
}
Alright, So I have this code
$key = $_SESSION['order_nums'];
$sqll = "SELECT * FROM `money` WHERE `order` = :key";
$qq=$con->prepare($sqll);
$qq->bindvalue(":key", $key);
$qq->execute();
$excel2 = PHPExcel_IOFactory::createReader('Excel2007');
$excel2 = $excel2->load('nTest.xlsx'); // Empty Sheet
$excel2->setActiveSheetIndex(0);
$worksheet = $excel2->getActiveSheet();
while($fdata=$qq->fetch(PDO::FETCH_ASSOC))
{
$worksheet
->setCellValue('A7', $fdata['code']);
}
Where it it setting the cell value for A7 there is about 6 more of those that match. When I do it like this however, It only puts its into the CELL A7
while($fdata=$qq->fetch(PDO::FETCH_ASSOC))
{
$worksheet
->setCellValue('A7', $fdata['code']);
}
How can I make it where
The above value will Drop down one cell for each new entry.
So the next would be A8, A9..... and so on.
That 'A7' isn't some kind of magic value, it's just a normal PHP string that's passed as a standard function argument to the setCellValue() method.... you can replace it with a string variable that you define yourself, and change for each row
$column = 'A';
$row = 7;
while($fdata=$qq->fetch(PDO::FETCH_ASSOC))
{
$worksheet
->setCellValue($column . $row, $fdata['code']);
$row++;
}
$row = 'A';
while($fdata=$qq->fetch(PDO::FETCH_ASSOC)){
$col = 1;
foreach($fdata as $data){
$worksheet->setCellValue("$row$col", $data);
$col++;
}
$row++;
}
This following code simply ignore all empty cells in my excelsheet.
Is there any way to read empty cell or replace them to "Null" values?
See the code here---https://arjunphp.com/how-to-use-phpexcel-with-codeigniter/
$file = './files/test.xlsx';
//load the excel library
$this->load->library('excel');
//read file from path
$objPHPExcel = PHPExcel_IOFactory::load($file);
//get only the Cell Collection
$cell_collection = $objPHPExcel->getActiveSheet()->getCellCollection();
$maxCell = $objPHPExcel->getHighestRowAndColumn();
$newdata = array();
//extract to a PHP readable array format
foreach ($cell_collection as $cell) {
I tried this following code
$newdata = $objPHPExcel->rangeToArray($cell . $maxCell['column'] . $maxCell['row']);
$newdata = array_map('array_filter', $data);
$newdata = array_filter($data);
$column = $objPHPExcel->getActiveSheet()->getCell($cell)->getColumn();
$row = $objPHPExcel->getActiveSheet()->getCell($cell)->getRow();
$data_value = $objPHPExcel->getActiveSheet()->getCell($cell)->getValue();
//header will/should be in row 1 only. of course this can be modified to suit your need.
if ($row == 1) {
$header[$row][$column] = $data_value;
} else {
$arr_data[$row][$column] = $data_value;
}
}
//send the data in an array format
$data['header'] = $header;
$data['values'] = $arr_data;
print_r($newdata);
Get this error messgae... Fatal error: Call to undefined method PHPExcel::getHighestRowAndColumn()
you're try to wrong way, in this way you only get the last active cell value and if you try to get empty cell cell value in middle you're not able to get value. and you use some PhpSpreadsheet function and also some time you try get value using class object. check your code one more time.
I know, there are lot's of questions here sbout improving PHPExcel performance. But all of them are about writing data, and my problem is in reading.
My function:
function parse($filename){
$objPHPExcel = PHPExcel_IOFactory::load($filename);
$activeSheet = $objPHPExcel->getActiveSheet();
$parsedData = array();
$columnHeaders = array('order', 'ts', 'summ', 'name', 'quant', 'price', 'bccu');
foreach ($activeSheet->getRowIterator() as $rkey => $row) {
$cellIterator = $row->getCellIterator();
foreach ($cellIterator as $ckey => $cell) {
$parsedData[$columnHeaders[$ckey]] = $cell->getCalculatedValue();
}
}
return $parsedData;
}
The file contains ~300 rows and 7 columns. And this script fails to run in 30 seconds.
How can i improve it?
edit:
used
$objReader = PHPExcel_IOFactory::createReader("Excel2007");
$objPHPExcel = $objReader->load($filename);
whth no success
If your columns are already defined, what about remove the column iterator?
Try something like this:
foreach ($activeSheet->getRowIterator() as $rkey => $row) {
$rowIndex = $row->getRowIndex ();
$parsedData[$rowIndex]['order'] = $activeSheet->getCell('A' . $rowIndex);
$parsedData[$rowIndex]['ts'] = $activeSheet->getCell('B' . $rowIndex);
$parsedData[$rowIndex]['summ'] = $activeSheet->getCell('C' . $rowIndex);
.
.
.
}
Try disabling the garbage collector before running parse() by issuing gc_disable(). Guessing that levels of iterations here don't get optimized properly by PHP.
If you're not going to change the file's contents; setting the reader to read-only gives about 10x boost.
For example:
$objReader = PHPExcel_IOFactory::createReader( 'Excel5' );
$objReader->setReadDataOnly( true );