Một tháng chỉ có một ngày 13. Chỉ cần lấy một lần ngày 13, sau có cứ +/- tháng (hàm DateAdd)Mình thử viết hàm mảng tự tạo & có nội dung sau:
PHP:... For J = 1 To 10000 If Day(J + Dat) = 13 And Weekday(J + Dat) = 6 Then ...
Một tháng chỉ có một ngày 13. Chỉ cần lấy một lần ngày 13, sau có cứ +/- tháng (hàm DateAdd)Mình thử viết hàm mảng tự tạo & có nội dung sau:
PHP:... For J = 1 To 10000 If Day(J + Dat) = 13 And Weekday(J + Dat) = 6 Then ...
STT | Ngày | Del ta | |||||||||||||||
1 | 12/13/19 | -45 | =T6N13(DATE(2020,1,27)) | ||||||||||||||
2 | 03/13/20 | 46 | |||||||||||||||
3 | 09/13/19 | -136 | |||||||||||||||
4 | 11/13/20 | 291 | |||||||||||||||
5 | 07/13/18 | -563 | |||||||||||||||
6 | 08/13/21 | 564 | |||||||||||||||
7 | 04/13/18 | -654 | |||||||||||||||
8 | 10/13/17 | -836 | |||||||||||||||
9 | 05/13/22 | 837 | |||||||||||||||
10 | 01/13/23 | 1082 |
Em góp vui với hàm tự tạo dựa theo ý tưởng của thầy VetMini với hàm tự tạo của thầy SA_DQMột tháng chỉ có một ngày 13. Chỉ cần lấy một lần ngày 13, sau có cứ +/- tháng (hàm DateAdd)
Function T6N13_2(Dat As Date, Count As Long)
ReDim Arr(1 To Count, 1 To 3)
Dim i As Long, j As Long, Year_Dat As Long
Dim W As Long
i = Month(Dat)
j = Month(Dat)
Year_Dat = Year(Dat)
Do Until W = Count
If (Weekday(DateSerial(Year_Dat, i, 13))) = 6 Then
W = W + 1
Arr(W, 1) = W
Arr(W, 2) = Format(DateSerial(Year_Dat, i, 13))
Arr(W, 3) = DateDiff("d", Dat, DateSerial(Year_Dat, i, 13))
End If
If W = Count Then Exit Do
If (Weekday(DateSerial(Year_Dat, j, 13))) = 6 Then
W = W + 1
Arr(W, 1) = W
Arr(W, 2) = Format(DateSerial(Year_Dat, j, 13))
Arr(W, 3) = DateDiff("d", Dat, DateSerial(Year_Dat, j, 13))
End If
i = i + 1: j = j - 1
Loop
T6N13_2 = Arr()
End Function
Hẳn là cách đó rất nhanh, cháu đang nghĩ xem có thể sài dic được không mà khó quátháng chỉ có một ngày 13. Chỉ cần lấy một lần ngày 13, sau có cứ +/- tháng (hàm DateAdd)
Nếu vậy thì chỉ cần xét số nào kiểm tra trước, số nào kiểm tra sau thôi, đỡ hơn là kiểm tra từng ngày.Lúc đầu mình cũng định đi theo hướng như vậy, nhưng 1 vài trường hợp cụ thể thì không thỏa yêu cầu & sẽ bị ai đó khó tính cự nự:
Function T6N13(Dat As Date)
Dim Arr(1 To 10, 1 To 3)
Dim a As Long, z As Long, i As Date, k As Long, d As Long, m As Long, y As Long
d = Day(Dat): m = Month(Dat): y = Year(Dat)
If d < 13 Then a = -1
z = a + 1
Do Until k = 10
If Dat - DateSerial(y, m + a, 13) < DateSerial(y, m + z, 13) - Dat Then
i = DateSerial(y, m + a, 13): a = a - 1
Else
i = DateSerial(y, m + z, 13): z = z + 1
End If
If Weekday(i) = 6 Then
k = k + 1: Arr(k, 2) = Format(i, "dd/mm/yyyy")
Arr(k, 1) = k: Arr(k, 3) = i - Dat
End If
Loop
T6N13 = Arr
End Function
=LET(MyDay,$B$1-SEQUENCE(5000),MDate1,TEXT(MyDay,"DDD"),MDate2,TEXT(MyDay,"DD"),mRange,FILTER(MyDay,(MDate1="Fri")*(MDate2="13"),"Not Found"),mOrder,SEQUENCE(COUNTA(mRange)),FILTER(mRange,mOrder<=$B$2,"Not Found"))
=LET(MyDay,$B$1+SEQUENCE(5000),MDate1,TEXT(MyDay,"DDD"),MDate2,TEXT(MyDay,"DD"),mRange,FILTER(MyDay,(MDate1="Fri")*(MDate2="13"),"Not Found"),mOrder,SEQUENCE(COUNTA(mRange)),FILTER(mRange,mOrder<=$B$2,"Not Found"))
=LET(Array1,OFFSET($A4,,,$B$2),Array2,OFFSET($B4,,,$B$2),ColToAppend,CHOOSE({1,2},Array1,Array2),FILTER(INDEX(ColToAppend,MOD(SEQUENCE(ROWS(ColToAppend)*COLUMNS(ColToAppend),,0),ROWS(ColToAppend))+1,SEQUENCE(ROWS(ColToAppend)*COLUMNS(ColToAppend),,0,1/ROWS(ColToAppend))+1),NOT(ISERROR(INDEX(ColToAppend,MOD(SEQUENCE(ROWS(ColToAppend)*COLUMNS(ColToAppend),,0),ROWS(ColToAppend))+1,SEQUENCE(ROWS(ColToAppend)*COLUMNS(ColToAppend),,0,1/ROWS(ColToAppend))+1)))))
Dạo này có tuổi nên HÀM yếu lắm rồi bác, mà vẫn xin 3 xị rượu nhé bác Sa, hẹn 1 ngày gần nhất ở SG.Sẽ có 3 xị rượu cho ai giải đúng & sớm nhất bằng công thức!
Chúc các bạn vui vẻ & mạnh khỏe nhân dịp xuân về!
Nếu đã có 2 danh sách ở A4 và B4 thì nối lại như sau:Nối 2 danh sách bên trên lại thành 1 danh sách gom bỏ vô trong 1 cột (Kiểu như "append data"):
Nay bần lão được thọ giáo chiêu A4# (thay cho offset) của tiên sinh, quả thật khâm phục, khâm phục!Nếu đã có 2 danh sách ở A4 và B4 thì nối lại như sau:
=LET(db,A4#,da,B4#,rwb,ROWS(db),rwa,ROWS(da),IF(SEQUENCE(rwb+rwa)<=rwb,INDEX(db,SEQUENCE(rwb+rwa),1),INDEX(da,SEQUENCE(rwb+rwa)-rwb,1)))
Vì bài này mảng là Date nên có thể dùng cách này để gom 2 mảngBần đạo tu trên núi lâu quá không biết bằng hữu đàm đạo chuyện này. Thôi thì góp vui vậy. Lưu ý dùng excel phiên bản tầng thứ 9 cửu âm chân kinh 365 mới được.
Cho trước 1 ngày cột mốc nào đó (ví dụ hôm nay), Cho trước số lần tìm Thứ Sáu ngày 13 (ví dụ 10 ngày),
Danh sách các ngày thứ sáu 13 trở về trước (trước ngày cột mốc):
Danh sách các ngày thứ sáu 13 trở về sau (sau ngày cột mốc):
Nối 2 danh sách bên trên lại thành 1 danh sách gom bỏ vô trong 1 cột (Kiểu như "append data"):
View attachment 265746
=LET(a,A4#,b,B4#,SMALL((a,b),SEQUENCE(COUNT(a,b))))
Nếu đặt thêm biến nữa công thức sẽ gọn, so index thì 2 mảng không cùng cấu trúc vẫn được vì nó luôn xét từ trên xuốngNếu đã có 2 danh sách ở A4 và B4 thì nối lại như sau:
=LET(db,A4#,da,B4#,rwb,ROWS(db),rwa,ROWS(da),IF(SEQUENCE(rwb+rwa)<=rwb,INDEX(db,SEQUENCE(rwb+rwa),1),INDEX(da,SEQUENCE(rwb+rwa)-rwb,1)))
=LET(db,A4#,da,B4#,lst,SEQUENCE(ROWS(db)+ROWS(db))-ROWS(db),IF(lst<=0,db,INDEX(da,lst)))
=LET(td,TODAY(),n,10,l_date,td+SEQUENCE(10001)-5001,l_filter,FILTER(l_date,TEXT(l_date,"dd ddd")="13 Fri"),pst,MATCH(td,l_filter),INDEX(l_filter,SEQUENCE(n*2)-n+pst))
Khà khà khà, đúng là ngọa hổ tàng long. Mong anh em bằng hữu có dịp đàm đạo luận kiếm, cầm tay uống rượu!Góp vui dùng 365 cho bài này không tách khớp
Mã:=LET(td,TODAY(),n,10,l_date,td+SEQUENCE(10001)-5001,l_filter,FILTER(l_date,TEXT(l_date,"dd ddd")="13 Fri"),pst,MATCH(td,l_filter),INDEX(l_filter,SEQUENCE(n*2)-n+pst))
=IF(ROWS(A$1:A1)<11,AGGREGATE(14,6,(EDATE(EDATE(TODAY()-DAY(TODAY())+13,-(DAY(TODAY())<=13)),1-ROW($1:$120)))/
(WEEKDAY(EDATE(EDATE(TODAY()-DAY(TODAY())+13,-(DAY(TODAY())<=13)),1-ROW($1:$120)))=6),11-ROWS(A$1:A1)),
IF(ROWS(A$1:A1)<21,AGGREGATE(15,6,(EDATE(EDATE(TODAY()-DAY(TODAY())+13,--(DAY(TODAY())>13)),ROW($1:$120)-1))/(WEEKDAY(EDATE(EDATE(TODAY()-DAY(TODAY())+13,--(DAY(TODAY())>13)),ROW($1:$120)-1))=6),ROWS(A$1:A1)-10),""))
Mình viết code thấy nó ngắn gọn sao các bác viết dài thòn vậy ta?Cách của bạn chỉ tìm 1 trong mười ngày đó mà thôi;
Đề bài là tìm cả mười ngày thứ sáu 13 gần nhất trong 1 lúc cơ!
Mình thử viết hàm mảng tự tạo & có nội dung sau:
PHP:Function T6N13(Optional Dat As Date) ReDim Arr(1 To 10, 1 To 3) Dim J As Long, W As Integer If Dat < 9 Then Dat = Date If Day(Dat) = 13 Then Dat = Dat - 1 For J = 1 To 10000 If Day(J + Dat) = 13 And Weekday(J + Dat) = 6 Then W = W + 1: Arr(W, 2) = Format(J + Dat, "MM/DD/yy") Arr(W, 3) = J: Arr(W, 1) = W End If If W = 10 Then Exit For If Day(Dat - J) = 13 And Weekday(Dat - J) = 6 Then W = W + 1: Arr(W, 2) = Format(Dat - J, "MM/DD/yy") Arr(W, 3) = Space(1) & -J: Arr(W, 1) = W End If If W = 10 Then Exit For Next J T6N13 = Arr() End Function
Sub Test()
Dim arrDate()
Dim n As Long
Dim d As Date, dteFromDate As Date, dteToDate As Date
dteFromDate = Date
dteToDate = DateSerial(2031, 12, 31)
For d = dteFromDate To dteToDate
If Weekday(d) = 6 And Day(d) = 13 Then
n = n + 1
ReDim Preserve arrDate(1 To n)
arrDate(n) = d
If n = 10 Then Exit For
End If
Next
Range("F5").Resize(n).Value = WorksheetFunction.Transpose(arrDate)
End Sub
Có năm có 1, có năm có 2, 3 thứ 6 ngày 13. Trong công thức ở bài #35 tôi lấy trung bìng là 1 năm 1 lần thứ 6 ngày 13. Vì thế để xét 10 lần thứ 6 ngày 13 thì tôi xét 10 năm, tức 120 tháng. Vì thế có con số 120 - ROW($1:$120)Mình không biết dùng hàm mình ngồi mình đếm thủ công tầm 10 năm từ 1/1/2021 đến 31/12/2031 thì có 17 ngày thứ sáu ngày 13:
View attachment 265791
Từ hiện tại phải dò theo 2 hướng chứ bạn?Mình viết code thấy nó ngắn gọn sao các bác viết dài thòn vậy ta?
PHP:Sub Test() Dim arrDate() Dim n As Long Dim d As Date, dteFromDate As Date, dteToDate As Date dteFromDate = Date dteToDate = DateSerial(2031, 12, 31) For d = dteFromDate To dteToDate If Weekday(d) = 6 And Day(d) = 13 Then n = n + 1 ReDim Preserve arrDate(1 To n) arrDate(n) = d If n = 10 Then Exit For End If Next Range("F5").Resize(n).Value = WorksheetFunction.Transpose(arrDate) End Sub
Hướng nào và hướng nào?Từ hiện tại phải dò theo 2 hướng chứ bạn?
Function FindFriday13th(ByVal intCount As Integer) As Variant
Dim arrDate(), d As Date, n As Long
d = Date
Do
If Weekday(d) = 6 And Day(d) = 13 Then
n = n + 1
ReDim Preserve arrDate(1 To n)
arrDate(n) = d
If n = intCount Then Exit Do
End If
d = d + 1
Loop
FindFriday13th = WorksheetFunction.Transpose(arrDate)
End Function
Thì chủ thớt đã nói rồi đó chi. Gần nhất 10 ngày là phải tính 5 ngày từ hiện tại đến tương lai + 5 ngày từ hiện tại đến quá khứ.Hướng nào và hướng nào?
Còn dùng hàm còn ngắn gọn hơn nữa!
PHP:Function FindFriday13th(ByVal intCount As Integer) As Variant Dim arrDate(), d As Date, n As Long d = Date Do If Weekday(d) = 6 And Day(d) = 13 Then n = n + 1 ReDim Preserve arrDate(1 To n) arrDate(n) = d If n = intCount Then Exit Do End If d = d + 1 Loop FindFriday13th = WorksheetFunction.Transpose(arrDate) End Function
Nếu như trong bài đếm số lượng 10 ngày gần đây nhất thì công thức: =FindFriday13th(10)