I've trawled through a few hours of Google looking for an answer for this, so I apologise if it seems obvious to you, it really isn't to me!
I'm trying to take a cell value from 1 workbook, search for it in another. As a result of that, select some data in the search result's row, copy and paste into a cell in the search term's row in the original workbook.
Here's what I've written:
Sub AutoCableSize()
'
' AutoCableSize Macro
Dim Row As Integer
Dim CableRef As String
Dim Rng As Integer
Rng = 0
Row = 1
CableRef = ""
Windows("170615-Submains Cable Schedule.xlsx").Activate
For Each Cell In Range("F3:F303"):
On Error Resume Next
If CableRef = "Finish" Then
GoTo Finish:
End If
CableRef = Range("F" & Row).Value
Windows("170601-B2-3-HL_BAS_SCH_61_0001.xlsx").Activate
Columns("A:A").Select
Selection.Find(What:=CableRef, LookIn:=xlValues _
, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Select
Rng = ActiveCell.Row
If Rng = 1 Then
GoTo Continue
End If
Range("C" & Rng, "D" & Rng).Copy
Windows("170615-Submains Cable Schedule.xlsx").Activate
Range("J" & Row).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Continue:
Row = Row + 1
Next Cell
Finish:
End Sub
What should I put in the Find variables to search for an exact result. I have used xlWhole but I am having an issue:
If the entry does not exist, it skips to the next correctly.
If the entry does exist, it selects the first blank cell in the search series, and treats that as the search result?! I have no idea why!
Try this instead:
Option Explicit
Sub AutoCableSize()
Dim r As Range, findRng As Range
Dim ws1 As Worksheet, ws2 As Worksheet
Set ws1 = Workbooks("170615-Submains Cable Schedule").Worksheets("Sheet1")
Set ws2 = Workbooks("170601-B2-3-HL_BAS_SCH_61_0001").Worksheets("Sheet1")
For Each r In ws1.Range("F3:F303")
Set findRng = ws2.Columns("A:A").Find(What:=r.Value, LookIn:=xlFormulas _
, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not findRng Is Nothing Then
findRng.Copy
ws1.Range("J" & r.Row).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
End If
Next r
End Sub
I've changed your code a lot. The main thing to notice is that I haven't used Activate or Select anywhere. Referring directly to the workbook/worksheet/cell rather than activating it and working with selection is a much better style and it's the first thing to learn if you want to write error-free code.
More here: How to avoid using Select in Excel VBA macros
#CallumDA
In looking at your answer code, I found that in recent Excel versions, it DID NOT FUNCTION correctly - UNLESS you used exactly what the Macro recorder creates:
Set X = {AnyRangeVariableHere}.Find(...) method calls fail universally to return an object instance now, leaving X = Nothing (and failing to find a target, even when a valid one exists).
The only syntax which seems to work is literally:
Set X = Cells.Find(...)
If you look it all up the documents, this distinction makes no sense, but I can assure you that with Excel 2016/2019, this certainly seems to be the case.
Apparently Application.Cells method is some sort of special case/subclass whereby the .Find method actually still functions and returns a range object reference.
Related
I am facing the problem of pasting data in my vba code mentioned below :
Range("B:AK").Select
Selection.Copy
Range("AN:BW").Paste
I need to copy the data with Range starting from column B to Column AK and paste it into columns starting from AN to BW. But I am getting error 1004. Kindly help me with the updated version of the code. and columns belong to the same worksheet.
Copy >> Paste is a 1-line command:
Range("B:AK").Copy Range("AN:BW")
Edit 1:
Dim LastRow As Long, LastCell As Range
With Worksheets("Sheet1") ' change to your sheet's name
' safest way to get the last row with data in column "B:AK"
Set LastCell = .Columns("B:AK").Find(What:="*", Lookat:=xlPart, LookIn:=xlFormulas, _
SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False)
If Not LastCell Is Nothing Then
LastRow = LastCell.Row
Else
MsgBox "Error! worksheet is empty", vbCritical
End
End If
.Range("B2:AK" & LastRow).Copy .Range("AN2")
End With
Try:
Range("B:AK").Select
Selection.Copy
Range("AN").Select
Activesheet.Paste
If it doesn't work, try adding a row number to AN, like "AN1"
Try this one
Range("$B$2:$AK$1048576").Select
Selection.Copy
Range("AN2").Select
ActiveSheet.Paste
Let me know if it helps.
When sending out budget files excel files I need to first copy them to a new book then remove the sections that formulas in the document use to get their values. I do this without calculating so #REF errors appear in the formulas but the values do not #REF until i calculate.
I then want to use these #REF errors as an identifier to search for, copy the cells value (pre calculation) and paste as values so I can keep the value.
I have a solution that works below but this takes upwards of ten minutes.
Sub Value_REF2()
'Definitions
Dim lCount As Long
Dim rFoundCell As Range
Dim rng As Range
Dim cell As Range
'If Error go to Process Error function
On Error GoTo ProcError
'Remove any #REF in text first to prevent infinite loop in find below
Set rng = Range("A1:BB999") 'Range may need adjusting based on Grid
'For Loop
For Each cell In rng
If cell.Text = "#REF!" Then
cell.ClearContents
End If
Next cell
' Search for #REFs in forumlas
Set rFoundCell = Range("A1")
Do
Set rFoundCell = Cells.Find(What:="#REF", After:=rFoundCell, _
LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
'Take found cell and copy paste values
With rFoundCell
.Copy
.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
End With
Loop 'Error will occur, this will trigger ProcError function
'Process Error Function - Exit Sub
ProcError:
Exit Sub
End Sub
My next solution is below which should be much faster but i just can't work out how to make the IsError look in the actual formula rather than just the cell.
IsError(cell.Formula) does not seem to work?
Sub Value()
Dim rng As Range
Application.ScreenUpdating = False
Application.Interactive = False
Set rng = Range("A1:BB999")
With ActiveSheet
For Each cell In rng
If IsError(cell.Formula) Then
cell.Copy
cell.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
End If
Next cell
End With
Application.ScreenUpdating = True
Application.Interactive = True
End Sub
The main goal of this is to keep all formulas that do not refer to outside the budget table (like FTE calculations or subtotals and totals) and only value ones that do look outside.
Any Ideas?
Want to write a Macro that would search for a particular word in a range of cells (or after a cell), let's say "hello" in our case. Suppose my spreadsheet looks like this:
Hello user
Hello Nancy
Hello count 2
The content of the spread sheet change daily, so that I may have different number of 'Hello's everyday. I want to copy the number (2) beside the last 'Hello' to another cell. If the word count of hello doesn't exits, it will put 0 in that cell(Note that even if the word count is 0, there might still be 'hello' in this spread sheet). The location of the last Hello will always be after Cell A17.
I was thinking about setting the parameter After to cell A17, and change SearchOrder to xlByColumns, but When the search reaches the end of the search range, it wraps around to the beginning of the range.
How should I stop the search when this wraparound occurs?
I also try to use the Find method within With to search within range A17 to B22:
With Sheets("Data").Range("A17:B22")
Set hello = Cells.Find(What:="hello", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
End With
If Not hello Is Nothing Then
With Sheets("Data").Range("A17:B22")
Cells.Find(What:="Hello", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Offset(0, 1).Range("A1").Select
Application.CutCopyMode = False
Selection.Copy
Range("B17").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
End With
Else
Range("B17").Select
ActiveCell.FormulaR1C1 = "0"
End If
But it will still locate the search to the first 'Hello' in the spreadsheet.
Try This:
Function GetLastNumber(TheRange As Range, TheWord As String) As Variant
Dim Finder
'You can add LookAt:=xlWhole if you want entire word only
Set Finder = TheRange.Find(TheWord, SearchDirection:=xlPrevious)
If Finder Is Nothing Then
GetLastNumber = CVErr(xlErrNA)
Else
'Return the value of the cell one column to the right of our search word
GetLastNumber = Finder.Offset(0, 1).Value
End If
End Function
You can use it like this:
Sub Test()
Range("D1") = GetLastNumber(Range("A1:A11"), "Hello")
End Sub
You can also use it as a formula:
=GetLastNumber(A1:A11,"Hello")
Results:
I want to copy the contents of two excel in one, and all goes well until I copy the contents of my second excel, because this overwrites what the first copy excel, done that :
These are my statements:
Dim wbOrigen1 As Workbook, _
wbOrigen2 As Workbook, _
wsDestino As Excel.Worksheet, _
wsOrigen1 As Excel.Worksheet, _
wsOrigen2 As Excel.Worksheet, _
rngOrigen1 As Excel.Range, _
rngDestino As Excel.Range, _
rngDestino2 As Excel.Range, _
rngOrigen2 As Excel.Range
Here is the problem
ThisWorkbook.Activate
Set rngDestino2 = wsDestino.Range(celdaDestino,Range(celdaDestino).End(xlDown).Offset(1, 0))
Range(celdaDestino).End(xlDown).Offset(1, 0).Select
wsOrigen2.Activate
rngOrigen2.Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
ThisWorkbook.Activate
rngDestino2.PasteSpecial xlPasteValues
Application.CutCopyMode = False
But this does not work the same way. The problem seems to be with rngDestino2
?rngDestino2
Type Mismatch
?err.Description
Type Mismatch
How I can fix it?
I prefer to avoid select, activate and selection in deference to direct addressing. The paste special, values can also be handled more efficiently by direct cell value transfer.
'make sure that the worksheet vars are set correctly
set wsOrigen2 = <other workbook>.Sheets("Sheet1")
set wsDestino = ThisWorkbook.Sheets("Sheet1")
With wsOrigen2.Cells(1, 1).CurrentRegion
wsDestino.Cells(Rows.Count, 1).End(xlUp) _
.Offset(1, 0).Resize(.Rows.Count, .Columns.Count) = .Cells.Value
End With
set wsDestino = nothing
set wsOrigen2 = nothing
If the workbooks are open and the worksheets are set correctly, that should be all that you really require.
See How to avoid using Select in Excel VBA macros for more methods on getting away from replying on select and activate.
I have 2 workbooks. I need copy the row in one workbook only if it contains a certain value from another workbook. Here's my code, it works for the first i=21 and i=22 but tells me there's an error in Cells.Find when I reach i=23.
For i = 21 To 35
Windows("Run Report.xlsm").Activate
Dim strL3 As String
strL3 = Sheets("Summary").Range("A" & i).Value
Workbooks("Ace Survey - Level 1 and level 3 Trending (w Resolution) v3").Activate
Range("A1").Activate
Cells.Find(What:=strL3, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
If strL3 = "Call Disconnected" Or strL3 = "Caller Not Present" Then
ActiveCell.Offset(2, 2).Select
Else
ActiveCell.Offset(1, 2).Select
End If
Application.CutCopyMode = False
ActiveCell.Copy
Windows("Run Report.xlsm").Activate
Sheets("Summary").Select
Range("G" & i).Select
ActiveSheet.Paste
Next i
Find returns a Range object if something is found, but Nothing otherwise. You are attempting to Activate the result of using Find, even if it is Nothing - which will generate an error.
You need to store the result of your Find attempt in a Range variable, and check for Nothing.
Dim rngFound As Range
Set rngFound = Range("A1").Find(...)
If Not rngFound Is Nothing Then
' we found something!
Else
' Nothing
End If
But, as advised, you should be supplying more details for your question.