Results 1 to 8 of 8

Thread: Filling DataGrid Columns w/ Excel Data

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Sep 2011
    Location
    Seattle
    Posts
    218

    Filling DataGrid Columns w/ Excel Data

    Alright, I finally got this code to work after hours of toiling:

    vb Code:
    1. Dim path As String = OpenFileDialog1.FileName
    2.         Dim myDataset As New DataSet()
    3.         Dim strConn = New OleDbConnection("Provider=Microsoft.ACE.Oledb.12.0;Data Source=" & path & ";Extended Properties=""Excel 12.0;HDR=YES;IMEX=1""")
    4.         Dim myData As New OleDb.OleDbDataAdapter("SELECT * FROM [Sheet1$]", strConn)
    5.         myData.Fill(myDataset)
    6.         DataGridView1.DataSource = myDataset.Tables(0).DefaultView

    Now that I figured that out I was going to try and place the data in a specific location. On my application I have a datagridview set up with 4 columns. What I would like to do is put column A of the excel file under the 1st column of the datagridview and column C of the Excel File in the second column of the datagridview.

    So replace:

    vb Code:
    1. DataGridView1.DataSource = myDataset.Tables(0).DefaultView

    with:

    vb Code:
    1. DataGridView1.columns(0) = myDataset.Tables(0).columns(0)
    2.     DataGridView1.columns(1) = myDataset.Tables(0).columns(2)

    Obviously this doesnt work, and something tells me I might need a for loop to import the data, but I have never imported information from an Excel file before and to make it worse I have never worked with datagridviews before so I have no idea how to go about this.

    I would like to do something like this if I could:
    vb Code:
    1. For x = 1 To xldoc.rows.length - 1
    2.             DataGridView1.Item(0, x).Value = CType(xlDoc.Cells(0, x + 1), Excel.Range).Text
    3.         Next

    Any and all help is always appreciated.

  2. #2
    Karen Payne MVP kareninstructor's Avatar
    Join Date
    Jun 2008
    Location
    Oregon
    Posts
    6,713

    Re: Filling DataGrid Columns w/ Excel Data

    If the data returned has column header information in the first row rather than data (seeing this in your connection string HDR=YES) I would suggest adding columns for the DataGridView at design time and set the data property for each column dependent on the column names of your data returned from Excel.

    So if column C header is say LastName assign LastName to the data property for column 1 which is your second column.

    Or you can change the display index of a column as follows which is an alternative if the column headers are not always the same.
    Code:
    DataGridView1.Columns(2).DisplayIndex = 1

  3. #3

    Thread Starter
    Addicted Member
    Join Date
    Sep 2011
    Location
    Seattle
    Posts
    218

    Re: Filling DataGrid Columns w/ Excel Data

    Unfortunately the data starts on row 8, the header is on row 7, and the data could be anywhere from 2 lines to 15 lines. Would it be easier just to stop using excel and switch back to CSV's? CSV's seemed to be much less of a headache

  4. #4
    Karen Payne MVP kareninstructor's Avatar
    Join Date
    Jun 2008
    Location
    Oregon
    Posts
    6,713

    Re: Filling DataGrid Columns w/ Excel Data

    Quote Originally Posted by Zmcpherson View Post
    Unfortunately the data starts on row 8, the header is on row 7, and the data could be anywhere from 2 lines to 15 lines. Would it be easier just to stop using excel and switch back to CSV's? CSV's seemed to be much less of a headache
    You could use a named range or set the cells to work with as shown below. There are two versions of the CommandText. In short it depends on if your column names are consistant or not. Blank rows can be easily handled as shown in the code below.

    Note place the attached Excel file into your Bin\Debug folder to try this code out.
    Code:
    Public Class frmMainForm
        Private Sub MainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim dtSheet1 As New DataTable
            Dim Builder As New OleDbConnectionStringBuilder _
            With _
            { _
                .DataSource = "ksg1.xlsx", _
                .Provider = "Microsoft.ACE.Oledb.12.0" _
            }
            '
            Using cn As New System.Data.OleDb.OleDbConnection
                Builder.Add("Extended Properties", "Excel 12.0;HDR=YES;IMEX=1;")
                cn.ConnectionString = Builder.ConnectionString
    
                Using cmd As OleDbCommand = New OleDbCommand With {.Connection = cn}
                    cn.Open()
    
                    cmd.CommandText = _
                        <SQL>
                        SELECT 
                            Column1, 
                            Column2, 
                            Column3, 
                            Column4 
                        FROM [Sheet1$A7:D19]
                        WHERE 
                            Column1 IS NOT NULL AND 
                            Column2 IS NOT NULL AND 
                            Column3 IS NOT NULL AND 
                            Column4 IS NOT NULL
                        </SQL>.Value
    
                    ' Alternate is to use a named range
                    'cmd.CommandText = _
                    '    <SQL>
                    '    SELECT 
                    '        Column1, 
                    '        Column2, 
                    '        Column3, 
                    '        Column4 
                    '    FROM MyRange
                    '    WHERE 
                    '        Column1 IS NOT NULL AND 
                    '        Column2 IS NOT NULL AND 
                    '        Column3 IS NOT NULL AND 
                    '        Column4 IS NOT NULL
                    '    </SQL>.Value
    
                    dtSheet1.Load(cmd.ExecuteReader)
    
                End Using
            End Using
    
            DataGridView1.DataSource = dtSheet1
    
            DataGridView1.Columns(2).DisplayIndex = 1
        End Sub
    End Class
    Attached Files Attached Files

  5. #5

    Thread Starter
    Addicted Member
    Join Date
    Sep 2011
    Location
    Seattle
    Posts
    218

    Re: Filling DataGrid Columns w/ Excel Data

    All in all there are going to be plenty more taken then just Columns 1-4. This is just a beginning to what I am trying to accomplish, Im just trying to understand this now so I do not need to ask for help in the future.

    what about something like this:

    vb Code:
    1. oXL = New Excel.Application
    2.             oBook = oXL.Workbooks.Open(OpenFileDialog1.FileName)
    3.             oSheet = oBook.Worksheets("Sheet1")
    4.             DataGridView1.Rows.Add()
    5.             DataGridView1.Item(0, 0).value = oSheet.Cells(1, 1).value
    6.             oSheet = Nothing
    7.             oBook.Close()
    8.             oBook = Nothing
    9.             oXL.Quit()
    10.             oXL = Nothing

    granted that only copies one cell, but with a for loop it could easily do the rest. Ultimately, is there any advantage or disadvantage doing it this way?
    Last edited by Zmcpherson; Mar 26th, 2012 at 04:59 PM.

  6. #6
    Karen Payne MVP kareninstructor's Avatar
    Join Date
    Jun 2008
    Location
    Oregon
    Posts
    6,713

    Re: Filling DataGrid Columns w/ Excel Data

    Quote Originally Posted by Zmcpherson View Post
    All in all there are going to be plenty more taken then just Columns 1-4. This is just a beginning to what I am trying to accomplish, Im just trying to understand this now so I do not need to ask for help in the future.

    what about something like this:

    vb Code:
    1. oXL = New Excel.Application
    2.             oBook = oXL.Workbooks.Open(OpenFileDialog1.FileName)
    3.             oSheet = oBook.Worksheets("Sheet1")
    4.             DataGridView1.Rows.Add()
    5.             DataGridView1.Item(0, 0).value = oSheet.Cells(1, 1).value
    6.             oSheet = Nothing
    7.             oBook.Close()
    8.             oBook = Nothing
    9.             oXL.Quit()
    10.             oXL = Nothing

    granted that only copies one cell, but with a for loop it could easily do the rest. Ultimately, is there any advantage or disadvantage doing it this way?
    When using Office automation this works fine if you get everything right. To start off, keeping with your code example, if you run this code while Window Task Manager is open note that Excel is not listed under processes. Now run the code and EXCEL appears under processes and when the code stops it is still there. The Excel process will not go away until you close the app.

    If any line of code referencing Excel has more than one dot 99 percent of the time a object is not disposed of (this is known as tunneling).

    Taken from your code, I count two dots hence Excel will remain in memory until the app closes.
    Code:
    oSheet.Cells(1, 1).value
    If there is an error while running said code and the app crashed you will have to manually close Excel under Task Manager. If the user does not notice this and keeps going again and again sooner or later memory is drained from the PC.

    Any ways with that said the example below shows how to open an Excel 2007 file, search for a value, read a single cell and properly dispose of all objects used to work with Excel. See attached zip for Excel file to be placed into Bin\Debug folder.

    The code within KSG_USE section will not compile as KSG_USE is not defined. I placed this section here because this is how most developers code to force objects to dispose before the app closes, going back to tunneling.

    Hope this helps you to see what is involved going the automation route.

    Code:
    Option Strict On
    Option Infer On
    Imports Excel = Microsoft.Office.Interop.Excel
    Imports Microsoft.Office
    Imports System.Runtime.InteropServices
    Public Class Form4
        Private Sub Form4_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            SearchExcelFile(IO.Path.Combine(Application.StartupPath, "MyTest.xlsx"), "BONAP")
        End Sub
        Private Sub SearchExcelFile(ByVal FileName As String, ByVal SearchFor As String)
            Dim xlApp As Excel.Application = Nothing
            Dim xlWorkBooks As Excel.Workbooks = Nothing
            Dim xlWorkBook As Excel.Workbook = Nothing
            Dim xlWorkSheet As Excel.Worksheet = Nothing
            Dim rng As Excel.Range = Nothing
            Dim Result As Excel.Range = Nothing
    
            xlApp = New Excel.Application
            xlApp.DisplayAlerts = False
            xlWorkBooks = xlApp.Workbooks
            xlWorkBook = xlWorkBooks.Open(FileName)
    
            xlWorkSheet = CType(xlWorkBook.Sheets(1), Excel.Worksheet)
    
            rng = xlWorkSheet.Range("A1")
            Result = rng.Find(SearchFor, , _
                              Excel.XlFindLookIn.xlValues, _
                              Excel.XlLookAt.xlPart, _
                              Excel.XlSearchOrder.xlByRows, _
                              Excel.XlSearchDirection.xlNext, _
                              False)
    
            If Result IsNot Nothing Then
                Console.WriteLine("Found [{0}] on row [{1}]", SearchFor, Result.Row)
            Else
                Console.WriteLine("Did not find [{0}]", SearchFor)
            End If
    
            '
            ' READING a single cell value
            '
            Dim xlCells As Excel.Range = Nothing
            Dim testCell = xlWorkSheet.Range("A1")
            Console.WriteLine(testCell.Value)
    
            Console.WriteLine(testCell)
    
            xlWorkBook.Close()
            xlApp.UserControl = True
    
            xlApp.Quit()
    
            If Not testCell Is Nothing Then
                Marshal.FinalReleaseComObject(testCell)
                testCell = Nothing
            End If
    
            If Not Result Is Nothing Then
                Marshal.FinalReleaseComObject(Result)
                Result = Nothing
            End If
    
            If Not rng Is Nothing Then
                Marshal.FinalReleaseComObject(rng)
                rng = Nothing
            End If
    
    
            If Not xlWorkSheet Is Nothing Then
                Marshal.FinalReleaseComObject(xlWorkSheet)
                xlWorkSheet = Nothing
            End If
    
            If Not xlWorkBook Is Nothing Then
                Marshal.FinalReleaseComObject(xlWorkBook)
                xlWorkBook = Nothing
            End If
    
            If Not xlWorkBooks Is Nothing Then
                Marshal.FinalReleaseComObject(xlWorkBooks)
                xlWorkBooks = Nothing
            End If
    
            If Not xlApp Is Nothing Then
                Marshal.FinalReleaseComObject(xlApp)
                xlApp = Nothing
            End If
    
    #If KSG_USE Then
            GC.Collect()
            GC.WaitForPendingFinalizers()
            ' GC needs to be called twice in order to get the Finalizers called 
            ' - the first time in, it simply makes a list of what is to be 
            ' finalized, the second time in, it actually the finalizing. Only 
            ' then will the object do its automatic ReleaseComObject.
            GC.Collect()
            GC.WaitForPendingFinalizers()
    #End If
            MsgBox("Done")
        End Sub
    
    End Class
    Attached Files Attached Files
    Last edited by kareninstructor; Mar 26th, 2012 at 05:39 PM. Reason: Forgot to add attachement

  7. #7

    Thread Starter
    Addicted Member
    Join Date
    Sep 2011
    Location
    Seattle
    Posts
    218

    Re: Filling DataGrid Columns w/ Excel Data

    I actually know exactly what you are talking about.

    On my last application I was automatizing the exportation of information to excel files and I would close the objects using this code block:

    vb Code:
    1. Public Sub releaseObject(ByVal obj As Object)
    2.         Try
    3.             System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
    4.             obj = Nothing
    5.         Catch ex As Exception
    6.             obj = Nothing
    7.         Finally
    8.             GC.Collect()
    9.         End Try

    and then I would call them using:

    vb Code:
    1. releaseObject(xlApp)
    2.             releaseObject(xlWorkBook)
    3.             releaseObject(xlWorkSheet201)

  8. #8
    Karen Payne MVP kareninstructor's Avatar
    Join Date
    Jun 2008
    Location
    Oregon
    Posts
    6,713

    Re: Filling DataGrid Columns w/ Excel Data

    Quote Originally Posted by Zmcpherson View Post
    I actually know exactly what you are talking about.

    On my last application I was automatizing the exportation of information to excel files and I would close the objects using this code block:

    vb Code:
    1. Public Sub releaseObject(ByVal obj As Object)
    2.         Try
    3.             System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
    4.             obj = Nothing
    5.         Catch ex As Exception
    6.             obj = Nothing
    7.         Finally
    8.             GC.Collect()
    9.         End Try

    and then I would call them using:

    vb Code:
    1. releaseObject(xlApp)
    2.             releaseObject(xlWorkBook)
    3.             releaseObject(xlWorkSheet201)
    This is forcing a garbage collection as soon as the automation function is off the stack (at which point the Runtime Callable Wrapper (RCW) objects are no longer rooted) to clean up RCWs and release COM objects.

    This is why my choices for automation are a) Aspose Cells library (third party), Open XML SDK (Micorosoft for Office 2007/2010 format) and OleDb.

    Apsose Cells works on any version of Excel without the need for Excel to be available or any runtimes only the Aspose Cells library, one DLL.

    Open XML involves a good deal more work, I have a Code Bank posting on this which shows how much more code is needed over Office Automation or any other methods for that matter. But a good option if you want to work with the underlying xml structure of 2007/2010 formatted Office products such as Excel and Word.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width