按xls标签替换docx及xls内容

embedded/2024/9/18 13:40:23/ 标签: python, 开发语言, python-docx, xlutils, tkinter, Treeview

WPSoffice环境下,需要批量替换doc文档及xls表格某些内容,在windows下,可以用VBA宏实现,先建一个标签表格,然后按标签批量替换。但在Linux下,WPS表格宏不能跨文档操作WPS文字,于是想用python实现。

1、标签文件与模板文件格式:

标签文件A列为标签名,B列为值。

模板文件关键词用#包围,如下:

2、基本功能

读入标签内容,然后打开模板文件,替换关键词为标签值,保存到新文件。

用到的python库:xlrd、xlutilstkinter。读入的标签及文件列表使用Treeview展示,并提供修改、增加项、删除项功能。

3、几个重要代码片段

3.1 读xls内容

        # 读入标签表# 打开一个 Excel 文件workbook = xlrd.open_workbook(fname)# 通过索引获取第一个工作表sheet = workbook.sheet_by_index(0)da = []# 遍历所有行和列输出for i in range(sheet.nrows):# 键值分布在1、2列key = str(sheet.cell_value(i, 0)).replace(' ', '')    # 删除空格val = sheet.cell_value(i, 1)date_format = sheet.cell_type(i, 1)# 日期类型if date_format == xlrd.XL_CELL_DATE:date_tuple = xlrd.xldate_as_tuple(val, workbook.datemode)val = '' + str(date_tuple[0]) + "年" + str(date_tuple[1]) + "月" + str(date_tuple[2]) + "日"# 文本类型if date_format == xlrd.XL_CELL_TEXT:val = '' + sheet.cell_value(i, 1)if str(key) != '':da.append((key, val))# print(da)workbook.release_resources()del workbook

3.2 替换docx文档关键词

    def procdocx(self, fname, lbitems, foutname):document = Document(fname)    # 打开文档for paragraph in document.paragraphs:runs = paragraph.runs  # 得到所有runfor i, run in enumerate(runs):key = run.text# 当前run不包含key值if key.count('#') == 0:continuecounter = i  # 记录起始位置if key.count('#') == 1:  # 如先导符与key值分在多个run中while counter < len(runs):  # 将先导符与后续run组成key后再查找counter = counter + 1if counter >= len(runs):breakkey += runs[counter].texttmp = runs[counter].textruns[counter].clear()    # 清空当前runs,本算法会改变文档内容格式if tmp.count('#') > 0:   # 注:如果有多个连续#,且第二个key分在多个run中,会有可能出现替换错误break# 开始替换for item in lbitems:key1 = '#' + self.labeltree.item(item)['values'][0].replace(' ', '') + '#'if key.find(key1) >= 0:# for j in range(i, counter + 1):#    runs[j].clear()key = key.replace(key1, self.labeltree.item(item)['values'][1])runs[i].text = key# 另存到输出文件夹document.save(foutname)

3.3 替换xls表格关键词

    def procxls(self, fname, lbitems, foutname):modxls = xlrd.open_workbook(fname, formatting_info=True)# 将操作文件对象拷贝,变成可写newxls = copy(modxls)# 获取所有sheet页及数量sheets = modxls.sheet_names()for shn in range(len(sheets)):# 通过索引获取第shn个工作表modsheet = modxls.sheet_by_index(shn)newsheet = newxls.get_sheet(shn)# 遍历mod所有行和列输出for i in range(modsheet.nrows):for j in range(modsheet.ncols):val = modsheet.cell_value(i, j)val_format = modsheet.cell_type(i, j)if val_format != xlrd.XL_CELL_TEXT:continue# 开始替换for item in lbitems:key1 = '#' + self.labeltree.item(item)['values'][0].replace(' ', '') + '#'if val.find(key1) >= 0:newval = val.replace(key1, self.labeltree.item(item)['values'][1])newsheet.write(i, j, newval)newxls.save(foutname)

3.4 Treeview代码

1) 创建一个treeview列表

        # 创建 self.labeltree 并添加到 self.mainframe 中columns1 = ("label", "value")self.labeltree = ttk.Treeview(frame51, show="headings", columns=columns1)self.labeltree.column('label', width=100, anchor='w')self.labeltree.heading('label', text="标签名")self.labeltree.column('value', width=300, anchor='w')self.labeltree.heading('value', text="标签值")self.labelscrollx = ttk.Scrollbar(frame51, orient="horizontal", command=self.labeltree.xview)self.labelscrolly = ttk.Scrollbar(frame51, orient="vertical", command=self.labeltree.yview)self.labeltree.configure(xscrollcommand=self.labelscrollx.set)self.labeltree.configure(yscrollcommand=self.labelscrolly.set)self.labelscrollx.pack(side="bottom", fill="x")self.labelscrolly.pack(side="right", fill="y")self.labeltree.pack(expand=1, fill='both', padx='1', pady='1')

2) 双击treeview编辑

    # 双击标签库列表def set_lbcell_value2(self, event):# 获取选中的项目col = self.labeltree.identify_column(event.x)  # 列row = self.labeltree.identify_row(event.y)  # 行if col == '' or row == '':returnselected_item = self.labeltree.selection()[0]cn = int(str(col).replace('#', ''))rn = int(str(row).replace('I', ''))x, y, w, h = self.labeltree.bbox(selected_item, col)txt = self.labeltree.item(selected_item, 'values')[cn-1]edstr = StringVar()edstr.set(txt)entryedit = ttk.Entry(self.labeltree, width=w//8, textvariable=edstr)entryedit.place(x=x, y=y)def saveedit(even):self.labeltree.set(selected_item, column=col, value=edstr.get())entryedit.destroy()entryedit.bind("<FocusOut>", saveedit)# 按下时触发entryedit.bind('<Return>', saveedit)  # 不是Enter而是Return

3) 右击treeview,弹出操作菜单

    # 右击标签库def set_lbcel_popup(self, event):# 创建右键菜单self.right_click_menu = Menu(self.labeltree, tearoff=False)self.right_click_menu.add_command(label="增加", command=lambda: self.on_menu_click_add(event))if self.labeltree.selection():self.right_click_menu.add_command(label="删除", command=lambda: self.on_menu_click_del(event))self.right_click_menu.post(event.x_root, event.y_root)# 新增标签def on_menu_click_add(self, event):self.labeltree.insert('', 'end', values=('新标签', '值'))self.labeltree.update()# 删除标签def on_menu_click_del(self, event):if self.labeltree.selection():self.labeltree.delete(self.labeltree.selection())

4、几个不足之处:

1)python-docx库只能操作docx文件,对doc文档支持不好。

2)对模板文档中标签格式有一定要求,但基本功能已实现。

5、源代码已上传,链接:https://download.csdn.net/download/zhoury/89612390


http://www.ppmy.cn/embedded/91030.html

相关文章

【Python机器学习】利用AdaBoost元算法提高分类性能——完整的AdaBoost算法的实现

上一篇记录了简化的单词决策树函数&#xff08;buildStump()&#xff09;的实现。下面实现完整AdaBoost算法。 完整AdaBoost算法的伪代码&#xff1a; 对每次迭代&#xff1a; 利用buildStump()函数找到最佳的单层决策树 将最佳单层决策树加入到单层决策树数组 计算alpha 计算…

mysql 各种锁归纳总结

文章目录 一、引言二、锁分类三、Mysql锁四、MyISAM表锁五、InnoDB锁六、间隙锁七、总结 一、引言 在现代应用程序中&#xff0c;数据库是不可或缺的组成部分之一。而MySQL作为一款开源的关系型数据库管理系统&#xff0c;广泛应用于各种规模的应用中。然而&#xff0c;在高并…

数据可视化(王者英雄数据分析)

目 录 第1章 绪 论 1.1 课题背景及研究目的 1.2 课题研究内容 第2章 课题概要及算法原理 2.1 课题概要 2.2 数据说明 2.3 关键技术 第3章 数据分析 3.1 数据统计分析 3.2 可视化分析 3.2.1数据读取及展示 3.2.2数据描述性分析 第4章 数据建模 4.1 数据预处理 4.2…

【Material-UI】Button 组件中的颜色设置(Color)详解

文章目录 一、基础颜色选项1. Secondary 颜色2. Success 颜色3. Error 颜色 二、定制颜色1. 添加自定义颜色2. 禁用默认颜色 三、高级用法和最佳实践1. 确保对比度2. 语义化颜色3. 考虑用户体验 四、总结 在用户界面设计中&#xff0c;颜色不仅仅是美学的一部分&#xff0c;更是…

C++数学库GNU Scientific Library (GSL)

在科学计算和数值分析领域&#xff0c;GNU Scientific Library (GSL) 是一个备受推崇的工具。它为 C 和 C 程序员提供了丰富的数学函数、数值算法和数据结构&#xff0c;极大地简化了复杂科学计算任务的实现。 GSL 涵盖了众多的数学领域&#xff0c;包括线性代数、数值积分、常…

3.2.2 最短路径 堆优化版Djkstra算法

堆优化版 Dijkstra算法 Dijkstra优化方法&#xff1a; 小根堆存储1号点到可以到达的每个节点的最短路径&#xff0c;直至拓展到n号点 例题 AcWing 850.Dijkstra求最短路 II 题目大意: 给定一个n 个点m 条边的有向图&#xff0c;图中可能存在重边和自环&#xff0c;所有边权…

Linux操作系统之进程信号

进程信号 一、信号1、概念2、系统定义的信号列表3、常见的信号处理方式 二、产生信号的方式1、终端按键&#xff08;1&#xff09;组合键&#xff08;2&#xff09;示例代码&#xff08;3&#xff09;运行结果 2、调用系统函数&#xff08;1&#xff09;kill命令&#xff08;2&…

LCR006:有序数组中两数之和

有序数组中两数之和 给定一个已按照 升序排列 的整数数组 numbers &#xff0c;请你从数组中找出两个数满足相加之和等于目标数 target 。 函数应该以长度为 2 的整数数组的形式返回这两个数的下标值*。*numbers 的下标 从 0 开始计数 &#xff0c;所以答案数组应当满足 0 &l…

1.记:两个List之间不能直接=赋值(Java)

1.两个List之间不能直接赋值,这样数据会同步&#xff0c;数值copy要用addAll(); List<String> list1 new ArrayList<>(); // 填充list1... List<String> list2 list1;这种情况下&#xff0c;list2并不是list1的一个独立副本&#xff0c;而是指向同一个Lis…

Linux OS:基于阻塞队列的生产者消费者模型

Linux OS&#xff1a;基于阻塞队列的生产者消费者模型 前言一、阻塞队列的大致框架二、生产者向阻塞队列中生产数据三、消费者获取阻塞队列中数据四、总体生产和消费思路及测试代码4.1 单生产单消费4.2 多生产多消费 五、所以代码 前言 阻塞队列是一种常用于实现生产者消费者模…

原神自定义倒计时

<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><title>原神倒计时</title><style>* {margin: 0;padding: 0;box-sizing: border-box;user-select: none;body {background: #0b1b2c;}}header {…

【IO】使用有名管道实现,一个进程用于给另一个进程发消息,另一个进程收到消息后,展示到终端上,并且将消息保存到文件上一份

目录 1、使用有名管道实现&#xff0c;一个进程用于给另一个进程发消息&#xff0c;另一个进程收到消息后&#xff0c;展示到终端上&#xff0c;并且将消息保存到文件上一份 2、使用有名管道实现两个进程间相互通信 1、使用有名管道实现&#xff0c;一个进程用于给另一个进程发…

Kubernetes 学习记录

概览 K8S官网文档&#xff1a;https://kubernetes.io/zh/docs/home/ K8S 是Kubernetes的全称&#xff0c;源于希腊语&#xff0c;意为“舵手”或“飞行员”&#xff0c;官方称其是&#xff1a;用于自动部署、扩展和管理“容器化&#xff08;containerized&#xff09;应用程序…

算法--初阶

1、tips 1.1、set求交集 {1,2,3} & {2,3} & {1,2} {2} 其实就是位运算&#xff0c; 只有set可以这样使用&#xff0c; list没有这种用法 {1,2,3} | {2,3, 4} | {1,2} {1, 2, 3, 4} 并集 1.2、*与** * 序列(列表、元组)解包&#xff0c;如果是字典&#xff0c;那…

基于SpringBoot+vue的智能家居控制系统(Java毕业设计)

大家好&#xff0c;我是DeBug&#xff0c;很高兴你能来阅读&#xff01;作为一名热爱编程的程序员&#xff0c;我希望通过这些教学笔记与大家分享我的编程经验和知识。在这里&#xff0c;我将会结合实际项目经验&#xff0c;分享编程技巧、最佳实践以及解决问题的方法。无论你是…

linux开发,问题记录 cc: not found

HOSTCC scripts/basic/fixdep /bin/sh: 1: cc: not found scripts/Makefile.host:99: recipe for target ‘scripts/basic/fixdep’ failed make[1]: *** [scripts/basic/fixdep] Error 127 Makefile:398: recipe for target ‘scripts_basic’ failed make: *** [scripts_basi…

什么情况?我代码没了

前两天检视代码时&#xff0c;发现PR里面有两个提交的描述信息一模一样&#xff0c;于是我提出应该将这两个提交合并成一个&#xff0c;保持提交树的清晰。 1 先储存起来&#xff01; 而同事这时正在开发别的特性&#xff0c;工作区不是干净的&#xff0c;没法直接执行 git r…

CTFHUB-文件上传-无验证

开启题目 1.php 一句话木马内容&#xff1a; <?php eval($_POST[cmd]);?> 上传一句话木马&#xff0c;发现上传成功 蚁剑连接 http://challenge-8b27d18368ecc25c.sandbox.ctfhub.com:10800/upload/1.php 在 “/var/www/html/flag_1791214435.php”发现了 flag

关于JNI的相关面试题

关于JNI&#xff08;Java Native Interface&#xff09;的面试题&#xff0c;可以涵盖多个方面&#xff0c;包括JNI的基本概念、工作原理、使用场景、常见问题及解决方案等。以下是一些可能的JNI面试题及其解答&#xff1a; 1. JNI是什么&#xff1f;它的主要作用是什么&#…

最新CSS3横向菜单的实现

横向菜单 原始代码&#xff1a; <nav class"list1"><ul><li><a href"#">Shirts</a></li><li><a href"#">Pants</a></li><li><a href"#">Dresses</a>…