Files
playwrite/excel_to_markdown.py

351 lines
13 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Excel to Markdown Converter
将Excel文件转换为Markdown格式的表格包含行号和列号英文字母
"""
import pandas as pd
import argparse
import sys
from pathlib import Path
def number_to_excel_col(n):
"""将数字转换为Excel列号A, B, ..., Z, AA, AB, ..."""
result = ""
while n > 0:
n -= 1
result = chr(n % 26 + ord('A')) + result
n //= 26
return result
def excel_to_markdown(input_file, output_file=None, sheet_name=0, include_row_numbers=True, include_col_numbers=True):
"""
将Excel文件转换为Markdown表格
Args:
input_file: 输入的Excel文件路径
output_file: 输出的Markdown文件路径可选默认为同名.md文件
sheet_name: 工作表名称或索引,或列表(默认为第一个工作表)
include_row_numbers: 是否包含行号
include_col_numbers: 是否包含列号
"""
input_path = Path(input_file)
if not input_path.exists():
print(f"错误: 文件 '{input_file}' 不存在")
return False
# 设置默认输出文件名
if output_file is None:
output_file = input_path.with_suffix('.md')
else:
output_file = Path(output_file)
try:
# 读取Excel文件
print(f"正在读取文件: {input_file}")
# 获取所有工作表名称(用于索引转换)
xls = pd.ExcelFile(input_file)
all_sheet_names = xls.sheet_names
# 将索引转换为实际的工作表名称
def resolve_sheet_name(name):
if isinstance(name, int):
if 0 <= name < len(all_sheet_names):
return all_sheet_names[name]
else:
raise ValueError(f"工作表索引 {name} 超出范围")
return name
# 处理多个工作表的情况
if isinstance(sheet_name, (list, tuple)):
# 转换索引为名称
resolved_names = [resolve_sheet_name(s) for s in sheet_name]
dfs = pd.read_excel(input_file, sheet_name=resolved_names, header=None)
# 如果只有一个工作表转换为单个DataFrame
if len(resolved_names) == 1:
dfs = {resolved_names[0]: dfs}
sheet_name = resolved_names
else:
resolved_name = resolve_sheet_name(sheet_name)
df = pd.read_excel(input_file, sheet_name=resolved_name, header=None)
dfs = {resolved_name: df}
sheet_name = resolved_name
# 生成所有工作表的Markdown内容
all_sheets_content = {}
for sheet_key, df in dfs.items():
# 转换数据为字符串处理NaN值
df = df.fillna('')
df = df.astype(str)
# 生成Markdown表格
markdown_lines = []
# 添加工作表标题
sheet_title = f"工作表: {sheet_key}"
markdown_lines.append(f"## {sheet_title}\n")
# 添加列号行
if include_col_numbers:
col_headers = [''] if include_row_numbers else []
col_headers.extend(number_to_excel_col(i + 1) for i in range(len(df.columns)))
markdown_lines.append('| ' + ' | '.join(col_headers) + ' |')
markdown_lines.append('| ' + ' | '.join(['---' for _ in col_headers]) + ' |')
# 添加数据行
for idx, row in df.iterrows():
row_data = []
if include_row_numbers:
row_data.append(str(idx + 1))
row_data.extend(row)
markdown_lines.append('| ' + ' | '.join(row_data) + ' |')
# 添加统计信息
markdown_lines.append(f"\n**统计信息:**")
markdown_lines.append(f"- 总行数: {len(df)}")
markdown_lines.append(f"- 总列数: {len(df.columns)}")
markdown_lines.append(f"- 数据范围: A1:{number_to_excel_col(len(df.columns))}{len(df)}")
all_sheets_content[sheet_key] = '\n'.join(markdown_lines)
# 写入文件
if len(dfs) == 1:
# 单个工作表:直接写入
sheet_key = list(dfs.keys())[0]
output_content = f"# {input_path.stem}\n\n"
output_content += f"从 `{input_file}` (工作表: {sheet_key}) 转换\n\n"
output_content += all_sheets_content[sheet_key]
output_file.write_text(output_content, encoding='utf-8')
print(f"✓ 转换成功!")
print(f" 输入文件: {input_file}")
print(f" 输出文件: {output_file}")
print(f" 工作表: {sheet_key}")
print(f" 行数: {len(dfs[sheet_key])}, 列数: {len(dfs[sheet_key].columns)}")
else:
return all_sheets_content, dfs, input_path, input_file
except Exception as e:
print(f"错误: {str(e)}")
import traceback
traceback.print_exc()
return False
def convert_multiple_sheets(input_file, output_file=None, sheet_names=None, include_row_numbers=True, include_col_numbers=True, merge_to_one_file=True):
"""
转换多个工作表
Args:
input_file: 输入的Excel文件路径
output_file: 输出的Markdown文件路径
sheet_names: 工作表名称或索引列表
include_row_numbers: 是否包含行号
include_col_numbers: 是否包含列号
merge_to_one_file: 是否合并到一个文件True或分别输出False
"""
input_path = Path(input_file)
if not input_path.exists():
print(f"错误: 文件 '{input_file}' 不存在")
return False
# 设置默认输出文件名
if output_file is None:
output_file = input_path.with_suffix('.md')
else:
output_file = Path(output_file)
try:
# 读取Excel文件
print(f"正在读取文件: {input_file}")
# 获取所有工作表名称
xls = pd.ExcelFile(input_file)
all_sheet_names = xls.sheet_names
if sheet_names is None or len(sheet_names) == 0:
# 读取所有工作表
sheet_names = all_sheet_names
print(f"找到 {len(sheet_names)} 个工作表")
else:
# 将索引转换为实际的工作表名称
resolved_names = []
for name in sheet_names:
if isinstance(name, int):
# 索引转换为名称
if 0 <= name < len(all_sheet_names):
resolved_names.append(all_sheet_names[name])
else:
print(f"警告: 工作表索引 {name} 超出范围,已跳过")
else:
# 直接使用名称
resolved_names.append(name)
sheet_names = resolved_names
# 使用实际的工作表名称读取数据
dfs = pd.read_excel(input_file, sheet_name=sheet_names, header=None)
# 确保返回的是字典格式
if not isinstance(dfs, dict):
dfs = {sheet_names[0]: dfs}
# 生成所有工作表的Markdown内容
all_sheets_content = {}
for sheet_key, df in dfs.items():
# 转换数据为字符串处理NaN值
df = df.fillna('')
df = df.astype(str)
# 生成Markdown表格
markdown_lines = []
# 添加工作表标题
sheet_title = f"工作表: {sheet_key}"
markdown_lines.append(f"## {sheet_title}\n")
# 添加列号行
if include_col_numbers:
col_headers = [''] if include_row_numbers else []
col_headers.extend(number_to_excel_col(i + 1) for i in range(len(df.columns)))
markdown_lines.append('| ' + ' | '.join(col_headers) + ' |')
markdown_lines.append('| ' + ' | '.join(['---' for _ in col_headers]) + ' |')
# 添加数据行
for idx, row in df.iterrows():
row_data = []
if include_row_numbers:
row_data.append(str(idx + 1))
row_data.extend(row)
markdown_lines.append('| ' + ' | '.join(row_data) + ' |')
# 添加统计信息
markdown_lines.append(f"\n**统计信息:**")
markdown_lines.append(f"- 总行数: {len(df)}")
markdown_lines.append(f"- 总列数: {len(df.columns)}")
markdown_lines.append(f"- 数据范围: A1:{number_to_excel_col(len(df.columns))}{len(df)}")
all_sheets_content[sheet_key] = '\n'.join(markdown_lines)
# 写入文件
if merge_to_one_file:
# 合并到一个文件
output_content = f"# {input_path.stem}\n\n"
output_content += f"从 `{input_file}` 转换,共 {len(dfs)} 个工作表\n\n"
output_content += "---\n\n"
for sheet_key in sheet_names:
if sheet_key in all_sheets_content:
output_content += all_sheets_content[sheet_key] + "\n\n---\n\n"
output_file.write_text(output_content, encoding='utf-8')
print(f"✓ 转换成功!")
print(f" 输入文件: {input_file}")
print(f" 输出文件: {output_file}")
print(f" 工作表数量: {len(dfs)}")
for sheet_key in sheet_names:
if sheet_key in dfs:
print(f" - {sheet_key}: {len(dfs[sheet_key])}行 x {len(dfs[sheet_key].columns)}")
else:
# 分别输出到多个文件
output_stem = output_file.stem
output_suffix = output_file.suffix
output_dir = output_file.parent
for sheet_key in sheet_names:
if sheet_key not in all_sheets_content:
continue
# 为每个工作表创建单独的文件
sheet_filename = f"{output_stem}_{sheet_key}{output_suffix}"
sheet_output_file = output_dir / sheet_filename
output_content = f"# {input_path.stem} - {sheet_key}\n\n"
output_content += f"从 `{input_file}` (工作表: {sheet_key}) 转换\n\n"
output_content += all_sheets_content[sheet_key]
sheet_output_file.write_text(output_content, encoding='utf-8')
print(f"✓ 转换成功!")
print(f" 输入文件: {input_file}")
print(f" 输出目录: {output_dir}")
print(f" 工作表数量: {len(dfs)}")
for sheet_key in sheet_names:
if sheet_key in dfs:
sheet_filename = f"{output_stem}_{sheet_key}{output_suffix}"
print(f" - {sheet_key} -> {sheet_filename} ({len(dfs[sheet_key])}行 x {len(dfs[sheet_key].columns)}列)")
return True
except Exception as e:
print(f"错误: {str(e)}")
import traceback
traceback.print_exc()
return False
# ============================================================
# 配置区域 - 直接修改下面的参数
# ============================================================
# 输入文件路径(必填)
INPUT_FILE = r"D:\python\playwrite\data\YTHN-100.A0.532-BOM-1.2版.xlsx"
# 输出文件路径(可选,默认为输入文件同名.md文件
OUTPUT_FILE = None # 或指定 r"D:\path\to\output.md"
# 工作表名称或索引可选默认为0即第一个工作表
# 可以是单个值: 0 或 "Sheet1"
# 可以是列表: [0, 1, 2] 或 ["Sheet1", "Sheet2", "Sheet3"]
# 可以是 None 表示读取所有工作表
SHEET_NAMES = [0, 1,2,3] # 指定多个工作表索引
# 是否包含行号可选默认为True
INCLUDE_ROW_NUMBERS = True
# 是否包含列号可选默认为True
INCLUDE_COL_NUMBERS = True
# 如果指定了多个工作表是否合并到一个文件可选默认为True
# True: 所有工作表合并到一个文件
# False: 每个工作表生成单独的文件(文件名格式: 原文件名_工作表名.md
MULTI_SHEETS_TO_ONE_FILE = True
# ============================================================
def main():
"""主函数 - 使用上方配置区域定义的参数"""
# 判断是否为多个工作表
if isinstance(SHEET_NAMES, list) and len(SHEET_NAMES) > 1:
# 多个工作表
convert_multiple_sheets(
input_file=INPUT_FILE,
output_file=OUTPUT_FILE,
sheet_names=SHEET_NAMES,
include_row_numbers=INCLUDE_ROW_NUMBERS,
include_col_numbers=INCLUDE_COL_NUMBERS,
merge_to_one_file=MULTI_SHEETS_TO_ONE_FILE
)
else:
# 单个工作表
sheet_name = SHEET_NAMES if isinstance(SHEET_NAMES, list) and len(SHEET_NAMES) == 1 else SHEET_NAMES
excel_to_markdown(
input_file=INPUT_FILE,
output_file=OUTPUT_FILE,
sheet_name=sheet_name,
include_row_numbers=INCLUDE_ROW_NUMBERS,
include_col_numbers=INCLUDE_COL_NUMBERS
)
if __name__ == '__main__':
main()