这两天帮公司写的一个考勤表报的脚本。
#!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,防止干扰之后的计算