当前位置: 首页 > ds >正文

csv文档批量转换xlsx,xls文档(带界面)

直接上代码

# -*- coding: utf-8 -*-
# @Time : 2025-06-15 9:43import tkinter as tk
from tkinter import ttk, filedialog, messagebox, scrolledtext
import re
import xlwings as xw
import os
from os import path as osp
import subprocess
import glob
import sys
from datetime import datetimeclass ExcelConverterApp:def __init__(self, root):self.root = rootself.root.title("CSV批量转Excel工具V1.0")self.root.geometry("700x600")  # 增大窗口高度以容纳日志框self.root.resizable(False, False)# 初始化变量self.folder_path = tk.StringVar()self.output_format = tk.StringVar(value="xlsx")  # 默认xlsx格式self.app = Noneself.setup_ui()def setup_ui(self):# 设置主题风格style = ttk.Style()style.theme_use('clam')# 主框架main_frame = ttk.Frame(self.root, padding="10")main_frame.pack(fill=tk.BOTH, expand=True)# 标题title_label = ttk.Label(main_frame,text="CSV批量转Excel转换工具",font=("微软雅黑", 16, "bold"),foreground="#2c3e50")title_label.pack(pady=(0, 15))# 文件夹选择部分folder_frame = ttk.LabelFrame(main_frame, text="选择文件夹", padding=10)folder_frame.pack(fill=tk.X, pady=5)ttk.Label(folder_frame, text="文件夹路径:").grid(row=0, column=0, sticky=tk.W)folder_entry = ttk.Entry(folder_frame, textvariable=self.folder_path, width=40)folder_entry.grid(row=0, column=1, padx=5, sticky=tk.EW)browse_btn = ttk.Button(folder_frame,text="浏览...",command=self.browse_folder,style="Accent.TButton")browse_btn.grid(row=0, column=2, padx=5)folder_frame.columnconfigure(1, weight=1)  # 让输入框可以扩展# 输出格式选择format_frame = ttk.LabelFrame(main_frame, text="输出格式", padding=10)format_frame.pack(fill=tk.X, pady=10)ttk.Radiobutton(format_frame,text="Excel 2007及以上 (.xlsx)",variable=self.output_format,value="xlsx").pack(anchor=tk.W, pady=2)ttk.Radiobutton(format_frame,text="Excel 97-2003 (.xls)",variable=self.output_format,value="xls").pack(anchor=tk.W, pady=2)# 转换按钮button_frame = ttk.Frame(main_frame)button_frame.pack(pady=10)convert_btn = ttk.Button(button_frame,text="开始转换",command=self.convert_files,style="Accent.TButton")convert_btn.pack(side=tk.LEFT, padx=5)clear_log_btn = ttk.Button(button_frame,text="清空日志",command=self.clear_log)clear_log_btn.pack(side=tk.LEFT, padx=5)# 日志框log_frame = ttk.LabelFrame(main_frame, text="转换日志", padding=5)log_frame.pack(fill=tk.BOTH, expand=True, pady=(10, 0))self.log_text = scrolledtext.ScrolledText(log_frame,wrap=tk.WORD,width=50,height=5,font=('Consolas', 10))self.log_text.pack(fill=tk.BOTH, expand=True)# 状态栏self.status_var = tk.StringVar(value="准备就绪")status_bar = ttk.Label(main_frame,textvariable=self.status_var,anchor=tk.W,padding=5)status_bar.pack(fill=tk.X, pady=(10, 0))# 配置样式self.configure_styles()def configure_styles(self):style = ttk.Style()# 主颜色style.configure('.', background="#ecf0f1", foreground="#2c3e50")style.configure('TLabel', background="#ecf0f1")style.configure('TFrame', background="#ecf0f1")style.configure('TLabelframe', background="#ecf0f1")style.configure('TLabelframe.Label', background="#ecf0f1")# 按钮样式style.configure('TButton', padding=6, font=("微软雅黑", 10))style.configure('Accent.TButton', foreground="white", background="#3498db")style.map('Accent.TButton',background=[('active', '#2980b9'), ('pressed', '#2c3e50')])# 输入框样式style.configure('TEntry', fieldbackground="white")# 单选按钮样式style.configure('TRadiobutton', background="#ecf0f1")# 日志框样式self.log_text.configure(background="white",foreground="black",insertbackground="black")def log_message(self, message):"""向日志框添加消息"""timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")log_entry = f"[{timestamp}] {message}\n"self.log_text.insert(tk.END, log_entry)self.log_text.see(tk.END)  # 自动滚动到底部self.root.update()  # 更新界面def clear_log(self):"""清空日志框"""self.log_text.delete(1.0, tk.END)self.log_message("日志已清空")def browse_folder(self):folder_selected = filedialog.askdirectory()if folder_selected:self.folder_path.set(folder_selected)self.log_message(f"已选择文件夹: {folder_selected}")self.status_var.set(f"已选择文件夹: {osp.basename(folder_selected)}")def load_excel(self):"""加载Excel应用"""self.log_message("正在启动Excel应用...")try:app = xw.App(visible=False)self.log_message("Excel应用启动成功")return appexcept Exception as e:self.log_message(f"打开Excel程序失败: {str(e)}")raise Exception("打开Excel程序失败") from edef natural_sort_key(self, s):"""自然排序的键生成函数"""return [int(text) if text.isdigit() else text.lower()for text in re.split(r'(\d+)', s)]def convert_files(self):"""执行转换操作"""folder = self.folder_path.get()if not folder:messagebox.showwarning("警告", "请先选择包含CSV文件的文件夹")self.log_message("警告: 未选择文件夹")returntry:self.status_var.set("正在初始化Excel...")self.log_message("开始转换过程...")self.root.update()self.app = self.load_excel()self.status_var.set("正在查找CSV文件...")self.log_message(f"正在搜索文件夹: {folder}")self.root.update()csv_files = glob.glob(osp.join(folder, '**', '*.csv'), recursive=True)csv_files.sort(key=lambda x: self.natural_sort_key(x), reverse=False)if not csv_files:messagebox.showinfo("提示", "没有找到任何CSV文件")self.log_message("未找到任何CSV文件")returntotal_files = len(csv_files)format_name = "XLSX" if self.output_format.get() == "xlsx" else "XLS"self.log_message(f"共找到 {total_files} 个CSV文件,将转换为{format_name}格式")confirm = messagebox.askyesno("确认",f"找到 {total_files} 个CSV文件,将转换为{format_name}格式,是否继续?")if not confirm:self.log_message("用户取消了转换操作")returnsuccess_count = 0for i, csv in enumerate(csv_files, 1):try:current_status = f"正在处理 ({i}/{total_files}): {osp.basename(csv)}"self.status_var.set(current_status)self.log_message(current_status)self.root.update()self.log_message(f"打开文件: {csv}")excel_path = osp.splitext(csv)[0] + ('.xlsx' if self.output_format.get() == "xlsx" else '.xls')# 打开csvwb = self.app.books.open(csv)self.log_message(f"正在保存为: {excel_path}")# 设置文件格式file_format = 51 if self.output_format.get() == "xlsx" else 56  # 51=xlsx, 56=xlswb.save(excel_path)wb.close()success_count += 1self.log_message(f"成功转换: {osp.basename(csv)}")except Exception as e:error_msg = f"处理文件 {osp.basename(csv)} 时出错: {str(e)}"self.log_message(error_msg)print(error_msg)result_msg = f"转换完成!成功: {success_count}/{total_files} 个文件"messagebox.showinfo("完成", result_msg)self.log_message(result_msg)self.status_var.set(f"转换完成,共处理 {success_count}/{total_files} 个文件")except Exception as e:error_msg = f"转换过程中出错: {str(e)}"messagebox.showerror("错误", error_msg)self.log_message(error_msg)self.status_var.set("转换出错")finally:if hasattr(self, 'app') and self.app:self.log_message("正在退出Excel应用...")self.app.quit()def main():root = tk.Tk()app = ExcelConverterApp(root)root.mainloop()if __name__ == "__main__":main()

在这里插入图片描述

http://www.xdnf.cn/news/14626.html

相关文章:

  • Go语言同步原语与数据竞争:数据竞争的检测工具
  • 2011-2020年各省互联网接入端口数数据
  • 打卡day54
  • AC-MT
  • C语言常用库函数
  • LangChain面试内容整理-知识点14:工具包(Toolkits)与用法
  • 生成对抗网络(GANs)入门介绍指南:让AI学会“创造“的魔法(二)【深入版】
  • Textacy:Python 中的文本数据清理和规范化简介
  • 自我实现的量子隐喻:在可能性场域中动态拓展涌现节点
  • LLMs:《WebDancer: Towards Autonomous Information Seeking Agency》翻译与解读
  • 02-Timer0-Timer1-Timer2-Timer3-Timer4测试程序
  • Sa-Token全面深入学习指南
  • 【慧游鲁博】【15】后台管理系统功能完善:仪表盘、多模态交互日志、简单问答词条管理
  • 建造者模式Builder Pattern
  • 深度解析5W2H:高效思维与问题解决工具详解
  • 离散隐藏变量下期望最大化(EM)算法的简化
  • LeetCode 第77题:组合
  • SimpleQtLogger 使用总结
  • 深入理解滑动窗口算法:原理、应用与 C++ 实现
  • C# 事件详解
  • React组件通信——发布订阅(pub/sub)
  • 紧急救援!Ubuntu崩溃修复大赛
  • 在Qt中使用OpenGL显示大量点(点云)
  • 136. 只出现一次的数字
  • 算法题(力扣每日一题)—改变一个整数能得到的最大差值
  • Arthas 全面学习指南
  • 动手实践:LangChain流图可视化全解析
  • [从0到1]环境准备--anaconda与pycharm的安装
  • Linux系统firewall-offline-cmd命令在企业网络安全防护中的应用案例分析
  • 图形编辑器基于Paper.js教程29:基于图层的所有矢量图元的填充规则实现