【问题标题】:Python Openpyxl convert CSV to XLSX & removing "$ ," from cells containing numbersPython Openpyxl 将 CSV 转换为 XLSX 并从包含数字的单元格中删除“$”
【发布时间】:2021-05-15 20:37:34
【问题描述】:

我必须将由第三方生成的 csv 文件读取到 XLSX 文件中,该文件包含字符串、整数和价格(有时带有 $ 符号)的混合。这是存储在 csv 文件 a_test_f.csv 中的示例数据:

ColA,ColB
1,$11.00
2,22
3,"$1,000.56"
4,44

这是我编写的代码。我的问题是,这是执行此转换的最有效方式吗?是否有替代方法可以使用更少的处理能力/内存?这一点尤其重要,因为真正的 csv 文件将包含数千条记录和数百列,并且每天必须执行数万次转换操作。

import csv
import openpyxl

#
# Convert the data in csv file format that contains a mix of
# strings, integers and dollar amounts into xlsx file format
#

csvfile  = 'a_test_f.csv'
xlsxfile = 'new_xlsx_f.xlsx'

wb = openpyxl.Workbook()
ws = wb.active

# remove $ and , from numbers
class Clean:
    def __init__(self, data=''):
        self.__obj = data
    def __repr__(self):
        return f"{self.__obj}"
    def getData(self):
        return self.__obj

    def dollar(self):
        try:
            return Clean(data=self.__obj.replace('$',''))
        except TypeError as err:
            print(err)

    def comma(self):
        try:
            return Clean(data=self.__obj.replace(',',''))
        except TypeError as err:
            print(err)

    def digit(self):
        try:
            float(self.__obj)
            return True
        except ValueError:
            return False            

with open(csvfile) as f:
    reader = csv.reader(f, delimiter=',', quotechar='"')
    row_count=1
    for row in reader:
        for i in range(len(row)):
            if Clean(data=row[i]).dollar().comma().digit():
                content = float(repr(Clean(data=row[i]).dollar().comma()))
            else:
                content = row[i]                
            ws.cell(row=row_count,column=i+1).value = content
        row_count +=1

wb.save(xlsxfile)

print('Finished!')

【问题讨论】:

  • 创建对象只是为了运行替换会非常慢。您最好在一个简单的循环中执行此操作。
  • 查理,非常感谢您的反馈。我会尝试使用函数并比较时间。

标签: python csv openpyxl xlsx file-conversion


【解决方案1】:

按照 Charlie 的建议,我使用 Functions 而不是 Class 重写了转换,然后尝试使用 Class 和 Functions 方法处理 csv 文件中的一百万个项目。结果:

  • Function 和 Class 方法使用了等量的 CPU 和内存
  • 类方法比使用函数慢 9.4%

函数取胜。谢谢查理!

函数方法如下:

import csv
import openpyxl

#
# Convert the data in csv file format that contains a mix of
# strings, integers and dollar amounts into xlsx file format
#

csvfile  = 'large_test_export.csv'
xlsxfile = 'new_xlsx_f.xlsx'

wb = openpyxl.Workbook()
ws = wb.active

# remove $ and , from numbers

def strip_stuff(a_string):
    try:
        temp = a_string.replace(',','')
    except TypeError as err:
        print(err)      
    
    try:
        temp2 = temp.replace('$','')
    except TypeError as err:
        print(err)      

    try:
        temp3 = float(temp2)
        return temp3
    except ValueError as err:
        return temp2


def is_number(b_string):
    temp = strip_stuff(b_string)
    try:
        float (temp)
        return True
    except ValueError:
        return False

with open(csvfile) as f:
    reader = csv.reader(f, delimiter=',', quotechar='"')
    row_count=1
    for row in reader:
        for i in range(len(row)):
            if is_number(row[i]):
                content = strip_stuff(row[i])
            else:
                content = row[i]                
            ws.cell(row=row_count,column=i+1).value = content
        row_count +=1

wb.save(xlsxfile)

print('Finished!')

【讨论】:

  • 这还是非常低效的。在 CSV 文件中,结构应该是规则的,因此您应该能够为特定列运行特定代码。
  • 我同意这并不理想。然而,源数据是由数千名独立人员输入的,负责存储源数据的第 3 方公司并未对每列应包含的内容实施严格的规定。他们只是将数字存储为字符串。因此,有各种格式的字符串和数字(​​int、$、%),我发现我必须解决这些问题才能对它们进行处理。所以是生活吧:)
  • 你调用函数的次数还是太多了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-06
  • 2013-07-15
  • 2018-08-27
  • 1970-01-01
  • 1970-01-01
  • 2020-11-07
  • 1970-01-01
相关资源
最近更新 更多