PHPSpreadsheet reads certain dates incorrectly - php

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.

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);

Transposing csv values in php

I need to transpose some values in some csv files that we get sent on a regular basis so that they are able to be imported into a website and I'm not sure the best way to go about doing it.
The data arrives in a csv file with a header row containing the column names, and the first column values are product ID's. The data looks like this…
ID F F-VF VF VF-XF XF
1 840 960 1080 1248 1944
2 1137.5 1300 1462.5 1690 2632.5
3 1225 1400 1575 1820 2835
What I'm looking to do is change this around so the column name and it's value are put into a new line for each value for the same id like so…
ID COND VALUE
1 F 840
1 F-VF 960
1 VF 1080
1 VF-XF 1248
1 XF 1944
2 F 1137.5
2 F-VF 1300
2 VF 1462.5
2 VF-XF 1690
2 XF 2835
I may also need to add some strings into the cells - is that easy to do?
Thanks a lot
Not necessarily the most elegant version, just to get an idea.
Something like this would work in case it's a existing csv, which gets read and overwritten with the transposed version.
// assuming a dataset like
// ----
// fruit, apple, pear, peach
// animal, eagle, bear, wolf
// car, renault, fiat, nio
$f = fopen($savePath, 'r');
$header = [];
$data = [];
while($row = fgetcsv($f, 0, ",")) {
$header[]=$row[0];
for ($i = 1; $i < sizeof(array_keys($row)); $i++) {
$data[$i][$row[0]]=$row[$i];
}
}
fclose($f);
$f = fopen($savePath, 'w');
fputcsv($f, $header);
foreach ($data as $recordColDataSet) {
fputcsv($f, array_values($recordColDataSet));
}
fclose($f);
Transposing arrays could also be something to look at eg in this question here:
Transposing multidimensional arrays in PHP
Have you tried any of the standard PHP methods like: str_getcsv() or fgetcsv()?
A quick search of "php csv" provides a TON of possible solutions. I suggest trying a few, then reporting back here if you have a specific problem.

LibCharts PHP X-Axis overlap

I am using Lib charts with mysql. i am getting the bar chart properly but there are too many values on x-axis so they are overlapping and another problem is full names on x-axis are not displaying(Like Ana-Adward. Adward is half displayed on graph). i have checked so many settings but i don't know how to solve this issue. if some one knows please help me. Thanks
i had same problem with overlapping, made some changes in library to not show every caption.
i use vertical bar chart, so in verticalbarchart.php, after "// Draw caption text on bar" insert:
$roznica1 = abs(($value-$prevvalue1)/$value);
$prevvalue1 = $prevvalue;
$roznica = abs(($value-$prevvalue)/$value);
$prevvalue = $value;
if ((($roznica < 0.2 && strlen($value)>3)||($roznica1 < 0.2 && strlen($value)>5)) && $columnWidth<20) $value="";
and before "for ($i = 0; $i < $pointCount; $i++) {" insert:
$prevvalue=0;
$prevvalue1=0;
it's not neat solution but it works!

PHP (ZLIB) uncompression of a C (ZLIB) compressed array returns gibberish

I have a set of ZLIB compressed / base64 encoded strings (done in a C program) that are stored in a database. I have written a small PHP page that should retrieve these values and plot them (the string originally was a list of floats).
Chunk of C program that compresses/encodes:
error=compress2(comp_buffer, &comp_length,(const Bytef*)data.mz ,(uLongf)length,Z_DEFAULT_COMPRESSION); /* compression */
if (error != Z_OK) {fprintf(stderr,"zlib error..exiting"); exit(EXIT_FAILURE);}
mz_binary=g_base64_encode (comp_buffer,comp_length); /* encoding */
(Example) of original input format:
292.1149 8379.5928
366.1519 101313.3906
367.3778 20361.8105
369.1290 17033.3223
375.4355 1159.1841
467.3191 8445.3926
Each column was compressed/encoded as a single string. To reconstruct the original data i am using the following code:
//$row[4] is retrieved from the DB and contains the compressed/encoded string
$mz = base64_decode($row[4]);
$unc_mz = gzuncompress($mz);
echo $unc_mz;
Yet this gives me the following output:
f6jEÍ„]EšiSE#IEfŽ
Could anyone give me a tip/hint about what I might be missing?
------ Added Information -----
I feel that the problem comes from the fact that currently php views $unc_mz as a single string while in reality i would have to re-construct an array containing X lines (this output was from a 9 line file) but... no idea how to do that assignment.
The C program that did that went roughly like this:
uncompress( pUncompr , &uncomprLen , (const Bytef*)pDecoded , decodedSize );
pToBeCorrected = (char *)pUncompr;
for (n = 0; n < (2 * peaksCount); n++) {
pPeaks[n] = (RAMPREAL) ((float *) pToBeCorrected)[n];
}
where peaksCount would be the amount of 'lines' in the input file.
EDIT (15-2-2012): The problem with my code was that I was not reconstructing the array, the fixed code is as follows (might be handy if someone needs a similar snippet):
while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
$m< = base64_decode($row[4]);
$mz_int = gzuncompress($int);
$max = strlen($unc_mz);
$counter = 0;
for ($i = 0; $i < $max; $i = $i + 4) {
$temp= substr($unc_mz,$i,4);
$temp = unpack("f",$temp);
$mz_array[$counter] = $temp[1];
$counter++;
}
The uncompressed string has to be chopped into chunks corresponding to the length of a float, unpack() then reconstructs the float data from teh binary 'chunk'. That's the simplest description that I can give for the above snippet.
compress2() produces the zlib format (RFC 1950). I would have to guess that something called gzuncompress() is expecting the gzip format (RFC 1952). So gzuncompress() would immediately fail upon not finding a gzip header.
You would need to use deflateInit2() in zlib to request that deflate() produce gzip-formatted output, or find or provide a different function in PHP that expects the zlib format.

Unable to display date, time and numbers properly using PHPExcel

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.

Categories