Python自动生成当月上班及加班时间模板表


原由

因为懒,所以每个月底都不想做当月上班及加班表格。
因为懒,所以不想每次做表格都要查日历算周末日期。
因为懒,所以想有人帮我做该表格。
因为懒,所以没有人能帮我,只能自己写代码做。

效果图

在这里插入图片描述

在这里插入图片描述

表格分析

表格标题:固定格式,宋体,14号,加粗
职员信息:固定格式,宋体,12号,加粗
A列:A5开始,当月天数列,宋体,9号
黑边框范围:A列至J列,5行开始,5+月天数+1行结束,宋体,9号
周末行:

  1. 如果星期天为月第一天,直接写入
  2. 如果星期六为月最后一天,直接写入
  3. 逢星期天,合并当前列格子与列前一个格子(例如:B7是星期天,合并B6:B7),写入

代码功能分析

  1. 默认对给定员工名,自动生成当年当月表格
  2. 给定员工名,指定年,月,自动生成指定年月表格

备注:详见代码最后部分,示例代码

代码环境

系统: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()
发布了31 篇原创文章 · 获赞 11 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/MrRight17/article/details/103340658
今日推荐