1

我正在使用 CSV 文件中的某些值创建一个制表符分隔的文件。CSV 文件包含上个月下的所有订单,我需要正确格式化它才能导入当前使用的会计软件。以下是 CSV 文件中的数据示例:

Customer    Order Number    Item Line Number    Quantity    Product Description

cust1       Order #1                1               40              desc1
cust1       Order #2                1               101             desc2
cust2       Order #3                1               3               desc3
cust2       Order #3                2               8               desc3
cust2       Order #3                3               8               desc3
cust1       Order #4                1               75              desc4

现在,对于每个系列,Order Number我需要创建一个 TDV 文件的一部分,看起来像这样:(忽略括号,这些只是为了显示上面的值来自哪里)

1       cust1           HA5ZV1          Desc1           Due Date        ...
2       1 (Item #)      40 (Qty)        ...             ...             ...

1       cust1           HA6A17          Desc2           Due Date        ...
2       1 (Item #)      101 (Qty)       ...             ...             ...

1       cust2           HA6AM1          Desc3           Due Date        ...
2       1 (Item #)      3 (Qty)         ...             ...             ...
2       2 (Item #)      8 (Qty)         ...             ...             ...
2       3 (Item #)      8 (Qty)         ...             ...             ...

希望这是有道理的。到目前为止,我所做的是从原始 CSV 文件中创建一个字典,但是对于如何循环遍历我的字典并编写标题(标有“1”的行)一次,然后编写值感到困惑(标有“2”的行)每次Order Number出现相同的情况。到目前为止,这是我的代码:

data = csv.reader(open(import_dir))
fields = data.next()
new_file = export_dir+os.path.basename(import_dir)
tab_file = open(export_dir+os.path.basename(import_dir), 'a+')
for row in data:
    items = zip(fields, row)
    item = {}
    for (name, value) in items:
        item[name] = value.strip()
    tab_file.write('1\t'+item['Customer']+'\t'+item['Order Number']+'\t'
                   +item['Product Description']+'\t'+item['Due Date']+'\n'+
                   '2\t'+item['Item Line Number']+'\t'+item['Quantity']+'\t'+
                   ...

但是此代码将标题数据放在每个行项目之前,而不是仅将其放在每个订单的开头。如果每个客户只订购一件商品,那很好,但由于某些订单有多个订单商品,它会破坏格式。如果有人能指出我正确的方向,那就太好了。谢谢!

4

1 回答 1

0

您想使用该itertools.groupby()工具按客户编号对输入行进行分组:

import csv
import os
from itertools import groupby
from operator import itemgetter

new_file = os.path.join(export_dir, os.path.basename(import_dir))

with open(import_dir) as import, open(new_file, 'ab') as tab_file:
    data = csv.reader(import)
    writer = csv.writer(tab_file, delimiter='\t')

    fields = next(data)
    for customer, rows in groupby(data, key=itemgetter(0)):
        first_row = next(rows)
        item = {f: v.strip() for f, v in zip(fields, first_row)}
        writer.writerow([1, customer, item['Order Number'], item['Product Description'], item['Due Date'])
        writer.writerow([2, item['Item Line Number'], item['Quantity'], ...])
        for i, row in enumerate(rows, 3):
            item = {f: v.strip() for f, v in zip(fields, row)}
            writer.writerow([i, item['Item Line Number'], item['Quantity'], ...])

groupby()返回函数的当前结果key,以及具有该键值的所有行的可迭代。一旦下一行不再具有相同的键,就会启动一个新组。

我改变的其他事情:

  • 用于with自动关闭打开的文件,无论发生什么其他情况。
  • 用于os.path.join()构建路径
  • 用于csv.writer(..., delimiter='\t')编写制表符分隔的文件;它只是另一种 CSV 方言,真的。
  • 我使用字典理解将您的行变成字典。或者,只需使用csv.DictReader()来做同样的事情;无需从第一行读取字段。
于 2013-06-04T19:49:39.073 回答