广东的太阳还是那么大,隔着玻璃都能感受到热浪。
明明前不久才立夏(明明已经过去三个月!!)
时间跑,日程赶。
昨日又迎来了立秋,正在放暑假的童靴是不是有点忘记时间了呢~
什么?真的忘记了?没关系,今日小编为大家带来一款由Excel简易DIY的小日历
给自己10分钟(滑稽),python回你一个智慧与美貌并存的备忘小神器 相信它会给你带来不少方便(滑稽)
一、环境说明
开始之前,当然要跟小伙伴们交代一下运行环境咯
我们使用的python版本为 Python3.6,需要使用到的包为 openpyxl 及calendar,后者是python自带的,而前者则需要小伙伴们打开Cmd/Terminal,运行以下指令安装,如果你还没有安装python,请看这篇文章:
pip install openpyxl
安装完成后我们就可以正式开始啦!
二、代码说明
我们会给大家先讲解一些细节的东西,等大家都理解明白了原理,最后会献上完整的源代码~
1. 首先,绘制一份日历,我们得先知道每个月份有多少天,每天都是星期几,我们使用calendar包获得这些信息:
calendar.monthcalendar(2019, i)
通过这个函数,我们能得到 2019年i月的日历,它类似一个j*k的矩阵,因此我们可以这样遍历得到每一个日期:
for j in range(len(calendar.monthcalendar(2019, i))): for k in range(len(calendar.monthcalendar(2019, i)[j])): value = calendar.monthcalendar(2019, i)[j][k]
2. 其次,我们怎么样绘制得到日历呢?
openpyxl包给予了我们答案,最方便的做法是我们先将日历绘制到Excel中,然后再从Excel中提取图片出来。openpyxl怎么用?给大家一个设置单元格字体的例子:
sheet.cell(row=j + 4 + count, column=k + 2).font = Font(u'微软雅黑', color=text_color , size=14)
sheet是对应的表格,row和column就是某个单元格的位置,然后对font属性进行设置,调用Font类并设置参数,如果大家不知道Font类有什么参数,可以参考openpyxl官方文档:https://openpyxl.readthedocs.io/en/stable/,你可以看到里面大部分单元格的属性都是这样设置的,非常简单。
3. 我们的作品是每个月份都有一个图在旁边做装饰,其添加方法如下:
imgs = ['12/1.jpg','12/2.jpg','12/3.jpg','12/4.jpg','12/5.jpg','12/6.jpg','12/7.jpg','12/8.jpg','12/9.jpg','12/10.jpg','12/11.jpg','12/12.jpg'] img = Image(imgs[i-1]) sheet.add_image(img, 'J2')
imgs是每个图的相对路径,如12/1.jpg 是名字为12的文件夹下的1.jpg. 图像路径要导入到openpyxl的Image对象中: img=Image(’12/1.jpg’),然后将该变量放置到某个单元格上:sheet.add_image(img, ‘J2).
这样看你可能会有点糊涂, i-1是哪里来的?sheet是哪里来的?没关系,其实是因为讲解的时候只能给大家献上部分代码,看完下面的完整代码你们就懂啦:
from openpyxl.styles import Alignment, PatternFill, Font, Border, Side from openpyxl.utils import get_column_letter from openpyxl.drawing.image import Image import openpyxl import calendar def set_information(date, text): t = {} t['month'] = date.split('-')[1] t['day'] = date.split('-')[2] t['text'] = text flex_text.append(t) def set_month_value(i, sheet, border_color, text_color, color_one, color_two): # i: 月份 # sheet: 该月份的excel # border_color: 边框颜色 count = 0 # render_color 用来设定单元格背景色,交替进行 render_color_1 = 1 render_color_2 = 0 for j in range(len(calendar.monthcalendar(2019, i))): for k in range(len(calendar.monthcalendar(2019, i)[j])): value = calendar.monthcalendar(2019, i)[j][k] # 将0值变为空值 bd = Border(right=Side(color=border_color, style='thick'), top=Side(color=border_color, style='thick'), left=Side(color=border_color, style='thick')) right_bd = Border(right=Side(color=border_color, style='thick'), left=Side(color=border_color, style='thick'), bottom=Side(color=border_color, style='thick')) if value == 0: value = '' sheet.cell(row=j + 4 + count, column=k + 2).value = value sheet.cell(row=j + 4 + count, column=k + 2).border = bd sheet.cell(row=j + 5 + count, column=k + 2).border = right_bd else: sheet.cell(row=j + 4 + count, column=k + 2).value = value sheet.cell(row=j + 4 + count, column=k + 2).border = bd sheet.cell(row=j + 4 + count, column=k + 2).font = Font(u'微软雅黑', color=text_color , size=14) sheet.cell(row=j + 5 + count, column=k + 2).border = right_bd # 单元格文字设置,右对齐,垂直居中 if render_color_1 > render_color_2: sheet.cell(row=j + 4 + count, column=k + 2).fill = PatternFill("solid", fgColor=color_one) sheet.cell(row=j + 5 + count, column=k + 2).fill = PatternFill("solid", fgColor=color_one) render_color_2 += 1 else: sheet.cell(row=j + 4 + count, column=k + 2).fill = PatternFill("solid", fgColor=color_two) sheet.cell(row=j + 5 + count, column=k + 2).fill = PatternFill("solid", fgColor=color_two) render_color_1 += 1 # 提取当天所有事件 text = '' for t in flex_text: if int(t['day']) == value and int(t['month']) == i: print(t) text = text + t['text']+'\n' # 设置事件信息 if text != '': sheet.cell(row=j + 5 + count, column=k + 2).value = text sheet.cell(row=j + 5 + count, column=k + 2).font = Font(u'宋体',color=text_color, size=13) align = Alignment(horizontal='right', vertical='center', wrapText=True) # wrapText 设置单元格可包含多行字符 sheet.cell(row=j + 5 + count, column=k + 2).alignment = align count += 1 def set_week_line(sheet, border_color, workday_color, otherday_color, text_color): # 设置星期栏 align = Alignment(horizontal='center', vertical='center') days = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'] bd_day = Border(right=Side(color=border_color, style='thick'), top=Side(color=border_color, style='thick'), left=Side(color=border_color, style='thick')) num = 0 # 单元格填充色属性设置 for day in range(2, 9): sheet.cell(row=3, column=day).value = days[num] sheet.cell(row=3, column=day).alignment = align sheet.cell(row=3, column=day).border = bd_day sheet.cell(row=3, column=day).font = Font(u'微软雅黑', color=text_color, bold=True , size=12) # 设置列宽12 c_char = get_column_letter(day) sheet.column_dimensions[get_column_letter(day)].width = 12 # 行高27 sheet.row_dimensions[day].height = 27 num += 1 if day == 2 or day == 8: for r in range(3, 14): sheet.cell(row=r, column=day).fill = PatternFill("solid", fgColor=otherday_color) else: sheet.cell(row=3, column=day).fill = PatternFill("solid", fgColor=workday_color) def set_month_year(i, sheet, year_color, month_color): # 添加年份及月份 sheet.cell(row=2, column=8).value = '2019' sheet.cell(row=2, column=8).font = Font(u'微软雅黑', size=30, color=year_color) sheet.cell(row=2, column=2).value = str(i) + '月' sheet.cell(row=2, column=2).font = Font(u'微软雅黑', size=25, color=month_color) sheet.row_dimensions[2].height = 35 def get_month_xlsx(wb, imgs, flex_text): for i in range(1, 13): sheet = wb.create_sheet(index=0, title=str(i) + '月') # 添加工作表 text_color = '000000' # 日历文字颜色 text_color_week = '000000' # 星期栏文字颜色 BorderCorlor = 'B7E0E8' # 边框颜色 backgroundColor = 'FFFFFF' # 背景颜色 workday_color = 'CBEEEE' # 工作日背景颜色 otherday_color = '7FD4D2' # 其他日背景颜色 year_color = '000000' # 年份颜色 month_color = '000000' # 月份颜色 s_color = 'CBEEEE' # 单数颜色 d_color = 'A5E1E0' # 双数颜色 # 单元格的背景色 for k1 in range(1, 15): for k2 in range(1, 16): sheet.cell(row=k1, column=k2).fill = PatternFill("solid", fgColor=backgroundColor) set_month_value(i, sheet, BorderCorlor, text_color, s_color, d_color) # 设定月份的值,参数:月份, 表, 边框颜色 set_week_line(sheet, BorderCorlor, workday_color, otherday_color, text_color_week) # 设定星期栏 set_month_year(i, sheet, year_color, month_color) # 设定年份和月份的格式 # 设置日历主体行高 for row in range(3, 19): if row % 2 == 0 or row == 3: sheet.row_dimensions[row].height = 28 else: sheet.row_dimensions[row].height = 56 # 合并单元格 sheet.merge_cells('I1:P14') # 添加图片 img = Image(imgs[i-1]) sheet.add_image(img, 'J2') # 添加二维码 img = Image('2.png') sheet.add_image(img, 'O2') calendar.setfirstweekday(firstweekday=6) wb = openpyxl.Workbook() flex_text = [] imgs = ['12/1.jpg','12/2.jpg','12/3.jpg','12/4.jpg','12/5.jpg','12/6.jpg','12/7.jpg','12/8.jpg','12/9.jpg','12/10.jpg','12/11.jpg','12/12.jpg'] # 每个月的图片 set_information('2019-12-1', '考试') set_information('2019-12-1', '约会') # 需要添加的信息 get_month_xlsx(wb, imgs, flex_text) # 得到文档 wb.save('my_calendary.xlsx') # 保存文档
4. 我们还有一个神秘功能
差点忘了告诉大家了,我们的日历能支持备注哦,在调用get_month_xlsx得到文档前,通过set_information()放入你某一天想做的事情即可。如:
set_information('2019-12-5', '面试')
三、运行代码
终于到了激动人心的运行代码部分了,运行这份代码,你只需要把你想要的图片变量名改一下即可,即imgs. 然后在本地cmd/terminal运行:
python 这份代码的文件名(滑稽.py
会自动生成一个Excel表格叫my_calendary.xlsx. 怎样从里面把日历提取成图片呢?很简单,复制拉取你想要的部分,粘贴到聊天窗口就能变成一个图片!这里给大家献上源代码里的12张图,希望大家喜欢!
根据大家的喜好,大家可以自己设置背景色、边框色、交替色和图片,还有把这个讨厌的好看的二维码去掉。如果有阅读完注释还是不懂的地方,欢迎在下方留言区讨论,我们会抽空回答的~
Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典
评论(2)
可以设置法定节假日么?
可以自己搜集法定节假日,标记在上面