ドゥアイネットのプログラマー、湯川が開発日記を綴ります。

CALENDAR
S M T W T F S
    123
45678910
11121314151617
18192021222324
252627282930 
<< November 2018 >>
ARCHIVES
CATEGORIES
Spreadsheet_Excel_Writerについて
かなり前に「PHPでExcel出力」という記事を書きました。

Spreadsheet_Excel_WriterでExcel2000形式を出力できるようにするといった内容です。

「Spreadsheet_Excel_Writer-0.9.1.patched」を使うことで
確かにExcel2000形式を出力できるのですが、
動作が不安定なところがありました。

1.同じセルにデータを出力すると、作成したExcelファイルが開けない。
2.日付テキスト(H23/03/31など)を出力すると、作成したExcelファイルが開けない。

「1」は同じセルに出力しなければ良いのですが、
「2」はlinuxサーバーでは問題なく動作して、windowsサーバーでは動作したりしなかったりでした。

「PHPExcel」に比べて動作が速いのですが、ちょっと不安定なので
なんとか使えるようにできないかなぁと思います。
| PHP | 17:09 | comments(0) | - |
PHPの文字コード設定
PHPで文字を出力するときは、mb_convert_encodingを使用して
出力する文字コードにあわせたりしていましたが、
phpの設定で出力する文字コードを設定できるようです。

以下のページに書かれていました。

http://www.bnote.net/windows/windows/code.shtml

php.iniのなかでこういったものも設定できるのですね。
うまく使いこなせば便利そうです。
| PHP | 16:36 | comments(0) | - |
マルチパートメール送信
メールの送信方法にテキストとHTMLメールを
一つのメールとして送信してする「マルチパートメール送信」を調べました。

マルチパートメールを受信したメールソフト側で
HTMLメールが読めない(表示しない)場合は、テキストメールを表示、
HTMLメールが読める(表示する)場合は、HTMLメールを表示します。

通常メールは以下の順でメールデータをセットして送信します。
1.メールヘッダー
2.メール本文

※HTMLメールもヘッダー情報は少し違うだけで同様です。

マルチパートメールの場合は以下になります。

1.メインのヘッダー
2.テキストメールヘッダー
3.テキストメール本文
4.HTMLメールヘッダー
5.HTMLメール本文    

2種類のメール内容をまとめてセットします。
内容の区切りとして以下のように「boundary」をいれます。

1.メインのヘッダー
--「boundary」
2.テキストメールヘッダー
3.テキストメール本文
--「boundary」
4.HTMLメールヘッダー
5.HTMLメール本文    
--「boundary」--

この区切りをメールソフトが見て、
2種類のメールが送られてきたと判断します。

ソースにしたらこのようになります。

$v_boundary = "-----" . date("YmdHis", time()) . "_MULTIPART_MIXED";

//1.メインのヘッダー
$Result['Header']  = 'From: ' . $Result['From'] . "¥r¥n" .
                     'To: '   . $p_send_to . "¥r¥n";

$Result['Header'] = "MIME-Version: 1.0" . "¥r¥n".    
                  "Content-Type: multipart/alternative; boundary=" . $v_boundary . "¥r¥n".
                  "Content-Transfer-Encoding: 7bit". "¥r¥n" .
                  $Result['Header'];

$Result['Header'] .= "Subject: ". $Result['Subject'] . "¥r¥n" .
                   "X-Priority: " . $p_priority . "¥r¥n" .
                   "X-To-Addr: " . $p_to . "¥r¥n" .
                   "Date: $v_offset_rfc" . "¥r¥n" ;

//2.テキストメールヘッダー
$Result['Body']    = "Multipart Message coming up" . "¥r¥n¥r¥n--". $v_boundary . "¥r¥n".
                   "Content-Type: text/plain; charset=iso-2022-jp" . "¥r¥n" .
                   "Content-Transfer-Encoding: 7bit" . "¥r¥n" . "¥r¥n" ;
                   
//3.テキストメール本文
$Result['Body']    .= $this->_encodeStr(ereg_replace("¥n", "¥r¥n", $p_body), 'JIS'). "¥r¥n". "¥r¥n";
$Result['Body']    .= "--" . $v_boundary . "¥r¥n";

//4.HTMLメールヘッダー
$Result['Body']    .= "Content-type: Text/HTML; charset=ISO-2022-JP¥r¥n" .
                    "Content-Transfer-Encoding: 7bit" . "¥r¥n". "¥r¥n";

//5.HTMLメール本文  
$Result['Body']    .= $this->_encodeStr(ereg_replace("¥n", "¥r¥n", $p_htmlbody), 'JIS'). "¥r¥n". "¥r¥n";
$Result['Body']    .= "--" . $v_boundary . "--" . "¥r¥n";


boundaryで少しハマりました。
"Content-Type: multipart/alternative; boundary=" . $v_boundary . "¥r¥n".
で指定するときは、「--」をつけないで、間にいれるときは、「--」を付けます。

ソースとしては長いですがルールがわかれば、そう難しくないと思いました。

| PHP | 17:37 | comments(0) | - |
IE6不具合
 PHPのシステムが、IE6で一部きちんと動かないところがありました。

・ボタンをクリックしても次のページに遷移しない。

以下のように書いているのが原因でした。
<li class="back"><a href="javascript:void(0);" onClick="return_submit();" class="back" >戻る</a></li>

clickイベント時の「return_submit」の中でformをsubmitしているのですが、
画面が遷移しません。
IE6では、falseを返さないと画面遷移しないそうです。

なので、
<li class="back"><a href="javascript:void(0);" onClick="return_submit();return false;" class="back" >戻る</a></li>
と書き換えて対応しました。

・スタイルを使って、ボタンのマウスオーバーなどをしていたが、画像がちらつく。

このようなボタン画像をcssで使っていました。
画像

hoverで画像の位置を変えてマウスオーバーを表現しています。

どうしてもちらつくので、ボタンの後ろにさらに背景としてボタン画像を表示するようにしました。
<li class="back"><a href="javascript:void(0);" onClick="return_submit();return false;" class="back" >戻る</a></li>
<li>の背景にボタン画像を指定。

Flexでの開発が多いのでブラウザの違いを意識していなかったので
今回は勉強になったと思います。
| PHP | 18:46 | comments(0) | - |
PHPExcelでの範囲指定
PHPExcelではセルの設定を変えるときに、
「getStyle」や「getStyleByColumnAndRow」を使って
そのセルのスタイルを取得して、フォント、色、線などの変更を行います。

「getStyleByColumnAndRow」は一つのセルしか選択できません。
「getStyle」は「A1:D1」のように指定すると範囲指定ができますが、
プログラムで書く場合は、「3,10,8,10」のように数字で範囲を指定したいところです。

PHPExcelのライブラリを見てみたら「Cell.php」の中に
「stringFromColumnIndex」というメソッドを見つけました。
これは、列番号を数字で渡すと、「A、AW」などの文字を使っての列番号に変換してくれるものでした。

このメソッドを使って、数字で範囲指定して色をつけるメソッドをつくりました。

  /**
   * 範囲指定で色をつける
   *
   * @param $p_colFrom,$p_rowFrom,$p_colTo,$p_rowTo(座標)
   * @param p_color   色
   */
  function setRangeColor($p_colFrom,$p_rowFrom,$p_colTo,$p_rowTo ,$p_color)
  {
    $v_range = PHPExcel_Cell::stringFromColumnIndex($p_colFrom) . $p_rowFrom . ":" .
               PHPExcel_Cell::stringFromColumnIndex($p_colTo) . $p_rowTo ;
    
    $v_style = $this->_activesheet->getStyle($v_range);
    $v_style->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
    $v_style->getFill()->getStartColor()->setRGB($p_color);
    $v_style->getFill()->getEndColor()->setRGB($p_color);
  }

一つずつセルを指定して色をつけてもできるのですが、
このやり方のほうが、少し速いのではないかと思います。
| PHP | 15:26 | comments(0) | - |
PHPExcelとautoload
PHP5の便利機能「autoload」を使って開発しています。
PHPExcelを使おうとするとエラーになってしまいます。

これは、PHPExcelのライブラリ内でも「autoload」を使っているようで
本来PHPExcelで使う予定の「autoload」を書き換えてしまうようです。

これを回避するには、「__autoload」を使わずに
自前で用意した関数を「autoload」として登録してやります。

こんな感じです。

function myAutoload($p_class) {
  if (file_exists("./model/" . $p_class . ".php5")){
    include_once "./model/" . $p_class . ".php5";
  }
}
//spl_autoload_registerでautoloadを登録
spl_autoload_register('myAutoload');


これで、今までどおり「autoload」が使えて、PHPExcelも使えるようになります。
| PHP | 08:44 | comments(0) | - |
クラス名の取得
PHPでログを作成する際に、
どのクラスで処理されているかを記述したかったので
クラス名を取得する方法を調べました。

「get_class」関数でクラス名を文字列として取得できます。

get_class($this);

当たり前かもしれないですが、
以下のように継承していてもそれぞれの名称を取得できます。

class testA()
{
  //コンストラクタ
  function testA(){
    print(get_class($this));
  }
}

class testB() extends testA
{
  //コンストラクタ
  function testB(){
    
  }
}

testAを実行すると「testA」、
testBを実行すると「testB」が出力されます。

| PHP | 15:17 | comments(0) | - |
PHPの「exec関数」
 PHPで処理時間がかかる処理を別で実行することになりました。

curlから呼び出した場合、PHPの処理時間がかかりすぎると
タイムアウトになってしまい、処理が途中で終わってしまうからです。

また、curl側で処理中表示で画面が固まっていると、
ユーザーさんがブラウザを閉じたり強制終了させてしまうこともあります。

なのでこのように変更しました。
curlからPHP呼び出し→PHPから別PHPを呼び出して時間のかかる処理をさせる

呼び出し方法は「exec」関数を使いました。

「exec」はコマンドを実行できます。

このような感じで呼び出しました。

exec('/usr/local/php4/bin/php/ファイル名.php パラメータ.txt > /dev/null &');

ファイル名の後に空白を入れて引数を渡せます。
今回は引数が多かったので、ファイル(パラメータ.txt)に引数を記入して
ファイル名を引数で渡して、実行されるPHPファイルの中で参照するようにしています。

最後の「> /dev/null &」を付けると、呼び出したPHPの終了を待たずに呼び出しもとに制御が戻ります。

はじめてこのように処理しましたが、いろいろ使えそうですね。

| PHP | 18:21 | comments(1) | - |
PHPのarray_unique関数
PHPのarray_unique関数は、要素の重複をなくしてくれて便利です。
使っていたら、要素の参照がうまくいかないことがありました。

$array = array();
$array[] = 'A0000205';
$array[] = 'A0000205';
$array[] = 'A0000103';
$array[] = 'A0000117';

print_r($array);
結果
Array
(
    [0] => A0000205
    [1] => A0000205
    [2] => A0000103
    [3] => A0000117
)

//array_uniqueを使う
$array2 = array_unique($array);

print_r($array2);

結果
Array
(
    [0] => A0000205
    [2] => A0000103
    [3] => A0000117
)

重複している「A0000205」は一つになっていますが、
インデックスはそのままです。
なので、このように配列カウントでループすると、最後の項目は参照できません。

for ($i=0; $i<count($array2); $i++) {
  print($array2[$i]. "¥n");
}

結果
A0000205

A0000103

※「1」の項目がないので空白になります。

foreachでループすれば、最後の項目まで参照できます。

foreach($array2 as $value) {
  print($value. "¥n");
}
結果
A0000205
A0000103
A0000103

| PHP | 17:30 | comments(0) | - |
うるう年の判定
 西暦の年が 4 で割り切れる年はうるう年になります。
なので2004年、2008年はうるう年です。

さらに条件があって以下にも該当しないとうるう年になりません。

100で割り切れる1900年などは、その年がさらに400
でも割り切れる場合のみうるう年。

誤差を解消するためにこのようになっているそうです。

言語によっては関数が用意されているものもあります。
Delphiや.NETだと「IsLeapYear」関数があります。

PHPではこの関数はないので以下のようにして判定しています。

以前書いた方法と同じく指定年の3/1から1日引いて、
2/29になったらうるう年と判定します。

if (date("d",strtotime("-1 day" ,strtotime("2008-03-01"))) == "29"){
  die("うるう年です。");
}
else{
  die("うるう年ではありません。");
}


実際、2100年まで100で割り切れないので4で割り切れたらうるう年でよさそうな感じはしますが、
少しでも不具合の元は残したくないので、きちんと判定しています。
| PHP | 15:01 | comments(0) | - |
| 1/2PAGES | >>