Allow me to explain the scenario first...
We have a reporting spreadsheet that is capable of updating monthly data for several different measures.
Over time, more and more macros have been added and now total over 20.
To make work a little easier I've added yet another macro, which brings up a user form that
Calls each of the other macros one by one and shows a progress bar to indicate how many tasks (macros) have been completed.
The first 8 macros called upon prompt with an input box for which month is being updated - this will always be the same month across all 8.
SO, what I want to do is add a global input box as the first thing the userform does, then for this input to be referenced in the other macros (having removed their individual prompts).
To be perfectly honest I have absolutely no idea how to do this but have tried the following (all together).
In Workbook
Public Monthglobal As Variant
At start of userform code
Function GetMonth()
Monthglobal = InputBox("Please enter the 3 letter abbreviation for the Month which your are updating (e.g. Jan, Feb...)", "Month")
If strName = vbNullString Then Exit Function
End Function
at the start of the userform Sub which calls the macros one by one
GetMonth
Within each of the 8 macros (contained in Module 1)
'Searches for correct column for month and pastes data
Selection.Find(What:=Monthglobal, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Offset(1, 0).Activate
ActiveCell.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
'Searches for correct column for month and pastes data
Result
Run-time error '91':
Object Variable or With block variable not set
The error is returned with the search (for Variable) section highlighted:
Selection.Find(What:=Monthglobal, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
I hope thats enough to make sense of it, if anyone needs to see more of the code for the individual macros please gimme a shout but I thought the error message clearly indicates WHERE the issue is...just not WHAT to someone of my lacking experience!
Thanks in advance,
I would do something like this:
Public Monthglobal As String
Function GetMonth()
Monthglobal = InputBox("Please enter the 3 letter abbreviation for the Month which your are updating (e.g. Jan, Feb...)", "Month")
End Function
The search bit - it's better to define what range to search through programatically, rather than using 'Selection'. Will the 3 letter month be the entire cell contents, or just part of it?
Dim rngFind as Range, rngFound as Range
Set rngFind = Range("A:A") ' Set this to whatever 'Selection' is currently
'Now set the rngFound variable to be the eventual 'ActiveCell' from your macro above (found cell, offset(1,0))
Set rngFound = rngFind.Find(What:=Monthglobal, After:=ActiveCell, LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext,MatchCase:=False).Offset(1, 0)
'Now paste without activating anything:
rngFind.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Related
I want to write the following Context using VBA.
When a specific word is selected in sheet 1, I want to find a specific word in sheet 2 and move it to that cell.
Selection.Copy
Sheets("Sheet2").Select
Cell.Find(What:=Apple, After:=ActiveCell, LookIn:=xlFormulas2, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, MatchByte:=False, SearchFormat:=False).Activate
End Sub
I want to put the word(Clipboard Paste?) to be copied instead of Apple, how can I do in this case ?
Don't use the Clipboard. The idea of the Clipboard is to exchange data between Applications. Just write the content of the selected cell into an intermediate variable and use that as search term.
And never access the result of a Find-command directly. If Find fails to find something, it will return Nothing, you will get nasty runtime errors when you execute Nothing.Activate. Instead, assign the result of the Find to another variable and check if it contains something:
Dim searchTerm as String
searchTerm = ActiveCell.Value
Sheets("Sheet2").Select
Dim hitRange as Range
Set hitRange = Cells.Find(What:=searchTerm, After:=ActiveCell, LookIn:=xlFormulas2, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, MatchByte:=False, SearchFormat:=False)
If Not hitRange Is Nothing Then hitRange.Activate
A remark: Usually it's a bad idea to use Select and Activate in your code. I just left it there because I assume that the reason for your Activate is to show the result to the user. If you plan to do something else with the result, don't use Activate. Instead, work with the Range variable (hitRange).
Looking for some assistance, I'm sure this is an easy fix but I can't get my head around how to google for it!
Basically, I am searching for a value in another sheet (this is part of a loop):
XYZ = ActiveCell.Value
Sheets("sheet1").Select
Range("a1").Activate
Cells.Find(What:=XYZ, After:=ActiveCell, LookIn:= _
xlFormulas2, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:= _
xlNext, MatchCase:=False, SearchFormat:=False).Activate
However, I have two source values that "overlap", eg: one cell is "Capability" and the other is "Capability Category".
When the macro reaches "Capability" as the look up value, it is finding the cell in with "Capability Category" in the data being searched and applies the action to that instead.
Is there a way I can tell it to look for a cell value that is an exact match, instead of any cell that contains the search term?
(Noting, I cannot re-name any source data or utilise helper columns in this particular workbook.)
Thanks
L
I have searched through your forum as well as many others for an answer to my question. Every time I get close to what I need; but each time I fall short of getting my need fulfilled.
I am working with two open workbooks; one having a list of phone numbers and data related to incoming calls; the other related to the phone numbers and the user name for the phone number.
On the first workbook I have separated the list into groups by phone number with a blank row between the groups. I then go through the list and capture the phone number to be used in a “Find” in the second workbook, so I can match the phone number and capture the user name to take back to the first workbook and paste into the blank row below the associated group.
My problem is that no matter how I modify my find, I cannot get it to perform properly and select the phone number in the second workbook. I have finally managed to get it to process with no errors, but now it will not do a search. Here is my VB code; if you can help me with this I would really appreciate it.
If I can get the first search to work, I plan to modify that into a loop to continue throughout the first workbook until the end of the worksheet.
Sub Test_Find_Match_Data()
'
' Test_Find_Match_Data Macro
'
Dim Phone_Number As String, _
Called_Number As Long, _
Find_Test As Range
Range("A1").Select
Cells.Find(What:="called number", _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False).Activate
Selection.End(xlDown).Select
Phone_Number = ActiveCell.Value
Selection.Copy
ActiveWindow.ActivateNext
Range("A1").Select
If Find_Test Is Nothing Then
ActiveCell.Offset(RowOffset:=1, _
ColumnOffset:=0).Activate
If ActiveCell.Value <> Phone_Number Then
Set Find_Test = Cells.Find(What:=Phone_Number, _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
Selection.Copy
Range("A1").Select
ActiveWindow.ActivateNext
End If
End If
End Sub
Try replacing Phone_Number = ActiveCell.Value with Phone_Number = ActiveCell.Text
I have a UserForm that sits on top of my spreadsheet and simply displays information from the row containing the currently selected cell. Buttons on the form allow the user to move up/down the spreadsheet row by row. For example, when the "next record" button is clicked, the code executed is something like:
Cells(ActiveCell.Row + 1, ActiveCell.Column).Select
LoadValues
I would like it to work even if the user filters the data and then loads the form. However, using the above code, it wants to loop through all cells, not just the ones still visible after filtering. I've seen solutions for immediately looping through only visible cells, e.g.,
For Each viscell In rng.SpecialCells(xlCellTypeVisible)
...
Next viscell
So there seems like there should be a better, more direct way to do this than looping through all rows until I get to the next one with .Hidden = False but I can't seem to figure out how to get a reference to "the next visible cell" in order to select it.
Any pointers would be greatly appreciated. Thanks.
Here's a lightning-quick way to activate the first not-blank, visible cell in a filtered range. Just change 'Range("A1")' to whatever range you'd like to search after. Also consider whether you want xlByColumns or xlByRows.
ActiveSheet.Cells.SpecialCells(xlCellTypeVisible).Find(What:="*", _
After:=ActiveSheet.Range("A1"), LookIn:=xlFormulas, lookat:=xlPart, searchorder:=xlByColumns, _
SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False).Activate
I recommend using tables whenever possible, as they have variable named ranges built-in that are easy to reference.
Here's another example, using tables. It's targeted to search a specific column, so it'll be even faster.
Just find and replace TABLE_NAME and COLUMN_NAME with your values.
ActiveSheet.Range("TABLE_NAME[[#All], COLUMN_NAME]]").SpecialCells(xlCellTypeVisible).Find _
(What:="*", After:=ActiveSheet.Range("TABLE_NAME[[#Headers],[COLUMN_NAME]]"), _
LookIn:=xlFormulas, lookat:=xlPart, searchorder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
No loops required because it's built off of Excel's "Find" functionality.
And just a tip,you can also use this to grab the data of such a cell on separate worksheet without activating/selecting it at all.
Just find and replace Dbl_EXAMPLE, SHEET_NAME, TABLE_NAME and COLUMN_NAME with your references.
Dim Dbl_EXAMPLE as Double
Dbl_EXAMPLE = Sheets("SHEET_NAME").Range("TABLE_NAME[[#All], COLUMN_NAME]]").SpecialCells(xlCellTypeVisible).Find _
(What:="*", After:=Sheets("SHEET_NAME").Range("TABLE_NAME[[#Headers],[COLUMN_NAME]]"), _
LookIn:=xlFormulas, lookat:=xlPart, searchorder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Value2
Just replace ".Value2" at the end with whatever property you're looking for.
Examples:
.Formula
.Row
.Column
The list goes on
I really struggled with this too and used Ryan's solution, albeit a little abbreviated, for my purposes..
This may be as brief as it gets. :)
ActiveCell.EntireColumn.SpecialCells(xlCellTypeVisible).Find(What:="*", After:=ActiveCell).Activate
Here is one method using a simple loop until the next row down is visible.
Dim rng As Range
Set rng = ActiveCell
Dim n As Long: n = 1
Do Until rng.Offset(n, 1).Rows.Hidden = False
n = n + 1
Loop
rng.Offset(n, 1).Select
LoadValues
I'm still learning VB. I tried recording a VB script in excel 2010 that selects a name on the main sheet, then goes to another sheet and finds all the rows with that name, copies all the rows and returns to the main sheet and insert the copied cells below the selected name. The cells are pushed down. The code should repeat for the next name below where the copied cells were paste.
My recording failed to do all of the above. Do you have a suggestion?
Sub Macro5()
'
' Macro5 Macro
'
' Keyboard Shortcut: Ctrl+l
'
Selection.Copy
Sheets("Sheet1").Select
ActiveCell.Offset(2, 3).Range("A1").Select
Cells.Find(What:="Leeanne Hickmott", After:=ActiveCell, LookIn:= _
xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:= _
xlNext, MatchCase:=False, SearchFormat:=False).Activate
Cells.FindNext(After:=ActiveCell).Activate
ActiveCell.Rows("1:3").EntireRow.Select
ActiveCell.Offset(0, -7).Range("A1").Activate
Application.CutCopyMode = False
Selection.Copy
Sheets("Sheet4").Select
ActiveCell.Offset(1, 0).Rows("1:1").EntireRow.Select
Selection.Insert Shift:=xlDown
ActiveCell.Offset(3, 6).Range("A1").Select
End Sub
Excel's record macro process can't record the conditionals or loops you need to make that kind of macro work. It also can't record that you pasted a value into the find dialog, it just records that you want to search for "Leeanne Hickmott"
My first suggestion would be to use range variables to point to the important cells on each worksheet. For example...
Dim rngPasteHere as Range, rngCopyFrom as Range
set rngPasteHere = Selection
set rngCopyFrom = Sheets("Sheet1").Range("D1")
' find first row
set rngCopyFrom = rngCopyFrom.Cells.Find(What:=rngPasteHere.Value _
, After:=rngCopyFrom, LookIn:=xlFormulas _
, LookAt:=xlPart, SearchOrder:=xlByRows _
, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False)
You will also need two loops, an outer loop that repeats the whole process for the next name and an inner loop that finds all the rows with the current name. I can't really get more specific than that without knowing what your data looks like.
Are the names sorted alphabetically?
Are all rows with the same name right next to each other or are they mixed with other names?
Are there just a few rows of each name or thousands?