言出法随系列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()

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

相关推荐
飞哥数智坊2 小时前
一起看看开发一个活动平台,国产和国际模型各自表现如何?
人工智能·ai编程·trae
数据库知识分享者小北2 小时前
从极速复制“死了么”APP,看AI编程时代的技术选型
数据库·阿里云·状态模式·ai编程·supabase
aosky3 小时前
Sisyphus深度技术测评:面向未来的AI编程代理框架 oh-my-opencode
ai编程·oh-my-opencode
LV技术派3 小时前
适合很多公司和团队的 AI Coding 落地范式(三)
前端·ai编程·cursor
乘风gg3 小时前
太猛了,我用“千问AI”帮我点了一杯混果汁外卖
人工智能·ai编程·cursor
玉梅小洋3 小时前
macOS 安装 Claude Code 完整教程
vscode·macos·ai编程
阳哥赚钱很牛4 小时前
数据可视化项目
信息可视化·ai编程·数据可视化
我的offer在哪里4 小时前
Lovable和cursor的本质区别
ai编程
candyTong13 小时前
深入解析:AI 智能体(Agent)是如何解决问题的?
前端·agent·ai编程