https://lentera.uin-alauddin.ac.id/question/gratis-terlengkap/https://old-elearning.uad.ac.id/gampang-menang/https://fk.ilearn.unand.ac.id/demo/https://elearning.uika-bogor.ac.id/tanpa-potongan/https://e-learning.iainponorogo.ac.id/thai/https://organisasi.palembang.go.id/userfiles/images/https://lms.binawan.ac.id/terbaik/https://disperkim.purwakartakab.go.id/storage/https://pakbejo.jatengprov.go.id/assets/https://zonalapor.fis.unp.ac.id/-/slot-terbaik/https://sepasi.tubankab.go.id/2024tte/storage/http://ti.lab.gunadarma.ac.id/jobe/runguard/https://satudata.kemenpora.go.id/uploads/terbaru/
รู้จักภาษา ABAP เปิดเบื้องหลังของ SAP R/3 ตอน 2 MUSLIMTHAIPOST

 

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


27,521 ผู้ชม


ภาษา ABAP (อ่านว่าอาบับ) หรือชื่อเต็มๆ ของมันก็คือ Advance Business Application Programming เป็นภาษาโปรแกรมที่อยู่เบื้องหลังระบบ SAP ซึ่งก็คือแอพพลิเคชันทั้งหมดทุกโมดูลในระบบ SAP นั้น ถูกพัฒนาขึ้นมาจากภาษาโปรแกรม ABAP ซึ่งเป็นภาษาโปรแกรมของ SAP

พื้นที่โฆษณา  
สนใจลงโฆษณา ติดต่อ โทร.0-2642-3400 ต่อ 4613

ภาษา ABAP (อ่านว่าอาบับ) หรือชื่อเต็มๆ ของมันก็คือ Advance Business Application Programming เป็นภาษาโปรแกรมที่อยู่เบื้องหลังระบบ SAP ซึ่งก็คือแอพพลิเคชันทั้งหมดทุกโมดูลในระบบ SAP นั้น ถูกพัฒนาขึ้นมาจากภาษาโปรแกรม ABAP ซึ่งเป็นภาษาโปรแกรมของ SAP มีบางคนบอกว่าภาษา ABAP เป็นภาษาโปรแกรมที่เขียนยากมาก แต่ในความรู้สึกของผมนะครับ ถ้าคุณเข้าใจการทำงานของมันแล้ว ภาษา ABAP ก็จะเป็นเรื่องง่ายสำหรับคุณ บทความของผมต่อจากนี้ไป จะเป็นการนำเสนอการเขียนโปรแกรม ABAP ในแนวทางที่ถูกต้อง ตามขั้นตอนที่ผมคิดว่า จะช่วยให้คุณเขียนโปรแกรม ABAP ได้อย่างไม่ยากเย็น ลองติดตามดูนะครับ แล้วคุณจะรู้สึกเหมือนกับอีกหลายคนว่า ทำไม ABAP ถึงง่ายขนาดนี้”

เคอร์เนลของ SAP R/3

ถึงแม้ว่าภาษา ABAP จะใช้ในการพัฒนาระบบ SAP ทั้งหมด แต่เบื้องหลังการทำงานของระบบ SAP อย่างแท้จริง ก็คือ เวิร์กโพรเซส (Work Process) หรือที่เรียกว่าเคอร์เนล (Kernel) ของระบบ SAP ซึ่งพัฒนาขึ้นมาจากภาษา C หรือ C++ และทำหน้าที่นำโปรแกรม ABAP ที่เราต้องการเอ็กซีคิวต์ (Execute) มาประมวลผลที่แอพพลิเคชันเซิร์ฟเวอร์ (Application Server)
รูปที่ 1 องค์ประกอบ 4 ส่วนของเวิร์กโพรเซส

ในระบบ SAP R/3 โดยที่เวิร์กโพรเซสในระบบ SAP R/3 จะประกอบไปด้วยองค์ประกอบ 4 ส่วนคือ TaskHandler, ABAP Processor, DYNPRO Processor และ DB Interface

TaskHandler เป็นส่วนที่คอยพิจารณาโปรแกรม ABAP ที่ต้องการเอ็กซิคิวต์ในโปรแกรมบัฟเฟอร์ (Program Buffer) บนแอพพลิเคชันเซิร์ฟเวอร์ (Application Server) ในแต่ละสเตจเมนต์ (Statement) ตามลำดับ โดยมันจะพิจารณาสเตจเมนต์ (ABAP Statement) นั้นว่าเป็นคำสั่งประเภทอะไร ถ้าเป็นคำสั่งประเภท ABAP ส่วน TaskHandler ก็จะส่งสเตจเมนต์นั้นให้กับ ABAP Processor เพื่อประมวลผลต่อไป และถ้าเป็นคำสั่งที่เกี่ยวข้องกับสกรีนโพรเซสซิง (Dialog Program) ส่วนของ TaskHandler ก็จะโอนการทำงานในส่วนนี้ให้กับ DYNPRO (Dynamic Program) Processor ประมวลผลงานในส่วนนี้ แต่ถ้า TaskHandler พบว่าคำสั่งที่ต้องการทำงาน เป็นคำสั่งประเภท Open SQL มันก็จะส่งคำสั่ง Open SQL นี้ให้กับ DB Interface เพื่อประมวลผลคำสั่ง Open SQL ต่อไป ซึ่งหมายความว่า DB Interface จะช่วยแปลง Open SQL ของ SAP ให้เป็น SQL ชนิดมาตรฐานหรือ Native SQL ของระบบดาต้าเบสเซิร์ฟเวอร์ต่อไป

สำหรับส่วน Local Memory จะเป็นพื้นที่หน่วยความจำของเวิร์กโพรเซส ซึ่งใช้เก็บข้อมูลที่ได้จากการประมวลผลคำสั่ง ABAP ต่างๆ โดยที่จะมีส่วนที่เรียกว่า Memory Space ที่จะเป็นพื้นที่เก็บข้อมูลดาต้าออบเจ็กต์ (Data Object) ต่างๆ ของโปรแกรม ABAP ที่กำลังทำงานอยู่ และพื้นที่ Local Memory นี้จะถูกเคลียร์ทิ้งเมื่อจบการทำงานของโปรแกรม ABAP
รูปที่ 2 องค์ประกอบใน Memory space

เริ่มต้นกับภาษา ABAP

หลังจากที่เราทราบการทำงานของเคอร์เนลในระบบ SAP กันแล้ว จากนี้ไปเราก็จะเริ่มลุยการเขียนโปรแกรม ABAP โดยที่ภาษา ABAP ก็เหมือนกับภาษาโปรแกรมทั่วไป ซึ่งประกอบไปด้วยคำสั่งที่ใช้ในการสร้างตัวแปร คำสั่งที่ใช้ในการคำนวณหรือเปรียบเทียบต่างๆ และคำสั่งที่ใช้ในการเข้าถึงข้อมูลในระบบฐานข้อมูล ที่เรียกว่า Open SQL ซึ่งเป็นภาษา SQL ของระบบ SAP แต่ก่อนจะเริ่มเรียนรู้การเขียนโปรแกรม ABAP เราจะต้องทราบเสียก่อนว่าดาต้าออบเจ็กต์ที่คำสั่ง ABAP จะทำงานกับมันใน Memory Space นั้นประกอบไปด้วย Variable, Structure, Table Structure และ Internal Table

คำสั่ง ABAP เกือบทั้งหมด จะทำงานกับดาต้าออบเจ็กต์เหล่านี้ใน Memory Space ของมันเท่านั้น ดังนั้นการที่เราเขียนโปรแกรม ABAP อย่างเข้าใจการทำงานของคำสั่งต่างๆ เราจะต้องเห็นภาพของดาต้าออบเจ็กต์ที่เราสร้างขึ้นมาที่ Memory Space เสียก่อน
ชนิดของข้อม๔ลในภาษา ABAP

ในภาษา ABAP จะมี Data Type หรือชนิดของข้อมูลทั้งหมด 10 ชนิด โดยที่ชนิดของข้อมูลที่ถูกใช้งานบ่อยในระบบ SAP ก็คือชนิด C, D, I, N และ P และชนิดของข้อมูลที่ควรจะทำความเข้าใจกับมันให้ดีก็คือ ชนิด N กับ D เพราะเป็นรูปแบบเฉพาะของระบบ SAP สำหรับรูปแบบโครงสร้างหรือ Syntax ของคำสั่งที่ใช้ในการสร้างตัวแปร (Variable) ของภาษา ABAP จะเป็นดังนี้

DATA var(length) TYPE <data type> VALUE <default value>.

โดย Statement ของภาษา ABAP นั้น จะต้องจบด้วยเครื่องหมาย . เสมอ เช่น

DATA temp1(10) TYPE C.
DATA temp2 TYPE I.
DATA temp3(8) TYPE P DECIMALS 2 VALUE ‘123.45’.

หรือเราเขียนโปรแกรมในรูปแบบ Colon Notation ก็คือ ยุบหลายๆ สเตจเมนต์ที่เหมือนกันให้เหลือแค่สเตจเมนต์เดียว เช่น

DATA: temp1(10) TYPE C,
temp2 TYPE I,
temp3(8) TYPE P DECIMALS 2 VALUE ‘123.45’.

โดยหลักการของการเขียนโปรแกรมแบบ Colon Notation ก็คือ คำสั่ง ABAP ที่เหมือนกันที่อยู่ติดกัน ให้รวมกันเหลือแค่คำสั่งเดียวแล้วตามด้วยเครื่องหมาย : จากนั้นส่วนที่แตกต่างจะคั่นด้วยเครื่องหมาย, สุดท้ายจะจบด้วยจุด (.) แต่เวลาระบบนำโปรแกรม ABAP ไปทำงาน ถ้า TaskHandler พบว่ามีคำสั่งไหนที่มี Colon Notation อยู่ มันจะแตกให้เป็นหลายสเตจเมนต์ตามรูปแบบปกติ ก่อนเริ่มต้นทำงานในคำสั่งสเตจเมนต์เหล่านั้น
รูปที่ 3 ดาต้าออบเจ็กต์ที่ได้จากการเอ็กซิคิวต์โปรแกรมตัวอย่าง

ข้อดีของการทำ Colon Notation ก็คือ เราจะเขียนโปรแกรมสั้นลง และประหยัดเนื้อที่ในการจัดเก็บซอร์สโค้ด (Source Code) ของโปรแกรมที่ดาต้าเบสเซิร์ฟเวอร์นั่นเอง

จากโปรแกรมตัวอย่าง เมื่อเราเอ็กซิคิวต์โปรแกรม เราจะได้ดาต้าออบเจ็กต์ที่ส่วนของ Memory Space ดังรูปที่3

หมายความว่า ABAP Processor จะสร้างตัวแปรที่ Memory Space พร้อมกับ Initial ค่าของตัวแปรตามชนิดข้อมูลของมัน โดยที่ถ้าเป็นข้อมูลประเภทตัวเลข ข้อมูลนั้นจะอยู่ชิดซ้าย ส่วนข้อมูลที่เป็น Character นั้น จะอยู่ชิดขวา แต่ถ้าเรามีการใช้ออปชัน VALUE ก็จะเป็นการกำหนดค่าดีฟอลต์ (Default) ให้กับตัวแปรเมื่อมีการสร้างตัวแปรนั่นเอง ถ้าลองสังเกตดีๆ จะพบว่าที่ตัวแปร temp3 จะมีการกำหนดค่าดีฟอลต์เป็นค่า ‘123.45’ การที่เราต้องใส่เครื่องหมาย ‘ ‘ ครอบตัวเลขก็เพราะว่า ค่า 123.45 นั้น มีเครื่องหมายจุดอยู่ด้วย ดังนั้นถ้าเราไม่ครอบค่าตัวเลข 123.45 ด้วยเครื่องหมาย ‘ ‘ ก็จะเกิด Syntax Error เพราะระบบจะมองตัวเลข 45 เป็นคำสั่งใหม่นั่นเอง

สำหรับค่าในวงเล็บสำหรับการสร้างตัวแปรนั้นก็คือค่า Length ของข้อมูลที่สามารถจัดเก็บได้ใน Memory Space ของตัวแปรแต่ละตัวนั่นเอง โดยที่ถ้าเราไม่ระบุ Length ของสร้างตัวแปรที่มีชนิดของข้อมูลเป็นชนิด C หรือ N ระบบจะให้ค่าดีฟอลต์ของ Length เป็น 1 เสมอ (สูงสุดได้ไม่เกิน 65,535) และถ้าเราไม่ระบุชนิดของข้อมูลในคำสั่งสร้างตัวแปร ระบบจะถือว่าเป็นชนิดข้อมูลประเภท C เสมอ และชนิดของข้อมูลชนิด I นั้น ในการสร้างตัวแปร ห้ามกำหนด Length โดยเด็ดขาด โดยที่ตัวแปรชนิด I จะเก็บค่าของข้อมูลสูงสุดได้ไม่เกิน -2,147,483,647 (-231 - 1) ถึง +2,147,483,648 (+231) สำหรับข้อมูลชนิด P นั้น ถ้าไม่ระบุ Length จะมีค่าดีฟอลต์เป็น 8 ซึ่งเราสามารถที่จะระบุค่า Length ของข้อมูลชนิด P นี้ได้อยู่ระหว่าง 1 - 16 และค่าจำนวนจุดทศนิยม (Decimals) ไม่เกิน 31 หลัก (ค่าดีฟอลต์ของจำนวนหลักจุดทศนิยมนั้นจะเป็น 0) และคำถามที่ว่า ข้อมูลที่มีชนิดของข้อมูลเป็นชนิด P นั้น สามารถจัดเก็บอยู่ใน Memory Space ได้ไม่เกินเท่าไร

ซึ่งจากตัวอย่างตัวแปร temp3 นั้น เราระบุค่า Length เป็น 8 แต่ความยาวของพื้นที่จัดเก็บข้อมูลใน Memory Space ของตัวแปร temp3 นั้น ไม่ใช่ 8 ไบต์แต่อย่างใด แต่จะเป็น 15 ไบต์ (ไม่รวมเครื่องหมายกับจุดทศนิยม) ซึ่งได้มาจากสูตร 2n - 1((2 * 8) - 1 = 15) นั่นเอง ดังนั้นตัวแปร temp3 จะเก็บข้อมูลได้ไม่เกิน 15 หลัก (ตัวเลขก่อนจุดทศนิยมรวมกับตัวเลขหลังจุดทศนิยมไม่เกิน 15 หลัก โดยที่ไม่รวมเครื่องหมาย . แต่อย่างใด)

ที่นี้เรามาดูตัวแปรที่มีชนิดของข้อมูลเป็นชนิด N ซึ่งเป็นชนิดของข้อมูลที่สร้างความสับสนให้กับหลายๆ คนที่ไม่คุ้นเคยกับภาษา ABAP กันพอสมควร โดยที่ตัวแปรที่มีชนิดของข้อมูลเป็นชนิด N นั้น จะเป็นตัวแปรที่เก็บข้อมูลเท็กซ์ (Text) ที่เป็นตัวเลขเท่านั้น ถ้ามีข้อมูลที่เป็น Space มันจะแทนค่าด้วย 0 แทน และมันจะไม่รับข้อมูลที่เป็น Character อื่นๆ ที่ไม่ใช่ตัวเลข ลองมาดูตัวอย่างต่อไปนี้

DATA temp(5) TYPE N.
temp = ‘aX5B12z’.

จากตัวอย่างข้างต้น เรามีการให้ค่า ‘aX5B12z’ กับตัวแปร temp ซึ่งมันจะรับเฉพาะตัวเลขเท่านั้น (Syntax ไม่ Error นะครับ) ส่วน Character อื่นนั้นมันไม่สนใจเลย และถ้ามีค่า Space มันจะแทนค่าด้วย 0 ทันทีที่ Memory Space โดยที่ตัวเลขที่มันจะเก็บค่า จะอยู่ชิดขวานะครับ ดังนั้นที่ Memory Space เราจะได้ค่าของข้อมูลดังรูปที่ 4
รูปที่ 4 ผลจากการระบุค่าให้ตัวแปร Temp

ถ้าเราต้องการแสดงข้อมูลที่หน้าจอ ก็ให้ใช้คำสั่ง WRITE temp. เราก็จะได้ข้อมูลของตัวแปร temp ที่หน้าจอ ซึ่งจะเห็นได้ว่า ในการให้ค่า ‘aX5B12z’ กับตัวแปร temp นั้น มันจะรับเฉพาะตัวเลขเท่านั้น ซึ่งในระบบ SAP จะใช้ชนิดข้อมูลชนิด N นี้ ในการจัดเก็บข้อมูลค่ารหัสต่างๆ เช่น รหัสลูกค้า หรือรหัสวัตถุดิบเป็นต้น ซึ่งข้อมูลชนิด N นี้ เราสามารถนำไปคำนวณได้ตามปกติ แต่ถ้าเราต้องการเก็บข้อมูลเพื่อใช้ในการคำนวณ ก็ขอแนะนำว่าให้ใช้ตัวแปรที่มีชนิดของข้อมูลเป็นชนิด I หรือ P จะเหมาะสมกว่า เพราะว่าถ้ามีการใช้ชนิดของข้อมูลชนิด N ในการคำนวณ ระบบจะทำการแปลงข้อมูลให้เป็นชนิดตัวเลขก่อนการคำนวณเสมอ

ต่อไปเรามาดูชนิดของข้อมูลชนิด D ซึ่งเป็นชนิดของข้อมูลที่เก็บข้อมูลวันที่กัน โดยที่ Internal Format ในการจัดเก็บข้อมูลชนิด D จะเป็นดังนี้

YYYYMMDD

คือมันจะเก็บปี 4 หลักตามด้วยเดือน 2 หลักและวันที่ 2 หลักตามลำดับ ลองมาดูตัวอย่างดังต่อไปนี้

DATA today TYPE D.
today = sy-datum.
WRITE today.

โดยที่ตัวแปร sy-datum (ฟีลด์ datum ของ Structure ที่ชื่อ sy) จะเป็นตัวแปรของระบบที่ให้ค่าวันที่ปัจจุบันออกมา โดยสมมติว่าวันนี้เป็นวันที่ 6 เดือน 8 ปี 2002 ที่ Memory Space เราจะได้ข้อมูลดังรูปที่ 5
รูปที่ 5 ผลจากการระบุค่าข้อมูล วันเดือนปี

และเมื่อเราใช้คำสั่ง WRITE today. ที่หน้าจอของเราจะได้ข้อมูลวันที่ในรูปแบบไหน? คำตอบก็คือ ข้อมูลวันที่หรือข้อมูลที่มีชนิดของข้อมูลเป็นชนิด D ที่แสดงบนจอภาพของไคลเอ็นต์ จะได้รูปแบบตาม User Default Format ซึ่ง Basis Administrator ของระบบ SAP ได้กำหนดไว้ให้ผู้ใช้ระบบ SAP แต่ละคนใน User Master Record ของระบบ SAP ดังนั้นถ้า Date Format ของผมเป็นวันเดือนปี ที่หน้าจอของผมจะได้ข้อมูล 06072002 แต่ถ้า Date Format ของผมเป็นเดือนวันปี ที่หน้าจอของผมก็จะได้ข้อมูล 08062002

เมื่อเราทราบ Internal Format ของการจัดเก็บข้อมูลชนิด D กันแล้ว ดังนั้นในการให้ค่าคงที่กับตัวแปรที่มีชนิดของข้อมูลเป็นชนิด D เราก็ควรให้ค่าคงที่ที่ถูกต้องตาม Internal Format เช่น

DATA today TYPE D.
today = ‘19991231’.

แต่ถ้าเราให้ค่าผิดๆ (Invalid Date) กับตัวแปรชนิด D แล้วมันจะรับหรือไม่? คำตอบก็คือรับครับผม โดยที่ Memory Space เราจะได้ข้อมูล cabcdefgh’ เรียงลงไป

DATA today TYPE D.
today = ‘abcdefgh’.

แล้วถ้าผมใช้คำสั่ง WRITE today. ที่หน้าจอผมจะได้ข้อมูลอะไร? คำตอบคือได้ค่า ghefabcd ทำไมจึงเป็นเช่นนี้ ที่เป็นเช่นนี้ก็เพราะมันมองข้อมูล 4 หลักแรกเป็นปี 2 หลักต่อมาเป็นเดือน และ 2 หลักต่อมาเป็นวันนั่นเอง ดังนั้นที่หน้าจอผมจึงได้ค่า ghefabcd (User Default Format ของผมเป็นวันเดือนปี)

สำหรับวิธีตรวจสอบข้อมูลชนิด D นี้ ใช้หลักการง่ายๆ ดังตัวอย่างต่อไปนี้

DATA today TYPE D.
today = ‘abcdefgh’.
today = today + 0.
IF today IS INITIAL.
WRITE: / ‘Invalid Date’.
ELSE.
WRITE: / today.
ENDIF.

โดยที่ถ้าข้อมูลของตัวแปร today เป็น Invalid Date (วันที่ที่ไม่มีอยู่จริง) เมื่อนำไปบวกด้วยค่า 0 ก่อนที่ระบบจะบวกค่าตัวเลข ก็จะแปลงรูปแบบวันที่ของตัวแปร today ให้เป็นตัวเลขของจำนวนวันที่นับตั้งแต่วันที่ 01 เดือน 01 ปี 0001 จากนั้นจึงนำไปบวกด้วยค่า 0 ต่อไป หลังจากนั้นระบบจะแปลงตัวเลขจำนวนวันให้กลับไปเป็นวันที่ ตามรูปแบบของ Gregorian Calendar เพื่อจัดเก็บใน Memory Space ต่อไป แต่ถ้าเป็น Invalid Date ก่อนที่จะมีการบวกกับค่า 0 ระบบจะเซ็ตค่าของตัวแปรนั้นๆ ให้เป็นค่า Initial ก่อนซึ่งก็คือค่า 00000000 เมื่อบวกกับ 0 ก็จะได้ 00000000 ซึ่งเป็นค่า Initial นั่นเอง สำหรับข้อมูลชนิด D นั้น เราสามารถบวกลบจำนวนวันได้ตามปกติ เช่น ถ้าเราต้องการทราบว่าอีก 10 วันถัดไป จะเป็นวันอะไร เราสามารถเขียนคำสั่งได้ดังนี้ (โดยที่ตัวแปรระบบ sy-datum มีชนิดของข้อมูลเป็นชนิด D นั่นเอง)

DATA today TYPE D.
today = sy-datum + 10.

คอมเมนต์ในภาษา ABAP

ในภาษา ABAP การเขียนคอมเมนต์ (Comment) ในโปรแกรมสามารถทำได้ 2 แบบดังนี้

1. Full Line Comment ที่คอลัมน์แรกของบรรทัดจะเป็นค่า *
2. Partial Line Comment ที่คอลัมน์ใดๆ ในบรรทัดนั้นจะมีค่า “ เช่น

*This is test program
DATA today TYPE D.
today = sy-datum. “Current Date

ที่บรรทัดแรกของโปรแกรมจะเป็นคอมเมนต์ และในบรรทัดที่ 3 ที่ส่วนของข้อความ Current Date จะเป็นคอมเมนต์เช่นเดียวกัน ก็คือระบบจะไม่นำคอมเมนต์เหล่านี้ไปประมวลผลแต่อย่างใด

คำสั่ง CLEAR

คำสั่ง CLEAR เป็นคำสั่งที่ใช้ในการเซ็ตค่าของข้อมูลที่ Memory Space ให้เป็นค่า Initial ตามชนิดของข้อมูล เช่นในตัวอย่างต่อไปนี้ สุดท้ายค่าของตัวแปร temp จะมีค่าเป็น 0 (Initial Value) ไม่ใช่ 9 (Default Value)

DATA temp TYPE I VALUE 9.
temp = 10.
CLEAR temp.

สำหรับบทเรียนแรก เรื่องของตัวแปรคงจะทำให้คุณเห็นภาพโครงสร้างของภาษา ABAP ไม่มากก็น้อยนะครับ ในการเขียนโปรแกรม ABAP ถ้าคุณเห็นภาพการทำงานในคำสั่งต่างๆ ที่ Memory Space จะทำให้คุณเข้าใจการเขียนโปรแกรม ABAP ได้ดียิ่งขึ้น ผมจะพยายามสอนคุณให้ทำหน้าที่เป็น ABAP Processor ที่จะนำคำสั่ง ABAP ต่างๆ ไปทำงาน โดยที่ผมจะไม่เน้นที่ Syntax ของภาษา ABAP แต่อย่างใด เพราะคุณสามารถเปิดดู Help ของระบบ SAP ได้ หรือถ้าใครไม่มีระบบ SAP ถ้าอยากดู Help ของระบบ SAP ก็สามารถเข้าไปดูได้ที่ help.sap.com ก็ได้ จะมีข้อมูลมากมายให้คุณศึกษาระบบ SAP


PC Magazine

ฉบับที่ 44 กันยายน 2545
อ่านบทความอื่นๆ >>

อัพเดทล่าสุด