有个打印机的项目让小V比较头疼:需要打印一个表格,原先是使用ESC/POS指令实现的,但是不同打印机会有兼容性问题,所以小V想自己写一个纯文本的表格,直接打印表格数据以此避免兼容问题,小V昨晚想着想着研究写到两点左右,2333,在此把一些代码分享出来,供广大网友参考!
/**
* PHP纯文本制表
* @author Veris
* @blog http://www.mostclan.com
* @date 2018.07.20
*/
/**
* 获取打印字符串长度
* @param string $str 待计算字符串
* @return integer 长度
*/
function get_printstr_len($str) {
if($str===''){
return 0;
}
$len=0;
$arr=preg_split('/(?
foreach($arr as $v){
if(strlen($v)==3){
$len+=2;
}else{
$len++;
}
}
return $len;
}
// $content='<16>
品名数量单价宫保鸡丁x50.01爆炒猪肝(不要葱、不要辣椒,少放盐!!!!!)x329.99';16>$content=isset($_POST['content'])?$_POST['content']:'';
// 排版模式
$mode=isset($_POST['mode'])?$_POST['mode']:'default';
// 打印机最大打印位数
$bit=isset($_POST['bit'])?$_POST['bit']:32;
// 行间距
$padding=isset($_POST['padding'])?$_POST['padding']:0;
// 列间距
$spacing=isset($_POST['spacing'])?$_POST['spacing']:1;
// 匹配制表
preg_match_all('/.*?)/',$content,$tableArr);
foreach($tableArr['table'] as $tableKey => $table)
{
$tableData=[];
// 获取制表点
$posArr=[];
$posSplit=strpos($table,'>');
if($posSplit!==false)
{
$posArr=explode(',',substr($table,0,$posSplit));
array_unshift($posArr,1);
$posArr=array_unique($posArr);
// 制表点排序
sort($posArr);
// 检查制表点合法性(每个制表点最少4位字符长度)
$posLeg=true;
foreach($posArr as $key => $pos)
{
if(isset($posArr[$key+1]))
{
if($posArr[$key+1]-$pos<4)
{
$posLeg=false;
break;
}
}
}
// 制表点不合法
if($posLeg==false){
continue;
}
}
// 列数
$column=count($posArr);
// 最多支持制表点
if($column>=$bit/4){
continue;
}
// 匹配行
preg_match_all('/
(?.*?)/',$table,$trArr);foreach($trArr['tr'] as $tr)
{
// 匹配列
$tdData=[];
// 各列折行数组
$foldArr=[];
// 各列折行文本
$foldTextArr=[];
preg_match_all('/
(?.*?)/',$tr,$tdArr);for($tdKey=0; $tdKey
{
if(!isset($tdArr['td'][$tdKey])){
$tdData[$tdKey]='';
continue;
}
$td=$tdArr['td'][$tdKey];
$n=get_printstr_len($td);
// 位差
$bitDiff=isset($posArr[$tdKey+1])?$posArr[$tdKey+1]-$posArr[$tdKey]:$bit-$posArr[$tdKey];
$bitDiff=$bitDiff>$spacing?$bitDiff-$spacing:1;
// 首列独行模式
if($n>$bitDiff && $mode=='FSAL'){
if($tdKey==0){
$tdData[0]=$td;
$tdData[0]='';
$tableData[][0]=$td;
// 新行
// $tableData[]=[];
continue;
}
}
// 获取折行数据
if($foldArr[]=(int)ceil($n/$bitDiff))
{
$len=0;
$i=0;
$foldText=[];
$arr=preg_split('/(?
foreach($arr as $v){
$len+=strlen($v)==3?2:1;
if($len<=$bitDiff){
if(!isset($foldText[$i])){
$foldText[$i]=$v;
}else{
$foldText[$i].=$v;
}
}else{
$foldText[++$i]=$v;
$len-=$bitDiff;
}
}
$tdData[$tdKey]=array_shift($foldText);
$foldTextArr[$tdKey]=$foldText;
}else{
$tdData[$tdKey]=$td;
}
}
$tableData[]=$tdData;
// 最大增加行数(-1去掉首行)
$maxFold=max($foldArr)-1+$padding;
// 补充折行数据
for($i=0; $i
{
$foldTdData=[];
for($j=0; $j
{
$foldTdData[$j]=isset($foldTextArr[$j][$i])?$foldTextArr[$j][$i]:'';
}
$tableData[]=$foldTdData;
}
}
// var_dump($tableData);
// 渲染数据
$tableRender='';
foreach($tableData as $tr)
{
$trStr='';
foreach($tr as $key => $td)
{
// 位差
$bitDiff=isset($posArr[$key+1])?$posArr[$key+1]-$posArr[$key]:$bit-$posArr[$key];
$tdLen=get_printstr_len($td);
$padNum=$bitDiff-$tdLen;
$pad=$padNum>0?str_repeat(' ',$padNum):'';
$trStr.=$td.$pad;
}
// var_dump($trStr);
$tableRender.=$trStr.PHP_EOL;
}
// echo $tableRender;
$content=str_replace($tableArr[0][$tableKey],$tableRender,$content);
}
echo '
';
echo '
';
echo $content;