Slide 1

Slide 1 text

© RAKUS Co., Ltd. 1 PHPでOfficeファイルを取り扱う! PHP Officeライブラリを プロダクトに組み込んだ話 #phperkaigi 2024/03/09 廣部知⽣

Slide 2

Slide 2 text

2 ⾃⼰紹介 21卒で株式会社ラクスに⼊社 PHPでMail Dealerの開発を⾏っている 『良いコード悪いコードで学ぶ設計⼊⾨』や 『ちょうぜつソフトウェア設計⼊⾨』で 設計を学ぶ⽇々…… スト6で戦いの螺旋を登り続けています (Act2はMR1700でフィニッシュ)

Slide 3

Slide 3 text

© RAKUS Co., Ltd. 3 PHPでOfficeファイル取り扱いたいな〜

Slide 4

Slide 4 text

© RAKUS Co., Ltd. 4 皆さん、思ったこと、ありますよね?

Slide 5

Slide 5 text

© RAKUS Co., Ltd. 5 あるある〜!

Slide 6

Slide 6 text

© RAKUS Co., Ltd. 6 できます!

Slide 7

Slide 7 text

7 PHPでOfficeを取り扱うためのライブラリ群 主に以下の3つがある ● PhpSpreadsheet ● PHPWord ● PHPPresentation https://github.com/PHPOffice PHPOffice

Slide 8

Slide 8 text

8 スプレッドシートの新規作成はもちろん PhpSpreadsheet $spreadsheet = new Spreadsheet(); $activeWorksheet = $spreadsheet->getActiveSheet(); $activeWorksheet->setCellValue('A1', 'Hello World !'); $writer = new Xlsx($spreadsheet); $writer->save('hello world.xlsx'); 参考:https://phpspreadsheet.readthedocs.io/en/latest/

Slide 9

Slide 9 text

9 スプレッドシートの読み込みもできる PhpSpreadsheet $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader("Xlsx"); $spreadsheet = $reader->load("05featuredemo.xlsx"); 参考:https://phpspreadsheet.readthedocs.io/en/latest/topics/reading-and-writing-to-file/

Slide 10

Slide 10 text

10 Wordファイルの新規作成 PHPWord $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $section->addText('Hello World!'); $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007'); $objWriter->save('helloWorld.docx'); 参考:https://phpoffice.github.io/PHPWord/usage/introduction.html

Slide 11

Slide 11 text

11 Wordファイルの読み込み PHPWord $reader = IOFactory::createReader('Word2007'); $reader->load(__DIR__ . '/sample.docx'); $reader = IOFactory::createReader('MsDoc'); $reader->load(__DIR__ . '/sample.doc'); 参考:https://phpoffice.github.io/PHPWord/usage/readers.html

Slide 12

Slide 12 text

12 rtfやodtもサポートしている PHPWord $reader = IOFactory::createReader('RTF'); $reader->load(__DIR__ . '/sample.rtf'); $reader = IOFactory::createReader('ODText'); $reader->load(__DIR__ . '/sample.odt'); 参考:https://phpoffice.github.io/PHPWord/usage/readers.html

Slide 13

Slide 13 text

13 書式の指定もできます PHPWord $fontStyleName = 'oneUserDefinedStyle'; $phpWord->addFontStyle( $fontStyleName, array('name' => 'Tahoma', 'size' => 10, 'color' => '1B2232', 'bold' => true) ); 参考:https://phpoffice.github.io/PHPWord/usage/introduction.html

Slide 14

Slide 14 text

14 pptxファイルの新規作成 PHPPresentation $presentation = new PhpPresentation(); $writerPPTX = IOFactory::createWriter($presentation, 'PowerPoint2007'); $writerPPTX->save(__DIR__ . '/sample.pptx'); 参考:https://phpoffice.github.io/PHPPresentation/usage/presentation.html

Slide 15

Slide 15 text

15 pptファイルの読み込み PHPPresentation $reader = IOFactory::createReader('PowerPoint2007'); $reader->load(__DIR__ . '/sample.pptx'); $reader = IOFactory::createReader('PowerPoint97'); $reader->load(__DIR__ . '/sample.ppt'); 参考:https://phpoffice.github.io/PHPPresentation/usage/readers.html

Slide 16

Slide 16 text

16 ⽂字や画像の位置指定が、ちょっと⾯倒? PHPPresentation $shape = $currentSlide->createDrawingShape(); $shape->setName('PHPPresentation logo') ->setDescription('PHPPresentation logo') ->setPath('./resources/logo.gif') ->setHeight(36) ->setOffsetX(10) ->setOffsetY(10); 参考:https://phpoffice.github.io/PHPPresentation/usage/presentation.html

Slide 17

Slide 17 text

© RAKUS Co., Ltd. 17 地球上の誰かがふと思った PHPでOfficeファイルを 扱えるようになったら どんな機能が実装できるだろうか……

Slide 18

Slide 18 text

18           について メール共有管理システム 15年連続シェアNo.1(2009〜2023)※ 歴史は更に⻑く、2001年4⽉に販売開始 Laravelは2011年リリースなので、10歳年上 ※出典:ITR「ITR Market View:メール∕Web∕SNSマーケティング市場2024」  メール処理市場:ベンダー別売上⾦額推移およびシェア(2009〜2023年度予測)

Slide 19

Slide 19 text

19 PHPOfficeで読み込んだファイルを⾃然⾔語処理で解析して 宛先を抽出する メール本⽂、添付ファイル名、添付ファイル内の宛先を 突き合わせて、違うものがあったら警告を出す機能 (write系の機能は使わず、readのみの利⽤) 誤添付防⽌機能を実装しました

Slide 20

Slide 20 text

20 実際の動作はこんな感じ

Slide 21

Slide 21 text

21 メモリ枯渇との戦いが多かった! 外部ライブラリなので、Officeファイルをどう解析して どういう形でメモリ内に保持するのかブラックボックス →メモリ枯渇のエラーハンドリングを⾏い  発⽣時に随時対応する以外思いつきませんでした 苦労したところ

Slide 22

Slide 22 text

22 PhpSpreadsheet、超メモリ容量⾷います > PhpSpreadsheet uses an average of about 1k per cell (1.6k on 64-bit PHP) in your worksheets 1セルごとに1kbのメモリを使⽤する →10000(100x100)セルで10MB使⽤する計算 とりあえず、読み込み範囲の制限をかけて対策 参考:https://phpspreadsheet.readthedocs.io/en/latest/topics/memory_saving/ 苦労したところ

Slide 23

Slide 23 text

23 社内サーバリリース後、メモリ枯渇発⽣の報告が  →添付ファイルを⾒ても、そんなにセル数多くない…… あれこれ検証した結果、vlookupが原因だと判明 ⾮表⽰シートに対し、⾮常に広い範囲で検索をかけていた  →関数の解析‧展開で、メモリ枯渇が発⽣していた! 関数を展開しないオプションがあったので そちらを適⽤することで解決 苦労したところ

Slide 24

Slide 24 text

24 他にも、空⽩のセルは無視するオプションや 1シートずつ読み込んで、適宜メモリ解放を⾏う等の 対策を⾏った 公式ドキュメントには、PSR-16が実装されたライブラリを 利⽤し、代替オブジェクト(APCu、Redist、Memcache) を利⽤する⽅法も紹介されているが、⾮採⽤ 参考:https://phpspreadsheet.readthedocs.io/en/latest/topics/memory_saving/ 苦労したところ

Slide 25

Slide 25 text

25 PowerPointもメモリ枯渇発⽣するときがある 特にドキュメントに記載はないが、画像ファイルが多い プレゼンテーションはメモリ枯渇が発⽣しやすい こちらは特に対策が記載されていない…… →諦めて、メモリ枯渇時は解析を実⾏しないように 苦労したところ

Slide 26

Slide 26 text

26 当然メモリ枯渇以外にも苦労はあり…… 神Excelがこの世に存在するように、どんなフォーマットの 添付ファイルが添付されるか予測がし⾟い 宛先を抽出する際「様」や「御中」などの敬称を 参考にするのだが、別セルに書かれていたり、同じセル に書かれていたりと形式が曖昧 セル結合も使われていたりすると、さらに複雑に 😱 苦労したところ(時間があれば)

Slide 27

Slide 27 text

© RAKUS Co., Ltd. 27 (いろいろ課題はありますが……) PHPで楽しい Officeライフを!