2013-12-15 48 views
0

我有一个“查看记录”按钮的开始窗体。在记录表单加载事件我有循环填充记录表单上的datagridview。我想要做的是在“开始”表单上的“查看记录”按钮旁边显示一个进度条,当用户单击“查看记录”按钮时,该按钮将显示“记录”窗体上datagridview的进度。然后,一旦datagridview循环成功完成,我想调出记录表单(但仍然将开始表单作为父表单打开,因此“查看记录”表单将由ShowDialog提供)。我有简单的代码来显示“查看记录”按钮点击进度条。我正在阅读,发现可能有一名后台工作人员可能是我需要的,但我不知道如何使用它。有人能帮助我通过它并提供一些代码来帮助我吗?一些信息,开始形式被称为“开始”,而“查看记录”形式被称为“记录”。进度条是名字'pb'。提前感谢任何想尝试帮助的人!如何添加一个进度条来显示窗体按钮点击,显示窗体2的加载进度

好吧,这里有错误

Imports Office = Microsoft.Office.Core 
Imports Excel = Microsoft.Office.Interop.Excel 
Public Class Start 
Dim Records As New Records 
Dim excel_app As Excel.Application 
Dim workbook As Excel.Workbook 
Dim sheet_name As String 
Dim sheet As Excel.Worksheet 
Dim exeDir As New IO.FileInfo(Reflection.Assembly.GetExecutingAssembly.FullName) 
Dim xlPath = IO.Path.Combine(exeDir.DirectoryName, "Records.xlsx") 

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

End Sub 

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



    ' 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 = "2013" 

    sheet = excel_app.Worksheets("2013") 

    Dim ColumnCount, RowCount, TotalCellCount As Long 
    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 = 0 
    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 

    'Loop through each column 
    Dim cIndex As Integer = 0 
    While cIndex < ColumnCount 

     'Loop through and populate each row in column 
     Dim rIndex As Integer = 0 
     While rIndex < RowCount - 1 
      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)/TotalCellCount) 

      rIndex = rIndex + 1 

     End While 

     'Format all cells in column as currency values 
     Records.DataGridView1.Columns(cIndex).DefaultCellStyle.Format = "c" 
     'Make column unsortable 
     Records.DataGridView1.Columns(cIndex).SortMode = DataGridViewColumnSortMode.NotSortable 
     'Resize all Row Headers so user can see Row Titles without resizing 
     Records.DataGridView1.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders) 

     cIndex = cIndex + 1 
    End While 

    Records.DataGridView1.AutoResizeColumns() 

End Sub 

Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bw.ProgressChanged 
    pb.Value = e.ProgressPercentage 
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.Visible = False 
      Records.ShowDialog() 
      If (Records.DialogResult) Then 
       ' Close the workbook. 
       workbook.Close() 

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

     End If 
    End If 
End Sub 

我这样做正确更新的代码?我该如何解决这个错误?

+0

这个进度条在哪里,Form1,2或者一些额外的表单?你确定延迟是在哪里吗?将代码放入表单加载可能是您最大的问题。一般来说,我会显示表单,然后调用显式方法来完成填充。我只看线程,如果get和process阶段很慢,我会在显示表单之前这样做。或者,如果我希望是异步的,即保持form1可用于其他操作,而“form2”进程正在弄清楚该怎么做。这也将分离获取和显示过程。 –

+0

只是澄清如果Form1是不可用的,并且form2还不能显示,那么对它进行线程化并同步UI是没有意义的复杂性。你需要分开关注点。 –

+0

进度条位于“查看记录”按钮旁边的表单1中,并在单击“查看记录”按钮时显示。我对你说的有点失落。对不起,我很新。我应该将“填充”循环代码移到“记录”表单中的表单加载事件之外吗?如果是这样,那么我如何才能开始循环呢? – CaffeinatedCoder

回答

1

我会在Form1上使用后台工作者,然后订阅其ProgressChanged事件来更新进度栏。然后,当工作人员完成时,您可以将该数据传递给Form2并将其打开。

假设你添加一个名为BW BackgroundWorker的到Form1

在您需要通过调用bw.RunWorkerAsync

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

末次启动工作按钮点击事件

Private Sub Setup() 
' 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 = "2013" 

sheet = excel_app.Worksheets("2013") 

Dim ColumnCount, RowCount, TotalCellCount As Long 
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 = 0 
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 

然后在bw.DoWork事件您将运行代码来获取数据。创建窗体级变量,所以你可以在DoWork的和RunWorkerCompleted事件

Dim f as New RecordForm 

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


'Loop through each column 
Dim cIndex As Integer = 0 
While cIndex < ColumnCount 

    'Loop through and populate each row in column 
    Dim rIndex As Integer = 0 
    While rIndex < RowCount - 1 
     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)/TotalCellCount) 

     rIndex = rIndex + 1 

    End While 

    'Format all cells in column as currency values 
    Records.DataGridView1.Columns(cIndex).DefaultCellStyle.Format = "c" 
    'Make column unsortable 
    Records.DataGridView1.Columns(cIndex).SortMode = DataGridViewColumnSortMode.NotSortable 
    'Resize all Row Headers so user can see Row Titles without resizing 
    Records.DataGridView1.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders) 

    cIndex = cIndex + 1 
End While 

Records.DataGridView1.AutoResizeColumns() 
End Sub 

Private Sub bw_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles bw.ProgressChanged 
    ProgressBar.Value = e.ProgressPercentage 
End Sub 

当工人完成后,将火其完成的事件访问。

Private Sub bw_RunWorkerCompleted(sender As Object, 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 finished. open Form2 
     f.Show 
    End If 
    End If 
End Sub 
+0

我得到一个InvalidOperationException,下面的解释“这个BackgroundWorker声明它不报告进度,修改WorkerReportsProgress来声明它报告进度。”我添加了与我共享的所有部分,但它仍然返回异常 – CaffeinatedCoder

+0

如何获取数据? datagridview在第二个表单(记录表单)上,并填充到第二个表单的加载事件中 – CaffeinatedCoder

+0

例外是告诉你该怎么做。将'WorkerReportsProgress'属性设置为'True'。您可以在设计器或代码中执行此操作。 – Jeff