简体   繁体   中英

Trouble displaying different worksheet data in datagridview on button click

I have a datagridview control on a form (Records form). On the first form (Start form) I have a button (View Records button) that when clicked includes all the code (which I will list below) to the backgroundworker (named bw) I have on the Start form. When the user clicks the 'View Records' button a progress bar appears next to the button and shows the progress of the datagridview being loaded. I am loading the datagridview via a loop that grabs all the values from an excel file. I have that working fine, but now I'm looking to be able to reload the datagridview using the same loop, but grabbing the data from a different sheet in the excel workbook when the user presses the 'Previous Year' button on the Records form. Below I've included images of the Start form and Records Form, as well as their respective code

开始表格

Imports Office = Microsoft.Office.Core
Imports Excel = Microsoft.Office.Interop.Excel

Public Class Start
Dim Records As New Records
Public excel_app As Excel.Application
Public workbook As Excel.Workbook
Public sheet_name As String
Public sheet As Excel.Worksheet

Public ColumnCount, RowCount, TotalCellCount As Long

Public yearstamp As String = _
    DateTime.Now.ToString("yyyy")

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    Setup()
    bw.RunWorkerAsync()
End Sub
Private Sub Setup()

    Dim exeDir As New IO.FileInfo(Reflection.Assembly.GetExecutingAssembly.FullName)
    Dim xlPath = IO.Path.Combine(exeDir.DirectoryName, "Records.xlsx")

    ' Get the Excel application object.
    excel_app = New Excel.Application

    ' Make Excel visible (optional).
    excel_app.Visible = False

    ' Open the workbook.
    workbook = excel_app.Workbooks.Open(xlPath)

    sheet_name = yearstamp
    Records.YearDisplay.Text = yearstamp & " Records"

    sheet = excel_app.Worksheets(sheet_name)

    ColumnCount = sheet.Range("A1").CurrentRegion.Columns.Count
    RowCount = sheet.Range("A1").CurrentRegion.Rows.Count

    Records.DataGridView1.ColumnCount = ColumnCount - 1
    Records.DataGridView1.RowCount = RowCount - 1
    Records.DataGridView1.ColumnHeadersVisible = True
    Records.DataGridView1.RowHeadersVisible = True
    TotalCellCount = Records.DataGridView1.ColumnCount * Records.DataGridView1.RowCount

    pb.Visible = True
    pb.Minimum = 0
    pb.Value = 1
    pb.Maximum = TotalCellCount

    Records.DataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing
    Records.DataGridView1.AllowUserToResizeColumns = False
    Records.DataGridView1.AllowUserToResizeRows = False
    Records.DataGridView1.ReadOnly = True


    Records.DataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells

End Sub
Private Sub bw_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork

    'Loop through each column
    Dim cIndex As Integer = 0
    Dim rIndex As Integer = 0
    While cIndex < Records.DataGridView1.ColumnCount

        'Loop through and populate each row in column
        rIndex = 0
        While rIndex < Records.DataGridView1.RowCount

            If cIndex = 0 Then
                'Set row header titles
                Records.DataGridView1.Rows.Item(rIndex).HeaderCell.Value = sheet.Range("A1").Offset(rIndex + 1, cIndex).Value()

                Records.DataGridView1.Rows(rIndex).Cells(cIndex).Value = sheet.Range("A1").Offset(rIndex + 1, cIndex + 1).Value()
            End If
            If cIndex > 0 Then
                Records.DataGridView1.Rows(rIndex).Cells(cIndex).Value = sheet.Range("A1").Offset(rIndex + 1, cIndex + 1).Value()
            End If

            'Set column header title
            Records.DataGridView1.Columns(cIndex).HeaderText = sheet.Range("A1").Offset(0, cIndex + 1).Value

            'Change last cell (Result) color Red or Green to represent positive gain or negative loss
            If rIndex = RowCount - 2 Then
                If Records.DataGridView1.Rows(rIndex).Cells(cIndex).Value < 0 Then
                    Records.DataGridView1.Item(cIndex, rIndex).Style.BackColor = Color.Red
                    Records.DataGridView1.Item(cIndex, rIndex).Style.ForeColor = Color.White
                End If
                If Records.DataGridView1.Rows(rIndex).Cells(cIndex).Value > 0 Then
                    Records.DataGridView1.Item(cIndex, rIndex).Style.BackColor = Color.Green
                    Records.DataGridView1.Item(cIndex, rIndex).Style.ForeColor = Color.White
                End If
                If Records.DataGridView1.Rows(rIndex).Cells(cIndex).Value = 0 Then
                    Records.DataGridView1.Rows(rIndex).Cells(cIndex).Value = "Broke Even"
                End If

            End If

            'Update the progress bar after each cell is populated
            bw.ReportProgress(rIndex * cIndex)

            rIndex = rIndex + 1

        End While

        'Make column unsortable
        Records.DataGridView1.Columns(cIndex).SortMode = DataGridViewColumnSortMode.NotSortable

        'Update the progress bar after each cell is populated
        bw.ReportProgress(rIndex * cIndex)

        cIndex = cIndex + 1

    End While

    Records.DataGridView1.AutoResizeColumns()

    'Update the progress bar for last time
    bw.ReportProgress(rIndex * cIndex)


End Sub

Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bw.ProgressChanged
    pb.Value = e.ProgressPercentage
    pb.Increment(1)
    pb.Refresh()
End Sub

Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
    If e.Error IsNot Nothing Then
        MessageBox.Show(e.Error.Message, "Background Worker Exception", MessageBoxButtons.OK, MessageBoxIcon.Error)
    Else
        If e.Cancelled Then
            'worker was cancelled
        Else
            'worker completed, open form2 here
            'pb.Value = TotalCellCount
            Records.ShowDialog()
            If (Records.DialogResult) Then
                pb.Visible = False
                ' Close the workbook.
                workbook.Close()

                ' Close the Excel server.
                excel_app.Quit()
            End If

        End If
    End If
End Sub

记录表

This is the code for the Previous Year button on the Records Form

   Private Sub PreviousYear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    'The code in this Sub is not working
    Start.sheet_name = yearstamp - 1
    Me.Close()
    Start.bw.RunWorkerAsync()
    ''
End Sub

UPDATED CODE

    Public Class Records

Dim excel_app As Excel.Application
Dim workbook As Excel.Workbook
Dim sheet_name As String
Dim sheet As Excel.Worksheet
Dim ColumnCount, RowCount, TotalCellCount As Long
Dim yearstamp As String = _
    DateTime.Now.ToString("yyyy")
Dim exeDir As New IO.FileInfo(Reflection.Assembly.GetExecutingAssembly.FullName)
Dim xlPath = IO.Path.Combine(exeDir.DirectoryName, "Records.xlsx")

Public Function QueryExcel(ByVal sheet As String) As DataTable
    'use this connection string for .xlsx files
    Dim cs2007 As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=xlPath;Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1"";"

    Dim sql As String = String.Format("SELECT * FROM [{0}$]", sheet)

    'get contents of xls file
    Using cnn As New OleDb.OleDbConnection(cs2007.Replace("@FILENAME", "YOUR EXCEL FILE"))
        Using cmd As New OleDb.OleDbCommand(sql, cnn)
            Dim t As New System.Data.DataTable
            Try
                cnn.Open()
                t.Load(cmd.ExecuteReader)
            Catch ex As Exception
                'handle exception. in this case i'm just returning an empty table
            End Try
            Return t
        End Using
    End Using
End Function
Private Sub Records_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim t2013 = QueryExcel("2013")
    DataGridView1.DataSource = t2013

End Sub

There are a lot of different ways to query excel and store the data in a variable. One method I have used in the past is OleDb

This is a function you can use to query excel and return the contents in a DataTable

  Public Function QueryExcel(sheet As String) As DataTable
    'use this connection string for .xlsx files
    Dim cs2007 As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=@FILENAME;Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1"";"

    'use this connection string for .xls files
    Dim cs2003 As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=@FILENAME;Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"

    Dim sql As String = String.Format("SELECT * FROM [{0}$]", sheet)
    dim cs = cs2007.Replace("@FILENAME", IO.Path.Combine(exeDir.DirectoryName, "Records.xlsx"))
    'get contents of xls file
    Using cnn As New OleDb.OleDbConnection(cs)
      Using cmd As New OleDb.OleDbCommand(sql, cnn)
        Dim t As New DataTable
        Try
          cnn.Open()
          t.Load(cmd.ExecuteReader)
        Catch ex As Exception
          'handle exception. in this case i'm just returning an empty table
        End Try
        Return t
      End Using
    End Using
  End Function

So now you can use

Dim t2013 = QueryExcel("2013")

And assign it to the DataGridView like this

DataGridView.DataSource = t2013

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM