In questo articolo avevamo visto come esportare in csv i dati di intestazione di una fattura elettronica per poi poterla leggere con Excel.
Il programma utilizzava la libreria eTree per scorrere i valori per poi scriverli su un file di testo csv.
Il problema si pone sulle righe di dettaglio, che naturalmente possono essere più di una.
Qui il problema principale è come accedervi ma anche come successivamente scriverle nel file in uscita.
Utilizzando una libreria diversa, xmltodict possiamo accedere direttamente agli oggetti dell’xml in vari formati o utilizzando degli xpath.
Nel nostro caso ho scelto di scorrere il dictionary creato e individuare il tipo di valore ottenuto dalle singole interrogazioni.
Siccome gli oggetti del dictionary sono raggruppati in liste o liste di dictionary, parlando per esempio dei valori DettagliLinee, della fatturazione elettronica.
Possiamo avere un dictionary con all’interno i campi di dettaglio di una sola riga oppure una lista di dictionary nel caso di fatture con più righe.
L’idea è quindi di ricreare una struttura Python che contenga ogni fattura in un oggetto lista, dove ogni valore di DettaglioLinee sia contenuto in un dictionary facilmente accessibile.
#!/usr/bin/env python3
import os, glob
import xmltodict
DatiFatture = []
StrutturaCampi = []
# Creiamo una struttura dei campi che ci interessa esportare seguendo la struttura xml, se i campi sono composti da più righe,
# come nel caso degli articoli, prendiamo il primo campo 'padre' necessario (DettaglioLinee) il programma si occuperà di prendere
# tutti i sottocampi contenuti.
StrutturaCampi = [['FatturaElettronicaHeader', 'DatiTrasmissione', 'ProgressivoInvio'],
['FatturaElettronicaHeader', 'DatiTrasmissione', 'CodiceDestinatario'],
['FatturaElettronicaHeader', 'CedentePrestatore', 'DatiAnagrafici', 'Anagrafica', 'Denominazione'],
['FatturaElettronicaHeader', 'CessionarioCommittente', 'Sede', 'Indirizzo'],
['FatturaElettronicaBody', 'DatiPagamento', 'CondizioniPagamento'],
['FatturaElettronicaBody', 'DatiBeniServizi', 'DettaglioLinee']]
# Qui indichiamo la certella con i file XML da elaborare
path = "C:\\Users\\user\\Downloads"
# Leggiamo tutti i file
for filename in glob.glob(os.path.join(path, "*.xml")):
Fattura = []
with open(filename) as fd:
doc = xmltodict.parse(fd.read())
# Prendiamo la chiave radice principale in automatico (es.: p:FatturaElettronica or ns1:FatturaElettronica)
root = list(doc.keys())[0]
# Facciamo il parse della struttura campi
for fieldpath in StrutturaCampi:
fieldname = ''
# Prepariamo la stringa da interrogare successivamente con il metodo eval
string_2_eval = 'doc["' + root + '"]'
row_dict = {}
for field in fieldpath:
# memorizziamo il nome dell'ultimo campo della lista (Es.ProgressivoInvio):
fieldname = fieldpath[-1]
# accodiamo il percorso per andare a recuperare il valore nell'xml
string_2_eval += '["' + field.replace('\n', '') + '"]'
# Verifichiamo se il valore esiste e che non dia errori
try:
value = eval(string_2_eval)
except:
value = False
# Verifichiamo che tipo di dato abbiamo:
# se è un dictionary vuol dire che è una fattura con una sola riga di dettaglio
if isinstance(value, dict) and value:
print("E' UN DICTIONARY !")
for k, v in value.items():
row_dict[k] = v
Fattura.append(('Righe fattura', row_dict))
# se è una lista vuol dire che è una fattura con una più righe di dettaglio
elif isinstance(value, list) and value:
print("E' UNA LISTA !")
for l in value:
for k, v in l.items():
row_dict[k] = v
Fattura.append(('Righe fattura', row_dict))
row_dict = {}
# se è un valore vuol dire che è un valore singolo
elif not isinstance(value, dict) and value:
print("VALORE NORMALE")
Fattura.append((fieldname, value))
# se è un valore ma non contiene dati aggiungiamo comunque il campo vuoto per non perdere la formattazione delle colonne nel file in uscita
elif not isinstance(value, dict) and not value:
Fattura.append((fieldname, ''))
# Fine lettura campi fattura
# A questo punto in Fattura[] abbiamo la lista di tutti i campi che ci interessano, dove ogni valore di 'Righe Fattura' conterrà
# il dictionary con i campi della riga.
# Volendo possiamo accodare a un'altra lista che conterrà tutte le fatture in formato lista.
DatiFatture.append(Fattura)
print('Dati fatture')
print('------------')
print(DatiFatture)
OUTPUT SPIEGATO:
Prima fattura
[
[('ProgressivoInvio', '00002'), ('CodiceDestinatario', 'XXXXXX'), ('Denominazione', 'Roberto Zanardo'), ('Indirizzo', 'Via dei Tigli,23'), ('CondizioniPagamento', 'TP02'),
Questa è una tuple che contiene come primo dato il nome del campo(Riga fattura) e come secondo dato il dictionary con tutte le chiavi/valori della riga.
('Riga fattura', {'NumeroLinea': '1', 'Descrizione': 'CONSULENZA/SVILUPPO SOFTWARE ODOO', 'Quantita': '1.00', 'PrezzoUnitario': '1600.00', 'PrezzoTotale': '1600.00', 'AliquotaIVA': '1.00', 'Natura': 'N2'}), ('Riga fattura', {'NumeroLinea': '2', 'Descrizione': 'cassa previdenziale 4', 'Quantita': '1.00', 'PrezzoUnitario': '64.00', 'PrezzoTotale': '64.00', 'AliquotaIVA': '2.00', 'Natura': 'N2'})
]
Fine prima fattura
,
Seconda fattura
[
('ProgressivoInvio', '00002'), ('CodiceDestinatario', 'SUXXXN'), ('Denominazione', 'Roberto Zanardo'), ('Indirizzo', 'Via Alpi 34'), ('CondizioniPagamento', 'TP02'),
Questa è la tuple della prima riga che contiene come primo dato il nome del campo(Riga fattura) e come secondo dato il dictionary con tutte le chiavi/valori della riga.
('Riga fattura', {'NumeroLinea': '1', 'Descrizione': 'ORE CONSULENZA E SVILUPPO SOFTWARE', 'Quantita': '1.00', 'PrezzoUnitario': '1200.00', 'PrezzoTotale': '1200.00', 'AliquotaIVA': '0.00', 'Natura': 'N2'}),
Questa è la tuple della prima seconda che contiene come primo dato il nome del campo(Riga fattura) e come secondo dato il dictionary con tutte le chiavi/valori della riga.
('Riga fattura', {'NumeroLinea': '2', 'Descrizione': 'Spese', 'Quantita': '1.00', 'PrezzoUnitario': '48.00', 'PrezzoTotale': '48.00', 'AliquotaIVA': '0.00', 'Natura': 'N2'})],
]
Fine seconda fattura
Da questo punto sarà quindi necessario rileggere la struttura creata per disporla nel file di output come preferiamo.
-

Consulenza Giornata Odoo (Offerta valida solo per acquisto via Web)
€490.00 Aggiungi al carrello -

Consulenza Oraria Odoo (Offerta valida solo per acquisto via Web)
€99.00 Aggiungi al carrello -

FExplore FREE per Windows – Visualizza dati Fatture elettroniche con demo esportazione Excel
€0.00 Aggiungi al carrello -
In offerta!

FExplore per Windows – Esporta XML Fatture elettroniche in CSV per Excel
Il prezzo originale era: €69.00.€49.00Il prezzo attuale è: €49.00. Aggiungi al carrello
1 commento su “Leggere dettaglio linee da fatture elettroniche con xmltodict”