2013-12-15 49 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