使用python读Excel文件并写入另一个xls模版

效果如下:

原文件内容

转化后的内容

大致代码如下:

1. load_it.py

#!/usr/bin/env python
import re
from datetime import datetime
from io import BytesIO
from pathlib import Path
from typing import List, Unionfrom fastapi import HTTPException
from openpyxl import load_workbookRE_SPACES = re.compile(r"\s{2,}")def slim(s: str) -> str:return RE_SPACES.sub(" ", s)class ValidationError(HTTPException):def __init__(self, detail: str, status_code: int = 400):super().__init__(status_code, detail=detail)def remove_author(s: str) -> str:if s := s.replace("作者:\n", "").replace("Administrator:\n", ""):return str(s)return ''def read_excel(filename: Union[Path, str, bytes, BytesIO]):if isinstance(filename, bytes):filename = BytesIO(filename)return load_workbook(filename)def load(filename: Union[Path, str, bytes, BytesIO]):wb = read_excel(filename)sheet_name = "工资表"try:sheet = wb[sheet_name]except KeyError:try:sheet = wb["Sheet1"]except KeyError:raise ValidationError(f"未找到名称为{sheet_name!r}的工作表")title = sheet.cell(1, 1).value.strip()now = datetime.now()if "月" in title:remark = title.split("年")[-1].strip("表").replace("份", "")else:if (month := now.month - 1) == 0:month = 12remark = f"{month}月工资"day = f"{now:%Y.%m.%d}"lines: List[list] = []for row in range(4, sheet.max_row):xuhao = sheet.cell(row, 1).valueif xuhao and (isinstance(xuhao, int) or xuhao.isdigit()):name = sheet.cell(row, 2).valuetotal = 0if (base := sheet.cell(row, 4).value) is None:base = "/"else:if isinstance(base, str):if base.startswith("="):base = eval(base[1:])else:raise TypeError(f"Expect int value, got: {base=}")total += basecommission_comment = ""  # 提成批注commission_cell = sheet.cell(row, 5)if (commission := commission_cell.value) is None:commission = "/"else:if isinstance(commission, str) and commission.startswith('='):commission = eval(commission[1:])total += commissionif _cc := commission_cell.comment:if _ct := _cc.text:commission_comment = remove_author(_ct)if (attend := sheet.cell(row, 6).value) is None:if (attend := sheet.cell(row, 13).value) is None:attend = "/"if (attend_money := sheet.cell(row, 7).value) is not None:total += attend_moneyattend = attend.strip().strip("+-/").strip()if attend_money > 0:attend += f" +{attend_money}"else:attend += f" {attend_money}"if (late := sheet.cell(row, 8).value) is None:late = "/"else:late = slim(late)if late_money := sheet.cell(row, 9).value:total += late_moneyif late_money > 0:late = f"{late}{late_money}"else:late = late.strip("/") + str(late_money)if subsidy_value := sheet.cell(row, 11).value:  # 补助if isinstance(subsidy_value, str) and subsidy_value.startswith("="):subsidy_value = eval(subsidy_value[1:])try:total += subsidy_valueexcept TypeError:raise ValidationError(f"第{row}行第11列数据异常:预期为数值,得到的是{subsidy_value!r}")subsidy = "/"if _c := sheet.cell(row, 10).comment:if _s := _c.text:subsidy = remove_author(_s)one = [name,base,commission,attend,late,subsidy,total,remark,day,commission_comment,]lines.append(one)return linesdef main():import sysif not sys.argv[1:]:print("No args, do nothing.")returnprint(load(sys.argv[1]))if __name__ == "__main__":main()

 

 2. gen_excel.py

#!/usr/bin/env python
from datetime import datetime
from pathlib import Path
from typing import List, Optional, Tuple, Unionimport xlrd
import xlwt
from xlutils.copy import copy as xls_copyfrom load_it import load, read_excel, remove_author
from settings import BASE_DIR, MEDIA_ROOTSAMPLE = "salary_tips.xls"
DataType = Union[int, float, str, None]def cell_style(is_top: bool = False, is_bottom: bool = False, has_border=True):"""单元格样式"""style = xlwt.XFStyle()# 字体大小,11为字号,20为衡量单位# font = xlwt.Font()style.font.height = 20 * 9align = xlwt.Alignment()# 0x01(左端对齐)、0x02(水平方向上居中对齐)、0x03(右端对齐)align.horz = 0x02# 0x00(上端对齐)、 0x01(垂直方向上居中对齐)、0x02(底端对齐)align.vert = 0x01# 设置自动换行align.wrap = 1style.alignment = align# 设置边框# 细实线:1,小粗实线:2,细虚线:3,中细虚线:4,大粗实线:5,双线:6,细点虚线:7# 大粗虚线:8,细点划线:9,粗点划线:10,细双点划线:11,粗双点划线:12,斜点划线:13if has_border:borders = xlwt.Borders()borders.left = 2borders.right = 2borders.top = 1 + is_topborders.bottom = 1 + is_bottomstyle.borders = bordersreturn styledef boom(tips: List[List[Tuple[int, int, DataType]]]) -> str:"""将数据填入模板生成Excel表"""sample = BASE_DIR / SAMPLExls = xls_copy(xlrd.open_workbook(sample, formatting_info=True))ws = xls.get_sheet(0)style = cell_style()top_style = cell_style(is_top=True)bottom_style = cell_style(is_bottom=True)plain_style = cell_style(has_border=False)last_index = 8for datas in tips:for i, d in enumerate(datas[:-1]):if i == 0:ws.write(*d, top_style)elif i == last_index:ws.write(*d, bottom_style)else:ws.write(*d, style)if _tc := datas[-1]:row, col, text = _tcif text:ws.write_merge(row, row, col - 1, col, text, plain_style)fname = MEDIA_ROOT / f"gzt_{datetime.now():%Y%m%d%H%M%S}.xls"try:xls.save(fname)except TypeError as e:print("May be you can look at this to fix it:")print("https://blog.csdn.net/zhangvalue/article/details/105170305")raise ereturn str(fname).replace(str(BASE_DIR), "")  # 返回相对路径def build_tips(lines: List[List[DataType]]):row_delta = 10  # 每隔10行填下一排的数据col_delta = 3  # 每隔3列填下一组数据line_tip = 5  # 每行有5个工资条row_begin = 0  # 从第一行开始col_begin = 1  # 从第二列开始填数据(第一列是固定的表头)tips = []for tip_index, tip in enumerate(lines):first_row = row_begin + tip_index // line_tip * row_deltacol_index = col_begin + tip_index % line_tip * col_deltad = [(row_index + first_row, col_index, value)for row_index, value in enumerate(tip)]tips.append(d)return tipsdef burn_life(content: bytes) -> str:return boom(build_tips(load(content)))def dear_sister(content: bytes, origin_name: Optional[str] = None) -> str:"""2022-04-04 亲爱的妹妹想要一个可以把批注提取出来的"""wb = read_excel(content)sheet = wb.worksheets[0]count = 0# openpyxl的行和列都是从1开始for row in range(1, sheet.max_row):for col in range(1, sheet.max_column):cell = sheet.cell(row, col)if comment := cell.comment:if text := comment.text:cell.value = remove_author(text)count += 1if origin_name:fname = MEDIA_ROOT / f"{Path(origin_name).stem}-批注提取{count}.xls"else:fname = MEDIA_ROOT / f"批注提取{count}.xls"wb.save(fname)return str(fname).replace(str(BASE_DIR), "")  # 返回相对路径def main():import sysif not sys.argv[1:]:print("No args, do nothing.")returnif (p := Path(sys.argv[1])).is_file():lines = load(p.read_bytes())else:day = f"{datetime.now():%Y.%m.%d}"ss = ["狄仁杰",1600,360,"休5天,请假7.5天 -400","迟到3次共16分钟","扣社保-373\n工龄+100\n漏刷卡6次-300",987,"12月工资",day,]lines = [ss, ss]print(boom(build_tips(lines)))if __name__ == "__main__":main()

    

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

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

相关文章

睿趣科技:抖音开网店现在做还来得及吗

随着社交媒体的迅速发展,抖音作为一款短视频平台,已经在年轻人中间取得了巨大的成功。而近年来,越来越多的人开始考虑在抖音上开设网店,以迎合这一潮流。那么,抖音开网店现在还来得及吗? 首先,要明确的是&…

一篇文章教会你搭建私人kindle图书馆,并内网穿透实现公网访问

搭建私人kindle图书馆,并内网穿透实现公网访问 在电子书风靡的时期,大部分人都购买了一本电子书,虽然这本电子书更多的时候是被搁置在储物架上吃灰,或者成为盖泡面的神器,但当亚马逊发布消息将放弃电子书在中国的服务…

Kubernetes部署Wordpress时碰到的两个问题解决

文章目录 小结问题1解决问题2解决参考 小结 在使用Kubernetes部署Wordpress时返回了两个问题: Function not implemented: AH00141: Could not initialize random number generator chown: changing ownership of .: Operation not permitted 对这个两个返回错误&#xff0…

利用Python隧道爬虫ip轻松构建全局爬虫网络

嘿,爬虫程序员们!你们有没有碰到过需要大规模数据爬取的情况?也许你们之前遇到过网站的反爬措施,卡住你们的进度。别担心,今天我来分享一个利用Python隧道爬虫ip实现的方法,帮助你们轻松搭建全局爬虫ip网络…

jmeter界面设置为中文

jmeter版本:5.6.2 找到jmeter下的bin目录,打开jmeter.properties 文件 第39行修改为 languagezh_CN去掉前面的#,以后打开就是中文界面了

IC设计仿真云架构

对于IC仿真来说,最重要的是要安全、可维护、高性能的的HPC环境环境。 那么云上如何搭建起一套完整的IC仿真云环境呢? 这种架构应该长什么样子? 桌面虚拟化基础架构 将所有桌面虚拟机在数据中心进行托管并统一管理;同时用户能够…

RxJava 复刻简版之三,map 多次中转数据

案例代码:https://gitee.com/bobidali/lite-rx-java/commit/292e9227a5491f7ec6a07f395292ef8e6ff69290 RxJava 的调用第一步是封装了观察者接受了数据的处理,进一步就是使用 map 将数据操作传递给上下游 1、类似Observer.create 创建一个简单的观察者…

神经网络基础-神经网络补充概念-05-导数

概念 导数是微积分中的一个概念,用于描述函数在某一点的变化率。在数学中,函数的导数表示函数值随着自变量的微小变化而产生的变化量,即斜率或变化率。 假设有一个函数 f(x),其中 x 是自变量,y f(x) 是因变量。函数…

如何评价机械革命?

机械革命是在全球顶尖IT厂商蓝天、intel、nvidia、Microsoft等联手的打造下推出的中高端品牌。(零件组装) 机械革命研发实力雄厚,糟糕的外观设计和极致的游戏性能一样出名。图片皆来自于未来世界。

【0214】postgres后端进程session退出,如何通过日志分析其会话信息

文章目录 1. postgres进程session退出2. 开启日志记录postgres进程会话状态3. postgres进程会话结束,记录日志的实现原理1. postgres进程session退出 默认情况下,新建一个postgres后端进程会话(session),或是postgres进程正常/异常退出时,日志中没有很明显的记录用于说明…

嵌入式:ARM Day4

一、自己编写代码实现三盏灯点亮 源码: .text .global _start _start: 进行一次初始化bl RCC_INITbl LED1_INITbl LED2_INITbl LED3_INITb looploop: 循环开关灯bl LED1_ONbl delay_1sbl LED1_OFFbl delay_1sbl LED2_ONbl delay_1sbl LED2_OFFbl delay_1sbl…

如何进行网络活动监控

组织的 IT 基础架构中的每个网络设备上都发生了大量活动,例如数据包传输、来自网络协议的消息、设备状态事件等。网络活动成为在检测到问题时识别网络瓶颈的面包屑,因此即使是最微小的网络活动也应受到监控,因为它直接影响整体网络性能、运行…

UI设计师个人工作总结范文精选

UI设计师个人工作总结范文(一) 在忙忙碌碌中,2019年又将过去了,在这一年当中,设计部无论是在运作模式、设计产值、还是人员结构,各方面的变化都比较大。 设计部的运作模式是从7月底开始进行调整的,以独立承包制的运营方…

爬虫抓取数据时显示超时,是代理IP质量不行?

很多人在做数据抓取的时候,会遇到显示超时了,然后就没有响应了。这是什么原因的?有的人回答是使用的代理IP质量不行,这种答案,对也不对。 数据抓取时,出现超时的原因时多方面影响的,主要分为目标…

python爬虫5:requests库-案例3

python爬虫5:requests库-案例3 前言 ​ python实现网络爬虫非常简单,只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点,方便以后复习。 申明 ​ 本系列所涉及的代码仅用于个人研究与讨论,并不会对网…

hivesql-dayofweek 函数

返回日期或时间戳的星期几。 此函数是 extract(DAYOFWEEK FROM expr) 的同义函数。 语法 dayofweek(expr) 参数 expr:一个 DATE 或 TIMESTAMP 表达式。 返回 一个 INTEGER,其中 1 Sunday 和 7 Saturday。 示例 > SELECT dayofweek(2009-07-30)…

mysql 01.三范式,数据类型

01.概念的区分: mysql是属于DBMS层次的,sql语句是用于DBMS的语句。 02.sql语句详细介绍: SQL的概述Structure Query Language(结构化查询语言)简称SQL,它被美国国家标准局(ANSI)确定为关系型数据库语言的美国标准,后…

神经网络基础-神经网络补充概念-37-其他正则化方法

概念 L1 正则化(Lasso Regularization):L1 正则化通过在损失函数中添加参数的绝对值之和作为惩罚项,促使部分参数变为零,实现特征选择。适用于稀疏性特征选择问题。 L2 正则化(Ridge Regularization&…

conda常用命令及国内镜像源

conda命令使用介绍 启动conda source ~/.bashrc帮助目录 conda create -h检查conda版本 conda --version升级当前版本的conda conda update conda环境管理 列出所有的环境 conda info -e conda env list安装一个不同版本的python新环境 conda create --name py27 pytho…

PHP FTP的相关函数及简单使用示例

简介 FTP是ARPANet的标准文件传输协议,该网络就是现今Internet的前身。 PHP FTP函数是通过文件传输协议提供对文件服务器的客户端访问,FTP函数用于打开、登陆以及关闭连接,也用于上传、下载、重命名、删除以及获取服务器上文件信息。 安装 …