File di testo, cerco consiglio su metodo migliore per trasformarlo in ...

lunedì 27 aprile 2009 - 18.37

plaguebreath Profilo | Junior Member

Ho un file di testo privo di separazioni con , o punteggiature varie. E' però nella sua struttura regolare e si presenta come segue:

QQQWWWW________I00000DDMMYYHHmm

i Q rappresentano un codice identificativo
i W rappresentano un codice identificativo di un articolo
_ sono spazi
I rappresenta un valore che può essere 1 o 0 ingresso e uscita articolo
0 sono zeri ovviamente
DD è il valore per il giorno
MM è il mese
YY anno
HH ora
mm sono i minuti

La mia idea era quella (scusatemi ma sono alle prime armi) di leggermi il file di testo convertendolo in una string() e splittandolo per fine riga, a questo punto mi estrapolo con substring i valori che mi interessano in pseudo campi database, avendo però cura di compattare i campi relativi alla data e all'ora in un unico campo datetime.
A questo punto scrivo i valori in un file XML, e poi lo importo in un dataset (anche per poterlo visualizzare in un datagrid perchè devo tenere traccia per un giorno entrate e uscite di un certo articolo in maniera visuale) è la procedura corretta a grandi linee ?
Grazie a tutti per i suggerimenti

R3GM4ST3R Profilo | Junior Member

Ciao "Respiro di peste" (bel nick!)
Si le idee ci sono, consigli :
cmq leggi il file riga per riga fino a EOF e per ogni riga usi substring per prendere la parte della riga letta, mettendo il risultato in variabili, per quanto riguarda il dataset, ti conviene crearlo a mano, senza passare dall'XML

Una possibile soluzione è questa :

Private Sub ExecuteDecoding()
'//Creo il dataset
Dim o_DS As New DataSet()
'//Creo la datatable
Dim o_DT As New DataTable("LISTA")
'//Aggiungo le colonne che servono al datatable per poterci inserire i dati
o_DT.Columns.Add(New DataColumn("COLONNA1"))
o_DT.Columns.Add(New DataColumn("COLONNA2"))
o_DT.Columns.Add(New DataColumn("COLONNA3"))
'//Con questa funzione aggiungi le righe al datatable (chiama la funzione sotto, che dovrà contenere poi tutte le tue substring
o_DT.Rows.Add(DecodeStringData("RIGA LETTA DAL FILE"))
'//Aggiungi la datatable al dataset, dopodichè avendo il dataset, puoi visualizzarlo con le datagrid, salvarlo in XML etc etc
o_DS.Tables.Add(o_DT)
End Sub

Private Function DecodeStringData(ByVal s_strFileRow As String) As String()
Dim s_strValues(2) As String
Try
s_strValues(0) = "Valore1"
s_strValues(1) = "Valore2"
s_strValues(2) = "Valore3"
Catch ex As Exception
s_strValues = Nothing
End Try
Return s_strValues
End Function

Ciao!


Tutti sanno che una cosa è impossibile da realizzare, finché arriva uno sprovveduto che non lo sa e la inventa. (Albert Einstein)

plaguebreath Profilo | Junior Member

Mhhh ho capito quello che dici tu però può succedere che a cause di aggiunte tardive mi si aggiunga una riga con data 01/04/09 anche se l'ultima riga inserita è quella di oggi 27/04/2009 in quel caso come faccio a inserire la riga (magari un'ingresso e poi una uscita merce) nella posizione giusta ?
(spero di essermi spiegato perchè il tutto è un po' arzigogolato e forse la soluzione XML è una complicazione agiguntiva, ma avevo pensato di ordinare tutti i record per data/ora in modo da avere per lo meno una sequenza rintracciabile di ingressi/uscite (ho il problema che potrebbe succedere una errata registrazione di un articolo che magari risulta uscito due volte senza un ingresso in mezzo, in quel caso dovrei saltare una colonna ma come risolvere ?) Grazie
Io pensavo di organizzare il dataset così:
cod1 codart i/u data1 i/u data2 i/u data3 i/u data4 i/u data5 i/u data6

forse mi sto complicando la vita ....

R3GM4ST3R Profilo | Junior Member

Ti rimando ad un link che ho scritto tempo fa...
http://www.dotnethell.it/forum/messages.aspx?ThreadID=29868
tratta di un file in csv, ma è + o meno uguale, al posto della split, usi la substring() e li metti in una collection di oggetti (in sostanza una tua riga è un oggetto della collection)
Se però mi dici che i dati nel file possono essere mescolati, il modo più veloce che mi viene in mente è di usare il database. (altrimenti dovresti ordinarti la collection)
Crei il tuo bel database access, penso basti quello, con una bella tabellina con all'interno i tuoi dati, una volta letti dal file ed inseriti nel database, fai una

>SELECT * FROM NOMETABELLA ORDER BY DATA ASC

E sei a posto!

Tutti sanno che una cosa è impossibile da realizzare, finché arriva uno sprovveduto che non lo sa e la inventa. (Albert Einstein)

plaguebreath Profilo | Junior Member

Ovviamente xml lo volevo usare al posto di un database access perchè importandomi i dati in un dataset poi potrei filtrarlo come se fosse un database e potrei gestirmelo con query e altro (ad esempio per vedere quanto tempo totale mi è rimasto fermo in magazzino interno l'articolo X) in questo caso la colonna 1 dovrebbe avere per forza in i/u il valore 0 per segnalare l'ingresso, e la colonna 2 dovrebbe avere un 1 come uscita e quindi mi ricavo il tempo-differenza tra col2-col1 e così via, ma come gestire il caso di errata lettura di ingresso uscita ? Spero di non fare casino, grazie per gli aiuti comunque sei molto gentile :)

R3GM4ST3R Profilo | Junior Member

beh prima di tutto, puoi usare sicuramente tipi più complessi, tipo puoi raggruppare giorno mese anno ora e minuti e castarli a data, e successivamente inserirli nel database in un campo unico di tipo datetime, così avresti solamente una cosa tipo :

QQQ = ID_riga
WWWW = ID_Articolo
________
I = Flag IN o OUT (se 0 o 1)
00000 = ???
DD/MM/YY/HH:mm:00 = DataOra

Una cosa così...

Tutti sanno che una cosa è impossibile da realizzare, finché arriva uno sprovveduto che non lo sa e la inventa. (Albert Einstein)

plaguebreath Profilo | Junior Member

Si lo avevo scritto sopra che non avrei tenuto separati i campi giorno mese anno ora minuti ma li avrei messi in un datetime, però ho ancora dubbi sulla fattibilità della cosa :( Speriamo che la notte porti consiglio anche se non ci spero molto, sono nella tipica situazione da buco nero :(

R3GM4ST3R Profilo | Junior Member

Sinceramente non la vedo una cosa devastantemente difficile...E' fattibile come cosa!
Tutti i controlli li fai dopo una volta che i dati sono salvati all'interno del database, così fai query dirette in modo rapido!
(una domanda ma quel file che devi leggere, lo scrive un'altra applicazione??)


Tutti sanno che una cosa è impossibile da realizzare, finché arriva uno sprovveduto che non lo sa e la inventa. (Albert Einstein)

plaguebreath Profilo | Junior Member

Purtroppo si è un lettore automatico di barcode a nastro che crea righe sequenzialmente anche se qualche volta si inceppa, cose fatte un po' artigianalmente. Ho fatto alla fine come consigliavi tu passando per database access, ho costruito una tabella composta dalle colonne:
idart, idartpro, in_out, dataora scorporando il tutto dal file di testo e togliendo i caratteri indesiderati. Ora ho il mio bel risultato in access però a questo punto volevo prendere quella tabella e travasare le varie righe in un altra tabella formata come segue:

idart, idartpro, dataora1, dataora2,dataora3, dataora4,dataora5,dataora6,dataora7,dataora8

nelle colonne dataora1,3,5,7 ci devono andare li ingressi (che possono essere meno di 4 ma almeno 1)
nelle colonne dataora2,4,6,8 ci devono andare le uscite (che possono essere anche meno di 4 ma almeno 1)

Solo che qui usando un un datareader utilizzando oledb mi sono un po' impappinato, hai qualche suggerimento ? Grazie

R3GM4ST3R Profilo | Junior Member

Dimmi pure in cosa ti sei impappinato, non ci sono problemi!

Se posso ti aiuto volentieri!


Tutti sanno che una cosa è impossibile da realizzare, finché arriva uno sprovveduto che non lo sa e la inventa. (Albert Einstein)

plaguebreath Profilo | Junior Member

mettiamo che ho delle righe fatte cosi nel database che voglio leggere

idart, idartpro, inout(0 = in 1 = out), dataora
001 0009 0 27/04/09 09:09 articolo è entrato
001 0009 1 27/04/09 09:30 articolo è uscito
001 0009 0 27/04/09 11:01 articolo entrato ancora
001 0009 1 27/04/09 11:15 articolo uscito
001 0009 1 27/04/09 11:17 articolo caricato erroneamente come uscito ancora
001 0010 1 27/04/09 08:09 articolo caricato come uscente ma non caricato prima come entrante

Ho riassunto le possibili casistiche, come vedi il mio risultato finale dovrebbe essere questo riportato in database e poi visualizzato tramite datagridview

idart dataora1 dataora2 dataora3 dataora4 dataora5 dataora6 dataora7 dataora8 (a fianco volevo visualizzare un altra colonna
0010009 27/04/09 09:09 27/04/09 09:30 27/04/09 11:01 27/04/09 11:15 nothing 27/04/09 11:17 nothing nothing che riporti (dataora2-dataora1)+(dataora4-dataora3)
0010010 nothing 27/04/09 08:09 nothing nothing nothing nothing nothing nothing + (dataora6-dataora5) + ( dataora8-dataora7))

avevo pensato di creare un array datetime() = {nothing, nothing, nothing,nothing,nothing,nothing,nothing,nothing}
ciclare tutte le righe ottenute dal datareader e qui mi impallo perchè non riesco a creare un meccaniscmo che mi rilevi in che colonna (indice) mettere i dati con data consecutiva. So che è una cavolata ma ho il tipico blocco del programmatore :( Magari dopo una notte di sonno ci arrivo ma un aiutino sarebbe comunque gradito :)
Il risultato nel secondo database poi lo bindo a un dataset e lo visualizzo tramitte un datagrid con filtro per data x.

R3GM4ST3R Profilo | Junior Member

Alura, vediamo un po'...
Come prima cosa ti consiglio di aggiungere una colonna di tipo "Contatore" come chiave primaria univoca, in modo da identificare, già nel DB ogni singolo record della tabella.
Seguendo il tuo esempio, il risultato è simile a questo (il primo campo, chiamalo ID, che è incrementale ed univoco, così da query puoi recuperare la singola riga se lo desideri)

1 001 0009 0 27/04/09 09:09 articolo è entrato
2 001 0009 1 27/04/09 09:30 articolo è uscito
3 001 0009 0 27/04/09 11:01 articolo entrato ancora
4 001 0009 1 27/04/09 11:15 articolo uscito
5 001 0009 1 27/04/09 11:17 articolo caricato erroneamente come uscito ancora
6 001 0010 1 27/04/09 08:09 articolo caricato come uscente ma non caricato prima come entrante

Una volta fatta questa operazione, hai tutte le informazioni che ti servono, e creare una tabella "ordinata" non ha senso, poichè puoi farlo direttamente tramite select.
Facendo una cosa tipo
>select * from tabella order by data ASC group by idart, idartpro
così facendo, selezioni tutti i campi dalla tabella ordinando i dati per il campo data in modo crescente, raggruppandoli infine per idart e poi per idartpro, una volta fatto ciò, mentre scorri il datareader, recor per record e fai tutti i tuoi controlli sulle date di ingresso/uscita, in modo da capire se un record è un errore (uscita quando l'aticolo è già uscito) oppure (uscita quando un articolo è uscito senza prima entrare)

Partendo dal presupposto che il sistema non è anticausale, ossia non può uscire un articolo che non è prima entrato...(correggimi se sbaglio)

Praticamente vorresti visualizzare nella datagrid, un riassuntivo orario della giornata della merce che è entrata ed uscita con evidenziata la relativa ora di Ingresso/uscita...tutto corretto???


Tutti sanno che una cosa è impossibile da realizzare, finché arriva uno sprovveduto che non lo sa e la inventa. (Albert Einstein)

plaguebreath Profilo | Junior Member

Allora ho evitato il campo incrementale perchè comunque non mi interessa recuperare valori tramite ID, poi per la query la select la ho usata appunto per creare il datareader quindi per popolarlo e ho fatto esattamente come hai detto tu tranne il fatto che non ho usato group by (erroneamente) ma l'order by
Il sistema non è anticasuale in quanto come ti ho detto ci possono essere questi errori, del tipo non mi scatta la passata dell'articolo in ingresso ma mi scatta l'uscita, questo è un campanello d'allarme per me che vorrei rappresentare in modo visuale all'utente ovviamente che si stancherebbe a passarsi un file con 5980 record :)
Il mio problema è appunto tradurre il tutto nella maniera più semplice possibile da essere visualizzata in un datagridview con il riassunto orario e filtrata per data singola quindi per giorno.
(vedo che da ieri comunque ho fatto passi avanti :) )

Piccolo aggiornamento del giorno 30/04/09
Dopo lungo faticare sono riuscito a costruire l'altra tabella completandola con una colonna calcolata dinamicamente che mi deve fare la somma tra (dataorauscita1-dataoraingresso1)+(dataorauscita2-dataoraingresso2) + ( dataorauscita3-dataoraingresso3)+( dataorauscita4-dataoraingresso4)
Il tutto funziona alla grande solo che a questo vorrei introdurre una sofisticazione, mi spiego:
poniamo il seguente caso 04:45 ingresso1 07:55 uscita1 11:05 ingresso2 15:36 uscita2
in questo caso vorrei che l'ora del datetime ingresso1 visto che ha passato i 30 minuti mi venga aumentata di un ora e tolti i minuti diventando le ore 5.00
mentre per l'uscita1 visto che è 7:55 la vorrei portare alla mezza ora precedente quindi alle 7.30
poi l'ingresso alle 11.05 mi rimane nella tolleranza e lo lascio così (o lo porto alle 11 è indifferente) mentre l'uscita la porto alle 15.30 così la somma mi cambia e mi rimane confinata come precisione alle mezze ore (che basta e avanza)
Sono però bloccato nella trasformazione della formula sopra riportata modificata con questa logica:
supponendo che dataingresso1 sia un datetime, io ne voglio solo la parte oraria e uso il .timeofday a questo punto per aggiungere minuti uso addminutes e per sottrarne uso un numero negativo, lo steso per le ore, ma sembra non funzionare, c'p qualche metodo più semplice forse ?
Grazie
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5