copy style and data in PHPExcel

后端 未结 3 1651
长情又很酷
长情又很酷 2021-02-03 14:48

I would like to copy all the data and the style of a certain range to other cells. for example I want to copy from A4: I15 and then paste exactly want I copied the contents and

3条回答
  •  臣服心动
    2021-02-03 15:15

    Update: @pavelDD pointed out that since version 1.x.x some of the imports has been renamed. Instead of accepting his edits to the original code I will share new version. Besides the renaming I've also fixed the annoying index bug and added a helper that copies styles from the original sheet. Unfortunately I'm too lazy to convert it from a class to a simple function like I did last time. But based on the previous version you should be able to do that by yourself if needed.

    getCellByColumnAndRow($col, $row);
                    $style = $sheet->getStyleByColumnAndRow($col, $row);
                    $dstCell = Coordinate::stringFromColumnIndex($destColumnStart + $colCount) . (string)($destRowStart + $rowCount);
                    $destSheet->setCellValue($dstCell, $cell->getValue());
                    $destSheet->duplicateStyle($style, $dstCell);
    
                    // Set width of column, but only once per column
                    if ($rowCount === 0) {
                        $w = $sheet->getColumnDimensionByColumn($col)->getWidth();
                        $destSheet->getColumnDimensionByColumn ($destColumnStart + $colCount)->setAutoSize(false);
                        $destSheet->getColumnDimensionByColumn ($destColumnStart + $colCount)->setWidth($w);
                    }
    
                    $colCount++;
                }
    
                $h = $sheet->getRowDimension($row)->getRowHeight();
                $destSheet->getRowDimension($destRowStart + $rowCount)->setRowHeight($h);
    
                $rowCount++;
            }
    
            foreach ($sheet->getMergeCells() as $mergeCell) {
                $mc = explode(":", $mergeCell);
                $mergeColSrcStart = Coordinate::columnIndexFromString(preg_replace("/[0-9]*/", "", $mc[0]));
                $mergeColSrcEnd = Coordinate::columnIndexFromString(preg_replace("/[0-9]*/", "", $mc[1]));
                $mergeRowSrcStart = ((int)preg_replace("/[A-Z]*/", "", $mc[0]));
                $mergeRowSrcEnd = ((int)preg_replace("/[A-Z]*/", "", $mc[1]));
    
                $relativeColStart = $mergeColSrcStart - $srcColumnStart;
                $relativeColEnd = $mergeColSrcEnd - $srcColumnStart;
                $relativeRowStart = $mergeRowSrcStart - $srcRowStart;
                $relativeRowEnd = $mergeRowSrcEnd - $srcRowStart;
    
                if (0 <= $mergeRowSrcStart && $mergeRowSrcStart >= $srcRowStart && $mergeRowSrcEnd <= $srcRowEnd) {
                    $targetColStart = Coordinate::stringFromColumnIndex($destColumnStart + $relativeColStart);
                    $targetColEnd = Coordinate::stringFromColumnIndex($destColumnStart + $relativeColEnd);
                    $targetRowStart = $destRowStart + $relativeRowStart;
                    $targetRowEnd = $destRowStart + $relativeRowEnd;
    
                    $merge = (string)$targetColStart . (string)($targetRowStart) . ":" . (string)$targetColEnd . (string)($targetRowEnd);
                    //Merge target cells
                    $destSheet->mergeCells($merge);
                }
            }
        }
    
        public static function copyStyleXFCollection(Spreadsheet $sourceSheet, Spreadsheet $destSheet) {
            $collection = $sourceSheet->getCellXfCollection();
    
            foreach ($collection as $key => $item) {
                $destSheet->addCellXf($item);
            }
        }
    }
    ?>
    

    I've taken Prashant's answer and extended it for easier use and added some additional functionality. It was a great source to begin with. But it was missing some key features for me: Taking a range (e.g. A10:B15) instead of just indexes Taking a destination cell rather then just a row. Setting width of the destination columns

    Please note that I'm using PHPSpreadsheet, the successor of PHPExcel. If you are using the older version just need to update the path for the Cell class.

    getCellByColumnAndRow($col, $row);
                $style = $sheet->getStyleByColumnAndRow($col, $row);
                $dstCell = Cell::stringFromColumnIndex($destColumnStart + $colCount) . (string)($destRowStart + $rowCount);
                $sheet->setCellValue($dstCell, $cell->getValue());
                $sheet->duplicateStyle($style, $dstCell);
    
                // Set width of column, but only once per row
                if ($rowCount === 0) {
                    $w = $sheet->getColumnDimensionByColumn($col)->getWidth();
                    $sheet->getColumnDimensionByColumn ($destColumnStart + $colCount)->setAutoSize(false);
                    $sheet->getColumnDimensionByColumn ($destColumnStart + $colCount)->setWidth($w);
                }
    
                $colCount++;
            }
    
            $h = $sheet->getRowDimension($row)->getRowHeight();
            $sheet->getRowDimension($destRowStart + $rowCount)->setRowHeight($h);
    
            $rowCount++;
        }
    
        foreach ($sheet->getMergeCells() as $mergeCell) {
            $mc = explode(":", $mergeCell);
            $mergeColSrcStart = Cell::columnIndexFromString(preg_replace("/[0-9]*/", "", $mc[0])) - 1;
            $mergeColSrcEnd = Cell::columnIndexFromString(preg_replace("/[0-9]*/", "", $mc[1])) - 1;
            $mergeRowSrcStart = ((int)preg_replace("/[A-Z]*/", "", $mc[0]));
            $mergeRowSrcEnd = ((int)preg_replace("/[A-Z]*/", "", $mc[1]));
    
            $relativeColStart = $mergeColSrcStart - $srcColumnStart;
            $relativeColEnd = $mergeColSrcEnd - $srcColumnStart;
            $relativeRowStart = $mergeRowSrcStart - $srcRowStart;
            $relativeRowEnd = $mergeRowSrcEnd - $srcRowStart;
    
            if (0 <= $mergeRowSrcStart && $mergeRowSrcStart >= $srcRowStart && $mergeRowSrcEnd <= $srcRowEnd) {
                $targetColStart = Cell::stringFromColumnIndex($destColumnStart + $relativeColStart);
                $targetColEnd = Cell::stringFromColumnIndex($destColumnStart + $relativeColEnd);
                $targetRowStart = $destRowStart + $relativeRowStart;
                $targetRowEnd = $destRowStart + $relativeRowEnd;
    
                $merge = (string)$targetColStart . (string)($targetRowStart) . ":" . (string)$targetColEnd . (string)($targetRowEnd);
                //Merge target cells
                $sheet->mergeCells($merge);
            }
        }
    }
    ?>
    

    Example usage:

    copyRange($sheet, 'A4:B8', 'E1');
    copyRange($sheet, 'A4:B8', 'A10');
    copyRange($sheet, 'A4:B8', 'C17');
    

    Note: I haven't tried it with a single cell. But in theory it should work with A1:A1

    Please let me if I have made any mistake, or feel free to edit the answer.

提交回复
热议问题