PHP数据跨行跨列处理

PS

PHP数据跨行跨列处理,表格展示,Excel导出。后台是Dcat Admin,导出是"maatwebsite/excel": “^3.1”

Excel效果

在这里插入图片描述

后台页面效果

在这里插入图片描述

示例代码

数据调用

可以放在Dcat对应Controller的数据仓库里面。

    public function get(Grid\Model $model)
    {
    	// 返回Controller数据
        return $this->getdataInit();

//        return parent::get($model); // TODO: Change the autogenerated stub
    }
	// 调用方法
    public function getdataInit()
    {
        // 数据查询
        $dataModel = $this->getData();
        if(!count($dataModel)) return [];
        // 数据格式化
        try {
			// 这是有3列汇总的情况
			// 如果只有2列汇总,传参column4注释
			// 如果只有1列汇总,传参column4、column3注释
			// 对应的字段得到控制属性,默认是等于true显示的,等于false表示不显示
			// $dataRowCol->isColumn4 = false; $dataRowCol->isColumn3 = false;
            $dataRowCol = new dataRowCol([
                'column1'   => 'pay_policy_time',  // 投保日期列 key
                'column2'   => 'channel_1',			// 一级渠道 key
                'column3'   => 'channel_2',			// 二级渠道 key
                'column4'   => 'channel_3',			// 三级渠道 key
            ],$this);

            // 模拟数据写入
//            $this->dbTestData(300);
            $data1 = $dataRowCol->dataInit($dataModel);
        }catch (\Exception $e)
        {
            echo $e->getTraceAsString();exit();
        }
        return $data1;
    }
    /**
     * 数据统一计算
     * 返回版
     * Created by PhpStorm
     * User: Noah
     * Date: 2022/12/19
     * Time: 17:50
     * @param $re
     * @param $v
     * @return mixed
     */
    public function reNumBc($re,$v,$isKey = 'id')
    {

        if(!isset($re[$isKey]))
        {
            return $v;
        }
        // 计数器,累加了几次
        $re['order_num'] += $v['order_num'];
        $re['unpaid_pay'] += $v['unpaid_pay'];
        $re['sign_num'] += $v['sign_num'];
        $re['premium'] = bcadd($re['premium'],$v['premium'],ConfigService::bc_float);
        $re['piece_avg'] = bcadd($re['piece_avg'],$v['piece_avg'],ConfigService::bc_float);
        $re['re_piece'] += $v['re_piece'];
        $re['re_premium'] = bcadd($re['re_premium'],$v['re_premium'],ConfigService::bc_float);
        $re['add_premium'] = bcadd($re['add_premium'],$v['add_premium'],ConfigService::bc_float);
        return $re;
    }
数据格式化类
<?php
/**
 *
 * Created by PhpStorm
 * User: Noah
 * Date: 2022/12/20
 * Time: 11:01
 */

namespace App\Admin\Server;


class dataRowCol
{

    /**
     * 四级栏目是否显示
     * 不显示的情况需要把数据组合到3级栏目
     * 且上级栏目跨行数也需要更改
     * @var bool
     */
    public $isColumn3 = true;
    public $isColumn4 = true;

    protected $summaryField1 = 'column1';
    protected $summaryField2 = 'column2';
    protected $summaryField3 = 'column3';
    protected $summaryField4 = 'column4';
    protected $summaryField5 = 'column5';

    /**
     * @var string[]
     *
        'column1'   => 'pay_policy_time',   // 一级栏目字段
        'column2'   => 'channel_1',         // 二级栏目字段
        'column3'   => 'channel_2',         // 三级栏目字段
        'column4'   => 'channel_3',         // 四级栏目字段
     *
     *
     */
    protected $columnArr  = [];

    /**
     * 明细数据累加方法
     * @var
     */
    protected  $ob;

    protected $channel;

    public function __construct($columnArr, $ob)
    {
        if(!isset($columnArr[$this->summaryField4])) $columnArr[$this->summaryField4] = $this->summaryField4;
        if(!isset($columnArr[$this->summaryField3])) $columnArr[$this->summaryField3] = $this->summaryField3;
        $this->columnArr = $columnArr;
        $this->ob = $ob;
    }

    /**
     * 调用外部方法计算累加
     * $re 累加并返回的数据
     * $v 计算的数据
     * $isKey = 'id' 判断否是为空的字段,字段不存在直接$v
     * Created by PhpStorm
     * User: Noah
     * Date: 2022/12/20
     * Time: 11:09
     * @param $sum
     * @param $v
     * @return mixed
     */
    private function reNumBc($sum,$v,$isKey = 'id')
    {
        return $this->ob->reNumBc($sum,$v,$isKey);
    }

    /**
     * 数据格式化
     * Created by PhpStorm
     * User: Noah
     * Date: 2022/12/16
     * Time: 11:25
     * @param $data'
     */
    public function dataInit($data)
    {
        $res = [];
        $sum = []; // 总汇-总合计
        $huizongs = []; // 总汇-数据格式化
        $dayDataInit = [];    //  每日合计-数据格式化
        $daySum = [];
        if(count($data))
        {
            foreach ($data as $v)
            {
                // 总汇-总合计
                $sum = $this->reNumBc($sum,$v);

                $this->channelInit($this->channel,$v);

                $key = date('Y-m-d',strtotime($v[$this->columnArr[$this->summaryField1]]));

                // 每日合计-数据格式化
                list($dayDataInit,$daySum) = $this->dayChannelInit($dayDataInit,$daySum,$v,$key);
            }
        }
//        dd($this->channel);
//        dd([
//            $dayDataInit,
//            $daySum
//        ]);
        // 总汇总-数据组合
        // 总合计
        $res[0] = $sum;
        $this->resFirst($res[0]);
        // 总汇总-数组组合
        $this->sumDataInit($this->channel,$res,0);

        // 每日汇总-数组组合
        $this->sumDayDataInit($dayDataInit,$daySum,$res);

        return $res;
    }


    /**
     * 首行合计
     * Created by PhpStorm
     * User: Noah
     * Date: 2022/12/20
     * Time: 0:37
     * @param $sum
     * @param string $value
     */
    private function resFirst(&$sum,$value = '汇总(截止到昨日)')
    {
        $sum[$this->summaryField1] = [
            'value' => $value,
        ];
        if($this->isColumn4)
        {
            $colspan = 3;

        }else
        {
            $colspan = 2;
        }

        $sum[$this->summaryField2] = [
            'value' => '汇总',
            'colspan'   => $colspan
        ];
        unset($sum[$this->summaryField3]);
        unset($sum[$this->summaryField4]);
    }

    /**
     * 每天-数组组合
     * Created by PhpStorm
     * User: Noah
     * Date: 2022/12/20
     * Time: 1:00
     * @param $dayDataInit
     * @param $daySum
     * @param $res
     */
    private function sumDayDataInit($dayDataInit,$daySum,&$res)
    {
        foreach ($dayDataInit as $k => $v)
        {
//            dd($daySum);
            $res[] = $daySum[$k];
            $resKey = count($res)?count($res)-1:0;
            $this->resFirst($res[$resKey],$k);
            $this->sumDataInit($v,$res,$resKey);
        }
    }

    /**
     * 总汇总-数组组合
     * Created by PhpStorm
     * User: Noah
     * Date: 2022/12/20
     * Time: 0:29
     * @param $res
     * @param int $type
     */
    private function sumDataInit($data,&$res,$resKey)
    {
        $inarray = ['data','num',$this->summaryField2,$this->summaryField3];
        $sumNum = 1;

        if($this->isColumn3) $sumNum += count($data[$this->summaryField2]);
        unset($data[$this->summaryField2]);
//        unset($data[$this->summaryField3]); login_time
        foreach ($data as $k1 => $v1)
        {
            // 二级栏目
            if($this->isColumn3)
            {
                $res[] = $this->column1Init($k1,$v1);
                if($this->isColumn4) $sumNum += count($v1[$this->summaryField2]);
            }
            if(!in_array($k1,$inarray))
            {
                foreach ($v1 as $k2 => $v2)
                {
                    $this->v2Init($res,$sumNum,$k2,$v2);
                }
            }

        }

        // 一级栏目跨行=二级栏目数量(去重)+三级栏目数量(对应二级栏目下去重)+归属一级栏目的行数
        $res[$resKey][$this->summaryField1]['rowspan'] = $sumNum;
    }

    /**
     * v2数据格式化
     * Created by PhpStorm
     * User: Noah
     * Date: 2022/12/20
     * Time: 14:24
     * @param $res
     * @param $sumNum
     * @param $k2
     * @param $v2
     */
    private function v2Init(&$res,&$sumNum,$k2,$v2)
    {
        $inarray = ['data','num',$this->summaryField2,$this->summaryField3];
        if(!$this->isColumn3) $inarray = ['data','num',$this->summaryField2];

        if(!in_array($k2,$inarray))
        {
            if($this->isColumn4)
            {
                // 四级栏目显示
                $column2 = $this->column2Init($k2,$v2);
                $res[] = $column2;
            }

            foreach ($v2 as $k3 => $v3)
            {
                $this->v3Init($res,$sumNum,$k3,$v3);
            }
        }
    }

    /**
     * v3数据处理
     * Created by PhpStorm
     * User: Noah
     * Date: 2022/12/20
     * Time: 14:21
     * @param $res
     * @param $sumNum
     * @param $k3
     * @param $v3
     * @param $k3inarray
     */
    private function v3Init(&$res,&$sumNum,$k3,$v3)
    {
        $k3inarray = ['data','num',$this->summaryField2,$this->summaryField3];

        if(!in_array($k3,$k3inarray))
        {
            $sumNum += count($v3['data']);
            foreach ($v3['data'] as $k4 => $v4)
            {
                if($this->isColumn4)
                {
                    // 四级栏目显示
                    $v4[$this->summaryField4] = $v4[$this->columnArr[$this->summaryField4]];
                    unset($v4[$this->columnArr[$this->summaryField1]]);
                    unset($v4[$this->columnArr[$this->summaryField2]]);
                    unset($v4[$this->columnArr[$this->summaryField3]]);
                }
                else
                {
                    if($this->isColumn3)
                    {
                        // 四级栏目隐藏
                        $v4[$this->summaryField3] = $v4[$this->columnArr[$this->summaryField3]];
                        unset($v4[$this->columnArr[$this->summaryField1]]);
                        unset($v4[$this->columnArr[$this->summaryField2]]);
                    }else
                    {
                        // 三级栏目隐藏
                        $v4[$this->summaryField2] = $v4[$this->columnArr[$this->summaryField2]];
                        unset($v4[$this->columnArr[$this->summaryField1]]);
//                        unset($v4[$this->columnArr[$this->summaryField2]]);
                    }

                }

                // 详细数据


                $res[] = $v4;
            }
        }
    }

    /**
     * 一级栏目数据组合
     * Created by PhpStorm
     * User: Noah
     * Date: 2022/12/19
     * Time: 22:49
     * @param $k1
     * @param $v1
     * @return mixed
     */
    private function column1Init($k1,$v1)
    {

        if($this->isColumn4)
        {
            $colspan = 2;
            $rowspan = count($v1[$this->summaryField2])+$v1['num'];

        }else
        {
            $colspan = 1;
            $rowspan = $v1['num'];
        }
        $column1 = $v1['data'];
        $column1[$this->summaryField1] = [
            'value' => $k1,
            'rowspan'   => $rowspan+1
        ];



        $column1[$this->summaryField2] = [
            'value' => '汇总',
            'colspan'   => $colspan
        ];
        unset($column1[$this->summaryField3]);
        unset($column1[$this->summaryField4]);
        return $column1;
    }

    /**
     * 二级栏目数据组合
     * Created by PhpStorm
     * User: Noah
     * Date: 2022/12/19
     * Time: 22:49
     * @param $k1
     * @param $v1
     * @return mixed
     */
    private function column2Init($k2,$v2)
    {
        $column2 = $v2['data'];
        $column2[$this->summaryField2] = [
            'value' => $k2,
            'rowspan'   => $v2['num']+1,
        ];
        $column2[$this->summaryField3] = [
            'value' => '汇总',
            'colspan'   => 1
        ];
        unset($column2[$this->summaryField1]);
        unset($column2[$this->summaryField4]);
        return $column2;
    }



    /**
     * 合计汇总
     * Created by PhpStorm
     * User: Noah
     * Date: 2022/12/16
     * Time: 13:41
     * @param $sum
     * @param $v
     * @return mixed
     */
    private function zongSum(&$sum,$v)
    {
        if(count($sum))
        {
            $this->numBc($sum,$v);
        }
        else{
            $sum = $v;
        }

        return $sum;
    }


    /**
     * 每天渠道数据存储
     * Created by PhpStorm
     * User: Noah
     * Date: 2022/12/20
     * Time: 0:35
     * @param $dayDataInit
     * @param $daySum
     * @param $v
     * @param $key
     * @return array
     */
    private function dayChannelInit($dayDataInit,$daySum,$v,$key)
    {
        if(!isset($dayDataInit[$key])) $dayDataInit[$key] = [];

        $this->channelInit($dayDataInit[$key],$v);


        if(!isset($daySum[$key])) $daySum[$key] = [];
        $daySum[$key] = $this->reNumBc($daySum[$key],$v);

        return [$dayDataInit,$daySum];
    }


    /**
     * 渠道数据存储
     * Created by PhpStorm
     * User: Noah
     * Date: 2022/12/19
     * Time: 20:22
     * @param $data
     */
    private function channelInit(&$dbData,$data)
    {
        $channel = $dbData;


        // 获取key
        $channel1Key = isset($data[$this->columnArr[$this->summaryField2]])?$data[$this->columnArr[$this->summaryField2]]:$this->summaryField2;
        $channel2Key = isset($data[$this->columnArr[$this->summaryField3]])?$data[$this->columnArr[$this->summaryField3]]:$this->summaryField3;
        $channel3Key = isset($data[$this->columnArr[$this->summaryField4]])?$data[$this->columnArr[$this->summaryField4]]:$this->summaryField4;

        // 初始化
        $channel[$channel1Key] = isset($channel[$channel1Key])?$channel[$channel1Key]:[];
        $channel[$channel1Key][$channel2Key] = isset($channel[$channel1Key][$channel2Key])?$channel[$channel1Key][$channel2Key]:[];
        $channel[$channel1Key][$channel2Key][$channel3Key] = isset($channel[$channel1Key][$channel2Key][$channel3Key])?$channel[$channel1Key][$channel2Key][$channel3Key]:[];

        $channel1Data = $channel[$channel1Key];
        $channel2Data = $channel[$channel1Key][$channel2Key];
        $channel3Data = $channel[$channel1Key][$channel2Key][$channel3Key];

        // 数据
        if(!isset($channel1Data['data'])) $channel1Data['data'] = [];
        if(!isset($channel2Data['data'])) $channel2Data['data'] = [];
        if(!isset($channel3Data['data'])) $channel3Data['data'] = [];
        if(!isset($channel3Data['sumdata'])) $channel3Data['sumdata'] = [];
        $channel1Data['data'] = $this->reNumBc($channel1Data['data'],$data);
        $channel2Data['data'] = $this->reNumBc($channel2Data['data'],$data);
        $channel3Data['data'][] = $data;
        $channel3Data['sumdata'] = $this->reNumBc($channel3Data['sumdata'],$data);


        // 值操作
        $channel1Data['num'] = isset($channel1Data['num'])?$channel1Data['num']+1:1;
        $channel2Data['num'] = isset($channel2Data['num'])?$channel2Data['num']+1:1;
        $channel3Data['num'] = isset($channel3Data['num'])?$channel3Data['num']+1:1;

//        // 二级级栏目不重复key
        $channel1Data[$this->summaryField2][$channel2Key] = 1;
//        // 二级级栏目不重复key
        $channel2Data[$this->summaryField3][$channel3Key] = 1;
        // 一级栏目不重复key
        $channel[$this->summaryField2][$channel1Key] = 1;
//        $channel[$this->summaryField2][$channel1Key][$channel2Key] = 1;
//        $channel[$this->summaryField3][$channel2Key] = 1;
//        // 栏目二不重复key
//        $channel[$this->summaryField3][$channel2Key] = 1;

        // 赋值
        $channel[$channel1Key] = $channel1Data;
        $channel[$channel1Key][$channel2Key] = $channel2Data;
        $channel[$channel1Key][$channel2Key][$channel3Key] = $channel3Data;

        $dbData = $channel;
    }
}

Dcat Admin Grid
            $grid->column('column1','投保日期')->view('admin.column1');
            $grid->column('column2','活动一级渠道')->view('admin.column2');
            $grid->column('column3','活动二级渠道')->view('admin.column3');
            $grid->column('column4','活动三级渠道')->view('admin.column4');
            $grid->disablePagination();
Dcat Admin View

链接:https://pan.baidu.com/s/1fel4RgzJtdvBIk6CfmSRvA
提取码:nw6l

Excel导出调用
        // 02
$excel = new BwPosition();
Excel::store($excel,'02-table-'.date('Y-m-d',strtotime('-1 day')).'.xlsx');

Excel导出示例
<?php
/**
 *
 * Created by PhpStorm
 * User: Noah
 * Date: 2022/12/20
 * Time: 19:37
 */

namespace App\Admin\Server\Excel;


use App\Admin\Repositories\BwChannel_canalDb;
use App\Api\Service\ConfigService;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

/**
 * 02
 */
class BwPosition extends ExcelServer
{


    public function __construct()
    {
        parent::__construct();
    }

    /**
     *  业务代码
     * @return array|string[][]
     */
    public function createData()
    {
        $start = date('Y-m-d 00:00:00',strtotime("-1 day"));
        $end = date('Y-m-d 23:59:59',strtotime("-1 day"));
        $login_time = [
            'start' => $start,
            'end'=> $end
        ];
        request()->request->set('login_time',$login_time);
        $BwChannel_canalDb = new \App\Admin\Repositories\BwPosition();
        $data = $BwChannel_canalDb->getdataInit();
        $headTitle = [
            '投保日期',
            '活动一级渠道',
            '活动二级渠道',
            '活动三级渠道',
            '产品名称',
            '订单数',
            '未支付订单数',
            '签单件数',
            '签单保费',
            '件均',
            '退保件数',
            '退保保费',
            '净增保费',
        ];

        $bodyData = [];
//        dd($data);


        // 数据循环
        foreach ($data as $k => $item) {


            list($column1,$column1Me) = $this->getValueArr($item,'column1');
            list($column2,$column2Me) = $this->getValueArr($item,'column2');
            list($column3,$column3Me) = $this->getValueArr($item,'column3');
            $column4 = $this->getStrValue($item,'column4');
            $column1Show = $column1;
            $column2Show = $column2;
            $column3Show = $column3;
            $column4Show = $column4;

            if($k == 0)
            {
                // 一级栏目第一行换行
                $login_time = $column1;
                $this->mergeCells['A2'] = 'A'.($column1Me+1);
                $this->mergeCells['B2'] = 'D2';
//                echo $column1Me.'<br/>';
            }

            /**
             * 判断如果是一级渠道得移动到一级渠道
             * 和后端用同一个数据源
             */
            if(in_array($column1,ConfigService::arr_channel_1))
            {
                // 二级栏目单元格合并
                $start2key = count($bodyData)+1+1;
                $this->mergeCells['B'.$start2key] = 'B'.($start2key+$column1Me-1);
                $this->mergeCells['C'.$start2key] = 'D'.$start2key;
                $column3Show = $column2;
                $column2Show = $column1;
            } else if (strtotime($column1))
            {
                // 一级栏目单元格合并
                $start_key = count($bodyData)+1+1;
                $this->mergeCells['A'.$start_key] = 'A'.($start_key+$column1Me-1);
                $this->mergeCells['B'.$start_key] = 'D'.$start_key;
            }

            /**
             * 三级栏目
             */
            if(in_array($column2,ConfigService::arr_channel_2))
            {
                // 三级栏目单元格合并
                $start3key = count($bodyData)+1+1;
                $this->mergeCells['C'.$start3key] = 'C'.($start3key+$column2Me-1);
//                echo $start3key.'|'.$column2Me.'<br/>';

                $column4Show = $column3;
                $column3Show = $column2;
            }

            $arr[0] = $column1Show;
            $arr[1] = $column2Show;
            $arr[2] = $column3Show;
            $arr[3] = $column4Show;
            $arr[4] = $this->getStrValue($item,'name');
            $arr[5] = $this->getValue($item,'order_num');
            $arr[6] = $this->getValue($item,'unpaid_pay');
            $arr[7] = $this->getValue($item,'sign_num');
            $arr[8] = $this->getValue($item,'premium');
            $arr[9] = $this->getValue($item,'piece_avg');
            $arr[10] = $this->getValue($item,'re_piece');
            $arr[11] = $this->getValue($item,'re_premium');
            $arr[12] = $this->getValue($item,'add_premium');

            $bodyData[] = $arr;
        }
        $this->dataCount = count($bodyData)+1;
//        dd($bodyData);
        // 单元格背景颜色
        $this->bgColor = [
            'A1'    => 'M1',
        ];
        $this->last = 'M';

        // 清除掉 $arr
        unset($arr);

        return [$headTitle, $bodyData];
    }


    public function setColumnDimension(Worksheet $sheet)
    {
        $sheet->getColumnDimension('A')->setWidth(20);
        $sheet->getColumnDimension('B')->setWidth(20);
        $sheet->getColumnDimension('C')->setWidth(20);
        $sheet->getColumnDimension('D')->setWidth(18);
        $sheet->getColumnDimension('E')->setWidth(18);
        $sheet->getColumnDimension('F')->setWidth(15);
        $sheet->getColumnDimension('G')->setWidth(15);
        $sheet->getColumnDimension('H')->setWidth(15);
        $sheet->getColumnDimension('I')->setWidth(15);
        $sheet->getColumnDimension('J')->setWidth(15);
        $sheet->getColumnDimension('K')->setWidth(15);
        $sheet->getColumnDimension('L')->setWidth(15);
        $sheet->getColumnDimension('M')->setWidth(15);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值