บั๊กที่สนับสนุนระบบปฏิทิน oleaut32.dll รุ่นใหม่ รวมถึง VB, VBA, และ VBScript

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:

If you post in Thai, do I have to comment in Thai as well?

I think I remember an editorial you wrote for VBPJ about this issue related to people needing to test their software before releasing it.

So Microsoft never fixed this bug?

# Michael Kaplan on 7 Mar 2005 1:11 AM:

Heh heh heh -- no, you can post comments in any language.

I did indeed write an editorial on this topic. I pointed out that there is no conceivable way that even the most minimal amount of compat. testing (run any VB application with Thai settings -- this is obvious to try when a Thai calendar was being added) would have found this problem.

Clearly they did not test this update in any real way.

Reminds me of a story -- a man goes to the ticket counter at the airport and says "I'd like to go to Orlando. This bag should go to Dallas and this other bag should go to Atlanta." When the person at the ticket counter apologetically says that they cannot do this, the man says "You did it YESTERDAY."

The next time a bug in oleaut is punted due to the hit to test resources, I'll be sure to remind everyone that no one is testing the component for regressions anyway. :-)

# Vorn on 7 Mar 2005 9:55 AM:

AAAAAAAAAAAAAAH!

::dies of thai::

Vorn

# Andrew van der Stock on 7 Mar 2005 6:22 PM:

Michael,

how many languages do you speak / write? I struggle with just the one and a bit!

thanks,
Andrew

# Michael Kaplan on 7 Mar 2005 6:28 PM:

Oh, I did not write the Thai version, I just have a helpful colleague who acted as a localizer. :-)

referenced by

2005/03/07 Successful experiment

2005/03/07 A bug with the new oleaut32.dll calendar support and VB, VBA, and VBScript

go to newer or older post, or back to index or month or day