简体   繁体   English

单击按钮时无法在datagridview中显示不同的工作表数据

[英]Trouble displaying different worksheet data in datagridview on button click

I have a datagridview control on a form (Records form). 我在窗体(记录窗体)上有一个datagridview控件。 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. 在第一个表单(“开始”表单)上,我有一个按钮(“查看记录”按钮),当单击该按钮时,它将包括我在“开始”表单上拥有的后台工作人员(名为bw)的所有代码(在下面列出)。 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. 当用户单击“查看记录”按钮时,该按钮旁边会出现一个进度条,并显示要加载的datagridview的进度。 I am loading the datagridview via a loop that grabs all the values from an excel file. 我正在通过从Excel文件获取所有值的循环加载datagridview。 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. 我的工作正常,但现在我希望能够使用相同的循环重新加载datagridview,但是当用户按下“记录”表单上的“上一年”按钮时,从excel工作簿中的另一张表中获取数据。 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. 查询excel并将数据存储在变量中有很多不同的方法。 One method I have used in the past is OleDb 我过去使用的一种方法是OleDb

This is a function you can use to query excel and return the contents in a DataTable 此函数可用于查询excel并返回数据表中的内容

  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

DataGridView.DataSource = t2013

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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