PhpSpreadsheet 导出特定格式 — 广告请款单

需求说明

最近需要实现一个导出这种格式的Excel表单,之前都有用过导出Excel的功能,但大都是表头+数据的形式,只用于获取数据,没有太多样式要求,不用合并单元格、合并居中等,也不用对每一行数据特异化定制的,所以对PhpSpreadsheet扩展库进行进阶理解。

解决过程

从github->官方文档->api文档->CSDN文章(文末有链接),完了跟着操作都会一直报错,csdn的那篇文章中一旦调用了样式的方法后,返回对象就变成了样式相关的,不能继续指定工作单元了,所以仍然不是太实用,只能作为参考了。

最后通过看源码 + api文档实现了这部分的功能点。

需要用到的方法

  1. mergeCells():合并单元格,参数为起始单元格到结束单元格
  2. getCellByColumnAndRow(): 获取指定位置的单元格对象
  3. setValueExplicit():设置单元格内容,并指定样式
  4. getStyle():获取单元格样式对象
  5. applyFromArray():指定单元格样式

代码片段解读

1、填充单元格数据

$sheet->mergeCells('A1:K2')->getCellByColumnAndRow(1, 1)->setValueExplicit('广告请款单', $contentType);
  1. mergeCells(‘A1:K2‘): 从A1合并到K2
  2. getCellByColumnAndRow(1, 1): 获取第一行第一列单元格对象
  3. setValueExplicit(‘广告请款单‘, $contentType): 填充内容为广告请款单, 并指定为字符串类型($contentType = DataType::TYPE_STRING)

2、指定样式

$styleArray = [
    'alignment' => [
        // 水平居中
        'horizontal' => Alignment::HORIZONTAL_CENTER,
        // 垂直居中
        'vertical' => Alignment::VERTICAL_CENTER,
        // 自动换行
        'wrapText' => true
    ],
];
$sheet->getStyle('A1:K21')->applyFromArray($styleArray);
  1. ‘wrapText‘ => true 指定单元格内容自动换行,会自动解析文本内容中的\n,\r\n换行符
  2. applyFromArray() 方法在\PhpOffice\PhpSpreadsheet\Style\Alignment类中,可根据需要指定参数;
  3. 注意:指定样式要在所有单元格数据设置之后,因为设置样式后返回的结果是\PhpOffice\PhpSpreadsheet\Style\Alignment对象,没有mergeCells()等设置单元格的方法了

剩余的麻烦点就是计算每个特定合并单元的位置了

暴力实现

起初在试验过程,理论基础不够充足,所以就通过暴力计算每个样式位置并进行设置了。

$contentType = DataType::TYPE_STRING;
$sheet->mergeCells('A1:K2')->getCellByColumnAndRow(1, 1)->setValueExplicit('广告请款单', $contentType);

$sheet->mergeCells('A3:B4')->getCellByColumnAndRow(1, 3)->setValueExplicit('申请时间', $contentType);
$sheet->mergeCells('C3:E4')->getCellByColumnAndRow(3, 3)->setValueExplicit(date('Y-m-d H:i:s', $data['apply_clear_time']), $contentType);
$sheet->mergeCells('F3:G4')->getCellByColumnAndRow(6, 3)->setValueExplicit('广告编号', $contentType);
$sheet->mergeCells('H3:K4')->getCellByColumnAndRow(8, 3)->setValueExplicit($data['ad_no'], $contentType);

$sheet->mergeCells('A5:B6')->getCellByColumnAndRow(1, 5)->setValueExplicit('收款单位', $contentType);
$sheet->mergeCells('C5:K6')->getCellByColumnAndRow(3, 5)->setValueExplicit($data['real_name'], $contentType);

$sheet->mergeCells('A7:B8')->getCellByColumnAndRow(1, 7)->setValueExplicit('银行账户', $contentType);
$sheet->mergeCells('C7:K8')->getCellByColumnAndRow(3, 7)->setValueExplicit($data['bank_no'], $contentType);

$sheet->mergeCells('A9:B10')->getCellByColumnAndRow(1, 9)->setValueExplicit('开户行', $contentType);
$sheet->mergeCells('C9:K10')->getCellByColumnAndRow(3, 9)->setValueExplicit($data['bank_name'], $contentType);

$sheet->mergeCells('A11:B12')->getCellByColumnAndRow(1, 11)->setValueExplicit('金额', $contentType);
$sheet->mergeCells('C11:E12')->getCellByColumnAndRow(3, 11)->setValueExplicit($data['amount'], $contentType);
$sheet->mergeCells('F11:G12')->getCellByColumnAndRow(6, 11)->setValueExplicit('大写金额', $contentType);
$sheet->mergeCells('H11:K12')->getCellByColumnAndRow(8, 11)->setValueExplicit($data['amount_desc'], $contentType);

$sheet->mergeCells('A13:B14')->getCellByColumnAndRow(1, 13)->setValueExplicit('备注', $contentType);
$sheet->mergeCells('C13:K14')->getCellByColumnAndRow(3, 13)->setValueExplicit($data['desc'], $contentType);

$sheet->mergeCells('A15:D16')->getCellByColumnAndRow(1, 15)->setValueExplicit('广告BD审核', $contentType);
$sheet->mergeCells('E15:H16')->getCellByColumnAndRow(5, 15)->setValueExplicit('广告主管审核', $contentType);
$sheet->mergeCells('I15:K16')->getCellByColumnAndRow(9, 15)->setValueExplicit('总经理审核', $contentType);

$sheet->mergeCells('A17:D19')->getCellByColumnAndRow(1, 17)->setValueExplicit($data['auth_log_list'][0]['auth_desc'], $contentType);
$sheet->mergeCells('E17:H19')->getCellByColumnAndRow(5, 17)->setValueExplicit($data['auth_log_list'][1]['auth_desc'], $contentType);
$sheet->mergeCells('I17:K19')->getCellByColumnAndRow(9, 17)->setValueExplicit($data['auth_log_list'][2] ? $data['auth_log_list'][2]['auth_desc'] : '无需审核', $contentType);

$sheet->mergeCells('A20:B21')->getCellByColumnAndRow(1, 20)->setValueExplicit('财务', $contentType);
$sheet->mergeCells('C20:K21')->getCellByColumnAndRow(3, 20)->setValueExplicit('', $contentType);

封装

复杂点

唯一需要计算一下的就是mergeCells()方法和getCellByColumnAndRow()方法的参数

$sheet->mergeCells($start.':'.$end)->getCellByColumnAndRow($column_start, $row_start)->setValueExplicit($column[2], $contentType);

但是通过暴力破解的过程也很好得到规律。

通用方法

public static function exportSpecialExcel($data, $filename='', $post=false)
{
    // 此处只需要导出单条数据,对内存没要求,
    // ini_set('memory_limit', '3072M');

    if (empty($filename)) {
        $filename = date('Y-m-d') . '导出表格';
    }

    $pathinfo = pathinfo($filename);
    if (empty($pathinfo['extension']) || !in_array($pathinfo['extension'], ['xls', 'xlsx'])) {
        $filename = $filename . '.xlsx';
    }

    $spreadsheet = new Spreadsheet();
    $sheet= $spreadsheet->getActiveSheet();

    $contentType = DataType::TYPE_STRING;

    /**
     * column
     *  0 - 行高
     *  1 - 列宽
     *  2 - 数据内容
     */
    $row_start = 1;
    foreach ($data as $row) {
        $column_start = 1;
        foreach ($row as $column) {
            $start = (static::$column_header[$column_start]) . $row_start;
            $end = (static::$column_header[$column_start + $column[1] - 1]).($row_start + $column[0] - 1);
            $sheet->mergeCells($start.':'.$end)->getCellByColumnAndRow($column_start, $row_start)->setValueExplicit($column[2], $contentType);
            $column_start += $column[1];
        }
        $row_start += $row[0][0];
    }

    $styleArray = [
        'alignment' => [
            'horizontal' => Alignment::HORIZONTAL_CENTER,
            'vertical' => Alignment::VERTICAL_CENTER,
            'wrapText' => true
        ],
    ];
    $sheet->getStyle('A1:K21')->applyFromArray($styleArray);

    header('Content-Description: File Transfer');
    header('Expires: 0');
    header('Pragma: public');
    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');//告诉浏览器输出07Excel文件
    header('Content-Disposition: attachment;filename="' . $filename . '"');
    header('Cache-Control: max-age=0');
    $writer = new Xlsx($spreadsheet);
    $writer->save('php://output');
    //删除清空:
    LogHelper::access(memory_get_peak_usage(), 'export_memory');
    $spreadsheet->disconnectWorksheets();
    unset($spreadsheet);
    exit;
}

业务数据

每个子元素数组由行高、列宽、数据内容三者组成

$showData = [
    [
        [2, 11, '广告请款单'],
    ],
    [
        [2, 2, '申请时间'],
        [2, 3, date('Y-m-d H:i:s', $data['apply_clear_time'])],
        [2, 2, '广告编号'],
        [2, 4, $data['ad_no']],
    ],
    [
        [2, 2, '收款单位'],
        [2, 9, $data['real_name']],
    ],
    [
        [2, 2, '银行账户'],
        [2, 9, $data['bank_no']],

    ],
    [
        [2, 2, '开户行'],
        [2, 9, $data['bank_name']],
    ],
    [
        [2, 2, '金额'],
        [2, 3, $data['amount']],
        [2, 2, '大写金额'],
        [2, 4, $data['amount_desc']],
    ],
    [
        [2, 2, '备注'],
        [2, 9, $data['desc']],
    ],
    [
        [2, 4, '广告BD审核'],
        [2, 4, '广告主管审核'],
        [2, 3, '总经理审核'],
    ],
    [
        [3, 4, $data['auth_log_list'][0]['auth_desc']],
        [3, 4, $data['auth_log_list'][1]['auth_desc']],
        [3, 3, isset($data['auth_log_list'][2]) ? $data['auth_log_list'][2]['auth_desc'] : '无需审核'],
    ],
    [
        [2, 2, '财务'],
        [2, 9, ''],
    ],
];

如此便实现了本次的业务需求,也便于今后相关业务功能的实现

参考资料

  1. github-PhpSpreadsheet: github源码库,可学习安装
  2. phpspreadsheet 文档 全英文文档
  3. phpspreadsheet api 库的类和方法说明
  4. CSDN-详解PhpSpreadsheet设置单元格:由官方文档整理出的部分使用案例,但过于简单,直接使用仍然会出现问题

原文地址:https://www.cnblogs.com/zqunor/p/11712075.html

时间: 2024-10-29 19:12:17

PhpSpreadsheet 导出特定格式 — 广告请款单的相关文章

使用Apache POI导出Excel小结--导出XLS格式文档

使用Apache POI导出Excel小结 关于使用Apache POI导出Excel我大概会分三篇文章去写 使用Apache POI导出Excel小结--导出XLS格式文档 使用Apache POI导出Excel小结--导出XLSX格式文档 使用Apache POI导出Excel--大数量导出 导出XLS格式文档 做企业应用项目难免会有数据导出到Excel的需求,最近在使用其,并对导出Excel封装成工具类开放出来供大家参考.关于Apache POI Excel基本的概念与操作我在这里就不啰嗦

使用PHPExcel导入导出excel格式文件

使用PHPExcel导入导出excel格式文件 作者:zccst 由于导出使用较多,下面是导出实现过程. 第一步,将PHPExcel的源代码复制到项目的lib下 文件包括:PHPExcel.php 和 文件夹PHPExcel 源代码见附件 注1:源代码是zip格式,能在windows和linux通用. 注2:PHPExcel.zip是干净代码,可以直接引用.PHPExcel2.zip有svn记录,不适合直接引用. 第二步:在需要导出的handler页面中引用 1,在头部引入三个文件 Php代码 

CSVHelper 导出CSV 格式

public class CSVHelper { System.Windows.Forms.SaveFileDialog saveFileDialog1;//保存 private string header = string.Empty;//标题 /// <summary> /// 初始化打印设置 /// </summary> /// <param name="printID"></param> protected void InitEx

拍大师导出其他格式视频操作方法图文教程

拍大师是一款很好用的视频制作软件,大家再用它制作好视频后怎么导出视频呢?小编给大家小小的分享下,导出的视频格式如果默认的不是自己想要的,那怎么办呢?小编告诉大家怎么使用拍大师导出其他格式的视频?这样大家就可以根据自己的需要来选择自己的视频格式了. 步骤一:如果需要导出制作好的作品为其他视频格式,你可以打开创作工场,点左上方我的作品,然后鼠标移到你要导出的视频上面,点"导出"按钮--然后点确定 步骤二:选择你需要导出的视频格式,然后点"选择路径"按钮,选择你导出后的视

PHP导入与导出xml格式的Excel

1 简介 1.1 导出 在实际的工作项目中,经常需要将一些重要的数据库中存的数据导出成Excel,比如导出考勤报表,导出财务报表,导出业绩报表,导出销售报表等.CleverCode以前使用了两年的PHPExcel来制作Excel导出数据,但发现用PHPExcel生成Excel实在是太麻烦了,特别是控制单元格的颜色,合并单元格,给单元格设置长度等.这些设计一个Excel通常会需要花费一天的时间.后来CleverCode发现了一个简便的方法PHP导出xml格式的Excel,以前需要一天的工作量,现在

fusioncharts批量导出图片之后自动提交表单

最近一个项目  一个页面有多个fusioncharts,需要将他们一次性导出之后再利用图片做一下操作,制作一个可以客户下载的质检简报. 对客户效果来说,我只需要点击一个按钮就能生成简报并且下载,对开发人员来说就需要,先将图片导出(当然不能挨个导出,要同时执行导出,因为fusioncharts导出太慢了),要确认全部导出了才能提交表单,要不然提交表单之后,图片没有生成出来必然产生异常.下面我们来看一下实现 首先我给每一个fusionchartschart指定一个有规律的id,作用有两个: 一个是导

PDMS模型导出RVM格式

2 .将PDMS中对象模型导出为RVM格式的宏文件代码如下: eg:如果要导出某几个房间内的全部bran equi !strus = array()!strus.append(|/1RXR246ZL|)!strus.append(|/1RXR148ZL|)!strus.append(|/1RXR248ZL|)!strus.append(|/1RXR220ZL|)!strus.append(|/1RXR748ZL|)!strus.append(|/1RXR521ZL|)!strus.append(

报表XML导出rtf格式,结果在浏览器中打开XML文件。用360浏览器下载rtf文件打开后出现Authentication failed 问题

报表XML导出rtf格式,结果在浏览器中打开XML文件.用360浏览器下载rtf文件打开后出现Authentication failed 问题 直接上问题图: 问题描述:在Oracle EBS中执行"资源事务处理 XML"请求,选择输出rtf格式,完成后查看输出,却在浏览器中打开了XML文件.        提示:需要检查一下是否有对应的模板文件和模板定义有效时间.        解决方案:1. 查看日志. 从中可以看出出错原因,以及模板代码.2. 添加Oracle XML Publi

利用XSD配合XSLT產出特定格式Word檔案 -摘自网络

利用類別產生XSD檔 產出XSD檔的目的在於提供Word樣板設計之資料框架 在此使用微軟提供之XML Schema Definition Tool (Xsd.exe)工具產生XSD檔 1. 定義類別 view source print? 01 // 書籍資料 02 public class Book 03 { 04     public string BookId { get; set; } 05     public string Name { get; set; } 06     publi