Last active
September 21, 2020 11:49
-
-
Save DenesKellner/d72a868ae9af761210c5dcdac1feb10d to your computer and use it in GitHub Desktop.
Simple Excel XML spreadsheet generator that can convert your 2D array to a valid XML that you can open with Excel. It's based on https://en.wikipedia.org/wiki/Microsoft_Office_XML_formats - but adds a few perks like text width calculation.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class SimpleSheet { | |
private $data = []; | |
private $worksheetName = "Export"; | |
private $widthMultiplier = 6; // how many points for one character; gives rough approximations | |
private $cellLimiter = " "; // add extra character after each cell value (overflow limiter) | |
private $rowLimiter = " "; // add extra cell at the end of each row (overflow limiter) | |
public function __construct ($a=null) {if($a) $this->loadFromArray($a);} | |
public function loadFromArray ($a) {foreach($a as $row) $this->data[]=$row;} | |
public function setTitle ($name) {$this->worksheetName = $name;} | |
public function saveAs ($filename) {file_put_contents($filename,$this->toString());} | |
private function toString() { | |
$C = '<Cell><Data ss:Type="String">%s%s</Data></Cell>'."\n"; | |
$R = '<Row>'."\n".'%s</Row>'."\n"; | |
$M = '<Column ss:Width="%s"/>'."\n"; | |
$T = ' | |
<?xml version="1.0" encoding="utf-8" ?> | |
<?mso-application progid="Excel.Sheet"?> | |
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" | |
xmlns:o="urn:schemas-microsoft-com:office:office" | |
xmlns:x="urn:schemas-microsoft-com:office:excel" | |
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" | |
xmlns:html="http://www.w3.org/TR/REC-html40"> | |
<Styles> | |
<Style ss:ID="Default"> | |
<Alignment ss:Indent="1"/> | |
</Style> | |
</Styles> | |
<Worksheet ss:Name="%s"> | |
<Table> | |
%s | |
%s | |
</Table> | |
</Worksheet> | |
</Workbook> | |
'; | |
$e = error_reporting();error_reporting(E_ALL - E_NOTICE); // notices are NOT errors. | |
$m = $this->widthMultiplier; | |
$l = $this->cellLimiter; | |
$z = $this->rowLimiter; | |
$N = $this->worksheetName; | |
$D = $this->data; | |
$z = $z?sprintf($C,"",$z):""; | |
$cw=[];foreach($D as $r) {foreach($r as $n=>$s) $cw[$n]=max($cw[$n],$this->nWidth($s));} | |
$cp="";foreach($cw as $x) {$x=($x+2)*$m; if($x>300) $x=300; $cp.=sprintf($M,$x)."\n";} | |
$tx="";foreach($D as $r) {$rt="";foreach($r as $c) {$rt.=sprintf($C,$c,$l)."\n";} $tx.=sprintf($R,"$rt$z");} | |
$text = sprintf($T,$N,$cp,$tx);$text = trim(preg_replace('/\s*\n\s*/',"\n",$text)); | |
error_reporting($e); | |
return $text; | |
} | |
private function nWidth($str) { // how many "n"-s wide is your text; good estimation for calibri-alike fonts | |
$trickySigns = "l ,:;fJ-t()[]{}!sxzGHNOUmwW"; | |
$similarChar = "iijjjtttttttttttcccVVVVVMMM"; | |
$str = strtr($str,$trickySigns,$similarChar); | |
$cch = count_chars($str,1); | |
$text = strlen($str)*168 // count all characters as average (letter "n") | |
+ $cch[ord("i")]*( 70 -168) // compensate by differences | |
+ $cch[ord("j")]*( 84 -168) // half "n" | |
+ $cch[ord("t")]*( 105 -168) | |
+ $cch[ord("r")]*( 120 -168) | |
+ $cch[ord("x")]*( 140 -168) // almost the same as "n" | |
+ $cch[ord("V")]*( 210 -168) // these are wider than "n" | |
+ $cch[ord("M")]*( 280 -168) // very wide | |
; | |
return (int)($text/168); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment