2012年4月25日水曜日

[PHP][Excel][PHPExcel] 作成したExcelをダウンロードする

PHPExcelで作成したExcelをダウンロードしたい時がある。
一旦適当なフォルダにExcelを作ってそれをダウンロードさせてもいいが、
フォルダにパーミッションを設定したりダウンロードし終わったExcelを削除したりと、
余計な手間が多い。

そういう時は直接Excelをダウンロードさせるといい。

//ClassesをおいたパスからPHPExcel.phpをインクルードする
require_once('Classes/PHPExcel.php');
//Excelのクラスを作る
$excel=new PHPExcel();
//アクティブなシートを取得する
$sheet=$excel->getActiveSheet();
//シートに名前をつける
$sheet->setTitle('test');
//A1参照で値を入れる
$sheet->setCellValue('A1','test');

//ヘッダを設定する
header('Content-Type: application/octet-stream');
//ダウンロードするときのファイル名を指定する
//.xlsx形式でDLするときは拡張子をxlsxに変えておく
header('Content-Disposition: attachment;filename="test.xls"');
//.xls形式で書き込むためのクラスを作る
//.xlsx形式を書き込む場合は'Excel5'の部分を'Excel2007'に変える →$writer=PHPExcel_IOFactory::createWriter($excel,'Excel2007');
$writer=PHPExcel_IOFactory::createWriter($excel,'Excel5');
//出力バッファへの書き込む
$writer->save('php://output');
exit;

こうすることによって、
一旦ファイルを作ったりすることなくダウンロードさせることが出来る。
なお
header('Content-Type: application/octet-stream')
の代わりに
header('Content-Type: application/vnd.ms-excel')
を指定することもあるが、ブラウザやバージョン、設定によって挙動が異なってしまうため、
あまりお勧めはしない。
ただ、あえてブラウザでExcelを開けるときは開きたいという場合は指定することもある。

2012年4月23日月曜日

[PHP][Excel][PHPExcel] ボーダーをまとめて設定する

PHPExcelの関連サイトを見ると一つのセルに対して上下左右のボーダーにつけるときに

//ClassesをおいたパスからPHPExcel.phpをインクルードする
require_once('Classes/PHPExcel.php');
//書き込むExcelのパス
define('EXCEL','data/test.xls');
//Excelのクラスを作る
$excel=new PHPExcel();
//アクティブなシートを取得する
$sheet=$excel->getActiveSheet();
//シートに名前をつける
$sheet->setTitle('border test');
//A1参照で値を入れる
$sheet->setCellValue('A1','test');
//セルの上に罫線を引く
$sheet->getStyle('A1')->getBorders()->getTop()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);
//セルの下に罫線を引く
$sheet->getStyle('A1')->getBorders()->getBottom()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);
//セルの左に罫線を引く
$sheet->getStyle('A1')->getBorders()->getLeft()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);
//セルの右に罫線を引く
$sheet->getStyle('A1')->getBorders()->getRight()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);
//.xls形式で書き込むためのクラスを作る
//.xlsx形式を書き込む場合は'Excel5'の部分を'Excel2007'に変える →$writer=PHPExcel_IOFactory::createWriter($excel,'Excel2007');
$writer=PHPExcel_IOFactory::createWriter($excel,'Excel5');
//ファイルに書き込む
$writer->save(EXCEL);

としていることが多い。
もちろんこれでも誤りではないし、きちんとボーダーは設定できるのだが、
いかんせんセル1つならまだしも数が多いと大変である。

実は

//ClassesをおいたパスからPHPExcel.phpをインクルードする
require_once('Classes/PHPExcel.php');
//書き込むExcelのパス
define('EXCEL','data/test.xls');
//Excelのクラスを作る
$excel=new PHPExcel();
//アクティブなシートを取得する
$sheet=$excel->getActiveSheet();
//シートに名前をつける
$sheet->setTitle('border test');
//A1参照で値を入れる
$sheet->setCellValue('A1','test');
//セルの上下左右全てに罫線を引く
$sheet->getStyle('A1')->getBorders()->getAllBorders()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);
//.xls形式で書き込むためのクラスを作る
//.xlsx形式を書き込む場合は'Excel5'の部分を'Excel2007'に変える →$writer=PHPExcel_IOFactory::createWriter($excel,'Excel2007');
$writer=PHPExcel_IOFactory::createWriter($excel,'Excel5');
//ファイルに書き込む
$writer->save(EXCEL);

とすることでまとめてボーダーを設定することが出来る。

覚えておいて損はないと思う。

2012年4月16日月曜日

[PHP] 現在のURLを取得する

たまに現在のURLを取得したい時がある。
しかし残念ながらPHPに一発で取得する方法は今のところない。
なので、地道にサーバ変数から作っていくことになる。

//link・・・http://mio-koduki.blogspot.jp/2012/04/php-url.html
//返り値・・・成功した場合は現在のURL、失敗した場合はfalse
function get_current_url()
{
    $host=getenv('HTTP_HOST');
    $uri=getenv('REQUEST_URI');
    if(strval($host)===''||strval($uri)==='')
    {
        return false;
    }
    $https=getenv('HTTPS');
    return 'http'.(isset($https)&&strval($https)!==''&&strtolower($https)!='off'?'s':'').'://'.$host.$uri;
}

というふうになる。
ちなみにgetenv()のところはもちろん$_SERVERでも構わないが、
$_SERVERが定義されてない際にE_NOTICEを出さないために使ってる。

また、getenv('HTTPS')HTTPSの判定はPHPの$_SERVERマニュアルを見てみると
スクリプトが HTTPS プロトコルを通じて実行されている場合に 空でない値が設定されます。
注意: ISAPI を IIS で使用している場合は、HTTPS プロトコルを通さないでリクエストが行われたときの値は off となることに注意しましょう。
と書いてあるため、上記のようなチェックにしてある。
ただし、世には「shttp」 とちょっと変わり種や「ftp」などのプロトコルもあるが、
基本必要ではないため「http」と「https」にのみ対応している。

また限定的な場合であるが、特定のSSLアクセラレータを使用しているサーバでは
https通信を行ってもHTTPSに値が設定されない。
その場合は残念ながらPHPではhttps通信をキャッチできない。

ポイントとなる関数
  • getenv ・・・ 環境変数の値を取得する

2012年4月3日火曜日

[PHP] 連想配列かどうか調べる

PHPは非常に型に柔軟なため、
添字配列(いわゆるキーが0から始まる連番の配列)でも
連想配列(キーが文字列など)でも
基本的に同じように扱うことができる。

ただ、たまに添字配列なのか連想配列なのかを判定したくなる時がある。
チェックする方法としてはキーが数字の連番になってるかを調べたら良いので

//link・・・http://mio-koduki.blogspot.jp/2012/04/php-0-linktruefalsefunction-ishasharray.html
//第一引数・・・調べたい配列
//返り値・・・連想配列であればtrue、でなければfalse
function is_hash($array)
{
    return array_keys($array)!==range(0,count($array)-1);
}

というふうになる。
ただし、array_keysとrangeで2個新たに調べたい配列と同数の要素を持つ配列を作るので、
配列サイズが大きいと無駄なメモリを食うことになる。
そういう時は

//link・・・http://mio-koduki.blogspot.jp/2012/04/php-0-linktruefalsefunction-ishasharray.html
//第一引数・・・調べたい配列
//返り値・・・連想配列であればtrue、でなければfalse
function is_hash($array)
{
    $i=0;
    foreach($array as $k=>$v)
    {
        if($k!==$i++)
        {
            return true;
        }
    }
    return false;
}

素直にforeachで回しながら、連番になってるかチェックすれば良い。

ポイントとなる関数
  • array_keys ・・・ 配列のキーすべて、あるいはその一部を返す
  • range ・・・ ある範囲の整数を有する配列を作成する