SSブログ
Lancers.jp

CakePHPでエクセルファイルの出力 [CakePHP]

超久しぶりにCakeの小ネタ。

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 でダウンロードできた。
よかったよかった。


nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。