こぶたのラッパ » Blog Archives

Tag Archives: PHP

プログラミング

PHPExcelでセルの入力規則に名前定義を使う方法

Published by:

PHPExcelとはPHPでExcelを読み書きするための便利ツールですが、一度はまると泥沼に陥りやすいので、取り扱いに非常~に注意が必要です。

そんな泥沼の一つからやっと生還したので、ブログに書き残しておこうと思います。

上手のようなものをPHPExcelで動的に行おうと思ったのですが、ニッチもサッチもいかない。
「Excel2007」のWriterだと $validation->setFormula1(‘=野菜’); で簡単に出来るのですが、要件的にExcel2003への対応が必須だったため、どうしても「Excel5」のWriterで吐き出される必要がある。

最終的にうまくいったのですが、PHPExcelのコードの修正が必要です。

■PHPExcel/Writer/Excel5/Worksheet.php(PHPExcel 1.7.7)
2844:                // formula 1
2845:                try {
2846:                    $formula1 = $dataValidation->getFormula1();
2847:                    // >>> Added by S.Sakai
2848://                    if ($type == 0x03) { // list type
2849:                    if ($type == 0x03 && preg_match('/^\".*\"$/', $formula1)) { // list type
2850:                    // <<< Added by S.Sakai

2851:                        $formula1 = str_replace(',', chr(0), $formula1);
2852:                    }
2853:                    $this->_parser->parse($formula1);
2854:                    // >>> Added by S.Sakai
2855:                    if (is_array($this->_parser->_parse_tree)
2856:                            && strtoupper($this->_parser->_parse_tree['value']) == 'INDIRECT') {
2857:                        $this->_parser->_parse_tree['force_reference'] = true;
2858:                    }
2859:                    // <<< Added by S.Sakai

2860:                    $formula1 = $this->_parser->toReversePolish();
2861:                    $sz1 = strlen($formula1);
2862: 
2863:                } catch(Exception $e) {
2864:                    $sz1 = 0;
2865:                    $formula1 = '';
2866:                }

■PHPExcel/Writer/Excel5/Parser.php(PHPExcel 1.7.7)
616:    // >>> Added by S.Sakai
617://    function _convertFunction($token, $num_args)
618:    function _convertFunction($token, $num_args, $force_reference)
619:    // <<< Added by S.Sakai

620:    {
621:        $args = $this->_functions[$token][1];
622://        $volatile = $this->_functions[$token][3];
623:
624:        // Fixed number of args eg. TIME($i,$j,$k).
625:        if ($args >= 0) {
626:            return pack("Cv", $this->ptg['ptgFuncV'], $this->_functions[$token][0]);
627:        }
628:        // Variable number of args eg. SUM($i,$j,$k, ..).
629:        if ($args == -1) {
630:            // >>> Added by S.Sakai
631://            return pack("CCv", $this->ptg['ptgFuncVarV'], $num_args, $this->_functions[$token][0]);
632:            if ($force_reference) {
633:                return pack("CCv", $this->ptg['ptgFuncVar'], $num_args, $this->_functions[$token][0]);
634:            } else {
635:                return pack("CCv", $this->ptg['ptgFuncVarV'], $num_args, $this->_functions[$token][0]);
636:            }
637:            // <<< Added by S.Sakai

638:        }
639:    }


1571:        // if it's a function convert it here (so we can set it's arguments)
1572:        if (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/",$tree['value']) and
1573:            !preg_match('/^([A-Ia-i]?[A-Za-z])(\d+)$/',$tree['value']) and
1574:            !preg_match("/^[A-Ia-i]?[A-Za-z](\d+)\.\.[A-Ia-i]?[A-Za-z](\d+)$/",$tree['value']) and
1575:            !is_numeric($tree['value']) and
1576:            !isset($this->ptg[$tree['value']]))
1577:        {
1578:            // left subtree for a function is always an array.
1579:            if ($tree['left'] != '') {
1580:                $left_tree = $this->toReversePolish($tree['left']);
1581:            } else {
1582:                $left_tree = '';
1583:            }
1584:            // add it's left subtree and return.
1585:            // >>> Added by S.Sakai
1586://            return $left_tree.$this->_convertFunction($tree['value'], $tree['right']);
1587:            return $left_tree.$this->_convertFunction($tree['value'], $tree['right'], $tree['force_reference']);
1588:            // <<< Added by S.Sakai

1589:        } else {
1590:            $converted_tree = $this->_convert($tree['value']);
1591:        }

CONCATENATE(“野菜”)の部分をCONCATENATE(“野菜_”,A2)のように変えれば、ほかのセルの入力値を使ってさらに動的な入力規則を設定できるようになりますよ。

今日は丸一日これにドはまりでした。
PHPExcelには、このページをそのまま通知しようかな。。

あ、あとPHPExcelで困っている人にお勧めなのが、下の2つです。

それではお休みなさい (つ_-*)。οΟ ゜

CMS プログラミング

WordPressなどのソース一式をzip圧縮してダウンロードする方法

Published by:

レンタルサーバーでWordPressなどのCMSを動かしている方は数多くいるかと思いますが、sshやtelnetアクセスができないサーバーも意外に多くあります。
その場合、FTPで時間をかけて何百、何千というファイルをアップロード、ダウンロードしなければいけません。

アップロードについてはすでに「unzip.zip」という素晴らしいツールがありますので、みなさまそちらを使いましょう。

今回ここで紹介するのは、zipで圧縮してまとめてダウンロードする方法です。

zipdownload.zip

上のプログラムをGET&解凍して出て来るzipdownload.phpを、まとめてダウンロードしたいディレクトリの中にアップロードします。
WordPressの場合は、wp-contentとか、wp-config.phpなどのファイルがあるところにアップすればよいかと思います。

ここまで出来れば、後はブラウザで http://xxx/zipdownload.php のようにリクエストしてください!
download.zipという名前でダウンロードが開始されます。

ダウンロードが終わった後に zipdownload.php を必ず削除してくださいねー

プログラミング

「PHP使いはもう正規表現をblogに書くな」のメールアドレスチェック用正規表現をPHP用に書きなおす

Published by:

メールアドレスをチェックする機能を作るときに、これまで2度「PHP使いはもう正規表現をblogに書くな」と言わせないでくれ / 404 Blog Not Foundを参考にさせていただきましたが、何故か(よっぽどお怒りだったのか?)PHPでは直接使えない記述になっていましたので、毎回自分で修正して使っていました。
今後も使いたい正規表現ですので、PHPでの実装コードと、JavaScript版の実装コードをメモします。

小飼 弾さんの作られたオリジナル正規表現

/^(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+))*)|(?:"(?:\\[^\r\n]|[^\\"])*")))\@(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+))*)|(?:\[(?:\\\S|[\x21-\x5a\x5e-\x7e])*\])))$/

PHP用の実装コード

if (!preg_match('/^(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+))*)|(?:"(?:\\[^\r\n]|[^\\"])*")))\@(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&\'*+\/=?\^`{}~|\-]+))*)|(?:\[(?:\\\S|[\x21-\x5a\x5e-\x7e])*\])))$/', $email)) {
    $error = '正しいメールアドレスを入力してください。';
}

ereg関数を使えばオリジナル正規表現のままでよいのですが、preg*の方が一般的だと思います。
ここでは「’」と「/」をエスケープしています。

JavaScript用の実装コード

if (!email.match(/^(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&'*+\/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&'*+\/=?\^`{}~|\-]+))*)|(?:"(?:\\[^\r\n]|[^\\"])*")))\@(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&'*+\/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&'*+\/=?\^`{}~|\-]+))*)|(?:\[(?:\\\S|[\x21-\x5a\x5e-\x7e])*\])))$/)) {
    error = "正しいメールアドレスを入力してください。";
}

JavaScriptは正規表現リテラルが使えますので、「/」のみをエスケープしています。

ただ、この正規表現では「da.me..@docomo.ne.jp」といったRF2822非準拠の携帯メールアドレスがエラーで弾かれるんですよね。
これをdocomoの変メールへの対応バージョンは・・・次の人にまかせた!