Chuyển ngày từ chuỗi để Excel hiểu

Liên hệ QC

cantl

!!! Giải thoát !!!
Tham gia
6/8/08
Bài viết
1,805
Được thích
1,153
Giới tính
Nam
Tình hình là em mới mò được cái này. Tạm thời viết sơ sơ, chưa biết sẽ gặp những lỗi gì.
Mã:
Public Function NgayTuChuoi(CellNgay As Range) As String
    Dim Regex As Object
    Dim Ngay As Object
    Set Regex = CreateObject("vbscript.regexp")
    With Regex
        .Global = True
        .pattern = "\d{2,4}[\/-]\d{1,2}[\/-]\d{2,4}"
       Set Ngay = Regex.Execute(CellNgay)
       End With
    NgayTuChuoi = Ngay(0)
End Function

Public Function NgayThat(CellNgay As Range, Optional Deli$ = "/", Optional TypeD$ = "dmy")
Dim arrNgay As Variant
Dim arrTypeD(3) As String
Dim Item As Variant
Dim NgayDangChuoi$
Dim Ngay%, Thang%, Nam%
arrTypeD(0) = Mid(TypeD, 1, 1)
arrTypeD(1) = Mid(TypeD, 2, 1)
arrTypeD(2) = Mid(TypeD, 3, 1)
NgayDangChuoi = NgayTuChuoi(CellNgay)
arrNgay = Split(NgayDangChuoi, Deli)
For Item = 0 To UBound(arrNgay)
Select Case arrTypeD(Item)
   Case Is = "d"
      Ngay = arrNgay(Item)
   Case Is = "m"
      Thang = arrNgay(Item)
   Case Else
      Nam = arrNgay(Item)
End Select
Next
NgayThat = DateSerial(Nam, Thang, Ngay)
End Function
Mục đích là như hình ảnh, khó diễn tả thành lời:

1697451460950.png

Hy vọng các bác lướt qua góp ý để em lại tiếp tục mò bổ sung.
File chưa bẫy lỗi vì trình độ không lường được sẽ gặp lỗi gì.
 

File đính kèm

  • Tach 1 ngay trong Chuoi.xlsm
    20.2 KB · Đọc: 10
=ngay(Date_Cell, Type)
với Type là 1 trong các loại sau = "dmy", "mdy","ydm","ymd"

PHP:
Option Explicit
Public Function Ngay(ce As Range, Optional typeD = "dmy")
Dim sp, c As Boolean
For Each sp In Split(ce)
    If InStr(1, sp, "/") Then
        sp = Split(sp, "/"): c = True
    ElseIf InStr(1, sp, "-") Then
        sp = Split(sp, "-"): c = True
    End If
    If c Then
        Select Case typeD
            Case "dmy"
                Ngay = DateSerial(sp(2), sp(1), sp(0))
            Case "mdy"
                Ngay = DateSerial(sp(2), sp(0), sp(1))
            Case "ydm"
                Ngay = DateSerial(sp(0), sp(2), sp(1))
            Case "ymd"
                Ngay = DateSerial(sp(0), sp(1), sp(2))
            Case Else
                Ngay = "Loai ngay thang khong hop le. Vui long chon lai!"
            End Select
        Exit Function
    End If
Next
End Function
 
Upvote 0
=ngay(Date_Cell, Type)
với Type là 1 trong các loại sau = "dmy", "mdy","ydm","ymd"

PHP:
Option Explicit
Public Function Ngay(ce As Range, Optional typeD = "dmy")
Dim sp, c As Boolean
For Each sp In Split(ce)
    If InStr(1, sp, "/") Then
        sp = Split(sp, "/"): c = True
    ElseIf InStr(1, sp, "-") Then
        sp = Split(sp, "-"): c = True
    End If
    If c Then
        Select Case typeD
            Case "dmy"
                Ngay = DateSerial(sp(2), sp(1), sp(0))
            Case "mdy"
                Ngay = DateSerial(sp(2), sp(0), sp(1))
            Case "ydm"
                Ngay = DateSerial(sp(0), sp(2), sp(1))
            Case "ymd"
                Ngay = DateSerial(sp(0), sp(1), sp(2))
            Case Else
                Ngay = "Loai ngay thang khong hop le. Vui long chon lai!"
            End Select
        Exit Function
    End If
Next
End Function
Chắc phải có rexeg bác ạ. Thiếu thì sẽ bị lỗi chút.

Với lại em đang vướng 1 chỗ là nếu lỡ tay nhập 1/13/23 hoặc 23/13/1 thì sẽ không báo lỗi mà tự động chuyển đúng thành 13/01/2023.
(nghĩa là nếu vị trí năm "y" đầu hoặc cuối đúng với typeD thì sẽ tự động chỉnh ngày tháng với các số trên 13 thay vì báo lỗi).
Chỉ báo lỗi khi thực sự ngày tháng năm sai hoàn toàn. VD:1/1/54697, ...
1697511746025.png

VD: như thế này sẽ tự động 13/12/2023.
slkda jflsd jflsa 12-13-23 ls ls sadkf
12/01/2024​
 
Upvote 0
Mục đích chính của bạn là gì?
1. Thử sáng kiến mới?
2. Thực tập viết pattern regex?
3. Thực tập làm việc vói dữ liệu trả về từ rx.Execute?
4. Thử kiến thức mình về các hàm chuyên Convert kiểu?

Theo như code trên, cả bốn điều đều lỗ hổng tùm lum. Nên chú trọng vào một cái thôi. Tham quá sẽ mắc nghẹn.
 
Upvote 0
Mục đích chính của bạn là gì?
1. Thử sáng kiến mới?
2. Thực tập viết pattern regex?
3. Thực tập làm việc vói dữ liệu trả về từ rx.Execute?
4. Thử kiến thức mình về các hàm chuyên Convert kiểu?

Theo như code trên, cả bốn điều đều lỗ hổng tùm lum. Nên chú trọng vào một cái thôi. Tham quá sẽ mắc nghẹn.
Hôm nọ có bài về ngày, em có nêu ra ý này nên mò thử bác ạ.
Em thấy nhiều bài đưa lên về ngày giờ lung tung nên viết đại ấy mà. Cũng là mò cách viết luôn.

Như trên em còn sót ngày giờ dạng xx.xx.xxxx nữa. Còn kiểu ngày giờ khác nữa thì thôi, 3 dạng /-. thông dụng hơn. Regex trên là code của diễn đàn, em cũng chỉ hiểu sơ sơ thôi.

Viết code trên là em mò về regex, function, array ấy, sửa đi sửa lại tè le luôn mới ra được. :wallbash::wallbash::wallbash:
 
Upvote 0
Mở VBE, vào cửa sổ Immediate, gõ:
? CDate("ngày")
Thử tất cả các dạng ngày tháng mà mình cho là hợp lý - nếu mình đoán được đạu khái ngày ấy thì phần lớn VBA cũng đoán được.
Sau nổ lực này, ít nhất bạn cũng nắm vững được một trong những hàm quan trọng nhất của nhóm convert kiểu.
 
Upvote 0
=ngay(Date_Cell, Type)
với Type là 1 trong các loại sau = "dmy", "mdy","ydm","ymd"

PHP:
Option Explicit
Public Function Ngay(ce As Range, Optional typeD = "dmy")
Dim sp, c As Boolean
For Each sp In Split(ce)
    If InStr(1, sp, "/") Then
        sp = Split(sp, "/"): c = True
    ElseIf InStr(1, sp, "-") Then
        sp = Split(sp, "-"): c = True
    End If
    If c Then
        Select Case typeD
            Case "dmy"
                Ngay = DateSerial(sp(2), sp(1), sp(0))
            Case "mdy"
                Ngay = DateSerial(sp(2), sp(0), sp(1))
            Case "ydm"
                Ngay = DateSerial(sp(0), sp(2), sp(1))
            Case "ymd"
                Ngay = DateSerial(sp(0), sp(1), sp(2))
            Case Else
                Ngay = "Loai ngay thang khong hop le. Vui long chon lai!"
            End Select
        Exit Function
    End If
Next
End Function
Theo như code thì phải biết đích xác type của ô nguồn để nhập cho hàm. Còn nguồn mà lung tung bộ đội như bài #1 thì kết quả cũng linh tinh bộ đội luôn. :p --=0:D
 
Upvote 0
Đúng là phải biết chuẩn của ô nguồn, kiểu như từ 1 phần mềm xuất ra, từ đó quyết định là:
- 1 trong 4 cái ("dmy", "mdy", "ydm", "ymd").
- Không áp dụng kiểu"y" nằm giữa vì kiểu này quý hiếm quá.
Hehe, regex bài 1 sai với ngày 1 ký tự. :wallbash: :wallbash: :wallbash:
Em đang mò, hiện tại ?cdate("2023-13-10") thì máy không hiểu... còn tiếp ...
 
Lần chỉnh sửa cuối:
Upvote 0
Dạng yyyy-mm-dd, yyyy-/mm/dd, yyyymmdd là dạng tiêu chuẩn để so sánh ngày theo kiểu chuỗi. Tiêu chuẩn quốc tế nó vậy, không phải của Windows hay VBA, không thể thay đổi.
 
Upvote 0
Dạng yyyy-mm-dd, yyyy-/mm/dd, yyyymmdd là dạng tiêu chuẩn để so sánh ngày theo kiểu chuỗi. Tiêu chuẩn quốc tế nó vậy, không phải của Windows hay VBA, không thể thay đổi.
Nếu theo chuẩn này thì em nghĩ không nên dùng hàm Cdate nữa, em đang so sánh từng giá trị với array(d,m,y), có lẽ nếu tháng>12 thì đảo "d" và "m".

Thêm nữa:
slkda jflsd jflsa 23-5-13 ls ls sadkf, em đang hiểu là 13/5/2023, Cdate hiểu là 23/5/2013.



Em còn vướng chỗ Regex thế này:

pattern = "\d{1,4}[\/|.|-]\d{1,2}[\/|.|-]\d{1,4}" sẽ lấy được 3 loại:
13/10/2023
13-10-2023
13.10.2023

nhưng nếu đổi chỗ "." và "-" (pattern = "\d{1,4}[\/|-|.]\d{1,2}[\/|-|.]\d{1,4}") thì lại chỉ lấy được 2 cái:
13/10/2023
13-10-2023
13.10.2023
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu bạn đang mặc định nó là "dd/mm/yyyy" theo tiêu chuẩn VN thì
Nếu ngày báo lỗi (tháng>12): đảo ngày và tháng
Nếu không báo lỗi thì để nguyên
 
Upvote 0
Nếu theo chuẩn này thì em nghĩ không nên dùng hàm Cdate nữa, em đang so sánh từng giá trị với array(d,m,y), có lẽ nếu tháng>12 thì đảo "d" và "m".
...
Bạn chưa thử đủ như tôi đề nghị ở bài #6.

1697532760750.png1697532809088.png

Cả đời, tôi vẫn tự hào rằng:
Nếu một người giỏi hơn tôi là do bẩm sinh người ấy có IQ cao hơn tôi. Nhưng không ai có thể hơn tôi do cố gắng hơn tôi cả.
 
Upvote 0
Bạn chưa thử đủ như tôi đề nghị ở bài #6.

View attachment 295827View attachment 295828

Cả đời, tôi vẫn tự hào rằng:
Nếu một người giỏi hơn tôi là do bẩm sinh người ấy có IQ cao hơn tôi. Nhưng không ai có thể hơn tôi do cố gắng hơn tôi cả.
Bài 8 em đang xét 2023 nằm đầu bác ơi.
Em test cũng nhiều, có thể sót, không thể lường hết được, nhưng tạm cho là nhiều cũng được mà.

1697533284330.png


Mã:
Cột G em đang định nghĩa hàm Cdate trong zzz thế này:
Function zzz(CellNgay As Range) As Date
zzz = CDate(NgayTuChuoi(CellNgay))
End Function

1697533364581.png
Bài đã được tự động gộp:

Tình hình lại ngày càng phức tạp, giờ lại đến việc hàm không tự động cập nhật. Phải F2, Enter mới thay đổi.
Liệu có phải em bị dính phốt là cùng tên biến 2 vị trí không ạ? VD cùng CellNgay ở 2 function, chắc em lại phải tìm hiểu byval byref rồi.

1697533795479.png
1697533809876.png
 
Lần chỉnh sửa cuối:
Upvote 0
nếu tháng>12 thì đảo "d" và "m"

Không ích gì cả, theo cách trên làm sao biết 06/07/2023 là tháng mấy?

Thế này vĩnh viễn không bao giờ hiểu được dữ liệu DateTime. Cả đời vật lộn với nó mà thôi.
 
Upvote 0
Chưa hiểu cấu trúc định dạng ngày tháng mà bỏ công ra viết mã, thì cộng đồng cũng bỏ công góp ý "té lên té xuống, xỉu lên xỉu xuống".

Tôi thấy riêng ở bài #1 là cần thêm kiến thức rất là nhiều.

(Chuỗi 2023-13-10 là chuỗi không hợp lệ là đúng rồi, vì năm đứng đầu thì tháng luôn luôn đứng giữa, làm gì có định nghĩa tháng đứng sau cùng)
 
Upvote 0
Không ích gì cả, theo cách trên làm sao biết 06/07/2023 là tháng mấy?
Giả sử muốn trích xuất ngày trên, và giả sử ngày trên từ phần mềm nào đó ra, thì người dùng phải biết nó là dạng nào để quyết định Tùy chọn TypeD như ảnh này mà:
1697534873043.png
(Chuỗi 2023-13-10 là chuỗi không hợp lệ là đúng rồi, vì năm đứng đầu thì tháng luôn luôn đứng giữa, làm gì có định nghĩa tháng đứng sau cùng)
Về việc ghi ngày tháng lẫn lộn thì có những lúc ghi nhầm thế này, và khi mình xét thì phải tự động chuyển về 13/10/2023 cho excel hiểu (nếu với ngày tháng đều dưới 12 thì phải chấp nhận chuỗi bị sai và trường hợp này là phải mặc kệ người dùng).

PS: thực sự là vấn đề ngày rất lộn xộn với nhiều bài đưa lên diễn đàn mà lúc là ngày, lúc là text nên tớ mới nghĩ ra cái món này, cũng là để bắt tay vào viết đoạn mã cho đàng hoàng. Tất nhiên về trình độ thì còn kém xa các bạn mà.
 
Upvote 0
Thôi tôi tạm ngưng chờ mấy bạn nào can đảm vào làm chốt thí. Có lẽ còn lại xa pháo mã trơn tru rồi mới vào thế được.

Tôi nghĩ là bạn đang ở tình trạng XY problem
1697536775386.png
Tạm dịch: bạn đang hỏi về cách giải quyết vấn đề của mình, thay vì đưa vấn đề ra để tìm cách khác giải quyết nó.
 
Upvote 0
Thôi tôi tạm ngưng chờ mấy bạn nào can đảm vào làm chốt thí. Có lẽ còn lại xa pháo mã trơn tru rồi mới vào thế được.

Tôi nghĩ là bạn đang ở tình trạng XY problem
View attachment 295837
Tạm dịch: bạn đang hỏi về cách giải quyết vấn đề của mình, thay vì đưa vấn đề ra để tìm cách khác giải quyết nó.
Vậy thay vì em đưa ra code rồi xin ý kiến thì em sẽ lập bài mới và xin code hoàn chỉnh sẽ dễ hơn. Để em nghiên cứu cách nêu ý tưởng bài mới đã.
 
Upvote 0
Hy vọng các bác hiểu ý là thay vì dùng hàm mid, left, right, find, date, ... để chuyển ngày dạng Text về dạng Number, thì em dùng Code.

Code lấy thêm ý tưởng bỏ tùy chọn dấu ngăn cách ngày (ngày mà viết liền thì em chịu), và đảo ngày tháng nếu vượt 12 sẽ không bị nhảy sang năm sau (ý bác bebo).

Tình hình em so sánh Cdate với Code mò nó sẽ như thế này.

Dữ liệu test này em nghĩ chắc là đầy đủ rồi phải không ạ?

PS: ảnh ở máy thì rõ mà lên đây mờ đi các bác ạ.
 

File đính kèm

  • Tach 1 ngay trong Chuoi.jpg
    Tach 1 ngay trong Chuoi.jpg
    145.8 KB · Đọc: 10
Upvote 0
Thì ra ý các cụ nói 49 chưa qua, 50 đã tới là nói về sự hiểu nhầm của hàm Cdate các bác ạ. :cool: :cool: :cool:

Và DateSerial cũng không hiểu được.

Tại sao lại có sự nhầm lẫn 50/50 này vậy ạ?

1697711168298.png

Hàm year thì hiểu đến 30 thôi. Thật là phức tạp.
1697711663825.png
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT

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

Back
Top Bottom