第二套数据的分解思路

第二套数据采用的跟第一套数据不同的方式,相比较而言,第二套数据的记录更详细,但是占据的字节空间也偏大。按照作者原有的思路是这样说的:一共设置24位,其中高位24位设置为备用,始终为0,23-18共6为设置为农历春节偏移同年元旦的天数,17-14共5位设置位闰月记录,如果无闰月则记录为0,13-1位设置位月份大小(含闰月,如果当年无闰月则闰月为0)。

这个数据相对来说更详细,跟第一套数据的区别在于:1)其定义了一个元旦偏移的天数作为当年春节的记录,这样比较第一套利用1900/01/31作为起点来逐月推算的方法而言,这个方法避免了累加或者数据录入失误产生的连锁效应。它按照年份来控制数据的推算,失误率更低;2)它设置了13个月的闰月天数记录,哪怕当年无闰月。这样有一个好处就是数据相对来说独立,它与上下年的数据不存在关联计算。

它的数据格式是三组16进制的数据连接为一个数据,形成6位的16进制来描述当所在年的数据信息。

举例分析:如2000年,它对应的数据是三组数据记录为:0x46,0x06,0x93,那么实际连接后的数据就是0x460693,转换为2进制后的数据为:010001100000011010010011(不足24为补齐24位),其中各位置的数据如下:

24为0,此数据为固定;

23-18为100011,转换为十进制对应的是35,表示当年的春节对应的阳历日期偏移元旦35天,计算可以得出春节对应的日期为:2000/2/5。

17-14为:0000,表示当年无闰月,如果非0,那么转换成十进制后就是对应的月份。

13-1为:0011010010011,对应13个月(含闰月)的大小,这里面有一个数据处理原作者没有将,后来测试后得知。如果当年有闰月,那么从13→1的位置分别时十二月……闰月,同闰月的平月……一月的顺序记录,如果当年无闰月,那么就是从12→1的位置分别为十二月……一月这样的顺序(这种情况下13为的数据无效,一般也就是0),这个时候读取数据需要区别对待

根据这样的方法,同样写出1900到2099年每个月份的描述和对应的天数记录列表,形成农历数据库,以供万年历调用查询,这一步跟第一套的操作没什么两用,区别就是代码中数据的处理不同而已。

读取数据生成月份记录表的代码:

With Range("s3:ae" & x)
.Interior.ColorIndex = xlNone
.ClearContents
End With

For j = 3 To x
    
    
    dayall = 0 '每月总天数
    rydata = Cells(j, "p") '闰月如果存在,则大于0,如果没有则=0
    
    
    If rydata = 0 Then '则表示该月无闰月,直接从第2位写到13位,对应12月到1月的数据
    
        For i = 2 To 13
           If Mid(Cells(j, "q"), i, 1) = 1 Then
               Cells(j, 17 + i) = 30 & "|" & 14 - i
               dayall = dayall + 30
           Else
               Cells(j, 17 + i) = 29 & "|" & 14 - i
               dayall = dayall + 29
           End If
        Next
    
    Else
    
        For i = 1 To 13 - rydata - 1 '先写到闰月后面一个月
                If Mid(Cells(j, "q"), i, 1) = 1 Then
                    Cells(j, 18 + i) = 30 & "|" & 13 - i
                    dayall = dayall + 30
                Else
                    Cells(j, 18 + i) = 29 & "|" & 13 - i
                    dayall = dayall + 29
                End If
        Next
        
        '写闰月
        If Mid(Cells(j, "q"), 13 - rydata, 1) = 1 Then
            Cells(j, 18 + 13 - rydata) = 30 & "|" & rydata & "R"
            dayall = dayall + 30

        Else
            Cells(j, 18 + 13 - rydata) = 29 & "|" & rydata & "R"
            dayall = dayall + 29

        End If
        
            Cells(j, 18 + 13 - rydata).Interior.ColorIndex = 3
            
        '写闰月后面的剩余月
        For i = 13 - rydata + 1 To 13
        
                If Mid(Cells(j, "q"), i, 1) = 1 Then
                Cells(j, 18 + i) = 30 & "|" & 14 - i
                dayall = dayall + 30
                Else
                Cells(j, 18 + i) = 29 & "|" & 14 - i
                dayall = dayall + 29
                End If
        Next
    
    End If

Cells(j, "af") = dayall
        
Next j

至于从月份记录表中查询和获取记录,则跟前面第一套数据的方法一致(前提是表的结构形式一样,修改一些对应列标就可以)



结尾

Excel真是个好东西!