Font s :
Background :

วิธีใช้ Macro Recorder ช่วยในการเรียนรู้ VBA

จากประสบการณ์สอนและตอบคำถามผ่านเว็บพบว่า ผู้เริ่มฝึกใช้ VBA หรือแม้แต่คนที่ใช้ VBA มานาน มักติดปัญหาตรงที่ไม่รู้ว่า รหัสคำสั่ง VBA ที่ตนต้องนำมาใช้นั้นเป็นอย่างไร บางคนสามารถเปิดตำราค้นหารหัสได้แล้ว แต่ไม่รู้ว่าจะดัดแปลงรหัสอย่างไรได้บ้าง ครั้นติดปัญหา ไม่สามารถแก้ไขทำต่อด้วยตนเอง ก็จะยกปัญหาขึ้นถามบนเว็บ พอได้คำตอบไปใช้งานสักพัก ต่อมาไม่นานก็กลับมาถามหารหัสต่อจากคำถามเดิมซ้ำแล้วซ้ำอีก

ขอย้ำอีกครั้งว่าถ้าอยากคิดใช้ VBA ต้องขอให้ตนเป็นที่พึ่งแห่งตน เพราะ VBA มีทั้งคุณมีทั้งโทษ เป็นดาบสองคม หากคิดใช้ VBA แล้วต้องใช้ให้เป็น หาทางใช้ให้ถูกวิธี ทุกครั้งที่ติดปัญหา ต้องพยายามหาทางแก้ไขด้วยตนเองให้ได้ ต่อเมื่อหมดหนทางแล้วจึงสอบถามจากผู้มีความรู้ และทำความเข้าใจกับคำตอบที่ได้รับมา อย่าท่อง อย่าลอก อย่าเอาไปใช้โดยปราศจากความเข้าใจ

ในบทนี้จะแนะนำวิธีใช้ Macro Recorder ช่วยในการเรียนรู้ VBA จะได้ทำตนให้เป็นที่พึ่งของตนเสียก่อน

ตัวอย่างที่ 1 : ต้องการเปลี่ยนชื่อชีท ให้มีชื่อใหม่ตามค่าที่อยู่ในเซลล์ A1

สมมติ เดิมชีทมีชื่อว่า Sheet1 เราต้องการเปลี่ยนชื่อชีทตามค่าที่เก็บไว้ในเซลล์ A1 เช่น ถ้า A1 มีคำว่า MyJan ก็ให้รหัส VBA ทำหน้าที่เปลี่ยนชื่อชีทเป็น MyJan และถ้า A1 มีค่าใหม่ ก็ให้ชื่อชีทถูกเปลี่ยนชื่อใหม่ตามค่าในเซลล์ A1 ได้ตามต้องการ

ขั้นที่ 1 : ใช้ Recorder บันทึกการคลิกเลือกเซลล์ A1 แล้วพิมพ์คำว่า MyJan ลงไป จะได้รหัส VBA :

Range("A1").Select
ActiveCell.FormulaR1C1 = "MyJan"

ขั้นที่ 2 : ใช้ Recorder บันทึกการสั่ง Format > Sheet > Rename แล้วพิมพ์คำว่า MyJan ทับคำว่า Sheet1 จะได้รหัส VBA :

Sheets("Sheet1").Name = "MyJan"

สังเกตว่าผลที่ได้จากการบันทึกขั้นตอนนี้ แสดงว่าการกำหนดค่าให้กับสิ่งใด ให้ใช้เครื่องหมายเท่ากับ โดยสิ่งที่อยู่ด้านซ้ายของเครื่องหมายเท่ากับ ถือเป็นสิ่งที่ถูกกำหนดค่า ให้มีค่าตาม ค่าที่อยู่ด้านขวาของเครื่องหมายเท่ากับ

ขั้นที่ 3 : ทดลองเขียน VBA โดยผสมรหัสทั้งสองขั้นเข้าด้วยกันเป็นดังนี้

Sub RenameSheet()
    Sheets("Sheet1").Name = Range("A1")
End Sub

ซึ่งจะพบว่ารหัสใน Sub Procedure ชื่อ RenameSheet นี้ทำงานได้เพียงครั้งเดียว เนื่องจากตัวรหัส Sheets("Sheet1").Name กำหนดไว้ว่า ให้เปลี่ยนชีทที่มีชื่อว่า Sheet1 ดังนั้นหากในแฟ้มไม่มีชีทชื่อ Sheet1 เพราะถูกเปลี่ยนชื่อชีทเป็น MyJan ไปแล้ว รหัสจึงไม่สามารถทำงานตามต้องการ

ขอให้สังเกตย้อนกลับไปดูรหัสที่ได้จากขั้นแรก จะเห็นว่ามีรหัสคำว่า ActiveCell ซึ่งมีหมายถึงเซลล์ตำแหน่งใดก็ได้ ขอเพียงแต่กำลังถูกเลือกใช้งานอยู่ จึงมีคำว่า Active นำหน้า สงสัยไหมว่าในเรื่องของชีทนั้นมี ActiveSheet ด้วยไหม คราวนี้ให้ลองใช้คำว่า ActiveSheet ค้นหาใน Help ดูจะพบคำอธิบาย ดังนี้

ActiveSheet Property

Returns an object that represents the active sheet (the sheet on top) in the active workbook or in the specified window or workbook. Returns Nothing if no sheet is active. Read-only.

Remarks

If you don't specify an object qualifier, this property returns the active sheet in the active workbook.

If a workbook appears in more than one window, the ActiveSheet property may be different in different windows.

Example

This example displays the name of the active sheet.

MsgBox "The name of the active sheet is " & ActiveSheet.Name

ถ้าอยากอ่านคำอธิบายทีละบรรทัดก็ตามใจ แต่ส่วนสำคัญที่สุดที่ควรดูเป็นจุดแรกก็คือตัวอย่างที่แสดงไว้ จะเห็นว่ามีคำสั่ง ActiveSheet.Name ซึ่งแปลว่า ชื่อชีทของชีทที่กำลังเลือกอยู่ และน่าจะนำมาใช้แทนคำว่า  Sheets("Sheet1").Name ได้

ขั้นที่ 4 : กลับไปแก้รหัสที่เขียนเองใหม่ แล้วจะพบว่ารหัสชุดนี้ทำงานได้ตลอด

Sub RenameSheet()
    ActiveSheet.Name = Range("A1")
End Sub

หมายเหตุ ถ้าค้นหาคำว่า Active จาก Help จะพบว่านอกจาก ActiveCell และ ActiveSheet แล้วยังมี ActiveWorkbook, ActiveWindow, ActiveChart, ActivePane, และ ActivePrinter ให้เลือกนำมาใช้ได้

 

ตัวอย่างที่ 2 : ต้องการจัดเก็บแฟ้ม โดยใช้ชื่อแฟ้มตามค่าที่อยู่ในเซลล์ A1

ตัวอย่างนี้ต้องการให้รหัสทำงานคล้ายกับตัวอย่างแรก เพียงแต่คราวนี้ให้เปลี่ยนชื่อแฟ้มแทนที่จะเป็นชื่อชีท

ขั้นที่ 1 : ขอให้ลองเขียนรหัสเองขึ้นมา โดยเลียนแบบตัวอย่างแรก

Sub RenameWorkbook()
    ActiveWorkbook.Name = Range("A1")
End Sub

เมื่อสั่ง Run จะพบว่ารหัสชุดนี้ไม่ทำงาน โดยมีคำเตือนว่า Compile error ในขั้นนี้ไม่ต้องสนใจว่า Compile error คืออะไร เพียงขอให้สังเกตว่า รหัสไม่ทำงาน แสดงว่าต้องมีอะไรที่ผิดพลาด และถ้าสังเกตต่อให้ดีจะพบว่าเมื่อคลิก OK ออกจากคำเตือน Compile error แล้ว VBE จะเลือกคำว่า .Name ไว้ เป็นอาการที่ชี้ให้เราเห็นว่า ส่วนที่ผิดพลาดน่าจะเป็นส่วนของคำว่า .Name นี่เอง

renameworkbookerror

ทุกครั้งที่รหัสไม่ทำงาน ให้คลิกปุ่ม Reset ซึ่งเป็นปุ่มสี่เหลี่ยมบนเมนูก่อน มิฉะนั้นจะทำอย่างอื่นต่อไม่ได้เลย

ขั้นที่ 2 : ใช้ Recorder บันทึกการสั่ง File > Save as เป็นชื่อแฟ้มใหม่ สมมติให้ใช้ชื่อว่า MyMonth.xls จะได้รหัส VBA :

ActiveWorkbook.SaveAs Filename:= _
"C:\MyMonth.xls", FileFormat:= _
xlNormal, Password:="", WriteResPassword:="", _
ReadOnlyRecommended:=False _
, CreateBackup:=False

ขั้นที่ 3 : ทดลองตัดรหัสในขั้นที่ 2 ให้สั้นลงเหลือเท่าที่ตรงกับการจัดเก็บแฟ้มตามชื่อที่ต้องการ แล้วทดสอบว่ารหัสใหม่นี้ทำงานได้หรือไม่ ซึ่งจะพบว่ารหัสทำงาน เพียงแต่จะถูกถามว่า ต้องการให้ต้องการจัดเก็บในชื่อนี้หรือไม่ เพราะมีแฟ้มชื่อนี้อยู่แล้ว

ActiveWorkbook.SaveAs Filename:="MyMonth.xls"

ขั้นที่ 4 : ย้อนกลับไปแก้รหัสในขั้นที่ 1 แล้วจะพบว่ารหัสทำงานได้ตามต้องการ

Sub RenameWorkbook()
    ActiveWorkbook.SaveAs Filename: = Range("A1")
End Sub

 

ตัวอย่างที่ 3 : ต้องการจัดปิดแฟ้ม โดยไม่ต้องจัดเก็บซ้ำอีก

ขั้นที่ 1 : ตัวอย่างนี้ต้องเปิดแฟ้มใหม่ขึ้นอีกแฟ้มหนึ่ง เพื่อใช้เก็บรหัสที่ได้จากการบันทึกการปิดแฟ้ม โดยมีขั้นตอนใช้ Recorder บันทึก ดังนี้

  1. คลิกเมนู Window > เลือกชื่อแฟ้มที่ต้องการปิด สมมติว่าชื่อ MyMonth.xls
  2. คลิกเมนู File > CLose

จะเกิดรหัส VBA :

Windows("MyMonth.xls").Activate
ActiveWorkbook.Close

ขั้นที่ 2 : ให้ copy รหัสเฉพาะ ActiveWorkbook.Close มาสร้าง Sub Procedure ลงใน MyMonth.xls

Sub CloseMyFile()
    ActiveWorkbook.Close
End Sub

เมื่อทดสอบรหัสนี้หลายๆครั้ง จะพบว่าถ้าในแฟ้มมีข้อมูลใหม่ จะมีคำเตือนเปิดขึ้นบนจอว่า คุณต้องการจัดเก็บข้อมูลที่เปลี่ยนแปลงหรือไม่

ขั้นที่ 3 : ถ้าอยากใช้คำสั่งปิดแฟ้ม โดยไม่ต้องถามเรื่องการจัดเก็บข้อมูลใหม่ คราวนี้ต้องศึกษาจาก Help โดยให้คลิกที่รหัสคำว่า Close จากนั้นกดปุ่ม F1 จะมีตัวอย่างแสดงไว้ในคำอธิบายของ Help ดังนี้

Workbooks("BOOK1.XLS").Close SaveChanges:=False

ขั้นที่ 4 : กลับไปแก้ไขรหัสเดิม โดยนำคำว่า SaveChanges:=False ไปเพิ่มต่อท้ายรหัสเดิม จะพบว่าคราวนี้ไม่มีคำเตือนเปิดขึ้นบนจอว่า คุณต้องการจัดเก็บข้อมูลที่เปลี่ยนแปลงหรือไม่

Sub CloseMyFile()
    ActiveWorkbook.Close SaveChanges:=False
End Sub

หมายเหตุ : หากศึกษาคำอธิบายจาก Help จะพบว่า คำสั่ง Close นั้น สามารถเขียนอีกรูปแบบหนึ่ง คือ expression.Close(SaveChanges, Filename, RouteWorkbook) โดยใช้วงเล็บกำหนดตัวเลือกต่อๆกันไป ทำให้รหัสสั้นลงเป็น

Sub CloseMyFile()
    ActiveWorkbook.Close(False)
End Sub

 

 

 

Categories

About this Entry

This page contains a single entry by สมเกียรติ ฟุ้งเกียรติ published on November 4, 2006 2:49 PM.

เคล็ดการใช้ Macro Recorder was the previous entry in this blog.

วิธีสร้างชุดคำสั่งควบคุมระบบเมื่อเปิดปิดแฟ้ม is the next entry in this blog.

Find recent content on the main index.

Font s :
Background :