Unable to display date, time and numbers properly using PHPExcel - php

this is my first question in stackoverflow. I am trying to use PHPExcel to create an HTML table from .xlsx file. You can find my project in:
http://rahulr92.x10.mx/excel/index.php
Login with username 'admin' and you will find an option to 'View Table'. That page displays a table from previously uploaded .xlsx file. I am new to PHPExcel and used some standard code I found online. Here it is:
<?php
require_once '/Classes/PHPExcel.php';
$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load("..\excel.xlsx");
$objWorksheet = $objPHPExcel->getActiveSheet();
$highestRow = $objWorksheet->getHighestRow();
$highestColumn = $objWorksheet->getHighestColumn();
$highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumn);
$user=strtolower($_GET['user']);
$r_count=0;
echo '<table border="1">' . "\n";
for ($row = 5; $row <= $highestRow; ++$row) {
if ($row <7 || $user=="admin" || strstr(strtolower($objWorksheet->getCellByColumnAndRow(8, $row)->getValue()),$user ))
{
if($row>7)$r_count++;
for ($col = 0; $col <= $highestColumnIndex; ++$col) {
if(PHPExcel_Shared_Date::isDateTime($objWorksheet->getCellByColumnAndRow($col,$row)))
echo '<td>' . date("d M Y",PHPExcel_Shared_Date::ExcelToPHP($objWorksheet->getCellByColumnAndRow($col, $row))) . '</td>' ;
else
echo '<td>' . $objWorksheet->getCellByColumnAndRow($col, $row)->getValue() . '</td>' . "\n";
}
echo '</tr>' . "\n";
}
}
echo '</table>' . "\n";
echo "No. of Entries: ".$r_count;
?>
Sorry for the sub-optimal code. When I run the php file, I get a table and all strings in it are displayed properly but datetime and number fields are filled with seemingly random gibberish. Please have a look at it from the above link. I have done some research and found out about the isDateTime() function that way. But it isn't working or probably is used wrongly. I am having a tight deadline for this project, so it would be great if anyone could point me in the right direction. Really sorry if the answer was very obvious. Thanks a lot in advance.
Rahul

Don't set $objReader->setReadDataOnly(true); if you want to be able to identify date/time values... Excel stores dates/times as floating point numbers, and the only way to differentiate a number from a date/time is using the format masking: isDateTime() uses that format masking to identify if a value is a number or a date/time... $objReader->setReadDataOnly(true) tells the file reader to read only the data (the numbers) and to ignore format masks, so it only reads the raw data.
However, I'm not sure I understand exactly what you mean by "random gibberish"... numbers should still display as numbers... can you please give an example.
EDIT
Note that cell methods such as getFormattedValue() will return numbers as they are format masked in the workbook, so date/time values will be formatted as dates/times, numbers will be displayed with appropriate number of decimal places, thousand separators or currencies or percentages (if they had the appropriate formatting in the Excel file), so you don't need to test for isDateTime().... as long as $objReader->setReadDataOnly(true) wasn't set for teh reader.

Related

PHPSpreadsheet formula not working between dates

I want to calculate difference between 2 datetimes in hours with PHPSpreadsheet. This is how Excel does it:
A1 and A2 cells format is:
This is the result on web:
When I change value through PHPSpreadsheet, I get #VALUE! and different value formatting.
$reader = PhpSpreadsheet\IOFactory::createReader("Xlsx");
$target_file = __DIR__ . '/test.xlsx';
$spreadsheet = $reader->load($target_file);
$spreadsheet->getActiveSheet()->setCellValue('A1', '24.6.2020 12:30');
$writer = new PhpSpreadsheet\Writer\Html($spreadsheet);
$output = $writer->generateHTMLHeader();
$output .= $writer->generateStyles(true);
$output .= $writer->generateSheetData();
$output .= $writer->generateHTMLFooter();
$doc = new DOMDocument();
#$doc->loadHTML($output);
echo $doc->saveHTML();
I also tried with formatting like this 6/24/2020 14:30 but the result was same (#VALUE!)
$spreadsheet->getActiveSheet()->setCellValue('A1', '6/24/2020 14:30');
Anyone got any idea on how this should be done?
In an Excel document, dates are stored as numbers, not strings. So you need to pass the correct number to setCellValue().
PhpSpreadsheet provides the utility method Date::stringToExcel() to convert strings to Excel dates. You can use it like this:
$date = PhpSpreadsheet\Shared\Date::stringToExcel('2020-06-24 12:30');
$spreadsheet->getActiveSheet()->setCellValue('A1', $date);

PHPSpreadsheet reads certain dates incorrectly

Ok, so i have an excel file "file1.xlsx" formatted like this:
A B C
1 xxxx 4/30/2019 xxxxx
2 xxxx 5/31/2019 xxxxx
And if I try using PHPSpreadsheet to read the column B like this:
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load('file1.xlsx');
$sheet = $spreadsheet->getActiveSheet();
for ($i = 1; $i <= $sheet->getHighestRow(); $i++) {
echo $sheet->getCell("B$i") . " ";
}
I get this result:
43585 43616
I have no idea what could be causing this. These numbers do not appear anywhere in the spreadsheet, and after some testing I noticed that it doesn't happen on all dates, just some. Can anyone let me know what could be causing this and/or what I can do to fix it? Thank you.

Parse CSV with headers into associative array, echo to serial port(Arduino) and display summary on screen

I'm building a time lapse control device with an Arduino and I need a script to take my preprogrammed time lapse sequences from a CSV and output a summary to screen on the terminal and also echo the CSV contents to the serial port for an Arduino to process. The Arduino will have a camera and a stepper motor controlled gymbal that will move according to the values in the csv.
This is all via php-cli and not a web interface because this will be built into a custom case and I will want to run it on a headless raspberry pi via ssh, no GUIs will be needed.
The CSV to be parsed might look like this, this is an example of a 60 minute time lapse sequence with photos being taken every 10 minutes.
Movement#,Pan(Degrees),Tilt(Degrees),Slide(mm),Delay(Seconds),Shoot,Flash
1,0,5,0,300,1,1
2,15,10,100,600,1,1
3,30,15,200,600,1,1
4,45,20,300,600,1,1
5,60,25,400,600,1,1
6,75,30,500,600,1,1
The "Movement#" header is only in place for "photographic troubleshooting" I don't want to use it for any processing.
I want the script to count the lines of csv to return the movements and also sum the Delay values for a total time in HH:MM:SS.
In the above example the output to the screen would be
Movements: 6
Total Time: 01:00:00
I'm also trying to use an associative array because I'll be doing other things with the array as I build more functionality into this setup. It also seems to make sense because when the totalling of time is being done, a sum of only that field can be run.
In the same example, the output to the serial port(Arduino) would be of the values under these headers.
The bracketed units I listed above are only to help with understanding the goals as described in this question, I don't need to include them in the actual header values that get stored and sent to the Arduino.
This is what would be sent to the Arduino so it can process these instructions to control camera movements, shutter release, flash operations and delay timing.
Pan,Tilt,Slide,Delay,Shoot,Flash
0,5,0,300,1,1
15,10,100,300,1,1
30,15,200,300,1,1
45,20,300,300,1,1
60,25,400,300,1,1
75,30,500,300,1,1
I have some code that I've tried to hack together, but I have had so many problems with it I'm not sure if any of it is any use. It's currently displaying values in the wrong order and if I try to put them in the right order, the variables aren't in place at the time things are processed.
//need to increment delay column into new variable that will be used to return total time of movement, probably goes in the loop which is processing each line of the csv
<?php
$row = 1;
if (($handle = fopen("Movement.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, ",")) !== FALSE) {
$lines = array($data);
$num = count($data);
echo "\n";
//echo "$num fields in line $row: ";
$row++;
for ($c=0; $c < $num; $c++) {
//echo $data[$c] . ",";
}
$movement = $data;
echo implode(",",$movement);
}
fclose($handle);
}
echo "\n";
echo "Movements:" . count($movement) . "\n";
echo "Total Time:" . "??" . "\n";
//echo array_sum();
?>
this is not an actual answer (i am not allowed to post a comment yet), but this might help for parsing the csv
fgetcsv
You could do something like this :
$num_move = 0 ;
$total = 0 ;
$lines = 0 ;
while (($data = fgetcsv($handle, ",")) !== FALSE) {
if ($line++ == 0) continue; // remove header
$total += intval($data[3]);
$num_move++;
}
var_dump($num_move, gmdate("H:i:s", $total));

Creating formula in PHPExcel

I am trying to calculate age based on birth date. Excel Formula is
=DATEDIF(K4,DATE(2014,3,31),"Y")=DATEDIF(K4,DATE(2014,3,31),"YM")
Which shows 9.7 if value in cell K is 2004-08-01 this is perfect but I am not able to set this formula in excel sheet using PHPExcel.
Here is code what I am trying
$date = date('2014,03,31');
for($i=3;$i<=100;$i++){
$objPHPExcel->getActiveSheet()-setCellValue('AQ'.$i,'=DATEDIF(K'.$i.',DATE('.$date.'),"Y")'.'& . & '.'DATEDIF(K'.$i.',DATE('.$date.'),"YM")');
}
What is wrong with the code why excel file not opening after download and showing fileformat or file extension not valid.
Your Excel formula concatenation is with an invalid .. Assuming you want to display a . between the Year and the Months then you need to treat it as a string literal ("."):
$date = date('2014,03,31');
for($i=3;$i<=100;$i++){
$objPHPExcel->getActiveSheet()-setCellValue(
'AQ'.$i,
'=DATEDIF(K'.$i.',DATE('.$date.'),"Y")'.'& "." & '.'DATEDIF(K'.$i.',DATE('.$date.'),"YM")'
);
}
not tested, try this,
$date = date('2014,03,31');
for($i=3;$i<=100;$i++){
$objPHPExcel->getActiveSheet()->setCellValue('AQ'.$i,'=DATEDIF(K'.$i.',DATE('.$date.'),"Y")'.'& . & '.'DATEDIF(K'.$i.',DATE('.$date.'),"YM")');
}

PHPExcel - read time value from a cell

I'm loading an Excel file that has cells with time data, e.g. 08:00:00. But when I try to read those cells with getValue(), it returns some floating point numbers instead of the actual time (in case of 08:00:00, it returns 0.3333333). Here's my code:
$objPHPExcel = PHPExcel_IOFactory::load($filename);
$objWorksheet = $objPHPExcel->getActiveSheet();
echo $objWorksheet->getCellByColumnAndRow(3, 5)->getValue();
How do I bypass this weird conversion?
PHPExcel 1.7.6 and Excel 2003 Worksheet (.xls)
You need to apply cell format for this:
$cell = $objWorksheet->getCellByColumnAndRow(3, 5);
$cell_value = PHPExcel_Style_NumberFormat::toFormattedString($cell->getCalculatedValue(), 'hh:mm:ss');
echo $cell_value;

Categories