I am trying to unhide a group of worksheets if they meet a certain condition. This uses a user form, triggered by a command button, with selection options and another command button. The expected behavior is that once the selection has been made and the button has been pressed, all worksheets meeting the criteria will be unhidden. The Target word is present at different locations along the first row and all cells before it are empty on that row. Ideally, the process will scan each cell in the first row of each worksheet in the workbook until it comes across the Target, unhide the worksheet, then move on to the next worksheet to start the process over again until all worksheets with the workbook have been checked.
Upon activation of the command button on the user form I have the following:
Private Sub ContinueCommand_Click()
Dim Valid As Boolean, wks As Worksheet, c As Integer, actCol As Long
actCol = ActiveSheet.Range("A1").End(xlToRight).Column
For Each wks In ActiveWorkbook.Worksheets
For c = 1 To actCol
If ActiveCell.Value = "Target" Then
wks.Visible = xlSheetVisible
Exit For
End If
Next c
Next wks
Valid = True
If Valid = True Then
Unload Me
End If
End Sub
I've borrowed from several sources, including here for using ActiveCell, determining if a value exists, unhidding worksheets, Finding values within a range, and searching for a string. Any help would be greatly appreciated.
As I said in my comments there are some issues with the way you've chosen to implement this.
Your For c = 1 To actCol loop is not needed. This can be easily seen because c is not really used anywhere in the loop.
Let's assume your Target value is in wks.Range("A100") (the 1st row and 100th column).
Your code would then perform the exact same operation 100 times and would come up with the exact same result. That's what leads you to use Exit For, which is a bad practice.
If I understood your initial post correctly, if Target exists in a particular worksheet, then all cells before Target are empty.
If that's the case, the Target will either be in wks.Range("A1") or in wks.Range("A1").End(xlToRight). If it's not in either of these two cells then it doesn't exist at all in this particular worksheet, which would mean that the 1st row is completely empty. You don't need to check any more cells apart from these two.
Your code does not check whether Target is in wks.Range("A1").
Also your use of Application.Match, makes me believe that you have probably been misled by the common misconception that wks.Range("A1").End(xlToRight) is a range of cells starting from A1 and extending all the way to the last non-empty cell in the 1st row.
The truth is that wks.Range("A1").End(xlToRight) is a single cell rather than a range of cells. Selecting A1 and then pressing CTRL+right arrow, will show you exactly which cell it is.
I might be missing something, but according to your description in the initial post, I would do something like the following:
Dim sht As Worksheet
For Each sht In ThisWorkbook.Worksheets
If sht.Range("A1").Value = "Target" Or sht.Range("A1").End(xlToRight).Value = "Target" Then
sht.Visible = xlSheetVisible
Else
MsgBox "target was not found in " & sht.Name
End If
Next sht
I want to thank BruceWayne, Scott Craner, Stavros Jon, Darell H whom all helped me get closer to this answer. The final result looked like this:
Private Sub ContinueCommand_Click()
Dim wks As Worksheet
For Each wks In ActiveWorkbook.Worksheets
If Not IsError(Application.Match("Target", wks.Range("A1").End(xlToRight), 0)) Then
wks.Visible = xlSheetVisible
End If
Next wks
Unload Me
End Sub
If anyone in the future has issues getting this to work, let me know and I will post a more complete version.
Related
This code is supposed to check if conditions in two certain columns are met and if they are it supposed to take a value from another sheet and paste it into the end of the row of the checked row to the source sheet. For testing purpose, I try to at least keep it at a specific range now. I think I know where I'm wrong, the cell. Value most likely and that the range is probably not working as I have imagined it in my mind. Also, it is probably not even looping through the columns. I have like 30 different cell possibilities to copy from for different conditions and I suppose I can adjust them each depending on the conditions, but need to make this first attempt to work, then it will be pancake day, or not..
Sub Update()
Dim Column As Range
Sheets("Q485").Select
Set Column = Range.Select("AV:AW")
If Column("AW") Is cell.Value("P") And Column("AV") Is cell.Value("V") Then
Sheets("Support").Select
Range("C9").Select
Selection.Copy
Sheets("Q485").Select
Range("AY6358").Select
Selection.Paste
' Else
' Other conditions will be written below
end if
End Sub
Testing, testing, testing, but would like some suggestions from experts
Sub MyMacroc ()
Dim rng as range
set rng = sheets("Source").range("A2:A7")
For Each cel In rng.Cells
with cel
'condition -1 '
if .offset(0,1)="P" and .Offset(0,2)="V" then
.offset(0,3) = Sheets("Extract").range("B2")
ElseIF
'your second conition
end if
end with
next
End sub
I'm trying to create a repeated copy and paste of a table I have in one of my worksheets and assign it to buttons in my budget worksheet.
For example whenever you click on the contract button, it will install the new table. Click it again, it will leave a line break and insert the new table. Same thing with the variation button.
Budget worksheet
Table sample
My attempt in a related copied sample in one of the questions asked here.
I understand to copy and paste I've been told to use this code
Sub CopyPasteToAnotherSheet()
Worksheets("Dataset").Range("B2:F9").Copy Worksheets("CopyPaste").Range("B2")
End Sub
It works, but I can only copy it once. I don't know how to copy it numerous times each time I run the macro.
Welcome to stack!
So I think I understand the want, it's usually good to have a go and show us the code you have but as its the first time here's a start of a code that might do that:
Sub variations()
Dim rng As Range
Set rng = ActiveWorkbook.Sheets("Variations").Range("A1:B5")
Run copyAcross(rng)
End Sub
Sub contracts()
Dim rng As Range
Set rng = Worksheets("Contract").Range("A1:B2")
Run copyAcross(rng)
End Sub
Function copyAcross(rng As Range)
Dim ws As Worksheet
Set ws = ActiveWorkbook.Sheets("Budget")
targetRow = ws.Range("A" & Rows.Count).End(xlUp).Row + 2
ws.Cells(targetRow, "A").Resize(rng.Rows.Count, rng.Columns.Count).Value = rng.Value
End Function
this gives two subs that the buttons can be pointed to. In each sub you can define the range you want and the function will copy it across.
Note: for this to work column A in the Budget file would need at least some value somewhere in it, the first copy would then be put two rows below that
What I want to do is to replace all cell values in the multiple worksheets except one.
So For example, there are worksheets sheet1, sheet2, sheet3, and I want to replace all the values "M9" into "M8", but leave M9 in Sheet1 remains unchanged.
This is my code:
`For Each Worksheet in WorkSheets
If Worksheet <> ThisWorkbook.Worksheets("Sheet1") Then
Worksheet.Cells.Replace .....
End if
Next`
For For-Next, Just ignore the details as it is related to my contents. I thought this logic would have been right, but vba keep on coming up with error.
Do you know why? And are there any right way to replace the values excluding Sheet1?
Thanks for your help
If you want clearing all cells content, as I suppose, please use the next way. It also shows the way of replacing:
Sub RemoveCellsValue()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
If ws.Name <> "Sheet1" Then
ws.cells.ClearContents
'or
'ws.Cells.Replace "Oldstring","NewString" 'if you need replacing
End If
Next
End Sub
If replacing, the function needs some more parameters. Especially to state if you need to replace if the whole string is found, or only part of it.
I have an excel workbook that contains multiple sheets. In this workbook sheets occasionally are removed, renamed, or added. This workbook features a sheet (Sheet1) that is supposed to be used as a command center for printing copies of the other sheets in the workbook. Unfortunately, this printing command center does not work as intended.
The command center has only two columns. In column A is a list with the names of the other Sheets. In column B the user can specify how many copies to print of the respective sheet in column A.
This is the current code:
Sub PrintSheets()
Dim mysheets As Range
For Each mySheets In Sheet1.Range("A2:A100")
If mySheets.Offset(0, 1).Value <> "" Then Sheets(mySheets.Value).PrintOut Copies:=mySheets.Offset(0, 1).Value
Next mySheets
End Sub
The first two sheets are printed as intended and then I get a "Run-time error '9': Subscript out of range"
1) How can I fix the error?
2) Can the list with the sheet names be generated automatically and sorted by their position (i.e., left to right in the sheet tab -> top to bottom in the column)?
If you rename, add and remove sheets, you will have to update your list before printing. This sub will clear Range("A2:A100") and it will insert all sheets names in your first sheet. Make sure your "command center" sheet is the first one (or change the index reference to the name of that special sheet).
Sub LIST_SHEETS()
Application.ScreenUpdating = False
Dim ws As Worksheet
Dim i As Byte
ThisWorkbook.Sheets(1).Range("A2:A100").Clear
i = 2
For Each ws In ThisWorkbook.Sheets
ThisWorkbook.Sheets(1).Range("A" & i).Value = ws.Name
i = i + 1
Next ws
Application.ScreenUpdating = True
End Sub
I'm afraid you will have to figure out where to put the code. I don't know your needs, so maybe after renaming/adding/deleting all sheets, or maybe when Workbook opens or something like that. Try it!.
It appears that a name in the list of sheets, does not exactly match the actual name. You can use either of the two options below, to loop through each sheet
For Each sht in ThisWorkbook.Sheets
'Do Something
Next
Or
Dim sht as Worksheet
For i= 0 to ThisWorkbook.Sheets.Count
Set sht=ThisWorkbook.Sheets(i)
'Do something
Next
The second option is not reliable when the sheets are deleted (their integer index may not be sequential then) so I would prefer the first option.
I'll start by making my objective clear, and then explaining it fully.
My goal is to check for non-blank values in a range, but only in the hidden cells of that range, and then use conditional formatting in a different cell, depending on whether the cells in the range are empty or not.
I have a named range called Location_Address_RangeCheck that covers the cells directly to the right of the location numbers, like this (location numbers are not part of the range).
When the Number of Locations is changed, the rows that go beyond that number (up to 25) are automatically hidden on worksheet_change to reduce clutter and reduce scrolling to see the stuff below it. That code works fine, so I'm not posting it here so as to not confuse anyone with what I'm trying to accomplish.
I want to provide a safeguard to ensure that there aren't values in the hidden rows that could affect outputs (i.e., if someone selects "3" for Number of Locations, but there is data in cells that might be on the row of the 8th location).
My goal is to check for non-blank values in the range, but only in the hidden cells, and then use conditional formatting in the cell next to the number of locations chosen, depending on whether the cells in the range are empty or not.
So if there is data in the hidden cells, then it would cause the sheet to look like this
.
I've tried so many different things so far, but I'm not making any progress. I've scoured the internet trying to find a solution, but everything I've found is about finding things in visible cells, which is the opposite of what I'm trying to achieve.
Here is the code I have written so far, which I know does not achieve my objective:
Sub testhiddencells()
Dim myRange As Range
Set myRange = Range("Location_Address_RangeCheck")
NumRows = Application.WorksheetFunction.CountA(myRange)
If Range("Location_Address_RangeCheck").Hidden = True Then
If Application.WorksheetFunction.CountA(Range("Location_Address_RangeCheck")) <> 0 Then
MsgBox "There's something there"
End If
End If
End Sub
Here is a minimal example to check with a cell is both hidden and is non-empty:
Option Explicit
Sub Test()
Dim ws As Worksheet
Dim rngToCheck As Range
'test range - all cells populated with 'a' and 3 are hidden
Set ws = ThisWorkbook.Worksheets("Sheet1")
Set rngToCheck = ws.Range("A1:A7")
If TestForNonBlankCellsInHiddenRange(rngToCheck) Then
'do you conditional format stuff here
End If
End Sub
Function TestForNonBlankCellsInHiddenRange(rngToCheck As Range) As Boolean
Dim rngCell As Range
Dim blnCheck As Boolean
'assume that hidden cells are blank
blnCheck = False
'iterate range
For Each rngCell In rngToCheck
If rngCell.EntireRow.Hidden And Not IsEmpty(rngCell.Value) Then
'found a hidden and non-empty cell
blnCheck = True
'debug address of this cell
Debug.Print rngCell.Address
End If
Next rngCell
'return check
TestForNonBlankCellsInHiddenRange = blnCheck
End Function
Looking at the code you used already, you should be able to adapt this to the particular use case of your worksheet.