Forked from onocom/PHPExcel-howto-range-copy.php
Last active
November 1, 2023 02:00
-
-
Save culage/b7aaace3a2de3720809c8f68337c190c to your computer and use it in GitHub Desktop.
[PHPExcel] 範囲コピー(セルの結合(マージ)にも対応、画像にも対応、行の高さにも対応、数式は相対位置でコピー)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// セルの書式を指定位置にコピーする | |
// @param $from_cells コピー元のセル範囲 | |
// @param $to_cell コピー先の左上のセル | |
// @param $copycount コピーを繰り返す回数(下へコピーするのみ) | |
function CopyCellsFormat($sheet, $from_cells, $to_cell, $copycount=1) { | |
// ---------------------------------------- | |
// コピー元のセルの範囲を数値で取得 | |
// ---------------------------------------- | |
$from_area = PHPExcel_Cell::rangeBoundaries($from_cells); // ex) array( array(2, "2"),array(53, "3")) | |
$from_start_col = (int)$from_area[0][0]; // 開始列数値 ex) B --- 2 | |
$from_start_row = (int)$from_area[0][1]; // 開始行数値 | |
$from_end_col = (int)$from_area[1][0]; // 終了列数値 ex) BA --- 53 | |
$from_end_row = (int)$from_area[1][1]; // 終了行数値 | |
// ---------------------------------------- | |
// 範囲の行数、列数を取得 | |
// ---------------------------------------- | |
$area_dmsn = PHPExcel_Cell::rangeDimension($from_cells); // ex) array( 53, 1 ) | |
$area_cols = $area_dmsn[0]; | |
$area_rows = $area_dmsn[1]; | |
// ---------------------------------------- | |
// セルをマージ | |
// ---------------------------------------- | |
// array(21) { ["AH6:AK6"]=> string(7) "AH6:AK6" ["AL6:AO6"]=> string(7) "AL6:AO6" ["AP6:AS6"]=> string(7) "AP6:AS6" ["AT6:AV6"]=> string(7) "AT6:AV6" ["AD6:AF6"]=> string(7) "AD6:AF6" ["B6:C6"]=> string(5) "B6:C6" ["D6:Q6"]=> string(5) "D6:Q6" ["R6:U6"]=> string(5) "R6:U6" ["V6:Y6"]=> string(5) "V6:Y6" ["Z6:AC6"]=> string(6) "Z6:AC6" ["B2:AW3"]=> string(6) "B2:AW3" ["B5:C5"]=> string(5) "B5:C5" ["R5:U5"]=> string(5) "R5:U5" ["V5:Y5"]=> string(5) "V5:Y5" ["Z5:AC5"]=> string(6) "Z5:AC5" ["AD5:AG5"]=> string(7) "AD5:AG5" ["AH5:AK5"]=> string(7) "AH5:AK5" ["AL5:AO5"]=> string(7) "AL5:AO5" ["AP5:AS5"]=> string(7) "AP5:AS5" ["AT5:AW5"]=> string(7) "AT5:AW5" ["D5:Q5"]=> string(5) "D5:Q5" } | |
$mg = $sheet->getMergeCells(); | |
$mg_cells = array(); | |
foreach ($mg as $mg_cell) { | |
$area = PHPExcel_Cell::rangeBoundaries($mg_cell); | |
if( $from_area[0][0] <= $area[0][0] && $from_area[1][0] >= $area[1][0] | |
&& $from_area[0][1] <= $area[0][1] && $from_area[1][1] >= $area[1][1]) { | |
$mg_cells[] = $mg_cell; | |
} | |
} | |
// コピー対象の画像を取得 | |
$image_collenction = $sheet->getDrawingCollection(); | |
$target_image = array(); | |
foreach ($image_collenction as $image) { | |
$area = PHPExcel_Cell::rangeBoundaries($image->getCoordinates()); | |
if( $from_area[0][0] <= $area[0][0] && $from_area[1][0] >= $area[1][0] | |
&& $from_area[0][1] <= $area[0][1] && $from_area[1][1] >= $area[1][1]) { | |
$target_image[] = $image; | |
} | |
} | |
$to = PHPExcel_Cell::rangeBoundaries($to_cell); // ex) array( array(2, "2"),array(53, "3")) | |
$to_start_col = (int)$to[0][0]; // 開始列数値 ex) B --- 2 | |
$to_start_row = (int)$to[0][1]; // 開始行数値 | |
// コピー回数分繰り返す | |
for( $cp_c = 0; $cp_c < $copycount; $cp_c++ ) { | |
// コピー元 | |
$from_col = $from_start_col; | |
$from_row = $from_start_row; | |
// コピー先 | |
$row_offset = $cp_c * $area_rows; // 位置の調整 | |
$start_col = $to_start_col; | |
$start_row = $to_start_row + $row_offset; | |
// 移動距離をチェック | |
$pos_col = $start_col - $from_col; | |
$pos_row = $start_row - $from_row; | |
// セル結合 | |
foreach ($mg_cells as $mg_cell) { | |
$mg_area = PHPExcel_Cell::rangeBoundaries($mg_cell); // ex) array( array(2, "2"),array(53, "3")) | |
// 位置を調整 | |
$mg_area[0][0] += $pos_col; | |
$mg_area[1][0] += $pos_col; | |
$mg_area[0][1] += $pos_row; | |
$mg_area[1][1] += $pos_row; | |
$mg_start = PHPExcel_Cell::stringFromColumnIndex($mg_area[0][0] - 1) . ($mg_area[0][1]); | |
$mg_end = PHPExcel_Cell::stringFromColumnIndex($mg_area[1][0] - 1) . ($mg_area[1][1]); | |
$mg_range = $mg_start . ":" . $mg_end; | |
$sheet->mergeCells( $mg_range ); | |
} | |
// 画像コピー | |
// コピー対象画像の取得と、画像コピーを1つのループで行うと、 | |
// foreachで回しているコレクションにアイテムを追加することで | |
// 無限ループになってしまうため注意。 | |
foreach ($target_image as $image) { | |
$area = PHPExcel_Cell::rangeBoundaries($image->getCoordinates()); | |
// 位置を調整 | |
$area[0][0] += $pos_col; | |
$area[0][1] += $pos_row; | |
$range = PHPExcel_Cell::stringFromColumnIndex($area[0][0] - 1) . ($area[0][1]); | |
$image_copy = new PHPExcel_Worksheet_Drawing(); | |
$image_copy->setResizeProportional(false); | |
$image_copy->setCoordinates ($range); | |
$image_copy->setPath ($image->getPath(), false); | |
$image_copy->setHeight ($image->getHeight()); | |
$image_copy->setWidth ($image->getWidth()); | |
$image_copy->setOffsetX ($image->getOffsetX()); | |
$image_copy->setOffsetY ($image->getOffsetY()); | |
$image_copy->setRotation ($image->getRotation()); | |
$image_copy->setShadow ($image->getShadow()); | |
$image_copy->setWorksheet($sheet); | |
} | |
// セルの書式設定 | |
for( $i = 0; $i < $area_rows; $i++ ) { | |
for( $j = 0; $j < $area_cols; $j++ ) { | |
// 値とスタイルを取得 | |
$original = PHPExcel_Cell::stringFromColumnIndex($from_col + $j - 1) . ($from_row + $i); | |
$value = $sheet->getCell($original)->getValue(); | |
if ($sheet->getCell($original)->getDataType() === PHPExcel_Cell_DataType::TYPE_FORMULA) { | |
$reference_helper = PHPExcel_ReferenceHelper::getInstance(); | |
$value = $reference_helper->updateFormulaReferences($value, "A1", $pos_col, $pos_row); | |
} | |
$style = $sheet->getCell($original)->getXfIndex(); | |
// 値とスタイルを設定 | |
$target = PHPExcel_Cell::stringFromColumnIndex($start_col + $j - 1) . ($start_row + $i); | |
$sheet->setCellValue($target, $value); | |
$sheet->getCell($target)->setXfIndex($style); | |
} | |
// 行の高さ | |
$height = $sheet->getRowDimension($from_row + $i)->getRowHeight(); | |
$sheet->getRowDimension($start_row + $i)->setRowHeight($height); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment