Home
About me



 VBA Programming
Download my Add-In tool (run on 32-bit MS Office Excel)
VBA Basic for beginners
Excel Main Objects
More with Rows, Columns, Cells, Range ...
Working around your Worksheet ...
Statements
Functions
Conditional Statements and Loops Structure
Errors Handling
UserForms
Pivot Tables
Charting
AutoFilter, Advanced Filter
File I/O VBA Examples
ADO and DAO, integrating Excel and Access
Other VBA fun staff

Conditional statements and Loop structures

If…Then…ElseIf…Else examples
Select Case examples
For… Next loop examples
Do...Loop examples
Do While ...Loop examples
Do ...Loop While examples
Do Until…Loop examples
Do …Loop Until examples
While...Wend examples

Many times in your work on spreadsheet, you may want to repeat an action (populate a formula, copy value over to somewhere, formatting, etc) a predetermined number of times, or to repeat an action or a series of action base upon a variable value that changes every time, or repeat until a certain condition is met. Under such circumstances, you would use loops structures  or conditional statement in VBA. Of course, there is nothing wrong if a readily recorded macro can do all the jobs for you, but a variable code should give you much more flexibility and advantages over hard-coding the number of repetitions. For example, when the sheet that you received sometimes had certain columns changed or the header names had changed, you would find that your recorded macro no longer work. Worst the macro may still worked and gave you the output that seemed normal but you did not notice that it had computed the wrong columns and what you thought normal was in deed a very misleading result.


Using Conditional Statements to make decisions
Conditional statements evaluate whether a condition is True or False, and then specify one or more statements to run, depending on the result.

If...Then...Else              :Branching and execute a statement when a condition is True or False
If…Then…ElseIf…Else
:Let you decide multiple courses of action, for example, when you need three or more Msgbox
Select Case                
:Selecting a branch from a set of conditions

The syntax for If…Then…Else statement is: 

If condition Then
    statements1
Else
    statements2
End If


You can use any number of ElseIf lines in a block IF statement, each with its own condition. It all depends on how complex the conditions and your problem are that you need to evaluate. Although the Else clause is optional, but because there is still a possibility that none of the stated conditions is true, you want to make it catches all conditions by providing with a last Else clause. The last Else in your list of conditions would act if none of the primary conditions is true. Take note that a single line If…Then…ElseIf…Else statements don’t need and End If statement, but a block If…Then…ElseIf…Else statements do need an End If. The syntax for If…Then…ElseIf…Else statement is:

If condition1 Then
   statements1
ElseIf condition2 Then
   statements2
ElseIf condition3 Then
   statements3
Else
   Statements4
End If


Nested IF statements are quite complicating but they are can be very useful for certain complex situations that you need to check. Each nested IF statement must be complete with its End If clause. For example, if you nest one block IF statement within another block IF statement and forget the End If clause for the nested If, VBA would assume that you only want the outer End, and that will give you very different result. In the following syntax for a nested IF, only when condition1 is False, the nested If statements would not execute, but VBA will branch straight to the outer Else line and continues execution from there. If condition1 is True, the code will execute the nested IF condition2, condition3, and so on.

If condition1 Then
   If condtion2 Then
      If condition3 Then
         statements1
      ElseIf condition4 Then
         statements2
      Else
         statements3
      End If
   Else
      If condition5 Then
         statement4
      End If
   End If
Else
       statement5
End If


Running several statements on the same Object

In VBA, usually you must specify an object before you can run one of its methods or change one of its properties. You can use the With statement to specify an object once for an entire series of statements. Select Case statement provides an alternative to multiple ElseIf statements. You use Select Case when the decision you need to make in the code depends on one variable or expression that has more than three different values that you need to examine. Case Else is similar to the Else clause in an IF statement. The expression is known as test case
.

Select Case Expression
   Case Expression1
      statement1
   Case Expression2
      statement2
   Case Expression3
      statement3
   Case Else
      statement4
End Select


Using Loops structure to repeat code

A loop is a structure that runs through a number of statements in a procedure, looping back again to the beginning of the structure once it has finished execution. Each cycle of execution of a loop is called reiteration. A fixed-iteration loop (loop that repeats an iteration a fixed number of times) typically use numerical expression, where as indefinite-iteration loop (loop that repeats an iteration a flexible number of times) typically use logical expression. 

Fixed-iteration loop types:
For...Next        
: Using a counter to repeats a statement or a sequence of actions a specified number of times
For Each...Next
: Repeating an action or a group of statements for each object in a VBA collection

There are five types of Indefinite-iteration loop of using While or Until:
Do While…Loop
:Continue to perform a statement or a sequence of actions if a condition is True, and stops only when the
                            condition becomes False

Do Until…Loop  
:Continue to perform a statement or a sequence of actions if a condition is False, and stops only when the
                            condition becomes True

Do…Loop While
:Performs an action or a sequence of actions once and then repeats it while a condition is True until it becomes
                            False

Do…Loop Until
   : Performs an action or a sequence of actions once and then repeats it while a condition is False until it becomes
                            True

While…Wend    
:Same like Do…Loop While but this one almost never see people use these days
 

 


In the above indefinite-iteration loop types, because you can construct the Do…Loop with the While or Until qualifiers at the beginning or at the end, it give you a lot of flexibility whether you want to execute the loop only once, given that your first condition is True at the beginning. There are some examples in the later section where you will be able to savour these looping power.
 

Return To Top


Example 1.1 is a simple If…Then…Else conditional statement. If the first sheet name is “template” and if user clicks Cancel, the procedure stops; otherwise it will call the macro. If the first sheet name is not “template”, it exits sub procedure right away.
Private Sub Workbook_Open()
On Error Resume Next
  If Sheets(1).Name = "template" Then
     If MsgBox("Do you want to continue?", vbOKCancel, "Message Alert")=vbCancel Then
  Exit Sub

         ‘ then call your Macro
  Else
  Exit Sub
  End If
End Sub



Example 1.2 another If…Then…Else statement that asks for user’s input of the value or text to select, from the active sheet’s used range. It selects all the cells that have the same value or text the user had selected. Press OK, it fills the selected cells with Green. In this example, I selected the value zero.
Dim rng As Range, iArea As Range, iRange As Range
Dim Valu As String, i As Long
Set iArea = Range(Cells(1, 1), ActiveCell.SpecialCells(xlLastCell))
Valu = InputBox("enter the value or text to select")
For Each rng In iArea
  If rng.Text = Valu Then
      If i = 0 Then
         Set iRange = rng
         i = 1
      Else
         Set iRange = Union(iRange, rng)
      End If
  End If
Next rng
iRange.Select
With Selection.Interior
  .ColorIndex = 50
  .Pattern = xlSolid
End With

 

 

Example 1.3 The following procedure has a rather long complex nested If…Then…ElseIf statements that I applied to one of my office work. I will show you a section of the statements so that you can more easily understand the nested If…Then…ElseIf structure which can sometimes gets very long and confusing especially for the VBA novices.  You can also download the original procedure which run base on different conditions and column of factual data, and help to make useful decisions. It then populates the outcome in the last two columns of the worksheet. In other cases, you can always combine If..Then..ElseIf statements with some other loop structure. Instead of using the Find method, you can use the InputBox method to ask for user’s input, and store the different column numbers in the variables. Note: raw data in the download example are not the true cases.

DOWNLOAD this example.

Return To Top

Sub Opt_Plan_analysis()

Dim i As Long, lastrow As Long, loc As Byte, cos As Byte, m As Byte, ec As Byte, summ As Byte, ttsl As Byte, sga As Byte, sgm As Byte, _
sgt As Byte, ls As Byte, m12 As Byte, tpmvs As Byte, obm As Byte, remk As Byte, align As Byte, Location As String, OptMin As Integer, _
UnitCost As Long, EventClassification As String, TotalTSL As Integer, SGAnnualDmd As Long, SGMOU As Byte, LocalSource As String, _
TPM_VitalSpares As String, ObsoletePartMOU As Byte, Remark As String, Reason As String, SG_m_1 As Integer, SG_m_2 As Integer, _
SG_m_3 As Integer, SG_m_6 As Integer, SG_m_7 As Integer, SGlast12months_average As Integer, SGlast12months_max As Integer, _
SGlast12months_min As Integer, SGlast3months_average As Integer

Const keep = "disagree to reduce TSL to Opt-Min: keep current TSL of "
lastrow = Cells(65536, 1).End(xlUp).Row
Rows("1:1").Cells.Find(What:="location", After:=[A1]).SelectlLoc = ActiveCell.Column
' or alternatively as,
'  loc = Range(Rows("1:1").Cells.Find(What:="location", After:=Cells(1, 1), LookIn:=xlValues, LookAt:=xlWhole, _
      SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True).Address).Column
'  or loc =  Rows("1:1").Cells.Find(What:="location", After:=Cells(1, 1).Column

cos = Rows("1:1").Cells.Find(What:="st*Cost", After:=[A1]).Column
m = Rows("1:1").Cells.Find(What:="opt*Min", After:=[A1]).Column
ec = Rows("1:1").Cells.Find(What:="event*class*", After:=[A1]).Column
summ = Rows("1:1").Cells.Find(What:="summary*", After:=[A1]).Column
ttsl = Rows("1:1").Cells.Find(What:="Total*TSL*", After:=[A1]).Column
sga = Rows("1:1").Cells.Find(What:="SG*Annual*", After:=[A1]).Column
sgm = Rows("1:1").Cells.Find(What:="SG*MOU", After:=[A1]).Column
ls = Rows("1:1").Cells.Find(What:="loc*source", After:=[A1]).Column
tpmvs = Rows("1:1").Cells.Find(What:="TPM*VIT*CE*", After:=[A1]).Column
obm = Rows("1:1").Cells.Find(What:="obsolete*mou*", After:=[A1]).Column
remk = Rows("1:1").Cells.Find(What:="*remark*", After:=[A1]).Column
align = Rows("1:1").Cells.Find(What:="align*", After:=[A1]).Column

For i = 2 To lastrow

Location = Cells(i, loc).Value
UnitCost = Cells(i, cos).Value
OptMin = Cells(i, m).Value
EventClassification = Cells(i, ec).Value
TotalTSL = Cells(i, ttsl).Value
SGAnnualDmd = Cells(i, sga).Value
SGMOU = Cells(i, sgm).Value
SG_m_1 = Cells(i, sga).Offset(, -1).Value
SG_m_2 = Cells(i, sga).Offset(, -2).Value
SG_m_3 = Cells(i, sga).Offset(, -3).Value
SG_m_6 = Cells(i, sga).Offset(, -6).Value
SG_m_7 = Cells(i, sga).Offset(, -7).Value
LocalSource = Cells(i, ls).Value
TPM_VitalSpares = Cells(i, tpmvs).Value
ObsoletePartMOU = Cells(i, obm).Value
Remark = Cells(i, remk).Value
Reason = Cells(i, align).Value

On Error Resume Next
If Location = "8800" Then
    If OptMin = 0 And TotalTSL > 0 Then 
' to remove Safety Stock Level?
        If SGMOU > 0 Then
            If (TPM_VitalSpares Like "TEC*" Or TPM_VitalSpares Like "UMC*" Or TPM_VitalSpares Like "Char*") Then
                Remark = "disagree to remove TSL: " & TPM_VitalSpares
                Reason = "Other"
            ElseIf TPM_VitalSpares Like "SSMC*" And LocalSource Like "Consign*" Then
                Remark = "disagree to remove TSL: SSMC TPM program spare with Consignment TSL in plant 8800"
                Reason = "ContractCommit"
            End If
        ElseIf SGMOU = 0 And ObsoletePartMOU = 0 Then
            If TPM_VitalSpares = vbNullString Then
                Remark = "agree to remove TSL (SG 12months MOU 0, and not vital spare)"
                Reason = "Agree with SIMPLE"
        End If
    ElseIf OptMin = TotalTSL Then 
'Optimized Min level = Safety Stock Level?
        Remark = "no mismatch as Opt-Min = site TSL"
        Reason = "Agree with SIMPLE"
    ElseIf OptMin > 0 And TotalTSL > OptMin Then  
 ' to reduce Safety Stock Level?
        With Application
        SGlast12months_max = .Max(Cells(i, sga).Offset(, -12).Resize(, 12))
        SGlast12months_min = .Min(Cells(i, sga).Offset(, -12).Resize(, 12))
        SGlast3months_average = .RoundUp(.Average(Cells(i, sga).Offset(, -3).Resize(, 3)), 0)
        If SGMOU > 0 Then
            If .CountA(Cells(i, sga).Offset(, -7).Resize(, 7)) = 0 Then
                Remark = "agree to reduce TSL to Opt-Min (no usage in SG in last 7 months)"
                Reason = "Agree with SIMPLE"
            ElseIf SG_m_1 < SG_m_2 And SG_m_2 < SG_m_3 Then   
' captures last 3 months slow-down in demand
                If .RoundUp(.Average(Cells(i, sga).Offset(, -3).Resize(, 3)), 0) = OptMin Or _
                   .RoundDown(.Average(Cells(i, sga).Offset(, -3).Resize(, 3)), 0) = OptMin Then
                    Remark = "agree to reduce TSL to Opt-Min (consecutive descending demand in last 3 months)"
                    Reason = "Agree with SIMPLE"
                ElseIf TotalTSL = .RoundUp(.Average(Cells(i, sga).Offset(, -3).Resize(, 3)), 0) Or _
                    TotalTSL = .RoundDown(.Average(Cells(i, sga).Offset(, -3).Resize(, 3)), 0) Then
                    Remark = keep & TotalTSL & " (consecutive descending demand in last 3 months)"
                    Reason = "DemandMapping"
                ElseIf OptMin < .Average(Cells(i, sga).Offset(, -3).Resize(, 3)) Then
                    Remark = "disgree to reduce TSL to Opt-Min: propose TSL change to " & SGlast3months_average _
                    & " (consecutive demand decrease in last 3 months)"
                    Reason = "DemandMapping"
                End If
            ElseIf SGMOU = 2 And SGlast12months_max - SGlast12months_min > 4 Then
                Remark = "agree to reduce TSL to Opt-Min (there was a demand surge of " & SGlast12months_max & " )"
                Reason = "Agree with SIMPLE"
            End If
        ElseIf SGMOU = 0 Then
            Remark = "agree to reduce TSL to Opt-Min (no usage in SG in last 12 months)"
            Reason = "Agree with SIMPLE"
        End If
        End With
    ElseIf OptMin > TotalTSL And TotalTSL > 0 Then   
' to increase Safety Stock Level?
        If SGMOU = 1 Then
            If (OptMin - TotalTSL) * UnitCost < 5000 Then
                Remark = "agree to increase TSL to Opt-Min (SG MOU1 & ext.cost<$5K)"
                Reason = "Agree with SIMPLE"
            ElseIf (OptMin - TotalTSL) * UnitCost > 10000 And EventClassification Like "*Fast" Then
                Remark = "agree to increase TSL (SG MOU1, ext.cost>$10K but it's global Fast-Mover)"
                Reason = "Agree with SIMPLE"
            ElseIf (OptMin - TotalTSL) * UnitCost > 10000 Then
                Remark = "disagree to increase TSL; support thru CDC (SG MOU1, ext.cost>$10K,non-Fast Mover)"
                Reason = "DemandMapping"
            Else
                Remark = "agree to increase TSL to Opt-Min"
                Reason = "Agree with SIMPLE"
            End If
        ElseIf SGMOU > 1 Then
            If (OptMin - TotalTSL) * UnitCost > 20000 Then
                Remark = "disagree to increase TSL; propose support thru CDC (there was usage but ext.cost $20K)"
                Reason = "DemandMapping"
            Else
                Remark = "agree to increase TSL to Opt-Min (SG used at least twice in last 12 months & ext.cost<$20K)"
                Reason = "Agree with SIMPLE"
            End If
        End If
    ElseIf OptMin > TotalTSL And TotalTSL = 0 Then   
' to set new Safety Stock Level?
        If OptMin * UnitCost < 1000 Then
            Remark = "agree to set new TSL to Opt-Min (ext.cost <$1000)"
            Reason = "Agree with SIMPLE"
        Else
            Remark = "need re-confirmation on setting new TSL (ext.cost >$1000)"
            Reason = "Other"
        End If
    End If
Else
  Remark = "* need check further"
  Reason = "Other"
End If
Cells(i, remk).Value = Remark
Cells(i, align).Value = Reason

Next i
End Sub

Above loop decision is only an evaluation for ONE plant. Imagine if you have 10 plants/sites or more to evaluate?? You certainly need a loop structure programming to handle your job. Using spreadsheet filters probably will take you many hours or more than a day. Using pivot table, there is no way you can achieve this level of details and analysis to make effective decisions. No doubt about it.

 

Return To Top

Example 3.1 using Select Case statement within the For…Next loop, to find the column of std cost, then insert a column to its right, and fill in the cost category in letters base upon the values of std cost It carries on looping until the last row of data is reached.
Dim c As Integer, i As Long, lastrow As Long
lastrow = Cells(65536, 1).End(xlUp).Row
Rows("1:1").Cells.Find(What:="st*cost", After:=[A1], SearchDirection:=xlPrevious).Select
ActiveCell.Select
c = ActiveCell.Column
ActiveCell.Offset(0, 1).EntireColumn.Insert
For i = 2 To lastrow
    Select Case Cells(i, c).Value
    Case Is < 10
         Cells(i, c + 1).Value = "Cat. F"
    Case Is < 100
         Cells(i, c + 1).Value = "Cat. E"
    Case Is < 500
         Cells(i, c + 1).Value = "Cat. D"
    Case Is < 1000
         Cells(i, c + 1).Value = "Cat. C"
    Case Is < 5000
         Cells(i, c + 1).Value = "Cat. B"
    Case Else
         Cells(i, c + 1).Value = "Cat. A"
    End Select
Next





E
xample 3.2 using Select Case statement. The code checks for two column headers name, identify the columns and stored the values in two variables. It then inserts a column to input answers and uses “Min Level” – “Total TSL” as text case. It runs through all the conditions and take action accordingly.
Dim cMin As Integer, cTSL As Integer, i As Long, lastrow As Long
lastrow = Cells(65536, 1).End(xlUp).Row
Rows("1:1").Cells.Find(What:="Min*", After:=[A1], SearchDirection:=xlPrevious).Select
ActiveCell.Select
cMin = ActiveCell.Column
Rows("1:1").Cells.Find(What:="Total TSL*", After:=[A1], SearchDirection:=xlPrevious).Select
ActiveCell.Select
cTSL = ActiveCell.Column
ActiveCell.Offset(0, 1).EntireColumn.Insert
For i = 2 To lastrow
    Select Case Cells(i, cMin).Value - Cells(i, cTSL).Value
    Case Is = 0
         Cells(i, cTSL + 1).Value = "no mismatch"
    Case Is < 0
         Cells(i, cTSL + 1).Value = "reduce TSL?"
    Case Is > 0
         Cells(i, cTSL + 1).Value = "increase TSL?"
    Case Else
         Cells(i, cTSL + 1).Value = "others"
    End Select
Next


Return To Top

Example 4.1.1 a simple For… Next loop. This code will add number 99 on Cells B1,C1...to F1 and B4,C4...to G4, and so on.
Dim r As Long, c As Integer
Range("B1").Select
  For r = 0 To 2
  For c = 0 To 4
    ActiveCell.Offset(r * 3, c).Value = 99
  Next c
  Next r


 

Example 4.1.2 Fill as 1,2,3.... on alternate column, and continues with every row, using Step.
Dim i As Integer, j As Integer, k As Integer

For i = 1 To 10
For j = 1 To 10 Step 2
   k = k + 1
   Cells(i, j) = k
Next j
Next i
Example 4.1.3 Fill as 1,2,3.... starting from bottom up, on alternate column, and alternate row, using Step -2.
Dim i As Integer, j As Integer, k As Integer

k = 1
For i = 9 To 1 Step -2
For j = 10 To 1 Step -2
   Cells(i, j) = k
   k = k + 1
Next j
Next i
Example 4.1.4 Fill as 1,3,5,7,9 on alternate column and alternate row, using  Step 2.
Dim i As Integer, j As Integer

For i = 1 To 10 Step 2
For j = 1 To 10 Step 2
   Cells(i, j) = j
Next j
Next i


 

Example 4.1.5  Fill as 1,2,3....and so on, on alternate column and alternate row.
Shade GREEN on every alternate row, from column 1 to 9.

Dim i As Integer, j As Integer, k As Integer, L As Integer

For i = 1 To 10 Step 2
For j = 1 To 10
Step 2
   L = L + 1
   Cells(i, j) = L
       For k = 1 To 9 
' change columns range as you suit
          Cells(i, k).Interior.ColorIndex = 4
       Next k
Next j
Next i

Return To Top


Example 4.2 another demonstration using multiple For… Next loop. The procedure will resize 4 columns to the Right from B2, then copy the extended Range (by stepping through every 3 Rows) and paste to one cell down from the last used Cell in Column G. The code then copy values from Sheet1 cells B2,C2…E2 to column B in Sheet2, so that first value (B2) will go to B2 and C2 in B3, D2 in B4 and so on.
Dim r As Long, rDes As Long
Dim i As Long, j As Long, k As Long
With Sheets("Sheet1")
Cells(, 1).Resize(2, 5).Copy Cells(, "G")
  For r = 2 To Cells(Rows.Count, "A").End(xlUp).Row Step 4
  rDes = .Cells(Rows.Count, "G").End(xlUp).Row + 1
    Cells(r, "A").Resize(, 5).Copy Cells(rDes, "G")
  Next r
  Range("A2", Range("A2").End(xlToRight).End(xlToRight)).Copy
  Range("G2").Insert Shift:=xlDown
End With
 

 

’ below multiple For..Next loop shows you a way to transpose the output to Sheet2
Range("B6").Select
  For i = 0 To 2
    For j = 0 To 3
      ActiveCell.Offset(i * 4, j).Copy
      Sheets("Sheet2").Activate
      Range("B" & 2 + k).Select
      Selection.PasteSpecial Paste:=xlPasteValuesAndNumberFormats
      Sheets("sheet1").Activate
      k = k + 1
    Next j
  Next i

 


Example 4.3 this For…Next loop will find the value in B1 and fill in red the cells in Column A that are found to have the same value as B1.
Dim findit, r
findit = Split(Range("B1"), ",")
For r = 0 To UBound(findit)
  Columns("A:A").Select
  Selection.FormatConditions.Add Type:=xlCellValue, Operator:=xlEqual, _
    Formula1:=findit(r)
  Selection.FormatConditions(1).Interior.ColorIndex = 3
Next r


The syntax of a Split function is:
Split(expression [, delimiter [, count [, compare]]])

  •          "Expression" is a required string expression containing substrings and delimiters.

  •          "Delimiter" is an optional string identifying the delimiter character. By default, a space character (" ") is considered to be the delimiter.

  •          "Count" is an optional number of substrings to return. The default is -1, which indicates all substrings are to be returned.

  •          "Compare" is an optional numeric value signifying how the comparison should take place for evaluating substrings. A 0 indicates binary comparison; a 1 (the default) signifies textual comparison.

' this code explains splitting the string into 4 'parts' (by \ ) and join them back with / as in "C:/MyData/Week4/MySheet4.xls"
parts = Split("C:\MyData\Week4\MySheet4.xls", "\")
  For i = 0 To UBound(parts)
    'MsgBox parts(i)
  Next i
Debug.Print Join(parts, "/")


Return To Top



Example 5.1 using For Each...Next loop to format the used range in column B in dollar symbol and specific decimals format in #,##0.000
Dim finalrow As Long, i As Long, cel As Range

finalrow = Cells(65536, 1).End(xlUp).Row

i = 1

  For Each cel In Range("A2:A" & finalrow).SpecialCells(xlCellTypeVisible)

    i = i + 1

    Cells(i, 1).NumberFormat = "$#,##0.000"

  Next

MsgBox i & "cells formatted"
 


 


 

Example 5.2  The first For Each…Next loops through the sheets, and colors all formula cells to Red font. The nested For Each…Next loop then run through all the cells in a range, and convert anything that has the font type like “Cour*” to “Arial” font type.

Dim sht As Worksheet, c As Range

For Each sht In Sheets

    On Error Resume Next

    sht.Cells.SpecialCells(xlFormulas).Font.ColorIndex = 3

        For Each c In [A1:A100]

            If c.Font.Name Like "Cour*" Then

                c.Font.Name = "Arial"

            End If

        Next c
Next sht

 

 

 

Example 5.3 For Each...Next loop. This simple procedure deletes all the other sheets except for two sheets named “pivot” and “maindata” in the active workbook.

Dim ws As Worksheet

    Application.ScreenUpdating = False

    Application.DisplayAlerts = False

On Error GoTo Exits:

For Each ws In Worksheets

    If ws.Name <> "pivot" And ws.Name <> "maindata" Then ws.Delete

Next

Exits:

    Application.ScreenUpdating = True

    Application.DisplayAlerts = True

 

 

 


Example 5.4 For Each...Next loop. This code checks through all the sheets in the active workbook that are not the sheet name “main”, and then copy range(“A2:D8”) from all the sheets to sheet “main” at cell B2.

Dim osh As Worksheet

Set osh = Sheets("main")

For Each sh In Worksheets

    If sh.Name <> "main" Then

       sh.Range("A2:D8").Copy

       osh.Cells(Rows.Count, 1).End(xlUp).Offset(1, 1).Select

       ActiveSheet.Paste link:=False

    End If

Next sh


Sometimes ago I did a procedure relating to my work, extending a little from the above example 5.4. This procedure copies all the sheets from path “C:\william91128\myVendors\” (you would change the path to suit) to the active workbook where you would place the code, and continue to copy all data except for headers, sheet by sheet, and append to the active sheet “main”. The formula in main sheet calculates with new data appended. You can DOWNLOAD the zip file here.

 

Return To Top


Using Do...Loop Statements

You can use Do...Loop statements to run a block of statements an indefinite number of times. The statements are repeated either while a condition is True or until a condition becomes True.

The code below will read in the entire boot.ini file. But there is no condition in that Do Loop, and so the code will keep trying to read in lines from the file, until VB throws up runtime error 62 : Input past end of file. Using a Do Until... Loop with function EOF() will resolve this problem.

Dim textLine As String
Open "c:\boot.ini" For Input As #1
Do
   Line Input #1, textLine
   Debug.Print textLine
Loop
Close #1

 

Dim textLine As String
Open "c:\autoexec.bat" For Input As #1
Do Until EOF(1)
   Line Input #1, textLine
   Debug.Print textLine
Loop
Close #1

Return To Top

Repeating Statements While a Condition is True

There are two ways to use the While keyword to check a condition in a Do...Loop statement. You can check the condition before you enter the loop, or you can check it after the loop has run at least once.

In the following
ChkFirstWhile procedure, you check the condition before you enter the loop. If myNum is set to 9 instead of 20, the statements inside the loop will never run. In the ChkLastWhile procedure, the statements inside the loop run only once before the condition becomes False.

Sub ChkFirstWhile()
    counter = 0
    myNum = 20
    Do While myNum > 10
       myNum = myNum - 1
       counter = counter + 1
    Loop
    MsgBox "The loop made " & counter & " repetitions."
End Sub


 

Sub ChkLastWhile()

    counter = 0

    myNum = 9

    Do

        myNum = myNum - 1

        counter = counter + 1

    Loop While myNum > 10

    MsgBox "The loop made " & counter & " repetitions."

End Sub

 

 

' This simple code replaces all characters of " with blank and print them out line by line.
Dim dText As String, TextLine As String
Open "D:\CheeYoong\biblecode.txt" For Input As #1

   Do While Not EOF(1)
      Line Input #1, TextLine
      TextLine = Replace(TextLine, Chr$(34), "") 
' Chr$(34) is character "
      dText = dText & TextLine & vbCrLf
   Loop
'debug.print dText
TextBox1.Text = dText

 

Return To Top

Repeating Statements Until a Condition Becomes True

There are two ways to use the Until keyword to check a condition in a Do...Loop statement. You can check the condition before you enter the loop (as shown in the ChkFirstUntil procedure), or you can check it after the loop has run at least once (as shown in the ChkLastUntil procedure). Looping continues while the condition remains False.

Sub ChkFirstUntil()
    counter = 0
    myNum = 20
    Do Until myNum = 10
       myNum = myNum - 1
       counter = counter + 1
    Loop
    MsgBox "The loop made " & counter & " repetitions."
End Sub

 

Sub ChkLastUntil()

    counter = 0

    myNum = 1

    Do

       myNum = myNum + 1

       counter = counter + 1

    Loop Until myNum = 10

    MsgBox "The loop made " & counter & " repetitions."

End Sub

Return To Top

Exiting a Do...Loop Statement from Inside the Loop

You can exit a Do...Loop using the Exit Do statement. For example, to exit an endless loop, use the Exit Do statement in the True statement block of either an If...Then...Else statement or a Select Case statement. If the condition is False, the loop will run as usual.

In the following example, myNum is assigned a value that creates an endless loop. The If...Then...Else statement checks for this condition, and then exits, preventing endless looping.

Sub ExitExample()

    counter = 0

    myNum = 9

    Do Until myNum = 10

        myNum = myNum - 1

        counter = counter + 1

        If myNum < 10 Then Exit Do

    Loop

    MsgBox "The loop made " & counter & " repetitions."

End Sub

 


Example 6.1 This Do While…Loop executes the code as long as there is something in the column to the left of the active cell E2. Even though there is already a cell in E6 in the column that is not empty, the Average formula runs through and overwrites its content.
Do While Not IsEmpty(ActiveCell.Offset(0, -1))
   ActiveCell.FormulaR1C1 = "=IF(RC[-3]<500,""don't stock"",AVERAGE(RC[-2]:RC[-1]))"
   ActiveCell.Offset(1, 0).Select
Loop

 


Example 6.2 Do While…Loop. This macro is the same as when you try use Excel to import all the text files from a specified location, in the format that you desired, except here that I demonstrate to you that you can include it in a Do While…Loop. Change the directory to whatever is necessary.

Dim FileName As String
FileName = Dir("C:\Documents and Settings\ptan91128\SapWorkDir\*.txt")
Do While FileName <> ""
   Workbooks.OpenText _
   FileName:=FileName, _
   Origin:=xlMSDOS, _
   StartRow:=1, _
   DataType:=xlDelimited, _
   TextQualifier:=xlDoubleQuote, _
   ConsecutiveDelimiter:=True, _
   Tab:=True, _
   Semicolon:=False, _
   Comma:=False, _
   Space:=True, _
   Other:=False, _
   FieldInfo:=Array(Array(1, 1)), _
   TrailingMinusNumbers:=True
   FileName = Dir
Loop

Return To Top


Example 7.1 Do Until…Loop structure is just the opposite of Do While…Loop. Do…Until Loop runs through the statements for as long as a condition is False, stops when the condition becomes True. The example below searched down the column you had selected for the person name called “Abramovich” until it reaches a blank cell. During the search, if the match is found, it will exit the loop prematurely with Exit Do statement. The counter increases by 1 every time through the loop, and the condition following Do Until is always based on a new cell.

Sub DoUntilLoop()
Dim selectedCol As Integer, lastCol As Integer, rowCount As Integer, Match As Boolean
With Range("A1")
lastCol = Range(.Offset(0, 0), .End(xlToRight)).Columns.Count
End With

selectedCol = InputBox("select the column number from 1 to " & lastCol & " to search" _
   & "for Roman Abramovich")
rowCount = 1
Match = False
With Range("A1").Offset(0, selectedCol - 1)
' loops until a blank cell is reached.
' If Abramovich is not found in your selected column, this loop will never execute
Do Until .Offset(rowCount, 0) = vbNullString
   If .Offset(rowCount, 0) Like "*Abramovich" Then
      Match = True
      MsgBox ActiveCell.Value & vbCrLf & ActiveCell.Offset(, 1).Value & vbCrLf _
        & ActiveCell.Offset(, 2), vbInformation, "Information found"
            ' exit loop prematurely as soon as match is found
      Exit Do
   Else
      rowCount = rowCount + 1 
' without counter =1, it will be an indefinite loop
   End If
Loop
End With
   If Match = False Then
    MsgBox "no match was found"
   End If
End Sub




Return To Top


Example 8.1 Do…Loop While loop that uses a password checker that prevent unauthorized persons from running your procedure without providing the correct password in the Workbook_Open module. Of course, you would first want to lock your project procedure with a password to prevent someone from seeing the password “dobeman”.
Private Sub Workbook_Open()
Dim pwd As String
Do
    pwd = InputBox("enter password to open this workbook:", "password in characters")
    If pwd = vbNullString Then
        MsgBox "you had not entered your password"
    End If
Loop While pwd <> "dobeman"

   ' Call yourMacro
End Sub

 

Example 8.2 a simple Do…Loop While that finds all cells in a dynamic range on Sheet1 that contain the value “#N/A” and changes it to “NA”
Dim myRange As Range, c As Range, iAddress
On Error Resume Next
With Worksheets("Sheet1").Range("myRange")
    Set c = .Find("#N/A", LookIn:=xlValues)
    If Not c Is Nothing Then
        iAddress = c.Address
        Do
            c.Value = "NA"
            Set c = .FindNext(c)
        Loop While Not c Is Nothing And c.Address <> iAddress
    End If
End With

Return To Top

Example 9.1 This Do…Loop Until decision loop runs as long as there is something in the column to the left of the active cell, and it does not calculate an average if there is already some cells down in the column that are not empty.
Do
  If IsEmpty(ActiveCell) Then
     ActiveCell.FormulaR1C1 = "=IF(RC[-3]<500,""don't stock"",AVERAGE(RC[-2]:RC[-1]))"
  End If
  ActiveCell.Offset(1, 0).Select
Loop Until IsEmpty(ActiveCell.Offset(0, -1))

 

 

 

Example 10.1  A While...Wend statement behaves like the Do While...Loop statement.
The following While...Wend counts from 1 to 100

Dim number As Integer

number = 1
While number < 100
   number = number + 1
Wend

Return To Top

free counters

This site was created in Feb.2007
by William Tan