上一篇文章写了怎么自动化写一个月报,其中有很多很好用的函数组件,都被我封装为了函数,功能很好用。下面一一介绍:
1.添加汇总函数
输入一个pandas的数据框,就会返回一个加了汇总行的数据框。
def add_summary_row(df):numeric_df = df.select_dtypes(include=['number'])summary = numeric_df.sum()for col in df.columns.difference(numeric_df.columns):summary[col] = Noneresult_df = pd.concat([df, pd.DataFrame(summary).T])result_df.index = list(range(len(df.index))) + ['汇总']return result_df
当然,全是数值型数据的情况下可以简化为:
df.groupby('资产类别名称').sum(numeric_only=True).T.assign(汇总=lambda x:x.sum(1)).T
2.锚点查找函数
例如我要找流动资产合计这一项,我可以用固定的位置来找,比如财务那边总把流动资产合计的值写在C26这个格子里面。
但这种固定位置的查找可能有时候会有问题,比如财务那边突然需要加个标题,把资产负债表整体向下挪动了一行....那么C26这个位置就不对了。
所以绝对位置不准确,那我们就应该用相对位置,例如我发现我需要的这个值总是在‘流动资产合计’这个格子的右边两列的位置。那我先查找‘流动资产合计’这一项,然后右移动两格就是我需要的值了。
我称这种查找为锚定查找,找一个锚点,然后偏移找到自己需要的附近的值。这种相对查找的方法比绝对查找的方法出问题的可能性会小一点。
定义一个函数来进行锚点查找:
#资产负债表
wb = xlrd.open_workbook('***********2023年7月报表20230731.xls')
sheet = wb.sheet_by_index(0) #wb.sheet_by_name('资产负债表')
def find_and_offset_xlrd(sheet, target_value, offset_row, offset_column):for row in range(sheet.nrows):for col in range(sheet.ncols):if str(sheet.cell(row, col).value).replace(' ','') == target_value:target_cell_value = sheet.cell(row + offset_row, col + offset_column).valuereturn target_cell_value
资产总计 = find_and_offset_xlrd(sheet, '资产总计', 0, 2)/10000
这个函数只针对xls文件,xlsx文件可以用下面的这个更高的函数:
wb = openpyxl.load_workbook('../周报/周报.xlsx',data_only=True)
ws = wb['汇总2']def find_and_offset_openpyxl(sheet, target_value, offset_row, offset_column, start_row=1, end_row=None, start_col=1, end_col=None):# If end_row or end_col is not specified, search until the last row or columnif end_row is None:end_row = sheet.max_rowif end_col is None:end_col = sheet.max_columnfor row in sheet.iter_rows(min_row=start_row, max_row=end_row, min_col=start_col, max_col=end_col):for cell in row:if str(cell.value).replace(' ', '') == target_value:target_cell = sheet.cell(row=cell.row+offset_row, column=cell.column+offset_column)return target_cell.value
使用样例:
物贸营收=find_and_offset_openpyxl(ws, '物贸',1, 0,start_col=1, end_col=6)
物贸合同=find_and_offset_openpyxl(ws, '物贸',1, 0,start_col=7, end_col=12)
它可以限制查找范围,免得重复锚点造成混乱。
3.修改文字段落样式函数
def set_style(paragraphs,style=u'仿宋_GB2312',size=16):for run in paragraphs.runs:run.font.name = stylerun.font.size = Pt(size)r = run._element.rPr.rFontsr.set(qn("w:eastAsia"),style)
这个函数的功能是修改这个段落的字体和大小。因为我发现每次代码修改了word里面的东西后,它就会默认使用微软体文字.....使用我们需要把内容变成我们要的模板格式。我们需要这个函数,无论替换了什么内容,都需要它来变一下格式 擦屁股。
使用样例:
for i,paragraph in enumerate(doc.paragraphs):if '月,**公司资产总计约'in paragraph.text:paragraph.text =txt[0]print('0') ; set_style(paragraph)
4.文字查找替换函数
#查找替换
def docx_replace(old_text, new_text, doc):for paragraph in doc.paragraphs:if old_text in paragraph.text:paragraph.text = paragraph.text.replace(old_text, new_text)set_style(paragraph)
docx_replace(f"截至{year}年{month-1}月", f"截至{year}年{month}月", doc)
这个函数类似于word里面的替换功能,把你要查找的文字,换为其他文字。
5.表格内容替换
我们对word表里面的数据也要进行修改,
直接替换里面的文字是不行的,还是因为样式会变成默认样式,和领导要求的模板不一样...
所以也需要设置一下。
定义一个表格替换函数,传入你要替换的格子,替换的文本,以及字体样式,大小,居中什么的
def set_cell_text(cell, text, font_name='仿宋_GB2312', font_size=12, alignment=WD_PARAGRAPH_ALIGNMENT.CENTER):cell.text = textfor paragraph in cell.paragraphs:paragraph.alignment = alignmentset_style(paragraph,font_name,font_size)
使用样例:
table = doc.tables[0]
set_cell_text(table.cell(2, 3), str(df.loc['房屋建筑物','资产数量']), '仿宋_GB2312', 12)
这样相当于把这个表第3行第4列的格子里面的数据进行了替换,设置为仿宋体,12号,居中。