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

解决过程
从github->官方文档->api文档->CSDN文章(文末有链接),完了跟着操作都会一直报错,csdn的那篇文章中一旦调用了样式的方法后,返回对象就变成了样式相关的,不能继续指定工作单元了,所以仍然不是太实用,只能作为参考了。
最后通过看源码 + api文档实现了这部分的功能点。
需要用到的方法
- mergeCells():合并单元格,参数为起始单元格到结束单元格
- getCellByColumnAndRow(): 获取指定位置的单元格对象
- setValueExplicit():设置单元格内容,并指定样式
- getStyle():获取单元格样式对象
- applyFromArray():指定单元格样式
代码片段解读
1、填充单元格数据
$sheet->mergeCells('A1:K2')->getCellByColumnAndRow(1, 1)->setValueExplicit('广告请款单', $contentType);
mergeCells('A1:K2'): 从A1合并到K2getCellByColumnAndRow(1, 1): 获取第一行第一列单元格对象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);
'wrapText' => true指定单元格内容自动换行,会自动解析文本内容中的\n,\r\n换行符applyFromArray()方法在\PhpOffice\PhpSpreadsheet\Style\Alignment类中,可根据需要指定参数;- 注意:指定样式要在所有单元格数据设置之后,因为设置样式后返回的结果是
\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, ''],
],
];
如此便实现了本次的业务需求,也便于今后相关业务功能的实现
参考资料
- github-PhpSpreadsheet: github源码库,可学习安装
- phpspreadsheet 文档 全英文文档
- phpspreadsheet api 库的类和方法说明
- CSDN-详解PhpSpreadsheet设置单元格:由官方文档整理出的部分使用案例,但过于简单,直接使用仍然会出现问题
PhpSpreadsheet 导出特定格式 — 广告请款单的更多相关文章
- Java导出Pdf格式表单
前言 作为开发人员,工作中难免会遇到复杂表单的导出,接下来介绍一种通过Java利用模板便捷导出Pdf表单的方式 模拟需求 需求:按照下面格式导出pdf格式的学生成绩单 准备工作 Excel软件 ...
- Powerdesigner 导出Excel格式数据字典 导出Excel格式文件
版权声明:本文为博主原创文章,转载请注明出处; 网上我也看到了很多的Powerdesigner 导出方法,因为Powerdesigner 提供了部分VBA功能,所以让我用代码导出Excel格式文件得以 ...
- 使用Apache POI导出Excel小结--导出XLS格式文档
使用Apache POI导出Excel小结 关于使用Apache POI导出Excel我大概会分三篇文章去写 使用Apache POI导出Excel小结--导出XLS格式文档 使用Apache POI ...
- 使用PHPExcel导入导出excel格式文件
使用PHPExcel导入导出excel格式文件 作者:zccst 因为导出使用较多,以下是导出实现过程. 第一步,将PHPExcel的源码拷贝到项目的lib下 文件包含:PHPExcel.ph ...
- phpspreadsheet导出数据到Excel
之前我们使用PHP导出Excel数据时使用的是PHPExcel库,但是phpoffice已经官方宣布PHPExcel已经被废弃不在维护,推荐使用phpspreadsheet,如下图所示 我们可以通过c ...
- Html Table用JS导出excel格式问题 导出EXCEL后单元格里的000412341234会变成412341234 7-14 会变成 2018-7-14(7月14) 自定义格式 web利用table表格生成excel格式问题 js导出excel增加表头、mso-number-format定义数据格式 数字输出格式转换 mso-number-format:"\@"
Html Table用JS导出excel格式问题 我在网上找的JS把HTML Tabel导出成EXCEL.但是如果Table里的数字内容为0开的的导成Excel后会自动删除0,我想以text的格式写入 ...
- C#关于时间(获取特定格式的时间及多种方式获取当前时间戳)以及10位和13位时间戳转为特定格式
C#关于时间(获取特定格式的时间及多种方式获取当前时间戳)以及10位和13位时间戳转为特定格式 置顶 2018年03月06日 19:16:51 黎筱曦 阅读数:19098 标签: C#时间 更多 个人 ...
- SQL SERVER导出特殊格式的平面文件
有时候我们需要将SQL SERVER的数据一次性导入到ORACLE中,对于数据量大的表.我一般习惯先从SQL SERVER导出特殊格式的平面文件(CSV或TXT),然后用SQL*Loader装载数据到 ...
- OAF_文件系列2_实现OAF导出CSV格式文件ExportButton(案例)
20150727 Created By BaoXinjian
随机推荐
- lambda表达式分类
public class StreamTest { public static void main(String[] args) { createStream(); getForEach(); get ...
- zookeeper 单机. 集群环境搭建
zookeeper分布式系统中面临的很多问题, 如分布式锁,统一的命名服务,配置中心,集群的管理Leader的选举等 环境准备 分布式系统中各个节点之间通信,Zookeeper保证了这个过程中 数据的 ...
- pycharm中报ImportError: libcublas.so.9.0错误的解决方法。
前些天不知为啥cuda不能用了,nvidia-smi也没反应.然后我就重新装了一下cuda.后来使用pycharm远程连接时,居然报错了. ImportError: libcublas.so.9.0: ...
- iOS -打包上传成功,在"构建版本"一直刷不出来
今天提交版本到appstore,构建版本一直不出来,等了一天也没有出来,其实就是权限问题,iOS13 来了,所以面临的问题随之而来,苹果给邮箱发了这段话: Dear Developer,We iden ...
- (六十九)c#Winform自定义控件-垂直滚动条
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...
- .netCore+Vue 搭建的简捷开发框架 (2)--仓储层实现和EFCore 的使用
书接上文,继续搭建我们基于.netCore 的开发框架.首先是我们的项目分层结构. 这个分层结构,是参考张老师的分层结构,但是实际项目中,我没有去实现仓储模型.因为我使用的是EFCore ,最近也一直 ...
- Spring IOC MVC DI简单实现
目录的大致情况:所有的类都会加进来. 1.首先先写基本的Controller Service ServiceImpl Controller Service ServiceImpl是用来验证下面写的框架 ...
- 【面试】我是如何在面试别人Redis相关知识时“软怼”他的
事出有因 Redis是一个分布式NoSQL数据库,因其数据都存储在内存中,所以访问速度极快,因此几乎所有公司都拿它做缓存使用,所以Redis常被称为分布式缓存. 一次我的一个同事让我帮他看Redis相 ...
- 将Jexus+mono和网站一起通过Dockerfile打包到docker镜像
上次使用别人打包好的docker镜像,往里边加入文件,最终asp.net的docker容器化运行. 这次决定直接全新打包一个jexus+asp.net网站的docker包. 进入root目录,并在ro ...
- 深入理解perf报告中的swapper进程
一.前言 1.在perf监控进程的系统调用时,会出现大量swapper进程 2.官方描述该进程是当CPU上没有其他任务运行时,就会执行swapper.换句话说swapper意味着CPU啥事也没干,跑去 ...