言出法随系列1-免费AI编程工具Trae开发“复制EXCEL内容转MARKDOWN”

不写一行代码,编写可用小工具,所以叫言出法随系列。

目前AI编程适用于:软件小工具、浏览器插件开发、文件处理等。

软件名称:EXCEL到MARKDOWN转换器

软件功能:实现复制EXCEL内容转化为MARKDOWN格式,把MARKDOWN内容粘到大模型软件让大模型帮我检查内容。(类型:我会给你markdown格式内容,检查内容一致性指出错误描述。)

开发工具:Trae

开发过程简单描述:

1、输入指令。2、优化指令。3、发送指令。4、发送错误或优化内容给trea修改。5、开发完成后,要求trea打包成exe.

下载地址:https://download.csdn.net/download/bobodadao/92562537 无需积分。

代码如下:

复制代码
import tkinter as tk
from tkinter import ttk, messagebox
import pandas as pd
import pyperclip

def get_clipboard_excel():
    """从剪贴板读取Excel内容并返回DataFrame"""
    try:
        # 优先使用pyperclip直接读取剪贴板内容,手动解析以避免pandas自动添加列名后缀
        try:
            import pyperclip
            clipboard_content = pyperclip.paste()
            if not clipboard_content:
                messagebox.showerror("错误", "剪贴板中没有可读取的内容")
                return None
            
            # 处理单元格内换行的情况
            # 当从Excel复制时,单元格内的换行通常会被保留为\n
            # 我们需要正确处理这种情况,确保多行单元格被视为单个单元格
            
            # 首先按换行符分割
            lines = clipboard_content.strip().split('\n')
            if not lines:
                messagebox.showerror("错误", "剪贴板中没有可读取的内容")
                return None
            
            # 解析数据,处理多行单元格和带引号的单元格
            data = []
            current_row = []
            current_cell = []
            in_quoted_cell = False
            
            # 首先将所有内容作为一个整体处理,以正确识别带引号的多行单元格
            all_content = clipboard_content.strip()
            lines = all_content.split('\n')
            
            # 处理每一行
            for line in lines:
                # 遍历每个字符以正确处理引号和制表符
                for char in line:
                    if char == '"':
                        in_quoted_cell = not in_quoted_cell
                    
                    # 如果我们在引号内
                    if in_quoted_cell:
                        # 在引号内,所有字符(包括制表符)都属于当前单元格
                        current_cell.append(char)
                    else:
                        # 不在引号内
                        if char == '\t':
                            # 制表符表示当前单元格结束
                            if current_cell:
                                cell_content = ''.join(current_cell).strip()
                                current_row.append(cell_content)
                                current_cell = []
                            else:
                                # 空单元格
                                current_row.append('')
                        else:
                            # 普通字符,开始或继续构建单元格
                            current_cell.append(char)
                
                # 处理行尾
                if in_quoted_cell:
                    # 如果在引号内,行尾表示单元格内的换行
                    current_cell.append('\n')
                else:
                    # 不在引号内,行尾表示当前行结束
                    if current_cell:
                        cell_content = ''.join(current_cell).strip()
                        current_row.append(cell_content)
                        current_cell = []
                    
                    # 保存当前行
                    if current_row:
                        data.append(current_row)
                        current_row = []
            
            # 处理最后一个单元格
            if current_cell:
                cell_content = ''.join(current_cell).strip('"').strip()
                current_row.append(cell_content)
            
            # 处理最后一行
            if current_row:
                data.append(current_row)
            
            # 计算最大列数
            max_cells = 0
            for row in data:
                max_cells = max(max_cells, len(row))
            
            # 检查是否有合适的表头(在归一化之前)
            # 表头应该满足:长度合理,且与大多数行的长度一致
            has_header = False
            if len(data) > 1:
                # 计算每行的长度
                row_lengths = [len(row) for row in data]
                # 找到最常见的长度
                most_common_length = max(set(row_lengths), key=row_lengths.count)
                # 如果第一行的长度等于最常见的长度,且不是1(避免将单列数据误判为表头)
                # 同时确保第一行不包含引号(避免将带引号的多行单元格误判为表头)
                first_row_has_quotes = any('"' in str(cell) for cell in data[0])
                if len(data[0]) == most_common_length and most_common_length > 1 and not first_row_has_quotes:
                    has_header = True
            
            # 第二次遍历:确保所有行都有相同的列数
            normalized_data = []
            for row in data:
                # 如果行长度不足,补充空字符串
                if len(row) < max_cells:
                    row.extend([''] * (max_cells - len(row)))
                # 如果行长度超过,截断
                elif len(row) > max_cells:
                    row = row[:max_cells]
                normalized_data.append(row)
            
            if has_header:
                # 使用第一行作为列名
                columns = normalized_data[0]
                rows = normalized_data[1:]
                # 创建DataFrame,使用原始列名
                df = pd.DataFrame(rows)
                df.columns = columns
            else:
                # 没有合适的表头,使用默认列名
                columns = [f"列{i+1}" for i in range(max_cells)]
                df = pd.DataFrame(normalized_data, columns=columns)
            
            return df
        except Exception as e:
            # 显示错误信息并继续
            messagebox.showinfo("提示", f"pyperclip解析失败,尝试其他方法: {str(e)}")
            
        # 尝试第一种方法:直接使用pd.read_clipboard()
        try:
            # 设置keep_default_na=False以避免将空字符串识别为NaN
            # 设置index_col=None以避免将第一列作为索引
            df = pd.read_clipboard(keep_default_na=False, index_col=None)
            if not df.empty:
                return df
        except:
            pass
        
        # 尝试第二种方法:设置header=None,手动处理列名
        try:
            # 设置keep_default_na=False以避免将空字符串识别为NaN
            # 设置index_col=None以避免将第一列作为索引
            df = pd.read_clipboard(header=None, keep_default_na=False, index_col=None)
            if df.empty:
                messagebox.showerror("错误", "剪贴板中没有可读取的内容")
                return None
            
            # 尝试自动检测列名
            try:
                # 检查第一行是否全为字符串(可能是列名)
                first_row_is_header = all(isinstance(val, str) for val in df.iloc[0])
                if first_row_is_header:
                    # 将第一行设为列名,删除第一行数据
                    # 使用原始列名,不允许pandas自动添加后缀
                    columns = df.iloc[0].tolist()
                    df = df[1:]
                    # 确保所有数据行的长度与列数一致
                    max_columns = len(columns)
                    rows = []
                    for _, row in df.iterrows():
                        row_list = row.tolist()
                        # 如果行长度不足,补充空字符串
                        if len(row_list) < max_columns:
                            row_list.extend([''] * (max_columns - len(row_list)))
                        # 如果行长度超过,截断
                        elif len(row_list) > max_columns:
                            row_list = row_list[:max_columns]
                        rows.append(row_list)
                    # 重新创建DataFrame,使用原始列名
                    df = pd.DataFrame(rows)
                    df.columns = columns
                else:
                    # 如果第一行不是字符串,使用默认列名
                    df.columns = [f"列{i+1}" for i in range(df.shape[1])]
            except:
                # 如果检测失败,使用默认列名
                df.columns = [f"列{i+1}" for i in range(df.shape[1])]
            
            return df
        except:
            pass
            
    except Exception as e:
        messagebox.showerror("错误", "无法从剪贴板读取Excel内容:\n" + str(e))
        return None

def excel_to_markdown(df):
    """将DataFrame转换为MARKDOWN表格格式"""
    if df is None:
        return ""
    
    # 获取列名
    columns = df.columns.tolist()
    
    # 构建表头,处理表头中的换行符
    processed_columns = []
    for col in columns:
        # 处理表头中的换行符
        processed_col = str(col).replace("\n", "<br>")
        processed_columns.append(processed_col)
    markdown = "| " + " | ".join(processed_columns) + " |\n"
    
    # 构建分隔线
    markdown += "| " + " | ".join("---" for _ in columns) + " |\n"
    
    # 构建数据行
    for _, row in df.iterrows():
        row_data = []
        for col in columns:
            try:
                value = row[col]
                # 处理NaN值
                if pd.isna(value):
                    row_data.append("")
                else:
                    # 处理单元格内换行的情况
                    # 在Markdown中,单元格内的换行需要用<br>标签表示
                    cell_text = str(value).replace("\n", "<br>")
                    row_data.append(cell_text)
            except:
                # 如果出现错误(例如列不存在),添加空字符串
                row_data.append("")
        markdown += "| " + " | ".join(row_data) + " |\n"
    
    return markdown

class ExcelToMarkdownConverter:
    def __init__(self, root):
        self.root = root
        self.root.title("Excel到MARKDOWN转换器")
        self.root.geometry("800x600")
        
        # 创建主框架
        main_frame = ttk.Frame(root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 创建原始内容展示区域
        original_frame = ttk.LabelFrame(main_frame, text="原始Excel内容", padding="10")
        original_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        self.original_text = tk.Text(original_frame, wrap=tk.WORD, height=10)
        self.original_text.pack(fill=tk.BOTH, expand=True)
        
        # 创建转换后内容展示区域
        markdown_frame = ttk.LabelFrame(main_frame, text="转换后MARKDOWN内容", padding="10")
        markdown_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        self.markdown_text = tk.Text(markdown_frame, wrap=tk.WORD, height=10)
        self.markdown_text.pack(fill=tk.BOTH, expand=True)
        
        # 创建按钮框架
        button_frame = ttk.Frame(main_frame, padding="10")
        button_frame.pack(fill=tk.X, pady=5)
        
        # 创建复制按钮
        self.copy_button = ttk.Button(button_frame, text="复制MARKDOWN内容", command=self.copy_markdown)
        self.copy_button.pack(side=tk.LEFT, padx=5)
        
        # 创建重新读取按钮
        self.refresh_button = ttk.Button(button_frame, text="重新读取剪贴板", command=self.refresh_content)
        self.refresh_button.pack(side=tk.LEFT, padx=5)
        
        # 初始化时读取剪贴板内容
        self.refresh_content()
    
    def copy_markdown(self):
        """复制转换后的MARKDOWN内容到剪贴板"""
        markdown_content = self.markdown_text.get(1.0, tk.END).strip()
        if markdown_content:
            pyperclip.copy(markdown_content)
            messagebox.showinfo("成功", "MARKDOWN内容已复制到剪贴板")
        else:
            messagebox.showwarning("警告", "没有可复制的MARKDOWN内容")
    
    def refresh_content(self):
        """重新读取剪贴板中的Excel内容并更新转换后的MARKDOWN内容"""
        df = get_clipboard_excel()
        if df is not None:
            # 更新原始内容展示
            self.original_text.delete(1.0, tk.END)
            self.original_text.insert(tk.END, df.to_string(index=False))
            
            # 转换为MARKDOWN并更新展示
            markdown_content = excel_to_markdown(df)
            self.markdown_text.delete(1.0, tk.END)
            self.markdown_text.insert(tk.END, markdown_content)
        else:
            # 清空展示区域
            self.original_text.delete(1.0, tk.END)
            self.markdown_text.delete(1.0, tk.END)

if __name__ == "__main__":
    root = tk.Tk()
    app = ExcelToMarkdownConverter(root)
    root.mainloop()

我真闲写这篇文章,你也真闲看到这里,我真羡慕咱俩。

相关推荐
程序员老刘·7 小时前
Android Studio Otter 3 发布:日常开发选AS还是Cursor?
flutter·android studio·ai编程·跨平台开发·客户端开发
JMchen12316 小时前
AI编程范式转移:深度解析人机协同编码的实战进阶与未来架构
人工智能·经验分享·python·深度学习·架构·pycharm·ai编程
HetFrame16 小时前
大模型驱动的禅道任务自动化规划与创建
python·ai·自动化·大模型·ai编程·任务·禅道
Ashley_Amanda1 天前
主流AI编程工具深度解析
ai编程
GISer_Jing2 天前
构建高性能Markdown引擎开发计划
前端·aigc·ai编程
Horizon_Ruan2 天前
从零开始掌握AI:LLM、RAG到Agent的完整学习路线图
人工智能·学习·ai编程
Testopia2 天前
AI编程实例 -- 数据可视化实战教程
人工智能·信息可视化·ai编程
PorkCanteen2 天前
Cursor使用-从问题到解决方案(以及一些通用rules)
前端·ai·ai编程
yangminlei2 天前
从零构建一个基于 DeepSeek 的 AI 对话系统:Spring Boot + 前端实战指南
spring boot·ai编程