尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
【办公类-109-12】20260228长方形挂牌卡片(电脑坏了,重制Word可编辑单面 )
背景需求电脑坏了需要重做《长方形挂牌》的模版、代码库根据最新一份长方形挂牌制作【办公类-109-09】20260228挂牌长方形挂牌卡片只有word编辑单面添加有效日期85*54mm横板和54*85mm竖版一页9张https://mp.csdn.net/mp_blog/creation/editor/158264646二、代码库制作把CSDN的代码复制进去修改参数把成果文件夹路径制作把包含所有幼儿信息的xlsx放入添加序号便于排序还需要做一个“横版”模版改名还需要做一个“竖版”模版改名三、模版制作参考这个文档里面的Word模版制作流程【办公类-109-04】20250807托小班新生的卡套长方形挂牌制作Python3.11.5 3285*54mm横板和54*85mm竖版一页9张https://mp.csdn.net/mp_blog/creation/editor/150009366一竖版3*3页边距2和2.4为了让表格能够在画布中间最后一行变成段间距0.7为了防止生成的内容下移到下一页最关键的设置‘’二横板3*3 页边距2和2.35部分中线隐藏为了防止生成的内容下移到下一页最关键的设置模版都做完了。四、运行代码 1.制作20250901托小班长方形卡片横版85*54mm和竖版54*85mm一页9张单面 2.添加姓名拼音显示功能拼音在姓名上方带声调 3.python 3.7.8 3. 横版布局单列显示园区和班级双列显示拼音、姓名和学号 4. 竖版布局单列显示所有信息 5. 添加照片占位符2.5cm宽*3.5cm高黑色框线中间写贴照片 6、生成全部班级或生成指定班级中1-中6班 7、添加日期2026.9-2027.6 豆包,deepseek,阿夏 20260901 # 记录程序开始时间 import time start_time time.time() # 创建照片占位符图片 import os from copy import deepcopy from PIL import Image, ImageDraw, ImageFont import shutil import pandas as pd from pypinyin import pinyin, Style from docx import Document from docx.shared import Cm, Pt from docx.enum.text import WD_PARAGRAPH_ALIGNMENT from docx.oxml.ns import qn from docx.oxml import OxmlElement import glob from docx.oxml.shared import qn as oxml_qn from docx.oxml import parse_xml from docx.enum.text import WD_BREAK from docx.oxml.shared import qn from docx.oxml import parse_xml date2026.9—2027.6 dates202609 schoolXXX幼 def create_photo_placeholder(image_path): 创建照片占位符图片 try: # 确保目录存在 os.makedirs(os.path.dirname(image_path), exist_okTrue) # 设置图片尺寸 (2.5cm x 3.5cm) width, height int(2.5/2.54*300), int(3.5/2.54*300) # 转换为300dpi的像素 # 创建白色背景图片 img Image.new(RGB, (width, height), white) draw ImageDraw.Draw(img) # 绘制黑色边框 draw.rectangle([(10, 10), (width-10, height-10)], outlineblack, width2) # 添加文字 try: # 尝试使用微软雅黑字体 font ImageFont.truetype(msyh.ttc, 20) except: # 如果找不到字体使用默认字体 font ImageFont.load_default() text 贴照片 text_bbox draw.textbbox((0, 0), text, fontfont) text_width text_bbox[2] - text_bbox[0] text_height text_bbox[3] - text_bbox[1] text_x (width - text_width) // 2 text_y (height - text_height) // 2 draw.text((text_x, text_y), text, fillblack, fontfont) # 保存图片 img.save(image_path) print(f已创建照片占位符: {image_path}) return True except Exception as e: print(f创建照片占位符失败: {str(e)}) return False # 读取Excel数据 def read_excel_data(file_path): 读取Excel文件所有工作表数据返回字典{班级名: 数据列表} # 特殊姓氏读音字典 SPECIAL_SURNAMES { 乐: Yuè, 单: Shàn, 解: Xiè, 查: Zhā, 盖: Gě, 仇: Qiú, 种: Chóng, 朴: Piáo, 翟: Zhái, 区: Ōu, 繁: Pó, 覃: Qín, 召: Shào, 华: Huà, 纪: Jǐ, 曾: Zēng, 缪: Miào, 员: Yùn, 车: Chē, 过: Guō, 尉: Yù, 万: Wàn } # 复姓处理字典 COMPOUND_SURNAMES { 欧阳: Ōu yáng, 上官: Shàng guān, 皇甫: Huáng fǔ, 尉迟: Yù chí, 万俟: Mò qí, 长孙: Zhǎng sūn, 司徒: Sī tú, 司空: Sī kōng, 司马: Sī mǎ, 诸葛: Zhū gě, 东方: Dōng fāng, 独孤: Dú gū, 慕容: Mù róng, 宇文: Yǔ wén } def correct_surname_pinyin(name): 校正姓氏拼音处理多音字问题 if not name or not isinstance(name, str) or name.strip() : return name name.strip() # 先检查复姓 for surname in COMPOUND_SURNAMES: if name.startswith(surname): surname_pinyin COMPOUND_SURNAMES[surname] given_name name[2:] given_pinyin .join([p[0] for p in pinyin(given_name, styleStyle.TONE)]) return f{surname_pinyin} {given_pinyin} # 检查单姓 first_char name[0] if first_char in SPECIAL_SURNAMES: surname_pinyin SPECIAL_SURNAMES[first_char] given_name name[1:] given_pinyin .join([p[0] for p in pinyin(given_name, styleStyle.TONE)]) return f{surname_pinyin} {given_pinyin} return .join([p[0] for p in pinyin(name, styleStyle.TONE)]) try: xls pd.ExcelFile(file_path) class_data {} for sheet_name in xls.sheet_names: df pd.read_excel( file_path, sheet_namesheet_name, usecolsrange(5), headerNone, dtype{0: str} ) df df.iloc[1:] data_list [] for index, row in df.iterrows(): row_num index 2 raw_id str(row[0]).strip() if pd.notna(row[0]) else # 如果没有学号但有名字或者有学号但没有名字都创建记录 name str(row[3]).strip() if pd.notna(row[3]) else try: # 处理学号 if raw_id.isdigit(): id_num int(raw_id) formatted_id f{id_num:02d} id_display f{id_num}号 else: # 如果没有学号使用行号作为学号 id_num index 1 formatted_id f{id_num:02d} id_display f{id_num}号 campus str(row[1]).strip() if pd.notna(row[1]) else class_name str(row[2]).strip() if pd.notna(row[2]) else gender str(row[4]).strip() if pd.notna(row[4]) else # 如果没有名字使用张三 if not name: name 张三 name_pinyin correct_surname_pinyin(name) data_list.append({ id_display: id_display, id_file: formatted_id, campus: campus, name: name, name_pinyin: name_pinyin, class_name: class_name, gender: gender }) except Exception as e: print(f处理第{row_num}行数据时出错: {str(e)}) continue if data_list: class_data[sheet_name] data_list return class_data except Exception as e: print(f读取Excel文件失败{str(e)}) return {} def expand_students_to_target_count(students, class_name): 将学生列表扩展到目标人数托小班27人中大班36人 # 确定目标人数 if 托 in class_name : target_count 27 elif 小 in class_name: target_count 27 elif 中 in class_name: target_count 36 else: target_count 36 # 如果实际人数已经达到或超过目标人数直接返回实际人数 if len(students) target_count: return students[:target_count] # 扩展学生列表 expanded_students students.copy() # 获取第一个学生的园区和班级信息用于填充空白学生 if students: base_campus students[0][campus] base_class students[0][class_name] else: base_campus base_class class_name # 添加空白学生 for i in range(len(students), target_count): empty_student { id_display: f{i1}号, id_file: f{i1:02d}, campus: base_campus, name: 张三, name_pinyin: Zhāng Sān, class_name: base_class, gender: } expanded_students.append(empty_student) return expanded_students def create_word_documents(class_data, orientation, temp_dir, photo_path): 创建Word文档横版或竖版 if orientation 横版: return create_horizontal_documents(class_data, temp_dir, photo_path) else: return create_vertical_documents(class_data, temp_dir, photo_path) def create_horizontal_documents(class_data, temp_dir, photo_path): 创建横版Word文档 # 模板文件路径 template_path os.path.join(path, 00 长方形挂牌_横版.docx) # 字体设置 font_name 微软雅黑 line_spacing_multiplier 1 for class_name, students in class_data.items(): # 按9人一组分组 groups [students[i:i9] for i in range(0, len(students), 9)] for group_num, group in enumerate(groups, 1): # 复制模板文件 file_name f{class_name}_横版_{group_num:02d}.docx file_path os.path.join(temp_dir, file_name) shutil.copy(template_path, file_path) # 打开文档 doc Document(file_path) if len(doc.tables) 0: print(f警告: {file_path} 中没有找到表格) continue table doc.tables[0] # 填充数据 for i, student in enumerate(group): row i // 3 col_pair i % 3 double_col 1 (col_pair * 2) single_col col_pair * 2 # 单列单元格园区和班级 single_cell table.cell(row, single_col) single_cell._element.clear_content() # 先插入照片 p_photo single_cell.add_paragraph() p_photo.alignment WD_PARAGRAPH_ALIGNMENT.CENTER try: run p_photo.add_run() run.add_picture(photo_path, widthCm(2.5), heightCm(3.5)) except Exception as e: print(f插入照片失败: {str(e)}) # 如果插入照片失败添加文字提示 run p_photo.add_run([照片占位符]) run.font.name font_name run._element.rPr.rFonts.set(qn(w:eastAsia), font_name) run.font.size Pt(10) # 然后添加园区和班级信息 # 然后添加园区和班级信息 p_info single_cell.add_paragraph() p_info.alignment WD_PARAGRAPH_ALIGNMENT.CENTER p_pr p_info._element.get_or_add_pPr() spacing OxmlElement(w:spacing) spacing.set(qn(w:lineRule), auto) spacing.set(qn(w:line), str(int(240 * line_spacing_multiplier))) spacing.set(qn(w:before), 0) spacing.set(qn(w:after), 0) p_pr.append(spacing) # 学校园区 run p_info.add_run(f{school} {student[campus]}\n) run.font.name font_name run._element.rPr.rFonts.set(qn(w:eastAsia), font_name) run.font.size Pt(15) run.font.bold False # 日期 run p_info.add_run(f有效期{date}) run.font.name font_name run._element.rPr.rFonts.set(qn(w:eastAsia), font_name) run.font.size Pt(10) # 小5 run.font.bold False # 双列单元格拼音、姓名和学号 double_cell table.cell(row, double_col) double_cell._element.clear_content() p_double double_cell.add_paragraph() p_double.alignment WD_PARAGRAPH_ALIGNMENT.CENTER p_pr p_double._element.get_or_add_pPr() spacing OxmlElement(w:spacing) spacing.set(qn(w:lineRule), auto) spacing.set(qn(w:line), str(int(240 * line_spacing_multiplier))) spacing.set(qn(w:before), 0) spacing.set(qn(w:after), 0) p_pr.append(spacing) run p_double.add_run(f{student[class_name]}\n) run.font.name font_name run._element.rPr.rFonts.set(qn(w:eastAsia), font_name) run.font.size Pt(20) run.font.bold True # 如果是多音字在拼音后面添加序号标识 pinyin_text student[name_pinyin] # if student[pinyin_total] 1: # # pinyin_text f ({student[pinyin_index]}/{student[pinyin_total]}) # pinyin_text f ({student[pinyin_index]}) run p_double.add_run(f{pinyin_text}\n) run.font.name font_name run._element.rPr.rFonts.set(qn(w:eastAsia), font_name) run.font.size Pt(12) run.font.bold False run p_double.add_run(f{student[name]}\n) run.font.name font_name run._element.rPr.rFonts.set(qn(w:eastAsia), font_name) run.font.size Pt(25) run.font.bold True run p_double.add_run(f{student[id_display]}) run.font.name font_name run._element.rPr.rFonts.set(qn(w:eastAsia), font_name) run.font.size Pt(20) run.font.bold True doc.save(file_path) print(f已创建横版: {file_path}) return temp_dir def create_vertical_documents(class_data, temp_dir, photo_path): 创建竖版Word文档 # 模板文件路径 template_path os.path.join(path, 00 长方形挂牌_竖版.docx) # 字体设置 font_name 微软雅黑 line_spacing_multiplier 1 for class_name, students in class_data.items(): # 按9人一组分组 groups [students[i:i9] for i in range(0, len(students), 9)] for group_num, group in enumerate(groups, 1): # 复制模板文件 file_name f{class_name}_竖版_{group_num:02d}.docx file_path os.path.join(temp_dir, file_name) shutil.copy(template_path, file_path) # 打开文档 doc Document(file_path) if len(doc.tables) 0: print(f警告: {file_path} 中没有找到表格) continue table doc.tables[0] # 填充数据 for i, student in enumerate(group): row i // 3 col i % 3 cell table.cell(row, col) cell._element.clear_content() # 添加学校园区信息 p_campus cell.add_paragraph() p_campus.alignment WD_PARAGRAPH_ALIGNMENT.CENTER # 设置行距 p_pr p_campus._element.get_or_add_pPr() spacing OxmlElement(w:spacing) spacing.set(qn(w:lineRule), auto) spacing.set(qn(w:line), str(int(240 * line_spacing_multiplier))) spacing.set(qn(w:before), 0) spacing.set(qn(w:after), 0) p_pr.append(spacing) # 学校园区 run p_campus.add_run(f{school} {student[campus]}) run.font.name font_name run._element.rPr.rFonts.set(qn(w:eastAsia), font_name) run.font.size Pt(15) run.font.bold False # 插入照片 p_photo cell.add_paragraph() p_photo.alignment WD_PARAGRAPH_ALIGNMENT.CENTER try: run p_photo.add_run() run.add_picture(photo_path, widthCm(2.5), heightCm(3.5)) except Exception as e: print(f插入照片失败: {str(e)}) # 如果插入照片失败添加文字提示 run p_photo.add_run([照片占位符]) run.font.name font_name run._element.rPr.rFonts.set(qn(w:eastAsia), font_name) run.font.size Pt(10) # 添加其他信息 p_info cell.add_paragraph() p_info.alignment WD_PARAGRAPH_ALIGNMENT.CENTER # 设置行距 p_pr p_info._element.get_or_add_pPr() spacing OxmlElement(w:spacing) spacing.set(qn(w:lineRule), auto) spacing.set(qn(w:line), str(int(240 * line_spacing_multiplier))) spacing.set(qn(w:before), 0) spacing.set(qn(w:after), 0) p_pr.append(spacing) # 班级和学号一行 run p_info.add_run(f{student[class_name]}_) run.font.name font_name run._element.rPr.rFonts.set(qn(w:eastAsia), font_name) run.font.size Pt(20) run.font.bold True run p_info.add_run(f{student[id_display]}\n) run.font.name font_name run._element.rPr.rFonts.set(qn(w:eastAsia), font_name) run.font.size Pt(20) run.font.bold True # 拼音 run p_info.add_run(f{student[name_pinyin]}\n) run.font.name font_name run._element.rPr.rFonts.set(qn(w:eastAsia), font_name) run.font.size Pt(12) run.font.bold False # 姓名 run p_info.add_run(f{student[name]}\n) run.font.name font_name run._element.rPr.rFonts.set(qn(w:eastAsia), font_name) run.font.size Pt(25) run.font.bold True # 日期 run p_info.add_run(f有效期{date}) run.font.name font_name run._element.rPr.rFonts.set(qn(w:eastAsia), font_name) run.font.size Pt(10) run.font.bold False doc.save(file_path) print(f已创建竖版: {file_path}) return temp_dir def merge_word_documents(temp_dir, output_dir, orientation): 将同一班级的Word文档合并为一个Word文件 - 使用复制粘贴方法 # 获取所有Word文件并按班级分组 word_files glob.glob(os.path.join(temp_dir, f*_{orientation}_*.docx)) class_files {} for word_file in word_files: filename os.path.basename(word_file) class_name filename.split(_)[0] if class_name not in class_files: class_files[class_name] [] class_files[class_name].append(word_file) # 确保输出目录存在 os.makedirs(output_dir, exist_okTrue) for class_name, files in class_files.items(): files.sort() if not files: continue # 使用第一个文档作为基础 base_doc Document(files[0]) # 添加剩余文档的内容 for i in range(1, len(files)): source_doc Document(files[i]) # # 添加分页符 # base_doc.add_page_break() # 复制所有段落和表格 for element in source_doc.element.body: base_doc.element.body.append(deepcopy(element)) # 保存合并后的文档 output_file os.path.join(output_dir, f03_{dates}_{orientation}_长方形挂牌_word可编辑_{class_name}.docx) base_doc.save(output_file) print(f已合并{orientation}版Word: {output_file}) return output_dir def cleanup(temp_dir): 清理临时文件 try: shutil.rmtree(temp_dir) print(f已清理临时文件夹: {temp_dir}) except Exception as e: print(f清理临时文件夹失败: {str(e)}) # 主程序 if __name__ __main__: # 指定Excel文件路径 path rD:\Python最终内容\20260901长方形挂牌 excel_file os.path.join(path, 01 20260805班级信息表.xlsx) # # 指定要生成的班级列表中1班到中6班 # target_classes [中1班, 中2班, 中3班, 中4班, 中5班, 中6班] # 获取所有工作表名称排除第一个 try: xls pd.ExcelFile(excel_file) all_sheets xls.sheet_names # 排除第一个工作表通常是封面或说明本次就是从第一张表开始 if len(all_sheets) 1: target_classes all_sheets[0:] # 【1】从第二个工作表开始取所有 print(f将处理以下工作表: {target_classes}) else: print(错误: Excel文件中没有足够的工作表) exit(1) except Exception as e: print(f读取Excel文件失败: {str(e)}) exit(1) # 创建照片占位符 photo_path os.path.join(path, photo_placeholder.png) create_photo_placeholder(photo_path) # 创建临时目录 temp_dir os.path.join(path, 零时文件夹) os.makedirs(temp_dir, exist_okTrue) # 处理横版和竖版 orientations [横版, 竖版] for orientation in orientations: if orientation 横版: output_dir os.path.join(path, f{dates}_托小中大班新生_横版_卡片_可编辑) else: output_dir os.path.join(path, f{dates}_托小中大班新生_竖版_卡片_可编辑) # 确保输出目录存在 os.makedirs(output_dir, exist_okTrue) print(f当前处理方向: {orientation}, 输出目录: {output_dir}) # 调用读取函数 all_class_data read_excel_data(excel_file) if all_class_data: # 如果指定了target_classes则只处理这些班级否则处理所有班级 if target_classes in locals() and target_classes: class_data {} for class_name in target_classes: if class_name in all_class_data: class_data[class_name] all_class_data[class_name] print(f找到班级: {class_name}, 共{len(all_class_data[class_name])}人) else: print(f警告: 班级 {class_name} 在Excel文件中未找到) else: # 处理所有班级 class_data all_class_data print(f将处理所有{len(class_data)}个班级) if class_data: # 扩展学生到目标人数 expanded_class_data {} for class_name, students in class_data.items(): expanded_students expand_students_to_target_count(students, class_name) expanded_class_data[class_name] expanded_students # 创建Word文档使用扩展后的数据 temp_dir create_word_documents(expanded_class_data, orientation, temp_dir, photo_path) # 合并同一班级的Word文档 output_dir merge_word_documents(temp_dir, output_dir, orientation) # 打印汇总信息 print(\n处理完成汇总信息:) for class_name, students in class_data.items(): # 显示原始人数和扩展后人数 expanded_students expand_students_to_target_count(students, class_name) group_count (len(expanded_students) // 9 (1 if len(expanded_students) % 9 ! 0 else 0)) print(f{class_name}: 原始{len(students)}人 - 扩展到{len(expanded_students)}人分成{group_count}个文档) else: print(没有找到任何班级的数据) else: print(未能读取到任何班级数据请检查文件路径和内容格式。) # 清理临时文件 cleanup(temp_dir) # 计算并显示运行时间 end_time time.time() total_seconds end_time - start_time minutes int(total_seconds // 60) seconds int(total_seconds % 60) print(f\n程序运行时间: {minutes}分{seconds}秒 (共{total_seconds:.2f}秒))五、感悟这个横版和竖版的docx模版设计起来好麻烦各种小细节要调整才能保证最后的表格3*3都能显示在A4一页内。所以必须把Word模版上传CSDN“资源绑定”做备份
RELATED

相关推荐

长安凯程F70设计解析:硬朗风格如何体现商用皮卡的功能与美学

长安凯程F70设计解析:硬朗风格如何体现商用皮卡的功能与美学

1. 从一张官图开始:如何解读一款商用皮卡的“硬朗”设计 看到“长安凯程F70官图发布”这个标题,可能很多朋友第一反应是:哦,又一款皮卡。但如果你仔细琢磨“设计风格硬朗”这个前缀,再结合当下皮卡市场从纯工具车向“宜…

📅 2026/10/21 13:49:59
AVL树原理与实现:解决二叉搜索树性能退化问题

AVL树原理与实现:解决二叉搜索树性能退化问题

1. 为什么你的二叉搜索树不够快? 第一次用二叉搜索树处理十万级数据时,我也被那肉眼可见的延迟震惊了——简单的查找操作竟然需要近1秒!这和我认知中O(log n)的时间复杂度完全不符。问题出在树的结构上:当插入顺序是10、20、30、4…

📅 2026/9/8 16:38:01
QUICK:GPU 加速的 ab initio / DFT 开源量子化学包—原理、安装实测与横向对比

QUICK:GPU 加速的 ab initio / DFT 开源量子化学包—原理、安装实测与横向对比

QUICK 是 UCSD Gtz Lab 与 Michigan State Merz Lab 联合开发的开源量子化学包,主打 GPU-native HF / DFT 计算、MPI 多卡扩展、内置 QM/MM 接口(与 AmberTools 26 直接集成)。专注于 HF/DFT 计算、几何优化、RESP 电荷和 QM/MM 模拟。最新版本 QUICK-26.03(2026-07-25)已…

📅 2026/10/8 11:48:46
MORE NEWS

更多资讯

📰

PyTorch线性回归实战:从数据构造到训练闭环

1. 线性回归在深度学习里的位置,以及为什么选它练手很多人刚开始接触 PyTorch,容易被各种名词劝退:反向传播、优化器、损失函数、张量……每一个听起来都像一座山。但如果你真正跑通一个线性回归模型,回头再看这些概念&#xff0c…

📰

REA分析框架:识别、评估、执行三步法提升效率

1. 从“rea”这个标题说起:一个被低估的缩写背后藏着什么 第一次看到“rea”这三个字母,大多数人脑子里蹦出来的第一反应可能是“real”的简写,或者是某个品牌、某个项目的代号。我在几个技术社区和效率工具圈子里泡了挺长时间,发…

📰

AI Agent记忆持久化实战:FileSystem中间件如何实现跨会话状态恢复

做AI Agent开发的朋友,一定都遇到过这个场景:对话窗口一关,agent就“失忆”了。刚才聊了一半的需求、已经确认好的用户偏好、写到一半的分析流程,界面一刷新全没了。这个问题在LangChain生态里,尤其是用到DeepAgents这…

📰

数据安全与隐私保护:探索合规数据工具与实践

简介:社工库(社会工程学数据库)源码包,定位为网络安全研究、Web开发学习与数据检索系统分析的教育性资料,适合安全工程师、PHP开发者及对搜索引擎实现感兴趣的学习者。压缩包共27个文件,核心以9个PHP脚本构…

📰

AI知识库实战:从材料筛选到提问,打造高质量个人知识底座

你是不是也遇到过这种情况:收藏夹里一堆文章、资料越积越多,真到要用的时候翻半天找不到,找到了也懒得看完,最后全在收藏夹吃灰。我前几个月被一个跨领域项目折腾得够呛,手头几十份文档、规范、报告来回切换&#xff0…

📰

Flutter for OpenHarmony表单验证实战:二手置换App开发踩坑与模块化设计

在把某二手物品置换App从原型推到可用版本的过程中,我反复打磨最多的一块,不是图片上传、不是消息推送,反而是很多人觉得“随便写写就行”的表单验证。Flutter for OpenHarmony这套组合本身就有一些环境上的特殊问题,再加上二手置…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬