บทความ

เมื่อ VFP Table พัง

สมัยก่อนผมใช้ VFP ไปแล้ว Table ใหญ่ๆ มี Memo Field ด้วย และมีกระแสไฟตกบ่อยๆ ก็มักเจอดีเหตุการณ์ไฟล์เสียเข้ามาเยือน ซ่อมได้ด้วยเทคนิคต่างๆที่ไม่เป็นทางการ แล้วก็น่าแปลกที่ VFP ไม่ทำโปรแกรมซ่อมโดยเฉพาะออกมา วิธีการที่ว่านั้นก็มีทั้งเล่นเป็นชุด เปิดไฟล์ขึ้นมา+เพิ่มเรคอร์ดใหม่+ลบออก+PACK+ปิดไฟล์ แล้วเปิดใช้อีกที , หรือไม่ก็ใช้ซอฟต์แวร์ซ่อม dbf ของผู้ใช้งานทำกันออกมาเอง ที่มีให้ดาว์นโหลดฟรีและเสียกะตังค์ แบบเล่นเป็นชุดที่ว่า...คุณ Anuwat (ขออภัยท่านนี้ผมยังไม่เคยทัก) ในกลุ่ม Line แนะนำมาว่า SET TABLEVALIDATE TO 0 USE table1 EXCLUSIVE APPEND BLANK DELETE PACK USE แบบนี้ครับ ส่วนคุณ Joe นักพัฒนาซอฟต์แวร์ที่เชี่ยวชาญและมีน้ำใจคอยช่วยตอบปัญหาให้เพื่อนๆชาว Fox มาตลอดได้แนะนำในกลุ่ม Line เดียวกันดังข้างล่างนี้ครับ *เรียกใช้ If FixMemoFile('c:\front\font.scx') *** Success. File is Fixed Else *** Fail. File is not fixed Endif *ฟังก์ชั่น Function FixMemoFile(tcFile as string) If vartype(tcFile) = 'C' and not Empty(tcFile) and File(tcFile) Local lnOldSelec

VFP SQL UPDATE ปรับปรุงค่าในฟิลด์ด้วยค่าจากตารางอื่น

ก่อนนี้ผมใช้ VFP มาแบบโบราณ เวลาเปลี่ยนค่าใน Field ก็ใช้ DO WHILE ร่วมกับ REPLACE ก็รอดมาได้ แต่ต่อมามาใช้ SQL ก็ดูเหมือนว่าชีวิตจะสะดวกสบายขึ้น โดยเฉพาะการปรับปรุงค่าในฟิลด์ของ Tabel_1 ด้วยค่าในฟิลด์ของ Table_2 ง่ายกว่าการใช้ DO WHILE ร่วมกับ REPLACE แบบเดิมๆมากมายมหาศาลเชียวล่ะ อยากรู้ก็อ่านต่อไปครับว่าทำได้ยังไง เค้าว่าตัวอย่างที่ดีมีค่ากว่าคำสอน ดังนั้น...เอาตัวอย่างไปครับ * เปิด table USE old_value IN 0 USE new_value IN 0 * สั่ง update field_name ใน old_value ด้วย field_name จาก new_value UPDATE old_value ; FROM  new_value  ; WHERE  old_value   .keyfield  =  new_value   .keyfield ; SET  old_value   .field_name =  new_value   .field_name * สังเกตผล SELECT old_value BROWSE จากตัวอย่างที่เห็นข้างต้นนี้ เราเปลี่ยนค่าในฟิลด์ที่ชื่อว่า field_name ของตาราง old_value ด้วยค่าใน field_name ของตาราง new_value ซึ่งแน่นอนว่าต้องระบุลงไปให้ชัดเจนใน SQL Command ด้วยว่าจะให้ฟิลด์ใดเป็นตัวอ้างอิงระหว่างกัน โดยระบุลงไปในคำสั่ง WHERE ได้เลยครับสะดวกมาก WHERE  old_value  . keyfi

ALEN นับความยาว Array ง่ายๆ

DIMENSION myArray(2,3)    && create an array of 2 rows and 3 columns ? ALEN(myArray)           && returns 6 (2*3 elements) ? ALEN(myArray,1)         && returns 2 (rows) ? ALEN(myArray,2)         && returns 3 (columns) ฟังก์ชั่น ALEN ของ VFP นั้นเราสามารถใช้ได้อย่างเบ็ดเสร็จทั้งนับคอลัมน์ นับแถว และความยาวทั้งหมด ง่ายมากๆเลยใช่ไหมล่ะครับ โดยเราอาจจะประยุกต์ใช้แสดงค่า Array โดยเขียนฟังก์ชั่นได้ดังข้างล่างนี้ครับ * แสดงค่าใน Array FUNCTION func_print_r PARAMETERS print_array maxrow = ALEN(print_array,1) maxcol = ALEN(print_array,2) FOR thisrow=1 TO maxrow ?thisrow,"" FOR thiscol=1 TO maxcol ??print_array(thisrow,thiscol) ??IIF(thiscol<>maxcol,",","") && เพิ่ม Comma คั่นท้ายหากยังไม่หมดทุก column NEXT thiscol NEXT thisrow ENDFUNC โดยวิธีการเรียกใช้ก็ใส่ @ เข้าไปหน้าชื่อ Array ที่ต้องการแสดงค่าเพื่อให้ส่งไปแบบอ้างอิง Pointer นั่นเองครับ =func_print_r(@test) ถือว่าเป็นตัวอย่างอย

เก็บเฉพาะชื่อไฟล์ .dbf (และอื่นๆ) โดยไม่เอา path

ปกติเรามีคำสั่ง dbf() ที่ใช้เก็บชื่อไฟล์ dbf และมันให้ path มาด้วย  ซึ่งบางครั้งไม่ใช่สิ่งที่เราต้องการ เราจึงอยากจะแยกมันเอามาเฉพาะชื่อไฟล์ และทำได้ 2 ขั้นตอนคือ 1. หาตำแหน่งที่เป็นจุดแบ่งระหว่างสิ่งที่จะตัดออกและสิ่งที่จะเอาไว้ ซึ่งอาจใช้ฟังก็ชั่น AT หรือ RAT ก็ได้ครับ (แต่งานนี้ผมใช้ RAT) คือ - ใช้ฟังก์ชั่น AT ร่วมกับประโยค do ... while เพื่อวนหา / ตัวสุดท้าย - ใช้ฟังก์ชั่น RAT ค้นหา / ตัวสุดท้ายซะเลย ทั้ง AT และ RAT เป็นฟังก์ชั่นที่ใช้ไล่หาตัวอักษรที่เราระบุ แล้วคืนค่ากลับมาว่าเป็นตัวอักษรที่เท่าไหร่ เราจะได้ตัดมันออกได้ตรงประเด็น ซึ่งจะเห็นว่างานนี้ AT จะยุ่งยากกว่า RAT มากเพราะว่า AT มันไล่หาจากด้านซ้ายไปด้านขวาครับ ส่วน RAT นั้นจะทำสลับกัน 2. เมื่อหาเจอจุดแบ่งของสิ่งที่จะตัดออก หรือจะเอาไว้แล้วก็ใช้ฟังก์ชั่น LEFT , RIGHT หรือ SUBST ในการดึงมันออกมาครับ (ในงานนี้ผมใช้ RIGHT เพราะดึงจากด้านขวาเข้าไปโดยไม่ต้องระบุความยาว จากหลักการข้างต้นเขียนเป็นคำสั่งได้ว่า... fname = RIGHT(dbf(), LEN(dbf())-RAT("\", dbf())) สำหรับท่านที่จะเอาเฉพาะชื่อไฟล์ โดยไม่เอานามสกุล ห

VFP ใช้ GROUP BY ได้ไหม?

VFP 8/9 ใช้หลักของ ANSI SQL (1992) จึงมีการตรวจสอบว่าอนุคำสั่ง GROUP BY  จะใช้ได้เมื่อทุกฟิลด์/คอลัมน์ไม่เป็น Aggregate Field (นัยยะหมายถึงพวกที่ต้องคำนวณหาทั้งหลาย เช่น sum(total) , max , min นั่นแหละ) ไม่เช่นนั้นจะถือว่าใช้คำสั่งผิด ซึ่งเราอาจตั้งค่าให้ไม่ต้องตรวจสอบเรื่องนี้ได้โดยใช้คำสั่ง SET ENGINEBEHAVIOR 70 โดยไว้ก่อนจะสั่งคำสั่งที่ใช้ GROUP BY ครับ ผมยังไม่มีเวลาหาข้อมูลต่อว่า เพราะอะไรเค้าถึงไม่ยอมให้ใช้ (เฉพาะ VFP นี่แหละ) ดังนั้นแนะนำว่าถ้าไม่ชัวร์ก็พยายามเลี่ยงนะครับ เพราะเค้าก็ต้องมีเหตุผลของเค้าแหละซึ่งมันอาจผิดพลาดได้ง่ายสำหรับกรณีแบบนี้ เราควรหาทางอื่นดีกว่าซึ่งทำได้เยอะแยะไป ไม่งั้นเกิดทำมึนๆใช้ๆไป ทำไปเยอะๆใช้ไปนานๆเข้าไปแล้วเจอ Runtime Error / Bug เข้าในตอนที่ลืมไปแล้วจะยุ่งและไม่คุ้มเสียครับ เว้นแต่ว่าคุณรู้ว่าคุณกำลังทำอะไร ^_^ เจอกันตอนหน้าครับ สวัสดี

การใช้ Array ร่วมกับ Function

เพื่อทดสอบการใช้ VFP ร่วมกับตัวแปรประเภท Array ผมจึงเขียนคำสั่งดังข้างล่างนี้เพื่อทดสอบการใช้งาน Array ทั้งส่งข้อมูลเข้าไปใน Function และการรับค่า Array ที่คืนจาก Function ออกมาใช้งานต่อ แยกเป็นส่วนๆได้ดังนี้ * สร้างตัวแปร myarray ให้เป็น array แล้วกำหนดค่าเป็น A,B ตามลำดับ DIMENSION myarray[2] myarray[1]="A" myarray[2]="B" * ทดลองพิมพ์ออกมาดูว่าเก็บค่าอยู่จริงมั๊ย ?"test print array value" for i=1 to alen(myarray) ?i,myarray[i] next i * ส่งค่าไปใช้ในฟังก์ชั้น do print_r with myarray * การรับค่า array คืนจากฟังก์ชั่น dime pointer[5] && ต้องประกาศตัวแปร array ที่จะเป็นตัว contrainer (ส่งค่าไปและรับค่ากลับ) ขึ้นมาก่อน pointer = returnarray(@pointer) && จากนั้นส่ง pinter ของตัวแปร array ที่จะเป็นตัว contrainer ไปยังฟังก์ชั่น * ค่าที่รับมาแบบ pointer จะเป็น array หรือไม่ก็ได้ แต่กรณีนี้เป็น array เพราะฟังก์ชั่นคืนค่า pointer ของตัวแปร array กลับมา * ทดลองพิมพ์ค่าออกมาดูว่าเก็บค่าอะไรไว้ do print_r with pointer return * ฟังก

VFP index tag มีอยู่จริงหรือเปล่า?

ไปเจอมาจากเว็บ foxite.com   ครับ เอามาเก็บไว้ก่อน ส่วนจะใช้ได้ผลยังไงหรือไม่นั้น..แหะๆลองแล้วบอกกันมั่งนะครับ ฮี่ฮี่ฮี่ How can I check if a given file has an index available for use? * Passed the name of an index tag * returns true if it is a tag for the specified table. * Uses table in the current work area if no table name is passed. FUNCTION IsTag( tcTagName, tcTable ) LOCAL ARRAY laTags[1] LOCAL llRetVal *** Did we get a tag name? IF TYPE( 'tcTagName' ) # 'C' *** Error - must pass a Tag Name ERROR '9000: Must Pass a Tag Name when calling ISTAG()' RETURN .F. ENDIF *** How about a table alias? IF TYPE( 'tcTable' ) = 'C' AND ! EMPTY( tcTable ) *** Get all open indexes for the specified table ATagInfo( laTags, "", tcTable ) ELSE *** Get all open indexes for the current table ATagInfo( laTags, "" ) ENDIF *** Do a Case Insensitive, Exact=ON, Scan of the first column of arr