Files
pathfinder/app/lib/sheet.php

216 lines
6.4 KiB
PHP

<?php
/**
* Sheet - CSV and Excel tools
*
* The contents of this file are subject to the terms of the GNU General
* Public License Version 3.0. You may not use this file except in
* compliance with the license. Any of the license terms and conditions
* can be waived if you get permission from the copyright holder.
*
* (c) Christian Knuth
*
* @date: 16.03.2015
* @version 0.4.1
*/
class Sheet extends \Prefab {
/**
* multiline-aware CSV parser
* @param $filepath
* @param string $delimiter
* @param string $enclosure
* @return array|bool
*/
public function parseCSV($filepath,$delimiter=";",$enclosure='"') {
if (!is_file($filepath)) {
user_error('File not found: '.$filepath);
return false;
}
$data = \Base::instance()->read($filepath,true);
if(!preg_match_all('/((?:.*?)'.$delimiter.'(?:'.$enclosure.'.*?'.
$enclosure.'|['.$delimiter.'(?:\d|\.|\/)*\d])*\n)/s',$data,$matches))
user_error('no rows found');
$out = array_map(function($val) use($delimiter,$enclosure) {
return str_getcsv($val,$delimiter,$enclosure);
},$matches[0]);
return $out;
}
/**
* use specified headers or first row as label for each row item key
* @param $rows
* @param null $headers
* @return array
*/
public function applyHeader($rows,$headers=null) {
if (!$headers)
$headers=array_shift($rows);
return array_map(function($row) use($headers) {
return array_combine(array_values($headers),array_values($row));
},$rows);
}
/**
* build and return xls file data
* @param $rows
* @param $headers
* @return string
*/
public function dumpXLS($rows,$headers) {
$numColumns = count($headers);
$numRows = count($rows);
foreach($headers as $key=>$val)
if (is_numeric($key)) {
$headers[$val]=ucfirst($val);
unset($headers[$key]);
}
$xls = $this->xlsBOF();
for ($i = 0; $i <= $numRows; $i++) {
for ($c = 0; $c <= $numColumns; $c++) {
$ckey = key($headers);
$val='';
if ($i==0)
$val = current($headers);
elseif (isset($rows[$i-1][$ckey]))
$val = trim($rows[$i-1][$ckey]);
if (is_array($val))
$val = json_encode($val);
$xls.= (is_int($val)
|| (ctype_digit($val) && ($val[0]!='0' && strlen($val)>1)))
? $this->xlsWriteNumber($i,$c,$val)
: $this->xlsWriteString($i,$c,utf8_decode($val));
next($headers);
}
reset($headers);
}
$xls .= $this->xlsEOF();
return $xls;
}
/**
* render xls file and send to HTTP client
* @param $rows
* @param $headers
* @param $filename
*/
function renderXLS($rows,$headers,$filename) {
$data = $this->dumpXLS($rows,$headers);
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Type: application/xls');
header("Content-Disposition: attachment;filename=".$filename);
header("Content-Transfer-Encoding: binary");
echo $data;
exit();
}
/**
* start file
* @return string
*/
protected function xlsBOF() {
return pack("ssssss", 0x809, 0x8, 0x0, 0x10, 0x0, 0x0);
}
/**
* end file
* @return string
*/
protected function xlsEOF() {
return pack("ss", 0x0A, 0x00);
}
/**
* put number
* @param $row
* @param $col
* @param $val
* @return string
*/
protected function xlsWriteNumber($row, $col, $val) {
$out = pack("sssss", 0x203, 14, $row, $col, 0x0);
$out.= pack("d", $val);
return $out;
}
/**
* put string
* @param $row
* @param $col
* @param $val
* @return string
*/
protected function xlsWriteString($row, $col, $val ) {
$l = strlen($val);
$out = pack("ssssss", 0x204, 8+$l, $row, $col, 0x0, $l);
$out.= $val;
return $out;
}
/**
* build and return CSV data sheet
* @param $rows
* @param $headers
* @param string $delimiter
* @param string $enclosure
* @param bool $encloseAll
* @return string
*/
public function dumpCSV($rows,$headers,$delimiter=';',$enclosure='"',$encloseAll=true) {
$numColumns = count($headers);
$numRows = count($rows);
foreach($headers as $key=>$val)
if (is_numeric($key)) {
$headers[$val]=ucfirst($val);
unset($headers[$key]);
}
$out = array();
for ($i = 0; $i <= $numRows; $i++) {
$line = array();
for ($c = 0; $c <= $numColumns; $c++) {
$ckey = key($headers);
$field='';
if ($i==0)
$field = current($headers);
elseif (isset($rows[$i-1][$ckey]))
$field = trim($rows[$i-1][$ckey]);
if (is_array($field))
$field = json_encode($field);
if (empty($field) && $field !== 0)
$line[] = '';
elseif ($encloseAll || preg_match('/(?:'.preg_quote($delimiter, '/').'|'.
preg_quote($enclosure, '/').'|\s)/', $field))
$line[] = $enclosure.str_replace($enclosure, $enclosure.$enclosure, $field).$enclosure;
else
$line[] = $field;
next($headers);
}
$out[] = implode($delimiter, $line);
reset($headers);
}
return implode("\n",$out);
}
/**
* send CSV file to client
* @param $rows
* @param $headers
* @param $filename
*/
function renderCSV($rows,$headers,$filename) {
$data = $this->dumpCSV($rows,$headers);
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Type: text/csv;charset=UTF-16LE');
header("Content-Disposition: attachment;filename=".$filename);
header("Content-Transfer-Encoding: binary");
echo "\xFF"."\xFE".mb_convert_encoding($data, 'UTF-16LE', 'UTF-8');
exit();
}
}