Python自动化小技巧18——自动化资产月报(word设置字体表格样式,查找替换文字)

案例背景

每月都要写各种月报,经营管理月报,资产月报.....这些报告文字目标都是高度相似的,只是需要替换为每个月的实际数据就行,如下:

 

(打码是怕信息泄露.....)

可以看到,这个报告的都是高度模板化,我们只需要对里面的某些文字进行替换,例如2023年7月换成2023年8月,资产数量490替换为最新的值,表格里面的数值也是一样的情况。

这篇文章的目的:我们并不是从头到尾,去从0开始生产月报,而是在往期的月报上进行修改。

这些东西都是复制粘贴,数据准备好了,按照定点的位置填就行了。所以代码来自动化这个流程就很变得很便捷。


代码实现

导入包:

import xlrd
import pandas as pdimport docx
from docx.oxml.ns import nsdecls
from docx.oxml import parse_xml
from docx import Document
from docx.oxml.ns import qn
import calendar
from docx.shared import Cm, Pt #设置像素、缩进等
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_ALIGN_VERTICAL
from docx.enum.text import WD_PARAGRAPH_ALIGNMENTyear = 2023
month = 7
num_days = calendar.monthrange(year, month)[1]
print(f"{year}年{month}月有{num_days}天")

 这里我们要先填入年份和信息,因为月报是月底写,最后的日期可能是31号可能是30号,所以需要用代码自动化计算一下日期.....


锚点查找

进行我们的第一步,我们需要数据来写报告,数据肯定都在excel里面算好了,没算好也肯定需要一定的流程加工算好了再说.....(参考我自动化小技巧16的文章)

例如上面我展示的目标,我需要填资产和负债的信息,这些数据都在财务那边给我的资产负债表里面,我肯定不会自己去打开excel表查找我要的值然后再写入代码里面.....这太低效了,而且这就不是自动化了。我们要用代码来找。

但是怎么找自己特定需要的数据呢?例如我要找流动资产合计这一项,我可以用固定的位置来找,比如财务那边总把流动资产合计的值写在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

然后进行查找各种我们需要的值:(注意这个函数是针对xls文件的,xlsx文件读取不了。。后面还会有针对xlsx的锚点查找函数,放在文章最后)

资产总计 = find_and_offset_xlrd(sheet, '资产总计', 0, 2)/10000
流动资产合计=find_and_offset_xlrd(sheet, '流动资产合计', 0, 2)/10000
非流动资产合计=find_and_offset_xlrd(sheet, '非流动资产合计', 0, 2)/10000
负债合计=find_and_offset_xlrd(sheet, '负债合计', 0, 2)/10000
固定资产净值=find_and_offset_xlrd(sheet, '固定资产净值', 0, 2)/10000
[资产总计,流动资产合计,非流动资产合计,负债合计,固定资产净值]

 这就是我们需要的值,然后进行一些必要的运算

流动资产占比=100*流动资产合计/资产总计
非流动资产占比=100*非流动资产合计/资产总计
净资产=资产总计-负债合计
固定资产占比=100*固定资产净值/资产总计
其他非流动资产=非流动资产合计-固定资产净值
其他非流动资产占比=100*其他非流动资产/资产总计

段落替换

由于我们是资产月报,还得往表格里面填入各种资产的信息,我们需要读取我之前文章做好的资产分类汇总表:

df=pd.read_excel('../../资产管理/资产类别变动后汇总/分类汇总金额.xlsx',sheet_name='汇总').set_index('资产类别名称')
df

 进行一些必要的计算...:

实物资产数量=df.loc['合计','资产数量']
资产原值=df.loc['合计','原值']/10000
生产及动力设备=df.loc['生产及动力设备','原值']/10000

写好我们 需要的文字目标:

txt=f'''截至{year}年{month}月,**公司资产总计约{资产总计:.0f}万元。其中,流动资产{流动资产合计:.0f}万元,占比{流动资产占比:.1f}%;非流动资产{非流动资产合计:.0f}万元,占比{非流动资产占比:.1f}%。负债合计{负债合计:.0f}万元,净资产{净资产:.0f}万元。
公司非流动资产中,固定资产{固定资产净值:.0f}万元(固定资产净值),占资产总额{固定资产占比:.0f}%;其他类非流动资产{其他非流动资产:.0f}万元,占资产总额{其他非流动资产占比:.2f}%(长期待摊费用、递延所得税资产、无形资产)。
截至{year}年{month}月,**公司管理实物资产数量{实物资产数量:.0f}项,金额{资产原值:.0f}万元(资产原值)。其中,自有实物资产数量{实物资产数量:.0f}项,主要为机械设备,账面价值{生产及动力设备:.0f}万元;受托管理实物资产数量0项,账面价值(或资产原值)0万元。公司管理实物资产情况如下表:
'''
txt=txt.split('\n')

这几句话我们就需要进行替换了,替换掉原来的段落。这种很多需要修改的我们就进行段落替换,如果只是像2023年7月换成8月的这种小修改就简单替换(后面会有这种函数)

核心函数!!修改样式:

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里面的东西后,它就会默认使用微软体文字.....使用我们需要把内容变成我们要的模板格式。我们需要这个函数,无论替换了什么内容,都需要它来变一下格式 擦屁股。

读取文档,替换文字:

doc = docx.Document(f'./资产附件/附件1:资产管理月度情况简报{month-1}月.docx')
for i,paragraph in enumerate(doc.paragraphs):#if '2023年' in run.text:if '月,远大公司资产总计约'in paragraph.text:paragraph.text =txt[0]print('0')   ; set_style(paragraph)if '公司非流动资产中,固定资产' in paragraph.text:paragraph.text = txt[1]print('1')  ;set_style(paragraph)if '月,远大公司管理实物资产数量' in paragraph.text:paragraph.text=txt[2]print('2')      ;set_style(paragraph)  if f'{year}年' in paragraph.text and (i>len(doc.paragraphs)-3):paragraph.text=f'{year}年{month}月{num_days}日'    ;set_style(paragraph)paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT

if判断是尽可能找到你需要替换的段落,然后换为上面我们设定的文字,然后设置一下样式。

最后这个条件判断意思是:如果段落行数为最后3行里面的出现了年月日,那么久换为最新的年月日。因为我需要改落款日期,但是对全文全部修改会可能出问题,所以限定了最后3行。


文字替换

这个函数类似于word里面的替换功能,把你要查找的文字,换为其他文字

#查找替换
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)

 这是替换了月份,每次都把月报里面的日期肯定要更新为最新的。

docx_replace(f"{year}年1-{month-1}月,经省", f"{year}年1-{month}月,经省", doc)
docx_replace(f"现将**公司{month-1}月资产管理情况报告如下", f"现将**公司{month}月资产管理情况报告如下", doc)

表格替换

文字我们都改了之后,我们对word表里面的数据也要进行修改:

我们可以获取word里面的表对象:

table = doc.tables[0]

直接替换里面的文字是不行的,还是因为样式会变成默认样式,和领导要求的模板不一样...

所以也需要设置一下。

定义一个表格替换函数,传入你要替换的格子,替换的文本,以及字体样式,大小,居中什么的

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)

 因为目标表格填的位置是固定的,所以我可以使用绝对位置来查找我需要换的数值:

set_cell_text(table.cell(2, 3), str(df.loc['房屋建筑物','资产数量']), '仿宋_GB2312', 12)
set_cell_text(table.cell(2, 4), f'''{df.loc['房屋建筑物','原值']/10000:.0f}''')set_cell_text(table.cell(7, 3), str(df.loc['办公及电子设备','资产数量']))
set_cell_text(table.cell(7, 4), f'''{df.loc['办公及电子设备','原值']/10000:.0f}''')set_cell_text(table.cell(8, 3), str(df.loc['车辆','资产数量']))
set_cell_text(table.cell(8, 4), f'''{df.loc['车辆','原值']/10000:.0f}''')set_cell_text(table.cell(9, 3), str(df.loc['生产及动力设备','资产数量']))
set_cell_text(table.cell(9, 4), f'''{df.loc['生产及动力设备','原值']/10000:.0f}''')set_cell_text(table.cell(10, 3), str(df.loc['安全设施','资产数量']))
set_cell_text(table.cell(10, 4), f'''{df.loc['安全设施','原值']/10000:.0f}''')set_cell_text(table.cell(11, 3), str(df.loc['家具和其他','资产数量']))
set_cell_text(table.cell(11, 4), f'''{df.loc['家具和其他','原值']/10000:.0f}''')set_cell_text(table.cell(15, 3), str(df.loc['合计','资产数量']))
set_cell_text(table.cell(15, 4), f'''{df.loc['合计','原值']/10000:.0f}''')

最后保存,一个自动化月报的工程就完成啦。

doc.save(f'附件1:资产管理月度情况简报{month}月.docx')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/98141.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

超实用的两款截图工具(FastStone Capture 和 Snipaste)

文章目录 一、概述1)FastStone Capture2)Snipaste 二、FastStone Capture 和 Snipaste 截图软件安装 一、概述 "FastStone Capture" 和 "Snipaste" 都是计算机上常用的截图工具,用于捕捉屏幕截图、编辑图像以及进行屏幕…

vite打包配置以及性能优化

vite打包配置以及性能优化 安装插件 首先该安装的插件,你要安装一下吧 这三个是基本的插件,其他优化的插件下面会介绍到 "vite": "4.4.6","vite-plugin-html": "^3.2.0","vitejs/plugin-vue": &qu…

【最新可用】VMware中ubuntu与主机window之间使用共享文件夹传输大文件

一、VMware设置共享文件夹 (1)虚拟机关机情况下,创建一个共享文件夹 (2)ubuntu中挂载共享文件夹 1、如果之前已经挂载 hgfs,先取消挂载 sudo umount /mnt/hgfs2、重新使用以下命令挂载 sudo /usr/bin/vmh…

Ubuntu安装Apache+Php

环境:ubuntu 22.04 虚拟机 首先更新一下 sudo apt-get update sudo apt-get upgrade安装Apache2: sudo apt-get install apache2 输入y,继续。等着他恐龙抗浪抗浪的下载安装就好了 打开浏览器访问http://localhost/ 安装php: …

Dockerfile概念、镜像原理、制作及案例讲解

1.Docker镜像原理 Linux文件操作系统讲解 2.镜像如何制作 3.Dockerfile概念 Docker网址:https://hub.docker.com 3.1 Dockerfile关键字 4.案例

pytest的fixture梳理

fixture特性 夹具是在测试中用于提供共享资源、设置测试环境或模拟行为的工具。 1. 可以重复使用,多个用例可以使用同一个fixture 2. 一个测试用例可以使用多个装置 import pytest # Arrange pytest.fixture def first_entry():return "a"# Arrange pyt…

DNNGP、DeepGS 和 DLGWAS模型构成对比

一、DNNGP DNNGP 是基于深度卷积神经网络,这个结构包括一个输入层,三个卷积层,一个批标准化层,两个dropout层,一个平坦化层,一个 dense层。 dropout层:在神经网络中,dropout层是一个非常有效的正…

个性化定制界面 VS 极简版原装界面:你更喜欢哪一个?为什么?

文章目录 每日一句正能量前言自己的喜好使用这种界面的原因这种界面对你的影响后记 每日一句正能量 不管昨天、今天、明天,能豁然开朗就是最美好的一天。 前言 个性化定制界面和极简版原装界面,哪一个你用起来更加顺手呢,相比之下你更喜欢哪一…

利用Figlet工具创建酷炫Linux Centos8服务器-登录欢迎界面-SHELL自动化编译安装代码

因为我们需要生成需要的特定字符,所以需要在当前服务器中安装Figlet,默认没有安装包的,其实如果我们也只要在一台环境中安装,然后需要什么字符只要复制到需要的服务器中,并不需要所有都安装。同样的,我们也可以利用此生成的字符用到脚本运行的开始起头部分,用ECHO分行标…

解决Java中的“Unchecked cast: java.lang.Object to java.util.List”问题

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

C++入门:函数缺省参数与函数重载

目录 1.函数缺省参数 1.1 缺省参数概念 1.2 缺省参数分类 2.函数重载 2.1 函数重载概念 2.2 C支持函数重载的原理 1.函数缺省参数 1.1 缺省参数概念 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实 参则采用该形参的…

python 自动化学习(四) pyppeteer 浏览器操作自动化

背景 之前我在工作中涉及到了很多地方都是重复性的页面点点点工作,又因为安全保密原则不开放接口和数据库,只有一个页面来提供点击进行操作,就想着用前面学的自动化来实现,但发现前面学的模拟操作对浏览器来说并没有那么友好&…

【C# 基础精讲】LINQ to Objects查询

LINQ to Objects是LINQ技术在C#中的一种应用,它专门用于对内存中的对象集合进行查询和操作。通过使用LINQ to Objects,您可以使用统一的语法来查询、过滤、排序、分组等操作各种.NET对象。本文将详细介绍LINQ to Objects的基本概念、常见的操作和示例&am…

开源低代码平台Openblocks

网友 HankMeng 想看低代码工具,正好手上有一个; 什么是 Openblocks ? Openblocks 是一个开发人员友好的开源低代码平台,可在几分钟内构建内部应用程序。 传统上,构建内部应用程序需要复杂的前端和后端交互,…

0基础入门C++之类和对象中篇

目录 1.类的6个默认成员函数2.构造函数2.1概念2.2特性 3.析构函数3.1概念3.2特性 4.拷贝构造函数4.1概念4.2 特性 5.赋值运算符重载5.1运算符重载5.2赋值重载5.3赋值运算符重载特性 6.const成员7.取地址及const取地址操作符重载 1.类的6个默认成员函数 通过类和对象上篇的学习&…

docker安装redis7-哨兵模式

说明 系统:CentOS7.9 redis:7.0.5 由于资源问题本次的部署全部在一台宿主机上通过启动不同的docker容器来完成部署。 搭建哨兵模式之前,首先搭建好主从模式,1主2从,可以参考上一篇文章:docker安装redis…

Linux 进程间通信——消息队列

一、消息队列的原理 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。每个数据块都被认为含有一个类型,接收进程可以独立接收含有不同类型值得数据库。 消息实际上是一个数据块,这个数据块是一个结构体,结构体由自己命名。消…

HTML笔记(3)

表单标签 用于登录、注册界面,以采集用户输入的信息,把信息采集到之后,用户一点按钮,就会把这些信息发送到服务端,服务端就可以把这些数据存储到数据库,所以表单是一个非常重要的html标签,它主要…

Appium 2安装与使用java对Android进行自动化测试

文章目录 1、Appium 2.1安装1.1、系统要求1.2、安装Appium2.1服务1.3、安装UiAutomator2驱动1.4、安装Android SDK platform tools1.5、下载OpenJDK 2、Android自动代码例子2.1、安装Android自动化测试元素定位工具Appium Inspector2.2、编写android app自动化测试代码和使用ex…

常见架构类型

目录 1.单机架构 2.应用数据分离架构 3.读写分离架构 4.冷热分离架构 5.垂直分库架构 6.微服务架构 7.容器编排架构 1.单机架构 单机架构是简单的将应用服务和数据库服务部署到同一台机器上。 缺点:存在很大的性能限制。 2.应用数据分离架构 引入负载均衡&a…