偶然在網路上看到介紹的文章:免費好用的 PDF Library 大蒐集。原本是想用來寫一個套印的小程式的,不過沒想到這玩意兒這麼難搞;因為中文編碼的關係。何況已經有人寫出類似的程式囉:藍色小舖PHP -> FPDF。還是稍微記錄一下使用的過程吧!

說到pdf檔產生,網路上似乎一面倒的推薦FPDF,其他pdf產生的class也幾乎是在它的基礎下衍生出來的~算是元老級的pdf class!另外對於中文的支援有提供
chinese.zip、以及支援中文Unicode的chinese-unicode.zip;目前我試用中文Unicode的FPDF可以完整呈現!(未使用Unicode的FPDF不知道為什麼我的FoxitReader一片空白...)以下是範例的程式碼:

<?php
require('fpdf/chinese-unicode.php');  //include必要程式

$pdf=new PDF_Unicode();  //
調用PDF_Unicode class

$pdf->Open();
$pdf->AddPage();
$pdf->AddUniCNShwFont('uni');
$pdf->SetFont('uni','',20);
 
$pdf->Write(10, "1234abcd學生名字\n伃綉堃亘");
$pdf->Ln();
$pdf->MultiCell (120, 10, "服\n務\n單\n位");
$pdf->Cell (240, 10, "本文用UTF8做為中文字編碼, 在這裡還是呼叫同樣的FPDF函數");
$pdf->Ln();

$pdf->Output();
?>

我另外還試過TCPDF,號稱支援Unicode,日文、德文、阿拉伯文洋洋灑灑的列了十幾種...只可惜獨漏中文(繁/簡體)~而且它所謂支援
Unicode的方法,是直接將字型檔壓縮在pdf檔中,所以會造成pdf檔的異常肥大;實在不是一種很優的方式。
文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

正規表示式Regular Expression。它有多種翻譯名稱:正規表示法、正則表達式...等等;這裡我用ptt CompScience群組中的RegExp版中文名稱為準。它是用來描述或者匹配一系列符合某個句法規則的字元串的單個字元串;舉例來說,它經常被用來檢查E-mail或是電話之類有規則的字串,輸入的資料是否正確。以下稍微介紹一下它的部分語法:

//:正規表示式開始與結束,設定需比對的字串規則於二個「/」之中。
\d:數字;意同[0-9]。
\D:非數字;意同[^0-9]。
\s:空白。
\S:非空白。
\w:字母。
\W:非字母。
^:起始。
$:結尾。
():先運算。
|:or,或。
+:前面字元必須至少出現一次,1次或多次;意同{1,}。
?:前面字元最多只可以出現一次,0次或1次;意同{0,1}。
*:前面字元可以不出現,也可以出現一次或者多次,0次、1次或多次;意同{0,}。
.:「\n」之外的任何單個字元。
{n}:出現最少n次。
{n,}:出現最少n次。
{n,m}:出現最少n次且最多m次。

這次使用到的地方是在PHP的日期判斷上,運用到PHP上驗證正規表示式的函數preg_match();符合條件傳回true,不符合則傳回false。以下是我對日期格式YYYY-MM-DD的驗證:

<?php
    $YYYY_MM_DD = '/^(\d{2}(([02468][048])|([13579][26]))\-((((0[13578])|(1[02]))\-((0[1-9])|([1-2][0-9])|(3[01])))|(((0[469])|(11))\-((0[1-9])|([1-2][0-9])|(30)))|(02\-((0[1-9])|([1-2][0-9])))))|(\d{2}(([02468][1235679])|([13579][01345789]))\-((((0[13578])|(1[02]))\-((0[1-9])|([1-2][0-9])|(3[01])))|(((0[469])|(11))\-((0[1-9])|([1-2][0-9])|(30)))|(02\-((0[1-9])|(1[0-9])|(2[0-8])))))$/';
    $DATE = '2048-02-29';
    if (!(preg_match($YYYY_MM_DD, $DATE))){
        echo '不符合!';
    }
    else{
        echo '符合!';
    }
?>

此正規表示式除了可以判斷大小月,甚至連閏二月也能清楚辨別。其實說穿了也不過是一堆數組的比對罷了;不過看不懂的人可能覺得這是火星文吧~(話說我之前一直覺得它就像火星文...)

另外再推薦一個正規表示式的lib網站:RegExLib.com。裡面有很多正規表示式的判斷可以利用唷!
文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

轉入之後當然接下來的就是轉出囉!我原本採用的轉出方法是非常陽春的斷欄「\t」與斷行「\n」的應用,所以在使用M$ Excel 2007時總是會出現錯誤訊息提示。與轉入的方式比較起來,Excel檔案轉出的方式似乎比較多:PHP導入導出Excel方法小結。裡面共介紹6種方式~不巧在下小弟我因為儲存格格式的問題,幾乎把所有方法都試過一遍了...下面來分別介紹使用方式與心得吧!

1、PHPExcel:PHPExcel,一個最好的控制excel的類

非常可惜的這是我能找到介紹最完整的網路說明~這套class是屬於非常新的一個class,所以關於用法網路上並沒有介紹的很詳細;官方網站裡的說明文件也非常陽春...雖然功能強大,而且通吃M$ Excel 2007及其以下的各版本,文章裡大力推薦,但是因為說明文件資料不足、網上範例太少、寫入時採用英文字母,很難用迴圈跑出來(汗)、儲存格格式無法設定...等原因,最後放棄這一個方法。

/*PHPExcel使用*/
error_reporting(E_ALL);  //開啟錯誤顯示(?)
set_include_path(get_include_path() . PATH_SEPARATOR . '../Excel/');  //設定class路徑
include 'PHPExcel.php';  //include必要程式
include 'PHPExcel/Writer/Excel5.php';  //使用Excel 2003以下的版本

$objPHPExcel = new PHPExcel();  //調用PHPExcel class
$objWriter = new PHPExcel_Writer_Excel5($objPHPExcel);  //調用Excel 2003以下的版本
$objPHPExcel->setActiveSheetIndex(0);  //設定動作Sheet      
       
$objPHPExcel->getActiveSheet()->setCellValue('A1', '日期');  //指定A1儲存格內容
$objPHPExcel->getActiveSheet()->setCellValue('B1', '姓名');  //指定B1儲存格內容
$objPHPExcel->getActiveSheet()->setCellValue('C1', '上班時數');  //指定C1儲存格內容
$objPHPExcel->getActiveSheet()->setCellValue('D1', '加班時數');  //指定D1儲存格內容
$objPHPExcel->getActiveSheet()->setCellValue('E1', '工程案號');  //指定E1儲存格內容
       
$objPHPExcel->getActiveSheet()->setTitle('Simple');  //指定Sheet名稱
$objWriter->save('error_log.xls');  //另存Excel檔案

最後儲存的檔案會再放置網頁的資料夾中,如果要讓使用者另存下載,就必須加上header。

2、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.1

pear就會自動上網下載與安裝!感覺好linux唷~安裝也變得非常容易。全部安裝完成以後,只剩下要注意pear在PHP裡的path路徑是否正確,就可以直接include進來囉!使用Spreadsheet_Excel_Writer唯一比較麻煩的是必須先安裝pear及其函式庫,使用上非常便利。原本是我心目中的第一首選!不過不知道為什麼,我們公司的伺服器pear裝不起來,試了好久都不行;雖然網路上說可以直接COPY pear整個資料夾再設定path,不過因為怕不正確安裝會導致不可預期的後果,且儲存格格式也是無法設定;所以放棄此一方法。

/*PEAR的Spreadsheet_Excel_Writer*/
require_once 'Spreadsheet/Excel/Writer.php';  //require必要程式
       
$workbook = new Spreadsheet_Excel_Writer();  //調用Spreadsheet_Excel_Writer class
$workbook->setVersion(8);  //設定Excel版本為XP以上
$worksheet =& $workbook->addWorksheet('Sheet1');  //增加一個Sheet
$worksheet->setInputEncoding('utf-8');  //設定編碼為UTF   
$format_locked =& $workbook->addFormat();
$format_locked -> setLocked();  //設定鎖定格式,防止別人修改
//$worksheet->setColumn(0,255,8.38,$format_locked);  //此為指定整個工作表鎖定狀態 
     
$worksheet->writeString(0, 0, '日期');  //設定(0,0)儲存格內容
$worksheet->writeString(0, 1, '姓名');  //設定(0,1)儲存格內容
$worksheet->writeString(0, 2, '上班時數');  //設定(0,2)儲存格內容
$worksheet->writeString(0, 3, '加班時數');  //設定(0,3)儲存格內容
$worksheet->writeString(0, 4, '工程案號');  //設定(0,4)儲存格內容

//錯誤資料寫入Excel      
for ($i = 1;$i <= $error_row;$i++){
    for ($j = 1;$j <= 5;$j++){
        $worksheet->write($i, $j-1, $error_msg[$i][$j]);
    }
}

$workbook->send('error_log.xls');  //另存下載Excel檔案          
$workbook->close();  //關閉(?)

3、XML轉出:使用 PHP 輸出帶格式的 Excel 文件

話說M$ Excel從2003開始,導入了對XML檔案的支援,終於冥頑不靈的M$也向開放性格事低頭了呢!只要由PHP輸出正確的XML格式,再另存成xls檔就可以餵給Excel讀了吧...本來是這樣想的...沒想到我用的M$ Excel 2007在另存成XML檔時好像還得經過些設定;我整個不知道要怎麼做啊!在不確定因素及設定太過複雜的情況下,我放棄了這個方法~(其實也是懶得弄一些有的沒的啦...)

4、利用pack()函數將資料包裝使其接近Excel格式:這段操作excel的代碼應該怎麼操作設置每列的寬度

如同標題說,就是利用pack()函數將資料包裝使其接近Excel格式。Excel的格式是M$自定的一種資料格式,這個方法是利用PHP的pack()函數,把我們所需的資料包裝成接近Excel原始格式的一種方法;其實說穿了不過就是把「\t」「\n」替換掉的另一種陽春的方法。不過這種方是因為接近Excel原始格式,所以在開啟的時候並不會有錯誤訊息提示,算是一種簡單易懂又最貼近Excel格式的方法。文章裡也推薦這個方法,所以最後我採用了這個方式~雖然它仍然無法設定儲存格格式...(汗)

/*利用pack()函數將資料包裝使其接近Excel格式*/
$filename = 'error_log.xls';  //設定另存下載檔案名稱
       
header ('Content-type: application/x-msexcel');  //送出header
header ("Content-Disposition: attachment; filename={$filename}" );
       
xlsBOF();  //起始包裝函數
//標題列
xlsWriteLabel(0, 0, u2b('日期'));  //設定(0,0)儲存格內容,儲存格內容為文字
xlsWriteLabel(0, 1, u2b('姓名'));  //設定(0,1)儲存格內容,儲存格內容為文字
xlsWriteLabel(0, 2, u2b('上班時數'));  //設定(0,2)儲存格內容,儲存格內容為文字
xlsWriteLabel(0, 3, u2b('加班時數'));  //設定(0,3)儲存格內容,儲存格內容為文字
xlsWriteLabel(0, 4, u2b('工程案號'));  //設定(0,4)儲存格內容,儲存格內容為文字
//錯誤列 
for ($i = 0;$i < $error_row;$i++){
    xlsWriteLabel($i + 1, 0, $error_msg[$i][0]);  //設定($i + 1,0)儲存格內容,儲存格內容為文字
    xlsWriteLabel($i + 1, 1, $error_msg[$i][1]);  //設定($i + 1,1)儲存格內容,儲存格內容為文字
    xlsWriteNumber($i + 1, 2, $error_msg[$i][2]);  //設定($i + 1,2)儲存格內容,儲存格內容為數字
    xlsWriteNumber($i + 1, 3, $error_msg[$i][3]);  //設定($i + 1,3)儲存格內容,儲存格內容為數字
    xlsWriteLabel($i + 1, 4, $error_msg[$i][4]);  //設定($i + 1,4)儲存格內容,儲存格內容為文字
}
xlsEOF();  //結束包裝函數

//Excel生成用函數,起始包裝
function xlsBOF() {
    echo pack("ssssss", 0x809, 0x8, 0x0, 0x10, 0x0, 0x0); 
    return;
}
//Excel生成用函數,結束包裝
function xlsEOF() {
    echo pack("ss", 0x0A, 0x00);
    return;
}
//Excel生成用函數,數字包裝用
function xlsWriteNumber($Row, $Col, $Value) {
    echo pack("sssss", 0x203, 14, $Row, $Col, 0x0);
    echo pack("d", $Value);
    return;
}
//Excel生成用函數,文字包裝用
function xlsWriteLabel($Row, $Col, $Value ) {
    $L = strlen($Value);
    echo pack("ssssss", 0x204, 8 + $L, $Row, $Col, 0x0, $L);
    echo $Value;
    return;
}

5、使用「\t」、「\n」的方法:

這就是我原來使用的方法,雖然簡單易懂易用,但是因為用M$ Excel 2007開啟時總是會出現錯誤訊息提示~所以才換掉。順便一提,它也沒辦法設定儲存格格式。

/*最原始的\t\n用法*/
$filename = 'error_log.xls';  //設定另存下載檔案名稱
       
header("Content-Type: application/vnd.ms-excel");  //送出header,這我是直接從網路上抄來的
header("Content-Disposition:filename=sub.xls");
header("Content-Disposition: attachment; filename={$filename}");
header("Pragma: no-cache");
header("Expires: 0");
       
$error = '';  //起始錯誤字串的值
//      
for ($i = 1;$i <= $error_row;$i++){
    for ($j = 1;$j <= 5;$j++){
        $error .= $error_msg[$i][$j]."\t";  //跨欄
    }
    $error .= "\n";  //斷行
}
echo $error;  //印出完整錯誤字串

6、使用com()函數:

這個方式應該是設定功能最完整個方法!因為它是直接調用Server端的M$ Excel來產生檔案的,關於這個方法我沒有實際研究。因為這個方法有限制:它只適用在Server為M$ Windows作業系統平台,且必須安裝M$ Office才能用;也就是說,如果作業平台是Linux,或是沒有安裝M$ Office就不能用。非常剛好的,我們公司的Server雖然是M$ Windows作業系統平台,卻沒有安裝M$ Office...想當然爾我就放棄這個方法啦!不過這或許是唯一一個可以設定儲存格格式的方法...

很難想像為了儲存格格式,我把網路上傳授的6種方法幾乎都試過了...雖然最後仍然沒有解決我的問題,不過因此而認識到PHP的無限可能~也學到不少東西哩!最後我對日期的處理方式,是消極的用錯誤訊息防止使用者匯入錯誤格式;這也不失為解決問題的其中一個方法啦!^^
文章標籤

danielhuang030 發表在 痞客邦 留言(16) 人氣()

依然是專案管理系統的功能。因為之前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("excel.application") or die("Unable to instanciate excel");  //調用COM class,順便判斷是否能正常連結Excel應用程式
$excel->DisplayAlerts = 0;  //關閉開啟Excel時的警告
$strTemp = 'C:\\xxx\\xxx\\xxx\\csv\\'.$file_name;  //上傳成功檔案的絕對路徑
$excel->Workbooks->Open($strTemp);  //打開該檔案
$csvfile_name = substr($file_name, 0,strlen($file_name)-4).'.csv';  //利用原檔名將副檔名改寫成csv
$strTemp = 'C:\\xxx\\xxx\\xxx\\csv\\'.$csvfile_name;  //另存成csv檔後的絕對路徑
$excel->ActiveWorkbook->SaveAs($strTemp ,6);  //另存新檔,6代表csv逗號分隔檔案                     
$excel->Quit();  //退出Excel
//$excel->Release();  //釋放Excel所佔用的記憶體...吧?不過我的電腦必須註解掉這行才能動作,不知道為什麼
$excel = null;  //釋放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();  //調用Spreadsheet_Excel_Reader class
$data->setOutputEncoding('utf-8');  //設定輸出的編碼,可直接選擇輸出為UTF8編碼
$data->read("../xxx/xxx/test.xls");  //檔案的路徑(可使用相對路徑)
error_reporting(E_ALL ^ E_NOTICE);  //錯誤顯示

for ($i = 1; $i <= $data->sheets[0]['numRows']; $i++) {
    for ($j = 1; $j <= $data->sheets[0]['numCols']; $j++) {
        echo "\"".$data->sheets[0]['cells'][$i][$j]."\",";
    }
    echo "\n";
}

利用陣列的方式,擷取Excel檔裡面的資料;['numRows']列、['numCols']行、['cells']元素,搭配二維陣列取得。擷取出來的資料就可以直接對其作處理,非常容易使用!

關於Excel檔寫入也有另一個class:Spreadsheet_Excel_Writer。這個class需要pear的支援,所以使用前必須先安裝pear;這個部份我還沒有深入研究測試,就先行打住。另外還有一個class比較新,是支援M$ Office Excel 2007的格式:PHPExcel。這個class同時支援讀入跟寫出,不過目前只針對Excel 2007的版本作處理。目前我們公司仍以2003為主,所以這個版本也沒有深究。當然2007一定是未來的趨勢,所以以後應該還是有機會會接觸到吧。

文章標籤

danielhuang030 發表在 痞客邦 留言(8) 人氣()

因為公司會計部門的人還是比較喜歡(習慣)過去使用Excel編輯成本的環境,新系統上線的不習慣在無形間浪費了許多工時;所以現在專案管理系統在輸入方面將新增轉入功能。簡單說就是利用原先熟悉的Excel環境提供轉檔程式轉進資料庫中。不過這也代表著我先前做的輸入介面與自動完成完全無用武之地啊~(噗)當然已經作的介面也不需要特別去刪掉,就當作有二種輸入介面吧!

因為Excel格式之複雜,導致PHP在轉檔時會發生許多不可預期的問題;所以不論是網路上或是PTT幾乎都建議改以csv檔作轉入的動作;Excel本身也有提供另存成csv檔的功能~也算是一種折衷的方案囉。

之前有試寫人工成本Excel的資料轉入,昨天嘗試著修改了一下介面與原系統整合,本來以為已經沒有問題了~沒想到今天早上卻發現原始csv檔內的特殊字元ex:\t、\n、\r在作怪,導致原先的Javascript警告視窗失效。上網搜尋一下馬上就找到解決的辦法啦~網路真是大家好朋友:PHP如何取消字串裡的特殊字元呢??

主要是利用str_replace()函數,運用取代函數將特殊字數取代掉;是很聰明的應用方式哩!其中以陣列方式一次取代是最方便:


$str = str_replace(array("\n","\t","\r"), array("","",""), $str);

剛好我從csv檔取得的資料也是陣列的格式,真是幫了我一個大忙哩^^
文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

春節前在公司卡很久的自動完成,終於解套啦!(吼)

會碰到這個問題,主要是因為本公司的專案管理系統,在材料成本新增時的廠商欄,會計反應會花很多時間在建立重複的資料上;一開始她建議使用下拉式選單...但是可想而知隨著資料量的增加,這下拉式選單也會變的愈來愈龐大...(汗)剛好前一陣子在研究自動完成,就想把這個應用加在專案管理系統中。關於自動完成,英文絕對沒什麼大問題;重點是中文啊~本來是要自己寫,真正動手以後才發現這個功能不是這麼簡單低。後來熊熊發現網路上有好用的免費資源啊!索性就先借用(?)來試試囉~

起初非常驚訝,沒想到網路上的自動完成功能完善,畫面精美;簡單說就是一整個適合!不過是二個javascript跟一個css就把自動完成做的如此完美,用法也非常簡單!不過高興的情緒並沒有持續太久,我很快的發現到這個自動完成,在IE瀏覽器下對中文不支援!(英文OK)非常出乎意料的該網誌作者註明對firefox不支援...但是我的firefox卻OK;很殘念的會計所慣用的瀏覽器是IE6...就這樣自動完成又走進死胡同。

後來我又花了不少時間在網上尋找適合的lib,期間不經意的發現原來一開始我所找到的免費資源其實是CAPXOUS的破解版;這壓根兒不是什麼免費資源!(汗)我所找到的是v1.3.0的版本,目前最新則是到v1.4.4版本。CAPXOUS本身也有提供程式碼下載以及解說~只不過它既然是個共享程式,廣告自然就少不了囉!最新的版本漂亮許多,當然付費授權的價格也就有點不親切...349 USD。

v1.4.4版也只有幾個檔案,當然重點還是在autocomplete.js、prototype.js以及autocomplete.css上囉!有興趣的人可以直接從CAPXOUS下載位置下載到,程式碼其實還頗複雜本人目前攻力尚淺,是處於一整個看不懂的階段,只好稍微解釋一下連結資料庫時的PHP檔,以及是如何運用在input欄位中的。

主要使用自動完成的頁面,千萬別忘記先導入二個javascript跟一個css:(夾在<head></head>之間)

<script language="JavaScript" src="javascripts/prototype.js" type="text/JavaScript"></script>
<script language="JavaScript" src="javascripts/autocomplete.js" type="text/JavaScript"></script>
<link rel="stylesheet" type="text/css" href="styles/autocomplete.css" />

廠商欄的輸入框:

<input name="supplier" type="text" id="supplier" size="10" />

表格結束後的javascript,導入AJAX:

<script>
 var d = new Date();
 new Autocomplete("supplier", function() {
  return "Suggest.php?msec=" + d.getMilliseconds() + "&type=0&keyword=" + this.value;
 });
</script>

d:特別建立的時間值,利用d.getMilliseconds()取得毫秒後,用以防止瀏覽器在以後只讀快取中的資料而沒有重新查詢。
supplier:input時的id(還是name忘記了...)
type&keyword:要傳入Suggest.php用以查詢資料庫

連結資料庫用的Suggest.php:

<?php
// 利用GET取得變數
$keyword = $_GET['keyword'];
$type = $_GET['type'];

// 連線《Project》資料庫
if($keyword != ''){
  $query = 'SELECT SUPPLIER ' .
           'FROM wh01_project_supplier ' .
           'WHERE SUPPLIER LIKE "' . $keyword . '%"' .
           'AND TYPE = "' . $type . '"';
}
// keyword無值時
else{
  $query = 'SELECT SUPPLIER ' .
           'FROM wh01_project_supplier ' .
           'WHERE SUPPLIER=""';
}
// 執行 SQL query
$result=mysql_query($query,$link);
// 如果$result存在時
if(!empty($result)>0){
  while (list($SUPPLIER) = mysql_fetch_row($result)){
    echo "<li onselect=\"this.text.value = '".$SUPPLIER."';\">\n";
    echo $SUPPLIER."\n";
    echo "</li>\n";
  }
}
// 結束這個連線
mysql_close();

?>

從資料庫取出後只要把結果呈現成:

<li onselect="this.text.value = '結果'; ">
 結果
</li>

就OK囉,最後請看成果

文章標籤

danielhuang030 發表在 痞客邦 留言(1) 人氣()

很久以前就有這樣的計畫,利用現有的圖片由使用者自行加註文字,然後合成為另一張新的圖片~爬了一下PTT的PHP版,很快就看到類似的東西。剛好十天的假期在家閒閒沒事,就來研究一下這玩意兒要怎麼弄吧。

說到跟圖片有關的東西,就不能忘了PHP的GD函式庫啦!它強大的功能也曾經幫我在名片查詢系統時,利用PHP上傳名片圖檔的時候同步縮小圖片呢~這次運用到的函數是ImageTTFText,它可以利用自備的TrueType字體檔,寫入文字到圖形中。最近我對微軟正黑體還蠻有好感的,再加上它算是一套免費(由微軟官方釋出,不過好像是不能任意提供給人家下載啦)的字體;拿來當圖片用的字型,在適合不過啦!

下面是php程式碼:


header("content-type:image/jpeg"); // 送出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); 

$nimage:新建立的圖片的變數名
26:字型的大小
0:字型的角度
60:X座標軸位置
570:Y座標軸位置
$black:字型顏色
$font:字體檔位置;這邊因為我架設主機的平台是linux,不知道為什麼相對位置整個沒反應。弄了好久最後用絕對位置搞定,所以要特別注意。
$wish_word:輸出於圖片上的話

另外因為輸出字數的問題也花了我一點時間...
因為ImageTTFText不會自動幫你斷行,所以必須自己加『\n』去斷行
UTF-8的編碼方式中文字是3個字元,解決方法就是自己算字數然後加『\n』:

if(strlen($wish_words) > (26*3) and (strlen($wish_words) < (26*3*3+1))){
   for($i=0;$i<floor(strlen($wish_words)/78);$i++){
    $wish_word .= substr($wish_words,($i*78),78)."\n";
   }
}

我設定在字數多於26個字時斷行
其中floor()函數是取小數點後無條件捨去的正整數,另一個ceil()函數則是無條件進位後的正整數
這裡我使用floor()函數
substr()函數擷取我要的字段後在自己加『\n』斷行

其實我來以為這只是一個很簡單的GD函數運用,可是因為字型檔路徑跟編碼問題還是讓我花了不少時間
成功了以後又覺得怎麼那麼簡單?
所以雖然函數就在那,但還是要用過才知道用法,才知道會碰到什麼問題,要怎麼解決!

因為從前年開始,我每年都會為PTT的資科系版畫新年賀圖
今年就想利用這個賀圖結合一些祝福的話,在除夕夜的簡訊中連同網址一起發出
所以才會心血來潮的想做這玩意兒;本來以為簡單的東西,其實還是花了不少時間。
這裡是成果,祝大家新年快樂^^
文章標籤

danielhuang030 發表在 痞客邦 留言(1) 人氣()

有鑑於本公司目前許多資料都是記錄在MySQL資料庫裡,常常會有事沒事的進資料庫看資料;然而在修改的過程中難免會有失誤,如果一不小心把資料庫裡的資料刪除了就欲哭無淚啦~因此,資料庫的備份就變得分外重要囉!

上網找了很多資料,大部分的MySQL資料庫備份法都是以Linux備份為主;可惜我們是用M$的作業系統,所以花了一點時間在找方法。所幸Windows有提供「工作排程」的方法,同樣可以提供每日、每周或每月設定時間。上面這個連結是採用Windows定時執行PHP的方式,使用mysqldump這個MySQL本身就有參數進行備份。不過我比較不解的地方是,直接使用批次檔執行mysqldump就可以啦~為什麼還要透過PHP?

不囉唆,下面是批次檔中mysqldump備份的語法:

C:\AppServ\MySQL\bin\mysqldump --opt -u*** -p*** Database_name >D:\%date:~0,4%-%date:~5,2%-%date:~8,2%.sql

-u:MySQL使用者名稱
-p:MySQL使用者密碼
Database_name:MySQL資料庫名稱
%date:~0,4%:這個是運用DOS本身的環境變數指令「date」,從第「o」位開始取「4」位;因為原本的「date」出來會有「/」不能當作檔名,所以必須取三次再自己用「-」連結。

使用方法參考: Mysql自動製作備份批次處理 for windows

這樣就可以把MySQL資料庫備份檔案,以「2008-01-29.sql」的型式備份於「D:\」下囉!另外如果有WinRAR的程式,可以參考連接中再壓縮成RAR檔案備存。

備份出來的檔案當然會有要還原回去的時候啦,還原的方法如下:

C:\AppServ\MySQL\bin\mysqladmin -u*** -p*** create target_db_name

C:\AppServ\MySQL\bin\mysql -u*** -p*** target_db_name < backup-file.sql

-u:MySQL使用者名稱
-p:MySQL使用者密碼
target_db_name:新建MySQL資料庫名稱
backup-file.sql:備份的MySQL資料庫檔案路徑

更詳盡的mysqldum使用方法參考:最簡便的備份MySql資料庫方法

以上,大概描述了一下MySQL於Windows平台下的備份與還原。
文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

原來PHP有內建數字格式建立的函數啊:number_formatmoney_format;可以直接對數字重新格式化。當然提到格式化就不能忘了sprintf這個函數囉!考慮加入在專案管理程式的可能性...
文章標籤

danielhuang030 發表在 痞客邦 留言(1) 人氣()

Close

您尚未登入,將以訪客身份留言。亦可以上方服務帳號登入留言

請輸入暱稱 ( 最多顯示 6 個中文字元 )

請輸入標題 ( 最多顯示 9 個中文字元 )

請輸入內容 ( 最多 140 個中文字元 )

reload

請輸入左方認證碼:

看不懂,換張圖

請輸入驗證碼