[HỎI] Lấy ngày giờ của một trang web đặt làm giờ hệ thống (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

Hoàng Trọng Nghĩa

Chuyên gia GPE
Thành viên BQT
Moderator
Tham gia
17/8/08
Bài viết
8,662
Được thích
16,720
Giới tính
Nam
Xin vui lòng cho tôi hỏi, nếu muốn lấy ngày giờ của một trang web chuẩn để làm cài đặt làm giờ hệ thống trên máy tính thì code phải viết thế nào?

Tôi muốn lấy ngày giờ tại trang web dưới đây:

https://www.timeanddate.com/worldclock/vietnam/hanoi

Trước đây tôi có dùng code này của một ai đó trên diễn đàn GPE, nhưng giờ không xài được. Tôi xài Window7.

Và trang web này giờ cũng không còn khả dụng:

http://wwp.greenwichmeantime.com/time/scripts/clock-8/runner.php?tz=gmt

Mã:
Sub SetDateTimeFromNet()
    Dim arrMonth
    Dim http, shell
    Dim currDate, currTime
    Dim index, zone_offset
    Dim strCmd, strCurrDateTime
    Dim strGMT_Time, strZone_name, strOpSys
   
    Const gmtTime = "http://wwp.greenwichmeantime.com/time/scripts/clock-8/runner.php?tz=gmt"
    arrMonth = Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")

    'On Error Resume Next
    zone_offset = 7: strZone_name = "SE Asia Standard Time"
    strOpSys = Application.OperatingSystem
    index = InStr(1, strOpSys, "NT")
    If index > 0 Then index = Mid(strOpSys, index + 3, 1)
    If index > 5 Then
        strCmd = "cmd.exe /c TZUTIL /strOpSys " & strZone_name
    ElseIf index = 5 Then
        strCmd = "cmd.exe /c rundll32.exe shell32.dll,Control_RunDLL timedate.cpl,,/Z " & strZone_name
    Else
        Exit Sub
    End If
  
    Set shell = CreateObject("WScript.Shell")
    shell.Run strCmd, 0, True
  
    Set http = CreateObject("Microsoft.XMLHTTP")
   
    http.Open "GET", gmtTime & Now(), False, "", ""
    http.send
   
    strGMT_Time = http.getResponseHeader("Date")
  
    strGMT_Time = Mid(strGMT_Time, 6, Len(strGMT_Time) - 9)
    For index = 0 To 11
        strOpSys = Mid(strGMT_Time, 3, 5)
        If InStr(1, strOpSys, arrMonth(index)) > 0 Then
            strGMT_Time = Replace(strGMT_Time, strOpSys, Application.International(xlDateSeparator) & _
                           Format(index + 1, "00") & Application.International(xlDateSeparator))
            Exit For
        End If
    Next
   
    strCurrDateTime = DateAdd("h", zone_offset, strGMT_Time)
    currDate = DateValue(strCurrDateTime)
    currTime = Format(TimeValue(strCurrDateTime), "hh:mm:ss")
    MsgBox currDate
    shell.Run "%comspec% /c time " & currTime, False
    shell.Run "%comspec% /c date " & currDate, False
  
    Set shell = Nothing
    Set http = Nothing
End Sub
Cảm ơn rất nhiều.
 
Lần chỉnh sửa cuối:
nếu muốn lấy ngày giờ của một trang web chuẩn để làm cài đặt làm giờ hệ thống trên máy tính thì code phải viết thế nào?
Thử xem
Mã:
Sub test()
'    TimeZone = 7 cho Viet Nam
    MsgBox GetDateTime(1, 7)
    MsgBox GetDateTime(2, 7)
    MsgBox GetDateTime(3, 7)
End Sub

Function GetDateTime(DateTime As Byte, TimeZone As Integer) As Date
'    DateTime: 1 - gio, 2 - ngay thang, 3 - ngay thang va gio                                              *
'    TimeZone: so nguyen (chenh lech voi gio Greenwich Mean Time)
'    TimeZone map: https://www.timeanddate.com/time/map/
Dim Arr
    On Error GoTo err

    Set XHTTP = CreateObject("MSXML2.XMLHTTP")
    With XHTTP
        .Open "Head", "http://time.windows.com/", False
        .Send
        Arr = Split(.GetResponseHeader("Date"), " ")
    End With

    Select Case Arr(2)
        Case "Jan": Arr(2) = 1
        Case "Feb": Arr(2) = 2
        Case "Mar": Arr(2) = 3
        Case "Apr": Arr(2) = 4
        Case "May": Arr(2) = 5
        Case "Jun": Arr(2) = 6
        Case "Jul": Arr(2) = 7
        Case "Aug": Arr(2) = 8
        Case "Sep": Arr(2) = 9
        Case "Oct": Arr(2) = 10
        Case "Nov": Arr(2) = 11
        Case "Dec": Arr(2) = 12
    End Select

    Select Case DateTime
        Case 1: GetDateTime = TimeValue(Arr(4)) + 1 / 24 * TimeZone
        Case 2: GetDateTime = Format(DateSerial(Arr(3), Arr(2), Arr(1)) + TimeValue(Arr(4)) + 1 / 24 * TimeZone, "yyyy-mm-dd")
        Case 3: GetDateTime = DateSerial(Arr(3), Arr(2), Arr(1)) + TimeValue(Arr(4)) + 1 / 24 * TimeZone
    End Select

    Set XHTTP = Nothing

    On Error GoTo 0
    Exit Function
err:
    MsgBox "Loi " & err.Number & " (" & err.Description & ") trong ham GetDateTime "
End Function
 
Upvote 0
Thử xem
Mã:
Sub test()
'    TimeZone = 7 cho Viet Nam
    MsgBox GetDateTime(1, 7)
    MsgBox GetDateTime(2, 7)
    MsgBox GetDateTime(3, 7)
End Sub

Function GetDateTime(DateTime As Byte, TimeZone As Integer) As Date
'    DateTime: 1 - gio, 2 - ngay thang, 3 - ngay thang va gio                                              *
'    TimeZone: so nguyen (chenh lech voi gio Greenwich Mean Time)
'    TimeZone map: https://www.timeanddate.com/time/map/
Dim Arr
    On Error GoTo err

    Set XHTTP = CreateObject("MSXML2.XMLHTTP")
    With XHTTP
        .Open "Head", "http://time.windows.com/", False
        .Send
        Arr = Split(.GetResponseHeader("Date"), " ")
    End With

    Select Case Arr(2)
        Case "Jan": Arr(2) = 1
        Case "Feb": Arr(2) = 2
        Case "Mar": Arr(2) = 3
        Case "Apr": Arr(2) = 4
        Case "May": Arr(2) = 5
        Case "Jun": Arr(2) = 6
        Case "Jul": Arr(2) = 7
        Case "Aug": Arr(2) = 8
        Case "Sep": Arr(2) = 9
        Case "Oct": Arr(2) = 10
        Case "Nov": Arr(2) = 11
        Case "Dec": Arr(2) = 12
    End Select

    Select Case DateTime
        Case 1: GetDateTime = TimeValue(Arr(4)) + 1 / 24 * TimeZone
        Case 2: GetDateTime = Format(DateSerial(Arr(3), Arr(2), Arr(1)) + TimeValue(Arr(4)) + 1 / 24 * TimeZone, "yyyy-mm-dd")
        Case 3: GetDateTime = DateSerial(Arr(3), Arr(2), Arr(1)) + TimeValue(Arr(4)) + 1 / 24 * TimeZone
    End Select

    Set XHTTP = Nothing

    On Error GoTo 0
    Exit Function
err:
    MsgBox "Loi " & err.Number & " (" & err.Description & ") trong ham GetDateTime "
End Function
Ôi, quá nhanh quá nguy hiểm, hihihi, cám ơn siêu nhân người dơi Batman nhiều nhé.

Nhân tiện cho em hỏi là mình định dạng giờ hệ thống theo kiểu English (United States), sau đó định dạng ngày tháng kiểu dd/mm/yyyy và dạng time là HH:mm:ss thì viết code như thế nào ạ?

Xin chân thành cảm ơn.
 
Upvote 0
Xem trong code thì biết Arr nó chứa gì rồi muốn ghép, định dạng thế nào tùy ý.
Chắc có lẽ là em dốt, nhưng em vẫn chưa hình dung ra, vì trong Arr có 6 mục về ngày giờ và GMT, nó chẳng liên quan gì đến việc định dạng cũng như thay đổi language gì cả ạ.
 
Upvote 0
Nhân tiện cho em hỏi là mình định dạng giờ hệ thống theo kiểu English (United States), sau đó định dạng ngày tháng kiểu dd/mm/yyyy và dạng time là HH:mm:ss thì viết code như thế nào
Hình như anh muốn thiết lập định dạng trong hệ điều hành Windows ạ? (Nếu không phải thì anh chờ anh @batman1 thôi.) :)

https://www.giaiphapexcel.com/diendan/threads/giúp-code-định-dạng-hệ-thống.112761/
 
Upvote 0
Hình như anh muốn thiết lập định dạng trong hệ điều hành Windows ạ? (Nếu không phải thì anh chờ anh @batman1 thôi.) :)

https://www.giaiphapexcel.com/diendan/threads/giúp-code-định-dạng-hệ-thống.112761/
Đúng là như thế đó befaint, thực sự mục đích của mình là kiểm tra định dạng của hệ thống như thế nào, lưu lại các thông số đó trong một biến public, sau đó mình chạy chương trình của mình và định dạng theo kiểu của mình, sau khi thoát ra, trả lại cho nó định dạng nguyên mẫu ban đầu.

P/s: Mình bị dính chưởng lỗi vì chạy chương trình mình định dạng kiểu "yyyy-mmm-dd", thế nhưng bị lỗi với kiểu language là Vietnamese vì cái mmm lại ra là Thg5 không phải là May trong CSDL.
 
Lần chỉnh sửa cuối:
Upvote 0
Tiêu đề và nội dung bài #1 nói về lấy ngày giờ từ trang web. Code đã làm việc này.

Tự dưng bạn lại hỏi về vấn đề khác. Do code ví dụ trả về ngày tháng được định dạng theo một cách cụ thể nên khi gặp câu hỏi mới tôi tưởng bạn hỏi về định dạng khác của kết quả trả về.

1. Thường thì khi hỏi về những cái khác với chủ đề thì nhiều người nhắc là phải lập chủ đề mới. Vì cái hỏi thêm tuy cũng dính dáng tới ngày giờ nhưng không đúng với chủ đề hiện hành.

2. Tôi hiểu bây giờ là bạn muốn ghi nhớ thiết lập hiện hành trong CP, sau đó thay đổi thiết lập trong CP và làm việc gì đó, cuối cùng thì trả lại thiết lập ban đầu. Nếu thế thì có câu hỏi:

2a. Cụ thể code định làm gì. Biết đâu lúc đó có thể có cách khác vẫn làm được việc mà không phải thay đổi các lựa chọn trong CP.

2b. Cụ thể là bạn muốn thay đổi gì trong CP? Thay đổi có muôn vàn kiểu thay đổi. Nhưng có thể chia làm hai loại:

+ giả dụ CP đang có thiết lập Việt Nam. Vẫn là VN nhưng bạn muốn thay đổi thiết lập định dạng ngày tháng và giờ.

+ giả dụ CP đang có thiết lập Việt Nam. Bạn muốn thay thành thiết lập Mỹ. Thế thôi. Hoặc thêm thay đổi thiết lập định dạng ngày tháng và giờ.

Rõ ràng việc 1 không đòi hỏi thay đổi vùng.

Nên nói rõ là tại sao để làm việc gì đó bạn phải, muốn thay đổi thiết lập trong CP. Biết đâu cái bạn muốn làm không đòi hỏi thay đổi trong CP thì sao?
 
Upvote 0
Tiêu đề và nội dung bài #1 nói về lấy ngày giờ từ trang web. Code đã làm việc này.

Tự dưng bạn lại hỏi về vấn đề khác. Do code ví dụ trả về ngày tháng được định dạng theo một cách cụ thể nên khi gặp câu hỏi mới tôi tưởng bạn hỏi về định dạng khác của kết quả trả về.

1. Thường thì khi hỏi về những cái khác với chủ đề thì nhiều người nhắc là phải lập chủ đề mới. Vì cái hỏi thêm tuy cũng dính dáng tới ngày giờ nhưng không đúng với chủ đề hiện hành.

2. Tôi hiểu bây giờ là bạn muốn ghi nhớ thiết lập hiện hành trong CP, sau đó thay đổi thiết lập trong CP và làm việc gì đó, cuối cùng thì trả lại thiết lập ban đầu. Nếu thế thì có câu hỏi:

2a. Cụ thể code định làm gì. Biết đâu lúc đó có thể có cách khác vẫn làm được việc mà không phải thay đổi các lựa chọn trong CP.

2b. Cụ thể là bạn muốn thay đổi gì trong CP? Thay đổi có muôn vàn kiểu thay đổi. Nhưng có thể chia làm hai loại:

+ giả dụ CP đang có thiết lập Việt Nam. Vẫn là VN nhưng bạn muốn thay đổi thiết lập định dạng ngày tháng và giờ.

+ giả dụ CP đang có thiết lập Việt Nam. Bạn muốn thay thành thiết lập Mỹ. Thế thôi. Hoặc thêm thay đổi thiết lập định dạng ngày tháng và giờ.

Rõ ràng việc 1 không đòi hỏi thay đổi vùng.

Nên nói rõ là tại sao để làm việc gì đó bạn phải, muốn thay đổi thiết lập trong CP. Biết đâu cái bạn muốn làm không đòi hỏi thay đổi trong CP thì sao?
Cái đầu em hỏi đã được anh trả lời đã thỏa đáng, nó rất tuyệt vời. Nhưng em ghi thêm là "nhân tiện cho em hỏi", bởi cả 2 đều có liên quan đến control panel nên em mở rộng ra để được hỗ trợ kiến thức của mọi người, đặc biệt là anh.
Cảm ơn anh nhiều.
 
Upvote 0
Thì tôi cũng nói rõ rồi
Nếu thế thì có câu hỏi:

2a. Cụ thể code định làm gì. Biết đâu lúc đó có thể có cách khác vẫn làm được việc mà không phải thay đổi các lựa chọn trong CP.

2b. Cụ thể là bạn muốn thay đổi gì trong CP? Thay đổi có muôn vàn kiểu thay đổi. Nhưng có thể chia làm hai loại:

+ giả dụ CP đang có thiết lập Việt Nam. Vẫn là VN nhưng bạn muốn thay đổi thiết lập định dạng ngày tháng và giờ.

+ giả dụ CP đang có thiết lập Việt Nam. Bạn muốn thay thành thiết lập Mỹ. Thế thôi. Hoặc thêm thay đổi thiết lập định dạng ngày tháng và giờ.

Rõ ràng việc 1 không đòi hỏi thay đổi vùng.

Nên nói rõ là tại sao để làm việc gì đó bạn phải, muốn thay đổi thiết lập trong CP. Biết đâu cái bạn muốn làm không đòi hỏi thay đổi trong CP thì sao?
 
Upvote 0
Thì tôi cũng nói rõ rồi
Em cũng xin phép diễn giải cái khó của em như sau:

PHP:
Public pblDateOrder As Long, pbcFormat As String

Sub SystemDateTimeSetup()
    Dim shell As Object
    Dim currDateTime As Date
    Dim blnConnect As Boolean
    Set shell = CreateObject("WScript.Shell")
 
    'Ham moi cap nhat boi Batman1 (có thêm bien blnConnect de nhan biet ket noi:
    currDateTime = GetDateTime(3, 7, blnConnect)
 
    If Not blnConnect Then
        Dim currDate As Date, currTime As Date
        currDate = Format(currDateTime, "dd/mm/yyyy")
        currTime = currDateTime - currDate
        currDate = GetDateTime(2, 7)
        shell.Run "%comspec% /c time " & currTime, False
        shell.Run "%comspec% /c date " & currDate, False
    End If
 
    'Kiem tra dinh dang cua he thong:
    pblDateOrder = Application.International(xlDateOrder)
    If pblDateOrder <> 1 Then
        Dim strFormat As String
        strFormat = "dd/mm/yyyy"
     
       ''Làm tới đây  trở về sau không biết:
        pbcFormat = shell.Run("copy dinh dang de tra lai nguyen mau sau khi thoát")
        ''Cai dat dinh dang moi:
        shell.Run "cai gi do de dinh dang theo ý mình" & strFormat
    End If
    Set shell = Nothing
End Sub

Sub ResetDateFormat()
    If pblDateOrder <> 1 Then
        Dim shell As Object
        Set shell = CreateObject("WScript.Shell")
        ''Tra lai dinh dang ban dau:
        shell.Run pbcFormat
    End If
End Sub

Anh vui lòng hướng dẫn em chỗ "Làm tới đây trở về sau không biết" được không, hay có cách giải quyết khác tốt hơn thế không?
 
Upvote 0
Em cũng xin phép diễn giải cái khó của em như sau:
...
Anh vui lòng hướng dẫn em chỗ "Làm tới đây trở về sau không biết" được không, hay có cách giải quyết khác tốt hơn thế không?
Tức bạn chỉ thay đổi định dạng ngày cho vùng hiện hành (vd. vùng hiện hành là Việt Nam) nếu nó khác "dd/MM/yyyy". Sau đó nếu trước đó thay đổi thì trả lại thiết lập cũ.

Về code thay đổi thì như ở dưới. Tuy nhiên có một câu hỏi quan trọng của tôi mà bạn không trả lời. Bạn định làm cái gì trong cái "chương trình" của mình mà bạn đề cập?

Bởi code tuy có thay đổi định dạng ngày tháng trong CP nhưng Excel không làm mới những dữ liệu ngày tháng trong các tập tin đang mở. Tức nếu trước đó bạn nhìn thấy vd. 2018-05-14 thì sau khi code đổi sang thành dd/MM/yyyy thì khi vào kiểm tra trong CP bạn có 14/05/2018. Nhưng nhìn trong Excel thì vẫn là 2018-05-14. Phải đóng Excel rồi mở lại thì mới có 14/05/2018 trong tập tin.

Tức khi bạn thay đổi định dạng "bằng tay" bằng cách vào thay đổi trong CP thì Excel sẽ cập nhật ngay nhưng khi code thay đổi thì Excel không cập nhật. Lý do là khi đổi bằng tay thì applet của CP sẽ gửi thông điệp WM_SETTINGCHANGE tới các ứng dụng trong system. Khi nhận thông điệp này thì Excel biết có sự thay đổi thiết lập trong system nên nó cập nhật. Khổ cái là khi code tự gửi thông điệp WM_SETTINGCHANGE thì lại không có tác dụng. Mọi ứng dụng "bên ngoài" nếu gửi thông điệp WM_SETTINGCHANGE thì Excel cập nhật nhưng gửi từ "trong lòng" Excel thì lại không có tác dụng. Tôi mới chỉ nghĩ ra một chiêu là tạo 1 EXE nhỏ, vd. sendmessage.exe với code
Mã:
Private Const WM_SETTINGCHANGE = &H1A
Private Const HWND_BROADCAST = &HFFFF&
Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As
Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long

Sub Main()
    Sleep 1000
    SendMessage HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0
End Sub
Sau đó code khi đã thay đổi xong thiết lập thì RUN sendmessage.exe.

Tập tin sendmessage thậm chí có thể "nhồi" vào tập tin Excel rồi khi cần thì bung ra đĩa rồi RUN, sau đó thì xóa. Nhưng cách này thì "hơi phiền".

Cũng có thể thay đổi khóa "sLongDate" trong registry tại "HKEY_CURRENT_USER\Control Panel\International" nhưng nếu tôi nhớ không lầm thì Excel cũng không cập nhật ngay.

Mọi cách khác chưa nghĩ ra :D

Xếp gạch ngồi hóng xem ai có cách để Excel cập nhật tức thì mọi thay đổi được thực hiện bởi code.
----------------
Code dưới dùng API GetLocaleInfo và SetLocaleInfo. Về GetLocaleInfo tôi có ví dụ trong bài #8
https://www.giaiphapexcel.com/diendan/threads/lập-công-thức-trả-kết-quả-là-các-thứ-trong-tuần.87755/post-548360
--------------
Code ví dụ cho chủ đề này
Mã:
Option Explicit

Public Const LOCALE_USE_CP_ACP = &H40000000
Public Const LCID_SUPPORTED = &H2
Public Const LOCALE_SSHORTDATE = &H1F     '   { short date format string }
Public Const LOCALE_IDATE = &H21     '   { short date format ordering }

Private Declare Function GetLocaleInfoW Lib "kernel32" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String, ByVal cchData As Long) As Long
Private Declare Function SetLocaleInfoW Lib "kernel32" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String) As Long
Private Declare Function GetUserDefaultLCID Lib "kernel32.dll" () As Long

Dim oldFormat As String

Function GetLocaleInfoString(ByVal LocaleID As Long, ByVal LCType As Long, Optional ByVal UseACP As Boolean = False) As String
Dim TypeInfo As Long, bufor As String, res As Long
    bufor = String(255, Chr(0))
    If UseACP Then
        TypeInfo = LCType Or LOCALE_USE_CP_ACP
    Else
        TypeInfo = LCType
    End If
    res = GetLocaleInfoW(LocaleID, TypeInfo, bufor, 255)
    If res > 0 Then GetLocaleInfoString = left(StrConv(bufor, vbFromUnicode), res - 1)
End Function

Sub sua()
Dim strFormat As String
    If GetLocaleInfoString(GetUserDefaultLCID, LOCALE_IDATE) <> "1" Then
'        ghi nho dinh dang hien hanh
        oldFormat = GetLocaleInfoString(GetUserDefaultLCID, LOCALE_SSHORTDATE)
'        Windows khong chap nhan "dd/mm/yyyy". Phai la "dd/MM/yyyy"
        strFormat = "dd/MM/yyyy"
'        thay doi dinh dang
        SetLocaleInfoW GetUserDefaultLCID, LOCALE_SSHORTDATE, StrConv(strFormat, vbUnicode)
    End If
End Sub

Sub trave()
'    neu dinh dang da thay doi boi code ...
    If Len(oldFormat) Then
'        tra ve dinh dang cu
        SetLocaleInfoW GetUserDefaultLCID, LOCALE_SSHORTDATE, StrConv(oldFormat, vbUnicode)
        oldFormat = ""
    End If
End Sub
 
Upvote 0
Tức bạn chỉ thay đổi định dạng ngày cho vùng hiện hành (vd. vùng hiện hành là Việt Nam) nếu nó khác "dd/MM/yyyy". Sau đó nếu trước đó thay đổi thì trả lại thiết lập cũ.

Về code thay đổi thì như ở dưới. Tuy nhiên có một câu hỏi quan trọng của tôi mà bạn không trả lời. Bạn định làm cái gì trong cái "chương trình" của mình mà bạn đề cập?

Bởi code tuy có thay đổi định dạng ngày tháng trong CP nhưng Excel không làm mới những dữ liệu ngày tháng trong các tập tin đang mở. Tức nếu trước đó bạn nhìn thấy vd. 2018-05-14 thì sau khi code đổi sang thành dd/MM/yyyy thì khi vào kiểm tra trong CP bạn có 14/05/2018. Nhưng nhìn trong Excel thì vẫn là 2018-05-14. Phải đóng Excel rồi mở lại thì mới có 14/05/2018 trong tập tin.

Tức khi bạn thay đổi định dạng "bằng tay" bằng cách vào thay đổi trong CP thì Excel sẽ cập nhật ngay nhưng khi code thay đổi thì Excel không cập nhật. Lý do là khi đổi bằng tay thì applet của CP sẽ gửi thông điệp WM_SETTINGCHANGE tới các ứng dụng trong system. Khi nhận thông điệp này thì Excel biết có sự thay đổi thiết lập trong system nên nó cập nhật. Khổ cái là khi code tự gửi thông điệp WM_SETTINGCHANGE thì lại không có tác dụng. Mọi ứng dụng "bên ngoài" nếu gửi thông điệp WM_SETTINGCHANGE thì Excel cập nhật nhưng gửi từ "trong lòng" Excel thì lại không có tác dụng. Tôi mới chỉ nghĩ ra một chiêu là tạo 1 EXE nhỏ, vd. sendmessage.exe với code
Mã:
Private Const WM_SETTINGCHANGE = &H1A
Private Const HWND_BROADCAST = &HFFFF&
Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As
Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long

Sub Main()
    Sleep 1000
    SendMessage HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0
End Sub
Sau đó code khi đã thay đổi xong thiết lập thì RUN sendmessage.exe.

Tập tin sendmessage thậm chí có thể "nhồi" vào tập tin Excel rồi khi cần thì bung ra đĩa rồi RUN, sau đó thì xóa. Nhưng cách này thì "hơi phiền".

Cũng có thể thay đổi khóa "sLongDate" trong registry tại "HKEY_CURRENT_USER\Control Panel\International" nhưng nếu tôi nhớ không lầm thì Excel cũng không cập nhật ngay.

Mọi cách khác chưa nghĩ ra :D

Xếp gạch ngồi hóng xem ai có cách để Excel cập nhật tức thì mọi thay đổi được thực hiện bởi code.
----------------
Code dưới dùng API GetLocaleInfo và SetLocaleInfo. Về GetLocaleInfo tôi có ví dụ trong bài #8
https://www.giaiphapexcel.com/diendan/threads/lập-công-thức-trả-kết-quả-là-các-thứ-trong-tuần.87755/post-548360
--------------
Code ví dụ cho chủ đề này
Mã:
Option Explicit

Public Const LOCALE_USE_CP_ACP = &H40000000
Public Const LCID_SUPPORTED = &H2
Public Const LOCALE_SSHORTDATE = &H1F     '   { short date format string }
Public Const LOCALE_IDATE = &H21     '   { short date format ordering }

Private Declare Function GetLocaleInfoW Lib "kernel32" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String, ByVal cchData As Long) As Long
Private Declare Function SetLocaleInfoW Lib "kernel32" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String) As Long
Private Declare Function GetUserDefaultLCID Lib "kernel32.dll" () As Long

Dim oldFormat As String

Function GetLocaleInfoString(ByVal LocaleID As Long, ByVal LCType As Long, Optional ByVal UseACP As Boolean = False) As String
Dim TypeInfo As Long, bufor As String, res As Long
    bufor = String(255, Chr(0))
    If UseACP Then
        TypeInfo = LCType Or LOCALE_USE_CP_ACP
    Else
        TypeInfo = LCType
    End If
    res = GetLocaleInfoW(LocaleID, TypeInfo, bufor, 255)
    If res > 0 Then GetLocaleInfoString = left(StrConv(bufor, vbFromUnicode), res - 1)
End Function

Sub sua()
Dim strFormat As String
    If GetLocaleInfoString(GetUserDefaultLCID, LOCALE_IDATE) <> "1" Then
'        ghi nho dinh dang hien hanh
        oldFormat = GetLocaleInfoString(GetUserDefaultLCID, LOCALE_SSHORTDATE)
'        Windows khong chap nhan "dd/mm/yyyy". Phai la "dd/MM/yyyy"
        strFormat = "dd/MM/yyyy"
'        thay doi dinh dang
        SetLocaleInfoW GetUserDefaultLCID, LOCALE_SSHORTDATE, StrConv(strFormat, vbUnicode)
    End If
End Sub

Sub trave()
'    neu dinh dang da thay doi boi code ...
    If Len(oldFormat) Then
'        tra ve dinh dang cu
        SetLocaleInfoW GetUserDefaultLCID, LOCALE_SSHORTDATE, StrConv(oldFormat, vbUnicode)
        oldFormat = ""
    End If
End Sub
Cám ơn Anh rất nhiều, kết quả thì OK trong CP, tuy nhiên các ứng dụng đều không tự cập nhật, kể cả thanh taskbar chỗ ghi thời gian ngày tháng, em nghĩ Restart lại máy mới cập nhật đúng (hiện tại đang test nên chưa khởi động lại).

Em cập nhật ngày giờ bằng Shell từ kết quả code của anh thấy nó cập nhật ngay và luôn trên thanh Taskbar, riêng hàm =Today() thì nhấn F9 nó mới cập nhật. Em nghĩ mình có nên dùng Shell hay không ạ?

Anh hỏi em mục đích làm gì thì xin thưa rằng, em làm việc trên Form là chủ yếu, ngày tháng nhập chuẩn phải là "dd/MM/yyyy", tuy nhiên nhập từ Calendar vào TextBox thì nó cứ ngược "MM/dd/yyyy" (theo định dạng của máy) làm cho người dùng rất dễ bị lẫn lộn giữa 05/04/2018 và 04/05/2018. Chính vì thế em muốn mọi thứ được đồng bộ một kiểu, nếu em định dạng theo kiểu VN thì vào CSDL nó đảo lại thành sai ngày tháng, cho nên mới nhờ mọi người giúp đỡ, may mắn gặp được anh.
 
Lần chỉnh sửa cuối:
Upvote 0
Nói chuyện kiểu nói tắt này mệt lắm.
Cám ơn Anh rất nhiều, kết quả thì OK trong CP, tuy nhiên các ứng dụng đều không tự cập nhật, kể cả thanh taskbar chỗ ghi thời gian ngày tháng,
Chỗ này là nói tới việc thay đổi ngày giờ hay nói tới thay đổi định dạng ngắn cho ngày tháng?
Nếu là nói về định dạng ngắn cho ngày tháng thì sao lại phải có thay đổi chỗ đồng hồ trên taskbar? Trên máy tôi thì đồng hồ chỉ thời gian, còn khi đưa chuột vào đồng hồ thì tip chỉ ngày tháng ở dạng dài. Nhưng code thay đổi định dạng ngắn của ngày tháng vậy thì thời gian đâu có thay đổi, định dạng dài của ngày tháng đâu có thay đổi để mà mong chờ cập nhật? Còn nếu ý khác thì xin nói rõ. Nói chuyện kiểu nói nửa câu mệt lắm.
Em cập nhật ngày giờ bằng Shell từ kết quả code của anh thấy nó cập nhật ngay và luôn trên thanh Taskbar, riêng hàm =Today() thì nhấn F9 nó mới cập nhật. Em nghĩ mình có nên dùng Shell hay không ạ?
Chỗ này là nói về cái gì? Trong code của mình bạn dùng Shell.Run, vậy Shell ở đây là đối tượng Shell? Hay Shell ở đây là "Windows Shell", hàm ý là thao tác thông qua giao diện (interface) của system, tức làm bằng tay?
Anh hỏi em mục đích làm gì thì xin thưa rằng, em làm việc trên Form là chủ yếu,
Nếu không có tập tin ví dụ với code và chỉ ra cụ thể các bước thao tác thì tôi chịu không hiểu. Vd.: Tôi có thiết lập trong CP thế này ..., khi mở Form tôi chọn ngày này ..., khi ghi vào csdl thì nó thành thế này ... Vậy vấn đề là thế này ...

Vì không có tập tin với code, mô tả trường dữ liệu v...v nên tôi thấy hơi ngạc nhiên là để làm cái việc nhập ngày tháng lại phải thay đổi gì đó trong CP.
ngày tháng nhập chuẩn phải là "dd/MM/yyyy",
Tại sao cứ bắt nhập chuẩn là "dd/MM/yyyy"? Nếu trên máy tôi mà nhập "2018-05-15" thì mới chuẩn vì đó là thiết lập trong CP. Nếu trên máy người khác trong CP có thiết lập "mm/dd/yyyy" thì phải nhập 05/15/2018 thì mới là chuẩn. Nếu bạn có trong CP mm/dd/yyyy và bạn nhập vào A1 = 15/05/2018 thì đó có phải là ngày tháng theo cách hiểu của Excel không? Hay đó chỉ là nhìn giống ngày tháng?
tuy nhiên nhập từ Calendar vào TextBox thì nó cứ ngược "MM/dd/yyyy" (theo định dạng của máy) làm cho người dùng rất dễ bị lẫn lộn giữa 05/04/2018 và 04/05/2018.
Chỗ này không chính xác. Tại sao lại là "MM/dd/yyyy"? Nếu code của bạn là
Mã:
Me.TextBox1.Value = Me.Calendar1.Value
thì dạng trong TextBox1 luôn là dạng thiết lập trong CP. Tức nếu trong CP có mm/dd/yyyy thì trong TextBox1 có 05/15/2018, nhưng nếu trong CP là dd/mm/yyyy thì trong TextBox1 là 15/05/2018. Như thế luôn chuẩn. Nếu bạn sợ người ta nhầm lẫn và qui định cứng nhắc luôn là trong TextBox phải có dạng dd/mm/yyyy thì dùng
Mã:
Me.TextBox1.Value = Format(Me.Calendar1.Value, "dd/mm/yyyy")
Chính vì thế em muốn mọi thứ được đồng bộ một kiểu, nếu em định dạng theo kiểu VN thì vào CSDL nó đảo lại thành sai ngày tháng, cho nên mới nhờ mọi người giúp đỡ, may mắn gặp được anh.
Trong csdl thì cái trường đó có kiểu gì? Nếu là TEXT thì khi ghi vào csdl thì ghi TextBox1.Value thôi (với định dạng trong TextBox và csdl là dd/mm/yyyy).
Nếu là kiểu số (ngày tháng) thì:
code nhập vào TextBox
Mã:
' định dạng để nhân viên ngơ ngơ ngác ngác nhìn quen quen
Me.TextBox1.Value = Format(Me.Calendar1.Value, "dd/mm/yyyy")
' nghi nhớ giá trị
Me.TextBox1.Tag = CLng(Me.Calendar1.Value)
Sau đó ghi số vào csdl: CLng(TextBox1.Tag) hoặc ghi ngày tháng vào csdl: CDate(TextBox1.Tag)

Tại sao lại phải thay đổi gì đó trong CP với việc cỏn con ấy nhỉ??? Khó hiểu
 
Upvote 0
Nói chuyện kiểu nói tắt này mệt lắm.

Chỗ này là nói tới việc thay đổi ngày giờ hay nói tới thay đổi định dạng ngắn cho ngày tháng?
Nếu là nói về định dạng ngắn cho ngày tháng thì sao lại phải có thay đổi chỗ đồng hồ trên taskbar? Trên máy tôi thì đồng hồ chỉ thời gian, còn khi đưa chuột vào đồng hồ thì tip chỉ ngày tháng ở dạng dài. Nhưng code thay đổi định dạng ngắn của ngày tháng vậy thì thời gian đâu có thay đổi, định dạng dài của ngày tháng đâu có thay đổi để mà mong chờ cập nhật? Còn nếu ý khác thì xin nói rõ. Nói chuyện kiểu nói nửa câu mệt lắm.

Chỗ này là nói về cái gì? Trong code của mình bạn dùng Shell.Run, vậy Shell ở đây là đối tượng Shell? Hay Shell ở đây là "Windows Shell", hàm ý là thao tác thông qua giao diện (interface) của system, tức làm bằng tay?

Nếu không có tập tin ví dụ với code và chỉ ra cụ thể các bước thao tác thì tôi chịu không hiểu. Vd.: Tôi có thiết lập trong CP thế này ..., khi mở Form tôi chọn ngày này ..., khi ghi vào csdl thì nó thành thế này ... Vậy vấn đề là thế này ...

Vì không có tập tin với code, mô tả trường dữ liệu v...v nên tôi thấy hơi ngạc nhiên là để làm cái việc nhập ngày tháng lại phải thay đổi gì đó trong CP.

Tại sao cứ bắt nhập chuẩn là "dd/MM/yyyy"? Nếu trên máy tôi mà nhập "2018-05-15" thì mới chuẩn vì đó là thiết lập trong CP. Nếu trên máy người khác trong CP có thiết lập "mm/dd/yyyy" thì phải nhập 05/15/2018 thì mới là chuẩn. Nếu bạn có trong CP mm/dd/yyyy và bạn nhập vào A1 = 15/05/2018 thì đó có phải là ngày tháng theo cách hiểu của Excel không? Hay đó chỉ là nhìn giống ngày tháng?

Chỗ này không chính xác. Tại sao lại là "MM/dd/yyyy"? Nếu code của bạn là
Mã:
Me.TextBox1.Value = Me.Calendar1.Value
thì dạng trong TextBox1 luôn là dạng thiết lập trong CP. Tức nếu trong CP có mm/dd/yyyy thì trong TextBox1 có 05/15/2018, nhưng nếu trong CP là dd/mm/yyyy thì trong TextBox1 là 15/05/2018. Như thế luôn chuẩn. Nếu bạn sợ người ta nhầm lẫn và qui định cứng nhắc luôn là trong TextBox phải có dạng dd/mm/yyyy thì dùng
Mã:
Me.TextBox1.Value = Format(Me.Calendar1.Value, "dd/mm/yyyy")

Trong csdl thì cái trường đó có kiểu gì? Nếu là TEXT thì khi ghi vào csdl thì ghi TextBox1.Value thôi (với định dạng trong TextBox và csdl là dd/mm/yyyy).
Nếu là kiểu số (ngày tháng) thì:
code nhập vào TextBox
Mã:
' định dạng để nhân viên ngơ ngơ ngác ngác nhìn quen quen
Me.TextBox1.Value = Format(Me.Calendar1.Value, "dd/mm/yyyy")
' nghi nhớ giá trị
Me.TextBox1.Tag = CLng(Me.Calendar1.Value)
Sau đó ghi số vào csdl: CLng(TextBox1.Tag) hoặc ghi ngày tháng vào csdl: CDate(TextBox1.Tag)

Tại sao lại phải thay đổi gì đó trong CP với việc cỏn con ấy nhỉ??? Khó hiểu
Có thể em diễn giải khó hiểu, tức là nhiều người dùng họ dùng chung một máy (tạm gọi là thay ca đi), và có nhiều máy cài đặt định dạng khác nhau, nhưng người ta xài chỉ biết hiển thị là ngày/tháng/năm chứ mỗi lần đão ngược là họ thắc mắc, họ cứ sợ họ nhập sai, bởi lúc thì kiểu này khi thì kiểu khác. Chứ khi làm em biết cách hoán đổi định dạng như thế nào để không bị lỗi, cái em muốn là cái hiển thị sao cho rất Việt Nam (giờ nhờ anh chỉ thêm cái TAG). Tuy nhiên nếu chỉ đơn giản vậy thì khỏe quá, dữ liệu nó được load lên ở các ComboBox, ListBox, kêu em nhớ sao đây? Như cái hình thì cái TextBox (ngày phát hành) là theo dd/mm/yyyy, nhưng dữ liệu load lên từ ComboBox (Tên tàu) nó lại m/d/yyyy.

HinhTest.jpg

Ngoài vấn đề biết thêm các hướng xử lý, thì được học hỏi thêm cách thâm nhập vào control panel thì cũng rất bổ ích Anh à, được những người uyên thâm như anh chỉ dạy là vinh dự lớn cho em.

Hôm qua test file EXE mà quên báo rằng máy em nó bị tình trạng thế này thì làm sao ạ?

Message.jpg
 
Lần chỉnh sửa cuối:
Upvote 0
Hôm qua test file EXE mà quên báo rằng máy em nó bị tình trạng thế này thì làm sao ạ?
Tôi soạn tập tin project1.exe (VB6) trên C:\ có code như đã đưa.
Sau đó tôi chạy code
Mã:
Sub sua()
Dim strFormat As String
    If GetLocaleInfoString(GetUserDefaultLCID, LOCALE_IDATE) <> "1" Then
'        ghi nho dinh dang hien hanh
        oldFormat = GetLocaleInfoString(GetUserDefaultLCID, LOCALE_SSHORTDATE)
'        Windows khong chap nhan "dd/mm/yyyy". Phai la "dd/MM/yyyy"
        strFormat = "dd/MM/yyyy"
'        thay doi dinh dang
        SetLocaleInfoW GetUserDefaultLCID, LOCALE_SSHORTDATE, StrConv(strFormat, vbUnicode)
        CreateObject("Wscript.Shell").Run "c:\project1.exe"
    End If
End Sub
thì chả có thông báo gì và định dạng ngày tháng được cập nhật.

Lỗi hơi vô lý. Code không truy cập tới bất cứ chỗ "nhậy cảm" nào trong system. Những ứng dụng trong system liên tục gửi thông điệp có sao đâu. Mà kiến trúc của Windows dựa trên nền tảng thông điệp - hàng ngàn thông điệp WM_***.

Dù gì thì tôi chưa bao giờ gặp lỗi.
-------------
Cách 2.
Như tôi đã nói nếu từ trong lòng ứng dụng Excel gửi thông điệp thì không có tác dụng. Vậy thì ta từ ứng dụng khác gửi thông điệp. Ở trên là do project1.exe gửi. Bây giờ ta khởi động process Excel thứ 2 và nó sẽ gửi thông điệp. Và thông điệp sẽ có tác dụng với process Excel thứ nhất do gửi từ ngoài.
1. Soạn tập tin c:\project1.xlsm có 1 sheet cho nhẹ, và code trong ThisWorkBook
Mã:
Private Const WM_SETTINGCHANGE = &H1A
Private Const HWND_BROADCAST = &HFFFF&

Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long

Private Sub Workbook_Open()
    SendMessage HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0
    Application.Quit
End Sub
Ghi lại vd. trên C:\ hoặc trong cùng thư mục với tập tin thứ nhất, và đóng Excel

2. Mở tập tin có code sau và chạy nó
Mã:
Sub sua()
Dim strFormat As String
    If GetLocaleInfoString(GetUserDefaultLCID, LOCALE_IDATE) <> "1" Then
'        ghi nho dinh dang hien hanh
        oldFormat = GetLocaleInfoString(GetUserDefaultLCID, LOCALE_SSHORTDATE)
'        Windows khong chap nhan "dd/mm/yyyy". Phai la "dd/MM/yyyy"
        strFormat = "dd/MM/yyyy"
'        thay doi dinh dang
        SetLocaleInfoW GetUserDefaultLCID, LOCALE_SSHORTDATE, StrConv(strFormat, vbUnicode)
        CreateObject("Excel.Application").Workbooks.Open "c:\project1.xlsm"
    End If
End Sub

Sub trave()
'    neu dinh dang da thay doi boi code ...
    If Len(oldFormat) Then
'        tra ve dinh dang cu
        SetLocaleInfoW GetUserDefaultLCID, LOCALE_SSHORTDATE, StrConv(oldFormat, vbUnicode)
        CreateObject("Excel.Application").Workbooks.Open "c:\project1.xlsm"
        oldFormat = ""
    End If
End Sub

Trong CP có thay đổi và ngày tháng trong các ô trên sheet cũng thay đổi định dạng.

Cách 3: chưa nghĩ ra :D. Cái đầu vẫn liên tục nghĩ nhưng vẫn chưa có ý tưởng.
 
Upvote 0
Tôi soạn tập tin project1.exe (VB6) trên C:\ có code như đã đưa.
Sau đó tôi chạy code
Mã:
Sub sua()
Dim strFormat As String
    If GetLocaleInfoString(GetUserDefaultLCID, LOCALE_IDATE) <> "1" Then
'        ghi nho dinh dang hien hanh
        oldFormat = GetLocaleInfoString(GetUserDefaultLCID, LOCALE_SSHORTDATE)
'        Windows khong chap nhan "dd/mm/yyyy". Phai la "dd/MM/yyyy"
        strFormat = "dd/MM/yyyy"
'        thay doi dinh dang
        SetLocaleInfoW GetUserDefaultLCID, LOCALE_SSHORTDATE, StrConv(strFormat, vbUnicode)
        CreateObject("Wscript.Shell").Run "c:\project1.exe"
    End If
End Sub
thì chả có thông báo gì và định dạng ngày tháng được cập nhật.

Lỗi hơi vô lý. Code không truy cập tới bất cứ chỗ "nhậy cảm" nào trong system. Những ứng dụng trong system liên tục gửi thông điệp có sao đâu. Mà kiến trúc của Windows dựa trên nền tảng thông điệp - hàng ngàn thông điệp WM_***.

Dù gì thì tôi chưa bao giờ gặp lỗi.
-------------
Cách 2.
Như tôi đã nói nếu từ trong lòng ứng dụng Excel gửi thông điệp thì không có tác dụng. Vậy thì ta từ ứng dụng khác gửi thông điệp. Ở trên là do project1.exe gửi. Bây giờ ta khởi động process Excel thứ 2 và nó sẽ gửi thông điệp. Và thông điệp sẽ có tác dụng với process Excel thứ nhất do gửi từ ngoài.
1. Soạn tập tin c:\project1.xlsm có 1 sheet cho nhẹ, và code trong ThisWorkBook
Mã:
Private Const WM_SETTINGCHANGE = &H1A
Private Const HWND_BROADCAST = &HFFFF&

Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long

Private Sub Workbook_Open()
    SendMessage HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0
    Application.Quit
End Sub
Ghi lại vd. trên C:\ hoặc trong cùng thư mục với tập tin thứ nhất, và đóng Excel

2. Mở tập tin có code sau và chạy nó
Mã:
Sub sua()
Dim strFormat As String
    If GetLocaleInfoString(GetUserDefaultLCID, LOCALE_IDATE) <> "1" Then
'        ghi nho dinh dang hien hanh
        oldFormat = GetLocaleInfoString(GetUserDefaultLCID, LOCALE_SSHORTDATE)
'        Windows khong chap nhan "dd/mm/yyyy". Phai la "dd/MM/yyyy"
        strFormat = "dd/MM/yyyy"
'        thay doi dinh dang
        SetLocaleInfoW GetUserDefaultLCID, LOCALE_SSHORTDATE, StrConv(strFormat, vbUnicode)
        CreateObject("Excel.Application").Workbooks.Open "c:\project1.xlsm"
    End If
End Sub

Sub trave()
'    neu dinh dang da thay doi boi code ...
    If Len(oldFormat) Then
'        tra ve dinh dang cu
        SetLocaleInfoW GetUserDefaultLCID, LOCALE_SSHORTDATE, StrConv(oldFormat, vbUnicode)
        CreateObject("Excel.Application").Workbooks.Open "c:\project1.xlsm"
        oldFormat = ""
    End If
End Sub

Trong CP có thay đổi và ngày tháng trong các ô trên sheet cũng thay đổi định dạng.

Cách 3: chưa nghĩ ra :D. Cái đầu vẫn liên tục nghĩ nhưng vẫn chưa có ý tưởng.
Tôi soạn tập tin project1.exe (VB6) trên C:\ có code như đã đưa.
Sau đó tôi chạy code
Mã:
Sub sua()
Dim strFormat As String
    If GetLocaleInfoString(GetUserDefaultLCID, LOCALE_IDATE) <> "1" Then
'        ghi nho dinh dang hien hanh
        oldFormat = GetLocaleInfoString(GetUserDefaultLCID, LOCALE_SSHORTDATE)
'        Windows khong chap nhan "dd/mm/yyyy". Phai la "dd/MM/yyyy"
        strFormat = "dd/MM/yyyy"
'        thay doi dinh dang
        SetLocaleInfoW GetUserDefaultLCID, LOCALE_SSHORTDATE, StrConv(strFormat, vbUnicode)
        CreateObject("Wscript.Shell").Run "c:\project1.exe"
    End If
End Sub
thì chả có thông báo gì và định dạng ngày tháng được cập nhật.

Lỗi hơi vô lý. Code không truy cập tới bất cứ chỗ "nhậy cảm" nào trong system. Những ứng dụng trong system liên tục gửi thông điệp có sao đâu. Mà kiến trúc của Windows dựa trên nền tảng thông điệp - hàng ngàn thông điệp WM_***.

Dù gì thì tôi chưa bao giờ gặp lỗi.
-------------
Cách 2.
Như tôi đã nói nếu từ trong lòng ứng dụng Excel gửi thông điệp thì không có tác dụng. Vậy thì ta từ ứng dụng khác gửi thông điệp. Ở trên là do project1.exe gửi. Bây giờ ta khởi động process Excel thứ 2 và nó sẽ gửi thông điệp. Và thông điệp sẽ có tác dụng với process Excel thứ nhất do gửi từ ngoài.
1. Soạn tập tin c:\project1.xlsm có 1 sheet cho nhẹ, và code trong ThisWorkBook
Mã:
Private Const WM_SETTINGCHANGE = &H1A
Private Const HWND_BROADCAST = &HFFFF&

Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long

Private Sub Workbook_Open()
    SendMessage HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0
    Application.Quit
End Sub
Ghi lại vd. trên C:\ hoặc trong cùng thư mục với tập tin thứ nhất, và đóng Excel

2. Mở tập tin có code sau và chạy nó
Mã:
Sub sua()
Dim strFormat As String
    If GetLocaleInfoString(GetUserDefaultLCID, LOCALE_IDATE) <> "1" Then
'        ghi nho dinh dang hien hanh
        oldFormat = GetLocaleInfoString(GetUserDefaultLCID, LOCALE_SSHORTDATE)
'        Windows khong chap nhan "dd/mm/yyyy". Phai la "dd/MM/yyyy"
        strFormat = "dd/MM/yyyy"
'        thay doi dinh dang
        SetLocaleInfoW GetUserDefaultLCID, LOCALE_SSHORTDATE, StrConv(strFormat, vbUnicode)
        CreateObject("Excel.Application").Workbooks.Open "c:\project1.xlsm"
    End If
End Sub

Sub trave()
'    neu dinh dang da thay doi boi code ...
    If Len(oldFormat) Then
'        tra ve dinh dang cu
        SetLocaleInfoW GetUserDefaultLCID, LOCALE_SSHORTDATE, StrConv(oldFormat, vbUnicode)
        CreateObject("Excel.Application").Workbooks.Open "c:\project1.xlsm"
        oldFormat = ""
    End If
End Sub

Trong CP có thay đổi và ngày tháng trong các ô trên sheet cũng thay đổi định dạng.

Cách 3: chưa nghĩ ra :D. Cái đầu vẫn liên tục nghĩ nhưng vẫn chưa có ý tưởng.
Chào anh,

Em cũng đã làm theo các cách mà anh hướng dẫn, tuy nhiên nó không update ngày tháng liền ạ, kể cả thoát file tất cả rồi mở lại.

Em có một số mã nguồn mà không biết sử dụng như thế nào, không biết anh có giúp được cho em trong trường hợp này không?

Mã:
Option Explicit

'Define Variables
Dim wshShell, oFSO
Dim Locale, RegionalSettingsFolder, RegionalSettingsFile

'Initialize Variables
Set wshShell = WScript.CreateObject("WScript.Shell")
Set oFSO = CreateObject("Scripting.FileSystemObject")

' Path to where the registry files are stored
RegionalSettingsFolder = "C:\regionalsettings"

' Change this to the Locale/Region you want like:
' EAST, WEST, MOUNTAIN, LONDON, BRUSSELS etc
Locale = EAST

' I log most things to the event log versus wscript.echo - feel free to change this
wshShell.LogEvent 4, "Office Identified: " & Locale

RegionalSettingsFile = WinDir & "\RegionalSettings_" & Locale & ".reg"

If oFSO.FileExists(RegionalSettingsFile) Then
    ' Load Default User Registry Hive for Windows XP
    wshShell.Run "%comspec% /c REG LOAD HKLM\.DEFAULT ""C:\Documents and Settings\default user\NTUSER.DAT""", 0, True

    ' Load Default User Registry Hive for Vista, 7 etc
    'wshShell.Run "%comspec% /c REG LOAD HKLM\.DEFAULT ""C:\users\default\NTUSER.DAT""",0,True

    wshShell.Run "%comspec% /c regedit /s " & RegionalSettingsFile, 0, True
    wshShell.Run "%comspec% /c REG UNLOAD HKLM\.DEFAULT", 0, True

    wshShell.LogEvent 4, Locale & " Regional Settings Updated in Default User"
Else
    wshShell.LogEvent 4, Locale & " Regional Settings have NOT been updated"
End If



'Save each one of the registry settings below as separate .REG files using the following naming convention:

RegionalSettings_EAST.reg
RegionalSettings_LONDON.reg
RegionalSettings_WEST.reg
'--------------------------------BRUSSELS------------------------------

'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\.DEFAULT\Control Panel\International]
'"iCountry"="32"
'"iCurrDigits"="2"
'"iCurrency"="3"
'"iDate"="1"
'"iDigits"="2"
'"iLZero"="1"
'"iMeasure"="0"
'"iNegCurr"="8"
'"iTime"="0"
'"iTLZero"="1"
'"Locale"="00000409"
'"s1159"="AM"
'"s2359"="PM"
'"sCountry"="Belgium"
'"sCurrency"="€"
'"sDate"="/"
'"sDecimal"="."
'"sLanguage"="FRB"
'"sList"=","
'"sLongDate"="dddd, dd, MMM, yyyy"
'"sShortDate"="d/M/yyyy"
'"sThousand"="."
'"sTime"=":"
'"sTimeFormat"="HH:mm:ss"
'"iTimePrefix"="0"
'"sMonDecimalSep"=","
'"sMonThousandSep"=","
'"iNegNumber"="1"
'"sNativeDigits"="0123456789"
'"NumShape"="1"
'"iCalendarType"="1"
'"iFirstDayOfWeek"="0"
'"iFirstWeekOfYear"="0"
'"sGrouping"="3;0"
'"sMonGrouping"="3;0"
'"sPositiveSign"=""
'"sNegativeSign"="-"

[HKEY_LOCAL_MACHINE\.DEFAULT\Control Panel\International\Geo]
'"Nation"="21"

'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\IMEtoggle]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\IMEtoggle\scancode]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Preload]
'"2"="00000409"
'"1"="0000080c"
'"3"="00000813"

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Substitutes]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Toggle]
'"Hotkey"="1"
'"Language Hotkey"="1"
'"Layout Hotkey"="2"

[HKEY_USERS\.DEFAULT\Keyboard Layout\Preload]
'"1"="0000080c"
'"2"="00000809"
'
'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\.DEFAULT\Software\Microsoft\CTF]
'"Disable Thread Input Manager"=dword:00000000

[HKEY_LOCAL_MACHINE\.DEFAULT\Software\Microsoft\CTF\LangBar]
'"ShowStatus"=dword:00000004

[HKEY_LOCAL_MACHINE\.DEFAULT\Software\Microsoft\CTF\Sapilayr]
'"ProfileInitialized"=dword:00000000

[HKEY_LOCAL_MACHINE\.DEFAULT\Software\Microsoft\CTF\MSUTB]
'"ShowDeskBand"=dword:00000001

[HKEY_LOCAL_MACHINE\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Run]
'"ctfmon.exe"="C:\\WINDOWS\\System32\\ctfmon.exe"

'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation]
'"Bias"=dword:ffffffc4
'"StandardName"="Romance Standard Time"
'"StandardBias"=dword:00000000
'"StandardStart"=hex:00,00,0a,00,05,00,03,00,00,00,00,00,00,00,00,00
'"DaylightName"="Romance Daylight Time"
'"DaylightBias"=dword:ffffffc4
'"DaylightStart"=hex:00,00,03,00,05,00,02,00,00,00,00,00,00,00,00,00
'"ActiveTimeBias"=dword:ffffffc4
'
'---------------------------------------------------------------------------
'
'----------------------------LONDON----------------------------------
'
'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\.DEFAULT\Control Panel\International]
'"iCountry"="44"
'"iCurrDigits"="2"
'"iCurrency"="0"
'"iDate"="1"
'"iDigits"="2"
'"iLZero"="1"
'"iMeasure"="0"
'"iNegCurr"="1"
'"iTime"="1"
'"iTLZero"="1"
'"Locale"="00000809"
'"s1159"="AM"
'"s2359"="PM"
'"sCountry"="United Kingdom"
'"sCurrency"="£"
'"sDate"="/"
'"sDecimal"="."
'"sLanguage"="ENG"
'"sList"=","
'"sLongDate"="dd MMMM yyyy"
'"sShortDate"="d/M/yyyy"
'"sThousand"=","
'"sTime"=":"
'"sTimeFormat"="HH:mm:ss"
'"iTimePrefix"="0"
'"sMonDecimalSep"="."
'"sMonThousandSep"=","
'"iNegNumber"="1"
'"sNativeDigits"="0123456789"
'"NumShape"="1"
'"iCalendarType"="1"
'"iFirstDayOfWeek"="0"
'"iFirstWeekOfYear"="0"
'"sGrouping"="3;0"
'"sMonGrouping"="3;0"
'"sPositiveSign"=""
'"sNegativeSign"="-"

[HKEY_LOCAL_MACHINE\.DEFAULT\Control Panel\International\Geo]
'"Nation"="242"

'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\IMEtoggle]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\IMEtoggle\scancode]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Preload]
'"1"="00000809"

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Substitutes]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Toggle]
'"Hotkey"="1"
'"Language Hotkey"="1"
'"Layout Hotkey"="2"

[HKEY_USERS\.DEFAULT\Keyboard Layout\Preload]
'"1"="00000809"

'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation]
'"Bias"=dword:00000000
'"StandardName"="GMT Standard Time"
'"StandardBias"=dword:00000000
'"StandardStart"=hex:00,00,0a,00,05,00,02,00,00,00,00,00,00,00,00,00
'"DaylightName"="GMT Daylight Time"
'"DaylightBias"=dword:ffffffc4
'"DaylightStart"=hex:00,00,03,00,05,00,01,00,00,00,00,00,00,00,00,00
'"ActiveTimeBias"=dword:00000000
'
'------------------------------------------------------------------------
'
'----------------------------US EAST COAST-------------------------
'
'Windows Registry Editor Version 5.00
'
[HKEY_LOCAL_MACHINE\.DEFAULT\Control Panel\International]
'"iCountry"="1"
'"iCurrDigits"="2"
'"iCurrency"="0"
'"iDate"="0"
'"iDigits"="2"
'"iLZero"="1"
'"iMeasure"="1"
'"iNegCurr"="0"
'"iTime"="0"
'"iTLZero"="0"
'"Locale"="00000409"
'"s1159"="AM"
'"s2359"="PM"
'"sCountry"="United States"
'"sCurrency"="$"
'"sDate"="/"
'"sDecimal"="."
'"sLanguage"="ENU"
'"sList"=","
'"sLongDate"="dddd, MMMM dd, yyyy"
'"sShortDate"="M/d/yyyy"
'"sThousand"=","
'"sTime"=":"
'"sTimeFormat"="h:mm:ss tt"
'"iTimePrefix"="0"
'"sMonDecimalSep"="."
'"sMonThousandSep"=","
'"iNegNumber"="1"
'"sNativeDigits"="0123456789"
'"NumShape"="1"
'"iCalendarType"="1"
'"iFirstDayOfWeek"="6"
'"iFirstWeekOfYear"="0"
'"sGrouping"="3;0"
'"sMonGrouping"="3;0"
'"sPositiveSign"=""
'"sNegativeSign"="-"

[HKEY_LOCAL_MACHINE\.DEFAULT\Control Panel\International\Geo]
'"Nation"="244"

'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\IMEtoggle]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\IMEtoggle\scancode]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Preload]
'"1"="00000409"

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Substitutes]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Toggle]
'"Hotkey"="3"
'"Language Hotkey"="3"
'"Layout Hotkey"="3"

[HKEY_USERS\.DEFAULT\Keyboard Layout\Preload]
'"1"="00000409"
'
'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation]
'"Bias"=dword:0000012c
'"StandardName"="Eastern Standard Time"
'"StandardBias"=dword:00000000
'"StandardStart"=hex:00,00,0b,00,01,00,02,00,00,00,00,00,00,00,00,00
'"DaylightName"="Eastern Daylight Time"
'"DaylightBias"=dword:ffffffc4
'"DaylightStart"=hex:00,00,03,00,02,00,02,00,00,00,00,00,00,00,00,00
'"ActiveTimeBias"=dword:000000f0
'
'------------------------------------------------------------------------
'
'-------------------------US WEST COAST---------------------------
'
'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\.DEFAULT\Control Panel\International]
'"iCountry"="1"
'"iCurrDigits"="2"
'"iCurrency"="0"
'"iDate"="0"
'"iDigits"="2"
'"iLZero"="1"
'"iMeasure"="1"
'"iNegCurr"="0"
'"iTime"="0"
'"iTLZero"="0"
'"Locale"="00000409"
'"s1159"="AM"
'"s2359"="PM"
'"sCountry"="United States"
'"sCurrency"="$"
'"sDate"="/"
'"sDecimal"="."
'"sLanguage"="ENU"
'"sList"=","
'"sLongDate"="dddd, MMMM dd, yyyy"
'"sShortDate"="M/d/yyyy"
'"sThousand"=","
'"sTime"=":"
'"sTimeFormat"="h:mm:ss tt"
'"iTimePrefix"="0"
'"sMonDecimalSep"="."
'"sMonThousandSep"=","
'"iNegNumber"="1"
'"sNativeDigits"="0123456789"
'"NumShape"="1"
'"iCalendarType"="1"
'"iFirstDayOfWeek"="6"
'"iFirstWeekOfYear"="0"
'"sGrouping"="3;0"
'"sMonGrouping"="3;0"
'"sPositiveSign"=""
'"sNegativeSign"="-"

[HKEY_LOCAL_MACHINE\.DEFAULT\Control Panel\International\Geo]
'"Nation"="244"
'
'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\IMEtoggle]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\IMEtoggle\scancode]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Preload]
'"1"="00000409"

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Substitutes]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Toggle]
'"Hotkey"="3"
'"Language Hotkey"="3"
'"Layout Hotkey"="3"

[HKEY_USERS\.DEFAULT\Keyboard Layout\Preload]
'"1"="00000409"
'
'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation]
'"Bias"=dword:000001e0
'"StandardName"="Pacific Standard Time"
'"StandardBias"=dword:00000000
'"StandardStart"=hex:00,00,0b,00,01,00,02,00,00,00,00,00,00,00,00,00
'"DaylightName"="Pacific Daylight Time"
'"DaylightBias"=dword:ffffffc4
'"DaylightStart"=hex:00,00,03,00,02,00,02,00,00,00,00,00,00,00,00,00
'"ActiveTimeBias"=dword:000001a4
'
'------------------------------------------------------------------------
'
'--------------------------US Mountain--------------------------------
'
'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\.DEFAULT\Control Panel\International]
'"iCountry"="1"
'"iCurrDigits"="2"
'"iCurrency"="0"
'"iDate"="0"
'"iDigits"="2"
'"iLZero"="1"
'"iMeasure"="1"
'"iNegCurr"="0"
'"iTime"="0"
'"iTLZero"="0"
'"Locale"="00000409"
'"s1159"="AM"
'"s2359"="PM"
'"sCountry"="United States"
'"sCurrency"="$"
'"sDate"="/"
'"sDecimal"="."
'"sLanguage"="ENU"
'"sList"=","
'"sLongDate"="dddd, MMMM dd, yyyy"
'"sShortDate"="M/d/yyyy"
'"sThousand"=","
'"sTime"=":"
'"sTimeFormat"="h:mm:ss tt"
'"iTimePrefix"="0"
'"sMonDecimalSep"="."
'"sMonThousandSep"=","
'"iNegNumber"="1"
'"sNativeDigits"="0123456789"
'"NumShape"="1"
'"iCalendarType"="1"
'"iFirstDayOfWeek"="6"
'"iFirstWeekOfYear"="0"
'"sGrouping"="3;0"
'"sMonGrouping"="3;0"
'"sPositiveSign"=""
'"sNegativeSign"="-"

[HKEY_LOCAL_MACHINE\.DEFAULT\Control Panel\International\Geo]
'"Nation"="244"
'
'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\IMEtoggle]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\IMEtoggle\scancode]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Preload]
'"1"="00000409"

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Substitutes]

[HKEY_LOCAL_MACHINE\.DEFAULT\Keyboard Layout\Toggle]
'"Hotkey"="3"
'"Language Hotkey"="3"
'"Layout Hotkey"="3"

[HKEY_USERS\.DEFAULT\Keyboard Layout\Preload]
'"1"="00000409"
'
'Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation]
'"Bias"=dword:000001a4
'"StandardName"="Mountain Standard Time"
'"StandardBias"=dword:00000000
'"StandardStart"=hex:00,00,0b,00,01,00,02,00,00,00,00,00,00,00,00,00
'"DaylightName"="Mountain Daylight Time"
'"DaylightBias"=dword:ffffffc4
'"DaylightStart"=hex:00,00,03,00,02,00,02,00,00,00,00,00,00,00,00,00
'"ActiveTimeBias"=dword:00000168
 
Upvote 0
Em cũng đã làm theo các cách mà anh hướng dẫn, tuy nhiên nó không update ngày tháng liền ạ, kể cả thoát file tất cả rồi mở lại.
Tôi chạy trên XP Home và Excel 2010 như trong test.avi
Em có một số mã nguồn mà không biết sử dụng như thế nào, không biết anh có giúp được cho em trong trường hợp này không?
Nhưng giúp cái gì? Tôi không hiểu
 

File đính kèm

Upvote 0
Tôi chạy trên XP Home và Excel 2010 như trong test.avi

Nhưng giúp cái gì? Tôi không hiểu
Giúp em viết code chạy trong VBA để thay đổi Region & language từ những mã nguồn đó ạ. Do không biết gì nên không dám mạo hiểm thử từng cái, cũng như cấu trúc viết thế nào chưa biết.
 
Lần chỉnh sửa cuối:
Upvote 0
Giúp em viết code chạy trong VBA để thay đổi Region & language từ những mã nguồn đó ạ. Do không biết gì nên không dám mạo hiểm thử từng cái, cũng như cấu trúc viết thế nào chưa biết.
Tôi cũng chả hiểu bạn muốn gì.
Ở đây là người ta muốn thay đổi cái gì đấy trong Registry.

1. Có thể dùng code để thêm, sửa, xóa một khóa hoặc giá trị trong Registry. Bạn và nhiều người đã từng dùng code thư thế.

2. Có thể soạn 1 tập tin REG. Tập tin REG thậm chí có thể viết trong notepad và ghi với định dạng REG, vd. test.reg

Nhưng muốn viết trong notepad thì phải biết cú pháp. Ngoài ra dễ gõ sai, gõ thiếu ký tự. Cách tốt nhất cho người ít am hiểu là dùng Regedit.

Giả sử bạn có thiết lập <> "dd/MM/yyyy" và bạn muốn chuyển thành "dd/MM/yyyy". Vậy mở CP -> sửa định dạng thành "dd/MM/yyyy" -> OK -> OK -> mở regedit (vd. trên máy tôi nằm trong "c:\Windows") -> duyệt tới khóa "HKEY_CURRENT_USER\Control Panel\International". Sẽ thấy nhiều tên trong đó có "sShortDate" với giá trị dd/MM/yyyy -> File -> Export -> chọn ghi trên "C:\" với tên vd. test.reg

Như thế bạn đã có toàn bộ nội dung của khóa "International" với thiết lập mong đợi.

-> vào lại CP và chuyển định dạng về như cũ.

Tập tin REG có thể kích hoạt bằng code để làm mới Registry. Người không am tường code có thể: phải chuột trên test.reg -> chọn Merge (đại loại thế vì tôi có phiên bản Ba Lan nên không biết tên menu trong phiên bản tiếng Anh là gì)

Thế là có nội dung mới trong Registry và khi mở CP thì thấy có thiết lập mới.
------------
Trong cái bạn viết người ta nói là phải soạn tập tin REG cho khóa "International". Và nếu muốn thay đổi TimeZone thì khóa "TimeZoneInformation". Rôi dùng code để kích hoạt cái tập tin REG đấy. Thế thôi.
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom