k-tanakaのエンジニア日記

Changing合同会社を設立しての仕事・生活、エンジニアとしてのブログ

FuelPHPでdocxファイルとpdfファイルを出力する

本記事は、FuelPHP Advent Calendar 2015 - Qiita の12/22分になります。

初めて参加するのですが、仕事が立て込んでて、丁寧に書けないと思います。ほんと申し訳ないです。

 

さて、 FuelPHP を使って、docxファイルとPDFファイルを出力するにはどうしたらよいかについて、手順を簡単に解説したいと思います。Webアプリを作る面でも、社内ツールを作る面でも、これらが出来ると非常に便利です。

 

前提

・docxファイル(*.docx)とは、Microsoft Word 2007以降で採用されているXMLベースの文書ファイルです。なお、別にMicrosoft Wordでだけ使えるというわけでなく、標準化されています。そこらへんは、Office Open XML - Wikipedia を参照のこと。

 なお、Microsoft Word 2003以前の文書ファイル形式(*.doc)を出力するライブラリは、今の所無いですし、これからも出ないと思います。(Office 2003はサポート切れですし。)

 

・PDFファイル(*.pdf)の説明は割愛します。

 

docxファイルの生成

phpoffice/phpword - Packagist というパッケージを利用します。

FuelPHP最新版においては、パッケージ管理にcomposerを利用しており、ここでもcomposerを利用して、上記パッケージをインストール、利用したいと思います。

 

composerからパッケージインストール

composer.jsonの、requireという部分に次を足します。(※コード表示がはてなブログの見たまま編集だと出来ないのですが、後で直します。) ※あとから編集モードを変更できなかったので、この形式でご勘弁願います。。。 

"phpoffice/phpword": "0.12.1"

 

 あとは、ターミナルから、

composer.phar update

 

で導入できます。

 

PHPOffice/phpwordで出力

手順としては、PhpWordオブジェクトインスタンスを生成し、そこから派生してsectionオブジェクトや、tableオブジェクトに文書の内容を入れていき、最後に、word2007形式でファイル出力用のオブジェクトに渡して、出力するという形です。

 

・PhpWordオブジェクトインスタンスを生成

$phpword = new \PhpOffice\PhpWord\PhpWord();

 

・派生してsectionオブジェクトに文書の内容をいれていく

$section = $phpword->createSection();

 

//font_style

$fs_default = array(
                        'size' => 10
                );

 

//paragraph style

$ps_default        = array(
                        'lineHeight' => 1.1, //行間
                        'align'      => 'left'
                );

 

$section->addText('コンテンツ内容の追記', $fs_default, $ps_default);

 

 ・word2007形式でファイル出力用のオブジェクトに渡して、出力する

$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpword, 'Word2007');

$objWriter->save($path . $file_title);

 といった形になります。

公式ドキュメントが、Welcome to PHPWord’s documentation — PhpWord 0.12.0 documentation から参照できます。上記のベースが分かれば、分かりやすいのではないかと思います。

すいません、文書のプロパティ、テーブル、テンプレートからの出力などについても記載したかったのですが、時間が無いので割愛します。今度加筆予定です。

※加筆は以下。

 

文書のプロパティ設定方法

文書を構成する設定、デフォルトフォントサイズや、 用紙の設定、用紙の向き、作成者などの名称設定が可能です。

//デフォルトフォントサイズ
$phpword->setDefaultFontSize(12);

//デフォルトフォント
$phpword->setDefaultFontName('MS P明朝');

 

//ドキュメントプロパティ
$properties = $phpword->getDocumentProperties();
$properties->setCreator('作成者名称');
$properties->setCompany('作成組織名称');
$properties->setTitle('文書タイトル');

 

また、各セクションもそれぞれマージンなどが設定可能です。

$section      = $phpword->createSection();
$sectionStyle = $section->getSettings();
$sectionStyle->setLandscape();
$sectionStyle->setPortrait();
$sectionStyle->setMarginLeft(567);
$sectionStyle->setMarginRight(567);
$sectionStyle->setMarginTop(567);
$sectionStyle->setMarginBottom(567);

で、このマージンの設定なのですが、単位がピクセルではなく、twipsという単位が使われます。1twipsは、1/1440inchとのことです。そうすると、

1440twips = 1 inch = 2.54cm

567 twips = 1cm

A4サイズ 210mm×297mm だと、(およそ) 8.26inch × 11.68inch、11,894 twips × 16,819 twips

という感じです。

なお、ここらへんは便利な関数が用意されており、下記の関数でインチとセンチからtwipsに変換して値を返してくれます。

$one_cm_twips = \PhpOffice\PhpWord\Shared\Converter::cmToTwip(1);

$half_cm_twips = \PhpOffice\PhpWord\Shared\Converter::cmToTwip(0.5);

$one_inch_twips = \PhpOffice\PhpWord\Shared\Converter::inchToTwip(1);

  

ヘッダ・フッタの追加

ヘッダとフッタは、下記のようにヘッダ変数を生成し、そこに普通にセクション変数と同じような形でコンテンツを追加することが出来ます。

//ヘッダー
$header = $section->addHeader();
$header->addText('ヘッダー', $fs, $ps);


//フッター
$footer = $section->addFooter();
$footer->addPreserveText('{PAGE} / {NUMPAGES}', $fs, $ps); //ページ番号 / 総ページ番号

 

テーブルの作成

表を作成するには、セクション変数からテーブル変数を作り、当該テーブル変数にaddRowで行を作り、addCellで列を追加していくという形になります。

幅や高さは、やはり同じくtwips単位になります。

//テーブルのスタイル
$table_style = array(
'cellMarginTop'=>30,
'cellMarginLeft'=>30,
'cellMarginRight'=>30,
'cellMarginBottom'=>30
);

 

//スタイルを設定して、セクションにテーブルを追加
$table = $section->addTable($table_style);

 

//セルのスタイル
$cell_style = array(
'valign' => 'center',
'align' => 'left',
'borderTopSize' => 5,
'borderLeftSize' => 5,
'borderRightSize' => 5,
'borderBottomSize' => 5
);


//行を追加 - 数値は高さ
$table->addRow(140);

 

//行にセルを追加
// addcell(幅, スタイル)->addText('内容', フォントスタイル, パラグラフスタイル)
$table->addCell(1350, $cell_style)->addText('1行目の1列目', $fs, $ps);
$table->addCell(3650, $cell_style)->addText('1行目の2列目', $fs, $ps);
$table->addCell(1150, $cell_style)->addText('1行目の3列目', $fs, $ps);
$table->addCell(3850, $cell_style)->addText('1行目の4列目', $fs, $ps);

 

 

もう一つテーブルを追加したい場合には、同じセクション変数から、別のテーブル変数を生成して、テーブルを追加していきます。

$table2 = $section->addTable($table_style);

 

といった感じです。

 

改行したいときは

テキストの改行は、<w:br/>というタグになります。複数行のテキストを出力したい場合には、以下のような感じで追加すれば複数行で出力されます。(なお、phpoffice/phpwordでは、バージョンが古いと対応していません。)

preg_replace('/\r\n/',"<w:br/>",$text);

 

 

pdfファイルを出力する

FuelPHP用のPDF出力用パッケージがあります。fuel-pdfというパッケージです: TJS-Technology/fuel-pdf

 

 同パッケージは、それ自体がPDF出力機能を有するのではなく、PDF出力機能を持つライブラリのラッパーとなっています。対応しているのは、fpdf/mpdf/tcpdf/dompdfの4つです。日本語への対応(というよりもUTF-8への対応)などを考えると、tcpdfかdompdfのどちらかをお勧めします。

 

ここでは、tcpdfを例に紹介します。(私が普段使っているためです。今から習おうという方は、dompdfが良いかもしれません。)

 

インストールと設定

oil (FuelPHP公式のコマンドラインツール) からインストールも出来ますし、手動でパッケージフォルダに入れることも可能です。

 

・Oil

php oil package install pdf

 

・手動

fuel/packages フォルダ以下にパッケージのフォルダごと入れる

 

※いずれにせよ、namespaceとフォルダ名を一致させるため、fuel/packages/pdf フォルダとなるように。そうすると、 fuel/packages/pdf/classes/pdf.phpのpdfクラスの読み込みが可能になります。

 

実際に出力する

TCPDFは、通常通りPDFオブジェクトにドキュメントの内容を入れていく方法と、HTMLを変換する方法があります。

HTMLを変換する方法は、手軽ですが使えないタグがあったり、CSSが効かなかったりします。

 

出力コード

//fuelpdfのロード(fuelpdfのフォルダ名をpdfにしている)

Package::load('pdf');

 

//tcpdfのロード。A4縦UTF-8で開始

$pdf = Pdf::factory('tcpdf')->init("P", "mm", "A4", true, "UTF-8");

 

//ヘッダ・フッタ無し

$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);

 

//紙の余白(左、上、右)

$pdf->SetMargins(19.2, 21.2, 18.6);

 

//コンテンツ量に応じて自動でページ追加
$pdf->SetAutoPageBreak(false);

 

//1ページ目の開始
$pdf->AddPage();

 

//日本語フォントの設定とフォント色設定

$pdf->SetFont('kozgopromedium', '', 14, true);
$pdf->SetTextColor(0, 0, 0);

 

続き: HTML出力パターン

$html = <<< HTML

<p>PDF出力機能のテスト</p>

HTML;

 

$pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', $html, $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=true);

$pdf->Output($save_dir.$save_pdftitle, 'FI');

 

 続き: 通常パターン

//Cell( $w, $h, $txt, $border, $ln, $align, $fill, $link, $stretch, $ignore_min_height, $calign, $valign )

 $pdf->Cell(0,12,"PDF出力機能のテスト",0,1,'L');

$pdf->Output($save_dir.$save_pdftitle, 'FI');

 

その他

PDFは、フォントを埋め込まれたPDFとそうでないPDFがあります。PDFは、生成したPDFの表示結果が一定なために便利なファイル形式なのでフォントを埋め込むべきです。幸いtcpdfは埋め込みに対応しています。

埋め込むためのフォントを用意する必要があり、そのフォントの生成や設置などは、下記サイトを参照して下さい。また、マニュアル類のリンクも以下に記します。

(※デフォルト日本語フォントの小塚フォントは、あまり綺麗と思いません。IPA明朝やIPAゴシックをお勧めします。)

 

関連サイト

 

時間がかかりましたが、加筆はこれで終了です。もっと丁寧にもっと網羅的に書きたかったのですが、申し訳ありません。時間が無く、難しいです。。