Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

PhpSpreadsheetの使い方

More than 1 year has passed since last update.

はじめに

仕事で使ったときどう使ったかを解説します。
PhpSpreadsheetはPhpExcelの後継で、最近のPHPっぽくなってるらしいです。
https://github.com/PHPOffice/PhpSpreadsheet

今回はxlsx形式のファイルから情報を読みだして、csv形式のファイルに書き込みます。

使い方

インストールとrequire

composer require phpoffice/phpspreadsheetをした後、普通に

require_once "vendor/autoload.php";

で終わりです。

読む

ファイルの読み込み

$reader = new PhpOffice\PhpSpreadsheet\Reader\Xlsx();
$spreadsheet = $reader->load($file_name);

ファイルからシートを取り出す

$sheet = $spreadsheet->getSheetByName("シートの名前");

もしくは、

//選択されているシートを取得
$sheet = $spreadsheet->getActiveSheet();

//2番目のシートを取得。Indexは0スタート
$sheet = $spreadsheet->getSheet(1);

そのシートのセルの情報を取り出す

//B2のセルの値
$sheet->getCell("B2")->getValue();

範囲のセルを配列で取り出す

空のセルにはnullが入ります

$data = $sheet->rangeToArray("A2:A100");

イテレータで情報を取り出す

イテレータが使えます。上のrangeToArrayは範囲がわかってないと使えませんでしたが、これを使うとCtrl+Shift+↓をしたみたいに空じゃないセルまでを取れます。←そんなことはなかった。xlsxファイルあるあるのなぜか空のセルまでデータが入っているやつのせいで、nullでもデータ自体は取れてしまう。

  • 行ごと。この例だとB1~Bnまで
foreach ($sheet->getRowIterator() as $row) {
    var_dump($sheet->getCell("B".$row->getRowIndex())->getValue());
}
  • 列ごと。この例だとA1~n1まで
foreach ($sheet->getColumnIterator() as $column) {
    var_dump($sheet->getCell($column->getColumnIndex() . "1")->getValue());
}

二つ組み合わせれば範囲を網羅できます。

結合されたセルを取得する

これ!!!これがしたかった!!!!

var_dump($sheet->getMergeCells());
/*
array(
    "A1:A10" => string(6)"A1:A10",
    "B2:C10" => string(6)"B2:C10"
);
*/

ただの文字列しか取得できませんが、結合の始点と終点を取得することができます!
値そのものは、結合する前のセルに入っています(場所は直接わからない)。
B2からC10の範囲にnullでないセルが1つだけ存在するはずなので、そこの値を取得しましょう。

書く

新しいSpreadSheetを作る

$spread_sheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();

この時点ではファイル形式は指定されません。後に出てくる$writerがなんのインスタンスかによって最終のファイル形式が決まります。

新しいSheetを作る

$sheet = $spreadsheet->createSheet(0);

0を入れないとシートが指定されなくて空白になるっぽい?

既存のSheetを取得する

$sheet = $spreadsheet->getSheet(0);

最後に保存するとき、csvじゃなくてxlsxを指定すると最初から1つシートがあってcreateSheetすると2枚目ができるので、xlsxファイルを作りたいときはこっちのほうが良いっぽい

値をセットしていく

$sheet->setCellValue("A1", "foo");
$sheet->setCellValue("B1", "bar");

$num = 2;
foreach ($data as $key => $value) {
    $sheet->setCellValue("A" . $num, $key);
    $sheet->setCellValue("B" . $num, $value);

    $num++;
}

配列から値をセットする

$array = [
    [
        "a1",
        "b1",
        "c1",
        null,
        "e1"
    ],
    [
        "a2",
        "b2",
        "c2"
    ]
];

//fromArray(セットする配列, セットしない値, 開始場所のセル)
$sheet->fromArray($array, null, 'A1');

とすると、以下の画像のように値が入る。
image.png

fromArray()の第二引数はnullじゃなくても、

$array = [
    [
        "a1",
        "b1",
        "c1",
        "秘密の値",
        "e1"
    ]
];

$sheet->fromArray($array, "秘密の値", 'A1');

みたいにすると以下の画像のように秘密の値がセットされない。
image.png

ファイルを保存する

$writer = new PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet);
$writer->setSheetIndex(0);
$writer->save("hoge.csv");

CSVのときはシートという概念がないので、保存するシートを指定しないと空白になるっぽい

$writer = new PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
$writer->save("hoge.xlsx");

csvじゃなくてxlsxwriterを使うとxlsx形式になる

おわりに

これで基本的な動作は網羅できてる気がします。
メタデータのセットとかセル結合とかもできますが、エクセルを読むことはあっても書くことはないので省略しました。
PHPでExcelを使うのは悪手と言われますが、そんなに難しくないし業務の補助に使う程度なら全然ありだと思います。

sudnonk12
大学生 基本情報技術者/応用情報技術者/ネットワークスペシャリスト/プロジェクトマネージャ/データベーススペシャリスト/情報処理安全確保支援士/線路主任技術者
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away