#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Excel to Markdown Converter 将Excel文档转换为Markdown表格格式 """ import openpyxl from openpyxl.utils import get_column_letter from typing import Optional, Tuple import argparse class ExcelToMarkdown: """Excel转Markdown转换器""" def __init__(self, excel_file: str): """ 初始化转换器 Args: excel_file: Excel文件路径 """ self.workbook = openpyxl.load_workbook(excel_file, data_only=True) self.sheet = self.workbook.active def detect_data_range(self, max_scan_rows: int = 100, max_scan_cols: int = 100) -> Tuple[int, int]: """ 自动检测数据范围 Args: max_scan_rows: 最大扫描行数 max_scan_cols: 最大扫描列数 Returns: (最大行号, 最大列号) """ max_row = 0 max_col = 0 # 扫描前100行和前100列 scan_rows = min(max_scan_rows, self.sheet.max_row) scan_cols = min(max_scan_cols, self.sheet.max_column) for row in range(1, scan_rows + 1): for col in range(1, scan_cols + 1): cell_value = self.sheet.cell(row=row, column=col).value if cell_value is not None and str(cell_value).strip() != "": max_row = max(max_row, row) max_col = max(max_col, col) return max_row, max_col def convert(self, max_rows: Optional[int] = None, max_cols: Optional[int] = None, show_row_numbers: bool = False, show_col_numbers: bool = False, start_row: int = 1, start_col: int = 1) -> str: """ 转换Excel为Markdown格式 Args: max_rows: 最大行数(None表示自动检测) max_cols: 最大列数(None表示自动检测) show_row_numbers: 是否显示行号 show_col_numbers: 是否显示列号(字母形式) start_row: 起始行号(默认1) start_col: 起始列号(默认1) Returns: Markdown格式的表格字符串 """ # 自动检测数据范围 if max_rows is None or max_cols is None: detected_rows, detected_cols = self.detect_data_range() if max_rows is None: max_rows = detected_rows if max_cols is None: max_cols = detected_cols # 确保至少有1行1列 if max_rows < 1 or max_cols < 1: return "| 无数据 |\n|--------|\n" # 计算实际的结束位置 end_row = min(start_row + max_rows - 1, self.sheet.max_row) end_col = min(start_col + max_cols - 1, self.sheet.max_column) markdown_lines = [] # 构建列号行(如果需要) if show_col_numbers: header_parts = [] if show_row_numbers: header_parts.append("") # 行号列的占位 for col in range(start_col, end_col + 1): col_letter = get_column_letter(col) header_parts.append(col_letter) markdown_lines.append("| " + " | ".join(header_parts) + " |") # 分隔线 separator_parts = ["---"] * len(header_parts) markdown_lines.append("| " + " | ".join(separator_parts) + " |") # 构建数据行 for row in range(start_row, end_row + 1): row_parts = [] # 添加行号(如果需要) if show_row_numbers: row_parts.append(str(row)) # 添加单元格数据 for col in range(start_col, end_col + 1): cell_value = self.sheet.cell(row=row, column=col).value # 处理空值 if cell_value is None: cell_str = "" else: cell_str = str(cell_value).strip() # 转义Markdown特殊字符 cell_str = cell_str.replace("|", "\\|") cell_str = cell_str.replace("\n", "
") row_parts.append(cell_str) markdown_lines.append("| " + " | ".join(row_parts) + " |") # 如果是第一行且没有显示列号,添加分隔线 if row == start_row and not show_col_numbers: separator_parts = ["---"] * len(row_parts) markdown_lines.append("| " + " | ".join(separator_parts) + " |") return "\n".join(markdown_lines) def save_to_file(self, markdown_text: str, output_file: str): """ 保存Markdown到文件 Args: markdown_text: Markdown文本 output_file: 输出文件路径 """ with open(output_file, 'w', encoding='utf-8') as f: f.write(markdown_text) def close(self): """关闭工作簿""" self.workbook.close() def main(): """命令行入口""" parser = argparse.ArgumentParser( description='将Excel文档转换为Markdown表格格式', formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" 示例: # 自动检测范围并转换 python excel_to_markdown.py input.xlsx -o output.md # 指定转换前10行、前5列 python excel_to_markdown.py input.xlsx -o output.md -r 10 -c 5 # 显示行号和列号 python excel_to_markdown.py input.xlsx -o output.md --show-rows --show-cols # 从第2行第2列开始,转换5行3列 python excel_to_markdown.py input.xlsx -o output.md -r 5 -c 3 --start-row 2 --start-col 2 """ ) parser.add_argument('input_file', help='输入的Excel文件路径') parser.add_argument('-o', '--output', help='输出的Markdown文件路径(不指定则输出到控制台)') parser.add_argument('-r', '--max-rows', type=int, help='最大转换行数(不指定则自动检测)') parser.add_argument('-c', '--max-cols', type=int, help='最大转换列数(不指定则自动检测)') parser.add_argument('--show-rows', action='store_true', help='显示行号') parser.add_argument('--show-cols', action='store_true', help='显示列号(字母形式)') parser.add_argument('--start-row', type=int, default=1, help='起始行号(默认1)') parser.add_argument('--start-col', type=int, default=1, help='起始列号(默认1)') args = parser.parse_args() try: # 创建转换器 converter = ExcelToMarkdown(args.input_file) # 执行转换 markdown_text = converter.convert( max_rows=args.max_rows, max_cols=args.max_cols, show_row_numbers=args.show_rows, show_col_numbers=args.show_cols, start_row=args.start_row, start_col=args.start_col ) # 输出结果 if args.output: converter.save_to_file(markdown_text, args.output) print(f"✓ 转换完成!已保存到: {args.output}") else: print(markdown_text) # 关闭工作簿 converter.close() except FileNotFoundError: print(f"✗ 错误: 找不到文件 '{args.input_file}'") except Exception as e: print(f"✗ 错误: {str(e)}") if __name__ == "__main__": main()