Python+openpyxl+pandas⼀步实现将Excel表中内容按指定条件筛选分成。。
。
⽂章⽬录
前⾔
应⽤背景:
⼯作需要将表格按某些条件拆分成多个⼯作薄,且⼀个⼯作薄中再按某些条件存放多个⼯作表,且保留格式,例如颜⾊,合并单元格,字体⼤⼩等等,主要⽤于表头的复制时保留格式。
难点:
1.将数据保存到同⼀⼯作薄的不同⼯作表。
2.复制excel表中的某些内容并保留对应的格式。
实现⽬标:完美地模拟“将⼀个总表数据,筛选负责⼈拆分成对应的负责⼈表,且在每⼀个表内分成库存和备货两张⼦表,并对表头进⾏处理”
⼀、将多个dataframe写⼊同⼀个Excel的不同⼯作Sheet
多个dataframe需要写⼊同⼀个excel时,每次使⽤df.to_excel(⽂件名)的形式去写,系统都会重新创建⼀个新的⽂件。也就意味着前⾯的⽂件会被覆盖掉,你得到的只能是最后⼀个df写⼊的结果⽂件
通过创建⼀个ExcelWriter对象,可以解决上⾯的问题
import pandas as pd
writer = pd.ExcelWriter(os.path.wd(),'⾃定义.xlsx'))
<_excel(writer, sheet_name='⾃定义sheet_name')#startcol=**, startrow=**)
<_excel(writer, sheet_name='⾃定义sheet_name')#startcol=**, startrow=**)
<_excel(writer, sheet_name='⾃定义sheet_name')#startcol=**, startrow=**)
...
writer.save()# 写⼊硬盘
#不传sheet_name参数时,默认多个dataframe会写⼊同⼀个xlsx⽂件的同⼀个sheet⾥
#startrow, startcol 不传时默认dataframe在excel⾥在sheet1⾥其实⾏列都是⼀
#需注意,python和excel的索引起始数字不同,如果startrow=2, startcol=4,不是从Excel第⼆⾏第四列开始写,⽽是从Excel第三⾏第五列开始写
#注意⼀定要⽤write.save(),不然⽣成的⽂件是没有对应的内容的
原⽂链接:
⼆、完整地复制粘贴Excel中的某些内容
上⽂中使⽤pandas进⾏数据处理的时候,输出的表格都是不带格式的,甚⾄于在读取存在“合并单元格”的数据的时候,还会出现⼀些难以处理的空值(基于个⼈理解,excel表格中的合并单元格,显⽰的值是取第⼀项的值,其他都只是空值)。
⽽实际⼯作中,领导要求的表格都是要好看的格式以及⼀些表头,颜⾊等等,因此使⽤pandas来对特定的表头格式进⾏完整的复制粘贴。
1.导⼊模块
import easygui as eg
import os
import openpyxl
import copy
python怎么读取excel某一列import pandas as pd
2.将列宽对应
代码如下:
def colwidth(s0, s1):
for i, row in enumerate(s0.iter_cols()):
# i = chr(i+97).upper()
i = convertToTitle(i+1)
lk = s0.column_dimensions[i].width
if lk ==0:
lk =8.38
其中s0是待复制excel表,s1是待粘贴excel表,都是openpyxl的Worksheet对象,即⼯作表对象。
enumerate() 函数⽤于将⼀个可遍历的数据对象(如列表、元组或字符串)组合为⼀个索引序列,同时列出数据和数据下标,⼀般⽤在for循环当中。
openpyxl读取⼀个sheet所有列数据除了⽤cols属性,也可以⽤iter_cols()⽅法,返回值是⽣成器,该⽅法也可以指定读取⾏和列,和iter_rows不同的是他按照列来输出数据。
综上所述,enumerate(s0.iter_cols())⽣成的是⼀个下标对应列的⽣成器,i默认初始等于0,对应的是’A列’,可通过chr()将数字对应转化为字母(⽤于下⽂中column_dimensions的引⽤)。
但是chr()对于⽣成”两位数的字母“即不能⽣成’AA’,⽽实际上的excel表可能会超过’AA’列,就会产⽣等同于’超出索引值’效果的报错,不符合实际需求。
>>>i =0#⽣成器⽣成的列中'A'对应的下标是0
>>>i =chr(i+97).upper()
>>>i
'A'
>>>i =26
>>>a =chr(i+97).upper()
>>>a
'{'
此时可以看到当i超出25(26个字母,因此最后⼀项是25)时,对应⽣成的不是’AA’,⽽是chr()本⾝编码中对应的值。
解决⽅法:
def convertToTitle(n):
# n为添⼊的数值,此时1对应的是'A',0⽆对应,所以在应⽤时,注意赋予的n是否要+1
"""
:type n: int
:rtype: str
"""
rStr =""
while n !=0:
res = n %26
if res ==0:
res =26
n -=26
rStr =chr(ord('A')+ res -1)+ rStr
n = n //26
return rStr
# 返回字母
此时,数字下标就和excel表格中的列⼀⼀对应上了。
3.将⾏宽对应
代码如下:
def rowheight(s0, s1):
for i in range(1, s0.max_row+1):
hg = s0.row_dimensions[i].height
if hg ==0:
hg =15
⾏的序号由纯数字组成,不存在字母与数字转化间的问题,但在使⽤range的时候注意与实际⾏数的对应关系。
4.复制粘贴单元格内容
def copycell(s0, s1, min_row=None, max_row=None, min_col=None, max_col=None):
for i, row in enumerate(s0.iter_rows(min_row=min_row, max_row=max_row, min_col=min_col, max_col=max_col)):
for j, cell in enumerate(row):
其中,i代表第⼏列,row代表这⼀列下的所有单元格cell对象组成元组。通过enumerate(),将row中的所有单元格及其对应的⾏号列出。iter_rows()和iter_cols()的参数都有(min_row=None, max_row=None, min_col=None, max_col=None),因此可以通过参数设置来圈定我们想要复制粘贴的区域,例如,我想复制前两⾏,那我就将max_row=2,以此来达成表头的复制粘贴的效果。
5.完整代码
import easygui as eg
import os
import openpyxl
import copy
import pandas as pd
# ⽤于数字与excel列字母之间的转换
def convertToTitle(n):
"""
:type n: int
:rtype: str
"""
rStr =""
while n !=0:
res = n %26
if res ==0:
res =26
n -=26
rStr =chr(ord('A')+ res -1)+ rStr
n = n //26
return rStr
# 复制列宽
def colwidth(s0, s1):
for k, co in enumerate(s0.iter_cols()):
k = convertToTitle(k+1)
lk = s0.column_dimensions[k].width
if lk ==0:
lk =8.38
# 复制⾏宽
def rowheight(s0, s1):
for i in range(1, s0.max_row+1):
hg = s0.row_dimensions[i].height
if hg ==0:
hg =15
# 复制单元格
def copycell(s0, s1, min_row=None, max_row=None, min_col=None, max_col=None):
for i, row in enumerate(s0.iter_rows(min_row=min_row, max_row=max_row, min_col=min_col, max_col=max_col)): for j, cell in enumerate(row):
# 执⾏复制
def copyfile(sht, sht1):
colwidth(sht, sht1)
rowheight(sht, sht1)
copycell(sht, sht1)
for merg d_cells:
<_cells(str(merg))
# 进⾏数据处理后复制表头
def screen_data(fn):
df = pd.read_excel(fn, header=1)
g = os.path.dirname(fn)
# 把要复制的表头和要处理的表格放在同⼀个⽬录内
header_file = os.path.join(g,'产品总表_表头.xlsx')
wb = openpyxl.load_workbook(header_file)
name_list =list(df['负责⼈'].drop_duplicates('first'))
for name in name_list:
file_name = os.path.join(g, name +'库存及备货表.xlsx')
writer = pd.ExcelWriter(file_name)
# 进⾏数据处理,⽣成对应的表
for sheet_name in wb.sheetnames:
header_df = pd.read_excel(header_file, header=1, sheet_name=sheet_name)
header = lumns
mid_df = pd.DataFrame(df[df['负责⼈']== name], columns=header)
_excel(writer, sheet_name=sheet_name, index=False, startrow=1)
# ⼀定要先保存并且关闭,否则⽆法⽣成有效的excel表
writer.save()
writer.close()
# 进⾏对应⼯作薄的各个⼯作表的表头的复制
for sheet_name in wb.sheetnames:
ws = wb[sheet_name]
wb1 = openpyxl.load_workbook(file_name)
ws1 = wb1[sheet_name]
copyfile(ws, ws1)
wb1.save(file_name)
if __name__ =='__main__':
ff = eg.fileopenbox('选择⽂件','选择⽂件')
screen_data(ff)
三、总结
本博⽂在解决“python 如何将多个DataFrame保存到不同⼯作表”,“python 如何复制粘贴excel表中的格式到另⼀个excel表” 这类的问题时应该都能提供些帮助,或者是直接可套⽤(伸⼿党)的代码。因为在长期的⾃学⾃⽤的过程中,知道了百度的重要性,更知道了上⽹资料时的⼼态(能直接套⽤就最好了),⼤多数时候都不需要了解原理,只需要解决当前问题即可,因此对于关键的功能点都有单独拎出描述,望能帮助读者解决问题。
本⼈⾮专业的IT⼯作⼈员,各类参数调整与⾃⾝实际⼯作时的应⽤问题,可在评论中提出,⼀起讨论解决,但我不⼀定能解决,请见谅。
这是第⼀次写⼀篇正式的博⽂,如有不⾜之处,可指出改正,谢谢。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论