Excel và ứng dụng tính toán Âm Dương

chgjst

Hội viên
Như các bạn đã biết, Excel là một phần mềm rất mạnh về tính toán và quản trị. Và với các thuật số của Đông Phương, tính đúng và tính chuẩn là yêu cầu quan trọng bậc nhất.

Chgjst viết lên chủ đề này bởi vì mình biết có rất nhiều bạn đang tìm cách dùng Excel để tính toán các thuật số, với mục đích là để chia xẻ, hai là để cùng nhau xây dựng lên các mã nguồn tốt cho mọi người tham khảo, phục vụ cho công tác nghiên cứu được dễ dàng.

Dưới đây là mình giới thiệu các hàm tự lập để tính toán, một số mình tham khảo và copy từ các nguồn khác trên internet, xin cám ơn người đã lập những mã nguồn này.
 

chgjst

Hội viên
Module 1: Phần bổ trợ

Chứa các hàm phục vụ viết tiếng Việt và chuyển đổi ngày tháng, sử dụng hàm MsgBoxVN(VN"Phong Thuyr Thawng Long") để viết MsgBox "Phong Thủy Thăng Long". Hàm VN để chuyển từ kiểu gõ Telex ra tiếng Việt:
----------------------------------

Option Explicit

Public Declare Function MessageBox Lib "user32.dll" Alias "MessageBoxW" (ByVal hwnd As Long, ByVal lpText As Long, ByVal lpCaption As Long, ByVal wType As Long) As Long

Public Function VN(Str As String) As String
Dim Ma As String, MaLuu As String, i As Long, a As Long
a = 1
If Str = "" Or Str = "Microsoft Excel" Then
VN = "Microsoft Excel"
Else
For i = a To Len(Str)
i = a
Ma = Mid(Str, i, 3)
MaLuu = Ma
Select Case Ma
Case "aws": Ma = ChrW(7855): Case "Aws": Ma = ChrW(7854)
Case "awf": Ma = ChrW(7857): Case "Awf": Ma = ChrW(7856)
Case "awr": Ma = ChrW(7859): Case "Awr": Ma = ChrW(7858)
Case "awx": Ma = ChrW(7861): Case "Awx": Ma = ChrW(7860)
Case "awj": Ma = ChrW(7863): Case "Awj": Ma = ChrW(7862)
Case "aas": Ma = ChrW(7845): Case "Aas": Ma = ChrW(7844)
Case "aaf": Ma = ChrW(7847): Case "Aaf": Ma = ChrW(7846)
Case "aar": Ma = ChrW(7849): Case "Aar": Ma = ChrW(7848)
Case "aax": Ma = ChrW(7851): Case "Aax": Ma = ChrW(7850)
Case "aaj": Ma = ChrW(7853): Case "Aaj": Ma = ChrW(7852)
Case "ees": Ma = ChrW(7871): Case "Ees": Ma = ChrW(7870)
Case "eef": Ma = ChrW(7873): Case "Eef": Ma = ChrW(7872)
Case "eer": Ma = ChrW(7875): Case "Eer": Ma = ChrW(7874)
Case "eex": Ma = ChrW(7877): Case "Eex": Ma = ChrW(7876)
Case "eej": Ma = ChrW(7879): Case "Eej": Ma = ChrW(7878)
Case "oos": Ma = ChrW(7889): Case "Oos": Ma = ChrW(7888)
Case "oof": Ma = ChrW(7891): Case "Oof": Ma = ChrW(7890)
Case "oor": Ma = ChrW(7893): Case "Oor": Ma = ChrW(7892)
Case "oox": Ma = ChrW(7895): Case "Oox": Ma = ChrW(7894)
Case "ooj": Ma = ChrW(7897): Case "Ooj": Ma = ChrW(7896)
Case "ows": Ma = ChrW(7899): Case "Ows": Ma = ChrW(7898)
Case "owf": Ma = ChrW(7901): Case "Owf": Ma = ChrW(7900)
Case "owr": Ma = ChrW(7903): Case "Owr": Ma = ChrW(7902)
Case "owx": Ma = ChrW(7905): Case "Owx": Ma = ChrW(7904)
Case "owj": Ma = ChrW(7907): Case "Owj": Ma = ChrW(7906)
Case "uws": Ma = ChrW(7913): Case "Uws": Ma = ChrW(7912)
Case "uwf": Ma = ChrW(7915): Case "Uwf": Ma = ChrW(7914)
Case "uwr": Ma = ChrW(7917): Case "Uwr": Ma = ChrW(7916)
Case "uwx": Ma = ChrW(7919): Case "Uwx": Ma = ChrW(7918)
Case "uwj": Ma = ChrW(7921): Case "Uwj": Ma = ChrW(7920)
End Select
If Ma <> MaLuu Then
VN = VN & Ma
a = i + 3
Else
Ma = Mid(Str, i, 2)
MaLuu = Ma
Select Case Ma
Case "as": Ma = ChrW(225): Case "As": Ma = ChrW(193)
Case "af": Ma = ChrW(224): Case "Af": Ma = ChrW(192)
Case "ar": Ma = ChrW(7843): Case "Ar": Ma = ChrW(7842)
Case "ax": Ma = ChrW(227): Case "Ax": Ma = ChrW(195)
Case "aj": Ma = ChrW(7841): Case "Aj": Ma = ChrW(7840)
Case "aw": Ma = ChrW(259): Case "Aw": Ma = ChrW(258)
Case "aa": Ma = ChrW(226): Case "Aa": Ma = ChrW(194)
Case "dd": Ma = ChrW(273): Case "Dd": Ma = ChrW(272)
Case "es": Ma = ChrW(233): Case "Es": Ma = ChrW(201)
Case "ef": Ma = ChrW(232): Case "Ef": Ma = ChrW(200)
Case "er": Ma = ChrW(7867): Case "Er": Ma = ChrW(7866)
Case "ex": Ma = ChrW(7869): Case "Ex": Ma = ChrW(7868)
Case "ej": Ma = ChrW(7865): Case "Ej": Ma = ChrW(7864)
Case "ee": Ma = ChrW(234): Case "Ee": Ma = ChrW(202)
Case "is": Ma = ChrW(237): Case "Is": Ma = ChrW(205)
Case "if": Ma = ChrW(236): Case "If": Ma = ChrW(204)
Case "ir": Ma = ChrW(7881): Case "Ir": Ma = ChrW(7880)
Case "ix": Ma = ChrW(297): Case "Ix": Ma = ChrW(296)
Case "ij": Ma = ChrW(7883): Case "Ij": Ma = ChrW(7882)
Case "os": Ma = ChrW(243): Case "Os": Ma = ChrW(211)
Case "of": Ma = ChrW(242): Case "Of": Ma = ChrW(210)
Case "or": Ma = ChrW(7887): Case "Or": Ma = ChrW(7886)
Case "ox": Ma = ChrW(245): Case "Ox": Ma = ChrW(213)
Case "oj": Ma = ChrW(7885): Case "Oj": Ma = ChrW(7884)
Case "oo": Ma = ChrW(244): Case "Oo": Ma = ChrW(212)
Case "ow": Ma = ChrW(417): Case "Ow": Ma = ChrW(416)
Case "us": Ma = ChrW(250): Case "Us": Ma = ChrW(218)
Case "uf": Ma = ChrW(249): Case "Uf": Ma = ChrW(217)
Case "ur": Ma = ChrW(7911): Case "Ur": Ma = ChrW(7910)
Case "ux": Ma = ChrW(361): Case "Ux": Ma = ChrW(360)
Case "uj": Ma = ChrW(7909): Case "Uj": Ma = ChrW(7908)
Case "uw": Ma = ChrW(432): Case "Uw": Ma = ChrW(431)
Case "ys": Ma = ChrW(253): Case "Ys": Ma = ChrW(221)
Case "yf": Ma = ChrW(7923): Case "Yf": Ma = ChrW(7922)
Case "yr": Ma = ChrW(7927): Case "Yr": Ma = ChrW(7926)
Case "yx": Ma = ChrW(7929): Case "Yx": Ma = ChrW(7928)
Case "yj": Ma = ChrW(7925): Case "Yj": Ma = ChrW(7924)
End Select
If Ma <> MaLuu Then
VN = VN & Ma
a = i + 2
Else
VN = VN & Mid(Str, i, 1)
a = i + 1
End If
End If
Next i
End If
End Function

Public Function MsgBoxVN(ByVal Chuoi As String, Optional Bieutuong As VbMsgBoxStyle = 64, Optional ByVal Tieude As String, Optional ByVal Khac As Long = 0) As VbMsgBoxResult
MsgBoxVN = MessageBox(Khac, StrPtr(VN(Chuoi)), StrPtr(VN(Tieude)), Bieutuong)
End Function

Public Function DateFrom(ByVal dd As Integer, ByVal mm As Integer, ByVal yy As Integer) As Long
Dim day As Long
day = yy - 1900
day = day * 365
day = day + Int((yy - 1900) / 4) + dd + 1 ' nam 1900 la nam nhuan
Select Case mm
Case 2: day = day + 31
Case 3: day = day + 59
Case 4: day = day + 90
Case 5: day = day + 120
Case 6: day = day + 151
Case 7: day = day + 181
Case 8: day = day + 212
Case 9: day = day + 243
Case 10: day = day + 273
Case 11: day = day + 304
Case 12: day = day + 334
End Select
DateFrom = day
End Function
 
Last edited by a moderator:

chgjst

Hội viên
Module 2: Chuyển đổi ngày tháng âm lịch - dương lịch

Gồm 2 hàm chính:

ChuyenDL(dd,mm,yy,Nhuan,Timezone): chuyển từ ngày Âm dd/mm/yy sang Dương lịch với Nhuan mặc định tháng nhuận là 0, nếu là tháng nhuận thì Nhuận bạn đưa giá trị = 1.

ChuyenAL(dd,mm,yy,Timezone): chuyển từ ngày Dương dd/mm/yy ra ngày Âm lịch trong vùng có Timezone, Timezone có mặc định là 7: Việt Nam.

Hàm phụ để xét xem ngày chuyển đổi có thuộc tháng Âm nhuận hay không:
NhuanAL(dd,mm,yy,Timezone) trả về giá trị True hoặc false
------------------

Option Explicit

Private Function jdFromDate(ByVal dd As Integer, ByVal mm As Integer, ByVal yy As Integer) As Long
Dim a, y, m, jd
a = Int((14 - mm) / 12)
y = yy + 4800 - a
m = mm + 12 * a - 3
jd = dd + Int((153 * m + 2) / 5) + 365 * y + Int(y / 4) - Int(y / 100) + Int(y / 400) - 32045
If (jd < 2299161) Then jd = dd + Int((153 * m + 2) / 5) + 365 * y + Int(y / 4) - 32083
jdFromDate = jd
End Function

Private Function jdToDate(ByVal jd As Long) As Long
Dim a, b, c, D, e, m, day, month, year
If (jd > 2299160) Then
a = jd + 32044
b = Int((4 * a + 3) / 146097)
c = a - Int((b * 146097) / 4)
Else
b = 0
c = jd + 32082
End If
D = Int((4 * c + 3) / 1461)
e = c - Int((1461 * D) / 4)
m = Int((5 * e + 2) / 153)
day = e - Int((153 * m + 2) / 5) + 1
month = m + 3 - 12 * Int(m / 10)
year = b * 100 + D - 4800 + Int(m / 10)
'jdToDate = day & "/" & month & "/" & year
jdToDate = DateFrom(day, month, year)
End Function

Private Function getNewMoonDay(ByVal k As Integer, ByVal Timezone As Integer) As Long ' Tinh ngay soc
Dim t, T2, T3, dr, Jd1, m, Mpr, F, C1, deltat, JdNew
t = k / 1236.85 '' Time in Julian centuries from 1900 January 0.5
T2 = t * t
T3 = T2 * t
dr = WorksheetFunction.Pi / 180
Jd1 = 2415020.75933 + 29.53058868 * k + 0.0001178 * T2 - 0.000000155 * T3
Jd1 = Jd1 + 0.00033 * Sin((166.56 + 132.87 * t - 0.009173 * T2) * dr) ' Mean new moon
m = 359.2242 + 29.10535608 * k - 0.0000333 * T2 - 0.00000347 * T3 ' Sun's mean anomaly
Mpr = 306.0253 + 385.81691806 * k + 0.0107306 * T2 + 0.00001236 * T3 ' Moon's mean anomaly
F = 21.2964 + 390.67050646 * k - 0.0016528 * T2 - 0.00000239 * T3 ' Moon's argument of latitude
C1 = (0.1734 - 0.000393 * t) * Sin(m * dr) + 0.0021 * Sin(2 * dr * m)
C1 = C1 - 0.4068 * Sin(Mpr * dr) + 0.0161 * Sin(dr * 2 * Mpr)
C1 = C1 - 0.0004 * Sin(dr * 3 * Mpr)
C1 = C1 + 0.0104 * Sin(dr * 2 * F) - 0.0051 * Sin(dr * (m + Mpr))
C1 = C1 - 0.0074 * Sin(dr * (m - Mpr)) + 0.0004 * Sin(dr * (2 * F + m))
C1 = C1 - 0.0004 * Sin(dr * (2 * F - m)) - 0.0006 * Sin(dr * (2 * F + Mpr))
C1 = C1 + 0.001 * Sin(dr * (2 * F - Mpr)) + 0.0005 * Sin(dr * (2 * Mpr + m))
If (t < -11) Then
deltat = 0.001 + 0.000839 * t + 0.0002261 * T2 - 0.00000845 * T3 - 0.000000081 * t * T3
Else
deltat = -0.000278 + 0.000265 * t + 0.000262 * T2
End If
JdNew = Jd1 + C1 - deltat
getNewMoonDay = Int(JdNew + 0.5 + Timezone / 24)
End Function

Private Function getSunLongitude(ByVal jdn As Long, ByVal Timezone As Integer, Optional ByVal Exactly As Boolean = False) As Double
Dim t, T2, dr, m, L0, DL, l
t = (jdn - 2451545.5 - Timezone / 24) / 36525 ' Time in Julian centuries from 2000-01-01 12:00:00 GMT
If Exactly Then t = t + 0.5 / 36525
T2 = t * t
dr = WorksheetFunction.Pi / 180 ' degree to radian
m = 357.5291 + 35999.0503 * t - 0.0001559 * T2 - 0.00000048 * t * T2 ' mean anomaly, degree
L0 = 280.46645 + 36000.76983 * t + 0.0003032 * T2 ' mean longitude, degree
DL = (1.9146 - 0.004817 * t - 0.000014 * T2) * Sin(dr * m)
DL = DL + (0.019993 - 0.000101 * t) * Sin(dr * 2 * m) + 0.00029 * Sin(dr * 3 * m)
l = L0 + DL ' true longitude, degree
If Exactly Then
l = l - 0.00569 - 0.00478 * Sin(125.04 * dr - 1934.136 * t * dr)
l = l - 360 * Int(l / 360)
getSunLongitude = l
Else
l = l * dr
l = l - WorksheetFunction.Pi * 2 * (Int(l / (WorksheetFunction.Pi * 2))) ' Normalize to (0, 2*PI)
getSunLongitude = Int(l / WorksheetFunction.Pi * 6)
End If
End Function

Private Function getLunarMonth11(ByVal yy As Integer, ByVal Timezone As Integer) As Long
Dim k, off, nm, sunLong
off = jdFromDate(31, 12, yy) - 2415021
k = Int(off / 29.530588853)
nm = getNewMoonDay(k, Timezone)
sunLong = getSunLongitude(nm, Timezone) ' sun longitude at local midnight
If (sunLong >= 9) Then nm = getNewMoonDay(k - 1, Timezone)
getLunarMonth11 = nm
End Function

Private Function getLeapMonthOffset(ByVal a11 As Long, ByVal Timezone As Integer) As Integer
Dim k, last, Arc, i
k = Int((a11 - 2415021.07699869) / 29.530588853 + 0.5)
last = 0
i = 1 ' We start with the month following lunar month 11
Arc = getSunLongitude(getNewMoonDay(k + i, Timezone), Timezone)
Do While (Arc <> last And i < 14)
last = Arc
i = i + 1
Arc = getSunLongitude(getNewMoonDay(k + i, Timezone), Timezone)
Loop
getLeapMonthOffset = i - 1
End Function

Public Function ChuyenAL(ByVal dd As Integer, ByVal mm As Integer, ByVal yy As Integer, Optional ByVal Timezone As Integer = 7) As Long
Dim k, dayNumber, monthStart, a11, b11, lunarLeap, diff, leapMonthDiff
Dim lunarDay As Integer, lunarMonth As Integer, lunarYear As Integer
dayNumber = jdFromDate(dd, mm, yy)
k = Int((dayNumber - 2415021.07699869) / 29.530588853)
monthStart = getNewMoonDay(k + 1, Timezone)
If (monthStart > dayNumber) Then monthStart = getNewMoonDay(k, Timezone)
a11 = getLunarMonth11(yy, Timezone)
b11 = a11
If (a11 >= monthStart) Then
lunarYear = yy
a11 = getLunarMonth11(yy - 1, Timezone)
Else
lunarYear = yy + 1
b11 = getLunarMonth11(yy + 1, Timezone)
End If
lunarDay = dayNumber - monthStart + 1
diff = Int((monthStart - a11) / 29)
lunarLeap = 0
lunarMonth = diff + 11
If (b11 - a11 > 365) Then
leapMonthDiff = getLeapMonthOffset(a11, Timezone)
If (diff >= leapMonthDiff) Then
lunarMonth = diff + 10
If (diff = leapMonthDiff) Then lunarLeap = 1
End If
End If
If (lunarMonth > 12) Then lunarMonth = lunarMonth - 12
If (lunarMonth >= 11 And diff < 4) Then lunarYear = lunarYear - 1
'If lunarLeap = 0 Then
' ChuyenAL = DateFrom(lunarDay, lunarMonth, lunarYear)
'Else
' ChuyenAL = lunarDay & "/" & lunarMonth & "n/" & lunarYear
'End If
ChuyenAL = DateFrom(lunarDay, lunarMonth, lunarYear)
End Function

Public Function ChuyenDL(ByVal lunarDay As Integer, ByVal lunarMonth As Integer, ByVal lunarYear As Integer, _
Optional ByVal lunarLeap As Integer = 0, Optional ByVal Timezone As Integer = 7) As Long
Dim k, a11, b11, off, leapOff, leapMonth, monthStart
If (lunarMonth < 11) Then
a11 = getLunarMonth11(lunarYear - 1, Timezone)
b11 = getLunarMonth11(lunarYear, Timezone)
Else
a11 = getLunarMonth11(lunarYear, Timezone)
b11 = getLunarMonth11(lunarYear + 1, Timezone)
End If
off = lunarMonth - 11
If (off < 0) Then off = off + 12
If (b11 - a11 > 365) Then
leapOff = getLeapMonthOffset(a11, Timezone)
leapMonth = leapOff - 2
If (leapMonth < 0) Then leapMonth = leapMonth + 12
If (lunarLeap <> 0 And lunarMonth <> leapMonth) Then
ChuyenDL = 0
Else
If (lunarLeap <> 0 Or off >= leapOff) Then off = off + 1
End If
End If
k = Int(0.5 + (a11 - 2415021.07699869) / 29.530588853)
monthStart = getNewMoonDay(k + off, Timezone)
ChuyenDL = jdToDate(monthStart + lunarDay - 1)
End Function

Public Function NhuanAL(ByVal dd As Integer, ByVal mm As Integer, ByVal yy As Integer, Optional ByVal Timezone As Integer = 7) As Boolean
Dim k, dayNumber, monthStart, a11, b11, lunarLeap, diff, leapMonthDiff
Dim lunarDay As Integer, lunarMonth As Integer, lunarYear As Integer
dayNumber = jdFromDate(dd, mm, yy)
k = Int((dayNumber - 2415021.07699869) / 29.530588853)
monthStart = getNewMoonDay(k + 1, Timezone)
If (monthStart > dayNumber) Then monthStart = getNewMoonDay(k, Timezone)
a11 = getLunarMonth11(yy, Timezone)
b11 = a11
If (a11 >= monthStart) Then
lunarYear = yy
a11 = getLunarMonth11(yy - 1, Timezone)
Else
lunarYear = yy + 1
b11 = getLunarMonth11(yy + 1, Timezone)
End If
diff = Int((monthStart - a11) / 29)
lunarLeap = 0
lunarMonth = diff + 11
If (b11 - a11 > 365) Then
leapMonthDiff = getLeapMonthOffset(a11, Timezone)
If (diff >= leapMonthDiff) Then
lunarMonth = diff + 10
If (diff = leapMonthDiff) Then lunarLeap = 1
End If
End If
NhuanAL = (lunarLeap = 1)
End Function
 

chgjst

Hội viên
Module 3: Can, Chi, Ngũ Hành, Hoa Giáp

Gồm một số hàm cơ bản:
1. Can(i), Chi(i): Trả về giá trị thứ tự can chi hoặc tên can chi, nếu đưa i = 1 thì sẽ trả về Giáp, Tý. Nếu đưa giá trị "Giáp", "Tý" sẽ trả về giá trị 1

2. NamAL, ThangAL, NgayAL, GioAL, chuyen doi nam thang ngay gio sang tên gọi theo âm lịch, vd bạn đưa NamAL(2013) sẽ trả về giá trị "Quý Tỵ", chú ý dùng ngày tháng năm âm.

3. HoaGiap(i): trả về giá trị số thứ tự của một năm theo lục thập hoa giáp hoặc trả về tên nếu i là số thứ tự, VD HoaGiap(1) = "Giáp Tý", HoaGiap("Giáp Tý") = 1.

4. TuanThu(i): trả về giá trị năm tuần thủ của năm thứ i theo bảng hoa giáp. VD: TuanThu(2) sẽ = 1, hay TuanThu("Ất Sửu") = "Giáp Tý"

5. NguHanh(i,Dangso): trả về giá trị ngũ hành của năm i. VD: NguHanh(1,TRUE) = 4 hay NguHanh(1,FALSE) = "Hải Trung Kim"

-------------------
Option Explicit

Public Function Can(ByVal i As Variant) As Variant
Dim Str As String
Dim Num As Integer
Select Case i
Case 1: Str = "Giasp"
Case 2: Str = "Aast"
Case 3: Str = "Bisnh"
Case 4: Str = "Ddinh"
Case 5: Str = "Maaju"
Case 6: Str = "Kyr"
Case 7: Str = "Canh"
Case 8: Str = "Taan"
Case 9: Str = "Nhaam"
Case 10: Str = "Quys"
Case VN("Giasp"): Num = 1
Case VN("Aast"): Num = 2
Case VN("Bisnh"): Num = 3
Case VN("Ddinh"): Num = 4
Case VN("Maaju"): Num = 5
Case VN("Kyr"): Num = 6
Case VN("Canh"): Num = 7
Case VN("Taan"): Num = 8
Case VN("Nhaam"): Num = 9
Case VN("Quys"): Num = 10
End Select
If i < 11 Then Can = VN(Str) Else Can = Num
End Function

Public Function Chi(ByVal i As Variant) As Variant
Dim Str As String
Dim Num As Integer
Select Case i
Case 1: Str = "Tys"
Case 2: Str = "Suwru"
Case 3: Str = "Daafn"
Case 4: Str = "Maxo"
Case 5: Str = "Thifn"
Case 6: Str = "Tyj"
Case 7: Str = "Ngoj"
Case 8: Str = "Mufi"
Case 9: Str = "Thaan"
Case 10: Str = "Daaju"
Case 11: Str = "Tuaast"
Case 12: Str = "Howji"
Case VN("Tys"): Num = 1
Case VN("Suwru"): Num = 2
Case VN("Daafn"): Num = 3
Case VN("Maxo"): Num = 4
Case VN("Thifn"): Num = 5
Case VN("Tyj"): Num = 6
Case VN("Ngoj"): Num = 7
Case VN("Mufi"): Num = 8
Case VN("Thaan"): Num = 9
Case VN("Daaju"): Num = 10
Case VN("Tuaast"): Num = 11
Case VN("Howji"): Num = 12
End Select
If i < 13 Then Chi = VN(Str) Else Chi = Num
End Function

Public Function NamAL(ByVal Nam As Integer) As String
Dim i As Integer
Dim j As Integer
i = (Nam - 3) Mod 10
j = (Nam - 3) Mod 12
If i <= 0 Then i = i + 10
If j <= 0 Then j = j + 12
NamAL = Can(i) & " " & Chi(j)
End Function

Public Function ThangAL(ByVal Thang As Integer, ByVal Nam As Integer) As String
Dim i As Integer
Dim j As Integer
i = (Nam - 3) Mod 10
i = i * 2 + 1
If i > 10 Then i = i - 10
i = i + Thang - 1
j = Thang + 2
ThangAL = Can(i) & " " & Chi(j)
End Function

Public Function NgayAL(ByVal Ngay As Integer, ByVal Thang As Integer, ByVal Nam As Integer, Optional DuongLich As Boolean = False) As String
Dim i As Integer
Dim j As Long
If DuongLich Then j = DateFrom(Ngay, Thang, Nam) Else j = ChuyenDL(Ngay, Thang, Nam)
i = (j - 1) Mod 10
j = (j - 3) Mod 12
If i = 0 Then i = 10
If j = 0 Then j = 12
NgayAL = Can(i) & " " & Chi(j)
End Function

Public Function GioAL(ByVal Gio As Single, ByVal Ngay As Integer, ByVal Thang As Integer, ByVal Nam As Integer, Optional DuongLich As Boolean = False) As String
Dim i As Integer
Dim j As Long
If DuongLich Then j = DateFrom(Ngay, Thang, Nam) Else j = ChuyenDL(Ngay, Thang, Nam)
i = (j - 1) Mod 10
i = (i - 1) * 2 + 1
If i > 10 Then i = i - 10
If Gio < 1 Then j = Int(Gio * 12 + 1.5) Else j = Int(Gio / 2 + 1.5)
i = i + j - 1
GioAL = Can(i) & " " & Chi(j)
End Function

Public Function TuanThu(ByVal n As Variant) As Variant
Dim Num As Integer
Dim Str As String
If n < 61 Then
Num = n - ((n - 1) Mod 10)
TuanThu = Num
Else
Num = HoaGiap(n)
Num = Num - ((Num - 1) Mod 10)
TuanThu = HoaGiap(Num)
End If
End Function

Public Function HoaGiap(ByVal n As Variant) As Variant
Dim i, j As Integer
Dim Str, s, t As String
If n < 61 Then
i = ((n - 1) Mod 10) + 1
j = ((n - 1) Mod 12) + 1
HoaGiap = Can(i) & " " & Chi(j)
Else
Str = n
i = Application.WorksheetFunction.Search(" ", Str, 1)
s = Left(n, i - 1)
t = Right(n, Len(Str) - i)
i = Can(s)
j = Chi(t)
Do While i <> j And i < 61
If i < j Then i = i + 10
If j < i Then j = j + 12
Loop
HoaGiap = i
End If
End Function

Public Function NguHanh(ByVal SttHG As Variant, Optional DangSo As Boolean = False) As Variant
Dim Num As Integer
Dim Str As String
Select Case i
Case 1, 2:
Str = "Hari Trung Kim"
Num = 4
Case 3, 4:
Str = "Loo Trung Hoar"
Num = 6
Case 5, 6:
Str = "Ddaji Laam Moojc"
Num = 3
Case 7, 8:
Str = "Looj Bafng Thoor"
Num = 5
Case 9, 10:
Str = "Kieesm Phong Kim"
Num = 4
Case 11, 12:
Str = "Sown Ddaafu Hoar"
Num = 6
Case 13, 14:
Str = "Giarn Haj Thuyr"
Num = 2
Case 15, 16:
Str = "Thafnh Ddaafu Thoor"
Num = 5
Case 17, 18:
Str = "Bajch Lajp Kim"
Num = 4
Case 19, 20:
Str = "Duwowng Lieexu Moojc"
Num = 3
Case 21, 22:
Str = "Tuyeefn Trung Thuyr"
Num = 2
Case 23, 24:
Str = "Oosc Thuwowjng Thoor"
Num = 5
Case 25, 26:
Str = "Tisch Lijch Hoar"
Num = 6
Case 27, 28:
Str = "Tufng Basch Moojc"
Num = 3
Case 29, 30:
Str = "Truwowfng Luwu Thuyr"
Num = 2
Case 31, 32:
Str = "Sa Trung Kim"
Num = 4
Case 33, 34:
Str = "Sown Ddaafu Hoar"
Num = 6
Case 35, 36:
Str = "Bifnh Ddija Moojc"
Num = 3
Case 37, 38:
Str = "Bisch Thuwowjng Thoor"
Num = 5
Case 39, 40:
Str = "Kim Bajc Kim"
Num = 4
Case 41, 42:
Str = "Phus Ddawng Hoar"
Num = 6
Case 43, 44:
Str = "Thieen Haf Thuyr"
Num = 2
Case 45, 46:
Str = "Ddaij Dijch Thoor"
Num = 5
Case 47, 48:
Str = "Thoa Xuyeesn Kim"
Num = 4
Case 49, 50:
Str = "Tang Ddoos Moojc"
Num = 3
Case 51, 52:
Str = "Ddaji Hari Thuyr"
Num = 2
Case 53, 54:
Str = "Sa Trung Thoor"
Num = 5
Case 55, 56:
Str = "Thieen Thuwowjng Hoar"
Num = 6
Case 57, 58:
Str = "Thajch Luwju Moojc"
Num = 3
Case 59, 60:
Str = "Ddaji Hari Thuyr"
Num = 2
End Select
If DangSo Then NguHanh = Num Else NguHanh = VN(Str)
End Function
 
Last edited by a moderator:

chgjst

Hội viên
Module 4: Tiết Khí, Số Cục

Phần Tietkhi các bạn nên đưa cùng vào module 2 vì có sử dụng hàm của module 2, nếu không các bạn đưa hàm Getsunglongitude thành public.

Hàm cơ bản: Tietkhi:

1. Tietkhi(i) trả về giá trị thứ tự hoặc tên: VD Tietkhi(1) = "Đông chí" hoặc Tietkhi("Đông chí") = 1

2. Tietkhi(i,j) trả về giá trị ngày đầu tiên của tiết khí i trong năm j

3. Tietkhi(i,j,k) trả về giá trị ngày i tháng j năm k (0:00 AM) đang thuộc tiết khí nào

Hàm SoCuc(i,j) trả về giá trị số cục của tiết j trong nguyên j (Thượng 1, trung 2, hạ 3)

Tương tự can chi là hàm ChucSu, ChucPhu

Hàm Chuyencung(i,j,k,l,m) trả về giá trị mới tính từ cung i chuyển j cung theo chiều k ("Dương","Âm", hoặc TRUE, FALSE) với tổng số cung trên bàn là l cung và nếu có bỏ qua cung nào thì đó là cung m.

-------------------------
Option Explicit


Public Function TietKhi(ByVal i As Variant, Optional j As Integer = 0, Optional NamDL As Integer = 0, Optional Timezone As Integer = 7) As Variant
Dim Str As String
Dim Num, TK, TD As Integer
Dim Ngaytim As Long
Dim D As Double
Select Case i
Case 1: Str = "Ddoong chis"
Case 2: Str = "Tieeru hafn"
Case 3: Str = "Ddaji hafn"
Case 4: Str = "Laajp xuaan"
Case 5: Str = "Vux thuyr"
Case 6: Str = "Kinh chaajp"
Case 7: Str = "Xuaan phaan"
Case 8: Str = "Thanh Minh"
Case 9: Str = "Coosc vux"
Case 10: Str = "Laajp haj"
Case 11: Str = "Tieeru maxn"
Case 12: Str = "Mang churng"
Case 13: Str = "Haj chis"
Case 14: Str = "Tieeru thuwr"
Case 15: Str = "Ddaji thuwr"
Case 16: Str = "Laajp thu"
Case 17: Str = "Suwr thuwr"
Case 18: Str = "Bajch looj"
Case 19: Str = "Thu phaan"
Case 20: Str = "Hafn looj"
Case 21: Str = "Suwowng giasng"
Case 22: Str = "Laajp ddoong"
Case 23: Str = "Tieeru tuyeest"
Case 24: Str = "Ddaji tuyeest"
Case VN("Ddoong chis"): Num = 1
Case VN("Tieeru hafn"): Num = 2
Case VN("Ddaji hafn"): Num = 3
Case VN("Laajp xuaan"): Num = 4
Case VN("Vux thuyr"): Num = 5
Case VN("Kinh chaajp"): Num = 6
Case VN("Xuaan phaan"): Num = 7
Case VN("Thanh Minh"): Num = 8
Case VN("Coosc vux"): Num = 9
Case VN("Laajp haj"): Num = 10
Case VN("Tieeru maxn"): Num = 11
Case VN("Mang churng"): Num = 12
Case VN("Haj chis"): Num = 13
Case VN("Tieeru thuwr"): Num = 14
Case VN("Ddaji thuwr"): Num = 15
Case VN("Laajp thu"): Num = 16
Case VN("Suwr thuwr"): Num = 17
Case VN("Bajch looj"): Num = 18
Case VN("Thu phaan"): Num = 19
Case VN("Hafn looj"): Num = 20
Case VN("Suwowng giasng"): Num = 21
Case VN("Laajp ddoong"): Num = 22
Case VN("Tieeru tuyeest"): Num = 23
Case VN("Ddaji tuyeest"): Num = 24
End Select
If j = 0 And NamDL = 0 Then
If i < 25 Then TietKhi = VN(Str) Else TietKhi = Num
Else
If NamDL = 0 Then
If i < 25 Then TK = i Else TK = Num
Ngaytim = jdFromDate(20, 12, j - 1)
Ngaytim = Ngaytim + 15 * (TK - 1)
TD = 270 + 15 * (TK - 1)
If TD >= 360 Then TD = TD - 360
D = getSunLongitude(Ngaytim, Timezone, True)
Do While D < TD
Ngaytim = Ngaytim + 1
D = getSunLongitude(Ngaytim, Timezone, True)
Loop
' Do While D > TD
' Ngaytim = Ngaytim - 1
' D = getSunLongitude(Ngaytim, Timezone, True)
' Loop
' Ngaytim = Ngaytim + 1
TietKhi = jdToDate(Ngaytim)
Else
Ngaytim = jdFromDate(i, j, NamDL)
D = getSunLongitude(Ngaytim, Timezone, True)
If D >= 270 Then Num = Int((D - 270) / 15) + 1 Else Num = Int(D / 15) + 7
TietKhi = Num
End If
End If
End Function

Function ChuyenCung(ByVal CungDau As Integer, ByVal SoCung As Integer, ByVal Thuan As Variant, ByVal TongCung As Integer, _
Optional ByVal CungBo As Integer = 0) As Integer
Dim i, n As Integer
n = CungDau
i = 1
If Thuan = VN("Duwowng") Then Thuan = True Else If Thuan = VN("Aam") Then Thuan = False
Do While i <= SoCung
If Thuan Then n = n + 1 Else n = n - 1
If n = 0 Then n = TongCung
If n > TongCung Then n = 1
If n <> CungBo Then i = i + 1
Loop
ChuyenCung = n
End Function

Public Function SoCuc(ByVal Tiet As Integer, ByVal Nguyen As Integer) As Integer
Dim i, j As Integer
If Tiet < 13 Then i = 1 Else i = -1
Select Case Tiet
Case 1: j = 1
Case 2: j = 2
Case 3: j = 3
Case 4: j = 8
Case 5: j = 9
Case 6: j = 1
Case 7: j = 3
Case 8: j = 4
Case 9: j = 5
Case 10: j = 4
Case 11: j = 5
Case 12: j = 6
Case 13: j = 9
Case 14: j = 8
Case 15: j = 7
Case 16: j = 2
Case 17: j = 1
Case 18: j = 9
Case 19: j = 7
Case 20: j = 6
Case 21: j = 5
Case 22: j = 6
Case 23: j = 5
Case 24: j = 4
End Select
If Nguyen < 4 And Nguyen > 0 Then
j = j + i * 6 * (Nguyen - 1)
Do While j < 1
j = j + 9
Loop
Do While j > 9
j = j - 9
Loop
SoCuc = j
End If
End Function

Public Function ChucSu(ByVal i As Variant) As Variant
Dim Str As String
Dim Num As Integer
If i < 10 Then
Select Case i
Case 1: Str = "Thieen Boofng"
Case 2: Str = "Thieen Nhuees"
Case 3: Str = "Thieen Xung"
Case 4: Str = "Thieen Phuj"
Case 5: Str = "Thieen Caafm"
Case 6: Str = "Thieen Taam"
Case 7: Str = "Thieen Truj"
Case 8: Str = "Thieen Nhaajm"
Case 9: Str = "Thieen Anh"
End Select
ChucSu = VN(Str)
Else
Select Case i
Case VN("Thieen Boofng"): Num = 1
Case VN("Thieen Nhuees"): Num = 2
Case VN("Thieen Xung"): Num = 3
Case VN("Thieen Phuj"): Num = 4
Case VN("Thieen Caafm"): Num = 5
Case VN("Thieen Taam"): Num = 6
Case VN("Thieen Truj"): Num = 7
Case VN("Thieen Nhaajm"): Num = 8
Case VN("Thieen Anh"): Num = 9
End Select
ChucSu = Num
End If
End Function

Public Function ChucPhu(ByVal i As Variant, Optional ByVal Duong As Variant) As Variant
Dim Str As String
Dim Num As Integer
If Duong = VN("Duwowng") Then Duong = True Else If Duong = VN("Aam") Then Duong = False
If i < 10 Then
Select Case i
Case 1: Str = "Huwu Moon"
Case 2: Str = "Sinh Moon"
Case 3: Str = "Thuwowng Moon"
Case 4: Str = "Ddoox Moon"
Case 5: If Duong Then Str = "Tuwr Moon" Else Str = "Sinh Moon"
Case 6: Str = "Carnh Moon"
Case 7: Str = "Tuwr Moon"
Case 8: Str = "Kinh Moon"
Case 9: Str = "Khai Moon"
End Select
ChucPhu = VN(Str)
Else
Select Case i
Case VN("Huwu Moon"): Num = 1
Case VN("Sinh Moon"): Num = 2
Case VN("Thuwowng Moon"): Num = 3
Case VN("Ddoox Moon"): Num = 4
Case VN("Carnh Moon"): Num = 6
Case VN("Tuwr Moon"): Num = 7
Case VN("Kinh Moon"): Num = 8
Case VN("Khai Moon"): Num = 9
End Select
ChucPhu = Num
End If
End Function
 

Sơn Chu

Quản trị viên
Trung lấy cái này ở đâu ra thế, hay là decode mấy file xls của người ta ra
 

chgjst

Hội viên
Cái này không có decode ra đâu ông bạn, còn nguồn của nó thì có nhiều nguồn như tôi đã nói ở phần đầu, trong đó phần tự biên cũng có nhiều. Riêng thuật toán tính ngày Âm Dương tôi chuyển thể từ mã JV của Mr Hồ Ngọc Đức. Anh em nào muốn dùng thì cần phải đưa nó vào marco đã nhé.

Note: các bạn cần đọc để hiểu thì chịu khó một chút vì nó không thò ra thụt vào như trên excel để dễ đọc được, cũng bởi vì khi chuyển sang đây thì nó bị mất, tuy nhiên đây là phần mã nguồn nên cũng chỉ cần copy vào là dùng được luôn.

@traiyeuthue: cái này chỉ dài thôi chứ không khó hiểu đâu.
 
Last edited by a moderator:

trungvu.sc

Thành viên
Sao e thấy như ngôn ngữ lập trình vì có các hàm if chẳng hạn, như vậy là đi sâu hơn tin học căn bản rồi ạ?
 

Sơn Chu

Quản trị viên
À mấy cái này thì không có gì, tôi tưởng có cái tính Tiết khí đến tận ngày giờ phút giây thì tham khảo luôn thôi. Ông thạo lập trình viết cái ấy đi tôi làm cái trình an Kỳ Môn cho ông keke
 

chgjst

Hội viên
À mấy cái này thì không có gì, tôi tưởng có cái tính Tiết khí đến tận ngày giờ phút giây thì tham khảo luôn thôi. Ông thạo lập trình viết cái ấy đi tôi làm cái trình an Kỳ Môn cho ông keke
Tôi cũng đã viết biến Exactly chờ sẵn trong hàm, đang định viết đây, nhưng cơ bản cái đó phải phù hợp với cách tính Thượng Trung Hạ nguyên và tiết Nhuận nữa
 

Sơn Chu

Quản trị viên
Tính theo cách của Hồ Ngọc Đức là được mà:
[h=1]Cách xác định 24 tiết khí[/h]Tiết khí là các thời điểm mà kinh độ mặt trời (KĐMT) có các giá trị 0°, 15°, 30°, 45°, 60°, ..., 345°. (0° là Xuân Phân, 15° là Thanh Minh v.v.). Như vậy để xác định tiết khí ta cần tìm xem vào khoảng thời gian nào thì kinh độ mặt trời có các giá trị này.[h=4]Tìm ngày chứa tiết khí[/h]Thường thì ta chỉ quan tâm tới tiết khí rơi vào ngày nào chứ không cần chính xác tới giờ/phút. Ngày chứa một tiết khí nhất định có thể được xác định như sau:
  • Chọn một ngày có khả năng chứa tiết khí cần xác định. Ngày có tiết khí chỉ xê dịch trong khoảng 1-2 ngày nên ta có thể chọn khá sát.
  • Tính kinh độ mặt trời lúc 0h sáng ngày hôm đó và 0h sáng ngày hôm sau
  • Nếu kinh độ mặt trời tương ứng với tiết khí cần xác định nằm giữa hai giá trị này thì ngày đã chọn chính là ngày chứa tiết khí, nếu không ta lặp lại việc tìm kiếm này với ngày trước hoặc sau đó.
[h=4]Tìm thời điểm tiết khí[/h]Để tìm thời điểm chính xác của một tiết khí, sau khi xác định được ngày chứa tiết khí đó ta có thể thực hiện một phép tìm kiếm nhị phân đơn giản để tìm ra ngày giờ của tiết khí này.
  • Chọn mốc trên và dưới là 0h và 24h (tức 0h sáng ngày hôm sau). Tính điểm giữa 2 mốc (12h trưa) và tính KĐMT tại điểm đó.
  • Nếu KĐMT này nhỏ hơn KĐMT của tiết khí, tìm tiếp trong khoảng từ 0h đến 12h, nếu không sẽ tìm trong khoảng từ 12h đến 24h.
  • Lặp lại việc tìm kiếm đến khi KĐMT của hai điểm mốc cách nhau không quá 0.001 độ.
Bước tính toán quan trọng nhất trong việc xác định tiết khí là tìm kinh độ mặt trời tại một thời điểm bất kỳ. Việc tính toán này được thực hiện với 2 bước:
  • Tính niên kỷ Julius của thời điểm đã cho
  • Tính kinh độ mặt trời cho thời điểm đó
[h=2]Ngày và niên kỷ Julius[/h]Số ngày Julius (Julian Day Number) của một ngày trong lịch Gregory có thể tính bởi các công thức sau, sử dụng năm thiên văn (1 TCN là 0, 2 TCN là −1, 4713 TCN là −4712):
a = [(14 - tháng)/ 12] y = năm + 4800 - a m= tháng + 12a - 3 JDN = ngày + [(153m + 2)/5] + 365y + [y/4] - [y/100] + [y/400] - 32045Trong các công thức trên [x/y] là phần nguyên của phép chia x/y.
Để tính niên kỷ Julius (Julian date), thêm giờ, phút, giây theo UT (Universal Time):

JD = JDN + (giờ - 12)/24 + phút/1440 + giây/86400Nếu giờ, phút, giây được tính theo giờ Hà Nội (UTC+7:00) thì kết quả phải trừ đi 7/24 ngày.
[h=2]Tính kinh độ mặt trời tại một thời điểm[/h]Để tính kinh độ mặt trời tại thời điểm, trước hết tìm niên kỷ Julius JD của thời điểm đó theo phương pháp trên. Sau đó thực hiện các bước sau:
T = (JD - 2451545.0) / 36525L0 = 280°.46645 + 36000°.76983*T + 0°.0003032*T[SUP]2[/SUP]M = 357°.52910 + 35999°.05030*T - 0°.0001559*T[SUP]2[/SUP] - 0°.00000048*T[SUP]3[/SUP]C = (1°.914600 - 0°.004817*T - 0°.000014*T[SUP]2[/SUP]) * sin M + (0°.01993 - 0°.000101*T) * sin 2M + 0°.000290 * sin 3Mtheta = L0 + Clambda = theta - 0.00569 - 0.00478 * sin(125°.04 - 1934°.136*T)lambda = lambda - 360 * [lambda/360]Kết quả lambda là kinh độ mặt trời cần tìm. Đó là một góc (tính bằng độ) trong khoảng (0,360).[h=3]Ví dụ[/h]Chọn ngày giờ (giờ Hà Nội, UTC+7:00) và nhấn OK để tính kinh độ mặt trời tại thời điểm đó: 0 h 1 h 2 h 3 h 4 h 5 h 6 h 7 h 8 h 9 h 10 h 11 h 12 h 13 h 14 h 15 h 16 h 17 h 18 h 19 h 20 h 21 h 22 h 23 h Ngày: tháng 1 2 3 4 5 6 7 8 9 10 11 12 năm Kết quả:
Tìm ngày Đông Chí năm 2008. Kinh độ mặt trời ứng với Đông Chí là 270°. Ngày Đông Chí thường rơi vào khoảng 20/12-22/12 hàng năm. Như vậy trước hết ta thử ngày 20/12/2008. KĐMT lúc 0h sáng ngày 20/12/2008 là 268°.17811 và lúc 0h sáng 21/12/2008 là 269°.19634. Góc 270° nằm sau cả hai giá trị này, như vậy ta phải thử ngày hôm sau. KĐMT lúc 0h sáng ngày 22/12/2008 là 270°.21471, như thế điểm Đông Chí nằm trong ngày 21/12/2008.
Để xác định thời điểm Đông Chí, ta tính KĐMT lúc 12h ngày 21/12/2008, được kết quả 269°.70551, nhỏ hơn 270°, như vậy điểm Đông Chí nằm trong khoảng từ 12h đến 24h. Chọn 18h00 ngày 21/12/2008 sẽ tìm thấy KĐMT 269°.96010, như vậy ta phải tìm tiếp trong khoảng 18h đến 24h. Vào lúc 21h, KĐMT là 270°.08741, như thế khoảng tìm kiếm bây giờ là 18h đến 21h. Lặp lại việc tìm kiếm này thêm khoảng 7 bước nữa sẽ tìm được thời điểm Đông Chí là 18h56. (Kết quả 'chính xác' tính theo lý thuyết VSOP87 là 19h04).
 

Sơn Chu

Quản trị viên
Để tính chính xác thì đơn giản là dùng thuật toán Đệ Quy ông ạ
 

chgjst

Hội viên
Thì tôi cũng đang viết theo thuật toán đấy rồi đó. Nhưng nó vẫn thiếu so với yêu cầu của Kỳ Môn
 

Sơn Chu

Quản trị viên
Tính thế đã, rồi tính tiếp keke, tính đi tôi còn convert qua php cho vào phần mềm Lịch của diễn đàn
 

trungtvls

Điều hành cấp cao
Tính thế đã, rồi tính tiếp keke, tính đi tôi còn convert qua php cho vào phần mềm Lịch của diễn đàn
Em tưởng ta đã có phần tính lịch, tiết khí trong phần mềm tử vi rồi chứ ạ ?
 

Sơn Chu

Quản trị viên
Trong phần mêm tính lịch cũng có rồi mà em Cái đó tinh ra đến ngày thôi em, chưa tinh đến chính xác đến tận phút giây
 

chgjst

Hội viên
Đây là module 2 + 4 đã chỉnh sửa hàm Tietkhi cho phép tính toán đến tận giờ phút giây. Tuy nhiên vẫn chưa phải là hàm để dùng trong Kỳ Môn (Vụ này để khí nào hỏi được thầy chi tiết đã, chứ tính Siêu Thần Tiếp Khí theo mốc năm nào thì chưa đọc ra)

Tietkhi(i) trả về giá trị thứ tự tiết khí hoặc tên. VD: Tietkhi(1) = "Đông chí" hay Tietkhi("Đông chí") = 1

Tietkhi(i,j) trả về giá trị ngày giờ bắt đầu của tiết khí i trong năm j

Tietkhi(i,"TRUE") trả về giá trị ngày giờ i (theo Excel) là thuộc tiết khí nào

------------------

Option Explicit

Private Function jdFromDate(ByVal dd As Integer, ByVal mm As Integer, ByVal yy As Integer, Optional ByVal hr As Integer = 0, _
Optional ByVal min As Integer = 0, Optional sec As Integer = 0, Optional Timezone As Integer = 7) As Double
Dim a, y, m, jd
a = Int((14 - mm) / 12)
y = yy + 4800 - a
m = mm + 12 * a - 3
jd = dd + Int((153 * m + 2) / 5) + 365 * y + Int(y / 4) - Int(y / 100) + Int(y / 400) - 32045
If (jd < 2299161) Then jd = dd + Int((153 * m + 2) / 5) + 365 * y + Int(y / 4) - 32083 - (Timezone / 24)
If hr > 0 Or min > 0 Or sec > 0 Then jd = jd + (hr - 12) / 24 + min / 1440 + sec / 86400
jdFromDate = jd
End Function

Private Function jdToDate(ByVal jd As Double) As Double
Dim a, b, c, D, e, m, day, month, year, hr, min, sec
If (jd > 2299160) Then
a = jd + 32044
b = Int((4 * a + 3) / 146097)
c = a - Int((b * 146097) / 4)
Else
b = 0
c = jd + 32082
End If
D = Int((4 * c + 3) / 1461)
e = c - Int((1461 * D) / 4)
m = Int((5 * e + 2) / 153)
day = e - Int((153 * m + 2) / 5) + 1
month = m + 3 - 12 * Int(m / 10)
year = b * 100 + D - 4800 + Int(m / 10)
'jdToDate = day & "/" & month & "/" & year
jdToDate = DateFrom(day, month, year) + jd - Int(jd)
End Function

Private Function getNewMoonDay(ByVal k As Integer, Optional ByVal Timezone As Integer = 7) As Long ' Tinh ngay soc
Dim T, T2, T3, dr, Jd1, m, Mpr, F, C1, deltat, JdNew
T = k / 1236.85 '' Time in Julian centuries from 1900 January 0.5
T2 = T * T
T3 = T2 * T
dr = WorksheetFunction.Pi / 180
Jd1 = 2415020.75933 + 29.53058868 * k + 0.0001178 * T2 - 0.000000155 * T3
Jd1 = Jd1 + 0.00033 * Sin((166.56 + 132.87 * T - 0.009173 * T2) * dr) ' Mean new moon
m = 359.2242 + 29.10535608 * k - 0.0000333 * T2 - 0.00000347 * T3 ' Sun's mean anomaly
Mpr = 306.0253 + 385.81691806 * k + 0.0107306 * T2 + 0.00001236 * T3 ' Moon's mean anomaly
F = 21.2964 + 390.67050646 * k - 0.0016528 * T2 - 0.00000239 * T3 ' Moon's argument of latitude
C1 = (0.1734 - 0.000393 * T) * Sin(m * dr) + 0.0021 * Sin(2 * dr * m)
C1 = C1 - 0.4068 * Sin(Mpr * dr) + 0.0161 * Sin(dr * 2 * Mpr)
C1 = C1 - 0.0004 * Sin(dr * 3 * Mpr)
C1 = C1 + 0.0104 * Sin(dr * 2 * F) - 0.0051 * Sin(dr * (m + Mpr))
C1 = C1 - 0.0074 * Sin(dr * (m - Mpr)) + 0.0004 * Sin(dr * (2 * F + m))
C1 = C1 - 0.0004 * Sin(dr * (2 * F - m)) - 0.0006 * Sin(dr * (2 * F + Mpr))
C1 = C1 + 0.001 * Sin(dr * (2 * F - Mpr)) + 0.0005 * Sin(dr * (2 * Mpr + m))
If (T < -11) Then
deltat = 0.001 + 0.000839 * T + 0.0002261 * T2 - 0.00000845 * T3 - 0.000000081 * T * T3
Else
deltat = -0.000278 + 0.000265 * T + 0.000262 * T2
End If
JdNew = Jd1 + C1 - deltat
getNewMoonDay = Int(JdNew + 0.5 + Timezone / 24)
End Function

Private Function getSunLongitude(ByVal jdn As Double, ByVal Timezone As Integer, Optional ByVal Exactly As Boolean = False) As Double
Dim T, T2, dr, m, L0, DL, l
T = (jdn - 2451545.5 - Timezone / 24) / 36525 ' Time in Julian centuries from 2000-01-01 12:00:00 GMT
If Exactly Then T = T + 0.5 / 36525
T2 = T * T
dr = WorksheetFunction.Pi / 180 ' degree to radian
m = 357.5291 + 35999.0503 * T - 0.0001559 * T2 - 0.00000048 * T * T2 ' mean anomaly, degree
L0 = 280.46645 + 36000.76983 * T + 0.0003032 * T2 ' mean longitude, degree
DL = (1.9146 - 0.004817 * T - 0.000014 * T2) * Sin(dr * m)
DL = DL + (0.019993 - 0.000101 * T) * Sin(dr * 2 * m) + 0.00029 * Sin(dr * 3 * m)
l = L0 + DL ' true longitude, degree
If Exactly Then
l = l - 0.00569 - 0.00478 * Sin(125.04 * dr - 1934.136 * T * dr)
l = l - 360 * Int(l / 360)
getSunLongitude = l
Else
l = l * dr
l = l - WorksheetFunction.Pi * 2 * (Int(l / (WorksheetFunction.Pi * 2))) ' Normalize to (0, 2*PI)
getSunLongitude = Int(l / WorksheetFunction.Pi * 6)
End If
End Function

Private Function getLunarMonth11(ByVal yy As Integer, Optional ByVal Timezone As Integer = 7) As Long
Dim k, off, nm, sunLong
off = jdFromDate(31, 12, yy) - 2415021
k = Int(off / 29.530588853)
nm = getNewMoonDay(k, Timezone)
sunLong = getSunLongitude(nm, Timezone) ' sun longitude at local midnight
If (sunLong >= 9) Then nm = getNewMoonDay(k - 1, Timezone)
getLunarMonth11 = nm
End Function

Private Function getLeapMonthOffset(ByVal a11 As Long, Optional ByVal Timezone As Integer = 7) As Integer
Dim k, last, Arc, i
k = Int((a11 - 2415021.07699869) / 29.530588853 + 0.5)
last = 0
i = 1 ' We start with the month following lunar month 11
Arc = getSunLongitude(getNewMoonDay(k + i, Timezone), Timezone)
Do While (Arc <> last And i < 14)
last = Arc
i = i + 1
Arc = getSunLongitude(getNewMoonDay(k + i, Timezone), Timezone)
Loop
getLeapMonthOffset = i - 1
End Function

Public Function ChuyenAL(ByVal dd As Integer, ByVal mm As Integer, ByVal yy As Integer, Optional ByVal Timezone As Integer = 7) As Double
Dim k, dayNumber, monthStart, a11, b11, lunarLeap, diff, leapMonthDiff
Dim lunarDay As Integer, lunarMonth As Integer, lunarYear As Integer
dayNumber = jdFromDate(dd, mm, yy)
k = Int((dayNumber - 2415021.07699869) / 29.530588853)
monthStart = getNewMoonDay(k + 1, Timezone)
If (monthStart > dayNumber) Then monthStart = getNewMoonDay(k, Timezone)
a11 = getLunarMonth11(yy, Timezone)
b11 = a11
If (a11 >= monthStart) Then
lunarYear = yy
a11 = getLunarMonth11(yy - 1, Timezone)
Else
lunarYear = yy + 1
b11 = getLunarMonth11(yy + 1, Timezone)
End If
lunarDay = dayNumber - monthStart + 1
diff = Int((monthStart - a11) / 29)
lunarLeap = 0
lunarMonth = diff + 11
If (b11 - a11 > 365) Then
leapMonthDiff = getLeapMonthOffset(a11, Timezone)
If (diff >= leapMonthDiff) Then
lunarMonth = diff + 10
If (diff = leapMonthDiff) Then lunarLeap = 1
End If
End If
If (lunarMonth > 12) Then lunarMonth = lunarMonth - 12
If (lunarMonth >= 11 And diff < 4) Then lunarYear = lunarYear - 1
'If lunarLeap = 0 Then
' ChuyenAL = DateFrom(lunarDay, lunarMonth, lunarYear)
'Else
' ChuyenAL = lunarDay & "/" & lunarMonth & "n/" & lunarYear
'End If
ChuyenAL = DateFrom(lunarDay, lunarMonth, lunarYear)
End Function

Public Function ChuyenDL(ByVal lunarDay As Integer, ByVal lunarMonth As Integer, ByVal lunarYear As Integer, _
Optional ByVal lunarLeap As Integer = 0, Optional ByVal Timezone As Integer = 7) As Double
Dim k, a11, b11, off, leapOff, leapMonth, monthStart
If (lunarMonth < 11) Then
a11 = getLunarMonth11(lunarYear - 1, Timezone)
b11 = getLunarMonth11(lunarYear, Timezone)
Else
a11 = getLunarMonth11(lunarYear, Timezone)
b11 = getLunarMonth11(lunarYear + 1, Timezone)
End If
off = lunarMonth - 11
If (off < 0) Then off = off + 12
If (b11 - a11 > 365) Then
leapOff = getLeapMonthOffset(a11, Timezone)
leapMonth = leapOff - 2
If (leapMonth < 0) Then leapMonth = leapMonth + 12
If (lunarLeap <> 0 And lunarMonth <> leapMonth) Then
ChuyenDL = 0
Else
If (lunarLeap <> 0 Or off >= leapOff) Then off = off + 1
End If
End If
k = Int(0.5 + (a11 - 2415021.07699869) / 29.530588853)
monthStart = getNewMoonDay(k + off, Timezone)
ChuyenDL = jdToDate(monthStart + lunarDay - 1)
End Function

Public Function ThangNhuan(ByVal dd As Integer, ByVal mm As Integer, ByVal yy As Integer, Optional ByVal Timezone As Integer = 7) As Boolean
Dim k, dayNumber, monthStart, a11, b11, lunarLeap, diff, leapMonthDiff
Dim lunarDay As Integer, lunarMonth As Integer, lunarYear As Integer
dayNumber = jdFromDate(dd, mm, yy)
k = Int((dayNumber - 2415021.07699869) / 29.530588853)
monthStart = getNewMoonDay(k + 1, Timezone)
If (monthStart > dayNumber) Then monthStart = getNewMoonDay(k, Timezone)
a11 = getLunarMonth11(yy, Timezone)
b11 = a11
If (a11 >= monthStart) Then
lunarYear = yy
a11 = getLunarMonth11(yy - 1, Timezone)
Else
lunarYear = yy + 1
b11 = getLunarMonth11(yy + 1, Timezone)
End If
diff = Int((monthStart - a11) / 29)
lunarLeap = 0
lunarMonth = diff + 11
If (b11 - a11 > 365) Then
leapMonthDiff = getLeapMonthOffset(a11, Timezone)
If (diff >= leapMonthDiff) Then
lunarMonth = diff + 10
If (diff = leapMonthDiff) Then lunarLeap = 1
End If
End If
ThangNhuan = (lunarLeap = 1)
End Function

Public Function TietKhi(ByVal i As Variant, Optional j As Variant = "FALSE", Optional Timezone As Integer = 7) As Variant
' Ham tra ve Ten Tiet Khi hoac STT tiet khi tinh tu Dong Chi, neu co tham so thu 2 thi se tra ve thoi diem bat dau cua tiet khi trong nam j
' Neu tham so thu 2 = "TRUE" thi se tinh xem ngay gio i nam trong tiet khi nao
Dim Str As String
Dim Num, TK, TD As Integer
Dim Ngaytim, Ngay1, Ngay2 As Double
Dim D As Double
Select Case i
Case 1: Str = "Ddoong chis"
Case 2: Str = "Tieeru hafn"
Case 3: Str = "Ddaji hafn"
Case 4: Str = "Laajp xuaan"
Case 5: Str = "Vux thuyr"
Case 6: Str = "Kinh chaajp"
Case 7: Str = "Xuaan phaan"
Case 8: Str = "Thanh Minh"
Case 9: Str = "Coosc vux"
Case 10: Str = "Laajp haj"
Case 11: Str = "Tieeru maxn"
Case 12: Str = "Mang churng"
Case 13: Str = "Haj chis"
Case 14: Str = "Tieeru thuwr"
Case 15: Str = "Ddaji thuwr"
Case 16: Str = "Laajp thu"
Case 17: Str = "Suwr thuwr"
Case 18: Str = "Bajch looj"
Case 19: Str = "Thu phaan"
Case 20: Str = "Hafn looj"
Case 21: Str = "Suwowng giasng"
Case 22: Str = "Laajp ddoong"
Case 23: Str = "Tieeru tuyeest"
Case 24: Str = "Ddaji tuyeest"
Case VN("Ddoong chis"): Num = 1
Case VN("Tieeru hafn"): Num = 2
Case VN("Ddaji hafn"): Num = 3
Case VN("Laajp xuaan"): Num = 4
Case VN("Vux thuyr"): Num = 5
Case VN("Kinh chaajp"): Num = 6
Case VN("Xuaan phaan"): Num = 7
Case VN("Thanh Minh"): Num = 8
Case VN("Coosc vux"): Num = 9
Case VN("Laajp haj"): Num = 10
Case VN("Tieeru maxn"): Num = 11
Case VN("Mang churng"): Num = 12
Case VN("Haj chis"): Num = 13
Case VN("Tieeru thuwr"): Num = 14
Case VN("Ddaji thuwr"): Num = 15
Case VN("Laajp thu"): Num = 16
Case VN("Suwr thuwr"): Num = 17
Case VN("Bajch looj"): Num = 18
Case VN("Thu phaan"): Num = 19
Case VN("Hafn looj"): Num = 20
Case VN("Suwowng giasng"): Num = 21
Case VN("Laajp ddoong"): Num = 22
Case VN("Tieeru tuyeest"): Num = 23
Case VN("Ddaji tuyeest"): Num = 24
End Select
If j = "FALSE" Then
If i < 25 Then TietKhi = VN(Str) Else TietKhi = Num
Else
If j <> "TRUE" Then
If i < 25 Then TK = i Else TK = Num
Ngaytim = jdFromDate(20, 12, j - 1, 0, 0, 0, Timezone)
Ngaytim = Ngaytim + 15 * (TK - 1)
TD = 270 + 15 * (TK - 1)
If TD >= 360 Then TD = TD - 360
D = getSunLongitude(Ngaytim, Timezone, True)
Do While D < TD
Ngaytim = Ngaytim + 1
D = getSunLongitude(Ngaytim, Timezone, True)
Loop
' Do While D > TD
' Ngaytim = Ngaytim - 1
' D = getSunLongitude(Ngaytim, Timezone, True)
' Loop
' Ngaytim = Ngaytim + 1
Ngay1 = Ngaytim - 1
Ngay2 = Ngaytim
Do While (Ngay1 + 1 / 86400) < Ngay2
Ngaytim = (Ngay1 + Ngay2) / 2
D = getSunLongitude(Ngaytim, Timezone, True)
If D < TD Then Ngay1 = Ngaytim Else Ngay2 = Ngaytim
Loop
TietKhi = jdToDate(Ngaytim)
Else
Ngaytim = jdFromDate(day(i), month(i), year(i), Hour(i), Minute(i), Second(i), Timezone)
D = getSunLongitude(Ngaytim, Timezone, True)
If D >= 270 Then Num = Int((D - 270) / 15) + 1 Else Num = Int(D / 15) + 7
TietKhi = Num
End If
End If
End Function
 

linhanh

Thành viên tâm huyết
À mấy cái này thì không có gì, tôi tưởng có cái tính Tiết khí đến tận ngày giờ phút giây thì tham khảo luôn thôi. Ông thạo lập trình viết cái ấy đi tôi làm cái trình an Kỳ Môn cho ông keke
Ước gì có cái trình an kỳ môn bằng tiếng việt =P~
 

Sơn Chu

Quản trị viên
Sẽ sớm có thôi bác, Hiện Diễn đàn đã có phần mềm an tinh bàn phong thủy rồi, còn vài cái nữa là Tử Bình và Kỳ Môn, Thái ất nữa thôi
 
Top