python 操作excel用来做考勤报表。

来源:互联网 发布:java同步和异步的区别 编辑:程序博客网 时间:2024/05/31 20:51
这两天帮公司写的一个考勤表报的脚本。


#!c://python25//env python
#-*-coding:utf8-*-
#-*-coding:GB2312-*-
#-*-coding:cp936-*-
#-*-coding:WINDOWS-936-*-


#from win32com.client import Dispatch
import win32com.client
import string

class easyExcel:
    """A utility to make it easier to get at Excel. Remembering
    to save the data is your problem, as is error handling.
    Operates on one workbook at a time."""

    def __init__(self, filename=None):
        self.xlApp = win32com.client.Dispatch('Excel.Application')
        self.d=dict(zip([i for i in range(1,27)],[s for s in string.uppercase]))   #生成一个如{1:'A',..26:'Z'} 的字典
        self.alltimecount={}
        if filename:
            self.filename = filename
            self.xlBook = self.xlApp.Workbooks.Open(filename)
        else:
            self.xlBook = self.xlApp.Workbooks.Add()
            self.filename = filename
        self.maincol1=self.get_string_in_row(1,u'迟到时间')                           #找出 迟到时间的列
        self.maincol2=self.get_string_in_row(1,u'早退时间')                           #找出 早退时间的列
        self.maincol3=self.get_string_in_row(1,u'实际工作时间')                       #找出 实际工作时间的列
        self.maincol4=self.get_string_in_row(1,u'加班时间')                           #找出 加班时间的列
        self.maincol5=self.get_string_in_row(1,u'是否旷工')                           #找出 是否矿工的列

    def save(self, newfilename=None):
        if newfilename:
            self.filename = newfilename
            self.xlBook.SaveAs(newfilename)
        else:
            self.xlBook.Save()

    def close(self):
        self.xlBook.Close(SaveChanges=0)
        del self.xlApp

    def getCell(self, sheet, row, col):
        "Get value of one cell"

        return self.xlBook.Worksheets(sheet).Cells(row, col).Value

    def setCell(self, sheet, row, col, value):
        "set value of one cell"
        self.xlBook.Worksheets(sheet).Cells(row, col).Value = value

    def getRange(self, sheet, row1, col1, row2, col2):
        "return a 2d array (i.e. tuple of tuples)"
        sht = self.xlBook.Worksheets(sheet)
        return sht.Range(sht.Cells(row1, col1), sht.Cells(row2, col2)).Value
    def getsheetname(self,sheet):
        "得到sheet的名字"
        return self.xlBook.Worksheets(sheet).name
    def changsheetname(self,sheet,name):
        "改变sheet的名字"
        self.xlBook.Worksheets(sheet).name=name

    def set_all_bank(self,sheet,row1,col1,row2,col2,value):             #把所有空白格的值设定为None
        row_max=max(row1,row2)
        row_min=min(row1,row2)
        col_max=max(col1,col2)
        col_min=min(col1,col2)
        for r in range(row_min,row_max+1):
            for c in range(col_min,col_max+1):
                if not self.getCell(sheet,r,c):
                    self.setCell(sheet,r,c,value)

    def addsheet(self,name):
        self.xlBook.Worksheets.Add(After='1')
        self.xlBook.ActiveSheet.name=name

    def addPicture(self, sheet, pictureName, Left, Top, Width, Height):
        "Insert a picture in sheet"
        sht = self.xlBook.Worksheets(sheet)
        sht.Shapes.AddPicture(pictureName, 1, 1, Left, Top, Width, Height)
    def getfirstrow(self):
        "得到第一行数据"
        i=1
        num=[]
        while True:
            if xls.getCell(1,1,i):
                num.append(xls.getCell(1,1,i))
            else:
                break
            i+=1
        n=tuple(num)
        return n
    def get_string_in_row(self,row,s):
        "检索当前工作簿中行中想要的数据的列(唯一的),s是unicode,比如 u'时间'"

        i=1
        while True:
            if self.getCell(1,row,i)==s:
                break
            i+=1


        return i

    def cpsheetdata2newsheet(self, sheet, row1, col1, row2, col2,row3,col3,name):
        "拷贝数据到新的sheet"
        sht = self.xlBook.Worksheets(sheet)
        sht.Range(sht.Cells(1,1),sht.Cells(1,15)).Select()
#        sht.Range(sht.Cells(row1,col1),sht.Cells(row2,col2)).Select()#选择范围,似乎没有必要
        sht.Range(sht.Cells(row1,col1),sht.Cells(row2,col2)).Copy()
        self.xlBook.Worksheets.Add(After='1')
        self.xlBook.ActiveSheet.name=name
        self.self.shtnow=self.xlBook.ActiveSheet
        self.self.shtnow.Cells(row3,col3).Select()
        self.self.shtnow.Paste()
    def cpsheetdata2newsheet2(self, sheet, row1, col1, row2, col2,row3,col3,name):
        "拷贝第一行数据到新的sheet的第一行,拷贝其余数据到新的sheet"
        data=self.getfirstrow()
        sht = self.xlBook.Worksheets(sheet)
#       sht.Range(sht.Cells(row1,col1),sht.Cells(row2,col2)).Select() #选择范围,似乎没有必要
        sht.Range(sht.Cells(row1,col1),sht.Cells(row2,col2)).Copy()    #复制范围
        self.xlBook.Worksheets.Add(After='1')
        self.xlBook.ActiveSheet.name=name
        for i in range(len(data)):
            self.setCell(1,1,i+1,data[i])#i的起始值是0,所以要+1.
        self.self.shtnow=self.xlBook.ActiveSheet
        self.self.shtnow.Cells(row3,col3).Select()
        self.self.shtnow.Paste()
    def cpsheetdata2newsheet3(self, sheet, row1, col1, row2, col2,row3,col3,name):
#更多内容,比cpsheetdata2newsheet2,expressions是Excel公式表达式.
#(row1,col1)、(row2,col2)是复制数据的范围。
# (row3,col3)粘贴新的工作薄的起始点
#    expressions:excel的公式表达式
#    name:新工作薄的名字
#    sheet:主工作簿
#   拷贝第一行数据到新的sheet的第一行,拷贝其余数据到新的sheet,单个页面的数据制作(涉及到数据计算)
        data=self.getfirstrow()
        sht = self.xlBook.Worksheets(sheet)
#       sht.Range(sht.Cells(row1,col1),sht.Cells(row2,col2)).Select()           #选择范围,似乎没有必要
        sht.Range(sht.Cells(row1,col1),sht.Cells(row2,col2)).Copy()             #复制范围

        self.xlBook.Worksheets.Add(After='1')                                    #添加新的工作薄
        self.xlBook.ActiveSheet.name=name                                        #新的工作薄的命名

        for i in range(len(data)):
            self.setCell(1,1,i+1,data[i])                                       # i的起始值是0,所以要+1.写入第一行的数值

        self.shtnow=self.xlBook.ActiveSheet                                          #开始执行粘贴操作
        self.shtnow.Cells(row3,col3).Select()
        self.shtnow.Paste()

        self.setCell(1,(row2-row1)+3,1,u'总计时间')                                     #写入 总计时间
        self.setCell(1,(row2-row1)+4,1,u'总次数')                                      #写入 总次数

        rtime3=(row2-row1)+3
        timeexp1='='+'+'.join([self.d[self.maincol1]+str(n) for n in range(2,rtime3)]) # 计算迟到时间公式(记住,从第二行开始算起)
        timeexp2='='+'+'.join([self.d[self.maincol2]+str(n) for n in range(2,rtime3)]) # 总早退时间公式
        timeexp3='='+'+'.join([self.d[self.maincol3]+str(n) for n in range(2,rtime3)]) #总实际工作时间公式
        timeexp4='='+'+'.join([self.d[self.maincol4]+str(n) for n in range(2,rtime3)]) #总加班时间公式 (row2-row1)+2是行数的差


        self.shtnow.Cells(rtime3,self.maincol1).Formula=timeexp1                               #计算总迟到时间,写入excel
        self.shtnow.Cells(rtime3,self.maincol2).Formula=timeexp2                               #计算总早退时间,写入excel
        self.shtnow.Cells(rtime3,self.maincol3).Formula=timeexp3                               #计算总实际工作时间 写入 excel
        self.shtnow.Cells(rtime3,self.maincol4).Formula=timeexp4                               #计算总加班时间 写入 excel

        rtime2=(row2-row1)+2
        countexp1='=COUNTA(%s2:%s%d)'%(self.d[self.maincol1],self.d[self.maincol1],rtime2)       #计算迟到总次数公式
        countexp2='=COUNTA(%s2:%s%d)'%(self.d[self.maincol2],self.d[self.maincol2],rtime2)       #计算早退总次数公式
        countexp3='=COUNTA(%s2:%s%d)'%(self.d[self.maincol3],self.d[self.maincol3],rtime2)       #计算实际总次公式
        countexp4='=COUNTA(%s2:%s%d)'%(self.d[self.maincol4],self.d[self.maincol4],rtime2)       #计算加班总次数公式
        countexp5='=COUNTA(%s2:%s%d)'%(self.d[self.maincol5],self.d[self.maincol5],rtime2)       #计算旷工总次数公式

        rtime4=(row2-row1)+4
        self.shtnow.Cells(rtime4,self.maincol1).Formula=countexp1                               #计算迟到总次数公式,写入
        self.shtnow.Cells(rtime4,self.maincol2).Formula=countexp2
        self.shtnow.Cells(rtime4,self.maincol3).Formula=countexp3
        self.shtnow.Cells(rtime4,self.maincol4).Formula=countexp4
        self.shtnow.Cells(rtime4,self.maincol5).Formula=countexp5

        self.alltimecount[name]=(self.getCell(name,rtime3,self.maincol1),self.getCell(name,rtime3,self.maincol2),\
        self.getCell(name,rtime3,self.maincol3),self.getCell(name,rtime3,self.maincol4),self.getCell(name,rtime4,\
        self.maincol1),self.getCell(name,rtime4,self.maincol2),self.getCell(name,rtime4,self.maincol3),self.getCell\
        (name,rtime4,self.maincol4),self.getCell(name,rtime4,self.maincol5))

    def cpsheetdata(self, sheet, row1, col1, row2, col2,row3,col3):
        "拷贝数据到当前sheet"
        sht = self.xlBook.Worksheets(sheet)
        sht.Range(sht.Cells(row1,col1),sht.Cells(row2,col2)).Select()
        sht.Range(sht.Cells(row1,col1),sht.Cells(row2,col2)).Copy()
        sht.Cells(row3,col3).Select()
        sht.Paste()

    def cpSheet(self, before):
        "copy sheet"
        shts = self.xlBook.Worksheets
        shts(1).Copy(None,shts(1))

#"下面是一些测试代码。"
if __name__ == "__main__":
    xls=easyExcel(r'E:\book\python\t.xls')
    mainsheetname=xls.xlBook.ActiveSheet.name                     #获得当前活动的sheet(起始的总表)
    i=2
    allname=[]
    allnamerow=[]
    department=[]
    tmp=2
    while True:        #得到全部的考勤名单
        if xls.getCell(1,i,1):
            if xls.getCell(1,i,1)!=tmp:
                allnamerow.append(i)                  #增加所有第一列“名字”改变的节点的行数。
                allname.append(xls.getCell(1,i,1))
                department.append(xls.getCell(1,i,15))
            tmp=xls.getCell(1,i,1)
        else:
            allnamerow.append(i)                     #最后有数字的一列
            break
        i+=1
    xls.set_all_bank(1,2,1,i-1,15,None)             #处理所有空白的空格,设定值为None,防止干扰之后的计算
##    print allname
##    print allnamerow

    namedata={}
    for n in range(len(allname)):
        namedata[allname[n]]=(allnamerow[n],allnamerow[n+1]-1,department[n])                       #生成{ 名字:(首行,尾行)}字典
    for name in namedata:
        xls.cpsheetdata2newsheet3(mainsheetname,namedata[name][0],1,namedata[name][1],15,2,1,name) #处理生成 Excel

    print xls.alltimecount


    xls.save()
    xls.close






TO BE CONTINUE。。。。。

空白行不是空值,怎么处理啊,很影响统计的!算出来就是#value

已经解决了!
xls.set_all_bank(1,2,1,i-1,15,None)             #处理所有空白的空格,设定值为None,防止干扰之后的计算