For Each method in VBA not working - vba

I am currently struggling to get the For Each method working in my VBA in Excel 2010.
I have used the methoed before and had no problem but for the life of me I cannot seem to get the new function I have written to work.
Here it is:
Sub A2_Color_Bob()
Dim sh As Worksheet
For Each sh In Sheets
Range("A2").Value = "Bob"
Next sh
End Sub

The reason why it's not working is that you haven't specified which sheet in this line
Range("A2").Value = "Bob"
Therefore, the default sheet will be used, i.e. the ActiveSheet
Hence, as others have also mentioned, it should be changed to
sh.Range("A2").Value = "Bob"

I think your issue is that's your Range is global, but you're trying to set a specific cell's value.
Did some checking and this works.
Sub A2_Color_Bob()
Dim sh As Worksheet
For Each sh In Sheets
sh.Cells(1, 1).Value = "bob"
Next sh
End Sub

change for each sh in sheets , to ...in worksheets
or can also do
dim i as long
for i=1 to worksheets.count
sheets(i).range("A2")=bob"
next i

Related

make VBA form only read one workbook when other workbooks are open

I'm new here, I've read the rules, but please inform/forgive me if I have missed anything or posted incorrectly.
Now, to my problem:
I have created my first form in Visual Basic that has allowed me to create a searchable and editable database.
Upon allowing colleagues to test the form, I quickly released that they cannot use any of their other Excel workbooks that they have open (The other workbooks are not related in any way to my workbook/form).
After some researching, I found that I can add (vbmodeless) to the button that opens the form. This then allows the team to flick between the form and use other workbooks to look at other information and then go back onto the form.
The only problem I have now, is that when they go back to the form, it reads an error in the macros, because its trying to use the macros on another workbook and not my workbook.
In short, is there any way you can use (vbmodeless), but lock the forms Macros to my specific workbook?
If anyone can solve this riddle, they will be my best friend. I'm aiming to have this ready for its presentation next week on the 6th of March.
Thank you.
Well, let's say like tigeravatar, you haven't declared a workbook :
Dim ws As Workbook
ws = ActiveWorkbook
'instead of
Sheets("Sheet1").Range("A3") = 5 'for example
'you would have
ws.Sheets("Sheet1").Range("A3") = 5
You can also work with the sheets itself, but you'll have to use parameters and search each :
Dim ws As Workbook
Dim sh, SpecificSheet1, SpecificSheet2 as Object 'To manipulate sheets
Dim Name_Sheet1, Name_Sheet2 As String
Set ws = ActiveWorkbook
Name_Sheet1= "Sheet1"
Name_Sheet2= "Sheet2"
For Each sh In Sheets
If InStr(sh.Name, Name_Sheet1) = 1 Then
Set SpecificSheet1 = sh
ElseIf InStr(sh.Name, Nom_Ref_Donnees) = 1 Then
Set SpecificSheet2 = sh
End If
Next
'Instead of :
Sheets("Sheet1").Range("A3") = 5 'for example
'You would use :
SpecificSheet1.Range("A3") = 5
According to your way of using subs, theses both solutions may need to use Public declaration of theses objects :
Option Explicit
Public ws As Workbook
Public SpecificSheet1, SpecificSheet2 as Object 'To manipulate sheets
Sub yoursub()
Dim sh, SpecificSheet1, SpecificSheet2 as Object 'To manipulate sheets
Dim Name_Sheet1, Name_Sheet2 As String
If (IsEmpty(ws)) Then
Set ws = ActiveWorkbook
Else
ws.activate
End If
Name_Sheet1= "Sheet1"
Name_Sheet2= "Sheet2"
For Each sh In Sheets
If InStr(sh.Name, Name_Sheet1) = 1 Then
Set SpecificSheet1 = sh
ElseIf InStr(sh.Name, Nom_Ref_Donnees) = 1 Then
Set SpecificSheet2 = sh
End If
Next
End Sub

VBA Hide all sheets that aren't being used in workbook

I have many sheets in a workbook. I have a main sheet/"form" called "JE" and on that sheet there are buttons and macros that lead to other sheets in the workbook. But, the intention is for other users, not myself, to use the workbook. So, I would only like the sheet that is being used to be visible at any given time. At no time do I want more than 1 sheet to be visible by the user. The user can navigate the workbook mainly thru clicking buttons and certain cells in select sheets that will allow them to navigate throughout the entire workbook. I have tried this by adding code into 'ThisWorkbook' module but it doesn't seem to working as I'd like. When I navigate to one sheet and back to another, some sheets remain visible when I'd like them to be hidden so I'm unsure of what other modifications I can make to code below to get my desired result. If anyone can offer up any modifications or changes I can make to accomplish this, I'd really appreciate it.
UPDATE:
I have added this code to my 'ThisWorkbook' Object:
Option Explicit
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Dim MySh As Worksheet
For Each MySh In ThisWorkbook.Worksheets
If MySh.Name <> Sh.Name Then MySh.Visible = 0
Next MySh
End Sub
but, when I go to double-click values that usually populate cells in my main sheet ("JE") I get a run-time 1004 error. The values still populate the main sheet but it no longer navigates back to the main sheet as I'd like.
If anyone knows of a solution or a mod I can make, I'd really appreciate it.
The code is nice. Simply put it in the Workbook part of the VBA project:
Option Explicit
Private Sub Workbook_Open()
Dim MySh As Worksheet
For Each MySh In ThisWorkbook.Worksheets
If MySh.Name = ActiveSheet.Name Then MySh.Visible = xlSheetHidden
Next MySh
End Sub
The ThisWorkbook part is here:
In general, I use always something similar, when I am starting an Excel application. I define two Arrays with Visible and Invisible Worksheets and I iterate over them, making them either visible or not visible. Like this:
Option Explicit
Public Sub HideNeeded()
Dim varSheet As Variant
Dim arrVisibleSheets As Variant
Dim arrHiddenSheets As Variant
arrVisibleSheets = Array(Sheet1)
arrHiddenSheets = Array(Sheet2, Sheet3)
For Each varSheet In arrVisibleSheets
varSheet.Visible = xlSheetVisible
Next varSheet
For Each varSheet In arrHiddenSheets
varSheet.Visible = xlSheetVeryHidden
Next varSheet
End Sub
xlSheetVeryHidden makes it possible to unhide it only from the VB Editor. Otherwise you need xlSheetHidden.
It should be Workbook_SheetActivate:
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Dim MySh As Worksheet
For Each MySh In ThisWorkbook.Worksheets
If MySh.Name <> Sh.Name Then MySh.Visible = 0 'zero - false, 1 - true, 2 - very hidden
Next MySh
End Sub
Sub HideInactive()
Set theActiveSheet = ActiveSheet
For Each Sheet In ThisWorkbook.Worksheets
If Sheet.Index <> theActiveSheet.Index Then Sheet.Visible = False
Next
End Sub
I 've test the code. Thank you for reading.

Looping through (Name) of Sheets

My question is actually quite simple but I can't find a solution.
I have a lot of sheets with different names that can be modified by the user. I've given to each of those sheets a background name, so for my first two sheets, their names in my VBA project look like this:
The fact is, I want to do a macro to loop through all those particular Sheets (I have 14 of them), and I don't want to Loop through the other ones that I use for different things, like this one:
It is easy to loop through my Sheets using the names that can be modified by the user ("General" et "Heritage" in my example). Nevertheless, I want the user to be able to modify this name whenever he wants, and if he does that, my macros will not recognize the new name of the sheet. It is really important for me that the user doesn't have to push a button or use a different textbox to rename his sheet, I don't want to avoid the problem this way.
What I want is to be able to loop through the background name (S1 and S2 in my example), doing something like that (I know that the following code isn't good, but it is just to give you an example):
Sub Example1()
Dim wksht As Worksheet
For i = 1 To 14
Set wksht = "S" & i
wksht.Cells(1, 1).Value = 1
Next i
End Sub
I know that the following code works for 1 sheet:
Sub Example2()
Dim wksht As Worksheet
Set wksht = S1
wksht.Cells(1, 1).Value = 1
Next i
End Sub
The problem is S1 in my previous code isn't a string, so I can't loop using "S" & i. Is there a solution to my problem ?
You are using the sheet code name, so can do something like this. By the way, this will match S followed by a single digit which may or may not be sufficient for your needs. (By the way, it's 'through', not 'threw'.)
Sub Example1()
Dim wksht As Worksheet
For Each wksht In Worksheets
If wksht.CodeName Like "S#" Then
'do something
End If
Next wksht
End Sub
Based on my research, there does not appear a way to reference sheets based on their codename string, however, you can get the codename as a string from a sheet.
Sub test()
Dim wb As Workbook
Dim ws As Worksheet
Dim ws_temp As Worksheet
Dim i As Long
Set wb = ThisWorkbook
For i = 1 To 4
For Each ws_temp In wb.Sheets
If ws_temp.CodeName = "S" & i Then
Set ws = ws_temp
End If
Next
Debug.Print ws.Name & " " & ws.CodeName
Next
End Sub
This code will march through all of the S# sheets in order, and allow you to work with each one as ws.

How to generate sheet from template

In VBA, i would like create a new sheet from a template after my first sheet.
Example:
In MyFirstSheet i have cell B16="House" and a button "NewSheetFromTemplate". When user click on the button a new sheet generated after my MyFirstSheet and contains same information than TEMPLATE sheet with title House.
My VBA code:
Sub NewSheetFromTemplate()
Dim sht As Worksheet
Set sht = Sheets("TEMPLATE").Copy After:=sheets("MyFirstSheet")
sht.Name = Range("B16").Value
End Sub
Excel say me "Syntax error" but why ?
I don't think is it really necessary to create Worksheet object just to rename it. Try simply like this:
Sub NewSheetFromTemplate()
Sheets("TEMPLATE").Copy After:=Sheets("MyFirstSheet")
ActiveSheet.Name = Sheets("MyFirstSheet").Range("B16").Value
End Sub
The following line of code does not return an object, one is created but this is not returned to VBA:
Sheets("TEMPLATE").Copy After:=sheets("MyFirstSheet")
This means that you cannot set this line of code to an object. Instead, try something like either of the following two options:
Using Index
Because you've copied the new worksheet after Sheets("MyFirstSheet") you can use the worksheet index of Sheets("MyFirstSheet") and then add 1 to get the sheet you've just created.
Sub NewSheetFromTemplate()
Dim sht As Worksheet
Sheets("TEMPLATE").Copy After:=sheets("MyFirstSheet")
Set sht = Sheets(Sheets("MyFirstSheet").Index+1)
sht.Name = Range("B16").Value
End Sub
Using "Name (2)"
Alternatively, the default name for a copied sheet is the original name with " (2)" tagged onto the end. This is still a useful way of identifying the new worksheet however it could become an issue if the original worksheet has a particularly long name.
Sub NewSheetFromTemplate()
Dim sht As Worksheet
Sheets("TEMPLATE").Copy After:=sheets("MyFirstSheet")
Set sht = Sheets("TEMPLATE (2)")
sht.Name = Range("B16").Value
End Sub
You can't create an instance of a Worksheet via Copy method. Since you know where are you placing the new sheet, you are able to find it after copied, and rename it. You are very close:
Sheets("TEMPLATE").Copy After:=Sheets("MyFirstSheet")
Sheets(Sheets("MyFirstSheet").Index + 1).Name = Sheets("TEMPLATE").Range("B16").Value
Make sure that you have a value in B16 range.
Hope this helps,
Cheers.

Using cell value as range VBA

I am trying to have a range (call it "A5:L10") be picked up from a cell. In other words, my code looks something similar to that below:
Dim summ_rng1 As String
summ_rng1 = Sheet11.Cells(17, 3).Value
Workbooks(wb).Sheets(summ).Range(summ_rng1).......
Where summ_rng1 = "A5:L10"
I have done this same thing for the workbooks and sheets in my code and it works fine, but when I try to replace the range reference with the variable summ_rng1 it does not work.
Any idea on how to get the code to run with the range value as a variable, like that above? Thanks for the help!
Your code is working for me. I think it is related to your wb object, which may contain the workbook itself, rather than the name of the workbook. Try this :
Sub testSub()
Dim myRange As String
Dim wb As Workbook
Set wb = ThisWorkbook
myRange = wb.Sheets(1).Cells(1, 1)
wb.Sheets(1).Range(myRange).Select
End Sub