CakePHPでエクセルファイルの出力 [CakePHP]
超久しぶりにCakeの小ネタ。
DBのデータをCSVで出力することは多いと思うけど、どうせ社内で使うならエクセル形式の方が良いので.xlsで出力する。
つっても、中身は XMLスプレッドシート(2004)形式。
だから本当は拡張子は .xml なのだけど、それだとATOMや普通のXMLとごっちゃになるので、.xlsで書き出す。
メリットは、
・罫線とか最初から設定してあると嬉しい。
・utf-8で書き出せるから、文字コードのコンバートが要らない。
・1ファイルでもワークシートごとに書き出せる。
・.xls だとエクセルと紐づいてるので、素人にも説明が楽。
デメリットは、
・OOoは拡張子と実際のファイル形式が違うとダメなので、OOoのときは .xml にしないとだめ。
まずは、ルータに下記を追加
/app/config/routes.php
テンプレートは、例えばこんな感じ
/app/views/layouts/xls/default.ctp
/app/views/users/xls/admin_index.ctp
ワークシートごとにしたい場合は、基本的には <Worksheet> 〜 </Worksheet> を繰り返せば、複数のワークシートが出来る。
アクセスする時は、.xls をつければ良いわけだから、
http://xxx.com/admin/users/index.xls
ページネートしたのを出力したい時は、
http://xxx.com/admin/users/index/page:3.xls
みたいなURLになるが無問題。
これでオッケー!超簡単!と思ってたら、出力されない??エラーも出ない。。なぜ?
CSVやXMLはこの手順だけだったのに?
わかんなければ、ソースを見るのがCakePHPの基本
あった、あった。
request_handler.php でファイルの定義をしてたのね、知らなかった。
そんで、当然.xlsはない。
追加すべきなんだけど、どっかのブログで beforeFilter() でやらないとダメというのを見かけたので(未確認)beforeFilterに追記する。
これで問題無く、.xls でダウンロードできた。
よかったよかった。
DBのデータをCSVで出力することは多いと思うけど、どうせ社内で使うならエクセル形式の方が良いので.xlsで出力する。
つっても、中身は XMLスプレッドシート(2004)形式。
だから本当は拡張子は .xml なのだけど、それだとATOMや普通のXMLとごっちゃになるので、.xlsで書き出す。
メリットは、
・罫線とか最初から設定してあると嬉しい。
・utf-8で書き出せるから、文字コードのコンバートが要らない。
・1ファイルでもワークシートごとに書き出せる。
・.xls だとエクセルと紐づいてるので、素人にも説明が楽。
デメリットは、
・OOoは拡張子と実際のファイル形式が違うとダメなので、OOoのときは .xml にしないとだめ。
まずは、ルータに下記を追加
/app/config/routes.php
Router::parseExtensions('csv','xml','xls');
テンプレートは、例えばこんな感じ
/app/views/layouts/xls/default.ctp
<?='<?xml version="1.0"?>'?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
<Author>Sandman</Author>
<LastAuthor>Sandman</LastAuthor>
<Created><?=(date('Y-m-d').'T'.date('H:i:s'))?></Created>
</DocumentProperties>
<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
<AllowPNG/>
</OfficeDocumentSettings>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<WindowHeight>21660</WindowHeight>
<WindowWidth>22580</WindowWidth>
<WindowTopX>6680</WindowTopX>
<WindowTopY>-520</WindowTopY>
<Date1904/>
<AcceptLabelsInFormulas/>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
<Styles>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Bottom"/>
<Borders/>
<Font ss:FontName="MS Pゴシック" x:CharSet="128" ss:Size="11.0"/>
<Interior/>
<NumberFormat/>
<Protection/>
</Style>
</Styles>
<?php
echo $content_for_layout;
?>
</Workbook>
/app/views/users/xls/admin_index.ctp
<Worksheet ss:Name="ユーザ一覧">
<Table ss:DefaultColumnWidth="77.0" ss:DefaultRowHeight="17.0">
<?php
foreach ($users as $u){
$id = $u['User']['id'];
$name = $u['User']['name_0']." ".$u['Users']['name_1'];
$mail = $u['User']['email'];
$created = $u['User']['created'];
$city = $cities[$u['User']['city']];
?>
<Row>
<Cell><Data ss:Type="String"><?=$id?></Data></Cell>
<Cell><Data ss:Type="String"><?=$name?></Data></Cell>
<Cell><Data ss:Type="String"><?=$mail?></Data></Cell>
<Cell><Data ss:Type="String"><?=$city?></Data></Cell>
<Cell><Data ss:Type="String"><?=$created?></Data></Cell>
</Row>
<?php
};//foreach ($Users as $u)
?>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup/>
<Print>
<ValidPrinterInfo/>
<PaperSizeIndex>0</PaperSizeIndex>
<HorizontalResolution>-4</HorizontalResolution>
<VerticalResolution>-4</VerticalResolution>
</Print>
<PageLayoutZoom>100</PageLayoutZoom>
<Selected/>
<Panes>
<Pane/>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
ワークシートごとにしたい場合は、基本的には <Worksheet> 〜 </Worksheet> を繰り返せば、複数のワークシートが出来る。
アクセスする時は、.xls をつければ良いわけだから、
http://xxx.com/admin/users/index.xls
ページネートしたのを出力したい時は、
http://xxx.com/admin/users/index/page:3.xls
みたいなURLになるが無問題。
これでオッケー!超簡単!と思ってたら、出力されない??エラーも出ない。。なぜ?
CSVやXMLはこの手順だけだったのに?
わかんなければ、ソースを見るのがCakePHPの基本
あった、あった。
request_handler.php でファイルの定義をしてたのね、知らなかった。
そんで、当然.xlsはない。
追加すべきなんだけど、どっかのブログで beforeFilter() でやらないとダメというのを見かけたので(未確認)beforeFilterに追記する。
function beforeFilter() {
parent::beforeFilter();
<中略>
if(isset($this->params['url']['ext']) && $this->params['url']['ext'] == 'xls'){
$this->RequestHandler->setContent('xls', array('application/vnd.ms-excel', 'text/plain'));
}
}
これで問題無く、.xls でダウンロードできた。
よかったよかった。
2011-04-04 17:55
nice!(0)
コメント(0)
トラックバック(0)
コメント 0