超简单的⽅法完整保留原有所有样式拆分Excel表
本⽂⽬录:
⽂章⽬录
透过本⽂你能够学到:
1. 通过VBA复制粘贴全部样式进⾏单⽂件表拆分
2. 纯Pandas拆分表,⽆样式保留
3. openpyxl模板法拆分表保留表头样式
作者:⼩⼩明,⾼阶数据处理玩家,帮助各⾏数据从业者解决各类数据处理难题。
需求描述
有⼀个Excel表格:
我们希望将其按照指定的字段拆分为多个表格。如果直接⽤pandas,代码很简单却只能保留数据;如果使⽤openpyxl,也⽆法直接设置原有的样式,需要逐个设置会⾮常⿇烦。下⾯我将使⽤Excel⾃带的筛选功能,筛选出指定的值,然后复制粘贴到⼀张新的⼯作表中。唯⼀值不多的时候我们⼈⼯操作也可以,但数据量⼤唯⼀值多的时候,⼈⼯操作就耗时很久了。
如何使⽤Python实现这个⾃动化操作呢?那就是通过pywin32调⽤VBA。
下⾯我们开始操作吧:
实现过程
⾸先,⽤pywin32打开⽬标⽂件:
import win32com.client as win32 # 导⼊模块
import os
excel_app = ache.EnsureDispatch('Excel.Application')
filename ="数据源.xlsx"
filename = os.path.abspath(filename)
wb = excel_app.Workbooks.Open(filename)
sheet = wb.ActiveSheet
max_rows = sheet.UsedRange.Rows.Count
max_cols = sheet.UsedRange.Columns.Count
max_rows, max_cols
(3216, 9)
可以看到源数据有3216⾏,9列。
获取数据范围,并设置⾃动列宽调整:
rng = sheet.Range(sheet.Cells(1,1), sheet.Cells(max_rows, max_cols))
# 设置⾃动列宽
rng.EntireColumn.AutoFit()
设置后的效果:
构建⼀个拆分函数:
def split_excel(num):
"""num⽰被拆分的列号"""
names =set(sheet.Range(sheet.Cells(2, num), sheet.Cells(max_rows, num)).Value)
# 禁⽤⾃动更新加快执⾏速度
excel_app.ScreenUpdating =False
for name,in names:
sheet.Activate()
rng.AutoFilter(Field=num, Criteria1=name)
rng.Select()
excel_app.Selection.Copy()
new_sheet = excel_app.Sheets.Add(After=wb.Worksheets(wb.Worksheets.Count))
new_sheet.Name = name
new_sheet.Range("A1").Activate()
new_sheet.Paste()
new_sheet.Range(new_sheet.Cells(1,1), new_sheet.Cells(1, max_cols)).EntireColumn.AutoFit() # 恢复⾃动更新
excel_app.ScreenUpdating =True
该函数涉及的⽅法很多,需要反复查询VBA⽂档并测试才能写出,不过前⼈栽树后⼈乘凉,我已经为⼤家写出来啦,可以直接使⽤。当然也欢迎VBA⼤佬对本⽅法进⾏升级改造。
⼀些重点的API:
其他需要注意的点:
excel最强教科书完全版pdf但我们再Python环境中使⽤VBA,则⽆需使⽤VBA的数组或字典对象,使⽤python本⾝的对象操作即可。
下⾯我们对区域列(第2列)进⾏拆分:
split_excel(2)
可以看到拆分的结果,完全保留了原有的样式。
最后我们保存⽂件即可:
wb.SaveAs(os.path.abspath("result.xlsx"))
直接修改原有⽂件直接调⽤wb.Save()即可,上述命令表⽰另存为。
可以关闭⼯作簿:
wb.Close()
还可以关闭Excel软件:
excel_app.Quit()
纯VBA实现
为了没有安装python的童鞋使⽤⽅便,将以上过程封装成纯vba代码,可以直接在Excel软件中使⽤:
Sub 带格式分列()
Application.ScreenUpdating = False
Set Sh = ActiveSheet
max_rows = Sh.UsedRange.Rows.Count
max_cols = Sh.UsedRange.Columns.Count
Set Rng = Sh.Range(Sh.Cells(1, 1), Sh.Cells(max_rows, max_cols))
Rng.EntireColumn.AutoFit
'Col为要⼿动输⼊要拆分的列序数
Col = CInt(InputBox("输⼊⽤于分组的列序号!"))
Range(Cells(2, Col), Cells(max_rows, Col)).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Cells(1, max_cols + 2), Unique:=True LastRow = Cells(1, max_cols + 2).End(xlDown).Row
Range(Cells(1, max_cols + 2), Cells(LastRow, max_cols + 2)).RemoveDuplicates Columns:=1, Head
er:=xlNo
LastRow = Cells(1, max_cols + 2).End(xlDown).Row
For i = 1 To LastRow
Name = CStr(Sh.Cells(i, max_cols + 2))
Sh.Activate
Rng.AutoFilter Field:=Col, Criteria1:=Name
Rng.Copy
Set new_sheet = Sheets.Add(After:=Sheets(Sheets.Count))
new_sheet.Name = Name
new_sheet.Range("A1").Activate
new_sheet.Paste
new_sheet.Range(new_sheet.Cells(1, 1), new_sheet.Cells(1, max_cols)).EntireColumn.AutoFit
Next
Sh.Activate
Columns(max_cols + 2).Delete Shift:=xlToLeft
Selection.AutoFilter
Application.ScreenUpdating = True
End Sub
升级:能指定起始⾏的带格式拆分
后⾯碰过了起始⾏不在开头的需求:
对于这类需求会增加复制⾮筛选区域的操作,我已经完整封装了全部过程到⼀个⽅法。
完整代码如下:
import win32com.client as win32 # 导⼊模块
import os
excel_app = ache.EnsureDispatch('Excel.Application')
def split_excel(filename, save_name, num, title_row=1):
"""作者⼩⼩明的csdn:blog.csdn/as604049322"""
wb = excel_app.Workbooks.Open(os.path.abspath(filename))
try:
sheet = wb.ActiveSheet
max_rows = sheet.UsedRange.Rows.Count
max_cols = sheet.UsedRange.Columns.Count
if title_row >1:
start = sheet.Range(sheet.Cells(
1,1), sheet.Cells(title_row-1, max_cols))
rng = sheet.Range(sheet.Cells(title_row,1),
sheet.Cells(max_rows, max_cols))
# 设置⾃动列宽
rng.EntireColumn.AutoFit()
names =set(sheet.Range(sheet.Cells(title_row+1, num),
sheet.Cells(max_rows, num)).Value)
for name,in names:
if not name:
continue
new_sheet = excel_app.Sheets.Add(
After=wb.Worksheets(wb.Worksheets.Count))
new_sheet.Name = name
if title_row >1:
sheet.Activate()
start.Copy()
new_sheet.Activate()
new_sheet.Range("A1").Activate()
new_sheet.Paste()
sheet.Activate()
rng.AutoFilter(Field=num, Criteria1=name)
rng.Copy()
new_sheet.Activate()
new_sheet.Range(f"A{title_row}").Activate()
new_sheet.Paste()
new_sheet.Range(new_sheet.Cells(1,1), new_sheet.Cells(
1, max_cols)).EntireColumn.AutoFit()
wb.SaveAs(os.path.abspath(save_name))
finally:
wb.Close()
split_excel("⼯单.xlsx",'拆分结果.xlsx',4,2)
#这步会关闭你正在使⽤的Excel软件,视具体情况决定是否要注释掉
excel_app.Quit()
VBA代码翻译成Python调⽤⽰例
前⾯我演⽰了Python带格式拆分Excel表,可能⼤家对使⽤python来调⽤vba还⽐较⽣疏,下⾯我将演⽰将⼀段vba代码翻译为python调⽤。
下⾯这段拆分Excel表的vba代码来⾃才哥的⽂章《》,作者是“两百⽄的⽼涛”,⼀起看看吧:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论