Liệt kê các ngày cộng dồn mong muốn vào 1 ô. Nhờ mọi người giúp mình ạ. (1 người xem)

Liên hệ QC

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

Tôi tuân thủ nội quy khi đăng bài

Manhhung90

Thành viên hoạt động
Tham gia
3/4/20
Bài viết
151
Được thích
7
Em muốn liệt kê tất cả các ngày mong muốn vào 1 ô như hình ảnh ạ. Nhờ mọi người giúp mình với ạ.
 

File đính kèm

  • 1000005749.jpg
    1000005749.jpg
    119.9 KB · Đọc: 41
Em muốn liệt kê tất cả các ngày mong muốn vào 1 ô như hình ảnh
Bạn làm theo các bước sau:
  • Nhấn F2 để vào chế độ nhập liệu (có thể bỏ qua)
  • Nhập ngày mong muốn thứ nhất
  • Nhập dấu phẩy (,)
  • Nhập ngày mong muốn thứ hai
  • Nhập dấu phẩy (,)
  • ...
  • Lặp lại cho đến khi hết ngày mong muốn. Lưu ý sau ngày cuối cùng không cần nhập dấu phẩy (,)
  • Nhấn Enter để hoàn tất và thoát chế độ nhập liệu
 
Bạn làm theo các bước sau:
  • Nhấn F2 để vào chế độ nhập liệu (có thể bỏ qua)
  • Nhập ngày mong muốn thứ nhất
  • Nhập dấu phẩy (,)
  • Nhập ngày mong muốn thứ hai
  • Nhập dấu phẩy (,)
  • ...
  • Lặp lại cho đến khi hết ngày mong muốn. Lưu ý sau ngày cuối cùng không cần nhập dấu phẩy (,)
  • Nhấn Enter để hoàn tất và thoát chế độ nhập liệu
Bác đùa em quá ạ.
 
Cái này làm bằng hàm thì em hông biết. Chờ các anh chị thầy cô vào hỗ trợ
 
Do mình không biết làm mới đưa file mình mong muốn kết quả đoạn bôi vàng như vậy.
Quan trọng là ở đâu ra các ngày trong ô bôi vàng. Nó ở trong đầu bạn mà không thể hiện bằng văn bản hay minh họa bằng các ô excel thì không ai làm được. Người đọc có thể đoán ra, nhưng bạn phải tự nói để khỏi đoán nhầm mỗi người đoán 1 kiểu.
 
Quan trọng là ở đâu ra các ngày trong ô bôi vàng. Nó ở trong đầu bạn mà không thể hiện bằng văn bản hay minh họa bằng các ô excel thì không ai làm được. Người đọc có thể đoán ra, nhưng bạn phải tự nói để khỏi đoán nhầm mỗi người đoán 1 kiểu.
Dạ. Ngày trong ô vàng là các ngày cộng dồn lên theo số ngày ở ô C4 ạ. Ví dụ: ngày bắt đầu là ngày 1/1/2023, các ngày tiếp theo sẽ cộng dồn 180 ngày đến ngày hiện tại ạ.
 
Dạ. Ngày trong ô vàng là các ngày cộng dồn lên theo số ngày ở ô C4 ạ. Ví dụ: ngày bắt đầu là ngày 1/1/2023, các ngày tiếp theo sẽ cộng dồn 180 ngày đến ngày hiện tại ạ.
Vậy là ai định giúp lại phải tự nhặt các ngày đó để làm ví dụ hộ bạn đã, sau đó mới nghĩ đến việc làm thế nào để cộng dồn được. Chờ được ai đủ kiên nhẫn làm hết các bước này e rằng hơi lâu. Có khi người ấy còn chưa sinh ra cũng nên.
 
Vậy là ai định giúp lại phải tự nhặt các ngày đó để làm ví dụ hộ bạn đã, sau đó mới nghĩ đến việc làm thế nào để cộng dồn được. Chờ được ai đủ kiên nhẫn làm hết các bước này e rằng hơi lâu. Có khi người ấy còn chưa sinh ra cũng nên.
Cái đề bài này đâu có gì gây khó hiểu đâu nhỉ.
Chủ thớt chỉ cần ví dụ 1 ngày là: 1/1/2023, sau đó cứ cộng lũy tiếm tiếp là ra mấy ngày trong ô màu vàng.
1/1/2023 + 180 = 27/12/2023 + 180 = 24/06/2024 +....
Bác nào biết công thức thì làm công thức, không thì xử lý bằng VBA vậy thôi
 
Bài này dùng công thức cho excel 2016 thì không tổng quát được. Trong lúc chờ đợi ý kiến thêm thì tham khảo hàm tự tạo này.
Taochuoingay(ngày bắt đầu; ngày kết thúc; khoảng cách ngày)
Mã:
Function Taochuoingay(ngaybd As Date, ngaykt As Date, kc As Long) As String
    Dim chuoingay As String
    Dim ngay As Date
    
    chuoingay = ""
    ngay = ngaybd + kc
    chuoingay = chuoingay & Format(ngay, "dd/mm/yyyy") & ", "
    
    If ngay > ngaykt Then
        chuoingay = ""
    End If
    
    Do While ngay < ngaykt
        ngay = ngay + kc
        If ngay <= ngaykt Then
            chuoingay = chuoingay & Format(ngay, "dd/mm/yyyy") & ", "
        End If
    Loop

    If ngay > ngaykt Then
        chuoingay = chuoingay & Format(ngaykt, "dd/mm/yyyy")
    End If

    If Right(chuoingay, 1) = " " Then
        chuoingay = Left(chuoingay, Len(chuoingay) - 2)
    End If

    Taochuoingay = chuoingay

End Function
Xem thêm trong file
 

File đính kèm

Cái đề bài này đâu có gì gây khó hiểu đâu nhỉ.
Chủ thớt chỉ cần ví dụ 1 ngày là: 1/1/2023, sau đó cứ cộng lũy tiếm tiếp là ra mấy ngày trong ô màu vàng.
1/1/2023 + 180 = 27/12/2023 + 180 = 24/06/2024 +....
Bác nào biết công thức thì làm công thức, không thì xử lý bằng VBA vậy thôi
Đúng như bạn nói nhưng do mình không trình bày rõ ạ. Cảm ơn bạn
 
Cái đề bài này đâu có gì gây khó hiểu đâu nhỉ.
Chủ thớt chỉ cần ví dụ 1 ngày là: 1/1/2023, sau đó cứ cộng lũy tiếm tiếp là ra mấy ngày trong ô màu vàng.
1/1/2023 + 180 = 27/12/2023 + 180 = 24/06/2024 +....
Bác nào biết công thức thì làm công thức, không thì xử lý bằng VBA vậy thôi
Có những người giúp biết rằng ý là như vậy, nhưng chủ bài ví dụ tiết kiệm quá nên người giúp cũng nản anh ạ.
 
Bài này dùng công thức cho excel 2016 thì không tổng quát được. Trong lúc chờ đợi ý kiến thêm thì tham khảo hàm tự tạo này.
Taochuoingay(ngày bắt đầu; ngày kết thúc; khoảng cách ngày)
Mã:
Function Taochuoingay(ngaybd As Date, ngaykt As Date, kc As Long) As String
    Dim chuoingay As String
    Dim ngay As Date
   
    chuoingay = ""
    ngay = ngaybd + kc
    chuoingay = chuoingay & Format(ngay, "dd/mm/yyyy") & ", "
   
    If ngay > ngaykt Then
        chuoingay = ""
    End If
   
    Do While ngay < ngaykt
        ngay = ngay + kc
        If ngay <= ngaykt Then
            chuoingay = chuoingay & Format(ngay, "dd/mm/yyyy") & ", "
        End If
    Loop

    If ngay > ngaykt Then
        chuoingay = chuoingay & Format(ngaykt, "dd/mm/yyyy")
    End If

    If Right(chuoingay, 1) = " " Then
        chuoingay = Left(chuoingay, Len(chuoingay) - 2)
    End If

    Taochuoingay = chuoingay

End Function
Xem thêm trong file
Cảm ơn bạn rất nhiều! Code chạy rất ổn và đúng theo ý muốn ạ
 
Bài này dùng công thức cho excel 2016 thì không tổng quát được. Trong lúc chờ đợi ý kiến thêm thì tham khảo hàm tự tạo này.
Taochuoingay(ngày bắt đầu; ngày kết thúc; khoảng cách ngày)
Mã:
Function Taochuoingay(ngaybd As Date, ngaykt As Date, kc As Long) As String
    Dim chuoingay As String
    Dim ngay As Date
  
    chuoingay = ""
    ngay = ngaybd + kc
    chuoingay = chuoingay & Format(ngay, "dd/mm/yyyy") & ", "
  
    If ngay > ngaykt Then
        chuoingay = ""
    End If
  
    Do While ngay < ngaykt
        ngay = ngay + kc
        If ngay <= ngaykt Then
            chuoingay = chuoingay & Format(ngay, "dd/mm/yyyy") & ", "
        End If
    Loop

    If ngay > ngaykt Then
        chuoingay = chuoingay & Format(ngaykt, "dd/mm/yyyy")
    End If

    If Right(chuoingay, 1) = " " Then
        chuoingay = Left(chuoingay, Len(chuoingay) - 2)
    End If

    Taochuoingay = chuoingay

End Function
Xem thêm trong file
Nhờ bạn giúp mình 1 lần nữa là nếu các ngày trong chuỗi đó trùng với ngày lễ mình chỉ định thì cộng thêm 1 ngày được không ạ?
 
Bạn làm theo các bước sau:
  • Nhấn F2 để vào chế độ nhập liệu (có thể bỏ qua)
  • Nhập ngày mong muốn thứ nhất
  • Nhập dấu phẩy (,)
  • Nhập ngày mong muốn thứ hai
  • Nhập dấu phẩy (,)
  • ...
  • Lặp lại cho đến khi hết ngày mong muốn. Lưu ý sau ngày cuối cùng không cần nhập dấu phẩy (,)
  • Nhấn Enter để hoàn tất và thoát chế độ nhập liệu
Bài hướng dẫn này chi tiết quá, đến từng dấu phẩy luôn.
 
Bài hướng dẫn này chi tiết quá, đến từng dấu phẩy luôn.
Vì bạn ấy là người có tâm "nhì" trái đất.
Nếu chịu khó gõ hết 2,3,4,... cho đến trường hợp cuối mà không dùng dấu ba chấm, mới là người nhất.
Bài đã được tự động gộp:

Nhờ bạn giúp mình 1 lần nữa là nếu các ngày trong chuỗi đó trùng với ngày lễ mình chỉ định thì cộng thêm 1 ngày được không ạ?
Rồi phải nhập các ngày lễ vào 1 vùng nào đó đúng không bạn?
VD: nếu ngày rơi vào 2/9 thì chọn ngày 3/9 đúng không? và chu kỳ +180 ngày lại bắt đầu từ 3/9 hay 2/9?
Nếu rơi vào 30/4 hay 1/5 thì chọn 2/5 đúng không?
 
Lần chỉnh sửa cuối:
Nhờ bạn giúp mình 1 lần nữa là nếu các ngày trong chuỗi đó trùng với ngày lễ mình chỉ định thì cộng thêm 1 ngày được không ạ?
Thường một số hình thức khác là ngày Lễ, Tết, ngày Nghỉ (CN) không tính. Bạn có áp dụng ngày nghỉ không thì đưa vô để bạn ấy xử lý luôn cho đầy đủ.
 
Em đoán mò rằng nếu rơi vào hai ngày này thì phải bắt đầu từ ngày 3/5 vì ngày 30/4 cộng một ngày, ngày 1/5 cộng một ngày nữa là 2 ngày nên thành ra bắt đầu từ ngày 3/5.
Chưa kể giỗ ông tổ theo ngày AL nên ngày DL không cố định
CHờ chủ thớt cập nhật lên file mới làm được.
 
Chưa kể giỗ ông tổ theo ngày AL nên ngày DL không cố định
CHờ chủ thớt cập nhật lên file mới làm được.
File mình thêm sheet LICH NGHI LE. Có cột Ngày nghỉ lễ là những ngày mình mong muốn bỏ qua ngày đó tới ngày tiếp theo. Thêm bao nhiêu ngày nghỉ thì thêm trong cột A- ngày nghỉ lễ đó. Nhờ mọi người quan tâm giúp em ạ
 

File đính kèm

File mình thêm sheet LICH NGHI LE. Có cột Ngày nghỉ lễ là những ngày mình mong muốn bỏ qua ngày đó tới ngày tiếp theo. Thêm bao nhiêu ngày nghỉ thì thêm trong cột A- ngày nghỉ lễ đó. Nhờ mọi người quan tâm giúp em ạ
Mình không biết cách làm bài này, nhưng File có Macro mà lại để đuôi ".xlsx" thì chạy thế nào được nhỉ.
 
Mình không biết cách làm bài này, ...
Không khó lắm. Phần khó nhất là phần đếm số ngày lễ trong các khoảng

Bạn bắt đầu bằng một loop ngoài, mỗi vòng cộng thêm 180 vào ngày bắt đầu, gọi là ngày kết. Hai ngày này xác định một khoảng thời gian khoảng 1/2 nưm.
Nếu ngày kết > DAY (ngày hiện tại) thì Exit loop
Phần sau cần tỉ mỷ một chút.
Loop trong, dùng hàm hay thủ thuật gì đó (SumIfs, Sumproduct) đếm số ngày nghỉ từ Lịch Nghỉ, điều kiện là ngày >= ngày đầu và <= ngày kết. Kế đó lại chuyển điều kiện sang >=ngày đầu và <= ngày kết + số ngày nghỉ. Tiếp tục cho đến khi số ngày nghỉ không thay dổi ở hai lần dò kế nhau. Mục đích của loop này là tìm tổng cộng số ngày nghỉ bị "cán bừa" ở đoạn cuối khoảng.
Ví dụ: ngày kết là ngày đầu + 180 = ngày 20/10/2024. Trong khoảng từ ngày đầu đến 20/10/2024 dò được 5 ngày lễ, đem cộng thêm cho ngày kết thì ra 25/10/2024. Vậy thì phải dò lại với trị 25/10/2014. Nếu 24/10/là ngày lễ thì kết quả mới là 6, cho ra kết quả mới là 26/10/2024. Bạn lại phải dò tiếp, nếu lần tới cũng ra 6 thì coi như có thể kết.
Ở trên, tôi đề cập đến sự tỉ mỷ là vì phần này đòi hỏi bạn chú ý save đủ các trị biến đúng lúc đúng chỗ.

Loop trong thường được viết bằng hàm đệ quy. Nếu bạn hứng, có thể thử.
 
Không khó lắm. Phần khó nhất là phần đếm số ngày lễ trong các khoảng
Cách dễ hơn là tính trước số giai đọan 180 ngày giữa ngày bắt đầu và ngày hiện tại (không có ngày kết thúc), để dùng được trong công thức 365.
Số giai đoạn N = (ngày hiện tại - ngày bắt đầu) / 180 lấy số nguyên.
Sau đó dùng Sequence(1, N, ngày bắt đầu, 180) để liệt kê các ngày, còn ngày cuối thì so sánh với Today(). CUối cùng thì TextJoin.

Tuy nhiên đó là chưa nói đến ngày lễ.

Còn ngày lễ thì chỉ + 1 nếu như sau khi cộng 180 trùng ngày lễ, chứ không phải là đếm số ngày lễ trong khoảng như anh nói.
Vấn đề là sau khi cộng 1 ra ngày bắt đầu của giai đoạn n, thì qua giai đoạn n + 1 lấy ngày đó cộng 180 hay lấy ngày trước khi cộng 1 để cộng 180? Câu hỏi này quan trọng và được hỏi từ bài 22 mà chưa trả lời

1730396450587.png

File mới hơn, đã liệt kê ngày lễ nhưng lại rất hời hợt và vô trách nhiệm. 1 năm 13 ngày lễ mà chỉ liệt kê có 4. Và đáng lẽ phải liệt kê lễ của ít nhất 5 năm trước 2024 và 5 năm sau 2024 là 130 ngày lễ mới đúng. Tại sao? Ngày bắt đầu mẫu trong file có ngày bắt đầu năm 2023, liệt kê lễ chỉ của năm 2024 thì sao đủ? Rồi dữ liệu khác bắt đầu 2019, 2020, ... thì sao?
Ngoài ra, Today() là 31/10/2024. Xài 3 tháng là qua năm 2025 trúng ngay ngày tết Tây mà không liệt kê ra? Dự phòng xài 5 năm mới phải chứ chẳng lẽ xài 3 tháng lại lên xin code mới!
 
...
Vấn đề là sau khi cộng 1 ra ngày bắt đầu của giai đoạn n, thì qua giai đoạn n + 1 lấy ngày đó cộng 180 hay lấy ngày trước khi cộng 1 để cộng 180? Câu hỏi này quan trọng và được hỏi từ bài 22 mà chưa trả lời
...
Thuật toán trên tôi chỉ cho bạn ấy cách giải khi bài đến chỗ khắc nghiệt nhất. Không phải là lời đoán ý thớt.

Bài toán của thớt là bài toán tính chốt ngày (chắc mang xe vào ga ra bảo trì theo kỳ hạn) theo từng khoảng thời gian 1/2 năm. (Theo tôi thì cứ nhảy qua ngày lễ là được.)
Vì vậy , thớt cho rằng quý vị ai cũng có xe xịn cần bảo trì đều đặn, cho nên nhìn câu hỏi là hiểu liền.
 
Nếu bạn hứng, có thể thử.
Vấn đề tiếp theo là sau khi gặp trường hợp đến ngày lễ rồi thì sau đó mốc tiếp theo sẽ là ngày lễ hay là ngày lễ +1 thì chủ bài cũng không đề cập đến, mặc dù đã có bài đề cập câu hỏi này trước bài trả lời gần nhất của chủ bài mấy bài rồi, cho nên em cũng chẳng thử nữa anh ạ.
 
Trong cái UDF này, sẽ cho phép chọn cách 1 hay 2 (là số ngày cộng dồn có tính từ ngày lễ +1 hay không)
=Listngay(ngày bắt đầu, số ngày, 1 (hay 2))

Trong file đính kèm, vùng màu vàng là vùng dùng công thức
Vùng kiểm tra phía dưới là mình dùng công thức để test lại, có thể delete vùng này đi

PHP:
Option Explicit
Function listngay(ngaybd As Date, songay As Integer, n As Integer) As String
If ngaybd = 0 Or songay = 0 Then
    listngay = "O nay khong co so lieu!"
    Exit Function
End If
Dim c&, st As String, ngaykt As Date, wf As Object
Set wf = WorksheetFunction
Do
    c = c + 1
    Select Case n
        Case 1
            ngaybd = IIf(c = 1, ngaybd, ngaykt)
            ngaykt = wf.Min(Date, wf.WorkDay_Intl(ngaybd, songay, "0000000", Sheets("LICH NGHI LE").Range("A2:A5")))
        Case 2
            ngaybd = ngaybd + songay
            ngaykt = wf.Min(Date, wf.WorkDay_Intl(ngaybd - 1, 1, "0000000", Sheets("LICH NGHI LE").Range("A2:A5")))
        Case Else
            MsgBox "Nhap 1 hay 2 cho tham so thu 3!"
            Exit Function
    End Select
    st = IIf(st = "", ngaykt, st & ", " & ngaykt)
    If ngaykt >= Date Then Exit Do
Loop
listngay = st
End Function
 

File đính kèm

Vấn đề tiếp theo là sau khi gặp trường hợp đến ngày lễ rồi thì sau đó mốc tiếp theo sẽ là ngày lễ hay là ngày lễ +1 thì chủ bài cũng không đề cập đến, mặc dù đã có bài đề cập câu hỏi này trước bài trả lời gần nhất của chủ bài mấy bài rồi, cho nên em cũng chẳng thử nữa anh ạ.
Tác giả một là không cần gấp, hai là quá thờ ơ, hời hợt. Giờ này chưa thấy phản hồi. Thật ra vẫn còn 1 việc cần phải nói rõ, đó là khi phát biểu "nếu lớn hơn ngày hiện tại thì ngày cuối cùng là ngày hiện tại", thì lớn hơn bao nhiêu? Lớn hơn dù 1 ngày hay lớn hơn 179 ngày cũng đều lấy ngày hiện tại?
Thí dụ ngày cộng dồn kế cuối là hôm qua (31/10) thì cũng lấy ngày hiện tại là 01/11 và 2 ngày trong dãy cách nhau có 1 ngày?
 
Tác giả một là không cần gấp, hai là quá thờ ơ, hời hợt. Giờ này chưa thấy phản hồi. Thật ra vẫn còn 1 việc cần phải nói rõ, đó là khi phát biểu "nếu lớn hơn ngày hiện tại thì ngày cuối cùng là ngày hiện tại", thì lớn hơn bao nhiêu? Lớn hơn dù 1 ngày hay lớn hơn 179 ngày cũng đều lấy ngày hiện tại?
Thí dụ ngày cộng dồn kế cuối là hôm qua (31/10) thì cũng lấy ngày hiện tại là 01/11 và 2 ngày trong dãy cách nhau có 1 ngày?
Xin lỗi anh và mọi người ạ! Do mình mắc công việc nên chưa phản hồi kịp thời ạ.
Đúng như thí dụ anh nói ạ : Thí dụ ngày cộng dồn kế cuối là hôm qua (31/10) thì cũng lấy ngày hiện tại là 01/11 và 2 ngày trong dãy cách nhau có 1 ngày.
Và ngày cộng dồn là từ ngày cuối cùng cộng dồn lên số ngày. Ví dụ: ngày bắt đầu 02/11/2023 +180 ngày là ngày 30/4/2024, đúng ngày nghỉ lễ 30/4/2024 và 1/5/2025 thì ngày tiếp là 2/5/2024 và tiếp theo +180 ngày bắt đầu từ ngày 2/5/2024 ạ.
 
Yêu cầu loại bỏ các ngày lễ cũng không khó. Chỉ cần lập 1 mảng gồm các ngày lễ, khi có biến 'ngay' thì thêm 1 vòng lặp để so sánh với phần tử mảng. Sau đó xử lý tiếp. Phát sinh nếu today = ngày nghỉ (vd 30/4) thì sẽ lấy ngày cuối là ngày nào?
 
Yêu cầu loại bỏ các ngày lễ cũng không khó. Chỉ cần lập 1 mảng gồm các ngày lễ, khi có biến 'ngay' thì thêm 1 vòng lặp để so sánh với phần tử mảng. Sau đó xử lý tiếp. Phát sinh nếu today = ngày nghỉ (vd 30/4) thì sẽ lấy ngày cuối là ngày nào?
Ngày cuối = ngày lễ thì bằng ngày lễ luôn ạ. Do mình đặt ngày làm sẽ không trùng với ngày lễ nên chắc chắn sẽ không trùng ngày lễ ạ.
Bài đã được tự động gộp:

Trong cái UDF này, sẽ cho phép chọn cách 1 hay 2 (là số ngày cộng dồn có tính từ ngày lễ +1 hay không)
=Listngay(ngày bắt đầu, số ngày, 1 (hay 2))

Trong file đính kèm, vùng màu vàng là vùng dùng công thức
Vùng kiểm tra phía dưới là mình dùng công thức để test lại, có thể delete vùng này đi

PHP:
Option Explicit
Function listngay(ngaybd As Date, songay As Integer, n As Integer) As String
If ngaybd = 0 Or songay = 0 Then
    listngay = "O nay khong co so lieu!"
    Exit Function
End If
Dim c&, st As String, ngaykt As Date, wf As Object
Set wf = WorksheetFunction
Do
    c = c + 1
    Select Case n
        Case 1
            ngaybd = IIf(c = 1, ngaybd, ngaykt)
            ngaykt = wf.Min(Date, wf.WorkDay_Intl(ngaybd, songay, "0000000", Sheets("LICH NGHI LE").Range("A2:A5")))
        Case 2
            ngaybd = ngaybd + songay
            ngaykt = wf.Min(Date, wf.WorkDay_Intl(ngaybd - 1, 1, "0000000", Sheets("LICH NGHI LE").Range("A2:A5")))
        Case Else
            MsgBox "Nhap 1 hay 2 cho tham so thu 3!"
            Exit Function
    End Select
    st = IIf(st = "", ngaykt, st & ", " & ngaykt)
    If ngaykt >= Date Then Exit Do
Loop
listngay = st
End Function
Code này anh thêm tham số ngày kết thúc để có thể chọn được không ạ. Do trong quá trình làm em làm ngày hôm nay nhưng ngày kết thúc chọn ngày khác ạ.
 
Code này anh thêm tham số ngày kết thúc để có thể chọn được không ạ. Do trong quá trình làm em làm ngày hôm nay nhưng ngày kết thúc chọn ngày khác ạ.
Ý bạn là xác định ngày cuối thay vì ngày today()?
Trong code này mình cố định ngày cuối trong code luôn. Nếu bạn muốn chọn ngày thì thay nó bằng 1 cái InputBox nhé
ngaycuoi = DateSerial(2024, 11, 3)
giả sử ngày cuối là ngày 03/11/2024

PHP:
Option Explicit
Function listngay(ngaybd As Date, songay As Integer) As String
If ngaybd = 0 Or songay = 0 Then
    listngay = "O nay khong co so lieu!"
    Exit Function
End If
Dim c&, st As String, ngaykt As Date, ngaycuoi As Date, wf As Object
Set wf = WorksheetFunction
ngaycuoi = DateSerial(2024, 11, 3) ' thay doi ngay tuy chon. Co the thay bang InputBox de chon ngay moi khi run, neu ngay nay co su bien dong
Do
    c = c + 1
    ngaybd = ngaybd + songay
    ngaykt = wf.Min(ngaycuoi, wf.WorkDay_Intl(ngaybd - 1, 1, "0000000", Sheets("LICH NGHI LE").Range("A2:A5")))
    st = IIf(st = "", ngaykt, st & ", " & ngaykt)
    If ngaykt >= ngaycuoi Then Exit Do
Loop
listngay = st
End Function
 

File đính kèm

Ý bạn là xác định ngày cuối thay vì ngày today()?
Trong code này mình cố định ngày cuối trong code luôn. Nếu bạn muốn chọn ngày thì thay nó bằng 1 cái InputBox nhé
ngaycuoi = DateSerial(2024, 11, 3)
giả sử ngày cuối là ngày 03/11/2024

PHP:
Option Explicit
Function listngay(ngaybd As Date, songay As Integer) As String
If ngaybd = 0 Or songay = 0 Then
    listngay = "O nay khong co so lieu!"
    Exit Function
End If
Dim c&, st As String, ngaykt As Date, ngaycuoi As Date, wf As Object
Set wf = WorksheetFunction
ngaycuoi = DateSerial(2024, 11, 3) ' thay doi ngay tuy chon. Co the thay bang InputBox de chon ngay moi khi run, neu ngay nay co su bien dong
Do
    c = c + 1
    ngaybd = ngaybd + songay
    ngaykt = wf.Min(ngaycuoi, wf.WorkDay_Intl(ngaybd - 1, 1, "0000000", Sheets("LICH NGHI LE").Range("A2:A5")))
    st = IIf(st = "", ngaykt, st & ", " & ngaykt)
    If ngaykt >= ngaycuoi Then Exit Do
Loop
listngay = st
End Function
Ý là mình muốn xác định ngày cuối giống như xác định ngày bắt đầu đó ạ. Để chọn vào các ô trong excel cho tiện.
 
Mình xin được phép gởi lại file dữ liệu mong muốn nhờ mọi người giúp đỡ ạ. Em cũng đã liệt kê các ngày lễ để bỏ qua từ năm 2021 đến 2027
 

File đính kèm

Ý là mình muốn xác định ngày cuối giống như xác định ngày bắt đầu đó ạ. Để chọn vào các ô trong excel cho tiện.
Cái này đơn giản, bạn có thể tự làm được mà.
Giả sử ô C5 chứa ngày cuối
PHP:
ngaycuoi = Range("C5").value
 
Cái này đơn giản, bạn có thể tự làm được mà.
Giả sử ô C5 chứa ngày cuối
PHP:
ngaycuoi = Range("C5").value
Được ạ. Nhưng do mình cần copy kéo xuống nhiều dòng khác thì sẽ không tiện bằng cách chọn ô C5, kéo xuống thì thành C6,C7,C8 ... có ô chứa ngày cuối tương ứng ạ.
 
Mình bổ sung thêm theo yêu cầu của bạn, đặt tên list ngày nghỉ là "ngayle" để bạn có thể tùy chỉnh số lượng ngày. Hàm vẫn chưa thực sự hoàn thiện. Nhưng trong phạm vi nào đó thì mình nghĩ vẫn áp dụng được. Vì yêu cầu của bạn không mang tính phổ biến và cũng không biết dữ liệu thực của bạn thế nào nên bạn tự kiểm tra.
Mã:
Function Taochuoingay(ngaybd As Date, ngaykt As Date, kc As Long) As String
    Dim chuoingay As String
    Dim ngay As Date
    Dim ngaynghile As Range
    Dim cell As Range
    Dim trungngayle As Boolean
    
    On Error Resume Next
    Set ngaynghile = ThisWorkbook.Names("ngayle").RefersToRange
    On Error GoTo 0
    If ngaynghile Is Nothing Then
       Set ngaynghile = ActiveSheet.Range("A1")
    End If
 
    chuoingay = ""
    ngay = ngaybd + kc

    Do While ngay <= ngaykt
        trungngayle = False
        For Each cell In ngaynghile
            If ngay = cell.Value Then
                ngay = ngay + 1
                trungngayle = True
                Exit For
            End If
        Next cell
              
              If Not trungngayle And ngay <= ngaykt Then
            chuoingay = chuoingay & Format(ngay, "dd/mm/yyyy") & ", "
            ngay = ngay + kc
        End If
    Loop

    If ngay > ngaykt Then
        chuoingay = chuoingay & Format(ngaykt, "dd/mm/yyyy")
    End If
    
     If Right(chuoingay, 1) = " " Then
        chuoingay = Left(chuoingay, Len(chuoingay) - 2)
    End If

    Taochuoingay = chuoingay
End Function
 

File đính kèm

Loại thớt này là loại đề tài rác gộp.
Cứ vài thử nghiệm thì sinh ra chi tiết mới.
Hiện tượng này xảy ra khi thớt cho rằng mình có thể "túm gọn vấn đề, tìm giải pháp chính rồi thêm chi tiết sau"
Rất tiếc là thớt không biết cách túm gọn vấn đề cho nên cắt xén nhiều quá trong bài #1. Đến chnwgf nhìn thấy kết quả thì bát đầu nhét lại các phần đã bị cắt xén.
Loại bài này lắm khi bắt người viết phải viết lại code.

Và nhắc nhở các bạn viết code: chưa chắc code đã dáp ứng được chuyện lâu dài. Nhìn cái kết quả, tôi biết nó chỉ là 'sáng kiến' nhất thời của thớt. Có thể vài tháng sau thì khám phá ra nó khó đọc bỏ bố, và bỏ luôn. Vì vậy code có options này nọ chỉ uổng công thôi
 
Mình bổ sung thêm theo yêu cầu của bạn, đặt tên list ngày nghỉ là "ngayle" để bạn có thể tùy chỉnh số lượng ngày. Hàm vẫn chưa thực sự hoàn thiện. Nhưng trong phạm vi nào đó thì mình nghĩ vẫn áp dụng được. Vì yêu cầu của bạn không mang tính phổ biến và cũng không biết dữ liệu thực của bạn thế nào nên bạn tự kiểm tra.
Mã:
Function Taochuoingay(ngaybd As Date, ngaykt As Date, kc As Long) As String
    Dim chuoingay As String
    Dim ngay As Date
    Dim ngaynghile As Range
    Dim cell As Range
    Dim trungngayle As Boolean
   
    On Error Resume Next
    Set ngaynghile = ThisWorkbook.Names("ngayle").RefersToRange
    On Error GoTo 0
    If ngaynghile Is Nothing Then
       Set ngaynghile = ActiveSheet.Range("A1")
    End If
 
    chuoingay = ""
    ngay = ngaybd + kc

    Do While ngay <= ngaykt
        trungngayle = False
        For Each cell In ngaynghile
            If ngay = cell.Value Then
                ngay = ngay + 1
                trungngayle = True
                Exit For
            End If
        Next cell
             
              If Not trungngayle And ngay <= ngaykt Then
            chuoingay = chuoingay & Format(ngay, "dd/mm/yyyy") & ", "
            ngay = ngay + kc
        End If
    Loop

    If ngay > ngaykt Then
        chuoingay = chuoingay & Format(ngaykt, "dd/mm/yyyy")
    End If
   
     If Right(chuoingay, 1) = " " Then
        chuoingay = Left(chuoingay, Len(chuoingay) - 2)
    End If

    Taochuoingay = chuoingay
End Function
Cảm ơn bạn rất nhiều. Mình đã tạo được dữ liệu theo ý muốn và nó rất cần thiết cho công việc của mình thời gian lâu dài ạ. Cảm ơn mọi người đã quan tâm thớt này ạ.
 
Code dưới đây đáp ứng yêu cầu cuối cùng. Không thêm bớt yêu cầu mới gì nữa, nếu có thì tự sửa.
PHP:
Function StrDate(StartD, EndD, Cycle As Long, Holidays As Range)
Dim TmpStr As String, TmpD As Long
TmpD = StartD
Do
    TmpD = TmpD + Cycle
    For Each Cll In Holidays
        If TmpD = Cll.Value Then TmpD = TmpD + 1
    Next
    TmpStr = TmpStr & ", " & Format(TmpD, "dd/mm/yy")
Loop Until TmpD + Cycle > EndD
    TmpStr = TmpStr & ", " & Format(EndD, "dd/mm/yy")
    StrDate = Mid(TmpStr, 3, Len(TmpStr))
End Function

Cú pháp:
=StrDate(ngày đầu, ngày cuối, chu kỳ, vùng ngày lễ)

1730480344057.png
 
Code dưới đây đáp ứng yêu cầu cuối cùng. Không thêm bớt yêu cầu mới gì nữa, nếu có thì tự sửa.
PHP:
Function StrDate(StartD, EndD, Cycle As Long, Holidays As Range)
Dim TmpStr As String, TmpD As Long
TmpD = StartD
Do
    TmpD = TmpD + Cycle
    For Each Cll In Holidays
        If TmpD = Cll.Value Then TmpD = TmpD + 1
    Next
    TmpStr = TmpStr & ", " & Format(TmpD, "dd/mm/yy")
Loop Until TmpD + Cycle > EndD
    TmpStr = TmpStr & ", " & Format(EndD, "dd/mm/yy")
    StrDate = Mid(TmpStr, 3, Len(TmpStr))
End Function

Cú pháp:
=StrDate(ngày đầu, ngày cuối, chu kỳ, vùng ngày lễ)

View attachment 305212
Cảm ơn anh rất nhiều ạ. Code chạy rất tốt đáp ứng nhu cầu làm việc thường xuyên của em ạ
 
Bẫy lỗi trường hợp ngày cuối cách ngày đầu đúng 1 chu kỳ:
Mã:
Function StrDate(StartD, EndD, Cycle As Long, Holidays As Range)
Dim TmpStr As String, TmpD As Long
Dim Cll As Variant
TmpD = StartD + Cycle

Do While TmpD < EndD
    For Each Cll In Holidays
        If TmpD = Cll.Value Then TmpD = TmpD + 1
    Next
    TmpStr = TmpStr & ", " & Format(TmpD, "dd/mm/yy")
    TmpD = TmpD + Cycle
Loop
    TmpStr = TmpStr & ", " & Format(EndD, "dd/mm/yy")
    StrDate = Mid(TmpStr, 3, Len(TmpStr))
End Function
 
Lần chỉnh sửa cuối:
Đúng là tôi chưa test trường hợp này. Có thể thêm 1 điều kiện If nhưng cách của bạn hay hơn.
Còn trường hợp 2 ngày nghỉ liên tiếp thì chỉ lên 1 ngày ạ. Ví dụ: trúng ngày 30/4/2024 thì nó chỉ nhảy lên 1 ngày là 1/5/2024 chứ không nhảy qua ngày 2/5/2024.
 
Còn trường hợp 2 ngày nghỉ liên tiếp thì chỉ lên 1 ngày ạ. Ví dụ: trúng ngày 30/4/2024 thì nó chỉ nhảy lên 1 ngày là 1/5/2024 chứ không nhảy qua ngày 2/5/2024.
Kết quả mong muốn bạn đưa lên ở bài 45 là 2/5. Bài 47 bạn còn cãi với bài 46.
Tôi đã nói là không xí quên, không xí lộn, không thêm bớt. Bạn phải tự sửa.

1730509875291.png
 
Đúng là tôi chưa test trường hợp này. Có thể thêm 1 điều kiện If nhưng cách của bạn hay hơn.
Chưa chắc là hay đâu anh, bẫy này vẫn để "sổng" lỗi khi ngày liền trước ngày kết thúc là ngày kết thúc chu kỳ đồng thời là ngày lễ.
--
Ngoài ra code còn một lỗi khá nghiêm trọng là sẽ rơi vào vòng lặp vô tận khi số ngày một chu kỳ bằng 0 (có thể do vô tình xóa ô chứa giá trị số ngày một chu kỳ).
--
Còn cái vế "lớn hơn ngày hiện tại thì ngày cuối cùng là ngày kết thúc" trong yêu cầu thì không hiểu ý nói gì, code cũng chưa thực hiện.
 
Chưa chắc là hay đâu anh, bẫy này vẫn để "sổng" lỗi khi ngày liền trước ngày kết thúc là ngày kết thúc chu kỳ đồng thời là ngày lễ.
--
Ngoài ra code còn một lỗi khá nghiêm trọng là sẽ rơi vào vòng lặp vô tận khi số ngày một chu kỳ bằng 0 (có thể do vô tình xóa ô chứa giá trị số ngày một chu kỳ).
--
Còn cái vế "lớn hơn ngày hiện tại thì ngày cuối cùng là ngày kết thúc" trong yêu cầu thì không hiểu ý nói gì, code cũng chưa thực hiện.
Hai lỗi đầu là đúng là lỗi, lỗi 3 thì hình như đã có rồi (dòng 12)
 
Dòng 12 khác gì so với các dòng khác anh? Trong code cũng không thấy chỗ nào so sánh với ngày hiện tại cả.
Ở bài #1, thớt nói là ngày hiện tại, nhưng sau thì đổi ý rồi.
Chỉ có LCT, nói là sợ "điều kiện ảo" nhưng vẫn bám chặt.
 
Dòng 12 khác gì so với các dòng khác anh? Trong code cũng không thấy chỗ nào so sánh với ngày hiện tại cả.
Y thị đổi ý là ngày kết thúc bất kỳ chứ không còn là ngày hiện tại nữa, nên thay thế bằng tham số EndD. Câu lệnh nối EndD nằm ngoài vòng lặp Do chính là thêm ngày cuối khi đã thoát vòng lặp. Mà điều kiện thoát vòng lặp là tmpD + Cycle > EndD bất kể lớn hơn 1 ngày hay nhiều ngày.
Dòng 12 nếu cộng tay (có cộng 2 ngày lễ) thì ngày cuối là 25/08/25, lớn hơn ngày cuối 25/12/24 (tô vàng), nên phải lấy ngày cuối và kết quả là E12.

1730560666112.png

Sinh ra lỗi là nếu ngày cuối bằng đúng ngày kết thúc thì bị 2 lần ngày kết thúc, và lỗi này fix bằng cách của phuocam đổi Loop Until thành Do While.
 
Lần chỉnh sửa cuối:
Chỉ có LCT, nói là sợ "điều kiện ảo" nhưng vẫn bám chặt.
Không anh. Sau khi đổi ý và sau khi có đủ số ngày nghỉ của những năm trước và những năm sau 2024 như tôi đòi, tôi mới viết cho yêu cầu mới nhất và dữ liệu đủ nhất.
 
Dòng 12 nếu cộng tay (có cộng 2 ngày lễ) thì ngày cuối là 25/08/25, lớn hơn ngày cuối 25/12/24 (tô vàng), nên phải lấy ngày cuối và kết quả là E12.
Mô tả yêu cầu ghi là "lớn hơn ngày hiện tại thì ngày cuối cùng là ngày kết thúc" nhưng anh hiểu là "lớn hơn ngày kết thúc thì ngày cuối cùng là ngày kết thúc" thế mà lại trúng. Hay thật.
1730600127863.png

lỗi này fix bằng cách của phuocam đổi Loop Until thành Do While.
Fix lỗi này nhưng lại lòi ra lỗi khác, bài #60 em có nêu trường hợp xảy ra lỗi.
 
Mô tả yêu cầu ghi là "lớn hơn ngày hiện tại thì ngày cuối cùng là ngày kết thúc" nhưng anh hiểu là "lớn hơn ngày kết thúc thì ngày cuối cùng là ngày kết thúc" thế mà lại trúng. Hay thật.
Yêu cầu thay ngày hiện tại bằng ngày kết thúc và chọn được là ở bài 40. Còn ô E5 trong file thì không sửa yêu cầu cũ từ bài 1 thành yêu cầu mới. Bài trên tôi có nói đương sự này là kẻ hời hợt và vô trách nhiệm mà. Hỏi mãi hỏi đủ thứ cho mãi đến bài 45 mới đủ thông tin, lúc đó tôi mới làm.
Fix lỗi này nhưng lại lòi ra lỗi khác, bài #60 em có nêu trường hợp xảy ra lỗi.
Tôi đã dự định không làm tiếp nên không test nữa và cũng không sửa nữa. Chẳng hạn như yêu cầu phát sinh 2 ngày lễ liên tiếp chỉ cộng 1 cho ngày lễ thứ nhất, tôi đã từ chối.
 
Yêu cầu thay ngày hiện tại bằng ngày kết thúc và chọn được là ở bài 40. Còn ô E5 trong file thì không sửa yêu cầu cũ từ bài 1 thành yêu cầu mới. Bài trên tôi có nói đương sự này là kẻ hời hợt và vô trách nhiệm mà. Hỏi mãi hỏi đủ thứ cho mãi đến bài 45 mới đủ thông tin, lúc đó tôi mới làm.

Tôi đã dự định không làm tiếp nên không test nữa và cũng không sửa nữa. Chẳng hạn như yêu cầu phát sinh 2 ngày lễ liên tiếp chỉ cộng 1 cho ngày lễ thứ nhất, tôi đã từ chối.
Cảm ơn anh và mọi người đã giúp đỡ tận tình ạ. Do trong quá trình làm phát sinh các lỗi em không lường trước được nên vấn đề cứ phát sinh dẫn đến làm phiền mọi người ạ. Ví dụ: dữ liều ban đầu là em chỉ dùng ngày hiện tại nhưng em muốn sử dụng các trường hợp khác nữa nên mới phát sinh như vậy hoặc khi chạy ra dữ liệu ra thì có những ngày trùng ngày nghỉ lễ nên phải tạo lịch nghỉ lễ để tránh những ngày đó.
 

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

Back
Top Bottom