#!/usr/bin/env python3
"""
TXT转Excel优化工具 - 合并到单一工作表(无来源文件列)
"""
import os
import pandas as pd
from glob import glob
import sys
import numpy as np
from datetime import datetime
# 常见编码列表(按优先级排序)
COMMON_ENCODINGS = ['utf-8', 'gbk', 'iso-8859-1', 'latin1']
def detect_encoding(file_path):
"""尝试检测文件编码"""
for encoding in COMMON_ENCODINGS:
try:
with open(file_path, 'r', encoding=encoding) as f:
f.read(1024)
return encoding
except UnicodeDecodeError:
continue
return 'utf-8' # 默认使用UTF-8
def try_read_file(file_path, sep):
"""尝试读取文件(增强健壮性)"""
encoding = detect_encoding(file_path)
print(f"使用编码: {encoding} (文件: {os.path.basename(file_path)})")
try:
# 读取文件(不添加来源文件列)
df = pd.read_csv(
file_path,
sep=sep,
encoding=encoding,
engine='python',
on_bad_lines='warn',
dtype=str, # 初始读取为字符串避免类型错误
keep_default_na=False # 防止空值被转换为NaN
)
print(f"成功读取 {len(df)} 行数据")
return df
except pd.errors.EmptyDataError:
print(f"警告: 文件不包含数据")
return None
except Exception as e:
print(f"读取文件失败: {str(e)}")
return None
def optimize_data_types(df):
"""优化数据类型并修复格式问题"""
print("优化数据类型...")
# 尝试转换数值列
for col in df.columns:
# 尝试转换为数值类型
try:
# 检查是否有非数字字符
if df[col].str.contains(r'[^0-9\.eE\-+]', na=False).any():
continue
converted = pd.to_numeric(df[col], errors='coerce')
# 如果转换后非空值超过90%,则应用转换
if converted.notna().mean() > 0.9:
df[col] = converted
except:
pass
# 尝试转换为日期类型
try:
# 常见日期格式
date_formats = [
'%Y-%m-%d', '%d/%m/%Y', '%m/%d/%Y',
'%Y%m%d', '%d-%b-%y', '%b %d, %Y'
]
for fmt in date_formats:
try:
converted = pd.to_datetime(df[col], format=fmt, errors='coerce')
# 如果转换后非空值超过80%,则应用转换
if converted.notna().mean() > 0.8:
df[col] = converted
break
except:
continue
except:
pass
return df
def process_files(input_dir, output_file, pattern='*.txt', sep='\t', recursive=False):
"""处理文件并生成Excel(所有数据合并到单一工作表)"""
# 获取文件列表
search_pattern = os.path.join(input_dir, '**', pattern) if recursive \
else os.path.join(input_dir, pattern)
txt_files = glob(search_pattern, recursive=recursive)
if not txt_files:
print(f"错误: 未找到匹配 {pattern} 的文件")
sys.exit(1)
print(f"\n找到 {len(txt_files)} 个文件:")
for i, f in enumerate(txt_files, 1):
print(f"{i}. {f}")
# 处理文件并合并数据
all_dfs = [] # 存储所有DataFrame
processed_files = 0
for file_path in txt_files:
print(f"\n处理文件: {os.path.basename(file_path)}")
# 读取文件
df = try_read_file(file_path, sep)
if df is not None:
all_dfs.append(df)
processed_files += 1
# 合并所有DataFrame
if all_dfs:
combined_df = pd.concat(all_dfs, ignore_index=True)
# 优化数据类型和格式
#combined_df = optimize_data_types(combined_df)
print(f"\n成功合并 {processed_files} 个文件,总计 {len(combined_df)} 行数据")
# 写入Excel(单一工作表)
try:
# 创建Excel写入器
writer = pd.ExcelWriter(
output_file,
engine='xlsxwriter',
datetime_format='YYYY-MM-DD', # 统一日期格式
date_format='YYYY-MM-DD'
)
# 写入数据
combined_df.to_excel(writer, sheet_name='合并数据', index=False)
# 获取工作簿和工作表对象以进行格式设置
workbook = writer.book
worksheet = writer.sheets['合并数据']
# 设置列宽自适应
for idx, col in enumerate(combined_df.columns):
# 查找列的最大长度
max_len = max((
combined_df[col].astype(str).map(len).max(), # 数据最大长度
len(str(col)) # 列名长度
)) + 2 # 额外填充
# 设置列宽(最大50字符)
worksheet.set_column(idx, idx, min(max_len, 50))
# 冻结首行
worksheet.freeze_panes(1, 0)
# 保存Excel
writer.close()
print(f"转换完成! 输出文件: {output_file}")
print(f"总数据量: {len(combined_df)} 行, {len(combined_df.columns)} 列")
except Exception as e:
print(f"写入Excel失败: {str(e)}")
else:
print("\n警告: 所有文件处理失败,未生成输出文件!")
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description='TXT转Excel优化工具(合并到单一工作表)')
parser.add_argument('-i', '--input', required=True, help='输入目录')
parser.add_argument('-o', '--output', default='合并数据.xlsx', help='输出文件')
parser.add_argument('-s', '--sep', default='\t', help='分隔符(默认为制表符)')
parser.add_argument('-r', '--recursive', action='store_true', help='递归搜索子目录')
args = parser.parse_args()
process_files(args.input, args.output, sep=args.sep, recursive=args.recursive) 对以上代码进行简化,不显示合并信息,只展示所有.txt文件的数据写入到同一个Excel表中
最新发布