2010-01-07 4 views
12

j'ai un fichier CSV qui ressemble à ceci:lecteur CSV de Python et l'itération

"Company, Inc.",,,,,,,,,,,,10/30/09 
A/R Summary Aged Analysis Report,,,,,,,,,,,,10:35:01 
All Clients,,,,,,,,,,,,USER 

Client Account,Customer Name,15-Jan,16 - 30,31 - 60,61 - 90,91 - 120,120 - Over,Total,Status,Credit Limit 
1000001111,CLIENT A,0,0,"3,711.32",0,0,"18,629.64","22,340.96",COD,"20,000.00" 
1000002222,CLIENT B,0,0,0,"3,591.27",0,0,"3,591.27",COD,0 
1000003333,CLIENT C,536.78,0,0,0,0,"11,216.60","11,753.38",COD,0 
1000004444,CLIENT D,0,514.94,"3,147.45",690,0,0,"4,352.39",COD,0 

Grand Total,,"139,203,856.06","84,607,749.30","110,746,640.18","58,474,379.45","52,025,869.06","292,653,734.82","737,712,228.87",,,, 

Mais je veux seulement traiter les lignes après la ligne « compte client ... » et avant « Grand total .. « . Voici le code que j'utilise maintenant:

inputFile = csv.reader(open(filename), dialect='excel') 
records = [line for line in inputFile if line and line[0].isdigit()] 
+1

Cela fonctionne. Quelle est la question? –

Répondre

6
import re 
import StringIO 

data=re.search("Client Account[^\r\n]+[\r\n]+(.*)(?=Grand Total)",open(filename).read(),re.DOTALL).group(1) 
datafile=StringIO.StringIO(data) 

inputFile = csv.reader(datafile, dialect='excel') 
records = [line for line in inputFile if line and line[0].isdigit()] 
+0

J'aime votre approche, c'est rapide et simple. Comment puis-je convertir le contenu du fichier de données en une liste? – Francis

+0

Vous avez ce message d'erreur quand j'ai essayé votre suggestion: "TypeError: coercing à Unicode: besoin de chaîne ou de tampon, instance trouvée" – Francis

+0

Désolé pour le délai, open (fichier de données) ne devrait être que "fichier de données", son instance de fichier déjà mise à jour. – YOU

10

vous pouvez le faire comme ça, en réglant le drapeau

import csv 
file = "file" 
f=0 
reader = csv.reader(open(file),delimiter=',') 
for row in reader: 
    if "Grand Total" in row: break 
    if "Client Account" in row: f=1;continue 
    if f: 
     if row[0].isdigit(): 
      print row 
+0

modifier - if "Grand Total" in row: break et, je pense que votre continue reviendra à «row in reader», ne jamais rien traiter. – KevinDTimm

+0

J'ai une question très similaire, ma ligne "Total général" n'est pas toujours "Total des subventions", il peut s'agir d'autres champs, mais il y a toujours une ligne vide avant. Comment puis-je casser la boucle en déterminant la ligne vide? – LWZ

3

Utilisez un petit générateur pour quelque chose comme ça. Celui-ci pourrait être généralisée un peu plus si vos besoins changent:

def lines_between(source, first, second): 
    for line in source: 
     if line and line[0] == first: 
      break 

    for line in source: 
     if line: and line[0] == second: 
      break 

     if line: # only non-empty lines 
      yield line 

for record in lines_between(inputFile, 'Client Account', 'Grand Total'): 
    # process record 

Vous n'avez pas demandé explicitement le filtre « lignes non vides », mais votre propre approche a fait cela, je suppose que vous le vouliez. Si vous ne voulez pas traiter les lignes « paresseusement » comme ça, mais vous voulez juste une liste avec tout construit à l'avance, faites ceci:

records = list(lines_between(inputFile, 'Client Account', 'Grand Total')) 

Par ailleurs, sur Windows, assurez-vous d'ouvrir le réel fichier source en utilisant en mode binaire, avec csv.reader(open(filename, 'rb'), dialect='excel') en tant que csv docs note.

12

Via les générateurs. Vous pouvez construire toutes sortes de complexité à partir de simples fonctions de générateur-filtre. Bien que considérablement plus complexe que votre filtre, il est plus extensible et peut facilement gérer des feuilles de calcul très complexes.

def skip_blank(rdr): 
    for row in rdr: 
     if len(row) == 0: continue 
     if all(len(col)==0 for col in row): continue 
     yield row 

def after_heading(text, rdr): 
    i= iter(rdr) 
    for row in i: 
     if any(column == text for column in row): 
      break 
    for row in i: 
     yield row 

def before_footing(text, rdr): 
    for row in rdr: 
     if any(column == text for column in row): 
      break 
     yield row 

def between(start, end, rdr): 
    for row in before_footing(end, after_heading(start, rdr)): 
     yield row 

for row in between('Grand Total', 'Client Account', skip_blank(inputFile)): 
    print row