python-xmind转Excel

1、准备环境:

2、运行代码:

python 复制代码
# !/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
XMind转Excel转换器
支持将XMind思维导图文件转换为Excel表格格式
Python版本要求: 3.9+
"""

import os
import sys
import pandas as pd
from xmindparser import xmind_to_dict
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
from datetime import datetime


class XmindToExcelConverter:
    """XMind转Excel转换器主类"""

    def __init__(self):
        self.supported_extensions = ['.xmind', '.XMind']

    def convert_xmind_to_excel(self, xmind_file_path, excel_file_path=None):
        """
        将XMind文件转换为Excel文件
        """
        try:
            # 验证输入文件
            if not os.path.exists(xmind_file_path):
                raise FileNotFoundError(f"XMind文件不存在: {xmind_file_path}")

            file_ext = os.path.splitext(xmind_file_path)[1].lower()
            if file_ext not in self.supported_extensions:
                raise ValueError(f"不支持的文件格式: {file_ext},仅支持 {self.supported_extensions}")

            # 解析XMind文件
            print(f"正在解析XMind文件: {xmind_file_path}")
            xmind_data = xmind_to_dict(xmind_file_path)

            if not xmind_data:
                raise ValueError("XMind文件解析失败,文件可能为空或格式不正确")

            # 提取主题数据
            root_topic = xmind_data[0]['topic']

            # 处理数据并转换为DataFrame
            processed_data = self._process_xmind_data(root_topic)

            # 生成Excel文件路径
            if not excel_file_path:
                base_name = os.path.splitext(os.path.basename(xmind_file_path))[0]
                excel_file_path = os.path.join(
                    os.path.dirname(xmind_file_path),
                    f"{base_name}_converted.xlsx"
                )

            # 保存为Excel文件
            self._save_to_excel(processed_data, excel_file_path)

            return excel_file_path

        except Exception as e:
            raise Exception(f"转换过程中出现错误: {str(e)}")

    def _process_xmind_data(self, topic, level=0, parent_path=None):
        """
        递归处理XMind数据,转换为表格格式
        """
        if parent_path is None:
            parent_path = []

        current_path = parent_path + [topic.get('title', '')]
        results = []

        # 添加当前节点
        row_data = {f'层级_{i + 1}': path for i, path in enumerate(current_path)}
        results.append(row_data)

        # 处理子主题
        child_topics = topic.get('topics', [])
        for child_topic in child_topics:
            child_results = self._process_xmind_data(child_topic, level + 1, current_path)
            results.extend(child_results)

        return results

    def _save_to_excel(self, data, excel_file_path):
        """
        将处理后的数据保存为Excel文件
        """
        if not data:
            raise ValueError("没有数据可以保存")

        # 转换为DataFrame
        df = pd.DataFrame(data)

        # 确保列的顺序正确
        max_level = max([int(col.split('_')[1]) for col in df.columns if col.startswith('层级_')])
        ordered_columns = [f'层级_{i + 1}' for i in range(max_level)]

        # 重新排序列
        df = df.reindex(columns=ordered_columns)

        # 保存Excel文件
        df.to_excel(excel_file_path, index=False, engine='openpyxl')
        print(f"Excel文件已保存: {excel_file_path}")


class XmindConverterGUI:
    """图形用户界面"""

    def __init__(self):
        self.root = tk.Tk()
        self.root.title("XMind转Excel转换器 v1.0")
        self.root.geometry("600x400")
        self.root.resizable(True, True)

        self.converter = XmindToExcelConverter()
        self.setup_ui()

    def setup_ui(self):
        """设置用户界面"""
        # 主框架
        main_frame = ttk.Frame(self.root, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 标题
        title_label = ttk.Label(
            main_frame,
            text="XMind转Excel转换器",
            font=("Arial", 16, "bold")
        )
        title_label.pack(pady=(0, 20))

        # 文件选择区域
        file_frame = ttk.LabelFrame(main_frame, text="文件选择", padding="15")
        file_frame.pack(fill=tk.X, pady=(0, 15))

        # XMind文件选择
        xmind_frame = ttk.Frame(file_frame)
        xmind_frame.pack(fill=tk.X, pady=(0, 10))

        ttk.Label(xmind_frame, text="XMind文件:").pack(side=tk.LEFT)

        self.xmind_path_var = tk.StringVar()
        xmind_entry = ttk.Entry(xmind_frame, textvariable=self.xmind_path_var, width=50)
        xmind_entry.pack(side=tk.LEFT, padx=(10, 5))

        ttk.Button(
            xmind_frame,
            text="浏览...",
            command=self.browse_xmind_file
        ).pack(side=tk.LEFT)

        # Excel文件保存位置
        excel_frame = ttk.Frame(file_frame)
        excel_frame.pack(fill=tk.X)

        ttk.Label(excel_frame, text="保存位置:").pack(side=tk.LEFT)

        self.excel_path_var = tk.StringVar()
        excel_entry = ttk.Entry(excel_frame, textvariable=self.excel_path_var, width=50)
        excel_entry.pack(side=tk.LEFT, padx=(10, 5))

        ttk.Button(
            excel_frame,
            text="浏览...",
            command=self.browse_excel_file
        ).pack(side=tk.LEFT)

        # 转换按钮
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X, pady=(20, 0))

        self.convert_button = ttk.Button(
            button_frame,
            text="开始转换",
            command=self.start_conversion
        )
        self.convert_button.pack(side=tk.LEFT, padx=(0, 10))

        ttk.Button(
            button_frame,
            text="清除",
            command=self.clear_all
        ).pack(side=tk.LEFT)

        ttk.Button(
            button_frame,
            text="退出",
            command=self.root.quit
        ).pack(side=tk.LEFT)

        # 日志区域
        log_frame = ttk.LabelFrame(main_frame, text="转换日志", padding="10")
        log_frame.pack(fill=tk.BOTH, expand=True, pady=(20, 0))

        self.log_text = tk.Text(log_frame, height=10, wrap=tk.WORD)
        scrollbar = ttk.Scrollbar(log_frame, command=self.log_text.yview)
        self.log_text.configure(yscrollcommand=scrollbar.set)

        self.log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 进度条
        self.progress_var = tk.DoubleVar()
        self.progress_bar = ttk.Progressbar(
            main_frame,
            variable=self.progress_var,
            maximum=100
        )
        self.progress_bar.pack(fill=tk.X, pady=(10, 0))

        # 状态标签
        self.status_var = tk.StringVar(value="准备就绪")
        status_label = ttk.Label(main_frame, textvariable=self.status_var)
        status_label.pack(fill=tk.X, pady=(5, 0))

    def browse_xmind_file(self):
        """浏览选择XMind文件"""
        file_path = filedialog.askopenfilename(
            title="选择XMind文件",
            filetypes=[
                ("XMind文件", "*.xmind"),
                ("XMind文件", "*.XMind"),
                ("所有文件", "*.*")
            ]
        )
        if file_path:
            self.xmind_path_var.set(file_path)
            # 自动设置Excel保存路径
            base_name = os.path.splitext(os.path.basename(file_path))[0]
            default_excel_path = os.path.join(
                os.path.dirname(file_path),
                f"{base_name}_converted.xlsx"
            )
            self.excel_path_var.set(default_excel_path)

    def browse_excel_file(self):
        """浏览选择Excel保存位置"""
        file_path = filedialog.asksaveasfilename(
            title="保存Excel文件",
            defaultextension=".xlsx",
            filetypes=[
                ("Excel文件", "*.xlsx"),
                ("所有文件", "*.*")
            ]
        )
        if file_path:
            self.excel_path_var.set(file_path)

    def log_message(self, message):
        """添加日志消息"""
        timestamp = datetime.now().strftime("%H:%M:%S")
        formatted_message = f"[{timestamp}] {message}\n"
        self.log_text.insert(tk.END, formatted_message)
        self.log_text.see(tk.END)
        self.root.update()

    def start_conversion(self):
        """开始转换过程"""
        xmind_path = self.xmind_path_var.get().strip()
        excel_path = self.excel_path_var.get().strip()

        if not xmind_path:
            messagebox.showerror("错误", "请选择XMind文件")
            return

        if not excel_path:
            messagebox.showerror("错误", "请选择Excel保存位置")
            return

        try:
            self.convert_button.config(state=tk.DISABLED)
            self.progress_var.set(10)
            self.status_var.set("正在验证文件...")
            self.log_message("开始转换过程")

            self.progress_var.set(30)
            self.status_var.set("正在解析XMind文件...")
            self.log_message(f"输入文件: {xmind_path}")
            self.log_message(f"输出文件: {excel_path}")

            # 执行转换
            result_path = self.converter.convert_xmind_to_excel(xmind_path, excel_path)

            self.progress_var.set(100)
            self.status_var.set("转换完成")
            self.log_message(f"转换成功! 文件已保存至: {result_path}")

            messagebox.showinfo("成功", f"转换完成!\n文件已保存至:\n{result_path}")

        except Exception as e:
            self.log_message(f"转换失败: {str(e)}")
            self.status_var.set("转换失败")
            messagebox.showerror("错误", f"转换过程中出现错误:\n{str(e)}")

        finally:
            self.convert_button.config(state=tk.NORMAL)

    def clear_all(self):
        """清除所有输入"""
        self.xmind_path_var.set("")
        self.excel_path_var.set("")
        self.log_text.delete(1.0, tk.END)
        self.progress_var.set(0)
        self.status_var.set("准备就绪")

    def run(self):
        """运行GUI"""
        self.root.mainloop()


def main():
    """主函数"""
    print("XMind转Excel转换器 v1.0")
    print("=" * 40)

    if len(sys.argv) > 1:
        # 命令行模式
        if sys.argv[1] in ['-h', '--help']:
            print("用法: python xmind_to_excel.py [XMind文件路径] [Excel保存路径]")
        print("示例: python xmind_to_excel.py test.xmind output.xlsx")
        return

    try:
        # 启动GUI
        app = XmindConverterGUI()
        app.run()
    except KeyboardInterrupt:
        print("\n程序已退出")
    except Exception as e:
        print(f"程序运行错误: {e}")


if __name__ == "__main__":
    main()
相关推荐
合作小小程序员小小店37 分钟前
web网页,在线%抖音,舆情,线性回归%分析系统demo,基于python+web+echart+nlp+线性回归,训练,数据库mysql
python·自然语言处理·回归·nlp·线性回归
q***25138 分钟前
Python中的简单爬虫
爬虫·python·信息可视化
最晚的py38 分钟前
Python Matplotlib
python·数据分析
柳鲲鹏1 小时前
OpenCV:文件视频防抖,python版
python·opencv·音视频
@sinner3 小时前
你好,Scikit-learn:从零开始你的第一个机器学习项目
python·机器学习·scikit-learn
麦烤楽鸡翅3 小时前
简单迭代法求单根的近似值
java·c++·python·数据分析·c·数值分析
hyswl6663 小时前
2025年开发小程序公司推荐
python·小程序
独行soc3 小时前
2025年渗透测试面试题总结-258(题目+回答)
网络·python·安全·web安全·渗透测试·安全狮
程序员小远4 小时前
Appium-移动端自动测试框架详解
自动化测试·软件测试·python·测试工具·职场和发展·appium·测试用例
johnny2334 小时前
AI加持测试工具汇总:Strix、
人工智能·测试工具