2013-06-04 116 views
1

我正在从CSV文件的特定值中创建制表符分隔文件。 CSV文件包含上个月所有订单,我需要正确格式化才能导入当前使用的会计软件。下面是数据从CSV文件中的示例:将CSV转换为TDV - 格式问题

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'+ 
        ... 

但这种代码把标题数据每行一个项目之前,而不是将其仅在每个订单的开始。如果每个客户只订购一件商品,那就没有问题,但由于某些订单有多个订单项,因此会导致格式化。如果任何人都能指出我会朝着正确的方向发展,那将是很棒的。谢谢!

+0

使用'csv.writer(tab_file,delimiter ='\ t')'它会写入TSV文件.. –

回答

0

您希望使用客户数itertools.groupby() tool,以便将输入线:

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()来做同样的事情;不需要从第一行读取字段。
+0

太棒了!谢谢!刚做了一些初步测试,看起来效果很好。 –

+0

感谢您帮助清理它。 –