Newsgroup: it.comp.lang.visual-basic
Titolo: importazione file ascii

Ciao a tutti...
Problema:
Devo importare alcuni file ascii in un db access...la procedura dovrebbe
essere correta xchè la ho gia utilizzata in altri programmi...ora sto
cercando di importare un file di 400000 record e dopo averne importato circa
2000/3000 mi si blocca il programma...cioè dall'interfaccia nn da segni di
interruzione, ma se faccio ctrl + alt + canc mi dice che il programma è
bloccato...
Grazie
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/



 faccio ctrl + alt + canc mi dice che il programma è bloccato...
E che cosa c'entra il Visual Basic con questo problema?
giusto per essere buono:
fai quest'operazione come prima cosa appena acceso il pc, e quando ti pare
che si sia bloccato lascialo fare, potrebbe aver trovato dei problemi e sta
facendo il log degli errori. Se verso sera non risponde ancora, allora vuol
dire che hai postato sul ng sbagliato e che aiuto noi non te ne possiamo
dare.
Ciao, SK
--
La pasienzia non è mai troppo (Totò)
<><><>
Esistono 10 tipi di persone: chi conosce il binario e chi no

 che aiuto noi non te ne possiamo dare.
Purtroppo non è così "semplice". E' capitato anche a me e su ADO+SQL Server,
non ho mai provato con ADO+Access (perchè non uso tale combinazione).
Sempre riferendomi a ADO+SQL Server, quando si aggiungono "singoli records"
e questi sono molti, dopo un po' tutto si impianta, anche fino a domani
sera.
Non ricordo esattamente cosa ho fatto, ma (a memoria e oltre il SP4 di SQL
Server 7.0) credo di aver messo dei DoEvents un po' in giro per il mondo
(nel ciclo, ovviamente), aumentato i timeout (Connection e/o Command)  e,
soprattutto (soluzione da canna del gas), chiuso e riaperto il recordset di
destinazione ogni 1000 records...
Lo so, non è professionale, ma quando le cose non vanno, oltre a esporre un
messaggio che dice "Quanto sto cercando di fare, senza riuscirvi, l'ho fatto
le 2999 volte prima, identicamente. Ora, piuttosto che spararti fuori
quell'errore pari a 2^31-qualcosa e con una descrizione del piffero, chiudo
e riapro. A Bill telefoni te, vero?!" io davvero non so che fare...

 programma è bloccato...
Senza il codice esatto e parte del file da importare si può solo cercare di
indovinare.
Provo a indovinare:
il file da importare non ha gli invii a capo standard di Windows (chr(13) &
chr(10)) e tu leggi il file tramite "Line Input".
termoPilucco.

 indovinare.
ti invio il codice....
Private Sub IniziaImport_Click()
Dim Qualefile As String, recInput As String * 242
Dim Record As RecordVendite
Dim contatore As Long
Dim db As Connection
  Set db = New Connection
  db.CursorLocation = adUseClient
  db.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Conad\Conad.mdb;"
 
  Set RSVendite = New Recordset
 
 contatore = 0
 Screen.MousePointer = vbHourglass
Qualefile = Dir1.Path + "\" + FileScelto.Text
Open Qualefile For Input As #1
Do While Not EOF(1) ' Ripete fino alla fine del file.
    Line Input #1, recInput ' legge il file
    'MsgBox recInput
   Record.CodicePdv = sostApostrofo(Mid$(recInput, 1, 5))
   Record.NumTessera = sostApostrofo(Mid$(recInput, 7, 13))
   Record.DataScontrino = Mid$(recInput, 29, 2) + "-" + Mid$(recInput, 26, 2) +
"-" + Mid$(recInput, 21, 4)
   Record.OraScontrino = sostApostrofo(Mid$(recInput, 32, 8))
   Record.NumCassa = Val(sostApostrofo(Mid$(recInput, 41, 2)))
   Record.TotValScontrino = CDbl(Replace(sostApostrofo(Mid$(recInput, 43, 11)),
".", ","))
 
   'a seconda del mese dello scontrino le vendite vengono memorizzate in
tabelle diverse
   Dim mese As String
   mese = "VenditeFidelity_" & Val(Mid$(recInput, 26, 2)) & " "
 
   ' Mette i dati nelle variabili.
   RSVendite.Open "select * from " & mese & " where TesseraFidelity = '" +
Record.NumTessera + "' and DataScontrino = #" & Format(Record.DataScontrino,
"mm/dd/yyyy") & "# and OraScontrino = #" & Format(Record.OraScontrino,
"hh:mm:ss") & "# ", db, adOpenStatic, adLockOptimistic
 
  With RSVendite
      If .RecordCount = 0 Then
            .AddNew
            .Fields("CodicePdv").Value = Record.CodicePdv
            .Fields("TesseraFidelity").Value = Record.NumTessera
            .Fields("DataScontrino").Value = Record.DataScontrino
            .Fields("OraScontrino").Value = Record.OraScontrino
            .Fields("NumCassa").Value = Val(Record.NumCassa)
            .Fields("TotScontrino").Value = CDbl(Record.TotValScontrino)
 
      End If
           ' .UpdateBatch adAffectAll
  End With
     RSVendite.Close
   'contatore = contatore + 1
 
Loop
Close #1
 Screen.MousePointer = vbDefault
db.Close
MsgBox "aggiornati " + Str(contatore) + " records"
End Sub
Per il file...se nn ti è di troppo disturbo te lo dovrei inviare x mail...ma
sono ca 4 MB
....cmq 2000/3000 record li importa..
Grazie Mille
Mary


 dare.
io ci provo sul serio....ma se poi rimane bloccato... :((


 Purtroppo non č cosě "semplice"... <cut>
Quindi č ado il problema?
ma con access e dao? ho scavato un pochino il baule e ho trovato questo:
Private Sub cmdImport_Click()
Dim delimiter As String
Dim contents As String
Dim lines() As String
Dim fields() As String
Dim wks As Workspace
Dim db As Database
Dim fnum As Integer
Dim line_num As Integer
Dim field_num As Integer
Dim sql_statement As String
Dim num_records As Long
    delimiter = cboDelimiter.Text
    If delimiter = "<space>" Then delimiter = " "
    If delimiter = "<tab>" Then delimiter = vbTab
    ' Grab the file's contents.
    fnum = FreeFile
    On Error GoTo NoTextFile
    Open txtTextFile.Text For Input As fnum
    contents = Input$(LOF(fnum), #fnum)
    Close #fnum
    ' Split the contents into lines.
    lines = Split(contents, vbCrLf)
    ' Open the database.
    On Error GoTo NoDatabase
    Set wks = DBEngine.Workspaces(0)
    Set db = wks.OpenDatabase(txtDatabaseFile.Text)
    On Error GoTo 0
    ' Process the lines and create records.
    For line_num = LBound(lines) To UBound(lines)
        ' Read a text line.
        If Len(lines(line_num)) > 0 Then
            ' Build an INSERT statement.
            sql_statement = "INSERT INTO " & _
                txtTable.Text & " VALUES ("
            fields = Split(lines(line_num), delimiter)
            For field_num = LBound(fields) To UBound(fields)
                ' Add the field to the statement.
                sql_statement = sql_statement & _
                    "'" & fields(field_num) & "', "
            Next field_num
            ' Remove the last comma.
            sql_statement = Left$(sql_statement, Len(sql_statement) - 2) &
")"
            ' Insert the record.
            On Error GoTo SQLError
            db.Execute sql_statement
            On Error GoTo 0
            num_records = num_records + 1
        End If
    Next line_num
    ' Close the database.
    db.Close
    wks.Close
    MsgBox "Inserted " & Format$(num_records) & " records"
    Exit Sub
NoTextFile:
    MsgBox "Error opening text file."
    Exit Sub
NoDatabase:
    MsgBox "Error opening database."
    Close fnum
    Exit Sub
SQLError:
    MsgBox "Error executing SQL statement '" & _
        sql_statement & "'"
    Close fnum
    db.Close
    wks.Close
    Exit Sub
End Sub
Private Sub Form_Load()
    ' Enter default file and database names.
    txtTextFile.Text = App.Path & "\testdata.txt"
    txtDatabaseFile.Text = App.Path & "\testdata.mdb"
End Sub
Mi chiedo se con ADOX non sia possibile farlo. vedrň un pochino.
Ciao , SK
ps ho postato il codice solo per sveltezza, cosě si puň provarlo su file
lunghi senza doverlo riscrivere.
--
La pasienzia non č mai troppo (Totň)


 ti invio il codice....
Secondo me manca (che poi lo faccia in automatico... IMHO meglio metterlo)
un Update esplicito dopo AddNew e l'assegnazione dei campi.
Poi non ho davvero capito quel test su RecordCount = 0...
Inoltre anteporrei ADODB. a tutti gli oggetti ADO


Sia Access che SQL Server hanno una gestione delle transazioni.
Quando si và a scrivere grosse quantità di record è possibile che il 
sistema si blocchi quando vengono usati gli ADO :-( .
Soluzione 1 per entrambi:
Suddividere i record da inserire in blocchi da al max 10 MB. Alla fine 
dell'inserimento eseguire un Truk Tran.. per SQL Server e un Repear & 
Compact DB per Access.
Soluzione 2 applicabile sono in alcuni casi con SQL Server:
Fare l'inserimento con una store procedure che vada a leggersi 
direttamente in file ASCI e nel contempo per quell'evento disabilitare 
il log delle Trans... (funziona lo ho testato con un trasferimento di 
circa 1 GB) il tutto è documentato nei Books on line di SQL.
Soluzione 3 applicabile sono ad Access:
Prima d'iniziare la transazione eseguire un Repear & Compact DB e 
controllare che la memoria disponibile al sistema sia almeno il doppio 
dei dati da trasferire. Attenzione a queste problematiche :-( spesso 
Access pretende di fare *tutte* le operazioni in RAM e successivamente 
scriverle fisicamente nel DB.
ciao Max

 ho scavato un pochino il baule e ho trovato questo:
...
No, va bene, ma io usavo Addnew, assegnazione campi, Update, non cioč il
comando SQL Insert ...
Esattamente come fa il codice di MariaGrazia.

 sistema si blocchi quando vengono usati gli ADO :-( .
...
Non lo so (chiaramente nulla di personale con te che nulla c'entri, anzi, mi
pare che tu scriva questo a ragion veduta), ma dico, forte, "sono dei
matti!!!"

In news:bttrkr$babo5$
1...@ID-174464.news.uni-berlin.de
, Lupo  wrote:
Provato con 30000 record e si impalla anche dao e access, 'ndiamo bene.
mi ricordi il $uo numero di telefono? ;-)
Ciao, SK
--
La pasienzia non è mai troppo (Totò)
<><><>


 faccio ctrl + alt + canc mi dice che il programma è bloccato...
Da cosa vedi che è bloccato?
Se sta lavorando in una sub, puoi fare tutti i ctrlaltcanc che vuoi, che
finchè non ha finito non ti considera, ma è un comportamento normale.
Alberto


per favore mi spieghi la frase "con te che nulla c'entri" ?

[*only-offroad* = 
st...@only-offroad.com
 in
news:RquMb.76456$
VW.32...@news3.tin.it
] ha scritto:

Non volevo, nel modo più assoluto (e per questo ho voluto specificarlo in
modo persino ridondante) che quel "sono dei matti" potesse essere essere
frainteso come rivolto a te o anche a te. Certo, se sei di M$, specialmente
se del team ADO, allora urlo "siete dei matti!!!" ;-)

 scriverle fisicamente nel DB.
dimensioni file testo 3,78 MB
file mdb 1,43 MB
RAM 512, libera > 400
risultato: si impalla.
Access dbms mi ha importato 3.000.000 di record da un txt (mdb > 400MB)
senza problemi; dovremmo sapere lui come fà.


 destinazione ogni 1000 records...
Grazie Lupo......ora provo a seguire il tuo consiglio...
Mary



Non sono più del partito di MS, essendo una mente libera e "scammata" 
quell' *ambiente* mi è diventato molto stretto ;-)
Comunque ritornando all'argomento ribadisco che ADO a mio parere è una 
retrocessione funzionale rispetto ai DAO. Nell'ottica di voler far tutto 
  *facile* le cose in realtà sono state notevolmente incasinate.
Anche Access stesso, da surrogato di DB relazionale, è stato spesso 
portato a fare delle cose che non sono di sua competenza nativa.
Quindi ... :-( cerchiamo d'arrangiarci!
La soluzione che ho indicato è un paliativo ai problemi di caricamento 
di grosse moli di dati che in realtà sono tipici di tutti i DB anche dei 
più blasonati (Oracle, Informix ecc.) infatti non sono stati progettati 
per un uso del genere. Quindi quando si vuole usare al limite un 
prodotto gli accrocchi sono, purtroppo, pane quotidiano.
ciao Max

 bene.
'Creare un database (io l'ho fatto 97) "C:\Pippo.mdb"
'con una tabella TAB1 con i campi:
'   C1  Testo 50 crt
'   C2  Long
'   ID  Long autoincrementante
'Creare un indice ix1 con chiave primaria
'e univoca sul solo campo ID
'
'Dichiarare fra i riferimento DAO 3.6
'Creare un form con un commandbutton (Command1)
'Incollare il codice che segue.
'
'A me, anche dopo 3 giri (senza svuotare TAB1),
'non ha dato alcun problema, nè ho notato alcun rallentamento.
'Ovvio che i dati ci sono, tutti.
Dim db As DAO.Database
Dim rs As DAO.Recordset
Private Sub Command1_Click()
    Set db = OpenDatabase("C:\Pippo.mdb")
    Set rs = db.OpenRecordset("Select * from TAB1")
    For nrec = 1 To 100000
        Command1.Caption = nrec
        rs.AddNew
        rs!c1 = "Rec " & nrec
        rs!c2 = nrec
        rs.Update
    Next nrec
    rs.Close
    Set rs = Nothing
    db.Close
    Set db = Nothing
    Beep
End Sub

"Maria Grazia"  ha scritto:
[...]
Se quello che scrivono tutti gli altri è vero, dovrebbe essere sufficiente
chiudere recordset e connection ogni 1000 record inseriti (e ovviamente
riaprirli).
termoPilucco.

 limite un prodotto gli accrocchi sono, purtroppo, pane quotidiano.
Ecco, questa me la segno. Non fosse altro per poter dire che "non lo dico
solo io".
Quel che hai scritto non è consolante (perchè "mal comune maggior gaudio" è
un'altra bestialità), ma mi fa sentire meno fuori...

 Poi non ho davvero capito quel test su RecordCount = 0...
è un controllo x nn duplicare il record ne db...controlla che nn ci sia già
e poi lo inserisce
 
ciao


 sia già e poi lo inserisce
Sì, ho visto. Io testerei BOF, piuttosto che usare RecordCount, ma nel caso
specifico va bene lo stesso
Piuttosto metterei un bel On error goto pippo
Non si sa mai che si verifichi qualcosa e per settaggi precedenti non venga
rilevato e/o entri in loop.

Grazie mille a tutti....
ora mi metto al lavoro...
vi farò sapere se poi funziona...
Mary


 ...
Fatto come hai scritto tu e ho copiato 100000 record in tabella, velocemente
e senza problemi.
Così come hai scritto tu, senza INSERT e cose varie, va una meraviglia.
Ho provato anche con ado, che rimane parecchio indietro, ma và anche lui con
access. Ma ho provato solo con access.


Ho appena finito di importare i 400000 record...
FNZIONA!!!!!!
nn so davvero come ringraziarvi!!!
GRAZIE...


 lui con access. Ma ho provato solo con access.
Ecco, appunto. Quando ho dovuto fare una cosa del genere (istruzioni
praticamente identiche, che recuperavano i dati di origina da un file di
testo banalissimo e congruente, erano circa 300.000 records) verso SQL
Server (ovviamente con ADO) mi si è presentato il problema che MariaGrazia
descrive con ADO+Access.
Io non lo so se c'entra ADO e/o SQL Server, però il rughino ce l'ho.

 nn so davvero come ringraziarvi!!!
Lo so io: Ci devi dire che modifiche hai fatto, meglio se ripubblicando il
nuovo codice.

 nn so davvero come ringraziarvi!!!
Per caso hai capito alla fine quale modifica è stata determinante?
termoPilucco, solo per curiosità personale

 Io non lo so se c'entra ADO e/o SQL Server, però il rughino ce l'ho.
ADO + Access gira, lento, ma gira.
A questo punto credo che il problema sia come si utilizza ado, piuttosto che
dao, per fare l'importazione e probabilmente sql server, che non utilizzo.


 Inviato via 
http://arianna.libero.it/usenet/
Ogni 1000 record esegui un DoEvents !!!
Attenzione devi gestire i potenziali problemi del rilascio del controllo
all'SO.
Ciao a tutti in Vubisti !!!
Loris.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 nuovo codice.
eccoti accontentato!!!
Private Sub IniziaImport_Click()
On Error GoTo ImportErr
Dim Qualefile As String, recInput As String * 242
Dim Record As RecordVendite
Dim contatore As Long
Dim db As Connection
  Set db = New Connection
  db.CursorLocation = adUseClient
  db.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Conad\Conad.mdb;"
 
  Set RSVendite = New Recordset
 
 contatore = 0
 Screen.MousePointer = vbHourglass
Qualefile = Dir1.Path + "\" + FileScelto.Text
Open Qualefile For Input As #1
'passa il controllo al sistema
   DoEvents
Do While Not EOF(1) ' Ripete fino alla fine del file.
    Line Input #1, recInput ' legge il file
    'MsgBox recInput
   Record.CodicePdv = sostApostrofo(Mid$(recInput, 1, 5))
   Record.NumTessera = sostApostrofo(Mid$(recInput, 7, 13))
   Record.DataScontrino = Mid$(recInput, 29, 2) + "-" + Mid$(recInput, 26, 2) +
"-" + Mid$(recInput, 21, 4)
   Record.OraScontrino = sostApostrofo(Mid$(recInput, 32, 8))
   Record.NumCassa = Val(sostApostrofo(Mid$(recInput, 41, 2)))
   Record.TotValScontrino = CDbl(Replace(sostApostrofo(Mid$(recInput, 43, 11)),
".", ","))
 
   'passa il controllo al sistema
   DoEvents
 
   'a seconda del mese dello scontrino le vendite vengono memorizzate in
tabelle diverse
   Dim mese As String
   mese = "VenditeFidelity_" & Val(Mid$(recInput, 26, 2)) & " "
 
   ' Mette i dati nelle variabili.
   RSVendite.Open "select * from " & mese & " where TesseraFidelity = '" +
Record.NumTessera + "' and DataScontrino = #" & Format(Record.DataScontrino,
"mm/dd/yyyy") & "# and OraScontrino = #" & Format(Record.OraScontrino,
"hh:mm:ss") & "# ", db, adOpenStatic, adLockOptimistic
 
  With RSVendite
      If .RecordCount = 0 Then
            .AddNew
            .Fields("CodicePdv").Value = Record.CodicePdv
            .Fields("TesseraFidelity").Value = Record.NumTessera
            .Fields("DataScontrino").Value = Record.DataScontrino
            .Fields("OraScontrino").Value = Record.OraScontrino
            .Fields("NumCassa").Value = Val(Record.NumCassa)
            .Fields("TotScontrino").Value = CDbl(Record.TotValScontrino)
 
      End If
            .UpdateBatch adAffectAll
 
        'passa il controllo al sistema
        DoEvents
  End With
     RSVendite.Close
   contatore = contatore + 1
 
Loop
Close #1
 Screen.MousePointer = vbDefault
db.Close
MsgBox "aggiornati " + Str(contatore) + " records"
ImportErr:
    'If Err.Number = -
2147217900
 Then
    Screen.MousePointer = vbDefault
        MsgBox "Attenzione! Verificare che il file che si cerca di importare sia nel
formato richiesto!", vbExclamation
     ' txtFields(1).Text = ""
      ' txtFields(1).SetFocus
        Exit Sub
    'End If
 
  MsgBox Err.Description
 
End Sub
ciao ciao


 Per caso hai capito alla fine quale modifica è stata determinante?
SI...l'aggiunta dei DoEvents...qua e la..
ciao


 SI...l'aggiunta dei DoEvents...qua e la..
E l'Update esplicito che non è più commentato...

 E l'Update esplicito che non è più commentato...
l'avevo commentato perchè allìinzio pensavo fosse quella la causa
dell'errore...
se il dato è gia presente nel db lo modifica con nuovi dati...nn mi dovrebbe
servire xchè i dati importati sono sempre diversi....ma x sicurezza...
