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()