前言:有一个蛮好玩的需求,根据起始序号和步长(终止序号)复制多个单元格内容,并保存为新的Sheet
原始表:
结果表:
实现起来很容易,2个遍历循环,如果不考虑复杂因素的话,vba 20行内解决,Python也差不多,正好我对类一直比较陌生,所以就用这个小脚本练练手~全部代码如下:
from win32com.client import Dispatch
from os import path
import traceback
from datetime import datetime
class Cal(object):
def __init__(self, xlin, copy_value, start_sn, choice, foot, end_sn):
'''
:param xlin: excel的目标sheet名,比如"Sheet1"
:param copy_value: 想要复制的元素所在的列,比如"1"
:param start_sn: 起始序号所在的列
:param choice: 选择步长还是终止序号(步长:1,终止序号:2)
:param foot: 如果选择步长,步长所在的列
:param end_sn: 结束序号所在的列
:param wb: 工作簿
'''
self.xlin = xlin
self.copy_value = copy_value
self.start_sn = start_sn
self.choice = choice
self.foot = foot
self.end_sn = end_sn
self.wb = xl.Workbooks.Open(ex_path)
self.xlin_sheet = self.wb.Sheets(self.xlin)
def main_fun(self):
'''主程序'''
self.output()
if self.choice == 1: self.foot_cal()
elif self.choice == 2: self.end_cal()
else: print('Something is wrong!')
self.close_wb()
def output(self):
'''导出结果准备'''
try:
self.wb.Worksheets('导出结果').Delete() # 如果本来就有'导出结果'表的话删除
print("已删除Sheet:'导出结果'")
except:
pass
finally:
self.wb.Worksheets.Add().Name = "导出结果"
print("新建Sheet:'导出结果'")
global xlout_sheet
xlout_sheet = self.wb.Sheets('导出结果')
# 给新表附加抬头
SN_name = self.xlin_sheet.Cells(1, self.start_sn).Value
num_name = self.xlin_sheet.Cells(1, self.copy_value).Value
xlout_sheet.Cells(1, 1).Value = SN_name
xlout_sheet.Cells(1, 2).Value = num_name
def foot_cal(self):
'''利用步长计算'''
in_maxrow = self.xlin_sheet.UsedRange.Rows.Count + 1 # 原始数据里的最大行数+1
# 遍历并把内容复制到新表中
for i in range(2, in_maxrow):
start_SN = int(self.xlin_sheet.Cells(i, self.start_sn).Value) # 序号开始数值
step = int(self.xlin_sheet.Cells(i, foot).Value) # 步长
copy_value = self.xlin_sheet.Cells(i, self.copy_value).Value # 需要拷贝的单元格
out_maxrow = xlout_sheet.UsedRange.Rows.Count + 1 # 导出数据里的最大行数+1
for j in range(out_maxrow, step + out_maxrow):
xlout_sheet.Cells(j, 1).Value = start_SN + j - out_maxrow # 新的序号
xlout_sheet.Cells(j, 2).Value = copy_value
print('已完成{}的复制,共{}行'.format(copy_value, step))
def end_cal(self):
'''利用终止序号计算'''
in_maxrow = self.xlin_sheet.UsedRange.Rows.Count + 1 # 原始数据里的最大行数+1
# 遍历并把内容复制到新表中
for i in range(2, in_maxrow):
start_SN = int(self.xlin_sheet.Cells(i, self.start_sn).Value) # 序号开始数值
end_SN = int(self.xlin_sheet.Cells(i, self.end_sn).Value) # 序号开始数值
step = end_SN - start_SN + 1 # 步长
copy_value = self.xlin_sheet.Cells(i, self.copy_value).Value # 需要拷贝的单元格
out_maxrow = xlout_sheet.UsedRange.Rows.Count + 1 # 导出数据里的最大行数+1
for j in range(out_maxrow, step + out_maxrow):
xlout_sheet.Cells(j, 1).Value = start_SN + j - out_maxrow # 新的序号
xlout_sheet.Cells(j, 2).Value = copy_value
print('已完成{}的复制,共{}行'.format(copy_value, step))
def close_wb(self):
'''关闭并保存excel'''
self.wb.Save()
self.wb.Close()
if __name__ == "__main__":
try:
start_time = datetime.now()
xl_name = input("请输入excel表格的名字(比如'数据分行.xlsx'):")
path_this_file = path.abspath('.') + "\\"
ex_path = path_this_file + xl_name
xl = Dispatch("Excel.Application")
xl.Visible = False # True是显示, False是隐藏
xl.DisplayAlerts = 0
xlin = input("请输入原始数据所在的Sheet名字(比如'Sheet1'):")
copy_value = int(input('请输入需要拷贝的数值所在的列号(比如1代表第一列):'))
start_sn = int(input('请输入起始序号所在的列号(比如2代表第二列):'))
choice = int(input('请选择步长还是终止序号(步长:1,终止序号:2):'))
if choice == 1:
foot = int(input('请输入步长所在的列号(比如3代表第三列):'))
t = Cal(xlin=xlin, copy_value=copy_value, start_sn=start_sn, choice=choice, end_sn=0, foot=foot)
elif choice == 2:
end_sn = int(input('请输入终止序号所在的列号(比如3代表第三列):'))
t = Cal(xlin=xlin, copy_value=copy_value, start_sn=start_sn, choice=choice, end_sn=end_sn, foot=0)
t.main_fun()
end_time = datetime.now()
total_time = (end_time - start_time).seconds
print('已完成,耗时{}秒'.format(total_time))
except:
traceback.print_exc()
finally:
xl.quit()
a = input("按回车键退出!")
复杂环境和非复杂环境代码量真的差好多好多,如果不是为了后续利用和封装的话,简单的函数就好了,不是非要上类,但若想以后继续使用以及基础的提升,类则是必不可少的。