Loop through worksheets, exclude some and look-up cell value - excel

I have an Excel workbook with several worksheets.
I would like the macro to look at the value of cell "A1" of each worksheet.
If the cell value is less than 8, A1 must be adjusted to 8.
If the cell value is greater than 8, nothing needs to be adjusted.
I have two macros:
Sub LoopCertain() 'Excel VBA to exclude sheets(1-3)
Dim sh As Worksheet
For Each sh In Sheets
Select Case sh.Name
Case Is = "Blad1", "Blad2", "Blad3"
'No Code here if excluded
Case Else
Call X2
End Select
Next sh
End Sub
and
Sub X2()
'declare a variable
Dim ws As Worksheet
Set ws = ActiveSheet
'calculate if a cell is less than a specific value
If ws.Range("A1") < 8 Then
ws.Range("A1") = 8
Else
End If
End Sub
The problem is that only the active worksheet is done and the rest of the worksheets are not looked at. The macro also does not check whether the worksheet should not be included.

If you want using two subs, please try the next way. Your code only use the active sheet in the second sub:
Sub LoopCertain() 'Excel VBA to exclude sheets(1-3)
Dim sh As Worksheet
For Each sh In Sheets
Select Case sh.name
Case "Blad1", "Blad2", "Blad3"
'No Code here if excluded
Case Else
Call X2(sh)
End Select
Next sh
End Sub
Sub X2(ws As Worksheet)
'calculate if a cell is less than a specific value
If ws.Range("A1").value < 8 Then ws.Range("A1") = 8
End Sub
But for such a simple processing, no need of the second since everything can be done in the first one:
Sub LoopCertain() 'Excel VBA to exclude sheets(1-3)
Dim sh As Worksheet
For Each sh In Sheets
Select Case sh.name
Case "Blad1", "Blad2", "Blad3"
'No Code here if excluded
Case Else
If sh.Range("A1").value < 8 Then sh.Range("A1") = 8
End Select
Next sh
End Sub

The cleanest way to do this with the code in its current form would be to pass the sheet object to the other sub:
Sub LoopCertain() 'Excel VBA to exclude sheets(1-3)
Dim sh As Worksheet
For Each sh In Sheets
Select Case sh.Name
Case Is = "Blad1", "Blad2", "Blad3"
'No Code here if excluded
Case Else
Call X2(sh)
End Select
Next sh
End Sub
and then
Sub X2(ByVal sh As Worksheet)
'calculate if a cell is less than a specific value
If sh.Range("A1") < 8 Then
sh.Range("A1") = 8
End If
End Sub
I've assumed you have a reason in the real-world use for having separate sub-routines, but once you understand this concept of passing the objects around then I would suggest just doing this in a single routine.

Related

hide sheet that not in array

I made array with the name of sheets that I want to select.
all the other sheets I want to hide.
its need to by dynamic.
list say that my array is
Sheets(Array("Sheets1", "sheet2")).Select
and I have 4 sheets
how I can hide all the others sheet that not in the array ?
Hide Sheets
The Sheets collection includes worksheets, charts, and whatnot.
Here is a similar solution for worksheets.
Option Explicit
Sub HideSheets()
' Do NOT hide:
Dim Exceptions As Variant: Exceptions = Array("Sheet1", "Sheet2")
Dim sh As Object
For Each sh In ThisWorkbook.Sheets
If IsError(Application.Match(sh.Name, Exceptions, 0)) Then
On Error Resume Next ' when trying to hide last visible sheet
If Not sh.Visible = xlSheetHidden Then
sh.Visible = xlSheetHidden
End If
On Error GoTo 0
End If
Next sh
End Sub

Skip some worksheets in loop function in Excel VBA

I want to have a button replace the info on MOST sheets with the info from a master sheet when a button is clicked. However, I want it to skip some sheets.
I have the below code that works, but there are 2 sheets I want it to skip when running. How can I specify that is skip the sheets named "Dates" and "Monthly"
Sub Button4_Click()
Dim wsVar As Worksheet
For Each wsVar In ThisWorkbook.Sheets
With wsVar
.Range("B9:M30").Value = Worksheets("BASE").Range("B9:M30").Value
End With
Next wsVar
End Sub
You can use an IF statement to check the name of the worksheet and then act accordingly.
For Each wsVar In ThisWorkbook.Sheets
If wsVar.Name = "foo" Or wsVar.Name = "bar" Then
' do nothing
Else
With wsVar
.Range("B9:M30").Value = Worksheets("BASE").Range("B9:M30").Value
End With
End If
Next wsVar
This code will exclude all sheets listed in the Exclude array. Note that sheets name comparisons are carried out case-insensitive and leading or trailing blanks are deemed unintentional and removed.
Sub Button4_Click()
Dim wsVar As Worksheet
Dim Exclude() As String
Dim i As Integer
Exclude = Split("Dates,Monthly", ",")
For Each wsVar In ThisWorkbook.Worksheets
With wsVar
For i = UBound(Exclude) To 0 Step -1
If StrComp(wsVar.Name, Trim(Exclude(i))) = 0 Then Exit For
Next i
If i >= 0 Then .Range("B9:M30").Value = Worksheets("BASE").Range("B9:M30").Value
End With
Next wsVar
End Sub
With a small change, you might convert this same function to process only listed sheets. To identify sheets for action positively, rather than negatively, is the safe way, generally speaking. But if you decide to do that, please also do rename the array :-)

Name of source worksheet entered by user, copy data from source worksheet, paste to target worksheet

Dear stackoverflow experts,
I am new to vba and would like a simple macro for some copy-and-paste tasks. I have an xlsm file, containing multiple worksheets, name as follows
CALCULATIONS
LEMON
ORANGE
BANANA
I only know a very simple and popular macro for laymen.
Sub copyandpasterawdata()
Workbooks("trymacro.xlsm").Worksheets("ORANGE").Range("A1:H2000").Copy
Workbooks("trymacro.xlsm").Worksheets("CALCULATIONS").Range("A1").PasteSpecial Paste:=xlPasteValues
End Sub
I would like to make the source worksheet name "dynamic". That is, when I input "ORANGE" to cell I1 on worksheet CALCULATIONS and run the macro, data from worksheet ORANGE were copy-n-pasted, while when I input "LEMON" to cell I1 on worksheet CALCULATIONS and run the macro, data from worksheet LEMON will instead be copy-n-pasted.
Thank you.
John
Because you only want to copy values, you can use the Range.value2= RangeCopy.value2
Note that I1 is located in the paste area of your data,Let try:
Option Compare Text
Sub copyandpasterawdata()
If ActiveSheet.Name <> "CALCULATIONS" Or Not (ThisWorkbook.Name Like "*trymacro*") Then Exit Sub
''check if sheetname
'Dim sheetsname As Variant
' sheetsname = Array("LEMON", "ORANGE", "BANANA")
'If IsEmpty(Filter(sheetsname, [I1].Value2, True, vbTextCompare)) Then Exit Sub
'---------------------------------------
Dim ws As Worksheet
Dim isSheetname As Boolean
For Each ws In Worksheets
If [I1].Value2 Like ws.Name Then
isSheetname = True
Exit For
End If
Next ws
If Not (isSheetname) Then Exit Sub
'assign value
Range("A1:H2000").Value = Worksheets([I1].Value2).Range("A1:H2000").Value
End Sub
Here is shorter code:
Sub copyandpasterawdata()
If ActiveSheet.Name <> "CALCULATIONS" Or Not (ThisWorkbook.Name Like "*trymacro*") Then Exit Sub
On Error Resume Next
' assign value
Range("A1:H2000").Value = Worksheets([I1].Value2).Range("A1:H2000").Value
End Sub

VBA code to call different macro depending on part of Worksheet name

I am working on a macro that will cycle through all of the sheets in the active workbook and will then clear a certain part of a particular worksheet, based on whether one of the relevant keywords is contained in the worksheet name. In each case the worksheet name will be different, but any I want to clear will contain one of the key words below.
I have set up a separate macro to clear the range of cells in each case. If the Worksheet name does not contain any of the keywords, I want the macro to move onto the next worksheet.
My ultimate aim is to be able to apply this to numerous different workbooks, as the project I am working on is split by region, with a separate Excel file per region.
The code I have been trying is below. There are no errors appearing when I run the code, the code does not seem to run either, in fact nothing at all happens!
Any guidance or advice would be greatly appreciated.
Sub Loop_Customer_Sheets()
Dim ws As Integer
Dim i As Integer
ws = ActiveWorkbook.Worksheets.Count
For i = 1 To ws
If ActiveSheet.Name Like "*ABC*" Then
Call ABCInfoClear
ElseIf ActiveSheet.Name Like "*DEF*" Then
Call DEFInfoClear
ElseIf ActiveSheet.Name Like "*GHI*" Then
Call GHIInfoClear
Else:
End If
Next i
End Sub
"Nothing at all happens" - fixing the issue with your code:
Your issue is that you are looping through the number of sheets, but you are only checking the ActiveSheet, which never changes! Replace your code with
ws = ActiveWorkbook.Worksheets.Count
For i = 1 To ws
With ActiveWorkbook.WorkSheets(i)
If .Name Like "*ABC*" Then
ABCInfoClear
ElseIf .Name Like "*DEF*" Then
DEFInfoClear
ElseIf ActiveSheet.Name Like "*GHI*" Then
GHIInfoClear
End If
End With
Next i
Note: you don't need the Call keyword, you can just call subs as presented above.
Alternative solutions
A better option than having numerous macros might be to create a generic sub like
Sub ClearRangeInSheet(rangeAddress As String, sh As WorkSheet)
Dim myRange As Range
Set myRange = sh.Range(rangeAddress)
myRange.ClearContents
' Any other cell clearing code e.g. for formatting here
End Sub
Then call in the loop
Dim wsCount as Long
wsCount = ActiveWorkbook.WorkSheets.Count
For i = 1 to wsCount
With ActiveWorkbook
If .WorkSheets(i).Name Like "*ABC*" Then
' Always pass ".WorkSheets(i)", but change the range address as needed
ClearRangeInSheet("A1:A20", .WorkSheets(i))
ElseIf ' Other worksheet name conditions ...
End If
End With
Next I
As suggested in the comments, you could ditch indexing the sheets, and just loop through the sheet objects themselves:
Dim wksht as WorkSheet
For Each wksht In ActiveWorkbook.WorkSheets
If wksht.Name Like "*ABC*" Then
' Always pass wksht but change the range address as needed
ClearRangeInSheet("A1:A20", wksht)
ElseIf ' Other worksheet name conditions ...
End If
Next wksht

Obtain displayed order of Excel worksheets

I'd like to find the position of a worksheet as it is displayed in a workbook.
For example, assume I have a workbook starting with Sheet1, Sheet2 and Sheet3 in that order. Then a user drags Sheet2 to left, before Sheet1.
I want Sheet2 to return 1, Sheet1 to return 2 (and Sheet3 still to return 3).
I can't find a way to determine this in VBA.
This should do it:
Worksheets("Sheet1").Index
https://msdn.microsoft.com/en-us/library/office/ff836415.aspx
You can just iterate the Worksheets collection of the Workbook object. You can test yourself by running the following code, switch the order around in the UI, then run it again:
Option Explicit
Sub IterateSheetsByOrder()
Dim intCounter As Integer
Dim wb As Workbook
Set wb = ThisWorkbook
For intCounter = 1 To wb.Worksheets.Count
Debug.Print wb.Worksheets(intCounter).Name
Next intCounter
End Sub
To loop through all worksheets in a workbook use For Each WS in ThisWorkbook.Worksheets where WS is a worksheet object. Hence to obtain order of Excel worksheets as shown, we may also use the following code:
Sub LoopThroughWorksheets()
Dim WS As Worksheet
For Each WS In ThisWorkbook.Worksheets
Debug.Print WS.Name
Next
End Sub
To obtain an output like Worksheets("Sheet1").Index then you may use this code
Sub IndexWorksheet()
Dim WS As Worksheet, n As Long
For Each WS In ThisWorkbook.Worksheets
n = n + 1
If WS.Name = "Sheet1" Then Debug.Print n
Next
End Sub
You can use the Sheets object. In your example, reading Sheets(2).Name should return Sheet1.
Right answer provided by Anastasiya-Romanova, but missing some important details.
There are two methods of doing this. First, with a For Each loop:
Sub ListSheetNames()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
Debug.Print ws.Name
Next ws
End Sub
Second, with a basic For loop:
Sub ListSheetNames
Dim i As Long
For i = 1 to ThisWorkbook.Worksheets.Count
Debug.Print ThisWorkbook.Worksheets(i).Name
Next i
End Sub
You will find the second method will always output the names in the sheet index order, which is generally the order the sheets were created in unless you change the index. Simply rearranging the sheets from the workbook window won't change the index.
Therefore, the first method is the correct way to do this. It will always follow the tab order as you see on your screen.
Below code works even if sheet is renamed or its sequence is changed.
Sub Display_Sheet_Tab_Number()
Dim WorksheetName As String
Dim n As Integer
WorksheetName = Sheet1.Name
MsgBox Worksheetname
n = Sheets(WorksheetName).Index 'n is index number of the sheet
MsgBox "Index No. = " & n
End Sub

Resources