#!/usr/bin/env python3 """ 优化版TXT转Excel工具 - 不使用chardet库 """ import os import pandas as pd from glob import glob import re import sys import csv # 常见编码列表(按优先级排序) COMMON_ENCODINGS = ['utf-8', 'gbk', 'iso-8859-1',] def detect_encoding(file_path): """尝试检测文件编码(不使用chardet)""" # 方法1:尝试常见编码 for encoding in COMMON_ENCODINGS: try: with open(file_path, 'r', encoding=encoding) as f: f.read(1024) # 测试读取一小部分 return encoding except UnicodeDecodeError: continue # 方法2:使用错误忽略模式 try: with open(file_path, 'r', encoding='utf-8', errors='ignore') as f: f.read(1024) return 'utf-8' # 即使有错误也使用utf-8 except: pass # 方法3:最后尝试二进制模式 return 'latin1' # 二进制安全编码 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') # 检查数据是否为空 if df.empty: print(f"警告: 文件读取成功但数据为空") return None 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 sanitize_sheet_name(name): """创建有效的工作表名称""" # 移除非法字符 name = re.sub(r'[\\/*?:[\]]', '', name) # 截断到Excel允许的最大长度 return name[:31] 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_data = [] # 存储所有成功读取的数据信息 with pd.ExcelWriter(output_file) as writer: for file_path in txt_files: print(f"\n处理文件: {os.path.basename(file_path)}") # 读取文件 df = try_read_file(file_path, sep) if df is None: print("警告: 跳过此文件") continue # 创建有效的工作表名称 sheet_name = os.path.splitext(os.path.basename(file_path))[0] sheet_name = sanitize_sheet_name(sheet_name) print('song'+ sheet_name) # 检查工作表名称是否重复 orig_sheet_name = sheet_name counter = 1 while sheet_name in [s[0] for s in all_data]: sheet_name = f"{orig_sheet_name}_{counter}" counter += 1 # 写入Excel try: df.to_excel(writer, sheet_name=sheet_name, index=False) print(f"成功写入工作表: {sheet_name}") all_data.append((sheet_name, len(df))) except Exception as e: print(f"写入Excel失败: {str(e)}") # 最终报告 if all_data: print(f"\n转换完成! 输出文件: {output_file}") print("\n包含的工作表:") for sheet, rows in all_data: print(f"- {sheet}: {rows} 行数据") 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='output.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工具 - 将所有TXT合并到同一工作表中,不显示数据来源的txt文件名称
时间: 2025-07-20 08:21:49 浏览: 6
<think>根据用户要求,我们需要优化之前的Python脚本,主要修改点包括:
1. 不再添加“来源文件”列(即移除插入来源文件列的代码)
2. 解决Excel格式问题(如日期格式、科学计数法问题等)
3. 其他优化(如列宽自适应、冻结首行等)
因此,我们将调整代码:
- 删除插入来源文件列的代码
- 增强数据类型转换(特别是日期和数值)
- 使用xlsxwriter引擎设置Excel格式
具体步骤:
1. 读取文件时不再添加来源文件列
2. 合并后对数据进行类型优化(尝试将数值列转为数字,日期列转为日期)
3. 写入Excel时,通过xlsxwriter设置列格式(避免科学计数法、统一日期格式等)
4. 设置自适应列宽和冻结首行
注意:由于用户要求不显示来源文件名,因此我们不再添加该列。
修改后的代码:</think>以下是优化后的 Python 脚本,实现将多个 TXT 文件合并到单一 Excel 工作表,解决格式问题,且不添加来源文件列:
```python
#!/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)
```
### 主要优化点:
1. **移除来源文件列**:
```python
# 修改前(添加来源文件列)
df.insert(0, '来源文件', filename)
# 修改后(直接读取,不添加额外列)
df = pd.read_csv(...)
```
2. **格式问题修复**:
- 日期格式统一:`datetime_format='YYYY-MM-DD'`
- 科学计数法避免:`dtype=str` 初始读取为字符串
- 空值处理:`keep_default_na=False` 防止空值被转换
3. **Excel显示优化**:
```python
# 自适应列宽
worksheet.set_column(idx, idx, min(max_len, 50))
# 冻结首行
worksheet.freeze_panes(1, 0)
```
4. **数据类型智能转换**:
```python
# 数值转换
converted = pd.to_numeric(df[col], errors='coerce')
# 日期转换
converted = pd.to_datetime(df[col], format=fmt, errors='coerce')
```
### 使用示例:
```bash
# 基本用法
python txt_to_excel.py -i ./txt_files -o 合并结果.xlsx
# 递归搜索子目录
python txt_to_excel.py -i ./数据目录 -r -o 全部数据.xlsx
# 指定逗号分隔符
python txt_to_excel.py -i ./csv_files -s ',' -o 合并数据.xlsx
```
### 性能优化公式
处理 $n$ 个文件,每个文件平均 $m$ 行时的复杂度为:
$$O(n \times m) + O\left(\sum_{k=1}^{c} p_k\right)$$
其中 $c$ 是列数,$p_k$ 是第 $k$ 列的数据处理复杂度[^1]。
### 相关问题
1. 如何处理包含不同列结构的TXT文件?
脚本会自动对齐列名,不同结构的文件合并时会自动填充空值。可通过 `pd.concat(..., join='inner')` 只保留共有列[^2]。
2. 如何防止科学计数法转换问题?
在数值转换时添加格式保护:
```python
worksheet.set_column(col_idx, col_idx, None, num_format='0')
```
3. 如何处理超大文件(>1GB)?
可添加分块处理:
```python
chunksize = 100000
for chunk in pd.read_csv(..., chunksize=chunksize):
process_chunk(chunk)
```
4. 如何自定义日期格式?
修改写入器参数:
```python
writer = pd.ExcelWriter(..., datetime_format='DD/MM/YYYY')
```
5. 如何只转换特定文件类型?
修改pattern参数:
```bash
python txt_to_excel.py -i ./data -p "data_*.csv"
```
[^1]: 算法复杂度分析基于Pandas的concat操作和列处理优化
[^2]: 当处理列结构不同的文件时,Pandas的自动对齐功能确保数据整合的灵活性
阅读全文
相关推荐

















