Excel批量插图工具源码[python]
- 2026-11-11 06:01:10
Excel批量插图工具源码[python]
列匹配模式: 行匹配模式:

主要功能
1. 两种匹配模式
按垂直方向匹配(列对列) 适合单列数据匹配场景 参数:待匹配列、插入列、边距、图片文件夹
按水平方向匹配(行对行) 适合单行数据匹配场景 参数:待匹配行、插入行、边距、图片文件夹
2. 工作原理
扫描指定的图片文件夹,提取文件名 在Excel中查找与图片文件名匹配的单元格内容 将匹配的图片插入到指定位置 支持多种图片格式(jpg/png/webp/bmp) """Excel批量插图-匹配表格内容需要库:pip install xlwings PyQt6"""import osimport reimport webbrowserfrom typing import Dictimport xlwings as xwfrom PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,QLabel, QPushButton, QLineEdit, QTabWidget, QTextEdit,QFileDialog, QMessageBox, QCheckBox)from PyQt6.QtGui import QFont, QColorfrom PyQt6.QtCore import Qtclass ExcelImageMatcherPro(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("Excel批量插图-匹配表格内容")self.resize(600, 700)self.col_image_map: Dict[str, str] = {}self.row_image_map: Dict[str, str] = {}# 创建主窗口self.central_widget = QWidget()self.setCentralWidget(self.central_widget)# 主布局self.main_layout = QVBoxLayout(self.central_widget)self.main_layout.setContentsMargins(20, 20, 20, 20)self.main_layout.setSpacing(20)# 创建标题栏self.create_title_bar()# 创建标签页self.create_tab_widget()# 创建状态栏self.create_status_bar()# 窗口居中self.center_window()# 显示帮助信息self.show_help_guide()# 设置窗口置顶self.setWindowFlags(self.windowFlags() | Qt.WindowType.WindowStaysOnTopHint)def create_title_bar(self):"""创建标题栏"""title_frame = QWidget()title_frame.setStyleSheet("""QWidget {background: qlineargradient(x1:0, y1:0, x2:1, y2:0,stop:0 #4CAF50, stop:1 #45a049);border-radius: 10px;}""")title_layout = QVBoxLayout(title_frame)title_layout.setContentsMargins(30, 20, 30, 20)title_label = QLabel("Excel批量插图-匹配表格内容")title_label.setFont(QFont("Microsoft YaHei", 14, QFont.Weight.Bold))title_label.setStyleSheet("color: white;")title_layout.addWidget(title_label)self.main_layout.addWidget(title_frame)def create_tab_widget(self):"""创建标签页"""self.tab_widget = QTabWidget()self.tab_widget.setStyleSheet("""QTabWidget {background: transparent;}QTabBar {background: #f5f5f5;border-radius: 8px;margin-bottom: 10px;}QTabBar::tab {background: white;color: #666666;padding: 12px 25px;margin: 5px;border-radius: 6px;font: 10pt 'Microsoft YaHei';font-weight: bold;}QTabBar::tab:selected {background: #4CAF50;color: white;}QTabBar::tab:hover:!selected {background: #f0f0f0;}""")# 创建列匹配标签页self.create_column_tab()# 创建行匹配标签页self.create_row_tab()self.main_layout.addWidget(self.tab_widget)def create_column_tab(self):"""创建列匹配标签页"""tab = QWidget()self.tab_widget.addTab(tab, "列匹配模式")tab_layout = QVBoxLayout(tab)tab_layout.setContentsMargins(0, 0, 0, 0)tab_layout.setSpacing(15)# 描述desc_label = QLabel("列匹配模式:按垂直方向匹配插入,适合单列数据匹配。")desc_label.setStyleSheet("color: #666666; font: 9pt 'Microsoft YaHei';")tab_layout.addWidget(desc_label)# 参数卡片param_card = QWidget()param_card.setStyleSheet("""QWidget {background: white;border-radius: 10px;border: 1px solid #e0e0e0;}""")param_layout = QVBoxLayout(param_card)param_layout.setContentsMargins(20, 20, 20, 20)param_layout.setSpacing(15)# 参数标题param_title = QLabel("列匹配参数")param_title.setFont(QFont("Microsoft YaHei", 11, QFont.Weight.Bold))param_title.setStyleSheet("color: #4CAF50;")param_layout.addWidget(param_title)# 参数输入input_layout = QHBoxLayout()input_layout.setSpacing(20)# 待匹配列match_col_layout = QVBoxLayout()match_col_label = QLabel("待匹配列:")match_col_label.setStyleSheet("color: #333333; font: 9pt 'Microsoft YaHei';")self.col_match = QLineEdit()self.col_match.setText("A")self.col_match.setStyleSheet("""QLineEdit {padding: 8px;border: 1px solid #e0e0e0;border-radius: 6px;font: 9pt 'Microsoft YaHei';background: #fafafa;}QLineEdit:focus {border: 1px solid #4CAF50;background: white;}""")self.col_match.setFixedWidth(80)match_col_layout.addWidget(match_col_label)match_col_layout.addWidget(self.col_match)input_layout.addLayout(match_col_layout)# 插入列insert_col_layout = QVBoxLayout()insert_col_label = QLabel("插入列:")insert_col_label.setStyleSheet("color: #333333; font: 9pt 'Microsoft YaHei';")self.col_insert = QLineEdit()self.col_insert.setText("B")self.col_insert.setStyleSheet("""QLineEdit {padding: 8px;border: 1px solid #e0e0e0;border-radius: 6px;font: 9pt 'Microsoft YaHei';background: #fafafa;}QLineEdit:focus {border: 1px solid #4CAF50;background: white;}""")self.col_insert.setFixedWidth(80)insert_col_layout.addWidget(insert_col_label)insert_col_layout.addWidget(self.col_insert)input_layout.addLayout(insert_col_layout)# 边距margin_layout = QVBoxLayout()margin_label = QLabel("边距:")margin_label.setStyleSheet("color: #333333; font: 9pt 'Microsoft YaHei';")self.col_margin = QLineEdit()self.col_margin.setText("2")self.col_margin.setStyleSheet("""QLineEdit {padding: 8px;border: 1px solid #e0e0e0;border-radius: 6px;font: 9pt 'Microsoft YaHei';background: #fafafa;}QLineEdit:focus {border: 1px solid #4CAF50;background: white;}""")self.col_margin.setFixedWidth(80)margin_layout.addWidget(margin_label)margin_layout.addWidget(self.col_margin)input_layout.addLayout(margin_layout)param_layout.addLayout(input_layout)# 文件夹选择folder_layout = QHBoxLayout()folder_label = QLabel("图片文件夹:")folder_label.setStyleSheet("color: #333333; font: 9pt 'Microsoft YaHei';")folder_label.setFixedWidth(80)self.col_folder_var = QLineEdit()self.col_folder_var.setReadOnly(True)self.col_folder_var.setStyleSheet("""QLineEdit {padding: 8px;border: 1px solid #e0e0e0;border-radius: 6px;font: 9pt 'Microsoft YaHei';background: #fafafa;color: #666666;}""")browse_btn = QPushButton("浏览...")browse_btn.setStyleSheet("""QPushButton {background: #4CAF50;color: white;padding: 8px 16px;border: none;border-radius: 6px;font: 9pt 'Microsoft YaHei';}QPushButton:hover {background: #45a049;}""")browse_btn.clicked.connect(lambda: self.select_folder("column"))folder_layout.addWidget(folder_label)folder_layout.addWidget(self.col_folder_var)folder_layout.addWidget(browse_btn)param_layout.addLayout(folder_layout)tab_layout.addWidget(param_card)# 执行按钮execute_btn = QPushButton("执行列匹配插入")execute_btn.setStyleSheet("""QPushButton {background: #4CAF50;color: white;padding: 12px;border: none;border-radius: 8px;font: 10pt 'Microsoft YaHei';font-weight: bold;}QPushButton:hover {background: #45a049;}""")execute_btn.clicked.connect(self.run_column_match)tab_layout.addWidget(execute_btn)# 日志卡片log_card = QWidget()log_card.setStyleSheet("""QWidget {background: white;border-radius: 10px;border: 1px solid #e0e0e0;}""")log_layout = QVBoxLayout(log_card)log_layout.setContentsMargins(20, 20, 20, 20)# 日志标题log_title = QLabel("操作日志")log_title.setFont(QFont("Microsoft YaHei", 11, QFont.Weight.Bold))log_title.setStyleSheet("color: #4CAF50;")log_layout.addWidget(log_title)# 日志文本框self.col_log = QTextEdit()self.col_log.setReadOnly(True)self.col_log.setStyleSheet("""QTextEdit {background: #fafafa;border: 1px solid #e0e0e0;border-radius: 6px;padding: 10px;font: 9pt 'Microsoft YaHei';color: #333333;}""")self.col_log.setMinimumHeight(200)log_layout.addWidget(self.col_log)tab_layout.addWidget(log_card)def create_row_tab(self):"""创建行匹配标签页"""tab = QWidget()self.tab_widget.addTab(tab, "行匹配模式")tab_layout = QVBoxLayout(tab)tab_layout.setContentsMargins(0, 0, 0, 0)tab_layout.setSpacing(15)# 描述desc_label = QLabel("行匹配模式:按水平方向匹配插入,适合单行数据匹配。")desc_label.setStyleSheet("color: #666666; font: 9pt 'Microsoft YaHei';")tab_layout.addWidget(desc_label)# 参数卡片param_card = QWidget()param_card.setStyleSheet("""QWidget {background: white;border-radius: 10px;border: 1px solid #e0e0e0;}""")param_layout = QVBoxLayout(param_card)param_layout.setContentsMargins(20, 20, 20, 20)param_layout.setSpacing(15)# 参数标题param_title = QLabel("行匹配参数")param_title.setFont(QFont("Microsoft YaHei", 11, QFont.Weight.Bold))param_title.setStyleSheet("color: #4CAF50;")param_layout.addWidget(param_title)# 参数输入input_layout = QHBoxLayout()input_layout.setSpacing(20)# 待匹配行match_row_layout = QVBoxLayout()match_row_label = QLabel("待匹配行:")match_row_label.setStyleSheet("color: #333333; font: 9pt 'Microsoft YaHei';")self.row_match = QLineEdit()self.row_match.setText("1")self.row_match.setStyleSheet("""QLineEdit {padding: 8px;border: 1px solid #e0e0e0;border-radius: 6px;font: 9pt 'Microsoft YaHei';background: #fafafa;}QLineEdit:focus {border: 1px solid #4CAF50;background: white;}""")self.row_match.setFixedWidth(80)match_row_layout.addWidget(match_row_label)match_row_layout.addWidget(self.row_match)input_layout.addLayout(match_row_layout)# 插入行insert_row_layout = QVBoxLayout()insert_row_label = QLabel("插入行:")insert_row_label.setStyleSheet("color: #333333; font: 9pt 'Microsoft YaHei';")self.row_insert = QLineEdit()self.row_insert.setText("2")self.row_insert.setStyleSheet("""QLineEdit {padding: 8px;border: 1px solid #e0e0e0;border-radius: 6px;font: 9pt 'Microsoft YaHei';background: #fafafa;}QLineEdit:focus {border: 1px solid #4CAF50;background: white;}""")self.row_insert.setFixedWidth(80)insert_row_layout.addWidget(insert_row_label)insert_row_layout.addWidget(self.row_insert)input_layout.addLayout(insert_row_layout)# 边距margin_layout = QVBoxLayout()margin_label = QLabel("边距:")margin_label.setStyleSheet("color: #333333; font: 9pt 'Microsoft YaHei';")self.row_margin = QLineEdit()self.row_margin.setText("2")self.row_margin.setStyleSheet("""QLineEdit {padding: 8px;border: 1px solid #e0e0e0;border-radius: 6px;font: 9pt 'Microsoft YaHei';background: #fafafa;}QLineEdit:focus {border: 1px solid #4CAF50;background: white;}""")self.row_margin.setFixedWidth(80)margin_layout.addWidget(margin_label)margin_layout.addWidget(self.row_margin)input_layout.addLayout(margin_layout)param_layout.addLayout(input_layout)# 文件夹选择folder_layout = QHBoxLayout()folder_label = QLabel("图片文件夹:")folder_label.setStyleSheet("color: #333333; font: 9pt 'Microsoft YaHei';")folder_label.setFixedWidth(80)self.row_folder_var = QLineEdit()self.row_folder_var.setReadOnly(True)self.row_folder_var.setStyleSheet("""QLineEdit {padding: 8px;border: 1px solid #e0e0e0;border-radius: 6px;font: 9pt 'Microsoft YaHei';background: #fafafa;color: #666666;}""")browse_btn = QPushButton("浏览...")browse_btn.setStyleSheet("""QPushButton {background: #4CAF50;color: white;padding: 8px 16px;border: none;border-radius: 6px;font: 9pt 'Microsoft YaHei';}QPushButton:hover {background: #45a049;}""")browse_btn.clicked.connect(lambda: self.select_folder("row"))folder_layout.addWidget(folder_label)folder_layout.addWidget(self.row_folder_var)folder_layout.addWidget(browse_btn)param_layout.addLayout(folder_layout)tab_layout.addWidget(param_card)# 执行按钮execute_btn = QPushButton("执行行匹配插入")execute_btn.setStyleSheet("""QPushButton {background: #4CAF50;color: white;padding: 12px;border: none;border-radius: 8px;font: 10pt 'Microsoft YaHei';font-weight: bold;}QPushButton:hover {background: #45a049;}""")execute_btn.clicked.connect(self.run_row_match)tab_layout.addWidget(execute_btn)# 日志卡片log_card = QWidget()log_card.setStyleSheet("""QWidget {background: white;border-radius: 10px;border: 1px solid #e0e0e0;}""")log_layout = QVBoxLayout(log_card)log_layout.setContentsMargins(20, 20, 20, 20)# 日志标题log_title = QLabel("操作日志")log_title.setFont(QFont("Microsoft YaHei", 11, QFont.Weight.Bold))log_title.setStyleSheet("color: #4CAF50;")log_layout.addWidget(log_title)# 日志文本框self.row_log = QTextEdit()self.row_log.setReadOnly(True)self.row_log.setStyleSheet("""QTextEdit {background: #fafafa;border: 1px solid #e0e0e0;border-radius: 6px;padding: 10px;font: 9pt 'Microsoft YaHei';color: #333333;}""")self.row_log.setMinimumHeight(200)log_layout.addWidget(self.row_log)tab_layout.addWidget(log_card)def create_status_bar(self):"""创建状态栏"""status_frame = QWidget()status_layout = QHBoxLayout(status_frame)status_layout.setContentsMargins(0, 0, 0, 0)status_layout.setSpacing(20)# 左侧按钮left_layout = QHBoxLayout()left_layout.setSpacing(15)# 窗口置顶self.topmost_check = QCheckBox("窗口置顶")self.topmost_check.setChecked(True)self.topmost_check.setStyleSheet("""QCheckBox {color: #666666;font: 9pt 'Microsoft YaHei';}""")self.topmost_check.stateChanged.connect(self.toggle_topmost)left_layout.addWidget(self.topmost_check)# 帮助按钮help_btn = QPushButton("帮助")help_btn.setStyleSheet("""QPushButton {background: #f0f0f0;color: #666666;padding: 6px 12px;border: none;border-radius: 4px;font: 9pt 'Microsoft YaHei';}QPushButton:hover {background: #e0e0e0;}""")help_btn.clicked.connect(self.show_help_guide)left_layout.addWidget(help_btn)# 右侧作者信息author_label = QLabel("By Savetime2022")author_label.setStyleSheet("""QLabel {color: #999999;font: 9pt 'Microsoft YaHei';}QLabel:hover {color: #4CAF50;}""")author_label.setCursor(Qt.CursorShape.PointingHandCursor)status_layout.addLayout(left_layout)status_layout.addStretch()status_layout.addWidget(author_label)self.main_layout.addWidget(status_frame)def toggle_topmost(self, state):"""切换窗口置顶状态"""if state == 2: # Qt.Checkedself.setWindowFlags(self.windowFlags() | Qt.WindowType.WindowStaysOnTopHint)else:self.setWindowFlags(self.windowFlags() & ~Qt.WindowType.WindowStaysOnTopHint)self.show()def center_window(self):"""窗口居中"""screen = QApplication.primaryScreen().geometry()size = self.geometry()self.move((screen.width() - size.width()) // 2,(screen.height() - size.height()) // 2)def show_help_guide(self):"""显示帮助信息"""help_text = """【新手操作指南】1. 准备工作:- 打开Excel文件- 准备图片文件夹(支持jpg/png/webp/bmp格式)2. 参数设置:- 匹配列/行:包含名称的列或行(如A列或1行)- 插入列/行:图片要插入的位置(如B列或2行)- 边距:图片与单元格边界的距离(推荐2,0表示撑满)3. 执行步骤:(1) 选择图片文件夹(2) 点击"执行匹配插入"按钮★ 注意事项:- 图片名称需与单元格内容完全一致(不区分大小写)- 示例:单元格"产品A" → 图片"产品A.jpg"- 插入过程中请不要操作Excel"""current_tab = self.tab_widget.currentIndex()if current_tab == 0:self.col_log.setPlainText(help_text)else:self.row_log.setPlainText(help_text)def select_folder(self, mode):"""选择图片文件夹"""folder_path = QFileDialog.getExistingDirectory(self, "选择图片文件夹", ".")if folder_path:if mode == "column":self.col_folder_var.setText(folder_path)log_widget = self.col_logself.col_image_map = self.build_image_map_from_folder(folder_path)else:self.row_folder_var.setText(folder_path)log_widget = self.row_logself.row_image_map = self.build_image_map_from_folder(folder_path)self.log_message("开始加载图片...", log_widget)image_count = len(self.col_image_map if mode == "column" else self.row_image_map)self.log_message(f"加载完成:找到 {image_count} 张支持的图片。", log_widget)self.preview_insert_positions(mode)def build_image_map_from_folder(self, folder_path: str) -> Dict[str, str]:"""构建图片名称到路径的映射"""image_map: Dict[str, str] = {}extensions = ('.jpg', '.jpeg', '.png', '.bmp', '.webp')try:for root, _, files in os.walk(folder_path):for file in files:if file.lower().endswith(extensions):name_without_ext = os.path.splitext(file)[0].strip().lower()image_map[name_without_ext] = os.path.abspath(os.path.join(root, file))except Exception as e:self.log_message(f"构建图片映射出错: {e}", self.col_log)return image_mapdef validate_column_params(self) -> Dict:"""验证列模式参数有效性"""params = {'match_col': self.col_match.text().upper(),'insert_col': self.col_insert.text().upper(),'margin': self.col_margin.text()}if not re.match(r'^[A-Z]{1,3}$', params['match_col']):raise ValueError("匹配列格式错误 (例如: A, B, AA)")if not re.match(r'^[A-Z]{1,3}$', params['insert_col']):raise ValueError("插入列格式错误 (例如: A, B, AA)")if not params['margin'].isdigit() or int(params['margin']) < 0:raise ValueError("边距必须是非负数字")return {'match_col': params['match_col'],'insert_col': params['insert_col'],'start_row': 2,'margin': int(params['margin'])}def validate_row_params(self) -> Dict:"""验证行模式参数有效性"""params = {'match_row': self.row_match.text(),'insert_row': self.row_insert.text(),'margin': self.row_margin.text()}if not params['match_row'].isdigit() or int(params['match_row']) < 1:raise ValueError("匹配行必须是大于0的数字")if not params['insert_row'].isdigit() or int(params['insert_row']) < 1:raise ValueError("插入行必须是大于0的数字")if not params['margin'].isdigit() or int(params['margin']) < 0:raise ValueError("边距必须是非负数字")return {'match_row': int(params['match_row']),'insert_row': int(params['insert_row']),'margin': int(params['margin'])}def excel_operation(self, app):"""Excel操作上下文管理器"""class ExcelOperation:def __init__(self, app):self.app = appself.wb = Noneself.ws = Nonedef __enter__(self):try:self.wb = self.app.books.activeif not self.wb:raise Exception("没有活动的Excel工作簿。")self.ws = self.wb.sheets.activeif not self.ws:raise Exception("活动工作簿中没有活动的工作表。")return self.wb, self.wsexcept Exception as e:raise Exception(f"无法访问活动工作簿或工作表: {str(e)}")def __exit__(self, exc_type, exc_val, exc_tb):passreturn ExcelOperation(app)def insert_image(self, ws, image_path, cell_addr, margin, log_widget):"""插入图片到指定单元格"""try:# 确保使用绝对路径abs_image_path = os.path.abspath(image_path)if not os.path.exists(abs_image_path):self.log_message(f"错误: 图片文件不存在 - {abs_image_path}", log_widget)return False# 获取目标单元格target_cell = ws.range(cell_addr)# 计算插入位置和大小left = target_cell.left + margintop = target_cell.top + marginwidth = target_cell.width - 2 * marginheight = target_cell.height - 2 * margin# 插入图片ws.pictures.add(abs_image_path,left=left,top=top,width=width,height=height)return Trueexcept Exception as e:error_msg = f"插入图片失败: {str(e)}"self.log_message(error_msg, log_widget)return Falsedef run_column_match(self):"""执行列匹配插入"""self.log_message("开始列匹配处理...", self.col_log, clear=True)try:if not self.col_folder_var.text():QMessageBox.warning(self, "提示", "请先选择图片文件夹!")self.log_message("错误: 未选择图片文件夹。", self.col_log)returnparams = self.validate_column_params()app = xw.apps.active or xw.App(visible=True)with self.excel_operation(app) as (wb, ws):max_row = ws.used_range.last_cell.rowsuccess_inserts = 0processed_excel_rows = 0self.log_message(f"将在列 {params['match_col']} 中查找名称,图片插入到列 {params['insert_col']},从行 {params['start_row']} 开始。",self.col_log)for row_num_excel in range(params['start_row'], max_row + 1):processed_excel_rows += 1match_cell_addr = f"{params['match_col']}{row_num_excel}"cell_value = ws.range(match_cell_addr).valuename_to_match = str(cell_value).strip() if cell_value is not None else ""if not name_to_match:continueinsert_cell_addr = f"{params['insert_col']}{row_num_excel}"lower_name_to_match = name_to_match.lower()if lower_name_to_match in self.col_image_map:image_file_path = os.path.abspath(self.col_image_map[lower_name_to_match])if not os.path.exists(image_file_path):self.log_message(f"错误: 图片文件不存在 - {image_file_path}",self.col_log)continueif self.insert_image(ws, image_file_path, insert_cell_addr, params['margin'], self.col_log):success_inserts += 1self.log_message(f"{match_cell_addr}:{name_to_match} → {insert_cell_addr}:{os.path.basename(image_file_path)}",self.col_log)else:self.log_message(f"{match_cell_addr}:{name_to_match} → 未找到匹配图片",self.col_log)summary = f"\n共处理 {processed_excel_rows} 行数据,成功插入 {success_inserts} 张图片。"self.log_message(summary, self.col_log)except Exception as e:error_msg = f"列匹配错误: {str(e)}"self.log_message(error_msg, self.col_log)QMessageBox.critical(self, "错误", error_msg)def run_row_match(self):"""执行行匹配插入"""self.log_message("开始行匹配处理...", self.row_log, clear=True)try:if not self.row_folder_var.text():QMessageBox.warning(self, "提示", "请先选择图片文件夹!")self.log_message("错误: 未选择图片文件夹。", self.row_log)returnparams = self.validate_row_params()app = xw.apps.active or xw.App(visible=True)with self.excel_operation(app) as (wb, ws):max_col = ws.used_range.last_cell.columnsuccess_inserts = 0processed_excel_cols = 0self.log_message(f"将在行 {params['match_row']} 中查找名称,图片插入到行 {params['insert_row']}。",self.row_log)for col_num_excel in range(1, max_col + 1):processed_excel_cols += 1match_cell_addr = f"{xw.utils.col_name(col_num_excel)}{params['match_row']}"cell_value = ws.range(match_cell_addr).valuename_to_match = str(cell_value).strip() if cell_value is not None else ""if not name_to_match:continueinsert_cell_addr = f"{xw.utils.col_name(col_num_excel)}{params['insert_row']}"lower_name_to_match = name_to_match.lower()if lower_name_to_match in self.row_image_map:image_file_path = os.path.abspath(self.row_image_map[lower_name_to_match])if not os.path.exists(image_file_path):self.log_message(f"错误: 图片文件不存在 - {image_file_path}",self.row_log)continueif self.insert_image(ws, image_file_path, insert_cell_addr, params['margin'], self.row_log):success_inserts += 1self.log_message(f"{match_cell_addr}:{name_to_match} → {insert_cell_addr}:{os.path.basename(image_file_path)}",self.row_log)else:self.log_message(f"{match_cell_addr}:{name_to_match} → 未找到匹配图片",self.row_log)summary = f"\n共处理 {processed_excel_cols} 列数据,成功插入 {success_inserts} 张图片。"self.log_message(summary, self.row_log)except Exception as e:error_msg = f"行匹配错误: {str(e)}"self.log_message(error_msg, self.row_log)QMessageBox.critical(self, "错误", error_msg)def preview_insert_positions(self, mode):"""预览插入位置"""image_map = self.col_image_map if mode == "column" else self.row_image_maplog_widget = self.col_log if mode == "column" else self.row_logif not image_map:self.log_message("没有图片可供预览。请先选择图片文件夹。", log_widget)returnself.log_message("【插入位置预览】", log_widget)for name, path in image_map.items():self.log_message(f"{name} -> {os.path.basename(path)}", log_widget)def log_message(self, message, log_widget, clear=False):"""记录日志消息"""if clear:log_widget.setPlainText(message + "\n")else:current_text = log_widget.toPlainText()log_widget.setPlainText(current_text + message + "\n")log_widget.verticalScrollBar().setValue(log_widget.verticalScrollBar().maximum())if __name__ == "__main__":import sysapp = QApplication(sys.argv)app.setStyle("Fusion")window = ExcelImageMatcherPro()window.show()sys.exit(app.exec())
本文来自网友投稿或网络内容,如有侵犯您的权益请联系我们删除,联系邮箱:wyl860211@qq.com 。