PHP使用GD库绘制表格(可根据数据自适应)

先上效果图

图中黄色背景为生成的图片

参考:

https://blog.csdn.net/admin_o1/article/details/106320147

https://blog.csdn.net/dujiaoxi/article/details/80148460

下面看源码:

<?php 
/**
* 需求 :
* 1.表头字段可以自定义,比如说两列、三列、四列(暂未实现)
* 2.表格列宽,可以根据表格内文字多少进行自动调整宽度(实现)
* 3.增加默认10行,不够10行补齐(实现)
*/
$data = [
	'title' 			=>'标题',
	'rows'				=>10,//默认10行,不够10行补齐
	'bgColor'			=>[255,255,170],//生成的图片背景色
	'name'				=>mt_rand(1000,9999), //生成的图片名称
	'font_url'			=>'./font/fangzheng.ttf', //字体路径
	'border'			=>10,//外边框
	'file_path' 		=>'./uploads/',//图片保存路径
	'title_height'		=>30,//报表名称高度
	'title_font_size'	=>16, //报表名称字体大小
	'text_size'			=>12, //正文字体大小
	'row_height'		=>30,//行高
	'filed_id_width'	=>40,//序号列宽度
	'filed_name_width' => 100,//列名称的宽度
    'filed_data_width' => 110,//数据列的宽度
    'header_height'		=>30,//表格上方,title下方高度
    'margin'			=>2, //表格外边框宽度
	'header'	=>['序号','型号','商品','数量','单价(元)','金额(元)'],//表头文字
	'footer'	=>'总计:1000元', //表格末尾
	'footer_height'		=>30,//表格末尾高度
	'filed_width'		=>[40,50,200,70,70,70],
	'data'		=>[
					[
						'xinghao' 	=>'0001',
						'goods'	  	=>'商品123',
						'num'		=>20,
						'price'		=>20.33,
						'total'		=>406.6
					],
					[
						'xinghao' 	=>'0002',
						'goods'	  	=>'商品',
						'num'		=>20,
						'price'		=>20.33,
						'total'		=>406.6
					],
				], //数据
];

// function create_table_image($title,$data,$code,$buyer){
function create_table_image($data){
	if(!isset($data['file_path']) || !$data['file_path']){
		echo '请设置保存路径';
		return false;
	}
	if(!isset($data['font_url']) || !$data['font_url']){
		echo '请设置字体路径';
		return false;
	}
	if(!isset($data['rows']) || !$data['rows']){
		$data['rows'] = 10;
	}
	if(!isset($data['filed_width'])){
		echo '请设置列宽';
		return false;
	}

	foreach($data['data'] as $item){
    	$arr=array_keys($item);
    	for ($i=0; $i < count($arr); $i++) { 
    		$table_header=imagettfbbox($data['text_size'],0,realpath($data['font_url']),$item[$arr[$i]]); //8个坐标
        	$font_width = $table_header[2] - $table_header[0];
        	if($data['filed_width'][$i+1] < $font_width){
        		$data['filed_width'][$i+1] = $font_width+20;
        	}
    	}
    }
	if(count($data['data'])< $data['rows']){
    	$new = [];
    	for($i=0;$i<($data['rows']-count($data['data']));$i++){
    		$tmp=[
    		];
    		$new[] = $tmp;
    	}
    	$data['data'] = array_merge($data['data'],$new);
    }
    $params = [
        'row' => count($data['data']) + 1,//数据的行数
        'file_name' => $data['name'] . '.png',
        'title' => $data['title'],
        'table_time' => date('Y-m-d H:i:s'),
        'data' => $data['data']

    ];
    $total_price = 0;

    foreach($data['data'] as $item){
        if($item['total']){
            $total_price+=$item['total']*1;
        }
    }


    $total_price_text = '合计:'. $total_price .'元';
    $base = [
        'border' => isset($data['border']) ? $data['border'] : 10,//图片外边框
        'file_path' => $data['file_path'],//图片保存路径
        'title_height' => isset($data['title_height']) ? $data['title_height'] : 30,//报表名称高度
        'title_font_size' => isset($data['title_font_size']) ? $data['title_font_size'] : 16,//报表名称字体大小
        'font_url' => realpath($data['font_url']),//字体文件路径
        'text_size' => isset($data['text_size']) ? $data['text_size'] : 12,//正文字体大小
        'row_hight' => isset($data['row_height']) ? $data['row_height'] : 30,//每行数据行高
        'filed_id_width' => isset($data['filed_id_width']) ? $data['filed_id_width'] : 40,//序号列的宽度
        'filed_name_width' => 100,//列名称的宽度
        'filed_data_width' => 110,//数据列的宽度
        'filed_width'		=>$data['filed_width'],
        'table_header' => $data['header'],//表头文字
        'column_text_offset_arr' => [2,8,100,0,0,0],//表头文字左偏移量
        'row_text_offset_arr' => [30,5,10,10,10,10],//数据列文字左偏移量
        'total_height' =>isset($data['footer_height']) ? $data['footer_height'] : 30,//底部总计高度
        'header_height' =>isset($data['header_height']) ? $data['footer_height'] : 30,
        'margin'	=>isset($data['margin']) ? $data['margin'] :2, //边框宽度
    ];

    $sum_width=0;
    foreach($data['filed_width'] as $item){
    	$sum_width+=$item;
    }
    $base['img_width'] = $sum_width + $base['border'] * 2;//图片宽度

    $base['img_height'] = $params['row'] * $base['row_hight'] + $base['border'] * 2 + $base['title_height'] + $base['total_height'] + $base['header_height'];//图片高度
    $border_top = $base['border'] + $base['title_height'] + $base['header_height'];//表格顶部高度
    $border_bottom = $base['img_height'] - $base['border'] - $base['total_height'];//表格底部高度

    //计算每一列的位置
    foreach ($base['filed_width'] as $key => $value) {
        	//图片总宽
        $w_sum += $value;
        //计算每一列的位置
        $base['column_x_arr'][$key] = $w_sum+$base['border'];
    }
    $img = imagecreatetruecolor($base['img_width'], $base['img_height']);//创建指定尺寸图片
    $bg_color = imagecolorallocate($img, $data['bgColor'][0], $data['bgColor'][1], $data['bgColor'][2]);//设定图片背景色
    $text_coler = imagecolorallocate($img, 0, 0, 0);//设定文字颜色
    $border_coler = imagecolorallocate($img, 255, 0, 0);//设定边框颜色
    $white_coler = imagecolorallocate($img, 255, 255, 255);//设定边框颜色
    imagefill($img, 0, 0, $bg_color);//填充图片背景色
    //先填充一个黑色的大块背景
    imagefilledrectangle($img, $base['border'], $border_top, $base['img_width'] - $base['border'], $base['img_height'] - $base['border'] - $base['total_height'], $border_coler);//画矩形
    //再填充一个小两个像素的 背景色区域,形成一个两个像素的外边框
    imagefilledrectangle($img, $base['border'] + $base['margin'], $border_top+$base['margin'], $base['img_width'] - $base['border'] - $base['margin'], $base['img_height'] - $base['border']- $base['total_height'] - $base['margin'], $bg_color);//画矩形
    // 画表格纵线 及 写入表头文字
    foreach($base['column_x_arr'] as $key => $x){
        imageline($img, $x, $border_top, $x, $border_bottom,$border_coler);//画纵线
        $table_header=imagettfbbox($base['text_size'],0,$base['font_url'],$base['table_header'][$key]); //8个坐标
        $font_width = $table_header[2] - $table_header[0];
        imagettftext($img, $base['text_size'], 0, $x - $font_width - $base['column_text_offset_arr'][$key], $border_top + $base['row_hight'] - $base['hight']/2 - $base['text_size']  , $text_coler, $base['font_url'], $base['table_header'][$key]);//写入表头文字
    }
    //画表格横线
    foreach($params['data'] as $key => $item){
        $border_top += $base['row_hight'];
        imageline($img, $base['border'], $border_top, $base['img_width'] - $base['border'], $border_top, $border_coler);

        imagettftext($img, $base['text_size'], 0, $base['column_x_arr'][0] - $base['row_text_offset_arr'][0], $border_top + $base['row_hight'] - 10, $text_coler, $base['font_url'], $key + 1);//写入序号
        $sub = 0;
        foreach ($item as $value){
            $sub++;
            $table_header=imagettfbbox($base['text_size'],0,$base['font_url'],$value); //8个坐标
        	$font_width = $table_header[2] - $table_header[0];
            imagettftext($img, $base['text_size'], 0, $base['column_x_arr'][$sub] - $font_width - $base['row_text_offset_arr'][$sub], $border_top + $base['row_hight'] - 10, $text_coler, $base['font_url'], $value);//写入data数据
        }
    }
    //计算标题写入起始位置
    $title_fout_box = imagettfbbox($base['title_font_size'], 0, $base['font_url'], $params['title']);//imagettfbbox() 返回一个含有 8 个单元的数组表示了文本外框的四个角:
    $title_fout_width = $title_fout_box[2] - $title_fout_box[0];//右下角 X 位置 - 左下角 X 位置 为文字宽度
    $title_fout_height = $title_fout_box[1] - $title_fout_box[7];//左下角 Y 位置- 左上角 Y 位置 为文字高度
    //计算合计内容写入起始位置
    $total_fout_box = imagettfbbox(10, 0, $base['font_url'], $total_price_text);//imagettfbbox() 返回一个含有 8 个单元的数组表示了文本外框的四个角:
    $total_fout_width = $total_fout_box[2] - $total_fout_box[0];//右下角 X 位置 - 左下角 X 位置 为文字宽度
    $total_fout_height = $total_fout_box[1] - $total_fout_box[7];//左下角 Y 位置- 左上角 Y 位置 为文字高度

    //居中写入标题
    imagettftext($img, $base['title_font_size'], 0, ($base['img_width'] - $title_fout_width)/2, $base['title_height'], $text_coler, $base['font_url'], $params['title']);

    //写入制表时间
    imagettftext($img, $base['text_size'], 0, $base['border'], $base['title_height'], $text_coler, $base['font_url'], '时间:' . $params['table_time']);
    //写入买家信息
    imagettftext($img, $base['text_size'], 0, $base['border'], $base['title_height']+20, $text_coler, $base['font_url'], '买家:' . '嘻嘻');
    //写入合计信息
    imagettftext($img, $base['text_size'], 0, $base['border']+50, $border_bottom + 20, $text_coler, $base['font_url'], $total_price_text);
    //imagettftext ( resource $image , float $size , float $angle , int $x , int $y , int $color , string $fontfile , string $text )
    $save_path = $base['file_path'] . $params['file_name'];

    if(!is_dir($base['file_path']))//判断存储路径是否存在,不存在则创建
    {
        mkdir($base['file_path'],0777,true);//可创建多级目录
    }
    imagepng($img,$save_path);
    return $save_path;
}

$url = create_table_image($data);

echo "<img src='$url'>";

 ?>

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值