在使用 mk-j/php_xlsxwriter 库时,markMergedCell 方法用于标记需要合并的单元格。以下是一个详细的示例,展示如何正确使用 markMergedCell 方法来合并单元格:
示例代码
php
<?php
require 'vendor/autoload.php';
use XLSXWriter;
// 创建一个新的 XLSXWriter 实例
$writer = new XLSXWriter();
// 设置表头
$header = ['姓名', '年龄', '城市'];
$writer->writeSheetHeader('Sheet1', $header);
// 数据
$data = [
['张三', 25, '北京'],
['张三', 25, '北京'],
['李四', 30, '上海'],
['李四', 30, '上海'],
['王五', 22, '广州'],
['王五', 22, '广州'],
];
// 记录需要合并的单元格范围
$mergeRanges = [];
// 遍历数据并写入单元格
$prevRow = null;
$startRow = 1; // 从第二行开始(第一行是表头)
foreach ($data as $index => $row) {
$currentRow = $index + 1; // 当前行号(从1开始)
// 如果当前行与前一行相同,则记录合并范围
if ($prevRow && $row === $prevRow) {
$mergeRanges[] = ['A' . $startRow . ':A' . $currentRow, 'B' . $startRow . ':B' . $currentRow, 'C' . $startRow . ':C' . $currentRow];
} else {
// 如果当前行与前一行不同,则更新起始行
$startRow = $currentRow;
}
// 写入当前行数据
$writer->writeSheetRow('Sheet1', $row);
// 更新前一行
$prevRow = $row;
}
// 合并单元格
foreach ($mergeRanges as $range) {
foreach ($range as $cellRange) {
list($startCell, $endCell) = explode(':', $cellRange);
list($startCol, $startRow) = parseCell($startCell);
list($endCol, $endRow) = parseCell($endCell);
$writer->markMergedCell('Sheet1', $startRow, $startCol, $endRow, $endCol);
}
}
// 设置 HTTP 头,告诉浏览器这是一个文件下载
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="example.xlsx"');
header('Cache-Control: max-age=0');
// 输出文件内容
$writer->writeToStdOut();
exit();
/**
* 解析单元格引用(如 A1)为列和行的索引
*
* @param string $cell 单元格引用(如 A1)
* @return array 列和行的索引(如 [0, 1])
*/
function parseCell($cell) {
preg_match('/([A-Z]+)(\d+)/', $cell, $matches);
$col = $matches[1];
$row = (int)$matches[2] - 1; // 行索引从0开始
// 将列字母转换为列索引
$colIndex = 0;
$len = strlen($col);
for ($i = 0; $i < $len; $i++) {
$colIndex = $colIndex * 26 + ord($col[$i]) - ord('A') + 1;
}
$colIndex -= 1; // 列索引从0开始
return [$colIndex, $row];
}
/**
* 计算单元格合并
* @param $data 数据
* @param $rules 合并规则 一行数据 下标设置 ['0','0,1','0,1,2']; 第一列 一样合并 第二列 0,1 下标数据一样合并
* @return array
* @author Lenovo
* @date 2024/10/30 下午3:43
*/
function getMergeList($data,$rules)
{
$rowIndex = count($data[0]);
$mergeRanges = [];
for ($index = 0;$index < $rowIndex;$index++)
{
$startIndex = 0;
foreach ($data as $key => $row)
{
$rule = isset($rules[$index]) ? $rules[$index] : false;
if($rule !== false){
$rule_key = explode(',', $rule);
$childRow = '';
foreach ($rule_key as $k) {
$childRow .= $row[$k];
}
if ($prevRow && $childRow === $prevRow) {
$mergeRanges[] = [$startIndex,$index,$key,$index];
}else{
$startIndex = $key;
}
$prevRow = '';
foreach ($rule_key as $k) {
$prevRow .= $row[$k];
}
}
}
}
return $mergeRanges;
}解释
创建
XLSXWriter实例:- 使用
new XLSXWriter()创建一个新的XLSXWriter实例。
- 使用
设置表头:
- 使用
writeSheetHeader方法设置表头。
- 使用
数据:
- 定义一个包含数据的数组
$data。
- 定义一个包含数据的数组
记录需要合并的单元格范围:
- 创建一个数组
$mergeRanges用于记录需要合并的单元格范围。
- 创建一个数组
遍历数据并写入单元格:
- 遍历数据数组
$data,并使用writeSheetRow方法写入每一行数据。 - 如果当前行与前一行相同,则记录合并范围。
- 如果当前行与前一行不同,则更新起始行。
- 遍历数据数组
合并单元格:
- 使用
markMergedCell方法合并单元格。 - 使用
parseCell函数将单元格引用(如A1)解析为列和行的索引。
- 使用
设置 HTTP 头:
- 使用
header函数设置 HTTP 头,告诉浏览器这是一个文件下载。
- 使用
输出文件内容:
- 使用
writeToStdOut方法将文件内容输出到标准输出(浏览器)。
- 使用
总结
通过手动解析单元格引用并使用 markMergedCell 方法,你可以在 php_xlsxwriter 中实现合并单元格的功能。这种方法适用于需要合并单元格的场景,如导出 Excel 报表时合并相同内容的单元格。确保合并单元格的逻辑和顺序正确,以避免单元格没有合并的问题。