by Michael S. Kaplan, published on 2005/03/07 02:03 -05:00, original URI: http://blogs.msdn.com/b/michkap/archive/2005/03/07/386453.aspx
(Recycling some electrons for a fun bug that can still be reproduced in the latest versions and service packs of VB and VBA <= 6.x (despite all the pressure I was able to muster in my position of unimportance!). To see this article in English, go to http://blogs.msdn.com/michkap/archive/2005/03/07/386452.aspx)
บั๊กที่สนับสนุนระบบปฏิทิน oleaut32.dll รุ่นใหม่ รวมถึง VB, VBA, และ VBScript
(ลงประกาศครั้งแรกเมื่อ 9/4/2000)
OLEAUT32.DLL เวอร์ชั่นใหม่ (2.40.4512.1) ซึ่งมาพร้อมกับ Windows 2000 ได้เพิ่มส่วนสนับสนุนปฏิทินไทย (ซึ่งก่อนหน้านั้นสนับสนุนเฉพาะวันที่ในระบบของ Gregorian และ Hijri ซึ่งสนับสนุน VB ทั้งหมด) ปัญหาที่เกิดเมื่อเริ่มแรกก็คือแม้ DLL จะมีส่วนสนับสนุนและ MSDN ได้ระบุความสามารถใหม่ๆไว้เป็นเอกสารแล้วก็ตาม แต่ platform SDK ไม่มีไฟล์เฮดเดอร์รุ่นล่าสุดอยู่ ทำให้คุณไม่สามารถใช้คุณสมบัตินี้ได้ ต่อไปนี้เป็นคุณสมบัติ (ซึ่งควรจะมีสำหรับ platform SDK ซึ่งกำลังจะออกในเดือนกรกฎาคม 2543):#define VARIANT_CALENDAR_THAI 0x20 // SOUTHASIA calendar support
#define VARIANT_CALENDAR_GREGORIAN 0x40 // SOUTHASIA calendar supportตอนนี้คุณก็ใช้คุณสมบัตินี้ได้แล้วสำหรับบั๊กตัวนี้:
เมื่อมี oleaut32.dll รุ่นใหม่บนเครื่องที่ใช้ Thai Win95/Win98/NT4 หรือ US Windows 2000 ที่มี Thai regional settings เครื่องคอมพิวเตอร์จะรู้ว่าต้องใช้ปฏิทินไทย แต่น่าเสียดายที่ VBA และ VBScript ไม่เข้าใจแนวคิดเรื่องวันที่ในภาษาไทย จึงสรุปเอาว่าวันที่ 9/4/2543 (วันที่ในภาษาไทยเทียบเท่ากับวันที่ 9 เมษายน 2000) เป็นวันที่ในอนาคตของระบบ Gregorian ทำให้โค้ดที่คุณใช้ในการแสดงค่าวันที่กลายเป็นปีในอนาคตอีก 543 ปีข้างหน้า และถ้าผู้ใช้ไม่พิมพ์วันที่ล่วงหน้าไป 543 ปี แอปพลิเคชั่นของคุณก็จะใช้วันที่ผิดพลาด
ปัญหานี้จะแย่ลงอีกถ้าคุณใช้วันที่ในระบบ Hijri ซึ่งเท่ากับก่อนวันที่ในระบบ Gregorian ประมาณ 600 ปี ทุกอย่างจะผิดพลาดหมด ผมเองก็ไม่แน่ใจเหมือนกันว่า VBA คำนวณวันที่ในระบบ Hijri อย่างไร แต่ถ้าให้เครื่องคอมพิวเตอร์คำนวณให้ เครื่องจะไม่สามารถระบุวันที่ได้เช่นเดียวกับวันที่ในระบบภาษาไทย เนื่องจากเครื่องคิดว่าเป็นวันที่ 5/1/1964 แทนที่จะเป็นวันที่ที่ถูกต้องในระบบ Hijri คือ 1/5/1421 ตรงนี้อาจจะยิ่งมีปัญหาหนักขึ้น เนื่องจากวันที่นี้ไม่สอดคล้องกับวันที่ที่ผู้ใช้สามารถเข้าใจได้ (ซึ่งตรงข้ามกับวันที่ในระบบภาษาไทยที่ผู้ใช้อาจเข้าใจได้ถ้าตั้งค่า Thai regional settings ไว้)
วิธีแก้ปัญหาสำหรับ VBA คือจะต้องมีกลไกจัดการวันที่ ซึ่งใช้ได้กับคอมพิวเตอร์ทุกเครื่องมีอยู่ แทนที่จะใส่โค้ดลงในเครื่อง (hardcoded) เพื่อให้ยอมรับวันที่ทั้งสองแบบทั้งๆที่ตอนนี้คอมพิวเตอร์สนับสนุนได้ 3 แบบ ในการใช้งานบั๊กตัวนี้คุณจะต้องใช้ฟังก์ชั่น VariantChangeTypeEx เปลี่ยนวันที่เป็น Gregorian date string แล้วเปลี่ยน Gregorian date string กลับไปเป็นวันที่ใหม่อีกครั้ง การประกาศฟังก์ชั่นและค่า constants ที่เกี่ยวข้องเป็นดังนี้:
Private Const VARIANT_NOUSEROVERRIDE = &H4
Private Const VARIANT_CALENDAR_HIJRI = &H8
Private Const VARIANT_CALENDAR_THAI = &H20
Private Const VARIANT_CALENDAR_GREGORIAN = &H40
Declare Function VariantChangeTypeEx _
Lib "oleaut32.dll" _
(ByRef pvargDest As Variant, _
ByRef pvarSrc As Variant, _
ByVal lcid As Long, _
ByVal wFlags As Integer, _
ByVal vt As VbVarType) As Longนอกจากนั้นคุณยังใช้ procedure ต่อไปนี้ (ถ้าคุณมี oleaut32.dll รุ่นใหม่เท่านั้น!) เพื่อทดสอบ:
Sub TestDateFormats()
Dim vSrc As Variant
Dim vDst As Variant
vSrc = Date
Call VariantChangeTypeEx(vDst, vSrc, 1033, VARIANT_CALENDAR_GREGORIAN, vbString)
Debug.Print "Gregorian date: " & vDst
Call VariantChangeTypeEx(vDst, vSrc, 1025, VARIANT_CALENDAR_HIJRI, vbString)
Debug.Print "Hijri date: " & vDst
Call VariantChangeTypeEx(vDst, vSrc, 1054, VARIANT_CALENDAR_THAI, vbString)
Debug.Print "Thai date: " & vDst
End Subผลที่ได้จะเป็นดังนี้:
Gregorian date: 4/9/2000
Hijri date: 05/01/1421
Thai date: 9/4/2543การจะเปลี่ยนจาก string เป็น date ให้ใส่ vbDate ใน parameter ที่ห้าแทน vbString คุณสามารถนำโค้ดเดียวกันนี้ไปใช้แปลงวันที่ตามเมืองต่างๆได้
เห็นได้ชัดว่าบั๊กตัวนี้ใช้ได้ไม่ดีนักกับแอปพลิเคชั่นที่ทำงานบนเครื่องคอมพิวเตอร์ภาษาไทย เนื่องจากจะมี behavior เปลี่ยนแปลงไป ผมหวังว่า Microsoft คงจะรีบจัดการกับปัญหานี้โดยเร็ว
This post and its original English cousin brought to you by "ภ" (U+0e20, a.k.a. THAI CHARACTER PHO SAMPHAO)
# AC on 7 Mar 2005 12:14 AM:
# Michael Kaplan on 7 Mar 2005 1:11 AM:
# Vorn on 7 Mar 2005 9:55 AM:
# Andrew van der Stock on 7 Mar 2005 6:22 PM:
# Michael Kaplan on 7 Mar 2005 6:28 PM:
referenced by