คุณคงทราบดีอยู่แล้วว่า Visual FoxPro ถูกสร้างขึ้นมาเพื่อจัดการกับฐานข้อมูล ซึ่งจะมีการเก็บข้อมูลต่างๆแล้วนำมาประมวลผล ในบทนี้เราจะมากล่าวกันเกี่ยวกัวการออกแบบฐานข้อมูล แฟ้มข้อมูล เรคอร์ด ฟิลด์ เพื่อเป็นแนวทางในการออกแบบและสร้างฐานข้อมูลต่อไป ท่านทราบหรือไม่ว่าหน่วยเก็บข้อมูลที่เล็กที่สุดของคอมพิวเตอร์คืออะไร
บิต(Bit) เป็นหน่วยเก็บข้อมูลที่เล็กที่สุดในคอมพิวเตอร์ เมื่อเรานำบิตหลายๆบิตมารวมกับก็จะเป็น ไบต์ (รหัส ASCII 8 บิต เท่ากับ 1 ไบต์) ซึ่งก็คือ 1 ตัวอักษรนั่นเอง แล้วนำตัวอักษรมารวมกันแล้วมีความหมายอย่างใดอย่างหนึ่งเราเรียกเป็นฟิลด์(Field) นำฟิลด์หลายๆฟิลด์มีมีความเกี่วยเนื่องกันมาประกอบกันรวมเป็น เรคคอร์ด(Record) หลายๆเรคคอร์รวมกันเก็บไว้ในแฟ้มข้อมูล(File) แล้วนำแฟ้มข้อมูลหลายๆแฟ้มข้อมูลมาสร้างความสัมพันธ์กันประกอบกันเป็นฐานข้อมูล ถ้าคุณต้องการที่จะสร้างระบบงานขึ้นมาใช้งานสักระบบงานหนึ่งสิ่งที่จำเป็นอย่างยิ่งก็คือ ฐานข้อมูล (Database) แล้วฐานข้อมูลมีประโยชน์อย่างไร?
1. เพื่อลดความซ้ำซ้อนของข้อมูล
2. เพื่อลดข้อผิดพลาดในการป้อนข้อมูลได้ระดับหนึ่ง
3. สามารถนำข้อมูลไปใช้ร่วมกันได้
4. ควบคุมดูแลง่าย
เป็นต้น
ผมจะขอยกตัวอย่างฐานข้อมูล ใบส่งสินค้า(Invoice) เพื่อเป็นแนวทางในการออกแบบดังต่อไปนี้ ก่อนอื่นท่านต้องมาดูก่อนว่าใบส่งสินค้านั้นประกอบไปด้วยข้อมูลอะไรบ้าง ประกอบด้วย ข้อมูลลูกค้า ข้อมูลสินค้า ข้อมูลการสั่งสินค้า เป็นต้น แล้วเรานำข้อมูลที่ได้นั้นมาออบแบบแฟ้มข้อมูล(Table) ซึ่งสามารถจำแนกออกเป็นแฟ้มข้อมูลดังตาราง
แฟ้มข้อมูลลูกค้า(Customer)
รัหสลูกค้า |
ชื่อ |
ที่อยู่ |
ยอดเงินคงค้าง |
วงเงินสินเชื่อ |
วันให้สินเชื่อ |
พนักงานขาย |
00001 |
บ.นานนานมีที | 198 ถ.สาธร กทม. |
150000 |
20000 |
30 |
S0001 |
00002 |
ร้านสะอาด | 189 ถ.อิสรภาพ กทม |
0 |
50000 |
60 |
S0001 |
00003 |
บ.สู่ความสำเร็จ | 44 ถ.ร่มเกล้า กทม. |
9850 |
7500 |
15 |
S0002 |
แฟ้มข้อมูลพนักงานขาย(Salesman)
รหัสพนักงานขาย |
ชื่อ |
ที่อยู่ |
อัตราคอมมิชชั่น |
S0001 |
นายสมหวัง | 393 ถ.รามคำแหง กทม. |
0.50% |
S0002 |
นายระเบียบ | 78 ซ.อ่อนนุช กทม. |
0.75% |
แฟ้มข้อมูลใบส่งสินค้า(Invoice)
เลขที่ใบส่งสินค้า |
วันที่สั่ง |
รหัสลูกค้า |
9800001 |
15/09/1998 |
00002 |
9800002 |
01/10/1998 |
00001 |
9800003 |
01/10/1998 |
00002 |
แฟ้มข้อมูลรายการสินค้า(Invoice Detail)
เลขที่ใบส่งสินค้า |
รหัสสินค้า |
จำนวน |
ราคาต่อหน่วย |
980001 |
AA001 |
5000 |
2.50 |
980001 |
BB001 |
850 |
10.00 |
980002 |
AA001 |
1000 |
2.25 |
98003 |
CC001 |
50 |
100.00 |
แฟ้มข้อมูลสินค้า(Product)
รหัสสินค้า |
ชื่อ NAME |
จำนวนคงเหลือ ON_HAND |
หน่วยนับ |
ราคาต่อหน่วย |
AA001 |
น๊อต |
550000 |
ตัว |
2.50 |
BB001 |
เทปพันสายไฟ |
4000 |
ม้วน |
10.00 |
CC001 |
สี |
6 |
กระป๋อง |
110.00 |
ถ้าคุณพิจารณาดูแฟ้มข้อมูลตามตารางจะสังเกตเห็นว่าแฟ้มข้อมูลแต่ละแฟ้มจะมีความสัมพันธ์กับอีกแฟ้มข้อมูลหนึ่ง เช่นแฟ้มข้อมูลใบส่งสินค้า กับ แฟ้มข้อมูลลูกค้าจะมีรหัสลูกค้าเป็นตัวเชื่อมความสัมพันธ์ แล้วแฟ้มข้อมูลลูกค้า ก็จะ เชื่อมกับแฟ้มข้อมูลพนักงานขายโดยมีรหัสพนักงานขายเป็นตัวสร้างความสัมพันธ์ แล้วเมื่อไหร่เราต้องทำการสร้างความสัมพันธ์ระหว่างแฟ้มข้อมูล? อันดับแรกในการสร้างความสัมพันธ์(relation) เราต้องคำนึ่งถึงความซ้ำซ้อนข้องข้อมูล เช่นในใบส่งสินค้า จะประกอบไปด้วยข้อมูลลูกค้า ถ้าลูกค้ารายนั้นๆทำการสั่งสินค้าเสมอ เมื่อเราทำการออกใบส่งสินค้าให้ ทุกครั้งเราต้องมาทำการป้อนข้อมูลลูกค้ารายนั้นอีก ซึ่งข้อมูลที่ป้อนจะมีลักษณะเหมือนกันทุกครั้งไป ดังนั้นเรา จำเป็นต้องสร้างแฟ้มข้อมูลลูกค้าเพื่อมารองรับในส่วนนี้ แล้วจัดการเชื่อมแฟ้มข้อมูลทั้งสองแฟ้มด้วยรหัส ซึ่งการเชื่อมนี้เราเรียกว่าการสร้างความสัมพันธ์ เมื่อแฟ้มข้อมูลมีการสร้างความสัมพันธ์ขึ้นมาก็เกิดเป็น ฐานข้อมูลขึ้น
แล้วใน Visual FoxPro จะสร้างฐานข้อมูลขึ้นมาได้อย่างไร?
ในบทที่ผ่านมาผมได้กล่างถึงคำสั่งที่ใช้สร้าง แฟ้มข้อมูล(Table) ไว้แล้ว ที่นี้เราจะมาทำการสร้าง แฟ้มข้อมูลขึ้นมาตามตัวอย่างในตารางข้างต้น
ให้ทำการสร้างโปรแกรมเพื่อทำการสร้าง ฐานข้อมูล (Database)
ทำการพิมพ์คำสั่งผ่านทาง Command Window โดยพิมพ์ คำสั่ง
MODIFY COMMAND GenStru แล้วกดปุ่ม Enter
แล้ว็ทำการป้อนคำสั่งต่อไปนี้
*GenStru.PRG
* Create Database File
CREATE DATABASE myDatabase
* Create Database Table
CREATE TABLE Salesman (Sales_ID c(5) PRIMARY KEY, ;
Name c(60),Address c(120),CommRate n(5,2))
CREATE TABLE Customer (Cust_ID c(5) PRIMARY KEY,;
Name c(60),Address c(120),Creditlmt n(3,0), ;
Term_day n(3,0), Sales_ID c(5), ;
FOREIGN KEY Sales_ID TAG Sales_ID REFERENCE Salesman)
CREATE TABLE Product (Prod_ID c(5) PRIMARY KEY, ;
Name c(60),On_Hand n(7,0),UM c(10),UnitPrice n(10,2))
CREATE TABLE Inv_Head (Inv_NO n(6,0) PRIMARY KEY, ;
Date d(8),Cust_ID c(5), ;
FOREIGN KEY Cust_ID TAG Cust_ID REFERENCE Customer)
CREATE TABLE Inv_Dtl (Inv_NO n(6,0),Prod_ID c(5), ;
Quantity n(6,0),UnitPrice n(10,2), ;
FOREIGN KEY Inv_NO TAG Inv_NO REFERENCE Inv_Head ,;
FOREIGN KEY Prod_ID TAG Prod_ID REFERENCE Product)
หรือ
*GenStru.PRG
CREATE DATABASE ‘MYDATABASE.DBC’
***** Table setup for SALESMAN *****
CREATE TABLE ‘SALESMAN’ (SALES_ID C(5) NOT NULL, ;
NAME C(60) NOT NULL, ;
ADDRESS C(120) NOT NULL, ;
COMMRATE N(5, 2) NOT NULL)
***** Create each index for SALESMAN *****
ALTER TABLE ‘SALESMAN’ ADD PRIMARY KEY SALES_ID TAG SALES_ID
***** Change properties (if any) for SALESMAN *****
***** Table setup for CUSTOMER *****
CREATE TABLE ‘CUSTOMER’ (CUST_ID C(5) NOT NULL, ;
NAME C(60) NOT NULL, ;
ADDRESS C(120) NOT NULL, ;
CREDITLMT N(3, 0) NOT NULL, ;
TERM_DAY N(3, 0) NOT NULL, ;
SALES_ID C(5) NOT NULL)
***** Create each index for CUSTOMER *****
ALTER TABLE ‘CUSTOMER’ ADD PRIMARY KEY CUST_ID TAG CUST_ID
INDEX ON SALES_ID TAG SALES_ID
***** Change properties (if any) for CUSTOMER *****
***** Table setup for PRODUCT *****
CREATE TABLE ‘PRODUCT’ (PROD_ID C(5) NOT NULL, ;
NAME C(60) NOT NULL, ;
ON_HAND N(7, 0) NOT NULL, ;
UM C(10) NOT NULL, ;
UNITPRICE N(10, 2) NOT NULL)
***** Create each index for PRODUCT *****
ALTER TABLE ‘PRODUCT’ ADD PRIMARY KEY PROD_ID TAG PROD_ID
***** Change properties (if any) for PRODUCT *****
***** Table setup for INV_HEAD *****
CREATE TABLE ‘INV_HEAD’ (INV_NO N(6, 0) NOT NULL, ;
DATE D NOT NULL, ;
CUST_ID C(5) NOT NULL)
***** Create each index for INV_HEAD *****
ALTER TABLE ‘INV_HEAD’ ADD PRIMARY KEY INV_NO TAG INV_NO
INDEX ON CUST_ID TAG CUST_ID
***** Change properties (if any) for INV_HEAD *****
***** Table setup for INV_DTL *****
CREATE TABLE ‘INV_DTL’ (INV_NO N(6, 0) NOT NULL, ;
PROD_ID C(5) NOT NULL, ;
QUANTITY N(6, 0) NOT NULL, ;
UNITPRICE N(10, 2) NOT NULL)
***** Create each index for INV_DTL *****
INDEX ON INV_NO TAG INV_NO
INDEX ON PROD_ID TAG PROD_ID
***** Change properties (if any) for INV_DTL *****
*************** Begin Relations Setup **************
ALTER TABLE ‘CUSTOMER’ ADD FOREIGN KEY TAG SALES_ID REFERENCES SALESMAN TAG SALES_ID
ALTER TABLE ‘INV_HEAD’ ADD FOREIGN KEY TAG CUST_ID REFERENCES CUSTOMER TAG CUST_ID
ALTER TABLE ‘INV_DTL’ ADD FOREIGN KEY TAG INV_NO REFERENCES INV_HEAD TAG INV_NO
ALTER TABLE ‘INV_DTL’ ADD FOREIGN KEY TAG PROD_ID REFERENCES PRODUCT TAG PROD_ID
เมื่อป้อนเสร็จให้ทำการ Save โดยกด Ctrl+W แล้วพิมพ์คำสั่ง DO GenStru ที่ Command Windows
โปรแกรมก็จะทำการสร้างฐานข้อมูลชื่อ myDatabase ขึ้นมาให้อัตโนมัติ จากนั้นให้พิมพ์คำสั่ง
CLOSE DATABASE
MODIFY DATABASE myDatabase
แล้วดูว่ามีอะไรเกิดขึ้นบ้าง
เคล็ดไม่ลับ ถ้าคุณมีแฟ้ม Database อยู่แล้วคุณสามารถแปลงกลับมาเป็น .PRG ได้โดยใช้คำสั่ง DO HOME()+’\TOOLS\GENDBC\GENDBC.PRG’ |
จริงๆแล้วในการสร้างฐานข้อมูลใน Visual FoxPro นั้นมีวิธีการสร้างหลายวิธี ที่ผมอธิบายมานี้ก็เป็น อีกวิธีหนึ่งในการสร้าง แต่ที่ผมสร้างเป็นโปรแกรมไว้นี้ต่อๆไปเราจะนำไปใช้งานกันอีก คงมีหลายท่านสงสัยว่าเมื่อสร้างเสร็จแล้วก็แล้วกันทำไมต้องเขียนเป็นโปรแกรมให้ยุ่งยาก เหตุผลของผมหรือวิธีการของผมนั้นมีเอาไว้เพื่อ ถ้าแฟ้มข้อมูลของคุณบังเอิญถูกลบหมดแล้วคุณจำโครงสร้างของแฟ้มข้อมูลไม่ได้ คุณสามารถนำมันไปสร้างฐานข้อมูลขึ้นมาใหม่ได้
เมื่อคุณนำโปรแกรมไปแจกจ่าย (Compile เป็น .exe แล้วคุณไม่จำเป็นต้อง Copy แฟ้มข้อมูลไปด้วยเพียงแต่คุณทำการเขียนโปรแกรมให้มันไปเรียก โปรแกรม GenStru ขึ้นมามันก็จะทำการสร้างฐานข้อมูลให้คุณ ส่วนวิธีการนำไปใช้นั้นตอนสร้าง ระบบงานผมจะอธิบายอีกครั้ง ขอย้ำนี้เป็นเพียงแนวความคิดส่วนตัวมิได้ห้ามเลียนแบบ
ตอนนี้เรามาดูรายละเอียดและคำสั่งต่างๆเกี่ยวกับ ฐานข้อมูล และ แฟ้มข้อมูล กันก่อน
ใน Visual FoxPro ได้แยกแฟ้มข้อมูลออกเป็น 2 ชนิด คือ Free Table กับ Database Table จริงๆแล้วมันก็คือแฟ้มตัวเดียวกันมีนามสกุลเป็น .DBF แล้วมันต่างกันอย่างไร?
Free Table คือแฟ้มข้อมูล .DBF ที่ไม่ผูกอยู่กับ แฟ้ม Database คุณสามารถทำการเปิดแฟ้มนี้หรือเพิ่มแฟ้มนี้เข้าไปใน แฟ้ม Database ใดก็ได้
Database Table คือแฟ้มข้อมูล .DBF ที่ไปผูกอยู่กับ แฟ้ม Database เมื่อนำไปใช้งานจะต้องเปิดพร้อมกับ Database File
แล้วทำไมต้องสร้าง Database file เพื่อมาผูกกับ Database Table ด้วย
เหตุผลหลักเลยก็คือทำให้คุณสามารถเห็นความสัมพันธ์ระหว่างแฟ้มข้อมูลซึ่งก็เข้าหลักของระบบฐานข้อมูล
และคุณสามารถตั้งชื่อ Database Table ตั้งชื่อ Field ได้ยาวขึ้น ถึง 128 ตัวอักษร ซึ่ง แฟ้ม .DBF เดิมตั้งชื่อ แฟ้มได้ 8 ตัว ชื่อ Field ได้ 10 ตัวอักษร
คำสั่งต่างเกี่ยวกับฐานข้อมูล
สร้างฐานข้อมูล (แฟ้ม .DBC)
CREATE DATABASE [DatabaseName | ?]
เช่น CREATE DATABASE myDatabase
สร้าง Table (แฟ้ม .DBF)
CREATE TABLE | DBF TableName1 [NAME LongTableName] [FREE]
(FieldName1 FieldType [(nFieldWidth [, nPrecision])]
[NULL | NOT NULL]
[CHECK lExpression1 [ERROR cMessageText1]]
[DEFAULT eExpression1]
[PRIMARY KEY | UNIQUE]
[REFERENCES TableName2 [TAG TagName1]]
[NOCPTRANS]
[, FieldName2 …]
[, PRIMARY KEY eExpression2 TAG TagName2
|, UNIQUE eExpression3 TAG TagName3]
[, FOREIGN KEY eExpression4 TAG TagName4 [NODUP]
REFERENCES TableName3 [TAG TagName5]]
[, CHECK lExpression2 [ERROR cMessageText2]])
| FROM ARRAY ArrayName
เช่น CREATE TABLE Customer (Cust_ID c(5) PRIMARY KEY,;
Name c(60),Address c(120),Creditlmt n(3,0), ;
Term_day n(3,0), Sales_ID c(5), ;
FOREIGN KEY Sales_ID TAG Sales_ID REFERENCE Salesman)
จากตัวอย่างข้างต้นจะเป็นการสร้าง database table พร้อมๆกับ สร้างแฟ้มดัชนี (ถ้ามีการเปิด database file อยู่ก่อนแล้วเมื่อเราทำการสร้าง table โปรแกรมจะถือว่าเป็นการสร้าง database table โดยอัตโนมัติ)
** ขอย้ำตอนนี้คุณสามารถกำหนดชื่อฟิลด์ได้ยาวถึง 128 ตัวน๊ะจะบอกให้
ใน Visual FoxPro จะมีแฟ้มดัชนีอยู่ 2 ประเภทคือ Structure Compound Compact Index (.CDX) และ Single-key (.IDX) ทั้งสองประเภทมีความแตกต่างกันอย่างไรและเราควรใช้แฟ้มดัชนีแบบไหน
Single-key Index |
Structural Compound Compact Index |
|
จำนวนดัชนีต่อ 1 แฟ้มข้อมูล | 1 ดัชนี | มากกว่า 1 ดัชนี |
ความยาวของดัชนี | 100 ตัวอัษร | 240 ตัวอัษร |
การเปิดแฟ้มดัชนี | ต้องทำการเปิดเองโดยใช้คำสั่ง set index to file.idx | จะทำการเปิดให้อัตโนมัติพร้อมกับการเปิด table |
การเรียกใช้ดัชนี | เรียกจากแฟ้มดัชนี | เรียกจาก tag name |
จากตารางข้างต้นคงจะสรุปได้ว่าเราควรใช้แฟ้มดัชนีแบบไหน ถ้าเป็นผมจะขอใช้ .CDX
มีวิธีอื่นอีกหรือไม่ที่จะทำการสร้างแฟ้มดัชนี ? เราสามารถสร้าแฟ้มดัชนี้ได้โดยใช้คำสั่ง
INDEX ON eExpression TO IDXFileName | TAG TagName [OF CDXFileName]
[FOR lExpression]
[COMPACT]
[ASCENDING | DESCENDING]
[UNIQUE | CANDIDATE]
[ADDITIVE]
จากคำสั่งข้างต้นถ้าเราใส่ key word IDXFileName โปรแกรมจะทำการสร้างแฟ้มดัชนีเป็นแบบ Single-key index ให้ แต่ถ้าเราไม่ใส่ ก็จะเป็น Structural Compound Compact Index แทน
เช่น INDEX ON CUST_ID TAG CUST_ID
INDEX ON SUBST(NAME,1,1) TAG NAME
เคล็ดไม่ลับ คุณสามารถ ขอดู tag name ได้โดยใช้คำสั่ง ?tag(1) ถ้าต้องการดูว่าดัชนีที่เราทำการจัดเรียงมีการเขียนประโยคว่าอย่างไรให้ใช้ ?sys(14,1) (1 คือลำดับในการทำ index ถ้ามีหลาย tag tag ตัวต่อไปก็จะเป็นเลข 2,3 .. ไปเรื่อยๆ) |
การเรียกดัชนีมาใช้งานนั้นถ้าเป็นแบบ compound index เราต้องบอกให้โปรแกรมทราบว่าเราจะนำ tag ใดมาใช้งานเพราะว่าการเปิด table มาใช้งานนั้นโปรแกรมจะทำการเปิด แฟ้มดัชนีขึ้นมาให้อัตโนมัติอยู่แล้ว แต่การจะเลือกใช้ว่าจะใช้ tag ตัวใหนเราต้องเป็นผู้กำหนด โดยใช้คำสั่ง
SET ORDER TO
[nIndexNumber | IDXIndexFileName | [TAG] TagName [OF CDXFileName]
[IN nWorkArea | cTableAlias]
[ASCENDING | DESCENDING]]
เช่น SET ORDER TO 1
SET ORDER TO TAG NAME
SET ORDER TO TAG SALES_ID
หรือเราสามารถเรียกดัชนีมาพร้อมกับการเปิดแฟ้มข้อมูลขึ้นมาก็ได้ โดยใช้คำสั่ง USE
USE SALESMAN ORDER 1
USE SALESMAN TAG SALES_ID
ถึงตอนนี้เราลองมาดูตัวอย่างโปรแกรมป้อนข้อมูลกันเล่นๆซักตัวอย่างแก้เซ็งกันก่อนแล้วค่อยว่ากันต่อ ให้คุณสร้างโปรแกรมชื่อ program4.prg ทำการป้อนตามตัวอย่างด้านล่างแล้วลองเรียกโปรแกรมนี้ดูว่าเป็นอย่างไร
อ๊ะๆ จะเรียกโปรแกรมใช้คำสั่ง do program4 ที่ command window น๊ะจ๊ะ
* program4.prg
PUBLIC oform1
ON SHUTDOWN DO PRGERR && When program error click X (close foxpro) botton
SET DELETE ON
IF !USED(‘SALESMAN’)
select 0
use Salesman
ENDIF
SET ORDER TO TAG SALES_ID
GO TOP
SCATTER MEMVAR
oform1=CREATEOBJECT(“form1”)
oform1.Show()
oform1.cmdGroup.oTop.Enabled=.F.
oform1.cmdGroup.oPrev.Enabled=.F.
if reccount() = 0
oform1.cmdGroup.oNext.Enabled=.F.
oform1.cmdGroup.oBott.Enabled=.F.
endif
READ EVENT
RETURN
DEFINE CLASS form1 AS form
Height = 261
Width = 633
DoCreate = .T.
AutoCenter = .T.
Caption = “Salesman”
ControlBox = .F.
LockScreen = .F.
Name = “Form1”
ADD OBJECT osales_id AS textbox WITH ;
ControlSource = “m.sales_id”, ;
Enabled = .F., ;
Height = 24, ;
Left = 132, ;
Top = 24, ;
Width = 73, ;
Name = “oSales_id”
ADD OBJECT oname AS textbox WITH ;
ControlSource = “m.name”, ;
Enabled = .F., ;
Height = 24, ;
Left = 132, ;
Top = 60, ;
Width = 265, ;
Name = “oName”
ADD OBJECT oaddress AS textbox WITH ;
ControlSource = “m.address”, ;
Enabled = .F., ;
Height = 24, ;
Left = 132, ;
Top = 96, ;
Width = 456, ;
Name = “oAddress”
ADD OBJECT ocommrate AS textbox WITH ;
Alignment = 3, ;
Value = 0, ;
ControlSource = “m.commrate”, ;
Enabled = .F., ;
Format = “R”, ;
Height = 24, ;
InputMask = “999.99”, ;
Left = 132, ;
Top = 132, ;
Width = 61, ;
Name = “oCommrate”
ADD OBJECT cmdgroup AS commandgroup WITH ;
ButtonCount = 8, ;
Value = 1, ;
Height = 39, ;
Left = 12, ;
Top = 192, ;
Width = 615, ;
Name = “cmdGroup”, ;
Command1.Top = 5, ;
Command1.Left = 5, ;
Command1.Height = 29, ;
Command1.Width = 73, ;
Command1.Caption = “Top”, ;
Command1.Name = “oTop”, ;
Command2.AutoSize = .F., ;
Command2.Top = 5, ;
Command2.Left = 81, ;
Command2.Height = 29, ;
Command2.Width = 73, ;
Command2.Caption = “Previous”, ;
Command2.Name = “oPrev”, ;
Command3.Top = 5, ;
Command3.Left = 157, ;
Command3.Height = 29, ;
Command3.Width = 73, ;
Command3.Caption = “Next”, ;
Command3.Name = “oNext”, ;
Command4.Top = 5, ;
Command4.Left = 233, ;
Command4.Height = 29, ;
Command4.Width = 73, ;
Command4.Caption = “Bottom”, ;
Command4.Name = “oBott”, ;
Command5.AutoSize = .F., ;
Command5.Top = 5, ;
Command5.Left = 309, ;
Command5.Height = 29, ;
Command5.Width = 73, ;
Command5.Caption = “New”, ;
Command5.Name = “oNew”, ;
Command6.Top = 5, ;
Command6.Left = 385, ;
Command6.Height = 29, ;
Command6.Width = 73, ;
Command6.Caption = “Change”, ;
Command6.Name = “oChge”, ;
Command7.Top = 5, ;
Command7.Left = 461, ;
Command7.Height = 29, ;
Command7.Width = 73, ;
Command7.Caption = “Delete”, ;
Command7.Name = “oDele”, ;
Command8.Top = 5, ;
Command8.Left = 537, ;
Command8.Height = 29, ;
Command8.Width = 73, ;
Command8.Caption = “Exit”, ;
Command8.Name = “oExit”
ADD OBJECT label1 AS label WITH ;
Caption = “Salesman No.”, ;
Height = 18, ;
Left = 24, ;
Top = 24, ;
Width = 88, ;
Name = “Label1”
ADD OBJECT label2 AS label WITH ;
Caption = “Name”, ;
Height = 18, ;
Left = 75, ;
Top = 60, ;
Width = 37, ;
Name = “Label2”
ADD OBJECT label3 AS label WITH ;
Caption = “Address”, ;
Height = 18, ;
Left = 62, ;
Top = 96, ;
Width = 50, ;
Name = “Label3”
ADD OBJECT label4 AS label WITH ;
Caption = “Commission”, ;
Height = 18, ;
Left = 35, ;
Top = 132, ;
Width = 77, ;
Name = “Label4”
PROCEDURE cmdgroup.oTop.Click
if !bof()
go top
scatt memvar
this.enabled=.F.
this.parent.oPrev.enabled=.F.
this.parent.oNext.enabled=.T.
this.parent.oBott.enabled=.T.
endif
thisform.refresh
ENDPROC
PROCEDURE cmdgroup.oPrev.Click
if !bof()
skip -1
if bof()
go top
this.parent.oTop.enabled=.f.
this.enabled=.f.
endif
scatt memvar
this.parent.oNext.enabled=.T.
this.parent.oBott.enabled=.T.
endif
thisform.refresh
ENDPROC
PROCEDURE cmdgroup.oNext.Click
if !eof()
skip
if eof()
go bott
this.enabled=.F.
this.parent.oBott.enabled=.F.
endif
scatt memvar
this.parent.oTop.enabled=.T.
this.parent.oPrev.enabled=.T.
endif
thisform.refresh
ENDPROC
PROCEDURE cmdgroup.oBott.Click
if !eof()
go bott
scatt memvar
this.enabled=.F.
this.parent.oNext.enabled=.F.
this.parent.oTop.enabled=.T.
this.parent.oPrev.enabled=.T.
endif
thisform.refresh
ENDPROC
PROCEDURE cmdgroup.oNew.Click
if this.caption = ‘New’
scat memvar blank
thisform.oSales_id.Enabled = .T.
thisform.oName.Enabled = .T.
thisform.oAddress.Enabled = .T.
thisform.oCommrate.Enabled = .T.
this.caption = ‘Save’
this.parent.oChge.caption = ‘Cancel’
this.parent.oTop.Enabled = .F.
this.parent.oPrev.Enabled = .F.
this.parent.oBott.Enabled = .F.
this.parent.oNext.Enabled = .F.
this.parent.oDele.Enabled = .F.
this.parent.oExit.Enabled = .F.
else
do case
case this.caption = ‘Save’ .and. this.parent.oChge.caption = ‘Cancel’
if !empty(thisform.oSales_id.value)
INSERT INTO Salesman FROM MEMVAR
else
wait window ‘Sales_id must be Entry! Program not save’
endif
case this.caption = ‘Save’ .and. this.parent.oChge.caption = ‘Reverse’
GATHER MEMVAR
endcase
thisform.oSales_id.Enabled = .F.
thisform.oName.Enabled = .F.
thisform.oAddress.Enabled = .F.
thisform.oCommrate.Enabled = .F.
this.caption = ‘New’
this.parent.oChge.caption = ‘Change’
this.parent.oTop.Enabled = .T.
this.parent.oPrev.Enabled = .T.
this.parent.oBott.Enabled = .T.
this.parent.oNext.Enabled = .T.
this.parent.oDele.Enabled = .T.
this.parent.oExit.Enabled = .T.
endif
thisform.refresh
ENDPROC
PROCEDURE cmdgroup.oChge.Click
if recc() = 0 .and. this.parent.oChge.caption = ‘Change’
wait wind ‘No data cannot change this record’
else
if this.caption = ‘Change’
thisform.oSales_id.Enabled = .T.
thisform.oName.Enabled = .T.
thisform.oAddress.Enabled = .T.
thisform.oCommrate.Enabled = .T.
this.caption = ‘Reverse’
this.parent.oNew.caption = ‘Save’
this.parent.oTop.Enabled = .F.
this.parent.oPrev.Enabled = .F.
this.parent.oBott.Enabled = .F.
this.parent.oNext.Enabled = .F.
this.parent.oDele.Enabled = .F.
this.parent.oExit.Enabled = .F.
else
do case
case this.caption = ‘Reverse’
scatter memvar
case this.caption = ‘Cancel’ && for addnew record
go bott
scatter memvar
endcase
thisform.oSales_id.Enabled = .F.
thisform.oName.Enabled = .F.
thisform.oAddress.Enabled = .F.
thisform.oCommrate.Enabled = .F.
this.caption = ‘Change’
this.parent.oNew.caption = ‘New’
this.parent.oTop.Enabled = .T.
this.parent.oPrev.Enabled = .T.
this.parent.oBott.Enabled = .T.
this.parent.oNext.Enabled = .T.
this.parent.oDele.Enabled = .T.
this.parent.oExit.Enabled = .T.
endif
endif
thisform.refresh
ENDPROC
PROCEDURE cmdgroup.oDele.Click
if recc() = 0
wait wind ‘No data cannot delete this record’
else
nAnswer = MESSAGEBOX(‘Confirm Delete’, 4 + 32 + 256,’Delete Record’)
DO CASE
CASE nAnswer = 6
Delete
go bott
scatt memvar
CASE nAnswer = 7
* not Delete
ENDCASE
endif
Thisform.refresh
ENDPROC
PROCEDURE cmdgroup.oExit.Click
USE
SET DELETE OFF
thisform.release
CLEAR EVENT
on shutdown
ENDPROC
ENDDEFINE
PROCEDURE PRGERR
CLEAR EVENT
close all
clear all
on shutdown
ENDPROC
ตัวอย่างที่ให้มานี้เป็นตัวอย่างการป้อนข้อมูลของ Salesman ก็ลองทำการป้อนข้อมูลเล่นๆไปสัก 4-5 คนก่อน แล้วเราจะมาต่อกันในบทต่อไปเรื่องจัดการข้อมูลภาคสอง