Laravel Excel 导入处理单元格合并数据

想要实现功能:

在导入该excel时,想要获取数组

$array = [
    ['xx公司','A部门','a中心'],
    ['xx公司','A部门','b中心'],
    ['xx公司','A部门','c中心'],
    ['xx公司','D部门','d中心'],
];

因为有合并单元格,所以读取excel内容A2:A5 的内容只有A2为XX公司,其余的均为null,所以我们只要获取到excel中合并单元格的范围,就可以将其余的null值赋予单元格的第一位;在phpExcel中获取单元格合并范围的函数为

getMergeCells()

但是在laravel excel中使用该函数获取的均为空数组,究其原因是默认读取excelData 数据设置

setReadDataOnly(true)

导致无法正确的读取excel具体格式,所以只要更改真个属性为false,就可以正确的使用getMergeCells()

但是我没有找到如何更改laravel excel 的这个属性所以只能用这种笨方法,用phpexcel原生方法设置setReadDataOnly(false)然后获取phpexcel原生的getMergeCells(),然后给laravel excel中返回结果赋值:

<?php


namespace App\Imports;


use Maatwebsite\Excel\Concerns\ToArray;
use Maatwebsite\Excel\Concerns\WithCalculatedFormulas;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Maatwebsite\Excel\Concerns\WithStartRow;
use Maatwebsite\Excel\Events\BeforeImport;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;

/**
 * 获取合并数据的excel 并将合并的单元格数据赋值:当前合并第一个单元格的数据,调用array(),方法可以获取正确的数据
 * Class mergeCellBasicImport
 * @package App\Imports
 */
class mergeCellBasicImport  implements WithEvents,ToArray, WithStartRow, WithCalculatedFormulas,WithMultipleSheets
{
    public $filePath;

    public $startRow = 2;

    public $mergeCells = [];

    public function __construct($startRow = 2, $filePath = '')
    {
        $this->filePath = $filePath;
    }

    /**
     * 将合并数据进行赋值,调用eg: $import = new mergeCellBasicImport(2,$filePath);$array = $excel->toArray($import,$file);$array = $import->array($array);
     * @param array $array
     * @return array
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     */
    public function array(array $array): array
    {
        if ($this->mergeCells) {
            $startRow = $this->startRow;
            foreach ($this->mergeCells as $key => $mergeCells) {
                if ($mergeCells && is_array($mergeCells)) {
                    foreach ($mergeCells as $mergeCell) {
                        [$begin, $end] = Coordinate::getRangeBoundaries($mergeCell);
                        //要和数组对应行列保持一直 数据对应: $array[$key][$row][$col],所以要进行行数据 - startRow ;列数据 - 1
                        $beginRow = $begin[1] - $startRow;
                        $beginCol = Coordinate::columnIndexFromString($begin[0]) - 1;
                        $endRow = $end[1] - $startRow;
                        $endCol = Coordinate::columnIndexFromString($end[0]) - 1;

                        $value = $array[$key][$beginRow][$beginCol];
                        for ($intCol = $beginCol; $intCol <= $endCol; $intCol++) {
                            for ($intRow = $beginRow; $intRow <= $endRow; $intRow++) {
                                $array[$key][$intRow][$intCol] = $value;
                            }
                        }
                    }
                }
            }
        }
        return $array;
    }

    public function registerEvents(): array
    {
        return [
            BeforeImport::class => function (BeforeImport $event) {
                //因为我无法设置laravel-excel中的setReadDataOnly 为false,所以在原生iof中设置setReadDataOnly 为false,获取合并数据
                $iofReader = $event->reader->getPhpSpreadsheetReader();
                $iofReader->setReadDataOnly(false);
                $iofLoad = $iofReader->load($event->getConcernable()->filePath);
                $mergeCells = [];
                foreach ($iofLoad->getAllSheets() as $key => $item) {
                    $mergeCells[$key] = $item->getMergeCells();
                }
                $event->getConcernable()->mergeCells = $mergeCells;
            },
        ];
    }

    public function sheets(): array
    {
       return [
           0 => new self()
       ];
    }

    public function startRow(): int
    {
        return $this->startRow;
    }
}

调用的方法是: 

        $import = new mergeCellBasicImport(2,$request->file('file')->getRealPath());
        $sheets =$excel->toArray($import, $request->file('file'));
        $sheet = $import->array($sheets)[0];

利用toArray的方式获取对应数组,再利用array()方法进行将数据变成想要的格式,dd打印结果如下:

array:4 [
  0 => array:3 [
    0 => "XX公司"
    1 => "A部门"
    2 => "a中心"
  ]
  1 => array:3 [
    0 => "XX公司"
    1 => "A部门"
    2 => "b中心"
  ]
  2 => array:3 [
    0 => "XX公司"
    1 => "A部门"
    2 => "c中心"
  ]
  3 => array:3 [
    0 => "XX公司"
    1 => "D部门"
    2 => "d中心"
  ]
]

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是Java中使用Apache POI库实现Excel导入合并单元格的示例代码: ```java import java.io.File; import java.io.FileInputStream; import java.io.IOException; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ExcelImportAndMergeCells { public static void main(String[] args) throws IOException { // 读取Excel文件 FileInputStream inputStream = new FileInputStream(new File("example.xlsx")); Workbook workbook = WorkbookFactory.create(inputStream); Sheet sheet = workbook.getSheetAt(0); // 合并单元格 CellRangeAddress mergedRegion = new CellRangeAddress(0, 1, 0, 3); sheet.addMergedRegion(mergedRegion); // 设置合并单元格的样式 XSSFCellStyle style = (XSSFCellStyle) workbook.createCellStyle(); style.setAlignment(CellStyle.ALIGN_CENTER); style.setVerticalAlignment(CellStyle.VERTICAL_CENTER); Row row = sheet.getRow(0); Cell cell = row.getCell(0); cell.setCellStyle(style); // 输出合并单元格的值 System.out.println(row.getCell(0).getStringCellValue()); // 关闭文件流 inputStream.close(); } } ``` 上述代码中,我们首先使用`FileInputStream`读取Excel文件,然后使用`WorkbookFactory`创建`Workbook`对象,接着获取第一个`Sheet`对象。接下来,我们使用`CellRangeAddress`创建一个需要合并单元格区域,使用`Sheet`的`addMergedRegion`方法将单元格区域合并。然后,我们使用`Workbook`的`createCellStyle`方法创建一个单元格样式,设置样式的对齐方式和垂直对齐方式,将样式应用到合并后的单元格上。最后,我们输出合并单元格的值,并关闭文件流。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值