Inherits DataGridView non funziona

sabato 07 marzo 2009 - 09.53

ans66 Profilo | Junior Member

Sto tentando di creare una classe che acquisisce dati da un file excel e li inserisce in un datagridview. Non riesco a far comparire il Datagridview e sto tentando di capire cosa sbaglio. Segue codice: (codice modificato)


Public Class CaricaFileExcelSuDatagrid
Inherits DataGridView
Friend WithEvents OpenFileDialog As System.Windows.Forms.OpenFileDialog
Friend WithEvents ProgressBar As System.Windows.Forms.ProgressBar
Private MioDataGridview As Windows.Forms.DataGridView

Private Sub InitializeComponent()
Me.OpenFileDialog = New System.Windows.Forms.OpenFileDialog
Me.ProgressBar = New System.Windows.Forms.ProgressBar
CType(Me, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'OpenFileDialog
'
Me.OpenFileDialog.FileName = "OpenFileDialog"
'
'ProgressBar
'
Me.ProgressBar.Location = New System.Drawing.Point(0, 0)
Me.ProgressBar.Name = "ProgressBar"
Me.ProgressBar.Size = New System.Drawing.Size(100, 23)
Me.ProgressBar.TabIndex = 0
CType(Me, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)

End Sub

Public Function ApriFileDaCl() As ArrayList
Dim cF As DialogResult
Dim myStream As IO.Stream = Nothing
Dim ArrayDirecotry As New ArrayList
OpenFileDialog = New OpenFileDialog

With OpenFileDialog
.InitialDirectory = Microsoft.VisualBasic.FileIO.SpecialDirectories.MyDocuments

.Filter = "excel (*.xls)|*.xls|excel 2007 (*.xlsx)|*.xlsx|All files (*.*)|*.*"
.FilterIndex = 3
.RestoreDirectory = True
.FileName = vbNullString

cF = .ShowDialog

If cF = Windows.Forms.DialogResult.OK Then

Try
myStream = OpenFileDialog.OpenFile()
If (myStream IsNot Nothing) Then



Dim fl As String, est As String, i As Integer, dr As String, dove As Integer


Static dove2 As Integer = 0

dove = InStr(OpenFileDialog.FileName, ".")
est = Mid(OpenFileDialog.FileName, dove + 1) 'estensione

For i = Len(OpenFileDialog.FileName) To 1 Step -1
dr = Mid(OpenFileDialog.FileName, i, 1)
If dr = "\" Then
dove2 = i
Exit For
End If

Next
dr = Mid(OpenFileDialog.FileName, 1, dove2 - 1) ' directory
fl = Mid(OpenFileDialog.FileName, dove2 + 1) ' file


If LCase(est) = "xlsx" Then
ArrayDirecotry.Add(OpenFileDialog.FileName)
ArrayDirecotry.Add(dr)
ArrayDirecotry.Add(fl)

Return ArrayDirecotry

ElseIf LCase(est) = "xls" Then
'Return OpenFileDialog.FileName & Space(2) & dr & Space(2) & fl
ArrayDirecotry.Add(OpenFileDialog.FileName)
ArrayDirecotry.Add(dr)
ArrayDirecotry.Add(fl)

Return ArrayDirecotry

Else
MessageBox.Show(est)
MessageBox.Show("File errato! Scegliere solo file excel!", "Errore", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return Nothing
End If


End If
Catch Ex As Exception
MessageBox.Show("Non riesco a leggere il file. Errore: " & Err.Description)
Return Nothing

Finally
' Check this again, since we need to make sure we didn't throw an exception on open.
If (myStream IsNot Nothing) Then
myStream.Close()

End If

End Try
ElseIf cF = Windows.Forms.DialogResult.Cancel Then
MessageBox.Show("Non hai caricato il file!", "Non hai caricato il file", MessageBoxButtons.OK, MessageBoxIcon.Warning)
End If
End With
Return Nothing
End Function

Public Function Car_Exc(ByVal drFl As ArrayList, ByVal NomeColonne As ArrayList, ByVal _
TipoColonne As ArrayList, ByVal FoglioNumero As Integer) As DataGridView



Dim xls As New Microsoft.Office.Interop.Excel.Application
Dim xlSheet As New Microsoft.Office.Interop.Excel.Worksheet
Dim sheetName As String
Dim NonVaBene As Boolean
Dim nr As Integer = 0
Dim Dt As New DataTable("DataTableExcel")
Dim ds As New DataSet

Do
For i As Integer = 0 To NomeColonne.Count - 1

If i <> nr Then
Dim Rit As Integer = String.Compare(NomeColonne(nr), NomeColonne(i))
If Rit = 0 Then NonVaBene = True
End If

Next
nr += 1
If nr = NomeColonne.Count - 1 Then Exit Do
Loop

If NonVaBene = True Then
MessageBox.Show("Attenzione due numeri colonne sono uguali!!!! Uscita forzata!", _
"Errore!", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return Nothing
Exit Function
End If

xls.Workbooks.Open(drFl(0))
xlSheet = xls.Worksheets.Item(FoglioNumero)
sheetName = xlSheet.Name
xls.Visible = True
xls.WindowState = Microsoft.Office.Interop.Excel.XlWindowState.xlMaximized

Dim NrColonne As New ArrayList
NrColonne = mesg(NomeColonne)

'---------------- L'utente può definire l'ultima riga se vuole ------------------
Dim Lastrow As Integer

Dim Ultrg As String = InputBox("Ultima Riga del foglio excel che viene utilizzata?", "Ultima Riga? Puoi anche non inserire nulla!")
If IsNumeric(Ultrg) = True AndAlso Ultrg <> 0 Then
Lastrow = Ultrg
Else
Lastrow = xlSheet.UsedRange.Rows.Count
End If

xls.WindowState = Microsoft.Office.Interop.Excel.XlWindowState.xlMinimized

For i As Integer = 0 To NomeColonne.Count - 1
Dt.Columns.Add(NomeColonne(i), System.Type.GetType(TipoColonne(i)))
Next

For rw = 0 To Lastrow
Dt.Rows.Add(Dt.NewRow)
Next


For rw As Integer = 1 To Lastrow
' prima riga

For cl As Integer = 0 To NrColonne.Count - 1
If Len(xlSheet.Cells(rw, NrColonne(cl)).Value()) = 0 Then
Else
Select Case TipoColonne(cl) ' = stringa nessun problema
Case Is = "System.String"
Dt.Rows(rw).Item(cl) = xlSheet.Cells(rw, NrColonne(cl)).Value()
Case Is = "System.Decimal"
' = decimal verifico se numerico
' o se puo` essere converito con
' daValuta_aNumero
If Not IsNumeric(xlSheet.Cells(rw, NrColonne(cl)).Value()) Then
Dim rit As String = daValuta_aNumero(xlSheet.Cells(rw, _
NrColonne(cl)).Value().ToString)
If Not IsNumeric(rit) Then
Dt.Rows(rw).Item(cl) = 0
Else
Dt.Rows(rw).Item(cl) = xlSheet.Cells(rw, NrColonne(cl)). _
Value()
End If

End If
Case Is = "System.DateTime" ' = Data

If Not IsDate(xlSheet.Cells(rw, NrColonne(cl)).Value()) Then
Else
Dt.Rows(rw).Item(cl) = xlSheet.Cells(rw, NrColonne(cl)). _
Value()
End If

End Select




End If

Next
Next

MioDataGridview = New System.Windows.Forms.DataGridView

MioDataGridview.DataSource = Dt
MioDataGridview.DataMember = "DataTableExcel"

MioDataGridview.Width = 700
MioDataGridview.Height = 370

'Dg.Show()
MioDataGridview.Show()

'Return Dt
xls.DisplayAlerts = False
xls.Workbooks.Close()
xlSheet = Nothing
xls.Quit()
xls = Nothing

Return MioDataGridview

End Function

Public Function daValuta_aNumero(ByVal daform As String) As String
Dim stringa As String, i As Integer, StrFormattata As String = vbNullString

For i = 1 To Len(daform)
stringa = Mid(daform, i, 1)
If stringa = "€" Or stringa = "$" Or stringa = Space(1) Or stringa = "." Then
ElseIf stringa = "," Then
stringa = "."
StrFormattata += stringa
Else
StrFormattata += stringa
End If
Next

Return StrFormattata
End Function

Private Function mesg(ByVal inp As ArrayList) As ArrayList

Dim QualeCol As String
Dim DaRitornare As New ArrayList

Try

For i As Integer = 0 To inp.Count - 1

Do
QualeCol = InputBox("La colonna " & inp(i) & " è la " & _
Chr(13) & Chr(10) & _
Chr(13) & Chr(10) & _
"colonna con la lettera " & _
Chr(13) & Chr(10) & _
"Es: A o B ecc." & _
Chr(13) & Chr(10) & _
Chr(13) & Chr(10) & _
"Apri finestra file Excel sotto iconizzata!!!", "Guarda bene prima di scegliere")

QualeCol = QualeCol.ToUpper

Select Case QualeCol.ToUpper
Case Is = "A"
DaRitornare.Add(1)
Exit Do
Case Is = "B"
DaRitornare.Add(2)
Exit Do
Case Is = "C"
DaRitornare.Add(3)
Exit Do
Case Is = "D"
DaRitornare.Add(4)
Exit Do
Case Is = "E"
DaRitornare.Add(5)
Exit Do
Case Is = "F"
DaRitornare.Add(6)
Exit Do
Case Is = "G"
DaRitornare.Add(7)
Exit Do
Case Is = "H"
DaRitornare.Add(8)
Exit Do
Case Is = "I"
DaRitornare.Add(9)
Exit Do
Case Is = "J"
DaRitornare.Add(10)
Exit Do

Case Else
MessageBox.Show("Inserire una lettera da [A] alla lettera [J]!!!", "Lettera sbagliata", MessageBoxButtons.OK, MessageBoxIcon.Stop)
End Select
Loop

Next

Return DaRitornare

Catch ex As Exception
Return Nothing
End Try


End Function
End Class



Public Class ProvaCaricaExcel

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim prova As New CaricaFileExcelSuDatagrid
Dim dt As New DataTable
Dim NomeColonne As New ArrayList
NomeColonne.Add("
Codice
")
NomeColonne.Add(" [DESCRIZIONE] ")
NomeColonne.Add(" [PREZZO in € ] ")
NomeColonne.Add(" [QTA'] ")

Dim TipoColonne As New ArrayList
TipoColonne.Add("System.String")
TipoColonne.Add("System.String")
TipoColonne.Add("System.Decimal")
TipoColonne.Add("System.Int32")

Dim ApriFile As New CaricaFileExcelSuDatagrid
Dim DaDir As New ArrayList
DaDir = ApriFile.ApriFileDaCl()

dt = prova.Car_Exc(DaDir, NomeColonne, TipoColonne, 1)

'For i As Integer = 0 To dt.Columns.Count - 1
'MessageBox.Show(dt.Rows(0).Item(i))
'Next

End Sub
End Class

Jeremy Profilo | Guru

Ciao Antonio.
Non è molto chiaro quello che vuoi fare ... ma partiamo subito da una cosa.

>Inherits DataGridView
Se erediti un DataGridView in una tua classe, che senso ha questa riga?????:
>Friend WithEvents DataGridView As System.Windows.Forms.DataGridView
te lo dico io .... NESSUNO .... a meno che tu non voglia visualizzare un datagridview all'interno di un datagridview.

Facci sapere....
Ciao

ans66 Profilo | Junior Member

quello che vorrei ottenere un datagrid che si apre a pieno schermo al quale collego un datatable che ho popolato con dei dati derivanti da un excel. Ho certamente esagerato: non voglio certo un datagridview in un datagridview ma cio` dipende dal fatto che non riesco a visualizzare il datagridview e percio` stavo tentando ogni strada. Aiutami a capire perche` non visualizzo il Datatgridview...grazie

Jeremy Profilo | Guru

Ma il 'tuo DataGridView personalizzato' come lo aggiungi al Form???...A DesignTime???.....o RunTime????
Cosa intendi per .....Non riesco a visualizzare il DataGridView?????
Ti riferisci al popolamento del DataGridView o proprio alla visualizzazione????
E' una cosa che riesci a risolvere con un Me.Visible=True scritto all'interno della tua classe???

Facci sapere....
Ciao

ans66 Profilo | Junior Member

Jeremi, il problema e` che non so come aggiungere il DataGridview al Form. Non riesco proprio a vedere il DataGridview. In merito al popolamento del DataGridview dovrebbe andare anche se non posso saperlo con esattezza visto che non vedo il DataGridview. Non ho risolto con Me.Visible=True.

Jeremy Profilo | Guru

Ciao Antonio.
Quando crei una classe che eredita un controllo (in questo caso DataGridView), implicitamente stai creando un controllo personalizzato, il quale, dovresti trovare disponibile nella casella degli strumenti di VisualStudio sotto la scheda che di solito prende il nome del progetto.
Quindi, devi semplicemente, selezionarlo e trascinarlo sul Form.
In alternativa, puoi crearlo ed inserirlo a runtime, come un qualsiasi altro oggetto del .NET Framework, ma, essendo un controllo, devi ricordarti di aggiungerlo alla collection Controls del Form.
Quindi, poniamo il caso tu voglia crearlo a runtime, devi scrivere le seguenti righe di codice:

Private sub Form_Load() handles Me.Load dim miodatagridview as new CaricaFileExcelSuDatagrid me.controls.add(miodatagridview) miodatagridview.visible=true <-------------Questa riga non dovrebbe essere comunque necessaria. End Sub

Facci sapere....
Ciao

ans66 Profilo | Junior Member

Ciao Jeremi, grazie tante per la tua spiegazione..per me e` un campo del tutto inesplorato. Importando il Datagrid "personalizzato" ho capito che tutta l'elaborazione per il popolamento del Datatable era andata perduta. Ho capito quindi che e` meglio trattare a parte il popolamento del DataTable e restituire con la funzione il DataTable riportato. Rimane pero` il dilemma di come visualizzare correttamente un controllo personalizzato. Questo esempio dovrebbe essere esemplificativo: volgio creare un GroupBox che con il suo testo indica la situazione attuale di popolamento del DataTable (Numero Record:...), un ProgressBar all'interno del GroupBox che indica visualmente la situazione di caricamento. Nel codice che segue ho notato due cose che non vanno:

- il ProgressBar dhe dovrebbe essere contenuto nel GroupBox "personalizzato" non si vede una volta importato nel Form chiamante
- se la funzione ritorna il testo "Nr. record.." devo bloccare tutto con un Messagebox.show per vedere GroupBox.Text cambiare e non basta System.Threading.Thread.Sleep(1000).

Spero di essere stato chiaro.

Di seguito ti scrivo il codice.....davvero complicato creare un oggetto personalizzato ! Dove posso trovare del materiale didattico su tale argomento?

Grazie

Option Strict On
Public Class CaricaExcelSuDataTable
Inherits GroupBox
Friend WithEvents ProgressBar1 As System.Windows.Forms.ProgressBar
Private Gbox As System.Windows.Forms.GroupBox

Private Sub InitializeComponent()
Me.ProgressBar1 = New System.Windows.Forms.ProgressBar
Me.SuspendLayout()
'
'ProgressBar1
'
Me.ProgressBar1.Location = New System.Drawing.Point(0, 0)
Me.ProgressBar1.Name = "ProgressBar1"
Me.ProgressBar1.Size = New System.Drawing.Size(100, 23)
Me.ProgressBar1.TabIndex = 0
Me.ResumeLayout(False)

End Sub

Public Function ContaRecordDataTable(ByVal QualeRiga As Integer, ByVal UltimoRecordDt As _
Integer) As String
ProgressBar1 = New System.Windows.Forms.ProgressBar
ProgressBar1.Visible=True
Gbox = New System.Windows.Forms.GroupBox
Gbox.Text = "Record nr.:" & CType(QualeRiga + 1, String)
ProgressBar1.Minimum = 0
ProgressBar1.Maximum = UltimoRecordDt
ProgressBar1.Value = QualeRiga
System.Threading.Thread.Sleep(1000)
MessageBox.Show(CType(QualeRiga, String))
Return Gbox.Text
End Function
End Class

Jeremy Profilo | Guru

Ciao Antonio....

>Ciao Jeremi, grazie tante per la tua spiegazione..per me e` un campo del tutto inesplorato. Importando il Datagrid "personalizzato" ho capito >che tutta l'elaborazione per il popolamento del Datatable era andata perduta
hai capito male..

Rimaniamo fermi su un problema .... se continui a cambiare le carte in tavola, facciamo solo un mucchio di confusione.
Allora, fai questa piccola prova, che dovrebbe chiarirti forse un pò le idee:
- Aggiungi una classe al tuo progetto e la chiami MyDataGridView
- Eredita la classe DataGridView
Quindi:
Public Class MyDataGridView Inherits DataGridView End Class

Compila tutto e vedrai che, nella casella degli strumenti, si renderà disponibile il tuo controllo MyDataGridView per essere trascinato sul Form.
Tutto il resto lo vediamo dopo......i problemi vanno risolti uno alla volta......altrimenti facciamo solo confusione.

ans66 Profilo | Junior Member

Jeremi, fin qui ci sono: e` una prova che avevo gia' fatto. Ho provato a lanciare il MyDatagridview con Show e non presentava alcuna riga. Ho provato allora a passare con la funzione il DataTable popolato e la cosa funzionava:

dt = prova.Car_Exc(DaDir, NomeColonne, TipoColonne, 1)
Me.WindowState = FormWindowState.Maximized
Me.CaricaFileExcelSuDatagrid1.DataSource = dt
Me.CaricaFileExcelSuDatagrid1.Width = 700
Me.CaricaFileExcelSuDatagrid1.Height = 300
Me.CaricaFileExcelSuDatagrid1.Show()

quindi in questo caso il problema lo avevo risolto bypassandolo. Il problema pero` rimane come creare un controllo personalizzato?

Jeremy Profilo | Guru

Ciao Antonio.
>Il problema pero` rimane come creare un controllo personalizzato?
Lo hai appena fatto!!!
Ovviamente, la creazione di un controllo personalizzato, non si riduce solo al fatto di ereditare un'altro controllo implementando nuove funzionalità, ma è anche ovvio che trattare un argomento così complesso se non hai una base dietro, è un pò complicato.
Ti suggerisco questo tutorial suddiviso in tre parti:
http://www.visual-basic.it/articoli/acNetWinFormCustomControls1.htm
http://www.visual-basic.it/articoli/acNetWinFormCustomControls2.htm
http://www.visual-basic.it/articoli/acNetWinFormCustomControls3.htm
che, mi sembra, entri nei dettagli per la creazione di un CustomControl e tratti anche un pò di teoria che non fà sicuramente male.
L'autore lo conoscerai sicuramente, in quanto è membro di un'altra community che segui anche tu.

Facci sapere....
Ciao
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