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 ạ.

Liên hệ QC
Tôi tuân thủ nội quy khi đăng bài
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?
 
Còn các ngày lễ đầy đủ cho các năm trước và sau 2024? Đặc biệt là các ngày lễ dựa vào âm lịch?
Mình chỉ cần các ngày lễ Dương lịch mà em ghi vào thôi ạ. Chứ không phải tất cả các ngày nghỉ lễ ạ.
 

File đính kèm

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 ạ.
 
Web KT

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

Back
Top Bottom