<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" 
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>台扣啵的研究日誌-PHP</title>
<link>http://blog.roodo.com/taikobo0/archives/cat_483513.html</link>
<description></description>
<language>zh-tw</language>
<generator>Roodo Blog System</generator>
<copyright>All Rights Reserved</copyright>
<atom:link href="http://blog.roodo.com/taikobo0/archives/cat_483513.xml" rel="self" type="application/rss+xml" />
<item>
	<title>[PHP] ZendFramework Zend_Db_Table_Rowset::getRow() 的用法</title>
	<description><![CDATA[
			一般在使用 ZendFramework 的 Zend_Db_Table_Rowset  fetchAll() 時，都是需要 Rowset 裡面全部的資料；不過偶爾有會有只需要單筆資料列的情況，這個時候就可以藉助 current() 或是 getRow() 取得單筆資料列。current() 很單純，就是目前 Rowset 中指向的資料列，通常在沒有指定指標的情況下，就是該 Rowset 中的第一筆資料：$table = new Table();$select = $table-&gt;select();$rowset = $table-&gt;fetchAll($select);$row = $rowset-&gt;current();// 這裡的 $row 就會是 $rowset 的第一筆資料列。getRow() 就比較有彈性，它可以指定取得第幾個資料列，並決定是不是要將指標移至該資料列（預設為不指定）。getRow($position, $seek = false) // $position 設定取得第幾列資料（從 0 開始）// $seek 設定是否要將指標移至該資料列（預設為不指定）用法如下：$table = new Table();$select = $table-&gt;select();$rowset = $table-&gt;fetchAll($select);$row = $rowset-&gt;getRow(1); // 這裡的 $row 就會是 $rowset 的第二筆資料列。要比較注意的是 $seek 的使用時機，是否有需要移動指標，就看程式的需求囉；使用後呈現的資料，如以下的例子：$table = new Table();$select = $table-&gt;select();$rowset = $table-&gt;fetchAll($select);$row = $rowset-&gt;current();// 這裡的 $row 就會是 $rowset 的第一筆資料列。$row = $rowset-&gt;getRow(1);// 這裡的 $row 就會是 $rowset 的第二筆資料列（$seek 預設為 false，故指標不移動）。$row = $rowset-&gt;current();// 這裡的 $row 還是 $rowset 的第一筆資料列。$row = $rowset-&gt;getRow(1, true);// 這裡的 $row 就會是 $rowset 的第二筆資料列（$seek 設為 true，故指標移動）。 $row = $rowset-&gt;current();// 這裡的 $row 就會變成是 $rowset 的第二筆資料列。大概就是這樣；在這邊做個紀錄，感謝 Jace 解惑^^
		]]>
	</description>
	<content:encoded><![CDATA[
			一般在使用 <a href="http://framework.zend.com/" target="_blank">ZendFramework</a> 的 <a href="http://framework.zend.com/manual/en/zend.db.table.rowset.html" target="_blank">Zend_Db_Table_Rowset</a>  fetchAll() 時，都是需要 Rowset 裡面全部的資料；不過偶爾有會有只需要單筆資料列的情況，這個時候就可以藉助 current() 或是 getRow() 取得單筆資料列。<br /><br />current() 很單純，就是目前 Rowset 中指向的資料列，通常在沒有指定指標的情況下，就是該 Rowset 中的第一筆資料：<br /><pre class="code">$table = new Table();<br />$select = $table-&gt;select();<br />$rowset = $table-&gt;fetchAll($select);<br />$row = $rowset-&gt;current();<br />// 這裡的 $row 就會是 $rowset 的第一筆資料列。<br /></pre>getRow() 就比較有彈性，它可以指定取得第幾個資料列，並決定是不是要將指標移至該資料列（預設為不指定）。<pre class="code">getRow($position, $seek = false) <br />// $position 設定取得第幾列資料（從 0 開始）<br />// $seek 設定是否要將指標移至該資料列（預設為不指定）</pre>用法如下：<pre class="code">$table = new Table();<br />$select = $table-&gt;select();<br />$rowset = $table-&gt;fetchAll($select);<br />$row = $rowset-&gt;getRow(1); <br />// 這裡的 $row 就會是 $rowset 的第二筆資料列。</pre>要比較注意的是 $seek 的使用時機，是否有需要移動指標，就看程式的需求囉；使用後呈現的資料，如以下的例子：<pre class="code">$table = new Table();<br />$select = $table-&gt;select();<br />$rowset = $table-&gt;fetchAll($select);<br />$row = $rowset-&gt;current();<br />// 這裡的 $row 就會是 $rowset 的第一筆資料列。<br /><br />$row = $rowset-&gt;getRow(1);<br />// 這裡的 $row 就會是 $rowset 的第二筆資料列（$seek 預設為 false，故指標不移動）。<br /><br />$row = $rowset-&gt;current();<br />// 這裡的 $row 還是 $rowset 的第一筆資料列。<br /><br />$row = $rowset-&gt;getRow(1, true);<br />// 這裡的 $row 就會是 $rowset 的第二筆資料列（$seek 設為 true，故指標移動）。<br /> <br />$row = $rowset-&gt;current();<br />// 這裡的 $row 就會變成是 $rowset 的第二筆資料列。</pre>大概就是這樣；在這邊做個紀錄，感謝 Jace 解惑^^
		
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/taikobo0/archives/8256035.html</link>
	<guid>http://blog.roodo.com/taikobo0/archives/8256035.html</guid>
	<category>PHP</category>
	<pubDate>Thu, 05 Feb 2009 15:27:45 +0800</pubDate>
</item>
<item>
	<title>[PHP] Zend_Search_Lucene中文分詞實做</title>
	<description><![CDATA[
			最近在練習中有用到搜尋的功能。一般對MySQL資料庫作搜尋，常用的做法是針對資料表中的特定欄位，用「%」LIKE的方式去尋找。然而這樣的做法常伴隨著許多限制，使用者必須先選定所要輸入的資料欄位，再對其進行搜尋；習慣了Google搜尋所帶來的便利，最理想的方式是只有一個輸入格，且可以在此輸入格中任意輸入，即可對整個資料庫進行搜尋。在MySQL中稱為Full-Text（全文檢索）；然而拜完Google大神以後，網路上前輩們幾乎是一面倒的否定全文檢索。最主要的原因是因為它不支持中文！全文檢索的做法，即是對資料庫裡的資料進行「分詞」的索引處理，有了索引，搜尋起來自然有效率的多；然而中文字不同於英文，一個句子中單獨一個中文字就可能有它的意思，另一個最大的分別在於中文句子可不像英文句子由單字與「空格」組成；建立索引時的「分詞」的動作，就是以空格進行判斷！全文檢索的問題在網路上一直存在著，但是前輩們似乎都沒有非常完美的解答；甚至有人直接勸退提問者：「全文檢索的功能，是可以讓你寫好幾篇博士論文的研究！」如此可見，Google雲端運算的強大。既然資料庫端無解，我就從PHP的方向著手吧～Google的確是大神，讓我找到了Zend Framework就有分詞的函式Zend Search Lucene；而且原本這個功能其實也不支持中文，萬能的Google大神還幫我找到了支持中文的解決方法！在PHP製作中文全文搜尋不求人中，作者巨細靡遺的說明了資料夾配置、原始程式碼，還非常貼心的提供範例程式的下載。在如何讓Zend_Search_Lucene支持中文分詞中，作者改良了分詞用的類別，讓中文分詞的動作更加準確！既然有如此完整的範例，我當然是馬上適用在練習中啦！目前練習所利用的開發框架，是Jace一手打造的Wacow Framework。結合Zend Framework與Smarty，以及許多在專案製作時常會用到的工具，是公司目前專案開發的主力，也是我目前需要熟練的工具。我把建立索引的功能放在首頁，這樣只要有人進入首頁就會觸發建立索引（當然這樣做的代價是每次進首頁的速度都會被拖慢）。因為自動載入類別的關係，在建立索引時不需再額外include或require，程式碼如下：IndexController.php（部分節錄）// 建立分詞索引// 關閉 Notice 錯誤提醒error_reporting(E_ALL ^ E_NOTICE);// 資料是 utf8 為編碼的這句為重點。如果你是 utf8 的話必需加入，否則資料會錯誤；另Phpbean是需要另外建立的中文分詞的類別Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Phpbean());if (function_exists("set_time_limit") && ! get_cfg_var('safe_mode')) {    set_time_limit(0);}$index = new Zend_Search_Lucene('index', true);$itemTable = new Items();$itemRowset = $itemTable->fetchAll();foreach ($itemRowset as $itemRow) {    $url         = '/gime/item/detail/id/' . $itemRow->id; // 建立連結    $itemName    = $itemRow->name; // 抓出物品名稱    $description = $itemRow->description; // 抓出物品敘述    //儲存網頁的位置以在搜尋結果中連結.    $doc = new Zend_Search_Lucene_Document(); // 建立新的索引文件    $doc->addField(Zend_Search_Lucene_Field::UnIndexed('url', strtolower($url)));    $doc->addField(Zend_Search_Lucene_Field::Text('name', strtolower($itemName), 'utf-8'));    $doc->addField(Zend_Search_Lucene_Field::Text('contents', strtolower($description), 'utf-8'));    $index->addDocument($doc); //把索引文件加到索引中}$index->commit(); //提交，及保存索引Phpbean.php
		]]>
	</description>
	<content:encoded><![CDATA[
			最近在練習中有用到搜尋的功能。一般對MySQL資料庫作搜尋，常用的做法是針對資料表中的特定欄位，用「%」LIKE的方式去尋找。然而這樣的做法常伴隨著許多限制，使用者必須先選定所要輸入的資料欄位，再對其進行搜尋；習慣了<a href="http://www.google.com.tw/" target="_blank">Google搜尋</a>所帶來的便利，最理想的方式是只有一個輸入格，且可以在此輸入格中任意輸入，即可對整個資料庫進行搜尋。在MySQL中稱為<a href="http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html" target="_blank">Full-Text（全文檢索）</a>；然而拜完Google大神以後，網路上前輩們幾乎是一面倒的否定全文檢索。最主要的原因是因為它不支持中文！<br /><br />全文檢索的做法，即是對資料庫裡的資料進行「分詞」的索引處理，有了索引，搜尋起來自然有效率的多；然而中文字不同於英文，一個句子中單獨一個中文字就可能有它的意思，另一個最大的分別在於中文句子可不像英文句子由單字與「空格」組成；建立索引時的「分詞」的動作，就是以空格進行判斷！<br /><br />全文檢索的問題在網路上一直存在著，但是前輩們似乎都沒有非常完美的解答；甚至有人直接勸退提問者：「全文檢索的功能，是可以讓你寫好幾篇博士論文的研究！」如此可見，Google<a href="http://zh.wikipedia.org/w/index.php?title=%E9%9B%B2%E7%AB%AF%E9%81%8B%E7%AE%97&variant=zh-tw" target="_blank">雲端運算</a>的強大。既然資料庫端無解，我就從PHP的方向著手吧～Google的確是大神，讓我找到了<a href="http://framework.zend.com/" target="_blank">Zend Framework</a>就有分詞的函式<a href="http://framework.zend.com/manual/en/zend.search.lucene.html" target="_blank">Zend Search Lucene</a>；而且原本這個功能其實也不支持中文，萬能的Google大神還幫我找到了支持中文的解決方法！<br /><br />在<a href="http://www.vincent.idv.hk/2007/10/16/php-chinese-fulltext-search/" target="_blank">PHP製作中文全文搜尋不求人</a>中，作者巨細靡遺的說明了資料夾配置、原始程式碼，還非常貼心的提供範例程式的下載。在<a href="http://www.blogkid.cn/archives/1001.html" target="_blank">如何讓Zend_Search_Lucene支持中文分詞</a>中，作者改良了分詞用的類別，讓中文分詞的動作更加準確！既然有如此完整的範例，我當然是馬上適用在練習中啦！<br /><br />目前練習所利用的開發框架，是<a href="http://blog.roodo.com/jaceju" target="_blank">Jace</a>一手打造的<a href="http://code.google.com/p/wacowframework/" target="_blank">Wacow Framework</a>。結合<a href="http://framework.zend.com/" target="_blank">Zend Framework</a>與<a href="http://www.smarty.net/" target="_blank">Smarty</a>，以及許多在專案製作時常會用到的工具，是公司目前專案開發的主力，也是我目前需要熟練的工具。我把建立索引的功能放在首頁，這樣只要有人進入首頁就會觸發建立索引（當然這樣做的代價是每次進首頁的速度都會被拖慢）。因為自動載入類別的關係，在建立索引時不需再額外include或require，程式碼如下：<br /><br /><strong>IndexController.php（部分節錄）</strong><br /><br />// 建立分詞索引<br />// 關閉 Notice 錯誤提醒<br />error_reporting(E_ALL ^ E_NOTICE);<br />// 資料是 utf8 為編碼的這句為重點。如果你是 utf8 的話必需加入，否則資料會錯誤；另Phpbean是需要另外建立的中文分詞的類別<br />Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Phpbean());<br />if (function_exists("set_time_limit") && ! get_cfg_var('safe_mode')) {<br />    set_time_limit(0);<br />}<br />$index = new Zend_Search_Lucene('index', true);<br />$itemTable = new Items();<br />$itemRowset = $itemTable->fetchAll();<br />foreach ($itemRowset as $itemRow) {<br />    $url         = '/gime/item/detail/id/' . $itemRow->id; // 建立連結<br />    $itemName    = $itemRow->name; // 抓出物品名稱<br />    $description = $itemRow->description; // 抓出物品敘述<br />    //儲存網頁的位置以在搜尋結果中連結.<br />    $doc = new Zend_Search_Lucene_Document(); // 建立新的索引文件<br />    $doc->addField(Zend_Search_Lucene_Field::UnIndexed('url', strtolower($url)));<br />    $doc->addField(Zend_Search_Lucene_Field::Text('name', strtolower($itemName), 'utf-8'));<br />    $doc->addField(Zend_Search_Lucene_Field::Text('contents', strtolower($description), 'utf-8'));<br />    $index->addDocument($doc); //把索引文件加到索引中<br />}<br />$index->commit(); //提交，及保存索引<br /><br /><strong>Phpbean.php</strong><br /><br /><?php<br /><br />class Phpbean extends Zend_Search_Lucene_Analysis_Analyzer_Common<br />{<br />    private $_position;<br /><br />    private $_cnStopWords = array();<br /><br />    public function setCnStopWords($cnStopWords){<br />        $this->_cnStopWords = $cnStopWords;<br />    }<br /><br />    /**<br />     * Reset token stream<br />     */<br />    public function reset()<br />    {<br />        $this->_position = 0;<br />        $search = array(",", "/", "\", ".", ";", ":", """, "!", "~", "`", "^", "(", ")", "?", "-", "'", "<", ">", "$", "&", "%", "#", "@", "+", "=", "{", "}", "[", "]", "：", "）", "（", "．", "。", "，", "！", "；", "“", "”", "‘", "’", "［", "］", "、", "—", "　", "《", "》", "－", "…", "【", "】","的");<br />        $this->_input = str_replace($search,' ',$this->_input);<br />        $this->_input = str_replace($this->_cnStopWords,' ',$this->_input);<br />    }<br /><br />    /**<br />     * Tokenization stream API<br />     * Get next token<br />     * Returns null at the end of stream<br />     *<br />     * @return Zend_Search_Lucene_Analysis_Token|null<br />     */<br />    public function nextToken()<br />    {<br />        if ($this->_input === null) {<br />            return null;<br />        }<br />        $len = strlen($this->_input);<br />        while ($this->_position < $len) {<br />            while ($this->_position < $len && $this->_input[$this->_position] == ' ') {<br />                $this->_position++;<br />            }<br />            $termStartPosition = $this->_position;<br />            $temp_char = $this->_input[$this->_position];<br />            $isCnWord = false;<br />            if (ord($temp_char) > 127) {<br />                $i = 0;<br />                while ($this->_position < $len && ord($this->_input[$this->_position]) >127) {<br />                    $this->_position = $this->_position + 3;<br />                    $i ++;<br />                    if ($i == 2) {<br />                        $isCnWord = true;<br />                        break;<br />                    }<br />                }<br />                if ($i == 1) continue;<br />            } else {<br />                while ($this->_position < $len && ctype_alnum($this->_input[$this->_position])) {<br />                    $this->_position++;<br />                }<br />                // echo $this->_position.":".$this->_input[$this->_position]."\n";<br />            }<br />            if ($this->_position == $termStartPosition) {<br />                $this->_position++;<br />                continue;<br />            }<br /><br />            $token = new Zend_Search_Lucene_Analysis_Token(<br />            substr($this->_input,<br />            $termStartPosition,<br />            $this->_position - $termStartPosition),<br />            $termStartPosition,<br />            $this->_position);<br />            $token = $this->normalize($token);<br />            if ($isCnWord) $this->_position = $this->_position - 3;<br />            if ($token !== null) {<br />                return $token;<br />            }<br />        }<br />        return null;<br />    }<br />}<br /><br /><strong>SearchController.php（部分節錄）</strong><br /><br />Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Phpbean());<br />$index = new Zend_Search_Lucene('index');<br />$query = $this->_request->getParam('query'); // 擷取來自表單的關鍵字<br />$query = trim($query);<br />if (strlen($query) > 0) {<br />    try {<br />        $query2 = Zend_Search_Lucene_Search_QueryParser::parse(strtolower($query), "utf-8");<br />        $hits = $index->find($query2); // 根據關鍵字找到資料，並將資料回存為物件<br />    }<br />    catch (Zend_Search_Lucene_Exception $ex) {<br />        $hits = array();<br />    }<br />    $numHits = count($hits); // 根據關鍵字找到資料的數量<br />}<br /><br />非常簡單的實作；然而就全文檢索來說還是有缺點的！首先，建立分詞索引時必定會耗費系統資源，故比較好的做法是批次定時處理建立索引的動作。第二點是中文的問題，因為中文字詞與連貫的句子的關係，在分詞時是以二個字為一個詞的最基本單位，所以單一個中文字是不會有任何搜尋結果的。最後因為建立分詞索引為觸發事件，如果沒有去觸發它就無法更新分詞至目前資料庫的最新狀態。我覺得分詞索引的方式很像是MySQL的View資料表，也是將資料表中的欄位作一個資料上的更新，只是它沒有欄位的限制，可以針對建立的「詞」索引進行搜尋。就某方面來說是很好用的功能，也不失為中文在全文索引時的一種解決方案。^^
		
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/taikobo0/archives/6027073.html</link>
	<guid>http://blog.roodo.com/taikobo0/archives/6027073.html</guid>
	<category>PHP</category>
	<pubDate>Thu, 15 May 2008 10:22:57 +0800</pubDate>
</item>
<item>
	<title>[PHP] 表單輸入時對於HTML的過濾</title>
	<description><![CDATA[
			在PHP中最常見的應用就是互動表單，因此接收用戶端資訊是非常常見的事！然而俗話說：「世風日下，人心不古」，這年頭誰知道用戶端的人在想些什麼？用戶端送出的資訊很有可能會包含一些惡意的語法，對於２４小時暴露在網路環境的網站來說，時時刻刻都得小心防範駭客的攻擊，提升自我的資訊安全觀念非常重要。所以在接收用戶端資訊後，存入資料庫之前，都會先對其進行基本的過濾；第一個要判斷的就是HTML語法的攻擊！許多惡意語法都是建立在HTML上，PHP本身有提供轉換HTML碼的函數：htmlspecialchars()與htmlentities()；其中htmlspecialchars()只會轉換HTML相關碼：             '&amp;' =&gt; '&amp;amp;'                        '&quot;' =&gt; '&amp;quot;'                        ''' =&gt; '&amp;#039;'&nbsp;                        '&lt;' =&gt; '&amp;lt;'                        '&gt;' =&gt; '&amp;gt;'           而htmlentities()則是把字串中所有字元做轉換，另外還可以設定轉換字串的編碼方式。還有一個函數：strip_tags()是直接把HTML的標籤整個過濾掉。之前在題目試作／哇寶基本能力測試一文中，也有提到相關的觀念。另外附上那個時候google到的一個國外防止XSS的網頁：PHP XSS (cross site scripting) filter function，他有對HTML作是否可能被當作惡意的語法作判斷，不過測試後發現對中文的處理好像有點問題...就當作是英文的過濾函式吧～
		]]>
	</description>
	<content:encoded><![CDATA[
			在PHP中最常見的應用就是互動表單，因此接收用戶端資訊是非常常見的事！然而俗話說：「世風日下，人心不古」，這年頭誰知道用戶端的人在想些什麼？用戶端送出的資訊很有可能會包含一些惡意的語法，對於２４小時暴露在網路環境的網站來說，時時刻刻都得小心防範駭客的攻擊，提升自我的資訊安全觀念非常重要。所以在接收用戶端資訊後，存入資料庫之前，都會先對其進行基本的過濾；第一個要判斷的就是HTML語法的攻擊！<br /><br />許多惡意語法都是建立在HTML上，PHP本身有提供轉換HTML碼的函數：<a href="http://tw.php.net/manual/en/function.htmlspecialchars.php" target="_blank">htmlspecialchars()</a>與<a href="http://tw.php.net/manual/en/function.htmlentities.php" target="_blank">htmlentities()</a>；其中<a href="http://tw.php.net/manual/en/function.htmlspecialchars.php" target="_blank">htmlspecialchars()</a>只會轉換HTML相關碼：<br /><ul class="itemizedlist"><li class="listitem">      <span class="simpara">       '&amp;' =&gt; '&amp;amp;'      </span>     </li><li class="listitem">      <span class="simpara">       '&quot;' </span><span class="simpara">=&gt;</span><span class="simpara"> '&amp;quot;'      </span>     </li><li class="listitem">      <span class="simpara">       ''' </span><span class="simpara">=&gt;</span><span class="simpara"> '&amp;#039;'&nbsp;      </span>     </li><li class="listitem">      <span class="simpara">       '&lt;' </span><span class="simpara">=&gt;</span><span class="simpara"> '&amp;lt;'      </span>     </li><li class="listitem">      <span class="simpara">       '&gt;' </span><span class="simpara">=&gt;</span><span class="simpara"> '&amp;gt;'      </span>     </li></ul>而<a href="http://tw.php.net/manual/en/function.htmlentities.php" target="_blank">htmlentities()</a>則是把字串中所有字元做轉換，另外還可以設定轉換字串的編碼方式。還有一個函數：<a href="http://tw.php.net/manual/en/function.strip-tags.php" target="_blank">strip_tags()</a>是直接把HTML的標籤整個過濾掉。<br /><br />之前在<a href="http://blog.roodo.com/taikobo0/archives/5751329.html" target="_blank">題目試作／哇寶基本能力測試</a>一文中，也有提到相關的觀念。另外附上那個時候google到的一個國外防止XSS的網頁：<a href="http://quickwired.com/smallprojects/php_xss_filter_function.php" target="_blank">PHP XSS (cross site scripting) filter function</a>，他有對HTML作是否可能被當作惡意的語法作判斷，不過測試後發現對中文的處理好像有點問題...就當作是英文的過濾函式吧～
		
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/taikobo0/archives/5881583.html</link>
	<guid>http://blog.roodo.com/taikobo0/archives/5881583.html</guid>
	<category>PHP</category>
	<pubDate>Fri, 18 Apr 2008 18:07:22 +0800</pubDate>
</item>
<item>
	<title>[PHP] ZendFramework 1.5.1安裝</title>
	<description><![CDATA[
			ZendFramework是PHP的一個開發用框架，主要以PHP5作為撰寫時的基礎。要使用之前當然得先建立環境，以下是安裝的順序：參考「在Zend Framework上開發一個HelloWorld」１、首先先從ZendFramework的官方網站下在最新版本的ZendFramework 1.5.1；解壓縮後放在任意資料夾。我是放在「C:\ZendFramework」這個目錄下。２、修改Apache httpd.conf設定：（１）啟動 Apache的 .htaccess功能，搜尋「AllowOverride」 並將其設定為 All（２） 開啟 LoadModule rewrite_module modules/mod_rewrite.so。３、修改PHP php.ini設定：（１）設定include_path = &quot;.;C:\ZendFramework&quot; （２）開啟extension=php_pdo.dll、extension=php_pdo_mysql.dll重新啟動Apache，如此一來基本的環境算是建置完成了。
		]]>
	</description>
	<content:encoded><![CDATA[
			ZendFramework是PHP的一個開發用框架，主要以PHP5作為撰寫時的基礎。要使用之前當然得先建立環境，以下是安裝的順序：參考「<a href="http://blog.ring.idv.tw/comment.ser?i=86" target="_blank">在Zend Framework上開發一個HelloWorld</a>」<br /><br />１、首先先從ZendFramework的<a href="http://framework.zend.com/" target="_blank">官方網站</a>下在最新版本的<a href="http://framework.zend.com/releases/ZendFramework-1.5.1/ZendFramework-1.5.1.zip" target="_blank">ZendFramework 1.5.1</a>；解壓縮後放在任意資料夾。我是放在「C:\ZendFramework」這個目錄下。<br /><br />２、修改Apache httpd.conf設定：<br /><span>（１）啟動 Apache的 .htaccess功能，搜尋「AllowOverride」 並將其設定為 All<br />（２）</span><span> 開啟</span><span> LoadModule rewrite_module modules/mod_rewrite.so。<br /><br />３、</span>修改PHP php.ini設定：<br />（１）設定include_path = &quot;.;C:\ZendFramework&quot; <br />（２）開啟<span>extension=php_pdo.dll、extension=php_pdo_mysql.dll<br /><br />重新啟動</span>Apache，<span>如此一來基本的環境算是建置完成了。</span>
		
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/taikobo0/archives/5827109.html</link>
	<guid>http://blog.roodo.com/taikobo0/archives/5827109.html</guid>
	<category>PHP</category>
	<pubDate>Sun, 06 Apr 2008 22:22:20 +0800</pubDate>
</item>
<item>
	<title>[PHP] 編碼轉換函數mb_convert_encoding()</title>
	<description><![CDATA[
			一般正常在處理Big5＜－＞UTF-8編碼上的轉換，第一個想到的就是iconv()函數；雖然需要額外安裝iconv函式庫，不過因為大部分人都有這種需求，虛擬主機商一般都會安裝，如果是自己的主機就更沒有這種問題了～在Big5轉換成UTF-8方面，完全沒有問題；不過在UTF-8轉換成Big5方面，可就出現問題啦！因為UTF-8編碼對應的字遠比Big5編碼多，所以在一些特殊中文字的轉換上，如：堃、犇等字，iconv()函數就會出現錯誤啦！本來一直都沒有發現到這方面的問題，不過最近在公司專案管理系統上的Excel表轉出時，遇到有對方公司有「犇」這個字，讓iconv()函數發生錯誤而導致轉出的Excel檔案整個損壞的情況發生...Excel在正常輸入時是對應UTF-8編碼的，不過在轉出檔案時必須改為Big5編碼，不然UTF-8編碼的中文字會變成亂碼～無法自動判斷真是傷腦筋耶！後來上網找了很久，都沒有令人滿意的答案；大家在轉出Excel檔時，幾乎都還是利用iconv()函數先轉成Big5編碼再轉出。後來我發現到另外一個函數：mb_convert_encoding()，似乎也是在處理編碼轉換的函數。試用之後雖然不存在的字還是不會自己生出來（如：堃、犇這些Big5編碼本來就沒有的字），但是轉不出來的字它會以「?」顯示，不會發生錯誤訊息，自然也就能正確的開啟轉出的Excel檔囉！雖然這並不是治本的方法，不過算是有稍微解決一些問題啦！編碼真的是我目前最深的痛，轉來轉去真的很麻煩；目前我寫的PHP已經一律採用UTF-8編碼了～在網頁上是沒什麼問題，不過需要配合其他程式（如：Excel）時就必須轉來轉去...還蠻麻煩的哩！希望以後開發的軟體都能支援Unicode，畢竟萬國碼才是未來的趨勢吧！
		]]>
	</description>
	<content:encoded><![CDATA[
			一般正常在處理Big5＜－＞UTF-8編碼上的轉換，第一個想到的就是<a href="http://tw.php.net/function.iconv" target="_blank">iconv()</a>函數；雖然需要額外安裝iconv函式庫，不過因為大部分人都有這種需求，虛擬主機商一般都會安裝，如果是自己的主機就更沒有這種問題了～<br /><br />在Big5轉換成UTF-8方面，完全沒有問題；不過在UTF-8轉換成Big5方面，可就出現問題啦！因為UTF-8編碼對應的字遠比Big5編碼多，所以在一些特殊中文字的轉換上，如：堃、犇等字，<a href="http://tw.php.net/function.iconv" target="_blank">iconv()</a>函數就會出現錯誤啦！本來一直都沒有發現到這方面的問題，不過最近在公司專案管理系統上的Excel表轉出時，遇到有對方公司有「犇」這個字，讓<a href="http://tw.php.net/function.iconv" target="_blank">iconv()</a>函數發生錯誤而導致轉出的Excel檔案整個損壞的情況發生...Excel在正常輸入時是對應UTF-8編碼的，不過在轉出檔案時必須改為Big5編碼，不然UTF-8編碼的中文字會變成亂碼～無法自動判斷真是傷腦筋耶！<br /><br />後來上網找了很久，都沒有令人滿意的答案；大家在轉出Excel檔時，幾乎都還是利用<a href="http://tw.php.net/function.iconv" target="_blank">iconv()</a>函數先轉成Big5編碼再轉出。後來我發現到另外一個函數：<a href="http://tw.php.net/mb_convert_encoding" target="_blank">mb_convert_encoding()</a>，似乎也是在處理編碼轉換的函數。試用之後雖然不存在的字還是不會自己生出來（如：堃、犇這些Big5編碼本來就沒有的字），但是轉不出來的字它會以「?」顯示，不會發生錯誤訊息，自然也就能正確的開啟轉出的Excel檔囉！雖然這並不是治本的方法，不過算是有稍微解決一些問題啦！<br /><br />編碼真的是我目前最深的痛，轉來轉去真的很麻煩；目前我寫的PHP已經一律採用UTF-8編碼了～在網頁上是沒什麼問題，不過需要配合其他程式（如：Excel）時就必須轉來轉去...還蠻麻煩的哩！希望以後開發的軟體都能支援Unicode，畢竟萬國碼才是未來的趨勢吧！
		
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/taikobo0/archives/5677701.html</link>
	<guid>http://blog.roodo.com/taikobo0/archives/5677701.html</guid>
	<category>PHP</category>
	<pubDate>Tue, 11 Mar 2008 10:37:46 +0800</pubDate>
</item>
<item>
	<title>[PHP] 匯出pdf檔的方法</title>
	<description><![CDATA[
			偶然在網路上看到介紹的文章：免費好用的 PDF Library 大蒐集。原本是想用來寫一個套印的小程式的，不過沒想到這玩意兒這麼難搞；因為中文編碼的關係。何況已經有人寫出類似的程式囉：藍色小舖PHP -&gt; FPDF。還是稍微記錄一下使用的過程吧！說到pdf檔產生，網路上似乎一面倒的推薦FPDF，其他pdf產生的class也幾乎是在它的基礎下衍生出來的～算是元老級的pdf class！另外對於中文的支援有提供chinese.zip、以及支援中文Unicode的chinese-unicode.zip；目前我試用中文Unicode的FPDF可以完整呈現！（未使用Unicode的FPDF不知道為什麼我的FoxitReader一片空白...）以下是範例的程式碼：&lt;?phprequire('fpdf/chinese-unicode.php');&nbsp; //include必要程式$pdf=new PDF_Unicode();&nbsp; //調用PDF_Unicode class $pdf-&gt;Open(); $pdf-&gt;AddPage(); $pdf-&gt;AddUniCNShwFont('uni'); $pdf-&gt;SetFont('uni','',20);&nbsp;$pdf-&gt;Write(10, &quot;1234abcd學生名字\n伃綉堃亘&quot;);$pdf-&gt;Ln();$pdf-&gt;MultiCell (120, 10, &quot;服\n務\n單\n位&quot;);$pdf-&gt;Cell (240, 10, &quot;本文用UTF8做為中文字編碼, 在這裡還是呼叫同樣的FPDF函數&quot;);$pdf-&gt;Ln();$pdf-&gt;Output();?&gt;我另外還試過TCPDF，號稱支援Unicode，日文、德文、阿拉伯文洋洋灑灑的列了十幾種...只可惜獨漏中文（繁/簡體）～而且它所謂支援Unicode的方法，是直接將字型檔壓縮在pdf檔中，所以會造成pdf檔的異常肥大；實在不是一種很優的方式。
		]]>
	</description>
	<content:encoded><![CDATA[
			<font color="#333333">偶然在網路上看到介紹的文章：<font color="#999999"><a href="http://www.neo.com.tw/archives/000896.html" target="_blank">免費好用的 PDF Library 大蒐集</a></font>。原本是想用來寫一個套印的小程式的，不過沒想到這玩意兒這麼難搞；因為中文編碼的關係。何況已經有人寫出類似的程式囉：<font color="#999999"><a href="http://www.blueshop.com.tw/board/show.asp?subcde=BRD20071021180930PXQ&amp;fumcde=FUM20041006152627A9N&amp;rplcnt=10" target="_blank">藍色小舖PHP -&gt; FPDF</a></font>。還是稍微記錄一下使用的過程吧！<br /><br />說到pdf檔產生，網路上似乎一面倒的推薦<font color="#999999"><a href="http://www.fpdf.org/" target="_blank">FPDF</a></font>，其他pdf產生的class也幾乎是在它的基礎下衍生出來的～算是元老級的pdf class！另外對於中文的支援有提供</font><font color="#333333"><font color="#999999"><a href="http://www.fpdf.org/download/chinese.zip">chinese.zip</a></font>、以及支援中文Unicode的</font><font color="#333333"><font color="#999999"><a href="https://www.eejj.net/fpdf/chinese-unicode.zip">chinese-unicode.zip</a></font>；目前我試用</font><font color="#333333">中文Unicode的FPDF可以完整呈現！（未使用</font><font color="#333333">Unicode的</font><font color="#333333">FPDF不知道為什麼我的FoxitReader一片空白...</font><font color="#333333">）以下是範例的程式碼：<br /><br />&lt;?php<br />require('fpdf/chinese-unicode.php');&nbsp; //include必要程式<br /><br />$pdf=new PDF_Unicode();&nbsp; //</font><font color="#333333">調用PDF_Unicode class <br /><br />$pdf-&gt;Open(); <br />$pdf-&gt;AddPage(); <br />$pdf-&gt;AddUniCNShwFont('uni'); <br />$pdf-&gt;SetFont('uni','',20);<br />&nbsp;<br />$pdf-&gt;Write(10, &quot;1234abcd學生名字\n伃綉堃亘&quot;);<br />$pdf-&gt;Ln();<br />$pdf-&gt;MultiCell (120, 10, &quot;服\n務\n單\n位&quot;);<br />$pdf-&gt;Cell (240, 10, &quot;本文用UTF8做為中文字編碼, 在這裡還是呼叫同樣的FPDF函數&quot;);<br />$pdf-&gt;Ln();<br /><br />$pdf-&gt;Output();<br />?&gt;<br /><br />我另外還試過<font color="#999999"><a href="http://www.tecnick.com/public/code/cp_dpage.php?aiocp_dp=tcpdf" target="_blank">TCPDF</a></font>，號稱支援Unicode，日文、德文、阿拉伯文洋洋灑灑的列了十幾種...只可惜獨漏中文（繁/簡體）～而且它所謂支援</font><font color="#333333">Unicode的方法，是直接將字型檔壓縮在pdf檔中，所以會造成</font><font color="#333333">pdf檔的異常肥大；實在不是一種很優的方式。</font>
		
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/taikobo0/archives/5649981.html</link>
	<guid>http://blog.roodo.com/taikobo0/archives/5649981.html</guid>
	<category>PHP</category>
	<pubDate>Thu, 06 Mar 2008 15:16:25 +0800</pubDate>
</item>
<item>
	<title> [PHP] Excel檔案轉出的方式</title>
	<description><![CDATA[
			轉入之後當然接下來的就是轉出囉！我原本採用的轉出方法是非常陽春的斷欄「\t」與斷行「\n」的應用，所以在使用M$ Excel 2007時總是會出現錯誤訊息提示。與轉入的方式比較起來，Excel檔案轉出的方式似乎比較多：PHP導入導出Excel方法小結。裡面共介紹６種方式～不巧在下小弟我因為儲存格格式的問題，幾乎把所有方法都試過一遍了...下面來分別介紹使用方式與心得吧！１、PHPExcel：PHPExcel，一個最好的控制excel的類非常可惜的這是我能找到介紹最完整的網路說明～這套class是屬於非常新的一個class，所以關於用法網路上並沒有介紹的很詳細；官方網站裡的說明文件也非常陽春...雖然功能強大，而且通吃M$ Excel 2007及其以下的各版本，文章裡大力推薦，但是因為說明文件資料不足、網上範例太少、寫入時採用英文字母，很難用迴圈跑出來（汗）、儲存格格式無法設定...等原因，最後放棄這一個方法。/*PHPExcel使用*/error_reporting(E_ALL);&nbsp; //開啟錯誤顯示（？）set_include_path(get_include_path() . PATH_SEPARATOR . '../Excel/');&nbsp; //設定class路徑include 'PHPExcel.php';&nbsp; //include必要程式include 'PHPExcel/Writer/Excel5.php';&nbsp; //使用Excel 2003以下的版本$objPHPExcel = new PHPExcel();&nbsp; //調用PHPExcel class$objWriter = new PHPExcel_Writer_Excel5($objPHPExcel);&nbsp; //調用Excel 2003以下的版本$objPHPExcel-&gt;setActiveSheetIndex(0);&nbsp; //設定動作Sheet &nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $objPHPExcel-&gt;getActiveSheet()-&gt;setCellValue('A1', '日期');&nbsp; //指定A1儲存格內容$objPHPExcel-&gt;getActiveSheet()-&gt;setCellValue('B1', '姓名');&nbsp; //指定B1儲存格內容$objPHPExcel-&gt;getActiveSheet()-&gt;setCellValue('C1', '上班時數');&nbsp; //指定C1儲存格內容$objPHPExcel-&gt;getActiveSheet()-&gt;setCellValue('D1', '加班時數');&nbsp; //指定D1儲存格內容$objPHPExcel-&gt;getActiveSheet()-&gt;setCellValue('E1', '工程案號');&nbsp; //指定E1儲存格內容&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $objPHPExcel-&gt;getActiveSheet()-&gt;setTitle('Simple');&nbsp; //指定Sheet名稱$objWriter-&gt;save('error_log.xls');&nbsp; //另存Excel檔案最後儲存的檔案會再放置網頁的資料夾中，如果要讓使用者另存下載，就必須加上header。２、pear的Spreadsheet_Excel_Writer：關於PEAR類庫中用於操作EXCEL的類庫Spreadsheet_Excel_Writer這算是一種歷史悠久的方法，運用PHP非常強大的函式庫pear；關於pear我其實一直不是很了解，這次剛好藉由這次機會接觸。首先是pear的安裝，實際跑過一遍以後才發現原來安裝這麼容易：直接執行PHP目錄下的「go-pear.bat」，安裝過程一直按「Enter」就OK了！安裝完成以後，PHP目錄下PEAR的目錄裡面就會有資料了，此時pear就算安裝完成啦！接下來是Spreadsheet_Excel_Writer的安裝；在命令提示字元下執行： pear install OLE-0.5 pear install Spreadsheet_Excel_Writer-0.9.1pear就會自動上網下載與安裝！感覺好linux唷～安裝也變得非常容易。全部安裝完成以後，只剩下要注意pear在PHP裡的path路徑是否正確，就可以直接include進來囉！使用Spreadsheet_Excel_Writer唯一比較麻煩的是必須先安裝pear及其函式庫，使用上非常便利。原本是我心目中的第一首選！不過不知道為什麼，我們公司的伺服器pear裝不起來，試了好久都不行；雖然網路上說可以直接COPY pear整個資料夾再設定path，不過因為怕不正確安裝會導致不可預期的後果，且儲存格格式也是無法設定；所以放棄此一方法。/*PEAR的Spreadsheet_Excel_Writer*/require_once 'Spreadsheet/Excel/Writer.php';&nbsp; //require必要程式&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $workbook = new Spreadsheet_Excel_Writer();&nbsp; //調用Spreadsheet_Excel_Writer class$workbook-&gt;setVersion(8);&nbsp; //設定Excel版本為XP以上$worksheet =&amp; $workbook-&gt;addWorksheet('Sheet1');&nbsp; //增加一個Sheet$worksheet-&gt;setInputEncoding('utf-8');&nbsp; //設定編碼為UTF&nbsp;&nbsp;&nbsp; $format_locked =&amp; $workbook-&gt;addFormat();$format_locked -&gt; setLocked();&nbsp; //設定鎖定格式，防止別人修改//$worksheet-&gt;setColumn(0,255,8.38,$format_locked);&nbsp; //此為指定整個工作表鎖定狀態&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; $worksheet-&gt;writeString(0, 0, '日期');&nbsp; //設定(0,0)儲存格內容$worksheet-&gt;writeString(0, 1, '姓名');&nbsp; //設定(0,1)儲存格內容$worksheet-&gt;writeString(0, 2, '上班時數');&nbsp; //設定(0,2)儲存格內容$worksheet-&gt;writeString(0, 3, '加班時數');&nbsp; //設定(0,3)儲存格內容$worksheet-&gt;writeString(0, 4, '工程案號');&nbsp; //設定(0,4)儲存格內容//錯誤資料寫入Excel &nbsp;&nbsp; &nbsp;&nbsp;  for ($i = 1;$i &lt;= $error_row;$i++){&nbsp;&nbsp;&nbsp; for ($j = 1;$j &lt;= 5;$j++){&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $worksheet-&gt;write($i, $j-1, $error_msg[$i][$j]);&nbsp;&nbsp;&nbsp; }}$workbook-&gt;send('error_log.xls');&nbsp; //另存下載Excel檔案 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  $workbook-&gt;close();&nbsp; //關閉（？）３、XML轉出：使用 PHP 輸出帶格式的 Excel 文件話說M$ Excel從2003開始，導入了對XML檔案的支援，終於冥頑不靈的M$也向開放性格事低頭了呢！只要由PHP輸出正確的XML格式，再另存成xls檔就可以餵給Excel讀了吧...本來是這樣想的...沒想到我用的M$ Excel 2007在另存成XML檔時好像還得經過些設定；我整個不知道要怎麼做啊！在不確定因素及設定太過複雜的情況下，我放棄了這個方法～（其實也是懶得弄一些有的沒的啦...）４、利用pack()函數將資料包裝使其接近Excel格式：這段操作excel的代碼應該怎麼操作設置每列的寬度如同標題說，就是利用pack()函數將資料包裝使其接近Excel格式。Excel的格式是M$自定的一種資料格式，這個方法是利用PHP的pack()函數，把我們所需的資料包裝成接近Excel原始格式的一種方法；其實說穿了不過就是把「\t」「\n」替換掉的另一種陽春的方法。不過這種方是因為接近Excel原始格式，所以在開啟的時候並不會有錯誤訊息提示，算是一種簡單易懂又最貼近Excel格式的方法。文章裡也推薦這個方法，所以最後我採用了這個方式～雖然它仍然無法設定儲存格格式...（汗）/*利用pack()函數將資料包裝使其接近Excel格式*/$filename = 'error_log.xls';&nbsp; //設定另存下載檔案名稱&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; header ('Content-type: application/x-msexcel');&nbsp; //送出headerheader (&quot;Content-Disposition: attachment; filename={$filename}&quot; );&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; xlsBOF();&nbsp; //起始包裝函數//標題列xlsWriteLabel(0, 0, u2b('日期'));&nbsp; //設定(0,0)儲存格內容，儲存格內容為文字xlsWriteLabel(0, 1, u2b('姓名'));&nbsp; //設定(0,1)儲存格內容，儲存格內容為文字xlsWriteLabel(0, 2, u2b('上班時數'));&nbsp; //設定(0,2)儲存格內容，儲存格內容為文字xlsWriteLabel(0, 3, u2b('加班時數'));&nbsp; //設定(0,3)儲存格內容，儲存格內容為文字xlsWriteLabel(0, 4, u2b('工程案號'));&nbsp; //設定(0,4)儲存格內容，儲存格內容為文字//錯誤列&nbsp; for ($i = 0;$i &lt; $error_row;$i++){&nbsp;&nbsp;&nbsp; xlsWriteLabel($i + 1, 0, $error_msg[$i][0]);&nbsp; //設定($i + 1,0)儲存格內容，儲存格內容為文字&nbsp;&nbsp;&nbsp; xlsWriteLabel($i + 1, 1, $error_msg[$i][1]);&nbsp; //設定($i + 1,1)儲存格內容，儲存格內容為文字&nbsp;&nbsp;&nbsp; xlsWriteNumber($i + 1, 2, $error_msg[$i][2]);&nbsp; //設定($i + 1,2)儲存格內容，儲存格內容為數字&nbsp;&nbsp;&nbsp; xlsWriteNumber($i + 1, 3, $error_msg[$i][3]);&nbsp; //設定($i + 1,3)儲存格內容，儲存格內容為數字&nbsp;&nbsp;&nbsp; xlsWriteLabel($i + 1, 4, $error_msg[$i][4]);&nbsp; //設定($i + 1,4)儲存格內容，儲存格內容為文字}xlsEOF();&nbsp; //結束包裝函數//Excel生成用函數，起始包裝function xlsBOF() {&nbsp;&nbsp;&nbsp; echo pack(&quot;ssssss&quot;, 0x809, 0x8, 0x0, 0x10, 0x0, 0x0);&nbsp; &nbsp;&nbsp;&nbsp; return;}//Excel生成用函數，結束包裝function xlsEOF() {&nbsp;&nbsp;&nbsp; echo pack(&quot;ss&quot;, 0x0A, 0x00);&nbsp;&nbsp;&nbsp; return;}//Excel生成用函數，數字包裝用function xlsWriteNumber($Row, $Col, $Value) {&nbsp;&nbsp;&nbsp; echo pack(&quot;sssss&quot;, 0x203, 14, $Row, $Col, 0x0);&nbsp;&nbsp;&nbsp; echo pack(&quot;d&quot;, $Value);&nbsp;&nbsp;&nbsp; return;}//Excel生成用函數，文字包裝用function xlsWriteLabel($Row, $Col, $Value ) {&nbsp;&nbsp;&nbsp; $L = strlen($Value);&nbsp;&nbsp;&nbsp; echo pack(&quot;ssssss&quot;, 0x204, 8 + $L, $Row, $Col, 0x0, $L);&nbsp;&nbsp;&nbsp; echo $Value;&nbsp;&nbsp;&nbsp; return;}５、使用「\t」、「\n」的方法：這就是我原來使用的方法，雖然簡單易懂易用，但是因為用M$ Excel 2007開啟時總是會出現錯誤訊息提示～所以才換掉。順便一提，它也沒辦法設定儲存格格式。/*最原始的\t\n用法*/$filename = 'error_log.xls';&nbsp; //設定另存下載檔案名稱&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; header(&quot;Content-Type: application/vnd.ms-excel&quot;);&nbsp; //送出header，這我是直接從網路上抄來的header(&quot;Content-Disposition:filename=sub.xls&quot;);header(&quot;Content-Disposition: attachment; filename={$filename}&quot;);header(&quot;Pragma: no-cache&quot;);header(&quot;Expires: 0&quot;);&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $error = '';&nbsp; //起始錯誤字串的值// &nbsp;&nbsp; &nbsp;&nbsp;  for ($i = 1;$i &lt;= $error_row;$i++){&nbsp;&nbsp;&nbsp; for ($j = 1;$j &lt;= 5;$j++){&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $error .= $error_msg[$i][$j].&quot;\t&quot;;&nbsp; //跨欄&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; $error .= &quot;\n&quot;;&nbsp; //斷行}echo $error;&nbsp; //印出完整錯誤字串６、使用com()函數：這個方式應該是設定功能最完整個方法！因為它是直接調用Server端的M$ Excel來產生檔案的，關於這個方法我沒有實際研究。因為這個方法有限制：它只適用在Server為M$ Windows作業系統平台，且必須安裝M$ Office才能用；也就是說，如果作業平台是Linux，或是沒有安裝M$ Office就不能用。非常剛好的，我們公司的Server雖然是M$ Windows作業系統平台，卻沒有安裝M$ Office...想當然爾我就放棄這個方法啦！不過這或許是唯一一個可以設定儲存格格式的方法...很難想像為了儲存格格式，我把網路上傳授的６種方法幾乎都試過了...雖然最後仍然沒有解決我的問題，不過因此而認識到PHP的無限可能～也學到不少東西哩！最後我對日期的處理方式，是消極的用錯誤訊息防止使用者匯入錯誤格式；這也不失為解決問題的其中一個方法啦！^^
		]]>
	</description>
	<content:encoded><![CDATA[
			轉入之後當然接下來的就是轉出囉！我原本採用的轉出方法是非常陽春的斷欄「\t」與斷行「\n」的應用，所以在使用M$ Excel 2007時總是會出現錯誤訊息提示。與轉入的方式比較起來，Excel檔案轉出的方式似乎比較多：<a href="http://unix-cd.com/vc/www/40/2007-12/10408.html" target="_blank">PHP導入導出Excel方法小結</a>。裡面共介紹６種方式～不巧在下小弟我因為儲存格格式的問題，幾乎把所有方法都試過一遍了...下面來分別介紹使用方式與心得吧！<br /><br />１、PHPExcel：<a href="http://www.arsison.com/warran/?p=10" target="_blank">PHPExcel，一個最好的控制excel的類</a><br /><br />非常可惜的這是我能找到介紹最完整的網路說明～這套class是屬於非常新的一個class，所以關於用法網路上並沒有介紹的很詳細；<a href="http://www.codeplex.com/PHPExcel" target="_blank">官方網站</a>裡的說明文件也非常陽春...雖然功能強大，而且通吃M$ Excel 2007及其以下的各版本，文章裡大力推薦，但是因為說明文件資料不足、網上範例太少、寫入時採用英文字母，很難用迴圈跑出來（汗）、儲存格格式無法設定...等原因，最後放棄這一個方法。<br /><br />/*PHPExcel使用*/<br />error_reporting(E_ALL);&nbsp; //開啟錯誤顯示（？）<br />set_include_path(get_include_path() . PATH_SEPARATOR . '../Excel/');&nbsp; //設定class路徑<br />include 'PHPExcel.php';&nbsp; //include必要程式<br />include 'PHPExcel/Writer/Excel5.php';&nbsp; //使用Excel 2003以下的版本<br /><br />$objPHPExcel = new PHPExcel();&nbsp; //調用PHPExcel class<br />$objWriter = new PHPExcel_Writer_Excel5($objPHPExcel);&nbsp; //調用Excel 2003以下的版本<br />$objPHPExcel-&gt;setActiveSheetIndex(0);&nbsp; //設定動作Sheet &nbsp;&nbsp; &nbsp;&nbsp;  <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />$objPHPExcel-&gt;getActiveSheet()-&gt;setCellValue('A1', '日期');&nbsp; //指定A1儲存格內容<br />$objPHPExcel-&gt;getActiveSheet()-&gt;setCellValue('B1', '姓名');&nbsp; //指定B1儲存格內容<br />$objPHPExcel-&gt;getActiveSheet()-&gt;setCellValue('C1', '上班時數');&nbsp; //指定C1儲存格內容<br />$objPHPExcel-&gt;getActiveSheet()-&gt;setCellValue('D1', '加班時數');&nbsp; //指定D1儲存格內容<br />$objPHPExcel-&gt;getActiveSheet()-&gt;setCellValue('E1', '工程案號');&nbsp; //指定E1儲存格內容<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />$objPHPExcel-&gt;getActiveSheet()-&gt;setTitle('Simple');&nbsp; //指定Sheet名稱<br />$objWriter-&gt;save('error_log.xls');&nbsp; //另存Excel檔案<br /><br />最後儲存的檔案會再放置網頁的資料夾中，如果要讓使用者另存下載，就必須加上header。<br /><br />２、pear的Spreadsheet_Excel_Writer：<a href="http://bbs.phpeye.com/redirect.php?tid=52&amp;goto=lastpost" target="_blank">關於PEAR類庫中用於操作EXCEL的類庫Spreadsheet_Excel_Writer</a><br /><br />這算是一種歷史悠久的方法，運用PHP非常強大的函式庫pear；關於pear我其實一直不是很了解，這次剛好藉由這次機會接觸。首先是<a href="http://www.qwe.idv.tw/discuz/viewthread.php?tid=1817&amp;extra=page%3D1" target="_blank">pear的安裝</a>，實際跑過一遍以後才發現原來安裝這麼容易：直接執行PHP目錄下的「go-pear.bat」，安裝過程一直按「Enter」就OK了！安裝完成以後，PHP目錄下PEAR的目錄裡面就會有資料了，此時pear就算安裝完成啦！接下來是<a href="http://pear.php.net/manual/en/package.fileformats.spreadsheet-excel-writer.php" target="_blank">Spreadsheet_Excel_Writer</a>的安裝；在命令提示字元下執行：<br /><br /> pear install OLE-0.5<br /> pear install Spreadsheet_Excel_Writer-0.9.1<br /><br />pear就會自動上網下載與安裝！感覺好linux唷～安裝也變得非常容易。全部安裝完成以後，只剩下要注意pear在PHP裡的path路徑是否正確，就可以直接include進來囉！使用Spreadsheet_Excel_Writer唯一比較麻煩的是必須先安裝pear及其函式庫，使用上非常便利。原本是我心目中的第一首選！不過不知道為什麼，我們公司的伺服器pear裝不起來，試了好久都不行；雖然網路上說可以直接COPY pear整個資料夾再設定path，不過因為怕不正確安裝會導致不可預期的後果，且儲存格格式也是無法設定；所以放棄此一方法。<br /><br />/*PEAR的Spreadsheet_Excel_Writer*/<br />require_once 'Spreadsheet/Excel/Writer.php';&nbsp; //require必要程式<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />$workbook = new Spreadsheet_Excel_Writer();&nbsp; //調用Spreadsheet_Excel_Writer class<br />$workbook-&gt;setVersion(8);&nbsp; //設定Excel版本為XP以上<br />$worksheet =&amp; $workbook-&gt;addWorksheet('Sheet1');&nbsp; //增加一個Sheet<br />$worksheet-&gt;setInputEncoding('utf-8');&nbsp; //設定編碼為UTF&nbsp;&nbsp;&nbsp; <br />$format_locked =&amp; $workbook-&gt;addFormat();<br />$format_locked -&gt; setLocked();&nbsp; //設定鎖定格式，防止別人修改<br />//$worksheet-&gt;setColumn(0,255,8.38,$format_locked);&nbsp; //此為指定整個工作表鎖定狀態&nbsp; <br />&nbsp; &nbsp;&nbsp;&nbsp; <br />$worksheet-&gt;writeString(0, 0, '日期');&nbsp; //設定(0,0)儲存格內容<br />$worksheet-&gt;writeString(0, 1, '姓名');&nbsp; //設定(0,1)儲存格內容<br />$worksheet-&gt;writeString(0, 2, '上班時數');&nbsp; //設定(0,2)儲存格內容<br />$worksheet-&gt;writeString(0, 3, '加班時數');&nbsp; //設定(0,3)儲存格內容<br />$worksheet-&gt;writeString(0, 4, '工程案號');&nbsp; //設定(0,4)儲存格內容<br /><br />//錯誤資料寫入Excel &nbsp;&nbsp; &nbsp;&nbsp;  <br />for ($i = 1;$i &lt;= $error_row;$i++){<br />&nbsp;&nbsp;&nbsp; for ($j = 1;$j &lt;= 5;$j++){<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $worksheet-&gt;write($i, $j-1, $error_msg[$i][$j]);<br />&nbsp;&nbsp;&nbsp; }<br />}<br /><br />$workbook-&gt;send('error_log.xls');&nbsp; //另存下載Excel檔案 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  <br />$workbook-&gt;close();&nbsp; //關閉（？）<br /><br />３、XML轉出：<a href="http://bbs.chinaunix.net/viewthread.php?tid=745757" target="_blank">使用 PHP 輸出帶格式的 Excel 文件<br /></a><br />話說M$ Excel從2003開始，導入了對XML檔案的支援，終於冥頑不靈的M$也向開放性格事低頭了呢！只要由PHP輸出正確的XML格式，再另存成xls檔就可以餵給Excel讀了吧...本來是這樣想的...沒想到我用的M$ Excel 2007在另存成XML檔時好像還得經過些設定；我整個不知道要怎麼做啊！在不確定因素及設定太過複雜的情況下，我放棄了這個方法～（其實也是懶得弄一些有的沒的啦...）<br /><br />４、利用pack()函數將資料包裝使其接近Excel格式：<a href="http://bbs.chinaunix.net/thread-923604-1-1.html" target="_blank">這段操作excel的代碼應該怎麼操作設置每列的寬度</a><br /><br />如同標題說，就是利用pack()函數將資料包裝使其接近Excel格式。Excel的格式是M$自定的一種資料格式，這個方法是利用PHP的pack()函數，把我們所需的資料包裝成接近Excel原始格式的一種方法；其實說穿了不過就是把「\t」「\n」替換掉的另一種陽春的方法。不過這種方是因為接近Excel原始格式，所以在開啟的時候並不會有錯誤訊息提示，算是一種簡單易懂又最貼近Excel格式的方法。文章裡也推薦這個方法，所以最後我採用了這個方式～雖然它仍然無法設定儲存格格式...（汗）<br /><br />/*利用pack()函數將資料包裝使其接近Excel格式*/<br />$filename = 'error_log.xls';&nbsp; //設定另存下載檔案名稱<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />header ('Content-type: application/x-msexcel');&nbsp; //送出header<br />header (&quot;Content-Disposition: attachment; filename={$filename}&quot; );<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />xlsBOF();&nbsp; //起始包裝函數<br />//標題列<br />xlsWriteLabel(0, 0, u2b('日期'));&nbsp; //設定(0,0)儲存格內容，儲存格內容為文字<br />xlsWriteLabel(0, 1, u2b('姓名'));&nbsp; //設定(0,1)儲存格內容，儲存格內容為文字<br />xlsWriteLabel(0, 2, u2b('上班時數'));&nbsp; //設定(0,2)儲存格內容，儲存格內容為文字<br />xlsWriteLabel(0, 3, u2b('加班時數'));&nbsp; //設定(0,3)儲存格內容，儲存格內容為文字<br />xlsWriteLabel(0, 4, u2b('工程案號'));&nbsp; //設定(0,4)儲存格內容，儲存格內容為文字<br />//錯誤列&nbsp; <br />for ($i = 0;$i &lt; $error_row;$i++){<br />&nbsp;&nbsp;&nbsp; xlsWriteLabel($i + 1, 0, $error_msg[$i][0]);&nbsp; //設定($i + 1,0)儲存格內容，儲存格內容為文字<br />&nbsp;&nbsp;&nbsp; xlsWriteLabel($i + 1, 1, $error_msg[$i][1]);&nbsp; //設定($i + 1,1)儲存格內容，儲存格內容為文字<br />&nbsp;&nbsp;&nbsp; xlsWriteNumber($i + 1, 2, $error_msg[$i][2]);&nbsp; //設定($i + 1,2)儲存格內容，儲存格內容為數字<br />&nbsp;&nbsp;&nbsp; xlsWriteNumber($i + 1, 3, $error_msg[$i][3]);&nbsp; //設定($i + 1,3)儲存格內容，儲存格內容為數字<br />&nbsp;&nbsp;&nbsp; xlsWriteLabel($i + 1, 4, $error_msg[$i][4]);&nbsp; //設定($i + 1,4)儲存格內容，儲存格內容為文字<br />}<br />xlsEOF();&nbsp; //結束包裝函數<br /><br />//Excel生成用函數，起始包裝<br />function xlsBOF() {<br />&nbsp;&nbsp;&nbsp; echo pack(&quot;ssssss&quot;, 0x809, 0x8, 0x0, 0x10, 0x0, 0x0);&nbsp; <br />&nbsp;&nbsp;&nbsp; return;<br />}<br />//Excel生成用函數，結束包裝<br />function xlsEOF() {<br />&nbsp;&nbsp;&nbsp; echo pack(&quot;ss&quot;, 0x0A, 0x00);<br />&nbsp;&nbsp;&nbsp; return;<br />}<br />//Excel生成用函數，數字包裝用<br />function xlsWriteNumber($Row, $Col, $Value) {<br />&nbsp;&nbsp;&nbsp; echo pack(&quot;sssss&quot;, 0x203, 14, $Row, $Col, 0x0);<br />&nbsp;&nbsp;&nbsp; echo pack(&quot;d&quot;, $Value);<br />&nbsp;&nbsp;&nbsp; return;<br />}<br />//Excel生成用函數，文字包裝用<br />function xlsWriteLabel($Row, $Col, $Value ) {<br />&nbsp;&nbsp;&nbsp; $L = strlen($Value);<br />&nbsp;&nbsp;&nbsp; echo pack(&quot;ssssss&quot;, 0x204, 8 + $L, $Row, $Col, 0x0, $L);<br />&nbsp;&nbsp;&nbsp; echo $Value;<br />&nbsp;&nbsp;&nbsp; return;<br />}<br /><br />５、使用「\t」、「\n」的方法：<br /><br />這就是我原來使用的方法，雖然簡單易懂易用，但是因為用M$ Excel 2007開啟時總是會出現錯誤訊息提示～所以才換掉。順便一提，它也沒辦法設定儲存格格式。<br /><br />/*最原始的\t\n用法*/<br />$filename = 'error_log.xls';&nbsp; //設定另存下載檔案名稱<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />header(&quot;Content-Type: application/vnd.ms-excel&quot;);&nbsp; //送出header，這我是直接從網路上抄來的<br />header(&quot;Content-Disposition:filename=sub.xls&quot;);<br />header(&quot;Content-Disposition: attachment; filename={$filename}&quot;);<br />header(&quot;Pragma: no-cache&quot;);<br />header(&quot;Expires: 0&quot;);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />$error = '';&nbsp; //起始錯誤字串的值<br />// &nbsp;&nbsp; &nbsp;&nbsp;  <br />for ($i = 1;$i &lt;= $error_row;$i++){<br />&nbsp;&nbsp;&nbsp; for ($j = 1;$j &lt;= 5;$j++){<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $error .= $error_msg[$i][$j].&quot;\t&quot;;&nbsp; //跨欄<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; $error .= &quot;\n&quot;;&nbsp; //斷行<br />}<br />echo $error;&nbsp; //印出完整錯誤字串<br /><br />６、使用com()函數：<br /><br />這個方式應該是設定功能最完整個方法！因為它是直接調用Server端的M$ Excel來產生檔案的，關於這個方法我沒有實際研究。因為這個方法有限制：它只適用在Server為M$ Windows作業系統平台，且必須安裝M$ Office才能用；也就是說，如果作業平台是Linux，或是沒有安裝M$ Office就不能用。非常剛好的，我們公司的Server雖然是M$ Windows作業系統平台，卻沒有安裝M$ Office...想當然爾我就放棄這個方法啦！不過這或許是唯一一個可以設定儲存格格式的方法...<br /><br />很難想像為了儲存格格式，我把網路上傳授的６種方法幾乎都試過了...雖然最後仍然沒有解決我的問題，不過因此而認識到PHP的無限可能～也學到不少東西哩！最後我對日期的處理方式，是消極的用錯誤訊息防止使用者匯入錯誤格式；這也不失為解決問題的其中一個方法啦！^^
		
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/taikobo0/archives/5625521.html</link>
	<guid>http://blog.roodo.com/taikobo0/archives/5625521.html</guid>
	<category>PHP</category>
	<pubDate>Mon, 03 Mar 2008 08:35:44 +0800</pubDate>
</item>
<item>
	<title>[PHP] Excel檔案轉入的方式</title>
	<description><![CDATA[
			依然是專案管理系統的功能。因為之前Excel檔案的匯入是採用另存新檔後的csv匯入；因為以PHP來說，xls的Excel檔內含太多不可確定的格式，不如單純的逗號分隔檔案csv的資料來的純粹。不過站在使用者的角度，「另存新檔」本身就是一個多餘的動作，何況再轉存成csv檔後並不是直接按確定這麼簡單；因為Excel檔案格式的改變，所以會有M$貼心的提醒...總之最後導致整個匯入動作感覺很不友善。儘管PTT PHP版一面倒的建議採用csv檔作資料的讀入處理，但是使用者才不管你這麼多勒！對使用者友善，就是對程式設計者的殘忍啊...然而，之所以會需要程式設計者，也是為了要對使用者更友善啊～所以，我找了一下網路上直接上傳Excel檔轉入資料的方法，目前找到二種試驗後都成功的方法：第一種是利用PHP的COM()函數，呼叫PHP所在Server的M$ Office程式做處理。這個函數運用的感覺比較像是在寫bat檔，利用一連串指令在使用者不知情的狀況下完成想要達到的目的；當然，缺點就是這種方式只適用在M$ Windows的作業系統，而且Server上還必須要有M$ Office...雖然說是直接上傳Excel檔轉入資料，但說穿了不過是利用COM()函數在使用者不知情的情況下另存成csv檔後，再作處理。以下是利用COM()函數另存新檔的程式碼：$excel = new COM(&quot;excel.application&quot;) or die(&quot;Unable to instanciate excel&quot;);&nbsp; //調用COM class，順便判斷是否能正常連結Excel應用程式$excel-&gt;DisplayAlerts = 0;&nbsp; //關閉開啟Excel時的警告$strTemp = 'C:\\xxx\\xxx\\xxx\\csv\\'.$file_name;&nbsp; //上傳成功檔案的絕對路徑$excel-&gt;Workbooks-&gt;Open($strTemp);&nbsp; //打開該檔案$csvfile_name = substr($file_name, 0,strlen($file_name)-4).'.csv';&nbsp; //利用原檔名將副檔名改寫成csv$strTemp = 'C:\\xxx\\xxx\\xxx\\csv\\'.$csvfile_name;&nbsp; //另存成csv檔後的絕對路徑$excel-&gt;ActiveWorkbook-&gt;SaveAs($strTemp ,6);&nbsp; //另存新檔，6代表csv逗號分隔檔案 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;$excel-&gt;Quit();&nbsp; //退出Excel//$excel-&gt;Release();&nbsp; //釋放Excel所佔用的記憶體...吧？不過我的電腦必須註解掉這行才能動作，不知道為什麼$excel = null;&nbsp; //釋放Excel所佔用的記憶體...吧？其實我不太知道這跟上面有什麼不同下來就是利用另存的csv檔對資料做處理囉！基本上作法沒有變，只是使用者可以省略自己另存的動作，而由Server代替轉存，使用者自然會覺得方便許多。可惜本公司的Server雖然是M$ Windows系統，但是並沒有安裝M$ Office；所以只能用第二種方法囉。第二種方法是偉大的前輩事先做好的class：PHP-ExcelReader。PHP真不愧為網路程式設計的龍頭，許多功能其實前輩們都已經想好了！其實主要用的的檔案也只有二個：oleread.inc跟reader.php。而且因為已經封裝成class，使用方面也非常的簡單，以下式簡單的程式碼：require_once '../Excel/reader.php';$data = new Spreadsheet_Excel_Reader();&nbsp; //調用Spreadsheet_Excel_Reader class$data-&gt;setOutputEncoding('utf-8');&nbsp; //設定輸出的編碼，可直接選擇輸出為UTF8編碼$data-&gt;read(&quot;../xxx/xxx/test.xls&quot;);&nbsp; //檔案的路徑（可使用相對路徑）error_reporting(E_ALL ^ E_NOTICE);&nbsp; //錯誤顯示for ($i = 1; $i &lt;= $data-&gt;sheets[0]['numRows']; $i++) {&nbsp;&nbsp;&nbsp; for ($j = 1; $j &lt;= $data-&gt;sheets[0]['numCols']; $j++) {&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; echo &quot;\&quot;&quot;.$data-&gt;sheets[0]['cells'][$i][$j].&quot;\&quot;,&quot;;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; echo &quot;\n&quot;;}利用陣列的方式，擷取Excel檔裡面的資料；['numRows']列、['numCols']行、['cells']元素，搭配二維陣列取得。擷取出來的資料就可以直接對其作處理，非常容易使用！關於Excel檔寫入也有另一個class：Spreadsheet_Excel_Writer。這個class需要pear的支援，所以使用前必須先安裝pear；這個部份我還沒有深入研究測試，就先行打住。另外還有一個class比較新，是支援M$ Office Excel 2007的格式：PHPExcel。這個class同時支援讀入跟寫出，不過目前只針對Excel 2007的版本作處理。目前我們公司仍以2003為主，所以這個版本也沒有深究。當然2007一定是未來的趨勢，所以以後應該還是有機會會接觸到吧。
		]]>
	</description>
	<content:encoded><![CDATA[
			依然是專案管理系統的功能。因為之前Excel檔案的匯入是採用另存新檔後的csv匯入；因為以PHP來說，xls的Excel檔內含太多不可確定的格式，不如單純的逗號分隔檔案csv的資料來的純粹。不過站在使用者的角度，「另存新檔」本身就是一個多餘的動作，何況再轉存成csv檔後並不是直接按確定這麼簡單；因為Excel檔案格式的改變，所以會有M$貼心的提醒...總之最後導致整個匯入動作感覺很不友善。<br /><br />儘管PTT PHP版一面倒的建議採用csv檔作資料的讀入處理，但是使用者才不管你這麼多勒！對使用者友善，就是對程式設計者的殘忍啊...然而，之所以會需要程式設計者，也是為了要對使用者更友善啊～所以，我找了一下網路上直接上傳Excel檔轉入資料的方法，目前找到二種試驗後都成功的方法：<br /><br />第一種是利用PHP的<a href="http://tw2.php.net/manual/en/class.com.php" target="_blank">COM()函數</a>，呼叫PHP所在Server的M$ Office程式做處理。這個函數運用的感覺比較像是在寫bat檔，利用一連串指令在使用者不知情的狀況下完成想要達到的目的；當然，缺點就是這種方式只適用在M$ Windows的作業系統，而且Server上還必須要有M$ Office...<br /><br />雖然說是直接上傳Excel檔轉入資料，但說穿了不過是利用<a href="http://tw2.php.net/manual/en/class.com.php" target="_blank">COM()函數</a>在使用者不知情的情況下另存成csv檔後，再作處理。以下是利用<a href="http://tw2.php.net/manual/en/class.com.php" target="_blank">COM()函數</a>另存新檔的程式碼：<br /><br />$excel = new COM(&quot;excel.application&quot;) or die(&quot;Unable to instanciate excel&quot;);&nbsp; //調用COM class，順便判斷是否能正常連結Excel應用程式<br />$excel-&gt;DisplayAlerts = 0;&nbsp; //關閉開啟Excel時的警告<br />$strTemp = 'C:\\xxx\\xxx\\xxx\\csv\\'.$file_name;&nbsp; //上傳成功檔案的絕對路徑<br />$excel-&gt;Workbooks-&gt;Open($strTemp);&nbsp; //打開該檔案<br />$csvfile_name = substr($file_name, 0,strlen($file_name)-4).'.csv';&nbsp; //利用原檔名將副檔名改寫成csv<br />$strTemp = 'C:\\xxx\\xxx\\xxx\\csv\\'.$csvfile_name;&nbsp; //另存成csv檔後的絕對路徑<br />$excel-&gt;ActiveWorkbook-&gt;SaveAs($strTemp ,6);&nbsp; //另存新檔，6代表csv逗號分隔檔案 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />$excel-&gt;Quit();&nbsp; //退出Excel<br />//$excel-&gt;Release();&nbsp; //釋放Excel所佔用的記憶體...吧？不過我的電腦必須註解掉這行才能動作，不知道為什麼<br />$excel = null;&nbsp; //釋放Excel所佔用的記憶體...吧？其實我不太知道這跟上面有什麼不同<br /><br />下來就是利用另存的csv檔對資料做處理囉！基本上作法沒有變，只是使用者可以省略自己另存的動作，而由Server代替轉存，使用者自然會覺得方便許多。可惜本公司的Server雖然是M$ Windows系統，但是並沒有安裝M$ Office；所以只能用第二種方法囉。<br /><br />第二種方法是偉大的前輩事先做好的class：<a href="http://sourceforge.net/projects/phpexcelreader/" target="_blank">PHP-ExcelReader</a>。PHP真不愧為網路程式設計的龍頭，許多功能其實前輩們都已經想好了！其實主要用的的檔案也只有二個：oleread.inc跟reader.php。而且因為已經封裝成class，使用方面也非常的簡單，以下式簡單的程式碼：<br /><br />require_once '../Excel/reader.php';<br />$data = new Spreadsheet_Excel_Reader();&nbsp; //調用Spreadsheet_Excel_Reader class<br />$data-&gt;setOutputEncoding('utf-8');&nbsp; //設定輸出的編碼，可直接選擇輸出為UTF8編碼<br />$data-&gt;read(&quot;../xxx/xxx/test.xls&quot;);&nbsp; //檔案的路徑（可使用相對路徑）<br />error_reporting(E_ALL ^ E_NOTICE);&nbsp; //錯誤顯示<br /><br />for ($i = 1; $i &lt;= $data-&gt;sheets[0]['numRows']; $i++) {<br />&nbsp;&nbsp;&nbsp; for ($j = 1; $j &lt;= $data-&gt;sheets[0]['numCols']; $j++) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; echo &quot;\&quot;&quot;.$data-&gt;sheets[0]['cells'][$i][$j].&quot;\&quot;,&quot;;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; echo &quot;\n&quot;;<br />}<br /><br />利用陣列的方式，擷取Excel檔裡面的資料；['numRows']列、['numCols']行、['cells']元素，搭配二維陣列取得。擷取出來的資料就可以直接對其作處理，非常容易使用！<br /><br />關於Excel檔寫入也有另一個class：<a href="http://pear.php.net/package/Spreadsheet_Excel_Writer/" target="_blank">Spreadsheet_Excel_Writer</a>。這個class需要pear的支援，所以使用前必須先安裝pear；這個部份我還沒有深入研究測試，就先行打住。另外還有一個class比較新，是支援M$ Office Excel 2007的格式：<a href="http://www.codeplex.com/PHPExcel" target="_blank">PHPExcel</a>。這個class同時支援讀入跟寫出，不過目前只針對Excel 2007的版本作處理。目前我們公司仍以2003為主，所以這個版本也沒有深究。當然2007一定是未來的趨勢，所以以後應該還是有機會會接觸到吧。<br /><br />
		
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/taikobo0/archives/5597727.html</link>
	<guid>http://blog.roodo.com/taikobo0/archives/5597727.html</guid>
	<category>PHP</category>
	<pubDate>Tue, 26 Feb 2008 09:08:17 +0800</pubDate>
</item>
<item>
	<title>[PHP] 去除特殊字元：str_replace()函數運用</title>
	<description><![CDATA[
			因為公司會計部門的人還是比較喜歡（習慣）過去使用Excel編輯成本的環境，新系統上線的不習慣在無形間浪費了許多工時；所以現在專案管理系統在輸入方面將新增轉入功能。簡單說就是利用原先熟悉的Excel環境提供轉檔程式轉進資料庫中。不過這也代表著我先前做的輸入介面與自動完成完全無用武之地啊～（噗）當然已經作的介面也不需要特別去刪掉，就當作有二種輸入介面吧！因為Excel格式之複雜，導致PHP在轉檔時會發生許多不可預期的問題；所以不論是網路上或是PTT幾乎都建議改以csv檔作轉入的動作；Excel本身也有提供另存成csv檔的功能～也算是一種折衷的方案囉。之前有試寫人工成本Excel的資料轉入，昨天嘗試著修改了一下介面與原系統整合，本來以為已經沒有問題了～沒想到今天早上卻發現原始csv檔內的特殊字元ex：\t、\n、\r在作怪，導致原先的Javascript警告視窗失效。上網搜尋一下馬上就找到解決的辦法啦～網路真是大家好朋友：PHP如何取消字串裡的特殊字元呢??主要是利用str_replace()函數，運用取代函數將特殊字數取代掉；是很聰明的應用方式哩！其中以陣列方式一次取代是最方便：$str = str_replace(array(&quot;\n&quot;,&quot;\t&quot;,&quot;\r&quot;), array(&quot;&quot;,&quot;&quot;,&quot;&quot;), $str);剛好我從csv檔取得的資料也是陣列的格式，真是幫了我一個大忙哩^^
		]]>
	</description>
	<content:encoded><![CDATA[
			因為公司會計部門的人還是比較喜歡（習慣）過去使用Excel編輯成本的環境，新系統上線的不習慣在無形間浪費了許多工時；所以現在專案管理系統在輸入方面將新增轉入功能。簡單說就是利用原先熟悉的Excel環境提供轉檔程式轉進資料庫中。不過這也代表著我先前做的輸入介面與自動完成完全無用武之地啊～（噗）當然已經作的介面也不需要特別去刪掉，就當作有二種輸入介面吧！<br /><br />因為Excel格式之複雜，導致PHP在轉檔時會發生許多不可預期的問題；所以不論是網路上或是PTT幾乎都建議改以csv檔作轉入的動作；Excel本身也有提供另存成csv檔的功能～也算是一種折衷的方案囉。<br /><br />之前有試寫人工成本Excel的資料轉入，昨天嘗試著修改了一下介面與原系統整合，本來以為已經沒有問題了～沒想到今天早上卻發現原始csv檔內的特殊字元ex：\t、\n、\r在作怪，導致原先的Javascript警告視窗失效。上網搜尋一下馬上就找到解決的辦法啦～網路真是大家好朋友：<a href="http://www.php5.idv.tw/bb-5232.htm" target="_blank">PHP如何取消字串裡的特殊字元呢??</a><br /><br /><font size="3">主要是利用</font><a href="http://linux.tnc.edu.tw/techdoc/banic/string/str_replace.html" target="_blank"><font face="Times New Roman" size="3">str_replace()</font></a>函數，運用取代函數將特殊字數取代掉；是很聰明的應用方式哩！其中以陣列方式一次取代是最方便：<pre><code><br /><br />$str = str_replace(array(&quot;\n&quot;,&quot;\t&quot;,&quot;\r&quot;), array(&quot;&quot;,&quot;&quot;,&quot;&quot;), $str);<br /><br /></code></pre>剛好我從csv檔取得的資料也是陣列的格式，真是幫了我一個大忙哩^^
		
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/taikobo0/archives/5534493.html</link>
	<guid>http://blog.roodo.com/taikobo0/archives/5534493.html</guid>
	<category>PHP</category>
	<pubDate>Wed, 13 Feb 2008 09:33:57 +0800</pubDate>
</item>
<item>
	<title>[PHP] 利用GD函式庫，製作互動式圖片</title>
	<description><![CDATA[
			很久以前就有這樣的計畫，利用現有的圖片由使用者自行加註文字，然後合成為另一張新的圖片～爬了一下PTT的PHP版，很快就看到類似的東西。剛好十天的假期在家閒閒沒事，就來研究一下這玩意兒要怎麼弄吧。說到跟圖片有關的東西，就不能忘了PHP的GD函式庫啦！它強大的功能也曾經幫我在名片查詢系統時，利用PHP上傳名片圖檔的時候同步縮小圖片呢～這次運用到的函數是ImageTTFText，它可以利用自備的TrueType字體檔，寫入文字到圖形中。最近我對微軟正黑體還蠻有好感的，再加上它算是一套免費（由微軟官方釋出，不過好像是不能任意提供給人家下載啦）的字體；拿來當圖片用的字型，在適合不過啦！下面是php程式碼：header(&quot;content-type:image/jpeg&quot;);  // 送出JPG的header $nimage=imagecreatetruecolor(1024,729);  // 建立一個寬 1024 高 729 像素的圖片 $black=imagecolorallocate($nimage,0,0,0);  // 設定文字顯示RGB顏色 $simage =ImageCreateFromJPEG('card2008.jpg');  // 利用ImageCreateFromJPEG函數讀取原始圖片 imagecopy($nimage,$simage,0,0,0,0,1024,729);  // 利用imagecopy函數複製原始圖片到建立的新圖片上 $font = '/xxx/xxx/xxx.TTF';  // 字形路徑設定 ImageTTFText($nimage,26,0,60,570,$black,$font,$wish_word);  // 利用ImageTTFText函數將文字合併於圖片 ImageJPEG($nimage);  // 輸出JPEG圖片 imagedestroy($nimage); imagedestroy($simage);  //釋放之前暫存圖片的記憶體當然，重點是在ImageTTFText函數的用法：ImageTTFText($nimage,26,0,60,570,$black,$font,$wish_word);&nbsp;$nimage：新建立的圖片的變數名26：字型的大小0：字型的角度60：X座標軸位置570：Y座標軸位置$black：字型顏色$font：字體檔位置；這邊因為我架設主機的平台是linux，不知道為什麼相對位置整個沒反應。弄了好久最後用絕對位置搞定，所以要特別注意。$wish_word：輸出於圖片上的話另外因為輸出字數的問題也花了我一點時間...因為ImageTTFText不會自動幫你斷行，所以必須自己加『\n』去斷行UTF-8的編碼方式中文字是3個字元，解決方法就是自己算字數然後加『\n』：if(strlen($wish_words) &gt; (26*3) and (strlen($wish_words) &lt; (26*3*3+1))){&nbsp;&nbsp;&nbsp;for($i=0;$i&lt;floor(strlen($wish_words)/78);$i++){&nbsp;&nbsp;&nbsp;&nbsp;$wish_word .= substr($wish_words,($i*78),78).&quot;\n&quot;;&nbsp;&nbsp;&nbsp;}}我設定在字數多於26個字時斷行其中floor()函數是取小數點後無條件捨去的正整數，另一個ceil()函數則是無條件進位後的正整數這裡我使用floor()函數substr()函數擷取我要的字段後在自己加『\n』斷行其實我來以為這只是一個很簡單的GD函數運用，可是因為字型檔路徑跟編碼問題還是讓我花了不少時間成功了以後又覺得怎麼那麼簡單？所以雖然函數就在那，但還是要用過才知道用法，才知道會碰到什麼問題，要怎麼解決！因為從前年開始，我每年都會為PTT的資科系版畫新年賀圖今年就想利用這個賀圖結合一些祝福的話，在除夕夜的簡訊中連同網址一起發出所以才會心血來潮的想做這玩意兒；本來以為簡單的東西，其實還是花了不少時間。這裡是成果，祝大家新年快樂^^
		]]>
	</description>
	<content:encoded><![CDATA[
			很久以前就有這樣的計畫，利用現有的圖片由使用者自行加註文字，然後合成為另一張新的圖片～爬了一下PTT的PHP版，很快就看到類似的<a href="http://203.194.245.88/wish/wish.asp?usrName=PTT%A6n%B4%CE%A3%AB&amp;submit=%C0%F2%A8%FA%C2%E0%B5o%A6a%A7%7D" target="_blank">東西</a>。剛好十天的假期在家閒閒沒事，就來研究一下這玩意兒要怎麼弄吧。<br /><br />說到跟圖片有關的東西，就不能忘了PHP的GD函式庫啦！它強大的功能也曾經幫我在名片查詢系統時，利用PHP上傳名片圖檔的時候同步縮小圖片呢～這次運用到的函數是<font face="Times New Roman"><a href="http://linux.tnc.edu.tw/techdoc/banic/image/imagettftext.html" target="_blank">ImageTTFText</a>，它可以利用自備的TrueType字體檔，寫入文字到圖形中。最近我對微軟正黑體還蠻有好感的，再加上它算是一套免費（由微軟官方釋出，不過好像是不能任意提供給人家下載啦）的字體；拿來當圖片用的字型，在適合不過啦！<br /><br />下面是php程式碼：</font><font face="Times New Roman"><br /><br />header(&quot;content-type:image/jpeg&quot;);  // 送出JPG的header<br /> $nimage=imagecreatetruecolor(1024,729);  // 建立一個寬 1024 高 729 像素的圖片<br /> $black=imagecolorallocate($nimage,0,0,0);  // 設定文字顯示RGB顏色<br /> $simage =ImageCreateFromJPEG('card2008.jpg');  // 利用ImageCreateFromJPEG函數讀取原始圖片<br /> imagecopy($nimage,$simage,0,0,0,0,1024,729);  // 利用imagecopy函數複製原始圖片到建立的新圖片上<br /> $font = '/xxx/xxx/xxx.TTF';  // 字形路徑設定<br /> ImageTTFText($nimage,26,0,60,570,$black,$font,$wish_word);  // 利用ImageTTFText函數將文字合併於圖片<br /> ImageJPEG($nimage);  // 輸出JPEG圖片<br /> imagedestroy($nimage);<br /> imagedestroy($simage);  //釋放之前暫存圖片的記憶體</font><font face="Times New Roman"><br /><br />當然，重點是在ImageTTFText函數的用法：<br /><br />ImageTTFText($nimage,26,0,60,570,$black,$font,$wish_word);&nbsp;<br /><br />$nimage：新建立的圖片的變數名<br />26：字型的大小<br />0：字型的角度<br />60：X座標軸位置<br />570：Y座標軸位置<br />$black：字型顏色<br />$font：字體檔位置；這邊因為我架設主機的平台是linux，不知道為什麼相對位置整個沒反應。弄了好久最後用絕對位置搞定，所以要特別注意。<br />$wish_word：輸出於圖片上的話<br /><br />另外因為輸出字數的問題也花了我一點時間...<br />因為ImageTTFText不會自動幫你斷行，所以必須自己加『\n』去斷行<br />UTF-8的編碼方式中文字是3個字元，解決方法就是自己算字數然後加『\n』：<br /><br />if(strlen($wish_words) &gt; (26*3) and (strlen($wish_words) &lt; (26*3*3+1))){<br />&nbsp;&nbsp;&nbsp;for($i=0;$i&lt;floor(strlen($wish_words)/78);$i++){<br />&nbsp;&nbsp;&nbsp;&nbsp;$wish_word .= substr($wish_words,($i*78),78).&quot;\n&quot;;<br />&nbsp;&nbsp;&nbsp;}<br />}<br /><br />我設定在字數多於26個字時斷行<br />其中<a href="http://member.ettoday.com/book/function.php-Floor.htm" target="_blank">floor()</a>函數是取小數點後無條件捨去的正整數，另一個<a href="http://member.ettoday.com/book/function.php-Ceil.htm" target="_blank">ceil()</a>函數則是無條件進位後的正整數<br />這裡我使用<a href="http://member.ettoday.com/book/function.php-Floor.htm" target="_blank">floor()</a>函數<br /><a href="http://member.ettoday.com/book/function.php-substr.htm" target="_blank">substr()</a>函數擷取我要的字段後在自己加『\n』斷行<br /><br />其實我來以為這只是一個很簡單的GD函數運用，可是因為字型檔路徑跟編碼問題還是讓我花了不少時間<br />成功了以後又覺得怎麼那麼簡單？<br />所以雖然函數就在那，但還是要用過才知道用法，才知道會碰到什麼問題，要怎麼解決！<br /><br />因為從前年開始，我每年都會為PTT的資科系版畫新年賀圖<br />今年就想利用這個賀圖結合一些祝福的話，在除夕夜的簡訊中連同網址一起發出<br />所以才會心血來潮的想做這玩意兒；本來以為簡單的東西，其實還是花了不少時間。<br />這裡是<a href="http://taikobo.no-ip.org/2008/" target="_blank">成果</a>，祝大家新年快樂^^<br /></font>
		
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/taikobo0/archives/5508369.html</link>
	<guid>http://blog.roodo.com/taikobo0/archives/5508369.html</guid>
	<category>PHP</category>
	<pubDate>Wed, 06 Feb 2008 12:13:49 +0800</pubDate>
</item>
<item>
	<title>[PHP] 數字格式建立函數：number_format</title>
	<description><![CDATA[
			原來PHP有內建數字格式建立的函數啊：number_format與money_format；可以直接對數字重新格式化。當然提到格式化就不能忘了sprintf這個函數囉！考慮加入在專案管理程式的可能性...
		]]>
	</description>
	<content:encoded><![CDATA[
			原來PHP有內建數字格式建立的函數啊：<a href="http://tw.php.net/number_format" target="_blank" title="number_format">number_format</a>與<a href="http://tw.php.net/manual/en/function.money-format.php" title="money-format"><span class="methodname">money_format</span></a><span class="methodname">；可以直接對數字重新格式化。當然提到格式化就不能忘了</span><a href="http://tw.php.net/manual/en/function.sprintf.php" title="sprintf">sprintf</a>這個函數囉！考慮加入在專案管理程式的可能性...
		
		]]>
	</content:encoded>
	<link>http://blog.roodo.com/taikobo0/archives/5098281.html</link>
	<guid>http://blog.roodo.com/taikobo0/archives/5098281.html</guid>
	<category>PHP</category>
	<pubDate>Thu, 24 Jan 2008 13:22:17 +0800</pubDate>
</item>
</channel>
</rss>