原由
因为懒,所以每个月底都不想做当月上班及加班表格。
因为懒,所以不想每次做表格都要查日历算周末日期。
因为懒,所以想有人帮我做该表格。
因为懒,所以没有人能帮我,只能自己写代码做。
效果图
表格分析
表格标题:固定格式,宋体,14号,加粗
职员信息:固定格式,宋体,12号,加粗
A列:A5开始,当月天数列,宋体,9号
黑边框范围:A列至J列,5行开始,5+月天数+1行结束,宋体,9号
周末行:
- 如果星期天为月第一天,直接写入
- 如果星期六为月最后一天,直接写入
- 逢星期天,合并当前列格子与列前一个格子(例如:B7是星期天,合并B6:B7),写入
代码功能分析
- 默认对给定员工名,自动生成当年当月表格
- 给定员工名,指定年,月,自动生成指定年月表格
备注:详见代码最后部分,示例代码
代码环境
系统:Windows
软件:需要安装office excel(最好版本新一些,要能支持xlsx格式)
语言环境:python2.7
- 需要包:win32com.client
备注:所需包使用pip install pywin32安装
代码
# -*- coding: UTF-8 -*-
# 生成当月上班及加班时间表
# by Yone 2019/12/1
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import win32com.client
import os
import datetime
import calendar
def getScriptPath():
return os.path.split(os.path.realpath(__file__))[0]
class Date(object):
def __init__(self, year=None, month=None):
if year == None: year = datetime.datetime.now().year
if month == None: month = datetime.datetime.now().month
self.__year = year
self.__month = month
def getYear(self):
return self.__year
def getMonth(self):
return self.__month
def getMonthRange(self):
calendar.setfirstweekday(firstweekday=6)
# eg. return value: (6, 31) 6为当月第一天,星期天(0为星期一);31为当月天数
return calendar.monthrange(self.getYear(), self.getMonth())
class ExcelApp(object):
def __init__(self, filePath):
self.__filePath = getScriptPath() + "\\" + filePath.encode('gb2312')
self.__app = win32com.client.DispatchEx('Excel.Application')
self.__workbook = self.__app.WorkBooks.Add()
self.__sheet = self.__workbook.ActiveSheet
def getFilePath(self):
return self.__filePath
def getSheet(self):
return self.__sheet
def saveAndQuit(self):
self.__workbook.SaveAs(self.__filePath)
self.__workbook.Close()
self.__app.Quit()
class Table(object):
def __init__(self, employee, year=None, month=None):
self.__date = Date(year, month)
self.__filename = '%d年上班及加班时间表.xlsx' % (self.__date.getYear())
self.__app = ExcelApp(self.__filename)
self.sheet = self.__app.getSheet()
self.__header = '%d年%d月加班申请表' % (self.__date.getYear(), self.__date.getMonth())
self.__employee = '职员:%s' % (employee)
self.__metadata = {
'A1:J1': self.__header,
'H2': self.__employee,
'A3:A4': '',
'B3': '考勤',
'B4': '时间',
'C3:C4': '加班内容',
'D3:D4': 'AM',
'E3:E4': 'PM',
'F3:F4': '批准',
'G3': '加班',
'G4': '时间',
'H3:J3': '累计时间',
'H4': '正常',
'I4': '周末',
'J4': '法定假日'
}
self.__auto_start_metadata = 'A5'
def __writeMetaData(self):
for key in self.__metadata:
if ':' in key:
self.sheet.Range(key).Merge()
self.sheet.Range(key).Value = self.__metadata[key].encode('gb2312')
self.sheet.Range(key).Font.Name = "宋体".encode('gb2312')
self.sheet.Range(key).Font.Size = 9
self.sheet.Range('A1:J1').Font.Name = "宋体".encode('gb2312')
self.sheet.Range('A1:J1').Font.Size = 14
self.sheet.Range('A1:J1').Font.Bold = True
self.sheet.Range('H2').Font.Name = "宋体".encode('gb2312')
self.sheet.Range('H2').Font.Size = 12
self.sheet.Range('H2').Font.Bold = True
def __deleteSameNameFile(self):
if os.path.exists(self.__app.getFilePath()):
os.remove(self.__app.getFilePath())
def __writeDays(self):
weekDay, days = self.__date.getMonthRange()
cell1 = self.__auto_start_metadata[0:1]
cell2 = self.__auto_start_metadata[1:2]
for day in range(1, days + 1):
self.sheet.Range(cell1 + cell2).Value = day
cell2 = str(int(cell2) + 1)
def __writeWeekday(self):
weekDay, days = self.__date.getMonthRange()
cell1 = self.__auto_start_metadata[0:1]
cell2 = self.__auto_start_metadata[1:2]
week = weekDay
cell1 = chr(ord(cell1) + 1)
for day in range(1, days + 1):
if weekDay == 6 and day == 1:
# B5 = 周末
self.sheet.Range(cell1 + cell2).Value = '周末'.encode('gb2312')
self.sheet.Range(cell1 + cell2 + ':' + 'J' + cell2).Interior.Color = self.RGB(191, 191, 191)
elif weekDay == 6:
# B6:B7 = 周末
self.sheet.Range(cell1 + str(int(cell2) - 1) + ':' + cell1 + cell2).Merge()
self.sheet.Range(cell1 + str(int(cell2) - 1) + ':' + cell1 + cell2).Value = '周末'.encode('gb2312')
self.sheet.Range(cell1 + str(int(cell2) - 1) + ':' + 'J' + cell2).Interior.Color = self.RGB(191, 191, 191)
# Worksheets("Sheet1").Range("A1").Interior.ColorIndex = 8 ' Cyan
# objExcelSheet.cells(row,column).Interior.color = RGB(255,0,0)
elif weekDay == 5 and day == days:
self.sheet.Range(cell1 + cell2).Value = '周末'.encode('gb2312')
self.sheet.Range(cell1 + cell2 + ':' + 'J' + cell2).Interior.Color = self.RGB(191, 191, 191)
if weekDay == 6:
weekDay = 0
else:
weekDay += 1
cell2 = str(int(cell2) + 1)
def RGB(self, R, G, B):
return (65536 * R) + (256 * G) + (B)
def __writeFinal(self):
weekDay, days = self.__date.getMonthRange()
cell2 = self.__auto_start_metadata[1:2]
finalCell2 = str(days + int(cell2))
merge = lambda c1,c2 : self.sheet.Range(c1 + finalCell2 + ':' + c2 + finalCell2).Merge()
merge('A', 'C')
self.sheet.Range('D' + finalCell2).Value = '统计人'.encode('gb2312')
merge('E', 'F')
self.sheet.Range('G' + finalCell2).Value = '小计'.encode('gb2312')
def __formatCell(self):
weekDay, days = self.__date.getMonthRange()
A = ord('A')
J = ord('J')
cell2 = self.__auto_start_metadata[1:2]
finalCell2 = str(days + int(cell2))
# https://docs.microsoft.com/zh-cn/office/vba/api/excel.xlhalign
xlHAlignCenter = -4108
self.sheet.Range('A1:J' + finalCell2).HorizontalAlignment = xlHAlignCenter
# https://docs.microsoft.com/zh-cn/office/vba/api/excel.xlbordersindex
XlBordersIndex = {
'xlDiagonalDown':5,
'xlDiagonalUp':6,
'xlEdgeBottom':9,
'xlEdgeLeft':7,
'xlEdgeRight':10,
'xlEdgeTop':8,
'xlInsideHorizontal':12,
'xlInsideVertical':11
}
# https://docs.microsoft.com/zh-cn/office/vba/api/excel.xllinestyle
XlLineStyle = {
'xlContinuous': 1,
'xlDash': -4115,
'xlDashDot': 4,
'xlDashDotDot': 5,
'xlDot': -4118,
'xlDouble': -4119,
'xlLineStyleNone': -4142,
'xlSlantDashDot': 13
}
# https://docs.microsoft.com/zh-cn/office/vba/api/excel.xlborderweight
XlBorderWeight = {
'xlHairline': 1,
'xlMedium': -4138,
'xlThick': 4,
'xlThin': 2
}
getIndex = lambda index : self.sheet.Range('A3:J' + finalCell2).Borders(XlBordersIndex[index])
getIndex('xlEdgeLeft').LineStyle = XlLineStyle['xlContinuous']
getIndex('xlEdgeLeft').Weight = XlBorderWeight['xlThin']
getIndex('xlEdgeTop').LineStyle = XlLineStyle['xlContinuous']
getIndex('xlEdgeTop').Weight = XlBorderWeight['xlThin']
getIndex('xlEdgeBottom').LineStyle = XlLineStyle['xlContinuous']
getIndex('xlEdgeBottom').Weight = XlBorderWeight['xlThin']
getIndex('xlEdgeRight').LineStyle = XlLineStyle['xlContinuous']
getIndex('xlEdgeRight').Weight = XlBorderWeight['xlThin']
getIndex('xlInsideVertical').LineStyle = XlLineStyle['xlContinuous']
getIndex('xlInsideVertical').Weight = XlBorderWeight['xlThin']
getIndex('xlInsideHorizontal').LineStyle = XlLineStyle['xlContinuous']
getIndex('xlInsideHorizontal').Weight = XlBorderWeight['xlThin']
self.sheet.Range('A3:J' + finalCell2).Font.Name = "宋体".encode('gb2312')
self.sheet.Range('A3:J' + finalCell2).Font.Size = 9
def createMetaDataTable(self):
self.__deleteSameNameFile()
self.__writeMetaData()
self.__writeDays()
self.__writeWeekday()
self.__writeFinal()
self.__formatCell()
def save(self):
self.__app.saveAndQuit()
def test(self):
print self.__filename.encode('gb2312')
print self.__header.encode('gb2312')
print self.__date.getYear()
print self.__date.getMonth()
print self.__date.getMonthRange()
if __name__ == "__main__":
# 以下二选一即可:名字,生成表格的年(不填,默认为当年),生成表格的月份(不填,默认为当月)
# table = Table('小明', 2019, 11)
table = Table('小明')
table.test()
table.createMetaDataTable()
table.save()