PhpSpreadsheetで行をコピーする方法

2023年2月7日火曜日

PHP

t f B! P L

enter image description here

[adsense}

はじめに

PhpSpreadsheetは PHPで Excelファイルを操作するためのライブラリである。

今回は、この PhpSpreadsheetで Excelの行コピーを実装する方法を紹介する。

まだ PHP をインストールしていない人は、こちらの記事で導入方法を解説してますので、まずはこちらから。

PhpSpreadsheet 便利帳!すぐに使える小ネタ集

行コピーする

行コピーでは、大きく「値のコピー」と「書式のコピー」の2つの手順が必要となる。

値のコピー

PhpSpreadsheetには、Excelのセル範囲の値を配列で取得する rangeToArrayと、配列の内容をまとめて設定する fromArray 関数があるので、それを利用する。また、行の挿入には insertNewRowBefore 関数を使用する。

//Excelファイルの読み込み
$book = IOFactory::load("sample.xlsx");
$sheet = $book->getSheet(0);

//コピー元のセルアドレス
$fromAddress = "B4:F5";
//コピー先のセル
$dustAddress = "B4";

//B4からF5までのセル値を配列で取得
$range = $sheet->rangeToArray($fromAddress);

//4行目の前に2行挿入
$sheet->insertNewRowBefore(4, 2);

//B4セルを始点に、配列でコピーした値を貼り付け
$sheet->fromArray($range, null, $dustAddress);

上のコードを実行すると、次のような結果が得られる。

値をコピーしたときの実行結果

見てのとおり、fromArray 関数でコピーできるのはセルの値だけであるため、赤字やオレンジの背景などの書式はコピーされていない。

書式も含めてコピーする場合は、次の手順も踏む必要がある。

書式のコピー

背景・文字色・フォントサイズなどの書式をコピーする場合は、duplicateStyle 関数でコピー元のセルスタイルを設定する。

値のコピーのように配列でまとめてセル範囲にスタイルをコピーできないため、次のようにループしながらセル1つずつスタイルをコピーしていく。

//コピー元セル範囲の開始、終了位置をインデックスで取得
[$start, $end] = Coordinate::rangeBoundaries($fromAddress);
//コピー先セルの位置をインデックスで取得
$dustRow = (int)Coordinate::rangeBoundaries($dustAddress)[0][1];

//書式のコピー
foreach (range((int)$start[1], (int)$end[1]) as $index => $row) {
    foreach (range($start[0], $end[0]) as $col) {
        //コピー元のセルスタイル取得
        $style = $sheet->getStyleByColumnAndRow($col, $row);
        //コピー先のセルにスタイルをコピー
        $sheet->duplicateStyle($style,
            Coordinate::stringFromColumnIndex($col).strval($dustRow + $index));
    }
}

値をコピーする処理に加えて、上のコードを実行すると次のような結果となり、値と書式がコピーされているのが分かる。

値と書式をコピーしたときの実行結果

[adsense}

まとめ

PhpSpreadsheetで行コピーする方法を紹介してきました。

最後に今回紹介したソースを使いやすいように関数化したソースを置いておきます。

    public function copyRows(Worksheet $sheet, string $fromAddress, string $dustAddress)
    {
        //コピー元のセル値を配列で取得
        $range = $sheet->rangeToArray($fromAddress);

        //コピー先に値を貼り付け
        $sheet->fromArray($range, null, $dustAddress);

        //コピー元セル範囲の開始、終了位置をインデックスで取得
        [$start, $end] = Coordinate::rangeBoundaries($fromAddress);
        //コピー先セルの位置をインデックスで取得
        $dustRow = (int)Coordinate::rangeBoundaries($dustAddress)[0][1];

        //書式のコピー
        foreach (range((int)$start[1], (int)$end[1]) as $index => $row) {
            foreach (range($start[0], $end[0]) as $col) {
                //コピー元のセルスタイル取得
                $style = $sheet->getStyleByColumnAndRow($col, $row);
                //コピー先のセルにスタイルをコピー
                $sheet->duplicateStyle($style,
                    Coordinate::stringFromColumnIndex($col).strval($dustRow + $index));
            }
        }
    }
スポンサーリンク
スポンサーリンク

このブログを検索

Profile

自分の写真
Webアプリエンジニア。 日々新しい技術を追い求めてブログでアウトプットしています。
プロフィール画像は、猫村ゆゆこ様に書いてもらいました。

仕事募集もしていたり、していなかったり。

QooQ