Excel VBA實(shí)現(xiàn)公歷轉(zhuǎn)農(nóng)歷函數(shù):算法解析與工程實(shí)踐
1. 項(xiàng)目概述為什么我們需要一個(gè)公歷轉(zhuǎn)農(nóng)歷的VBA函數(shù)在日常的辦公數(shù)據(jù)處理中尤其是處理涉及傳統(tǒng)節(jié)日、生辰八字、黃道吉日或者歷史檔案日期時(shí)我們常常會(huì)遇到一個(gè)需求如何將Excel表格里大量的公歷日期快速、準(zhǔn)確地轉(zhuǎn)換成對(duì)應(yīng)的農(nóng)歷日期Excel本身并沒(méi)有內(nèi)置這個(gè)功能網(wǎng)上找的公式往往又復(fù)雜難懂或者返回的格式五花八門(mén)不方便后續(xù)的排序、篩選和數(shù)據(jù)分析。這就是“EXCEL-VBA函數(shù)公歷轉(zhuǎn)農(nóng)歷返回格式Y(jié)YYY-MM-DD”這個(gè)項(xiàng)目要解決的核心痛點(diǎn)。這個(gè)函數(shù)的價(jià)值在于它將一個(gè)復(fù)雜的文化歷法計(jì)算過(guò)程封裝成一個(gè)像TODAY()一樣簡(jiǎn)單的自定義函數(shù)。你只需要在單元格里輸入ToLunar(A1)就能立刻得到格式統(tǒng)一為“2024-四月初五”這樣的標(biāo)準(zhǔn)農(nóng)歷日期字符串。對(duì)于HR部門(mén)排定傳統(tǒng)節(jié)日福利、文化活動(dòng)策劃人員安排日程、甚至是一些金融行業(yè)分析“月度效應(yīng)”時(shí)這個(gè)工具都能極大地提升效率。我自己就曾為了整理一份橫跨十年的傳統(tǒng)節(jié)氣活動(dòng)表手動(dòng)查了無(wú)數(shù)次日歷耗時(shí)耗力還容易出錯(cuò)直到自己動(dòng)手寫(xiě)了這個(gè)VBA函數(shù)才真正把時(shí)間還給了數(shù)據(jù)分析本身。2. 核心思路與算法選擇農(nóng)歷計(jì)算的底層邏輯農(nóng)歷又稱(chēng)夏歷是一種陰陽(yáng)合歷。它的計(jì)算遠(yuǎn)比單純的公歷復(fù)雜核心規(guī)則包括月相周期朔望月約29.53天、太陽(yáng)回歸年長(zhǎng)度以及為了調(diào)和這兩者而設(shè)置的閏月。這意味著我們不能用一個(gè)簡(jiǎn)單的數(shù)學(xué)公式來(lái)直接轉(zhuǎn)換。要實(shí)現(xiàn)公歷轉(zhuǎn)農(nóng)歷本質(zhì)上需要一個(gè)“映射表”或一套嚴(yán)密的推算規(guī)則。2.1 主流實(shí)現(xiàn)方案對(duì)比在動(dòng)手之前我調(diào)研了常見(jiàn)的幾種實(shí)現(xiàn)思路查表法預(yù)先建立一個(gè)龐大的公歷-農(nóng)歷對(duì)應(yīng)關(guān)系數(shù)據(jù)表函數(shù)通過(guò)查找這張表來(lái)返回結(jié)果。優(yōu)點(diǎn)是速度快、準(zhǔn)確因?yàn)閿?shù)據(jù)是固定的缺點(diǎn)是數(shù)據(jù)表龐大如果要覆蓋足夠長(zhǎng)的年份且缺乏靈活性無(wú)法計(jì)算表外日期。計(jì)算法基于天文算法或權(quán)威的農(nóng)歷計(jì)算規(guī)則如《壽星天文歷》的算法進(jìn)行實(shí)時(shí)推算。優(yōu)點(diǎn)是理論上可以計(jì)算任意日期無(wú)需存儲(chǔ)大量數(shù)據(jù)缺點(diǎn)是算法極其復(fù)雜涉及大量天文參數(shù)和迭代計(jì)算在VBA中實(shí)現(xiàn)難度高、運(yùn)行效率可能較低?;旌戏ū卷?xiàng)目采用結(jié)合兩者優(yōu)點(diǎn)。存儲(chǔ)農(nóng)歷新年春節(jié)的公歷日期以及該農(nóng)歷年的閏月信息等關(guān)鍵節(jié)點(diǎn)數(shù)據(jù)。轉(zhuǎn)換時(shí)先定位目標(biāo)公歷日期屬于哪個(gè)農(nóng)歷年再根據(jù)該年的月序和閏月信息推算出具體的農(nóng)歷月和日。這種方法在準(zhǔn)確性和復(fù)雜度之間取得了最佳平衡。我最終選擇了混合法。對(duì)于大多數(shù)辦公場(chǎng)景我們需要的日期范圍通常在1900-2100年之間這個(gè)范圍內(nèi)的農(nóng)歷數(shù)據(jù)是穩(wěn)定且可窮舉的。存儲(chǔ)約200年的關(guān)鍵節(jié)點(diǎn)數(shù)據(jù)其代碼體積是完全可以接受的而換來(lái)的則是函數(shù)邏輯的清晰和運(yùn)行速度的飛快。2.2 關(guān)鍵數(shù)據(jù)表的設(shè)計(jì)這是整個(gè)函數(shù)的核心。我們需要兩張關(guān)鍵數(shù)據(jù)表在VBA中用數(shù)組存儲(chǔ)農(nóng)歷新年表一個(gè)一維數(shù)組存儲(chǔ)每年農(nóng)歷正月初一對(duì)應(yīng)的公歷日期序列號(hào)。例如LunarNewYear(2024) 44927對(duì)應(yīng)公歷2024-02-10的Excel序列號(hào)。通過(guò)比較目標(biāo)日期和這些新年日期就能快速確定它屬于哪個(gè)農(nóng)歷年。農(nóng)歷年信息表一個(gè)一維數(shù)組存儲(chǔ)每年農(nóng)歷的“信息碼”。這是一個(gè)經(jīng)過(guò)編碼的整數(shù)它包含了該農(nóng)歷年總月數(shù)12或13個(gè)月。每個(gè)農(nóng)歷月是大月30天還是小月29天。通常用二進(jìn)制位來(lái)表示1為大月0為小月。如何獲取這些數(shù)據(jù)最可靠的方式是從權(quán)威的農(nóng)歷算法庫(kù)如lunardate等開(kāi)源項(xiàng)目或經(jīng)過(guò)校驗(yàn)的數(shù)據(jù)庫(kù)中提取出1900-2100年的關(guān)鍵數(shù)據(jù)然后將其硬編碼到VBA模塊中。雖然這會(huì)讓代碼看起來(lái)有一長(zhǎng)串?dāng)?shù)字但這是保證函數(shù)獨(dú)立性和準(zhǔn)確性的基石。注意網(wǎng)上有些簡(jiǎn)易算法使用近似公式計(jì)算在閏月處理或月末日期上可能會(huì)有誤差。對(duì)于嚴(yán)肅的工作應(yīng)用使用經(jīng)過(guò)驗(yàn)證的靜態(tài)數(shù)據(jù)表是更穩(wěn)妥的選擇。3. 函數(shù)設(shè)計(jì)與實(shí)現(xiàn)步驟拆解有了核心思路和數(shù)據(jù)我們就可以開(kāi)始構(gòu)建ToLunar函數(shù)了。我們的目標(biāo)是創(chuàng)建一個(gè)可以在Excel單元格中直接使用的自定義工作表函數(shù)。3.1 函數(shù)接口與參數(shù)設(shè)計(jì)函數(shù)簽名應(yīng)該盡可能簡(jiǎn)潔易用。Public Function ToLunar(ByVal GregorianDate As Variant, Optional ByVal FormatStr As String YYYY-MM-DD) As StringGregorianDate輸入的公歷日期。類(lèi)型設(shè)為Variant可以接受單元格引用、日期序列號(hào)或能被CDate識(shí)別的日期字符串容錯(cuò)性更好。FormatStr可選參數(shù)指定輸出格式。默認(rèn)是“YYYY-MM-DD”例如“2024-四月初五”。也可以設(shè)計(jì)支持“YYYY年M月D日”等多種格式。返回值格式化后的農(nóng)歷日期字符串。3.2 核心轉(zhuǎn)換流程詳解函數(shù)內(nèi)部的邏輯流程可以分解為以下幾個(gè)關(guān)鍵步驟步驟一輸入驗(yàn)證與初始化首先檢查輸入是否為空或無(wú)效日期。利用IsDate函數(shù)進(jìn)行判斷如果無(wú)效可以返回錯(cuò)誤提示如“#無(wú)效日期!”。將有效的輸入日期轉(zhuǎn)換為Excel的日期序列號(hào)一個(gè)整數(shù)方便后續(xù)計(jì)算。步驟二確定農(nóng)歷年份這是查表法的第一步。遍歷預(yù)存的“農(nóng)歷新年表”找到最后一個(gè)小于或等于目標(biāo)公歷日期序列號(hào)的農(nóng)歷新年。該新年對(duì)應(yīng)的年份就是目標(biāo)日期所在的農(nóng)歷年。 例如目標(biāo)日期是2024-05-12序列號(hào)45418。查表得知2024年春節(jié)是2024-02-10序列號(hào)449272025年春節(jié)是2025-01-29序列號(hào)45691。因?yàn)?4927 45418 45691所以確定其為農(nóng)歷2024年。步驟三解碼農(nóng)歷年信息計(jì)算農(nóng)歷月日獲取該農(nóng)歷年的“信息碼”。假設(shè)信息碼是0x15A96十六進(jìn)制實(shí)際存儲(chǔ)為十進(jìn)制整數(shù)。我們需要解碼它取出最后4位或根據(jù)編碼規(guī)則判斷該年是否有閏月以及閏在第幾月。例如0xA表示閏四月。從信息碼中解析出每個(gè)月的天數(shù)分布。通常是從高位到低位每一位代表一個(gè)月的天數(shù)1為30天0為29天。從該農(nóng)歷年的正月初一春節(jié)開(kāi)始用目標(biāo)公歷日期減去春節(jié)日期得到相差的天數(shù)DiffDays。用DiffDays從農(nóng)歷一月開(kāi)始依次減去每個(gè)農(nóng)歷月的天數(shù)先處理平月再處理閏月如果需要。當(dāng)DiffDays減去某個(gè)月的天數(shù)后即將小于0時(shí)當(dāng)前正在減的這個(gè)月就是農(nóng)歷月份而DiffDays1因?yàn)閺牡谝惶扉_(kāi)始算就是農(nóng)歷日期。步驟四格式化輸出將計(jì)算得到的農(nóng)歷年、月、日數(shù)字根據(jù)FormatStr參數(shù)進(jìn)行格式化。月份和日期需要轉(zhuǎn)換為中文數(shù)字如一、二、十、廿、卅。對(duì)于閏月要在月份前加上“閏”字如“閏四月”。 最后將格式化后的字符串返回。3.3 VBA代碼模塊結(jié)構(gòu)一個(gè)健壯的實(shí)現(xiàn)通常包含以下部分常量與數(shù)據(jù)模塊定義存儲(chǔ)農(nóng)歷新年數(shù)組和年信息數(shù)組的常量。這部分?jǐn)?shù)據(jù)量最大可以單獨(dú)放在一個(gè)模塊里。核心計(jì)算函數(shù)即ToLunar函數(shù)包含上述主邏輯。輔助函數(shù)GetLunarYearInfo根據(jù)公歷日期獲取對(duì)應(yīng)的農(nóng)歷年信息碼。DecodeLunarMonthDays解碼信息碼返回該農(nóng)歷年每月天數(shù)的數(shù)組。FormatLunarDate將農(nóng)歷年月日數(shù)字格式化為指定的中文字符串。DigitToChinese將數(shù)字1-30轉(zhuǎn)換為中文日期表示初一、二十、卅等。4. 完整代碼實(shí)現(xiàn)與關(guān)鍵點(diǎn)注釋下面是一個(gè)高度精簡(jiǎn)但結(jié)構(gòu)完整的示例框架展示了核心邏輯。實(shí)際應(yīng)用中LUNAR_NEW_YEAR_LIST和LUNAR_YEAR_INFO這兩個(gè)大數(shù)組需要你用完整數(shù)據(jù)填充?!?模塊LunarCalendarData ‘ 這里存放龐大的數(shù)據(jù)數(shù)組實(shí)際代碼中會(huì)有從1900到2100年的數(shù)據(jù) Public Const LUNAR_NEW_YEAR_LIST As String “19000131,19010219,...” ‘ 簡(jiǎn)化表示實(shí)際是數(shù)組 Public Const LUNAR_YEAR_INFO As String “0x04BD8,0x04AE0,...” ‘ 簡(jiǎn)化表示實(shí)際是數(shù)組 ‘ 模塊LunarConversion ‘ 主函數(shù) Public Function ToLunar(ByVal GregorianDate As Variant, Optional ByVal FormatStr As String “YYYY-MM-DD”) As String On Error GoTo ErrorHandler ‘ —– 步驟1輸入驗(yàn)證 —– If IsMissing(GregorianDate) Or IsEmpty(GregorianDate) Then ToLunar “” Exit Function End If If Not IsDate(GregorianDate) Then ToLunar “#無(wú)效日期!” Exit Function End If Dim dtTarget As Double dtTarget CDbl(CDate(GregorianDate)) ‘ 轉(zhuǎn)換為Excel日期序列號(hào) ‘ —– 步驟2確定農(nóng)歷年份 (偽代碼邏輯) —– Dim lunarYear As Integer Dim springFestivalDate As Double ‘ 遍歷 LUNAR_NEW_YEAR_LIST找到對(duì)應(yīng)的農(nóng)歷年lunarYear和春節(jié)日期springFestivalDate ‘ ... (具體查找代碼通常用循環(huán)比較) ‘ —– 步驟3獲取并解碼農(nóng)歷年信息 —– Dim yearInfoCode As Long yearInfoCode GetLunarYearInfoCode(lunarYear) ‘ 從LUNAR_YEAR_INFO中獲取 Dim leapMonth As Integer Dim monthDays() As Integer leapMonth (yearInfoCode 16) And 0xFF ‘ 假設(shè)高字節(jié)存儲(chǔ)閏月信息 monthDays DecodeMonthDays(yearInfoCode) ‘ 解碼出每月天數(shù)數(shù)組 ‘ —– 計(jì)算農(nóng)歷月日 —– Dim diffDays As Long diffDays CLng(dtTarget - springFestivalDate) ‘ 與春節(jié)相差的天數(shù) Dim lunarMonth As Integer, lunarDay As Integer Dim i As Integer, monthCount As Integer monthCount UBound(monthDays) ‘ 該年總月數(shù) For i 1 To monthCount If diffDays monthDays(i) Then lunarMonth i lunarDay diffDays 1 ‘ 天數(shù)從0開(kāi)始日期要1 Exit For End If diffDays diffDays - monthDays(i) Next i ‘ 處理閏月標(biāo)識(shí) Dim isLeapMonth As Boolean isLeapMonth (leapMonth 0 And lunarMonth leapMonth) ‘ 如果閏月存在且當(dāng)前月份大于閏月月份實(shí)際月份數(shù)需要調(diào)整此處邏輯需細(xì)化 ‘ —– 步驟4格式化輸出 —– ToLunar FormatLunarDate(lunarYear, lunarMonth, lunarDay, isLeapMonth, FormatStr) Exit Function ErrorHandler: ToLunar “#計(jì)算錯(cuò)誤!” End Function ‘ 輔助函數(shù)解碼月份天數(shù) Private Function DecodeMonthDays(ByVal yearInfo As Long) As Integer() ‘ 假設(shè)yearInfo的低位存儲(chǔ)了每月大小信息1為大月(30天)0為小月(29天) Dim days(1 To 13) As Integer ‘ 最多13個(gè)月 Dim i As Integer Dim tempInfo As Long tempInfo yearInfo And HFFFF ‘ 取低16位 For i 1 To 13 If (tempInfo And (1 (16 - i))) 0 Then ‘ 檢查每一位 days(i) 30 Else days(i) 29 End If ‘ 如果該年只有12個(gè)月則第13個(gè)月為0 Next i DecodeMonthDays days End Function ‘ 輔助函數(shù)格式化農(nóng)歷日期 Private Function FormatLunarDate(ByVal year As Integer, ByVal month As Integer, ByVal day As Integer, ByVal isLeap As Boolean, ByVal fmt As String) As String Dim chnMonth As String, chnDay As String ‘ 調(diào)用函數(shù)將數(shù)字轉(zhuǎn)為中文 chnMonth DigitToChinese(month, True) ‘ True表示月份 chnDay DigitToChinese(day, False) ‘ False表示日期 If isLeap Then chnMonth “閏” chnMonth End If ‘ 根據(jù)fmt格式化這里簡(jiǎn)單實(shí)現(xiàn)默認(rèn)格式 If fmt “YYYY-MM-DD” Then FormatLunarDate year “-” chnMonth “月” chnDay ElseIf fmt “YYYY年M月D日” Then FormatLunarDate year “年” chnMonth “月” chnDay “日” Else ‘ 其他格式處理… FormatLunarDate year “-” chnMonth “月” chnDay End If End Function ‘ 輔助函數(shù)數(shù)字轉(zhuǎn)中文簡(jiǎn)易版 Private Function DigitToChinese(ByVal num As Integer, ByVal isMonth As Boolean) As String Dim chnNumbers As Variant chnNumbers Array(“”, “一”, “二”, “三”, “四”, “五”, “六”, “七”, “八”, “九”, “十”) Dim chnDayStrings As Variant chnDayStrings Array(“初一”, “初二”, “初三”, “初四”, “初五”, “初六”, “初七”, “初八”, “初九”, “初十”, _ “十一”, “十二”, “十三”, “十四”, “十五”, “十六”, “十七”, “十八”, “十九”, “二十”, _ “廿一”, “廿二”, “廿三”, “廿四”, “廿五”, “廿六”, “廿七”, “廿八”, “廿九”, “三十”, “卅一”) If isMonth Then If num 10 Then DigitToChinese chnNumbers(num) ElseIf num 11 Then DigitToChinese “十一” ElseIf num 12 Then DigitToChinese “十二” End If Else If num 1 And num 31 Then DigitToChinese chnDayStrings(num - 1) Else DigitToChinese “” End If End If End Function5. 在Excel中的部署與使用指南編寫(xiě)好代碼后你需要將其部署到Excel中才能使用。5.1 如何導(dǎo)入VBA代碼打開(kāi)你的Excel工作簿。按下Alt F11快捷鍵打開(kāi)Visual Basic for Applications (VBA)編輯器。在編輯器菜單欄點(diǎn)擊“插入” - “模塊”。這會(huì)在左側(cè)“工程資源管理器”中創(chuàng)建一個(gè)新的標(biāo)準(zhǔn)模塊如“模塊1”。將上述完整的代碼包括數(shù)據(jù)數(shù)組、主函數(shù)和輔助函數(shù)復(fù)制粘貼到這個(gè)新模塊的代碼窗口中。關(guān)閉VBA編輯器返回Excel。5.2 在工作表中使用函數(shù)現(xiàn)在你可以像使用內(nèi)置函數(shù)一樣使用ToLunar了。假設(shè)A1單元格有一個(gè)公歷日期2024-05-12。在B1單元格輸入公式ToLunar(A1)按下回車(chē)B1單元格就會(huì)顯示2024-四月初五。你也可以指定格式ToLunar(A1, “YYYY年M月D日”)結(jié)果將是2024年四月十二日。5.3 保存工作簿的注意事項(xiàng)包含VBA代碼的Excel文件需要保存為“Excel 啟用宏的工作簿 (*.xlsm)”格式。如果保存為普通的.xlsx格式所有VBA代碼將會(huì)丟失。實(shí)操心得建議你將這個(gè)函數(shù)封裝在一個(gè)專(zhuān)門(mén)用于工具的工作簿中然后通過(guò)“加載宏”的方式使其在所有Excel文件中可用。具體操作是在VBA編輯器中將你的模塊導(dǎo)出為.bas文件然后在一個(gè)新建的.xlam文件中導(dǎo)入最后在Excel的“開(kāi)發(fā)工具”-“加載項(xiàng)”中瀏覽并添加這個(gè).xlam文件。這樣無(wú)論你打開(kāi)哪個(gè)工作簿都可以直接調(diào)用ToLunar函數(shù)了。6. 常見(jiàn)問(wèn)題、誤差排查與優(yōu)化技巧即使算法和數(shù)據(jù)正確在實(shí)際使用中也可能遇到各種問(wèn)題。以下是我在開(kāi)發(fā)和長(zhǎng)期使用中總結(jié)的一些坑點(diǎn)和解決方案。6.1 日期轉(zhuǎn)換錯(cuò)誤或返回#VALUE!問(wèn)題表現(xiàn)函數(shù)返回#無(wú)效日期!或#VALUE!錯(cuò)誤。排查步驟檢查輸入確保函數(shù)參數(shù)引用的是一個(gè)真正的Excel日期單元格。Excel有時(shí)會(huì)將看起來(lái)像日期的文本存儲(chǔ)為文本格式。用ISNUMBER(A1)檢查如果是日期應(yīng)返回TRUE。檢查數(shù)據(jù)范圍確認(rèn)你的公歷日期是否在預(yù)置的農(nóng)歷數(shù)據(jù)年份范圍內(nèi)如1900-2100年。如果輸入了2101年的日期函數(shù)可能因找不到對(duì)應(yīng)農(nóng)歷年信息而報(bào)錯(cuò)??梢栽诤瘮?shù)開(kāi)頭添加范圍校驗(yàn)并給出友好提示。檢查VBA引用極少數(shù)情況下如果代碼中使用了某些特殊的庫(kù)函數(shù)需要確保VBA工程引用正確。但我們的純算法函數(shù)通常不需要。6.2 農(nóng)歷日期結(jié)果明顯錯(cuò)誤問(wèn)題表現(xiàn)轉(zhuǎn)換出的農(nóng)歷日期與權(quán)威日歷對(duì)不上尤其是月末、閏月附近。排查步驟驗(yàn)證基準(zhǔn)點(diǎn)首先驗(yàn)證幾個(gè)關(guān)鍵節(jié)點(diǎn)的正確性如每年的春節(jié)日期。找一個(gè)已知的春節(jié)如2024年2月10日用函數(shù)轉(zhuǎn)換看是否顯示“2024-正月初一”。如果春節(jié)就錯(cuò)了說(shuō)明LUNAR_NEW_YEAR_LIST數(shù)據(jù)有誤。檢查閏月邏輯這是最容易出錯(cuò)的地方。重點(diǎn)測(cè)試閏月前后的日期。例如2023年閏二月檢查公歷2023-03-22閏二月初一和2023-04-20三月初一的轉(zhuǎn)換是否正確。需要仔細(xì)核對(duì)DecodeLunarMonthDays函數(shù)中閏月的插入位置和月份天數(shù)的累計(jì)邏輯。調(diào)試計(jì)算過(guò)程在VBA編輯器中對(duì)特定日期設(shè)置斷點(diǎn)單步執(zhí)行觀(guān)察diffDays變量在循環(huán)減去每月天數(shù)時(shí)的變化看它是在哪個(gè)月份跳出循環(huán)的并與正確結(jié)果對(duì)比。6.3 性能優(yōu)化建議當(dāng)需要對(duì)數(shù)萬(wàn)行日期進(jìn)行批量轉(zhuǎn)換時(shí)函數(shù)的效率就變得重要了。使用靜態(tài)數(shù)組或字典在函數(shù)內(nèi)部將龐大的LUNAR_NEW_YEAR_LIST和LUNAR_YEAR_INFO數(shù)據(jù)從常量字符串加載到靜態(tài)數(shù)組或Scripting.Dictionary中。靜態(tài)變量只會(huì)在第一次調(diào)用函數(shù)時(shí)初始化之后的所有調(diào)用都直接使用內(nèi)存中的數(shù)據(jù)避免了每次調(diào)用都解析字符串的開(kāi)銷(xiāo)。Private Static DictNewYear As Object Private Function GetNewYearDict() As Object If DictNewYear Is Nothing Then Set DictNewYear CreateObject(“Scripting.Dictionary”) ‘ 將LUNAR_NEW_YEAR_LIST的數(shù)據(jù)加載到字典中… End If Set GetNewYearDict DictNewYear End Function限制計(jì)算范圍在商業(yè)應(yīng)用中日期往往集中在最近幾十年??梢栽诤瘮?shù)開(kāi)始時(shí)判斷如果輸入日期遠(yuǎn)超出業(yè)務(wù)合理范圍如早于1990年直接返回錯(cuò)誤或空值避免無(wú)意義的查找計(jì)算。批量計(jì)算優(yōu)化如果是在VBA宏中循環(huán)調(diào)用此函數(shù)處理整個(gè)列可以考慮重構(gòu)一個(gè)批量處理的子程序一次性讀入所有日期數(shù)組在內(nèi)存中完成所有計(jì)算后再一次性寫(xiě)回工作表這比單元格公式逐個(gè)計(jì)算快得多。6.4 功能擴(kuò)展方向這個(gè)基礎(chǔ)函數(shù)可以衍生出很多實(shí)用變體節(jié)日判斷基于農(nóng)歷日期很容易判斷是否是傳統(tǒng)節(jié)日??梢詫?xiě)一個(gè)配套函數(shù)IsFestival(date, “春節(jié)”)。生肖與干支農(nóng)歷年份對(duì)應(yīng)生肖和干支??梢栽赥oLunar函數(shù)中增加可選參數(shù)使其同時(shí)返回生肖或干支信息如ToLunar(A1, “YYYY-MM-DD”, True)返回“2024-四月初五 龍年”。節(jié)氣計(jì)算雖然節(jié)氣是太陽(yáng)歷概念但常與農(nóng)歷一同使用。可以集成簡(jiǎn)單的節(jié)氣近似計(jì)算或查表功能。逆轉(zhuǎn)換農(nóng)歷轉(zhuǎn)公歷實(shí)現(xiàn)逆向函數(shù)ToGregorian(“2024-四月初五”)這需要另一套查找邏輯但核心數(shù)據(jù)可以復(fù)用。最后我想分享一點(diǎn)個(gè)人體會(huì)。自己動(dòng)手實(shí)現(xiàn)這樣一個(gè)工具最大的收獲不是省下了查日歷的那幾分鐘而是對(duì)一項(xiàng)古老而精密的計(jì)時(shí)系統(tǒng)有了更深刻的理解。當(dāng)你在代碼中精確地復(fù)現(xiàn)出閏月的規(guī)則、大小月的交替時(shí)會(huì)真切地感受到傳統(tǒng)文化與現(xiàn)代技術(shù)的交融。把這個(gè)函數(shù)分享給同事后它成了我們部門(mén)處理相關(guān)數(shù)據(jù)的標(biāo)配工具這種創(chuàng)造價(jià)值并得到認(rèn)可的感覺(jué)遠(yuǎn)比單純完成一個(gè)任務(wù)要好得多。如果你在使用的過(guò)程中想到了更有趣的擴(kuò)展功能不妨試著動(dòng)手改一改代碼這或許會(huì)成為你深入學(xué)習(xí)VBA和算法的一個(gè)絕佳起點(diǎn)。

相關(guān)新聞

Python爬蟲(chóng)與數(shù)據(jù)分析實(shí)戰(zhàn):從零基礎(chǔ)到項(xiàng)目應(yīng)用的全棧學(xué)習(xí)指南

Python爬蟲(chóng)與數(shù)據(jù)分析實(shí)戰(zhàn):從零基礎(chǔ)到項(xiàng)目應(yīng)用的全棧學(xué)習(xí)指南

這次我們來(lái)看一套被B站技術(shù)區(qū)廣泛推薦的Python自學(xué)教程。這套教程號(hào)稱(chēng)“2026最細(xì)”,主打從零基礎(chǔ)到實(shí)戰(zhàn)應(yīng)用,核心覆蓋Python基礎(chǔ)、爬蟲(chóng)和數(shù)據(jù)分析三大模塊。如果你正在尋找一套系統(tǒng)性強(qiáng)、實(shí)戰(zhàn)案例多、能快速上手的Python學(xué)習(xí)資源,這篇文章會(huì)幫…

2026/8/2 13:36:10 閱讀更多
OpenClaw智能體開(kāi)發(fā)實(shí)戰(zhàn):6款核心工具深度評(píng)測(cè)與自動(dòng)化工作流構(gòu)建指南

OpenClaw智能體開(kāi)發(fā)實(shí)戰(zhàn):6款核心工具深度評(píng)測(cè)與自動(dòng)化工作流構(gòu)建指南

1. 項(xiàng)目概述:OpenClaw生態(tài)與“最佳工具榜”的價(jià)值 最近在AI智能體開(kāi)發(fā)圈子里,OpenClaw的熱度持續(xù)攀升,幾乎成了每個(gè)想嘗試AI自動(dòng)化流程的開(kāi)發(fā)者繞不開(kāi)的名字。它本質(zhì)上是一個(gè)開(kāi)源的AI智能體框架,你可以把它理解為一個(gè)“AI大腦”的…

2026/8/2 14:56:17 閱讀更多
UML行為圖實(shí)戰(zhàn):狀態(tài)圖與活動(dòng)圖的核心差異與選型指南

UML行為圖實(shí)戰(zhàn):狀態(tài)圖與活動(dòng)圖的核心差異與選型指南

1. 從“靜態(tài)”到“動(dòng)態(tài)”:為什么我們需要行為圖?在軟件設(shè)計(jì)和系統(tǒng)分析的世界里,我們常常從“靜態(tài)”開(kāi)始。類(lèi)圖、組件圖、部署圖,這些UML圖描繪了系統(tǒng)的骨骼和器官——有哪些類(lèi)、它們?nèi)绾侮P(guān)聯(lián)、系統(tǒng)由哪些部分組成、最終部署在哪里…

2026/8/2 14:56:17 閱讀更多
5大場(chǎng)景重塑你的思維:為什么你需要一個(gè)真正強(qiáng)大的思維導(dǎo)圖工具?

5大場(chǎng)景重塑你的思維:為什么你需要一個(gè)真正強(qiáng)大的思維導(dǎo)圖工具?

5大場(chǎng)景重塑你的思維:為什么你需要一個(gè)真正強(qiáng)大的思維導(dǎo)圖工具? 【免費(fèi)下載鏈接】mind-map SimpleMindMap(思緒思維導(dǎo)圖):一個(gè)強(qiáng)大的思維導(dǎo)圖。A powerful mind map. 項(xiàng)目地址: https://gitcode.com/GitHub_Trending…

2026/8/2 14:56:17 閱讀更多
REBUILD企業(yè)管理系統(tǒng):零代碼搭建企業(yè)級(jí)應(yīng)用的終極指南

REBUILD企業(yè)管理系統(tǒng):零代碼搭建企業(yè)級(jí)應(yīng)用的終極指南

REBUILD企業(yè)管理系統(tǒng):零代碼搭建企業(yè)級(jí)應(yīng)用的終極指南 【免費(fèi)下載鏈接】rebuild 高度可配置化的企業(yè)管理系統(tǒng)!企業(yè)內(nèi)部可免費(fèi)使用!零代碼/低代碼快速搭建企業(yè)中臺(tái)、CRM客戶(hù)關(guān)系管理、WMS庫(kù)存管理、TMS運(yùn)輸管理、SCM供應(yīng)鏈管理、MES/MOM&#…

2026/8/2 14:56:17 閱讀更多
格拉姆角場(chǎng)(GAF)原理與實(shí)戰(zhàn):時(shí)序信號(hào)轉(zhuǎn)圖像用于軸承故障診斷

格拉姆角場(chǎng)(GAF)原理與實(shí)戰(zhàn):時(shí)序信號(hào)轉(zhuǎn)圖像用于軸承故障診斷

1. 項(xiàng)目概述:從時(shí)序信號(hào)到圖像識(shí)別的故障診斷新思路格拉姆角場(chǎng)(Gramian Angular Field, GAF)結(jié)合軸承故障診斷,這個(gè)組合在工業(yè)預(yù)測(cè)性維護(hù)領(lǐng)域已經(jīng)不算新鮮,但對(duì)于剛接觸的同學(xué)來(lái)說(shuō),看到東南大學(xué)…

2026/8/2 14:56:17 閱讀更多
MoneyPrinterPlus實(shí)戰(zhàn)指南:AI視頻批量生成與自動(dòng)化發(fā)布完整解決方案

MoneyPrinterPlus實(shí)戰(zhàn)指南:AI視頻批量生成與自動(dòng)化發(fā)布完整解決方案

MoneyPrinterPlus實(shí)戰(zhàn)指南:AI視頻批量生成與自動(dòng)化發(fā)布完整解決方案 【免費(fèi)下載鏈接】MoneyPrinterPlus AI一鍵批量生成各類(lèi)短視頻,自動(dòng)批量混剪短視頻,自動(dòng)把視頻發(fā)布到抖音,快手,小紅書(shū),視頻號(hào)上,賺錢(qián)從來(lái)沒(méi)有這么容易過(guò)! 支持本地語(yǔ)音模型chatTTS,fasterwhisper,…

2026/8/2 0:04:00 閱讀更多
3分鐘搞定!QQ空間歷史說(shuō)說(shuō)完整備份終極指南

3分鐘搞定!QQ空間歷史說(shuō)說(shuō)完整備份終極指南

3分鐘搞定!QQ空間歷史說(shuō)說(shuō)完整備份終極指南 【免費(fèi)下載鏈接】GetQzonehistory 獲取QQ空間發(fā)布的歷史說(shuō)說(shuō) 項(xiàng)目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你是否曾想過(guò),那些年發(fā)過(guò)的QQ空間說(shuō)說(shuō),那些記錄青春的文字…

2026/8/2 0:04:01 閱讀更多
MoneyPrinterPlus實(shí)戰(zhàn)指南:AI視頻批量生成與自動(dòng)化發(fā)布完整解決方案

MoneyPrinterPlus實(shí)戰(zhàn)指南:AI視頻批量生成與自動(dòng)化發(fā)布完整解決方案

MoneyPrinterPlus實(shí)戰(zhàn)指南:AI視頻批量生成與自動(dòng)化發(fā)布完整解決方案 【免費(fèi)下載鏈接】MoneyPrinterPlus AI一鍵批量生成各類(lèi)短視頻,自動(dòng)批量混剪短視頻,自動(dòng)把視頻發(fā)布到抖音,快手,小紅書(shū),視頻號(hào)上,賺錢(qián)從來(lái)沒(méi)有這么容易過(guò)! 支持本地語(yǔ)音模型chatTTS,fasterwhisper,…

2026/8/2 0:04:00 閱讀更多
3分鐘搞定!QQ空間歷史說(shuō)說(shuō)完整備份終極指南

3分鐘搞定!QQ空間歷史說(shuō)說(shuō)完整備份終極指南

3分鐘搞定!QQ空間歷史說(shuō)說(shuō)完整備份終極指南 【免費(fèi)下載鏈接】GetQzonehistory 獲取QQ空間發(fā)布的歷史說(shuō)說(shuō) 項(xiàng)目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你是否曾想過(guò),那些年發(fā)過(guò)的QQ空間說(shuō)說(shuō),那些記錄青春的文字…

2026/8/2 0:04:01 閱讀更多
AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O 分配 PCB

AMAT 0100-02186 I/O分配PCB板是應(yīng)用材料(Applied Materials)公司生產(chǎn)的一款用于半導(dǎo)體設(shè)備的I/O信號(hào)分配電路板。該型號(hào)(0100-02186)的核心特點(diǎn)如下:專(zhuān)用于Endura等半導(dǎo)體工藝腔室。集成信號(hào)路由與分配功能。連接控制…

2026/8/2 2:51:21 閱讀更多
Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)

Nissei Corp FFMN-32L-10-T0 40AX 三相異步電動(dòng)機(jī)是日本日清(Nissei)品牌的一款工業(yè)用三相異步電機(jī),適用于自動(dòng)化設(shè)備及通用機(jī)械驅(qū)動(dòng)。該型號(hào)(FFMN-32L-10-T0 40AX)的核心特點(diǎn)如下:三相交流異步電動(dòng)機(jī)。額定…

2026/8/2 2:52:49 閱讀更多