以前ご紹介したLaravel Excelの続きです。今回はExcelシートに画像を挿入する方法についてご紹介いたします。

WithDrawings

公式ドキュメントに画像を挿入する手順について説明がありますのでそちらを参考に進めて行きます。

まず、挿入する画像をpublic/img配下に配置します。ファイル名はとりあえずmike.jpgとしました。適当な画像が無ければ以下のサンプル画像を使って頂いても構いませんよ!

次に、Exportクラスを作成します、今回はImageExportとしました。

php artisan make:export ImageExport

次に、ImageExportクラスにてWithDrawingsをimplementし、drawings()を実装します。drawings()内で使うDrawingクラスはPhpSpreadsheetのクラスなのでそちらをuseするのも忘れずに。


namespace App\Exports;

use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\WithDrawings;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;

class ImageExport implements WithDrawings
{
    use Exportable;

    public function drawings()
    {
        $drawing = new Drawing();
        $drawing->setPath(public_path('/img/mike.jpg'));    // 画像のパス指定
        $drawing->setCoordinates('A1');     // 出力先のセルを指定
        
        return $drawing;
    }
}

一度、tinkerから出力してみましょう。以下を実行すると storage/app/test.xlsx が出力されるはずです。

use App\Exports\ImageExport;
(new ImageExport)->store('test.xlsx');
=> true

出力されたファイルはこんな感じです。setCoordinates()で指定した通り、画像の左上がセルのA1に揃えられています。

因みにドキュメントにもある通り、複数の画像を出力する際はdrawings()からDrawingインスタンスの配列をreturnします。試しにA1C1にそれぞれ同じ画像を出力してみましょう。

...
    public function drawings()
    {
        $drawing1 = new Drawing();
        $drawing1->setPath(public_path('/img/mike.jpg'));
        $drawing1->setCoordinates('A1');

        $drawing2 = new Drawing();
        $drawing2->setPath(public_path('/img/mike.jpg'));
        $drawing2->setCoordinates('C1');
        
        return [$drawing1, $drawing2];
    }
...

出力は以下のようになります。

画像の幅や高さを変更する

前項で出力した画像は元の画像のサイズのまま出力されています。出力する画像の幅や高さを変更したい場合はsetWidth(),setHeight()が使えます。drawings()を編集して高さを2倍にした画像、幅を2倍にした画像をそれぞれ出力してみましょう。

...
    public function drawings()
    {
        // 元のサイズ
        $drawing1 = new Drawing();
        $drawing1->setPath(public_path('/img/mike.jpg'));
        $drawing1->setCoordinates('A1');

        // 高さ2倍
        $drawing2 = new Drawing();
        $drawing2->setPath(public_path('/img/mike.jpg'));
        $drawing2->setCoordinates('C1');
        $drawing2->setHeight($drawing1->getHeight() * 2);

        // 幅2倍
        $drawing3 = new Drawing();
        $drawing3->setPath(public_path('/img/mike.jpg'));
        $drawing3->setCoordinates('G1');
        $drawing3->setWidth($drawing1->getWidth() * 2);
         
        return [$drawing1, $drawing2, $drawing3];
    }
...

出力は以下になりました。

あれ、同じサイズになりましたね、もしかして元のアスペクト比のままサイズ変更される?

どうやらそのようです。
Drawingの親クラスであるBaseDrawingクラス(vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/BaseDrawing.php)を確認するとsetWidth(), setHeight()にて、resizeProportionaltrueなら元のアスペクト比を維持しています。そして、デフォルトのresizeProportionaltrueです。

もし、アスペクト比を無視して幅や高さを変更したい場合は、

...
        // 高さ2倍
        $drawing2 = new Drawing();
        $drawing2->setPath(public_path('/img/mike.jpg'));
        $drawing2->setCoordinates('C1');
        $drawing2->setResizeProportional(false); //アスペクト比を無視
        $drawing2->setHeight($drawing1->getHeight() * 2);

        // 幅2倍
        $drawing3 = new Drawing();
        $drawing3->setPath(public_path('/img/mike.jpg'));
        $drawing3->setCoordinates('G1');
        $drawing3->setResizeProportional(false); //アスペクト比を無視
        $drawing3->setWidth($drawing1->getWidth() * 2);
...

とすれば良いですね。出力は以下になりました。

BaseDrawingクラス を確認していると他にも便利そうなメソッドがありました。例えば、setWidthAndHeight()は指定した幅と高さに収まるように画像をリサイズしてくれます。画像をセル内に収めたい場合などに使えそうですね!

By hikaru