加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

使用Excel数组函数制作日历

(2011-03-23 16:23:53)
标签:

excel

数组公式

制作日历

时间日期函数

分类: Excel
参照John Walkenbach书中的方法,制作了一个日历,效果如下:
http://s14/middle/70fa8d2a49f21312d350d&690

 

这个日历可以实现从1900年开始至9999年的日期的显示,实现方法主要是基于时间日期函数和数组公式的应用。

现对实现过程解释如下:

第一步、首先定义如下几个名称

1.MonthNames:{January,Febury,March,April,May,June,July,August,September,October,November,December}

用于月份下拉列表中的序列。

2.TheMonth:记录所选择的月份。

3.TheYear:记录所选择的年份。

4.week:{0;1;2;3;4;5}注意这里的数组常量中由分号分隔,这是一个六维的数组,之所以是六个,是因为一个月中最多横跨六个周。

5.weekday:{0,1,2,3,4,5,6}注意此处的数组常量由逗号分隔,这是一个一维的七元数组,表示一周的七天(更确切的讲是七天的位置)。

6.StartDate:表示在选定的年份、选定的月份条件下,该月第一天。即=DATE("TheYear","TheMonth",1),使用这个值是为了之后区分是否是本月的数据方便。

7.StartDow:表示StartDate在一个星期中的位置,即在weekday中的某一个数组。即公式:=WEEKDAY("StartDay")-1。此处WEEKDAYEXCEL中的一个时间日期函数,返回参数代表日期的星期数,在本文中的格式下,按照SunSta的顺序依次显示1-7。因此,StartDow的取值为0-6,刚好与weekday(数组常量)中的数值相一致。

 

第二步、分析

可以确定,一个月中最大是星期跨度为6,因此每月的日期必然能够放在一个6*7的区域内,在本文中即为"C6:I11"。下面我们要解决的是如下两个问题:
问题1:如何得到该6*7区域中每一天的日期。

问题2:如何区分出该区域中哪些是在本月的,哪些不是在本月的,不在本月份的应不予显示。

 

第三步、实现:

1.问题1的解决:

我们可以利用两个数组常量week={0;1;2;3;4;5}weekday={0,1,2,3,4,5,6}进行数组公式运算、借助StartDateStartDow、使用其他时间日期函数来实现,具体方法为

选定单元格区域"C6:I11",输入公式“=StartDate-StartDow+week*7+Weekday -1,并按下“Ctrl+Shift+Enter”组合键,输入此数组公式。结果如下:(以2011/03月为例)

40601

40602

40603

40604

40605

40606

40607

40608

40609

40610

40611

40612

40613

40614

40615

40616

40617

40618

40619

40620

40621

40622

40623

40624

40625

40626

40627

40628

40629

40630

40631

40632

40633

40634

40635

40636

40637

40638

40639

40640

40641

40642

 

其中week*7+weekday-1会得到如下二位数组:

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

 

-StartDow+week*7+weekday-1则表示每一天相对于本月第一天(用StartDate表示)的相对距离,结果如下

-2

-1

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

 

所以StartDate-StartDow+week*7+Weekday-1就可以得到这个表格中的每一个单元格中代表的日期的真实日期值。如果我们把这个单元格的格式调成日期时间格式,结果如下:

 

2011-2-27

2011-2-28

2011-3-1

2011-3-2

2011-3-3

2011-3-4

2011-3-5

2011-3-6

2011-3-7

2011-3-8

2011-3-9

2011-3-10

2011-3-11

2011-3-12

2011-3-13

2011-3-14

2011-3-15

2011-3-16

2011-3-17

2011-3-18

2011-3-19

2011-3-20

2011-3-21

2011-3-22

2011-3-23

2011-3-24

2011-3-25

2011-3-26

2011-3-27

2011-3-28

2011-3-29

2011-3-30

2011-3-31

2011-4-1

2011-4-2

2011-4-3

2011-4-4

2011-4-5

2011-4-6

2011-4-7

2011-4-8

2011-4-9

 

至此,问题1已经得到了解决,我们得到了这个6*7的单元格

 

2.问题2的解决。

我们使用If函数和Month函数的混合搭配即可过滤掉非当前月份的数据,具体如下:

选定该单元格区域,输入如下公式

=IF(MONTH(StartDate-StartDow+week*7+Weekday-1)<>TheMonth,"",DAY(StartDate-StartDow+week*7+Weekday-1))”,按下“Ctrl+Shift+Enter”组合键。

该公式通过判断每一个单元格区域代表日期所在的月份值与所选定的月份值是否相等,如不相等,则不显示任何数据,如相等,也就是确实是选定月份的日期数据,则显示出该日期的日数(有DAY函数给出)。注意,这样需将该区域的单元格格式调为“数值”或“常规”,而不能是“时间日期”。

 

 

 

 

PS:

1.至此,整个工作完成,但是自己“一日一贴”的豪言壮语也被自己给破灭掉了。http://www/uc/myshow/blog/misc/gif/E___6695EN00SIGG.gif

2.此文还有如下修改方向,留待以后完善吧:

  (1)修改成中国人更习惯的“周一至周日”的格式,而不是本文中的Sun-Sta格式;

  (2)使用VBA代码实现相同的功能。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有