【Python办公】使用pandas批量读取csv保存为Excel

目录

专栏导读

🌸 欢迎来到Python办公自动化专栏---Python处理办公问题,解放您的双手

🏳️‍🌈 博客主页:请点击------> 一晌小贪欢的博客主页求关注

👍 该系列文章专栏:请点击------>Python办公自动化专栏求订阅

🕷 此外还有爬虫专栏:请点击------>Python爬虫基础专栏求订阅

📕 此外还有python基础专栏:请点击------>Python基础学习专栏求订阅

文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏

❤️ 欢迎各位佬关注! ❤️

Python使用pandas批量读取CSV保存为Excel

概述

在数据处理工作中,经常需要将多个CSV文件转换为Excel格式,或者将多个CSV文件合并到一个Excel文件的不同工作表中。pandas库提供了强大的数据处理功能,可以轻松实现CSV到Excel的批量转换。本文将详细介绍如何使用pandas进行批量CSV文件处理,包括基础转换、高级功能和性能优化等内容。

环境准备

安装必要的库

bash 复制代码
pip install pandas openpyxl xlsxwriter

库说明:

  • pandas:核心数据处理库
  • openpyxl:用于读写Excel 2010 xlsx/xlsm/xltx/xltm文件
  • xlsxwriter:用于创建Excel文件,支持更多格式设置

导入必要的模块

python 复制代码
import pandas as pd
import os
import glob
from pathlib import Path
import warnings
warnings.filterwarnings('ignore')

基础用法

1. 单个CSV文件转Excel

python 复制代码
def csv_to_excel_single(csv_file, excel_file):
    """
    将单个CSV文件转换为Excel文件
    
    参数:
    csv_file: CSV文件路径
    excel_file: 输出Excel文件路径
    """
    try:
        # 读取CSV文件
        df = pd.read_csv(csv_file, encoding='utf-8')
        
        # 保存为Excel文件
        df.to_excel(excel_file, index=False, engine='openpyxl')
        
        print(f"转换成功: {csv_file} -> {excel_file}")
        return True
    except Exception as e:
        print(f"转换失败: {csv_file}, 错误: {str(e)}")
        return False

# 使用示例
csv_to_excel_single('data.csv', 'data.xlsx')

2. 批量转换CSV文件到独立Excel文件

python 复制代码
def batch_csv_to_excel(input_folder, output_folder):
    """
    批量将CSV文件转换为独立的Excel文件
    
    参数:
    input_folder: 包含CSV文件的输入文件夹
    output_folder: Excel文件输出文件夹
    """
    # 确保输出文件夹存在
    os.makedirs(output_folder, exist_ok=True)
    
    # 获取所有CSV文件
    csv_files = glob.glob(os.path.join(input_folder, "*.csv"))
    
    success_count = 0
    fail_count = 0
    
    print(f"发现 {len(csv_files)} 个CSV文件")
    
    for csv_file in csv_files:
        # 生成对应的Excel文件名
        base_name = os.path.splitext(os.path.basename(csv_file))[0]
        excel_file = os.path.join(output_folder, f"{base_name}.xlsx")
        
        # 转换文件
        if csv_to_excel_single(csv_file, excel_file):
            success_count += 1
        else:
            fail_count += 1
    
    print(f"\n转换完成!成功: {success_count}, 失败: {fail_count}")

# 使用示例
batch_csv_to_excel('csv_files/', 'excel_files/')

高级功能

3. 多个CSV文件合并到一个Excel文件的不同工作表

python 复制代码
def merge_csv_to_excel_sheets(input_folder, output_file):
    """
    将多个CSV文件合并到一个Excel文件的不同工作表中
    
    参数:
    input_folder: 包含CSV文件的输入文件夹
    output_file: 输出Excel文件路径
    """
    csv_files = glob.glob(os.path.join(input_folder, "*.csv"))
    
    if not csv_files:
        print("未找到CSV文件")
        return
    
    # 创建Excel写入器
    with pd.ExcelWriter(output_file, engine='openpyxl') as writer:
        for csv_file in csv_files:
            try:
                # 读取CSV文件
                df = pd.read_csv(csv_file, encoding='utf-8')
                
                # 使用文件名作为工作表名(去掉扩展名)
                sheet_name = os.path.splitext(os.path.basename(csv_file))[0]
                
                # 确保工作表名不超过31个字符(Excel限制)
                if len(sheet_name) > 31:
                    sheet_name = sheet_name[:31]
                
                # 写入工作表
                df.to_excel(writer, sheet_name=sheet_name, index=False)
                
                print(f"已添加工作表: {sheet_name}")
                
            except Exception as e:
                print(f"处理文件失败: {csv_file}, 错误: {str(e)}")
    
    print(f"\n合并完成!输出文件: {output_file}")

# 使用示例
merge_csv_to_excel_sheets('csv_files/', 'merged_data.xlsx')

4. 带格式设置的转换

python 复制代码
def csv_to_excel_with_format(csv_file, excel_file):
    """
    将CSV转换为带格式的Excel文件
    """
    # 读取CSV文件
    df = pd.read_csv(csv_file, encoding='utf-8')
    
    # 创建Excel写入器
    with pd.ExcelWriter(excel_file, engine='xlsxwriter') as writer:
        # 写入数据
        df.to_excel(writer, sheet_name='数据', index=False)
        
        # 获取工作簿和工作表对象
        workbook = writer.book
        worksheet = writer.sheets['数据']
        
        # 定义格式
        header_format = workbook.add_format({
            'bold': True,
            'text_wrap': True,
            'valign': 'top',
            'fg_color': '#D7E4BC',
            'border': 1
        })
        
        # 设置列宽
        for i, col in enumerate(df.columns):
            # 计算列宽(基于列名和数据的最大长度)
            max_len = max(
                df[col].astype(str).map(len).max(),  # 数据最大长度
                len(str(col))  # 列名长度
            )
            worksheet.set_column(i, i, min(max_len + 2, 50))  # 限制最大宽度为50
        
        # 设置表头格式
        for col_num, value in enumerate(df.columns.values):
            worksheet.write(0, col_num, value, header_format)
        
        # 冻结首行
        worksheet.freeze_panes(1, 0)
    
    print(f"带格式转换完成: {excel_file}")

# 使用示例
csv_to_excel_with_format('data.csv', 'formatted_data.xlsx')

5. 数据清洗和预处理

python 复制代码
def csv_to_excel_with_cleaning(csv_file, excel_file):
    """
    转换CSV到Excel并进行数据清洗
    """
    try:
        # 读取CSV文件
        df = pd.read_csv(csv_file, encoding='utf-8')
        
        print(f"原始数据形状: {df.shape}")
        
        # 数据清洗步骤
        # 1. 删除完全重复的行
        df = df.drop_duplicates()
        
        # 2. 删除全为空值的行
        df = df.dropna(how='all')
        
        # 3. 删除全为空值的列
        df = df.dropna(axis=1, how='all')
        
        # 4. 清理字符串列的前后空格
        string_columns = df.select_dtypes(include=['object']).columns
        for col in string_columns:
            df[col] = df[col].astype(str).str.strip()
        
        # 5. 替换空字符串为NaN
        df = df.replace('', pd.NA)
        
        print(f"清洗后数据形状: {df.shape}")
        
        # 保存到Excel
        with pd.ExcelWriter(excel_file, engine='openpyxl') as writer:
            # 原始数据
            df.to_excel(writer, sheet_name='清洗后数据', index=False)
            
            # 数据概览
            summary_df = pd.DataFrame({
                '列名': df.columns,
                '数据类型': [str(dtype) for dtype in df.dtypes],
                '非空值数量': [df[col].count() for col in df.columns],
                '空值数量': [df[col].isnull().sum() for col in df.columns],
                '唯一值数量': [df[col].nunique() for col in df.columns]
            })
            summary_df.to_excel(writer, sheet_name='数据概览', index=False)
        
        print(f"数据清洗和转换完成: {excel_file}")
        return True
        
    except Exception as e:
        print(f"处理失败: {str(e)}")
        return False

# 使用示例
csv_to_excel_with_cleaning('messy_data.csv', 'cleaned_data.xlsx')

完整的批量处理解决方案

6. 多功能批量处理类

python 复制代码
class CSVToExcelConverter:
    """
    CSV到Excel的批量转换器
    """
    
    def __init__(self, input_folder, output_folder=None):
        self.input_folder = Path(input_folder)
        self.output_folder = Path(output_folder) if output_folder else self.input_folder / 'excel_output'
        self.output_folder.mkdir(exist_ok=True)
        
        # 统计信息
        self.total_files = 0
        self.success_count = 0
        self.fail_count = 0
        self.error_log = []
    
    def get_csv_files(self):
        """获取所有CSV文件"""
        return list(self.input_folder.glob('*.csv'))
    
    def convert_single_file(self, csv_file, clean_data=True, add_format=True):
        """
        转换单个文件
        
        参数:
        csv_file: CSV文件路径
        clean_data: 是否进行数据清洗
        add_format: 是否添加格式
        """
        try:
            # 读取CSV
            df = pd.read_csv(csv_file, encoding='utf-8')
            
            # 数据清洗
            if clean_data:
                df = self._clean_data(df)
            
            # 生成输出文件名
            excel_file = self.output_folder / f"{csv_file.stem}.xlsx"
            
            # 保存Excel
            if add_format:
                self._save_with_format(df, excel_file)
            else:
                df.to_excel(excel_file, index=False, engine='openpyxl')
            
            self.success_count += 1
            print(f"✓ 转换成功: {csv_file.name}")
            return True
            
        except Exception as e:
            self.fail_count += 1
            error_msg = f"✗ 转换失败: {csv_file.name}, 错误: {str(e)}"
            print(error_msg)
            self.error_log.append(error_msg)
            return False
    
    def _clean_data(self, df):
        """数据清洗"""
        # 删除重复行
        df = df.drop_duplicates()
        
        # 删除全空行和列
        df = df.dropna(how='all').dropna(axis=1, how='all')
        
        # 清理字符串
        string_cols = df.select_dtypes(include=['object']).columns
        for col in string_cols:
            df[col] = df[col].astype(str).str.strip().replace('nan', '')
        
        return df
    
    def _save_with_format(self, df, excel_file):
        """保存带格式的Excel文件"""
        with pd.ExcelWriter(excel_file, engine='xlsxwriter') as writer:
            df.to_excel(writer, sheet_name='数据', index=False)
            
            workbook = writer.book
            worksheet = writer.sheets['数据']
            
            # 表头格式
            header_format = workbook.add_format({
                'bold': True,
                'text_wrap': True,
                'valign': 'top',
                'fg_color': '#D7E4BC',
                'border': 1
            })
            
            # 设置列宽和表头格式
            for col_num, value in enumerate(df.columns.values):
                # 计算列宽
                max_len = max(
                    df.iloc[:, col_num].astype(str).map(len).max(),
                    len(str(value))
                )
                worksheet.set_column(col_num, col_num, min(max_len + 2, 50))
                
                # 设置表头格式
                worksheet.write(0, col_num, value, header_format)
            
            # 冻结首行
            worksheet.freeze_panes(1, 0)
    
    def batch_convert(self, clean_data=True, add_format=True):
        """批量转换"""
        csv_files = self.get_csv_files()
        self.total_files = len(csv_files)
        
        if self.total_files == 0:
            print("未找到CSV文件")
            return
        
        print(f"开始批量转换,共 {self.total_files} 个文件")
        print("=" * 50)
        
        for csv_file in csv_files:
            self.convert_single_file(csv_file, clean_data, add_format)
        
        self._print_summary()
    
    def merge_to_single_excel(self, output_file='merged_data.xlsx'):
        """合并所有CSV到单个Excel文件"""
        csv_files = self.get_csv_files()
        
        if not csv_files:
            print("未找到CSV文件")
            return
        
        output_path = self.output_folder / output_file
        
        with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
            for csv_file in csv_files:
                try:
                    df = pd.read_csv(csv_file, encoding='utf-8')
                    sheet_name = csv_file.stem[:31]  # Excel工作表名限制
                    df.to_excel(writer, sheet_name=sheet_name, index=False)
                    print(f"✓ 已添加工作表: {sheet_name}")
                except Exception as e:
                    print(f"✗ 处理失败: {csv_file.name}, 错误: {str(e)}")
        
        print(f"\n合并完成!输出文件: {output_path}")
    
    def _print_summary(self):
        """打印处理摘要"""
        print("=" * 50)
        print(f"批量转换完成!")
        print(f"总文件数: {self.total_files}")
        print(f"成功转换: {self.success_count}")
        print(f"转换失败: {self.fail_count}")
        print(f"输出目录: {self.output_folder}")
        
        if self.error_log:
            print("\n错误详情:")
            for error in self.error_log:
                print(f"  {error}")

# 使用示例
if __name__ == "__main__":
    # 创建转换器实例
    converter = CSVToExcelConverter(
        input_folder='csv_files',
        output_folder='excel_output'
    )
    
    # 方式1: 批量转换为独立Excel文件
    converter.batch_convert(clean_data=True, add_format=True)
    
    # 方式2: 合并为单个Excel文件
    # converter.merge_to_single_excel('all_data.xlsx')

性能优化

7. 多线程批量处理

python 复制代码
import concurrent.futures
from threading import Lock

class MultiThreadCSVConverter(CSVToExcelConverter):
    """
    多线程CSV转换器
    """
    
    def __init__(self, input_folder, output_folder=None, max_workers=4):
        super().__init__(input_folder, output_folder)
        self.max_workers = max_workers
        self.lock = Lock()  # 线程锁,用于安全地更新计数器
    
    def _thread_safe_update(self, success=True, error_msg=None):
        """线程安全的计数器更新"""
        with self.lock:
            if success:
                self.success_count += 1
            else:
                self.fail_count += 1
                if error_msg:
                    self.error_log.append(error_msg)
    
    def _convert_file_thread(self, csv_file, clean_data=True, add_format=True):
        """线程中执行的转换函数"""
        try:
            # 读取CSV
            df = pd.read_csv(csv_file, encoding='utf-8')
            
            # 数据清洗
            if clean_data:
                df = self._clean_data(df)
            
            # 生成输出文件名
            excel_file = self.output_folder / f"{csv_file.stem}.xlsx"
            
            # 保存Excel
            if add_format:
                self._save_with_format(df, excel_file)
            else:
                df.to_excel(excel_file, index=False, engine='openpyxl')
            
            self._thread_safe_update(success=True)
            print(f"✓ [线程] 转换成功: {csv_file.name}")
            return True
            
        except Exception as e:
            error_msg = f"✗ [线程] 转换失败: {csv_file.name}, 错误: {str(e)}"
            self._thread_safe_update(success=False, error_msg=error_msg)
            print(error_msg)
            return False
    
    def batch_convert_multithread(self, clean_data=True, add_format=True):
        """多线程批量转换"""
        csv_files = self.get_csv_files()
        self.total_files = len(csv_files)
        
        if self.total_files == 0:
            print("未找到CSV文件")
            return
        
        print(f"开始多线程批量转换,共 {self.total_files} 个文件")
        print(f"使用线程数: {self.max_workers}")
        print("=" * 50)
        
        # 使用线程池执行转换
        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:
            # 提交所有任务
            futures = [
                executor.submit(self._convert_file_thread, csv_file, clean_data, add_format)
                for csv_file in csv_files
            ]
            
            # 等待所有任务完成
            concurrent.futures.wait(futures)
        
        self._print_summary()

# 使用示例
if __name__ == "__main__":
    # 多线程转换器
    mt_converter = MultiThreadCSVConverter(
        input_folder='csv_files',
        output_folder='excel_output',
        max_workers=8  # 根据CPU核心数调整
    )
    
    # 执行多线程批量转换
    mt_converter.batch_convert_multithread(clean_data=True, add_format=True)

常见问题解决方案

编码问题

python 复制代码
def read_csv_with_encoding_detection(file_path):
    """
    自动检测CSV文件编码并读取
    """
    import chardet
    
    # 检测文件编码
    with open(file_path, 'rb') as f:
        raw_data = f.read(10000)  # 读取前10KB用于检测
        encoding = chardet.detect(raw_data)['encoding']
    
    print(f"检测到编码: {encoding}")
    
    # 尝试不同的编码
    encodings = [encoding, 'utf-8', 'gbk', 'gb2312', 'utf-8-sig']
    
    for enc in encodings:
        try:
            df = pd.read_csv(file_path, encoding=enc)
            print(f"成功使用编码: {enc}")
            return df
        except UnicodeDecodeError:
            continue
    
    raise ValueError(f"无法读取文件 {file_path},尝试了编码: {encodings}")

大文件处理

python 复制代码
def process_large_csv(csv_file, excel_file, chunk_size=10000):
    """
    分块处理大型CSV文件
    """
    # 创建Excel写入器
    with pd.ExcelWriter(excel_file, engine='xlsxwriter') as writer:
        # 分块读取CSV
        chunk_iter = pd.read_csv(csv_file, chunksize=chunk_size)
        
        for i, chunk in enumerate(chunk_iter):
            # 处理每个块
            sheet_name = f'数据_{i+1}'
            chunk.to_excel(writer, sheet_name=sheet_name, index=False)
            print(f"已处理块 {i+1},行数: {len(chunk)}")
    
    print(f"大文件处理完成: {excel_file}")

内存优化

python 复制代码
def memory_efficient_conversion(csv_files, output_file):
    """
    内存高效的批量转换
    """
    with pd.ExcelWriter(output_file, engine='xlsxwriter') as writer:
        for csv_file in csv_files:
            # 逐个处理文件,避免同时加载所有数据
            df = pd.read_csv(csv_file)
            
            # 立即写入Excel并释放内存
            sheet_name = Path(csv_file).stem[:31]
            df.to_excel(writer, sheet_name=sheet_name, index=False)
            
            # 显式删除DataFrame释放内存
            del df
            
            print(f"已处理: {csv_file}")

最佳实践

1. 错误处理和日志记录

python 复制代码
import logging
from datetime import datetime

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler(f'csv_conversion_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log'),
        logging.StreamHandler()
    ]
)

def robust_csv_to_excel(csv_file, excel_file):
    """
    带完整错误处理的转换函数
    """
    try:
        logging.info(f"开始处理: {csv_file}")
        
        # 检查文件是否存在
        if not os.path.exists(csv_file):
            raise FileNotFoundError(f"CSV文件不存在: {csv_file}")
        
        # 检查文件大小
        file_size = os.path.getsize(csv_file)
        logging.info(f"文件大小: {file_size / 1024 / 1024:.2f} MB")
        
        # 读取CSV
        df = pd.read_csv(csv_file, encoding='utf-8')
        logging.info(f"数据形状: {df.shape}")
        
        # 保存Excel
        df.to_excel(excel_file, index=False, engine='openpyxl')
        
        logging.info(f"转换成功: {excel_file}")
        return True
        
    except Exception as e:
        logging.error(f"转换失败: {csv_file}, 错误: {str(e)}")
        return False

2. 配置文件管理

python 复制代码
import json

# config.json
config = {
    "input_folder": "csv_files",
    "output_folder": "excel_output",
    "clean_data": True,
    "add_format": True,
    "max_workers": 8,
    "chunk_size": 10000,
    "supported_encodings": ["utf-8", "gbk", "gb2312", "utf-8-sig"]
}

def load_config(config_file='config.json'):
    """加载配置文件"""
    try:
        with open(config_file, 'r', encoding='utf-8') as f:
            return json.load(f)
    except FileNotFoundError:
        # 创建默认配置文件
        with open(config_file, 'w', encoding='utf-8') as f:
            json.dump(config, f, indent=2, ensure_ascii=False)
        return config

3. 进度监控

python 复制代码
from tqdm import tqdm

def batch_convert_with_progress(csv_files, output_folder):
    """
    带进度条的批量转换
    """
    success_count = 0
    
    # 使用tqdm显示进度
    with tqdm(total=len(csv_files), desc="转换进度") as pbar:
        for csv_file in csv_files:
            excel_file = os.path.join(output_folder, f"{Path(csv_file).stem}.xlsx")
            
            if csv_to_excel_single(csv_file, excel_file):
                success_count += 1
            
            # 更新进度条
            pbar.set_postfix({
                '成功': success_count,
                '当前': Path(csv_file).name
            })
            pbar.update(1)
    
    return success_count

总结

本文详细介绍了使用pandas进行CSV到Excel批量转换的各种方法,从基础的单文件转换到高级的多线程批量处理。主要要点包括:

  1. 基础转换 :使用pd.read_csv()to_excel()实现基本转换
  2. 批量处理:通过循环和文件操作实现批量转换
  3. 数据清洗:在转换过程中进行数据预处理
  4. 格式设置:使用xlsxwriter添加Excel格式
  5. 性能优化:多线程处理和内存管理
  6. 错误处理:完善的异常处理和日志记录

选择建议:

  • 小批量文件(<100个):使用基础批量转换
  • 大批量文件(>100个):使用多线程转换
  • 需要合并数据:使用多工作表合并方案
  • 需要格式化:使用xlsxwriter引擎
  • 处理大文件:使用分块读取方案

通过合理选择和组合这些方法,可以高效地完成各种CSV到Excel的转换需求。

结尾

希望对初学者有帮助;致力于办公自动化的小小程序员一枚

希望能得到大家的【❤️一个免费关注❤️】感谢!

求个 🤞 关注 🤞 +❤️ 喜欢 ❤️ +👍 收藏 👍

此外还有办公自动化专栏,欢迎大家订阅:Python办公自动化专栏

此外还有爬虫专栏,欢迎大家订阅:Python爬虫基础专栏

此外还有Python基础专栏,欢迎大家订阅:Python基础学习专栏

相关推荐
阿蒙Amon39 分钟前
【Python小工具】使用 OpenCV 获取视频时长的详细指南
python·opencv·音视频
橘子编程2 小时前
Python-Word文档、PPT、PDF以及Pillow处理图像详解
开发语言·python
蓝婷儿2 小时前
Python 机器学习核心入门与实战进阶 Day 2 - KNN(K-近邻算法)分类实战与调参
python·机器学习·近邻算法
之歆2 小时前
Python-封装和解构-set及操作-字典及操作-解析式生成器-内建函数迭代器-学习笔记
笔记·python·学习
天天爱吃肉82183 小时前
ZigBee通信技术全解析:从协议栈到底层实现,全方位解读物联网核心无线技术
python·嵌入式硬件·物联网·servlet
Allen_LVyingbo4 小时前
Python常用医疗AI库以及案例解析(2025年版、上)
开发语言·人工智能·python·学习·健康医疗
智能砖头4 小时前
LangChain 与 LlamaIndex 深度对比与选型指南
人工智能·python
不坑老师4 小时前
利用不坑盒子的Copilot,快速排值班表
microsoft·word·powerpoint·excel·copilot·wps
风逸hhh5 小时前
python打卡day58@浙大疏锦行
开发语言·python
烛阴6 小时前
一文搞懂 Python 闭包:让你的代码瞬间“高级”起来!
前端·python