使用openpyxl转Excel工作表为CSV时列被转浮点数,如何保留原字符串格式?
问题描述
我查阅了openpyxl和csv两个库的官方文档,仍未解决当前遇到的问题:我的业务流程是先将Excel工作簿内指定工作表转换为CSV文件,再对生成的CSV执行ETL操作。
遇到的问题是:最终输出的CSV中有一列同时包含数字和字符串内容,在Excel中查看显示正常,但在Notepad++中打开可以看到数值类内容被追加了浮点数后缀,我需要该列完全保留原始字符串格式。
我已经在ETL代码中将该列强制转换为字符串类型,但该操作仅能将Excel转CSV阶段生成的浮点数转为字符串,仍然保留了.0后缀。
ETL中强制转字符串的代码如下:
df['Old Serial Number'] = df['Old Serial Number'].astype(str)# Old Serial Number是同时包含字符串和整数的目标列
请问是否可以在CSV文件生成阶段就将指定列转换为字符串类型,避免生成浮点数?
我当前使用的Excel转CSV代码如下:
import openpyxl import csv import glob import datetime import shutil import time import logging def convert_to_csv(): for filename in glob.glob(r"C:\Users\excel_file_that_i_want*"): wb = openpyxl.load_workbook(filename) sh = wb['Report']# 要提取的Excel工作表名称 with open('excel_file_that_i_want' + datetime.datetime.today().strftime('%d%m%Y%H%M%S.csv'), 'w', encoding='utf-8', newline="") as f: col = csv.writer(f, quotechar='"', quoting=csv.QUOTE_ALL) for row in sh.rows: col.writerow([cell.value for cell in row]) logging.info('Excel file converted to CSV')
解决方案
完全可以在CSV生成阶段就处理好格式问题,避免后续ETL还要处理.0后缀。
问题根源是Excel底层的数值默认以浮点型存储,openpyxl读取数值类型单元格时默认返回float类型,直接写入CSV就会自带.0后缀。
你可以修改转CSV的代码,单独处理目标列的格式即可,修改后代码如下:
import openpyxl import csv import glob import datetime import logging def convert_to_csv(): for filename in glob.glob(r"C:\Users\excel_file_that_i_want*"): wb = openpyxl.load_workbook(filename) sh = wb['Report'] # 定位目标列索引,不用硬编码,适配列顺序变化的情况 target_col_idx = None header_row = [cell.value for cell in next(sh.rows)] if 'Old Serial Number' in header_row: target_col_idx = header_row.index('Old Serial Number') with open('excel_file_that_i_want' + datetime.datetime.today().strftime('%d%m%Y%H%M%S.csv'), 'w', encoding='utf-8', newline="") as f: csv_writer = csv.writer(f, quotechar='"', quoting=csv.QUOTE_ALL) # 写入表头 csv_writer.writerow(header_row) # 遍历处理数据行 for row in list(sh.rows)[1:]: processed_row = [] for col_idx, cell in enumerate(row): val = cell.value # 仅针对目标列做浮点数去.0处理 if col_idx == target_col_idx and isinstance(val, float): # 判断是否为整数型浮点数 if val.is_integer(): processed_row.append(str(int(val))) else: processed_row.append(str(val)) else: processed_row.append(val) csv_writer.writerow(processed_row) logging.info('Excel file converted to CSV')
修改说明:
- 先读取表头自动定位目标列的位置,不用手动数列索引,更稳定
- 遍历数据行时单独判断目标列的数值类型,如果是整数型浮点数就先转整数再转字符串,直接抹掉.0后缀
- 其他列处理逻辑不变,不会影响其余字段的格式
处理后生成的CSV里目标列就不会出现.0后缀,后续ETL阶段也不需要再额外做格式转换。
内容的提问来源于stack exchange,提问作者Mizanur Choudhury
相关产品推荐
相关产品推荐

