Salve a tutti, ho un problemino riguardante importazione di dati da un foglio excel ad un database access. Vado subito al punto e vi spiego i miei parametri di programmazione.
I passi che esegue il mio software sono i seguenti:
1) Tramite un form prelevo il file excel in cui sono inseriti i dati da importare, analizzo il file e mi porto sul primo foglio del file per esaminare la tabella.
2) Accedo al foglio Excel tramite OleDb Connection, impostando in prima riga le intestazioni delle colonne
3) Prelevo i nomi delle colonne di Excel e le metto a confronto con le colonne del database facendo scegliere all'utente quali devono essere importate e quali campi del database devono popolare
4) Fatto ciò eseguo una SELECT ALL sul foglio excel e tramite un OleDbDataReader.Read faccio scorrere riga per riga, controllo che ci sia un duplicato nel mio database e quindi inserisco. In questa fase ho inserito un Application.DoEvents che fa in modo che mi mostri, passo per passo a video, a che punto si è arrivati, impostando anche un Threading.Thread.Sleep(1500) nella fase di inserimento.
Il problema sorge al punto 4: nella fase di prelevamento dei dati, quando vado a fare un controllo sul database e un eventuale inserimento, dopo 62 (o forse 63) iterazioni il programma si blocca con 2 messaggi di errore:
1) "Errore non specificato"
2) "Excecute Reader richiede una connessione aperta e disponibile. Lo stato della connessione è chiuso"
Ma non è possibile che sia chiuso, in quanto ad ogni controllo apro e chiudo la connessione, ad ogni aggiunta al database apro e chiudo la connessione. Di seguito vi posto il codice
Fuzione DBImport
Parametri in input:
1) Type: Stringa che stabilisce il tipo di importazione
2) Filename: Stringa che stabilisce il nome del file excel da cui importare i dati
3) Relation: Hashtab relazioni tra le colonne del db e le colonne excel
4) l : listbox dove verranno visualizzati i passi per ogni riga del foglio excel
5) lblinseriti: label num di righe excel inserite nel database
6) lblduplicati: label num di righe excel già presenti nel database (controllo su un campo indicizzato)
7) lelerrori: label d num di righe excel che non possono essere aggiunte al database.
codice:
Public Sub DBImport(ByVal type As String, ByVal filename As String, ByVal relation As Hashtable, ByRef l As ListBox, ByRef labelInseriti As Label, ByRef labelDuplicati As Label, ByRef labelErrori As Label)
Dim sheet As String
Dim log As String
Select Case type
Case "EXCEL"
sheet = ExcelSheetName(filename)
End Select
Dim cn2 As OleDbConnection
cn2 = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filename + ";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1;FirstRowHasNames=1';")
Try
cn2.Open()
Dim sql As String = "select * from [" + sheet + "]"
Dim cmd As New OleDbCommand(sql, cn2)
Dim reader2 As OleDbDataReader = cmd.ExecuteReader
Dim i = 0
Dim dup As Integer
Dim ins As Integer
Dim err As Integer
While reader2.Read
log = ""
Dim t As New Tesserato
t.CodiceFiscale = reader2(relation("CodiceFiscale")).ToString.ToUpper
t.Cognome = reader2(relation("Cognome")).ToString.ToUpper
t.Nome = reader2(relation("Nome")).ToString.ToUpper
Application.DoEvents()
If (t.CodiceFiscale.Length <> 16 Or t.Cognome.Length = 0 Or t.Nome.Length = 0) Then
err = err + 1
l.Items.Add("Errore. Dati obbligatori non corretti - " + t.CodiceFiscale + " " + t.Cognome + " " + t.Nome)
labelErrori.Text = err.ToString
Else
If CFControl(t.CodiceFiscale) = True Then
dup = dup + 1
l.Items.Add("Già esistente in database - " + t.CodiceFiscale + " " + t.Cognome + " " + t.Nome)
labelDuplicati.Text = dup.ToString
Else
Dim ok As Integer = DBadd(t)
Threading.Thread.Sleep(1500)
ins = ins + 1
l.Items.Add("Inserito in database: " + t.CodiceFiscale + " " + t.Cognome + " " + t.Nome + " - LOG:" + log) labelInseriti.Text = ins.ToString
End If
End if
End While
cn2.Close()
cn2.Dispose()
Catch ex As Exception
End Try
End Sub
codice:
Public Function ExcelSheetName(ByVal filename As String) As String Dim cn2 As OleDbConnection cn2 = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filename + ";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1;FirstRowHasNames=1';") Dim dtTables As DataTable Dim colonne As New ArrayList Dim tablename As String cn2.Open() dtTables = cn2.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing) Dim i As Integer = 0 For Each row As DataRow In dtTables.Rows If i = 0 Then tablename = row("TABLE_NAME").ToString() i = 1 End If Next cn2.Close() cn2.Dispose() Return tablename End Function Private Function NTControl(ByVal ntessera As Int64) As Boolean Dim t As New Tesserato Dim reader As OleDbDataReader = DBsearchFor("NTessera", ntessera, DbType.Int64, False) While reader.Read readerToTesser(reader, t) End While If t.CodiceFiscale.Length <> 0 Then Return True Else Return False End If End Function
codice:
Public Function CFControl(ByVal cf As String) As Boolean Dim t As New Tesserato Dim reader As OleDbDataReader = DBsearchFor("CodiceFiscale", cf, DbType.String, False) While reader.Read readerToTesser(reader, t) End While If t.CodiceFiscale.Length <> 0 Then Return True Else Return False End If End Function
codice:
Public Function DBsearchFor(ByRef criteria As String, ByRef content As Object, ByVal type As DbType, ByVal amplia As Boolean) As OleDbDataReader Connetti() Dim cmd As OleDbCommand If amplia Then cmd = New OleDbCommand("SELECT * FROM Tesseramenti WHERE " + criteria + " LIKE '%" + content + "%' ORDER BY Cognome", cn) Else cmd = New OleDbCommand("SELECT * FROM Tesseramenti WHERE " + criteria + "=? ORDER BY Cognome", cn) Dim prm As New OleDbParameter prm.DbType = type prm.Value = content cmd.Parameters.Add(prm) End If Dim reader As OleDbDataReader Try reader = cmd.ExecuteReader Catch ex As Exception MsgBox(ex.ToString) End Try Return reader Disconnetti() End Function
codice:
Public Function DBadd(ByRef t As Tesserato) As Integer Connetti() Dim cmd As New OleDbCommand("INSERT INTO Tesseramenti([CodiceFiscale],[Cognome],[Nome],[DataNascita],[LuogoNascita],[Categoria],[Azienda],[Via],[NCivico],[Cap],[Citta],[Provincia],[Telefono],[Cellulare],[Email],[NTessera],[DataTesseramento]) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", cn) Dim prm As New OleDbParameter prm.DbType = DbType.String prm.Value = t.CodiceFiscale cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.String prm.Value = t.Cognome cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.String prm.Value = t.Nome cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.Date prm.Value = t.DataNascita cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.String prm.Value = t.LuogoNascita cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.String prm.Value = t.Categoria cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.String prm.Value = t.Azienda cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.String prm.Value = t.Via cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.String prm.Value = t.NCivico cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.String prm.Value = t.Cap cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.String prm.Value = t.Citta cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.String prm.Value = t.Provincia cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.String prm.Value = t.Telefono cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.String prm.Value = t.Cellulare cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.String prm.Value = t.Email cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.Int32 prm.Value = t.NTessera cmd.Parameters.Add(prm) prm = New OleDbParameter prm.DbType = DbType.Date prm.Value = t.DataTesseramento cmd.Parameters.Add(prm) Dim result As Integer Try Connetti() result = cmd.ExecuteNonQuery Catch ex As Exception MsgBox(ex.ToString) End Try Return result Disconnetti() End Function
Grazie a tutti!