2017-09-26 29 views
1

這是我在SO中的第一篇文章。如你所知,我不是一個專業的程序員,只是一個普通的辦公室工作人員不時地做一些VBA來加快他的工作。循環訪問選定條件的非連續行

我想循環使用VBA的一系列單元格,其中一列包含特定的標誌值。這些範圍是非連續的,因爲我們選擇具有連續標誌值的範圍,並且此值在每一行中隨機更改。

例如在下表中,我們如何循環三次(因爲有三個不連續的範圍和連續的-1個標誌),選擇第一次迭代中的前三行,第二次中的第五和第六行運行,並在第三次迭代中選擇第8行?

+-------+---------+------+ 
| Index | Value | Flag | 
+-------+---------+------+ 
|  1 | 0.43534 | -1 | 
|  2 | 0.24366 | -1 | 
|  3 | 0.23654 | -1 | 
|  4 | 0.56854 | 0 | 
|  5 | 0.97867 | -1 | 
|  6 | 0.35678 | -1 | 
|  7 | 0.47845 | 0 | 
|  8 | 0.74567 | -1 | 
+-------+---------+------+ 
+0

無論是在較低級別還是較高級別,一切都在循環。即使在數據庫中,每條記錄都有初始循環。關鍵是你如何處理循環,你可以在一個循環中做你需要做的所有事情,而不需要重做。如果你想對一個循環內的組進行計算,那麼考慮'Do Loop While' – MacroMarc

+0

感謝@MacroMarc的建議。你可能會分享一些網絡資源或關鍵字,在這些資源或關鍵字中我可以閱讀更多關於循環的內容,特別是在如何處理循環算法以在單個循環中完成所有事情的情況下?對不起,如果這是一個基本的計算機科學問題,因爲我仍然試圖學習這個主題。 –

回答

1

以下代碼將在消息框中給出用Flag = -1指定所有範圍的結果。根據您的樣本數據圖像,輸出將是$C$2:$C$4$C$6:$C$7,$C$9

Sub Demo() 
    Dim ws As Worksheet 
    Dim cel As Range, rng As Range, fCell As Range, tempRng As Range 
    Dim lastRow As Long 
    Dim isNegative As Boolean 

    Set ws = ThisWorkbook.Sheets("Sheet2")  'change Sheet2 to your data sheet 
    isNegative = False 

    With ws 
     lastRow = .Cells(.Rows.Count, "C").End(xlUp).Row 'last row with data in Column C 

     For Each cel In .Range("C2:C" & lastRow + 1) 'loop through each cell in Column C 
      If cel.Value = -1 Then  'check if value is -1 
       If Not isNegative Then 
        Set fCell = cel 
        isNegative = True 
       End If 
      Else      'if not then set range 
       If isNegative Then 
        If rng Is Nothing Then 
         Set rng = .Range(fCell, cel.Offset(-1, 0).Address) 
        Else 
         Set rng = Union(rng, .Range(fCell, cel.Offset(-1, 0).Address)) 
        End If 
        isNegative = False 
       End If 
      End If 
     Next cel 
    End With 
    For Each tempRng In rng.Areas 'loop through all ranges with -1 
     MsgBox tempRng.Address 
     'write your code here 
    Next tempRng 
End Sub 

這裏的代碼中使用的Booloean變量isNegative的簡要說明。

isNegative用於維持標誌範圍.Range("C2:C" & lastRow + 1)最後一個單元格的值是否是-1與否,在開始處被設置爲FALSE。當第一個-1被反抗時,則isNegative被設置爲TRUE並且fCell被分配了相應的單元地址。直到循環遇到-1,isNegative將保持TRUE。當遇到具有值不等於-1細胞,範圍是使用rngfCell使用Set rng = .Range(fCell, cel.Offset(-1, 0).Address)如果遇到與-1只有一個小區別的Set rng = Union(rng, .Range(fCell, cel.Offset(-1, 0).Address))如果遇到與-1多於一個小區設置爲當前小區。
當遇到第二個或更多個值不等於-1的連續單元格時,則不會發生任何事情。當遇到值爲-1的下一個單元時,重複上述過程。

+0

Mrig,非常感謝你提供這個詳細的答案,我沒有意識到這個問題將在幾個小時內得到解決。 SO真是太神奇了,它的天才社區願意幫助他人接觸編程。 –

+0

如果你還有時間,我想問你是如何得到解決方案的?不一定是詳細的解釋,也許只是一個粗略的邏輯圖,它將顯示數據流並指導我深入挖掘並研究所使用的方法。 (我對使用'isNegative'和'isRange'布爾變量特別困惑) –

+0

@EmanmanD。 - 我已經添加了「isNegative」的解釋。 'isRange'不是必需的,用於測試並在上傳答案時忘記從代碼中刪除它。讓我知道是否還有什麼不清楚。 – Mrig

1

你仍然環路正常,但使用IF語句來檢查,如果第3列(C)具有-1,如:

Dim i as Long 

For i = 2 to 9 'Assumes 1 is a header row, despite 1-8 being counted 
    If Cells(i,3).Value= -1 Then 
     'Do something 
    End If 
Next i 
0

我會考慮使用類似do while flag=-1

或者改爲使用條件if Flag(index)=Flag(index+1) then *do something*,因爲我認爲更復雜的事情需要設計模塊類。