PHP导出含图片的Excel

本文介绍如何在PHP中利用maatwebsite库(基于PHPExcel)将包含网络图片的数据导出为Excel文件。首先,需要下载并注册该库,然后将网络图片保存到本地,计算图片在Excel中的存放坐标,最后实现Excel的导出功能。在学习过程中,还发现PHP在处理字符变量的算数运算时与C语言不同,只支持递增和纯字母操作。

情景:一条数据中某字段包含多张图片,分单元格存放导出

类库:maatwebsite(Laravel基于PHPExcel进行封装)

使用:

下载:
composer require "maatwebsite/excel:~2.1.0"
注册:

在config/app.php的 providers 中添加

Maatwebsite\Excel\ExcelServiceProvider::class,

注册到门面:

'Excel' => Maatwebsite\Excel\Facades\Excel::class,

发布配置设置:

php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider"
其他:
    (•ˇ‸ˇ•)没找到支持导出网络图片的方法,只好先用curl缓存到本地,然后防止硬盘爆炸,写了个定时任务删掉缓存的图片。
将网络图片保存到本地:
function getCloudImg($url, $path){
     if (!file_exists($path)) {
         mkdir($path, 0777, true);
     }
     $ch = curl_init();
     curl_setopt($ch, CURLOPT_URL, $url);
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
     curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
     $file = curl_exec($ch);
     curl_close($ch);
     $filename = pathinfo($url, PATHINFO_BASENAME);
     $resource = fopen($path . '\\' . $filename, 'w+');
     fwrite($resource, $file);
     fclose($resource);
     return $path .'\\'. $filename;
}
计算图片存放坐标:
    function getExcelMapOffset($count, $start = 'A')
    {
        //定义excelMap
        $excelMap = [
            'A',
            'B',
            'C',
            ...
            'Z'
        ];

        //判断起始偏移列名在excelMap键名+偏移后长度是否大于excelMap长度
        $mapCount = count($excelMap);

        $startKey = array_search($start, $excelMap);

        //不大于直接返回偏移列名
        if ($startKey + $count <= $mapCount - 1) {
            return $excelMap[$startKey + $count];
        } else { 
            //大于excelMap长度,取商在excelMap作为键名查找第一位,取余数在excelMap中查找第二位
            return $excelMap[($startKey + $count) / $mapCount - 1] . $excelMap[($startKey + $count) % $mapCount];
        }
    }
Excel导出部分:
use Maatwebsite\Excel\Facades\Excel;

//$celldata为已构造好结构的文字数据,$cloudImgs为按照key与$celldata数据对应的网络图片地址
Excel::create($fileName, function ($excel) use ($celldata, $cloudImgs) {
    $excel->sheet('score', function ($sheet) use ($celldata, $cloudImgs) {
        $sheet->rows($celldata);
        //设置图片本地路径,加上时间戳用于定时任务删除判断
        $path = config('app.excelImageCachePath') . '\\' . time();
        foreach ($cloudImgs as $key => $item) {
            foreach ($item as $k => $img) {
                //计算列名
                $x = Example::getExcelMapOffset('S', $k);
                //用网络地址换取本地存储路径
                $cloudImg = UploadHelper::getCloudImg($img, $path);
                $objDrawing = new \PHPExcel_Worksheet_Drawing();
                $objDrawing->setPath($cloudImg);
                //设置图片坐标(单元格)
                $objDrawing->setCoordinates($x . ($key + 2));
                //限定图片高度
                $objDrawing->setHeight(100);
                //图片在单元格中的偏移位置(若不设置则图位于单元格左上方)
                $objDrawing->setOffsetX(10);
                $objDrawing->setOffsetY(10);
                $objDrawing->setRotation(100);
                $objDrawing->setWorksheet($sheet);
                //如果有图片,把列拉宽
                $sheet->setWidth([$x => 40]);
            }
        }

        //设置单元格样式(第一行为title)
        $setCount = count($celldata[0]);
        for ($c = 2; $c < $setCount; $c++) {
            $sheet->setHeight([//设置第二行起每一行的高度
                $c => 100,
            ]);
        }

        //设置每一行宽度
        $sheet->setWidth([
            'A' => 15,
            'B' => 15,
        ....
        ]);

        //计算总数据量
        $count = count($celldata);
        $sheet->cells("A1:R$count", function ($cells) {
            //设置单元格内元素靠左向上
            $cells->setAlignment('left');
            $cells->setValignment('top');
        });
        //标题加粗
        $sheet->cells("A1:S1", function ($cells) {
            $cells->setFontWeight('bold');
        });
    });
})->export('xls');
更新:

今天学到了一个新东西:在处理字符变量的算数运算时,PHP 沿袭了 Perl 的习惯,而非 C 的。

    $a = 'Z';
    $a++;

将把 $a 变成 ‘AA’,而在 C 中,

a = 'Z';
    a++;

将把 a 变成 ‘[‘(’Z’ 的 ASCII 值是 90,’[’ 的 ASCII 值是 91)。

注意字符变量只能递增,不能递减,并且只支持纯字母(a-z 和 A-Z)。

所以之前的单元格坐标计算可以换成:

function getExcelMapOffset($count, $start = 'A')
{
    $start = 'A';
    for($i=0;$i<$count;$i++){
        $start++;
    }
}
return $start;

示例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值