2011-03-03 62 views
47

Tôi đang làm một ứng dụng Excel cần nhiều dữ liệu cập nhật từ cơ sở dữ liệu, vì vậy phải mất thời gian. Tôi muốn tạo một thanh tiến trình trong một userform và nó hiện lên khi dữ liệu đang được cập nhật. Thanh tôi muốn chỉ là một thanh màu xanh nhỏ di chuyển sang phải và trái và lặp lại cho đến khi cập nhật xong, không cần phần trăm. Tôi biết tôi nên sử dụng điều khiển progressbar, nhưng tôi đã thử một thời gian nhưng không thể thực hiện được.Thanh tiến trình trong VBA Excel

EDIT: Vấn đề của tôi là với điều khiển progressbar, tôi không thể thấy thanh 'tiến trình', nó chỉ hoàn thành khi biểu mẫu bật lên. Tôi sử dụng vòng lặp và DoEvent nhưng không hoạt động. Ngoài ra, tôi muốn quá trình lặp lại, không chỉ một lần.

+2

"cố gắng trong một thời gian, nhưng không thể làm cho nó" - cho chúng ta thấy những gì bạn đã quản lý để làm, các vấn đề là gì và chúng tôi sẽ cố gắng giúp bạn –

+1

thx để được tư vấn, xem chỉnh sửa – darkjh

Trả lời

30

Trong quá khứ, với các dự án VBA, tôi đã sử dụng điều khiển nhãn với màu nền và điều chỉnh kích thước dựa trên tiến trình. Một số ví dụ với cách tiếp cận tương tự có thể được tìm thấy trong các liên kết sau đây:

  1. http://oreilly.com/pub/h/2607
  2. http://www.ehow.com/how_7764247_create-progress-bar-vba.html
  3. http://spreadsheetpage.com/index.php/tip/displaying_a_progress_indicator/

Dưới đây là một trong đó sử dụng AutoShapes của Excel:

http://www.andypope.info/vba/pmeter.htm

+1

thx tôi sẽ cố gắng theo cách này – darkjh

+1

@darkjh: Bạn được chào đón. Thấy bạn mới, hãy nhớ chấp nhận và/hoặc bỏ phiếu nếu điều này trả lời câu hỏi của bạn hoặc hữu ích. Cảm ơn. – Matt

8
============== This code goes in Module1 ============ 

Sub ShowProgress() 
    UserForm1.Show 
End Sub 

============== Module1 Code Block End ============= 

Tạo một Nút trên Trang tính; nút bản đồ để "ShowProgress" vĩ mô

Tạo một UserForm1 với 2 nút, thanh tiến trình, hộp quầy bar, hộp văn bản:

UserForm1 = canvas to hold other 5 elements 
CommandButton2 = Run Progress Bar Code; Caption:Run 
CommandButton1 = Close UserForm1; Caption:Close 
Bar1 (label) = Progress bar graphic; BackColor:Blue 
BarBox (label) = Empty box to frame Progress Bar; BackColor:White 
Counter (label) = Display the integers used to drive the progress bar 

======== Attach the following code to UserForm1 ========= 

Option Explicit 

' This is used to create a delay to prevent memory overflow 
' remove after software testing is complete 

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 

Private Sub UserForm_Initialize() 

    Bar1.Tag = Bar1.Width 
    Bar1.Width = 0 

End Sub 
Sub ProgressBarDemo() 
    Dim intIndex As Integer 
    Dim sngPercent As Single 
    Dim intMax As Integer 
    '============================================== 
    '====== Bar Length Calculation Start ========== 

    '-----------------------------------------------' 
    ' This section is where you can use your own ' 
    ' variables to increase bar length.    ' 
    ' Set intMax to your total number of passes  ' 
    ' to match bar length to code progress.   ' 
    ' This sample code automatically runs 1 to 100 ' 
    '-----------------------------------------------' 
    intMax = 100 
    For intIndex = 1 To intMax 
     sngPercent = intIndex/intMax 
     Bar1.Width = Int(Bar1.Tag * sngPercent) 
     Counter.Caption = intIndex 


    '======= Bar Length Calculation End =========== 
    '============================================== 


DoEvents 
     '------------------------ 
     ' Your production code would go here and cycle 
     ' back to pass through the bar length calculation 
     ' increasing the bar length on each pass. 
     '------------------------ 

'this is a delay to keep the loop from overrunning memory 
'remove after testing is complete 
     Sleep 10 

    Next 

End Sub 
Private Sub CommandButton1_Click() 'CLOSE button 

Unload Me 

End Sub 
Private Sub CommandButton2_Click() 'RUN button 

     ProgressBarDemo 

End Sub 

================= UserForm1 Code Block End ===================== 

============== This code goes in Module1 ============= 

Sub ShowProgress() 
    UserForm1.Show 
End Sub 

============== Module1 Code Block End ============= 
+0

Đây là một giải pháp tốt đẹp! – Stephan

106

Đôi khi một thông điệp đơn giản trong thanh trạng thái là đủ:

Message in Excel status bar using VBA

Đây là very simple to implement:

Dim x    As Integer 
Dim MyTimer   As Double 

'Change this loop as needed. 
For x = 1 To 50 
    ' Do stuff 
    Application.StatusBar = "Progress: " & x & " of 50: " & Format(x/50, "0%") 
Next x 

Application.StatusBar = False 
+4

Rất vui khi tôi thấy điều này. Là một ý tưởng tốt hơn cho tôi hơn là thực sự giả mạo một thanh tiến trình. – atomicules

+1

Như tôi - đơn giản và hiệu quả. – Sean

+0

Câu trả lời tuyệt vời. +1 – Caltor

41

Đây là một ví dụ khác bằng cách sử dụng thanh trạng thái như một thanh tiến trình.

Bằng cách sử dụng một số ký tự Unicode, bạn có thể bắt chước thanh tiến trình. 9608 - 9615 là những mã tôi đã thử cho các thanh. Chỉ cần chọn một theo bao nhiêu không gian bạn muốn hiển thị giữa các thanh. Bạn có thể đặt độ dài của thanh bằng cách thay đổi NUM_BARS. Cũng bằng cách sử dụng một lớp, bạn có thể thiết lập nó để xử lý khởi tạo và phát hành Statusbar một cách tự động. Một khi đối tượng đi ra khỏi phạm vi nó sẽ tự động dọn dẹp và phát hành StatusBar trở lại Excel.

' Class Module - ProgressBar 
Option Explicit 

Private statusBarState As Boolean 
Private enableEventsState As Boolean 
Private screenUpdatingState As Boolean 
Private Const NUM_BARS As Integer = 50 
Private Const MAX_LENGTH As Integer = 255 
Private BAR_CHAR As String 
Private SPACE_CHAR As String 

Private Sub Class_Initialize() 
    ' Save the state of the variables to change 
    statusBarState = Application.DisplayStatusBar 
    enableEventsState = Application.EnableEvents 
    screenUpdatingState = Application.ScreenUpdating 
    ' set the progress bar chars (should be equal size) 
    BAR_CHAR = ChrW(9608) 
    SPACE_CHAR = ChrW(9620) 
    ' Set the desired state 
    Application.DisplayStatusBar = True 
    Application.ScreenUpdating = False 
    Application.EnableEvents = False 
End Sub 

Private Sub Class_Terminate() 
    ' Restore settings 
    Application.DisplayStatusBar = statusBarState 
    Application.ScreenUpdating = screenUpdatingState 
    Application.EnableEvents = enableEventsState 
    Application.StatusBar = False 
End Sub 

Public Sub Update(ByVal Value As Long, _ 
        Optional ByVal MaxValue As Long= 0, _ 
        Optional ByVal Status As String = "", _ 
        Optional ByVal DisplayPercent As Boolean = True) 

    ' Value   : 0 to 100 (if no max is set) 
    ' Value   : >=0 (if max is set) 
    ' MaxValue  : >= 0 
    ' Status   : optional message to display for user 
    ' DisplayPercent : Display the percent complete after the status bar 

    ' <Status> <Progress Bar> <Percent Complete> 

    ' Validate entries 
    If Value < 0 Or MaxValue < 0 Or (Value > 100 And MaxValue = 0) Then Exit Sub 

    ' If the maximum is set then adjust value to be in the range 0 to 100 
    If MaxValue > 0 Then Value = WorksheetFunction.RoundUp((Value * 100)/MaxValue, 0) 

    ' Message to set the status bar to 
    Dim display As String 
    display = Status & " " 

    ' Set bars 
    display = display & String(Int(Value/(100/NUM_BARS)), BAR_CHAR) 
    ' set spaces 
    display = display & String(NUM_BARS - Int(Value/(100/NUM_BARS)), SPACE_CHAR) 

    ' Closing character to show end of the bar 
    display = display & BAR_CHAR 

    If DisplayPercent = True Then display = display & " (" & Value & "%) " 

    ' chop off to the maximum length if necessary 
    If Len(display) > MAX_LENGTH Then display = Right(display, MAX_LENGTH) 

    Application.StatusBar = display 
End Sub 

Sample Cách sử dụng:

Dim progressBar As New ProgressBar 

For i = 1 To 100 
    Call progressBar.Update(i, 100, "My Message Here", True) 
    Application.Wait (Now + TimeValue("0:00:01")) 
Next 
2
Sub ShowProgress() 
' Author : Marecki 
    Const x As Long = 150000 
    Dim i&, PB$ 

    For i = 1 To x 
    PB = Format(i/x, "00 %") 
    Application.StatusBar = "Progress: " & PB & " >>" & String(Val(PB), Chr(183)) & String(100 - Val(PB), Chr(32)) & "<<" 
    Application.StatusBar = "Progress: " & PB & " " & ChrW$(10111 - Val(PB)/11) 
    Application.StatusBar = "Progress: " & PB & " " & String(100 - Val(PB), ChrW$(9608)) 
    Next i 

    Application.StatusBar = "" 
End SubShowProgress 
0

đẹp hình thức progressbar thoại tôi đã tìm kiếm. progressbar from alainbryden

rất dễ sử dụng và trông đẹp mắt.

chỉnh sửa: liên kết chỉ hoạt động cho thành viên cao cấp bây giờ:/

here là đẹp lớp thay thế.

6

Điều khiển nhãn đổi kích thước là giải pháp nhanh. Tuy nhiên, hầu hết mọi người sẽ tạo ra các biểu mẫu riêng lẻ cho mỗi macro của họ. Tôi đã sử dụng hàm DoEvents và một biểu mẫu vô dụng để sử dụng một biểu mẫu duy nhất cho tất cả các macro của bạn.

Đây là một bài viết trên blog, tôi đã viết về nó: http://strugglingtoexcel.wordpress.com/2014/03/27/progress-bar-excel-vba/

Tất cả bạn phải làm là nhập khẩu các hình thức và một module vào các dự án của bạn, và gọi thanh tiến trình với: Gọi modProgress.ShowProgress (ActionIndex, TotalActions , Tiêu đề .....)

Tôi hy vọng điều này sẽ hữu ích.

+1

Tôi cũng tìm thấy nút "Hủy bỏ" trên Hộp thoại rất hữu ích, cảm ơn bạn. –

+1

Xin chào Thomas. Tất cả chúng ta đều muốn dừng một vòng theo ý muốn, đó là lý do tại sao tôi mã hóa nó. Cảm ơn vì đã chú ý. Có một ngày tuyệt vời. –

2

Tôi yêu tất cả các giải pháp được đăng ở đây, nhưng tôi đã giải quyết vấn đề này bằng Định dạng có điều kiện dưới dạng Thanh dữ liệu dựa trên phần trăm.

Conditional Formatting

này được áp dụng cho một dãy tế bào như hình dưới đây. Các ô bao gồm 0% và 100% thường bị ẩn, vì chúng chỉ ở đó để cung cấp ngữ cảnh "Phạm vi quét" được đặt tên (Trái).

Scan progress

Trong mã tôi đang lặp qua bảng làm một số nội dung.

For intRow = 1 To shData.Range("tblData").Rows.Count 

    shData.Range("ScanProgress").Value = intRow/shData.Range("tblData").Rows.Count 
    DoEvents 

    ' Other processing 

Next intRow 

Mã tối thiểu, trông khá.

+5

Vấn đề chính tôi thấy với cách tiếp cận này là tôi thường tắt các cập nhật màn hình và calcs khi tôi đang thực hiện các thao tác lớn làm cho thanh tiến trình trở nên hữu ích. – VoteCoffee

2

Xin chào phiên bản sửa đổi của bài đăng khác theo số Marecki. Có 4 kiểu

1. dots .... 
2 10 to 1 count down 
3. progress bar (default) 
4. just percentage. 

Trước khi bạn hỏi tại sao tôi không chỉnh sửa bài đăng đó là tôi đã làm và từ chối được yêu cầu đăng câu trả lời mới.

Sub ShowProgress() 

    Const x As Long = 150000 
    Dim i&, PB$ 

    For i = 1 To x 
    DoEvents 
    UpdateProgress i, x 
    Next i 

    Application.StatusBar = "" 
End Sub 'ShowProgress 

Sub UpdateProgress(icurr As Long, imax As Long, Optional istyle As Integer = 3) 
    Dim PB$ 
    PB = Format(icurr/imax, "00 %") 
    If istyle = 1 Then ' text dots >>.... <<' 
     Application.StatusBar = "Progress: " & PB & " >>" & String(Val(PB), Chr(183)) & String(100 - Val(PB), Chr(32)) & "<<" 
    ElseIf istyle = 2 Then ' 10 to 1 count down (eight balls style) 
     Application.StatusBar = "Progress: " & PB & " " & ChrW$(10111 - Val(PB)/11) 
    ElseIf istyle = 3 Then ' solid progres bar (default) 
     Application.StatusBar = "Progress: " & PB & " " & String(100 - Val(PB), ChrW$(9608)) 
    Else ' just 00 % 
     Application.StatusBar = "Progress: " & PB 
    End If 
End Sub 
2

Về progressbar kiểm soát trong một userform, nó sẽ không hiển thị bất kỳ tiến bộ nếu bạn không sử dụng các sự kiện repaint. Bạn phải mã sự kiện này bên trong vòng lặp (và rõ ràng là tăng giá trị progressbar).

Ví dụ về sử dụng:

userFormName.repaint 
0

Giải pháp đăng bởi @eykanal thể không phải là tốt nhất trong trường hợp bạn có số lượng lớn các dữ liệu để đối phó với như tạo điều kiện cho thanh trạng thái sẽ làm chậm thực thi mã.

Liên kết sau giải thích cách tốt để tạo thanh tiến trình.Hoạt động tốt với khối lượng dữ liệu cao (~ 250K hồ sơ +):

http://www.excel-easy.com/vba/examples/progress-indicator.html