ABAP - 8 ตอน รู้จักภาษา ABAP เปิดเบื้องหลังของ SAP R/3

ภาคต่อของ Internal Table และ Selection Screen

เนื้อหาเกี่ยวกับ ABAP Programming ที่ผ่านมา น่าจะทำให้หลายท่านเข้าใจการเขียนโปรแกรม ABAP ในระบบ SAP มากขึ้น ไม่มากก็น้อย และถ้าใครได้ติดตามเนื้อหา ABAP มาอย่างต่อเนื่อง ผมคิดว่าคุณพร้อมแล้วที่จะเข้ามาในโลกของการพัฒนาระบบงาน SAP โดยใช้ภาษา ABAP เพราะเนื้อหาส่วนสำคัญที่สุด ก็คือส่วนของคำสั่ง Open SQL นั่นเอง โปรแกรม ABAP ทุกโปรแกรมที่เราเขียนขึ้นมานั้น ไม่พ้นที่จะต้องมีการอ่านข้อมูลจาก Database Server ของระบบ SAP และสำหรับเนื้อหาในฉบับนี้ ผมจะพูดถึงเรื่องของหน้าจอ Selection Screen ต่อไปจากเรื่องของ Internal Table


การเรียงลำดับข้อมูลใน Internal Table

เราจะใช้คำสั่ง Sort ในการเรียงลำดับข้อมูลใน Internal Table เช่น หลังจากมีข้อมูลที่ Internal Table เรียบร้อยแล้ว ถ้าเราต้องการเรียงลำดับของข้อมูลตามชื่อของลูกค้า เราสามารถเขียนโปรแกรมได้ดังต่อไปนี้

Data itab like customers occurs 0 with header line.
Select * from customers into table itab.
Sort itab by name.

และถ้าต้องการเรียงลำดับของข้อมูลจากมากไปหาน้อย ก็ให้ใช้ออปชัน descending เช่น

Sort itab by name descending.

ดังนั้น ที่ผมเคยกล่าวไว้ในเรื่องเกี่ยวกับคำสั่ง Select ว่า เราไม่ควรใช้ออปชัน Order by ของคำสั่ง Select ในการเรียงลำดับข้อมูลของตารางในฐานข้อมูล เพราะความเร็วในการทำงาน (Performance) จะไม่ค่อยดีสักเท่าไร เพราะเป็นการเรียงลำดับของข้อมูลที่ Database Server ทางแก้ก็คือ ให้ทำการอ่านข้อมูลมาเก็บไว้ที่ Internal Table จากนั้นค่อยสั่งเรียงลำดับของข้อมูลจากคำสั่ง Sort ต่อไป วิธีนี้จะดีกว่าเพราะเป็นการเรียงลำดับของข้อมูลที่ Memory Space นั่นเอง

การอ่านข้อมูลจาก Internal Table

การอ่านข้อมูลจาก Internal Table มีอยู่ 2 วิธีด้วยกันคือ การอ่านแบบ Multiple Record และแบบ Single Record มาดูแบบแรกกันก่อน โดยที่การอ่านข้อมูลจาก Internal Table ในแบบ Multiple Record นั้น เราจะใช้คำสั่ง Loop at ... Endloop เช่น

Data itab like customers occurs 0 with header line.
Select * from customers into table itab.
Loop at itab.
Write: / itab-id, itab-name.
Endloop.

หน้าที่ของคำสั่ง Loop at ก็คืออ่านข้อมูลใน Internal Table ตามที่ระบุใน เรคอร์ดที่พอยน์เตอร์ (Pointer) ชี้อยู่ (ถ้าเป็นการอ่านเรคอร์ดแรก พอยน์เตอร์จะชี้อยู่ที่เรคอร์ดแรก) จากนั้นระบบจะคัดลอกข้อมูลทั้งแถวมาไว้ที่ Header Line ดังรูปที่ 13
รูปที่ 13
จากนั้นก็จะเป็นการทำงานคำสั่งภายในบล็อก Loop at ... Endloop ซึ่งก็คือคำสั่ง Write: / itab-id, itab-name โดยที่หน้าที่ของคำสั่ง Write ยังคงเหมือนเดิมคือ นำข้อมูลจาก Memory Space ตามที่ระบุ ซึ่งในที่นี้คือ itab-id และ itab-name จาก Header Line ไปเขียนไว้ที่ Buffer List ที่ Local Memory ของ Work Process นั่นเอง ดังที่ผมได้กล่าวไว้ก็คือ การทำงานกับ Internal Table นั้น ทุกคำสั่งจะทำงานกับ Header Line เท่านั้น ซึ่งจริงๆ แล้ว Header Line ของ Internal Table ก็คือ Structure ธรรมดา

จากนั้นเมื่อพบคำสั่ง Endloop ระบบก็จะเช็กว่ามีข้อมูลเรคอร์ดถัดไปที่จะต้องอ่านอีกหรือไม่ ถ้ามีก็จะเลื่อน Pointer ไปยังเรคอร์ดถัดไป จากนั้นก็จะโอนการทำงานกลับไปยังคำสั่ง Loop at เพื่ออ่านข้อมูลไปไว้ที่ Header Line ต่อไป การทำงานก็จะเป็นเช่นนี้ ไปจนกระทั่งหมดข้อมูลใน Internal Table แล้วโปรแกรมก็จะข้ามไปทำงานยังคำสั่งถัดจาก Endloop นั่นเอง ถ้าเราสังเกตดีๆ จะพบว่า การทำงานของคำสั่ง Loop at ... Endloop จะคล้ายกับการทำงานของคำสั่ง Select ... Endselect ทุกประการ แตกต่างกันตรงที่ว่า คำสั่ง Select เป็นการอ่านข้อมูลที่ Result Set ในพื้นที่ของ DB Interface แต่คำสั่ง Loop at จะเป็นการอ่านข้อมูลจากเนื้อข้อมูลของ Internal Table ใน Memory Space

ดังนั้นการอ่านข้อมูลจากตารางในฐานข้อมูลมาเก็บไว้ที่ Internal Table จากนั้นก็ใช้คำสั่ง Loop at ในการอ่านข้อมูลจาก Internal Table จะมีความเร็วสูงกว่า การอ่านข้อมูลจากตารางในฐานข้อมูลโดยตรงจากคำสั่ง Select นอกจากนี้เรายังใช้ตัวแปรระบบที่ชื่อ sy-tabix ในการแสดงค่ารอบปัจจุบันของการวนลูปในบล็อกของ Loop at ... Endloop (เหมือนกับค่า sy-index ในบล็อกของ Do กับ WHILE หรือ sy-dbcnt ในบล็อกของ Select... Endselect) แต่ตัวแปรระบบ sy-tabix นั้น สามารถใช้ได้เฉพาะภายในบล็อกของ Loop at ... Endloop เท่านั้น ซึ่งจะแตกต่างจากตัวแปรระบบ sy-dbcnt ที่เราใช้งานนอกบล็อก Select ... Endselect ได้

นอกจากนี้ ในคำสั่ง Loop at ยังใช้ Where Clause ในการกรองข้อมูลได้ตามปกติเหมือนกับคำสั่ง Select เช่น

Loop at itab where id > 1. หรือ
Loop at itab where name < > 'John'.

สำหรับการใช้ Template หรือ Wildcard ใน Where Clause ของคำสั่ง Loop at เราจะใช้ค่า * แทนตัวอักษรอะไรก็ได้กี่ตัวก็ได้ (เหมือนกับค่า % ของคำสั่ง Select) และ + แทนตัวอักษรอะไรก็ได้หนึ่งตัว (เหมือนกับค่า _ ของคำสั่ง Select) เช่น ถ้าเราต้องการอ่านข้อมูลของ Internal Table เฉพาะชื่อของลูกค้าที่ตัวอักษรตัวที่สองเป็นค่า a เราสามารถเขียนคำสั่งได้ดังนี้

Loop at itab where name cp '+a*'.

โดยที่เราจะใช้ cp แทน = ใน Where Clause (เหมือนกับ Like ของคำสั่ง Select) สำหรับการอ่านข้อมูลใน Internal Table แบบ Single Record นั้น เราจะใช้คำสั่ง Read Table เช่น ถ้าต้องการอ่านข้อมูลจาก Internal Table สำหรับค่า id มีค่าเท่ากับ 1 เราสามารถเขียนคำสั่งได้ดังนี้

...
Read table itab with key id = 1.
If sy-subre = 0.
Write: / itab-id, itab-name
Endif.

การทำงานของคำสั่ง Read Table นั้น ระบบจะอ่านข้อมูลที่ Internal Table ตามเงื่อนไข ถ้าพบข้อมูลที่ต้องการ ระบบก็จะคัดลอกข้อมูลของเรคอร์ดนั้นๆ ที่เนื้อข้อมูลของ Internal Table ไปไว้ที่ Header Line ของ Internal Table พร้อมทั้งให้ค่าศูนย์กับตัวแปรระบบ sy-subrc แต่ถ้าไม่พบข้อมูลค่าของตัวแปรระบบ sy-subrc ก็จะได้ค่าที่มากกว่าศูนย์ และจะไม่มีการแตะต้อง Header Line ของ Internal Table แต่อย่างใด เช่นเดียวกัน การทำงานของคำสั่ง Read Table นั้นจะคล้ายกันกับคำสั่ง Select Single นั่นเอง สำหรับการอ่านข้อมูลที่มีเงื่อนไขมากกว่าหนึ่งฟิลด์ เราจะไม่ใช้ and ใน Where Clause เช่น

...
Read table itab with key name = 'John'
City = 'New York'.

และถ้าต้องการให้การอ่านข้อมูลแบบ Single Record ใน Internal Table มีประสิทธิภาพดีที่สุด ในกรณีที่ข้อมูลใน Internal Table มีปริมาณมาก เราสามารถใช้ออปชัน Binary Search ได้ เช่น

...
Sort itab by name.
Read table itab with key name = 'David'
binary search.

แต่ก่อนที่จะใช้ออปชัน Binary Search ได้นั้น เราจะต้องเรียงลำดับข้อมูลตามค่าฟิลด์ที่ระบุในออปชัน with key ของคำสั่ง Read Table เสียก่อน มิฉะนั้นเราอาจได้ข้อมูลผิดๆ ไปก็ได้ แล้วพบกันใหม่ในตอนหน้าครับ

Selection Screen

การเขียนโปรแกรม ABAP ที่ผ่านมานั้น เรายังไม่มีส่วนของการปฏิสัมพันธ์กับผู้ใช้ระบบแต่อย่างใด ก็คือเมื่อเราสั่งเอ็กซิคิวต์โปรแกรม ABAP เราก็จะได้หน้าจอ List โดยทันที เมื่อโปรแกรม ABAP ถูกประมวลผลในทุกคำสั่งเสร็จสิ้นโดยสมบูรณ์ แต่ถ้าเรา ต้องการให้โปรแกรมมีการปฏิสัมพันธ์กับผู้ใช้ระบบ เช่น ให้ผู้ใช้ระบบใส่เงื่อนไขที่ต้องการแสดงข้อมูล จากนั้นเมื่อสั่งเอ็กซิคิวต์โปรแกรม ก็จะได้ข้อมูลใน List ตามเงื่อนไขที่ได้ระบุไว้ ซึ่งในส่วนของการปฏิสัมพันธ์กับผู้ใช้ระบบนี้ ในภาษา ABAP นั้น จะมีคำสั่งอยู่สองคำสั่งด้วยกัน ในการสร้างหน้าจอที่มีการปฏิสัมพันธ์กับผู้ใช้ระบบ ก็คือคำสั่ง Parameters กับคำสั่ง Select-options ซึ่งหน้าจอที่ได้จากการทำงานของสองคำสั่งนี้ เราจะเรียกว่าหน้าจอ Selection Screen

คำสั่ง Parameters

คำสั่ง Parameters เป็นคำสั่งที่ใช้ในการสร้างหน้าจอ Selection Screen โดยที่เราจะได้ช่อง Input ให้ผู้ใช้ระบบใส่ข้อมูลลงไป เช่นตัวอย่างโปรแกรมดังต่อไปนี้

Parameters: tmp1(10) type c,
tmp2(5) type n,
tmp3 like sy-datum,
id like customers-id.

เมื่อสั่งเอ็กซิคิวต์โปรแกรมข้างต้น เราจะได้หน้าจอ Selection Screen ดังรูปที่ 1
รูปที่ 1
จากโปรแกรมในตัวอย่างแรกของเรา เห็นได้ว่ามี Input อยู่สี่ช่องด้วยกัน ซึ่งถ้าเราดูรูปแบบหรือซินแท็กซ์ของคำสั่ง Parameters แล้วจะพบว่ามีรูปแบบของคำสั่งเหมือนกับคำสั่ง Data ซึ่งเป็นคำสั่งที่ใช้ในการสร้างตัวแปรทุกประการ ใช่ครับ ที่จริงแล้วคำสั่ง Parameters นั้นเป็นคำสั่งที่ใช้ในการสร้างตัวแปรหรือ Variable เหมือนกับคำสั่ง Data นั่นเอง โดยส่วนที่แตกต่างออกไปคือในคำสั่ง Parameters ระบบจะสร้างหน้าจอ Selection Screen ในการรอรับค่าข้อมูลของตัวแปรจากผู้ใช้ระบบที่หน้าจอนั่นเอง เราลองมาดูขั้นตอนของระบบในการทำงานของคำสั่ง Parameters สมมติว่าเราต้องการเอ็กซิคิวต์โปรแกรมดังต่อไปนี้

Report ztest.
Parameters tmp(10) type c.
Write: / tmp.

เมื่อเอ็กซิคิวต์โปรแกรม ระบบจะทำการสร้างตัวแปร tmp ที่ Memory Space ดังรูปที่ 2
รูปที่ 2
จากนั้นระบบจะสร้างหน้าจอ Selection Screen สำหรับรอรับข้อมูลของตัวแปร tmp ดังรูปที่ 3
รูปที่ 3
จากนั้นเมื่อเราใส่ข้อมูลของตัวแปร tmp สมมุติว่าเป็นค่า abcd ดังรูปที่ 4
รูปที่ 4
เมื่อกดปุ่ม Execute ระบบจะนำค่าข้อมูลที่เราใส่จากหน้าจอ Selection Screen ไปกำหนดค่า (Assign) ให้กับตัวแปรที่ Memory Space ดังรูปที่ 5
รูปที่ 5
จากรูป Memory Space ที่ได้ จะเห็นว่าระบบได้เปลี่ยนข้อมูลของตัวแปรชนิด C ให้เป็นตัวใหญ่ (Upper Case) เสมอ เมื่อ Assign ค่าข้อมูลจากหน้าจอ Selection Screen ไปที่ Memory Space ถ้าไม่ต้องการให้ระบบเปลี่ยนข้อมูลของตัวแปรชนิด C ก็ให้ระบุออปชัน lower case ในคำสั่ง Parameters เช่น

Parameters tmp(10) type c lower case.

ภายหลังจากที่ระบบ Assign ค่าข้อมูลของตัวแปรจากหน้าจอ Selection Screen ไปที่ Memory Space เรียบร้อยแล้ว ระบบก็จะประมวลผลคำสั่ง ABAP ถัดไปคือ write: / tmp. ซึ่งหมายถึงการนำข้อมูลของตัวแปร tmp จาก Memory Space ไปเขียนที่ List Buffer เพื่อแสดงข้อมูลที่หน้าจอของผู้ใช้ระบบต่อไป จะเห็นได้ว่าคำสั่ง Parameters เป็นคำสั่งที่ใช้ในการสร้างตัวแปร ดังนั้นเราจึงควรที่จะเขียนคำสั่ง Parameters นี้ ไว้ที่ส่วนต้นของโปรแกรมเหมือนกับคำสั่ง Data และตัวแปรที่ได้จากคำสั่ง Parameters จะเหมือนกับตัวแปรที่ได้จากคำสั่ง Data ทุกประการ

ถ้าเราต้องการให้ค่าเริ่มต้นหรือค่าดีฟอลต์ (Default) ของตัวแปรที่สร้างจากคำสั่ง Parameters ให้ใช้ออปชัน default (คล้ายกับออปชัน value ของคำสั่ง Data โดยที่เราสามารถใช้ตัวแปรใดๆ ในการให้ค่าเริ่มต้นกับตัวแปร Parameters ได้ เช่น default sy-datum แต่ออปชัน value ทำเช่นนี้ไม่ได้) เช่น

Parameters today like sy-datum default sy-datum.

เราจะได้ข้อมูลที่ Memory Space ดังรูปที่ 6
รูปที่ 6
แล้วเราจะได้หน้าจอ Selection Screen ดังรูปที่ 7
รูปที่ 7
จากนั้นถ้าราใส่ค่าตัวแปร today ใหม่ที่หน้าจอ Selection Screen เช่น 31122003 (ที่หน้าจอ Selection Screen ของตัวแปรชนิด D เราจะต้องใส่ค่าข้อมูลตาม User Default : Date Format) ดังรูปที่ 8
รูปที่ 8
เมื่อเราสั่งเอ็กซิคิวต์ ระบบก็จะ Assign ค่าตัวแปร today ที่เราใส่ไปที่หน้าจอ Selection Screen ให้กับตัวแปร today ที่ Memory Space ดังรูปที่ 9 และถ้ามีคำสั่งถัดไป ระบบก็จะทำงานในคำสั่งนั้นต่อไปตามปกติ)
รูปที่ 9
ถ้าเราต้องการให้ผู้ใช้ระบบต้องใส่ข้อมูลของตัวแปรใดๆ ที่หน้าจอ Selection Screen เสมอ ถ้าไม่ใส่จะไม่ยอมให้ผ่านการทำงานของหน้าจอ Selection Screen ไปทำงานในคำสั่งถัดไป ซึ่งก็เหมือนกับการทำ Require Field ก็ให้เราใช้ออปชัน obligatory ในคำสั่ง Parameters เช่น

Parameters tmp(10) obligatory.

ถ้าเราไม่ระบุชนิดของตัวแปรจากออปชัน type ในคำสั่ง Parameters ระบบจะถือว่าเป็นตัวแปรชนิด C และถ้าไม่ระบุ Length ระบบก็จะถือว่าเป็นค่า 1 ไปโดยปริยาย ซึ่งจากการระบุออปชัน obligatory ในคำสั่ง Parameters ทำให้เราไม่สามารถผ่านหน้าจอ Selection Screen ไปทำงานคำสั่งถัดไปได้ หากไม่ใส่ข้อมูลของตัวแปร tmp ที่หน้าจอ Selection Screen โดยที่ระบบจะแสดงข้อความ Make an entry in all required fields ที่บรรทัด Status Line ดังรูปที่ 10
รูปที่ 10
นอกจากนี้เรายังสามารถสร้างปุ่ม Check Box กับ Radio Button ได้เช่น

Parameters: check1 as checkbox,
check2 as checkbox default 'X',
radio1 radiobutton group test,
radio2 radiobutton group test.

ตัวแปร Check Box กับ Radio Button ที่ได้ใน Memory Space นั้น จะเป็นชนิด C และมี Length เป็นค่า 1 เสมอ

ที่มา : http://www.arip.co.th/articles.php?id=406417

ไม่มีความคิดเห็น:

แสดงความคิดเห็น