Set Range as Found String Location in VBA - vba

I'm trying to set a range in VBA as the range of the inputted string that I am looking for. The full procedure is supposed to pop up a dialog box to look for a specific string, find the string, create a range called location, set this range to the range of the string that was found, move a finite amount of columns to the right, and with that new columns value, print a string into that range.
The problem right now is that for some reason It is not setting the range to the range of the string it finds.
There is only one instance of the string throughout the workbook.
I'm also relatively new to VBA so there are something commands I don't know or understand how they work.
Sub test()
Dim wb As Workbook
Set wb = ActiveWorkbook
Dim Inp As String
Dim Loc As Range
Dim Row As Integer
Dim Col As Integer
Dim NewLoc As Range
Dim Sh As Worksheet
Inp = InputBox("Scan ESD Tag")
For Each Sh In ThisWorkbook.Worksheets
With Sh.Columns("A")
Set Loc = .Find(What:=Inp)
End With
Next
Row = Loc.Row
Col = Loc.Column + (3 * 5)
Set NewLoc = Worksheets("Building 46").Cells(Row, Col)
NewLoc.Value = "Over Here"
Range("G2") = 6
End Sub

Your problem is probably that your final block should be inside the loop as otherwise Loc is likely to be Nothing (unless the term is found on the last sheet) and your code will error. You should also check first that it is found to avoid such errors.
Sub test()
Dim wb As Workbook
Set wb = ActiveWorkbook
Dim Inp As String
Dim Loc As Range
Dim Row As Integer
Dim Col As Integer
Dim NewLoc As Range
Dim Sh As Worksheet
Inp = InputBox("Scan ESD Tag")
For Each Sh In ThisWorkbook.Worksheets
With Sh.Columns("A")
Set Loc = .Find(What:=Inp)
If Not Loc Is Nothing Then
Row = Loc.Row
Col = Loc.Column + (3 * 5)
Set NewLoc = Worksheets("Building 46").Cells(Row, Col)
NewLoc.Value = "Over Here"
Range("G2") = 6 'should specify a sheet here
Exit Sub
End If
End With
Next
End Sub

Related

VBA to duplicate large dataset using array

I have data on sheet A and want to duplicate it on sheet B. Because it is a lot of data, I do not want to use copy-paste. If I really simplify it, this is my code. My ranges change although I made it sort of fixed in this simplified code. I do not want to use something like range("A1:BBB100000") since my range will change. I get 1004 error "Application-defined or object-defined error". What am I doing wrong?
Dim origin(1 to 100000, 1 to 100000) as Variant
Dim dest(1 to 100000, 1 to 100000) as Variant
Set A=Worksheets("A")
Set B=Worksheets("B")
Vrow=100000
set origin=A.range(cells(1,1),cells(Vrow, Vrow))
set dest=B.range(cells(1,1),cells(Vrow, Vrow))
dest=origin
You don't need the array. Only generate an array if your actually going to do any calculations on it. If you just want to do value -> value then that's what you do (as shown below).
Remember to always declare all your variables as well.
Dim A As Worksheet, B As Worksheet, Vrow As Long
Set A = Worksheets("A")
Set B = Worksheets("B")
Vrow = 100000
B.Range(B.Cells(1, 1), B.Cells(Vrow, Vrow)).Value = A.Range(A.Cells(1, 1), A.Cells(Vrow, Vrow)).Value
Copy Range Values to Another Worksheet
Sub CopyValues()
Const sName As String = "A"
Const sFirstCellAddress As String = "A1"
Const dName As String = "B"
Const dFirstCellAddress As String = "A1"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim sfCell As Range: Set sfCell = sws.Range(sFirstCellAddress)
Dim srg As Range: Set srg = sfCell.CurrentRegion
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim dfCell As Range: Set dfCell = dws.Range(dFirstCellAddress)
Dim drg As Range: Set drg = dfCell.Resize(srg.Rows.Count, srg.Columns.Count)
drg.Value = srg.Value
End Sub
Sub CopyValuesShorter()
Dim srg As Range
Set srg = ThisWorkbook.Worksheets("A").Range("A1").CurrentRegion
Dim drg As Range
Set drg = ThisWorkbook.Worksheets("B").Range("A1") _
.Resize(srg.Rows.Count, srg.Columns.Count)
drg.Value = srg.Value
End Sub
Sub CopyValuesShortest()
With ThisWorkbook.Worksheets("A").Range("A1").CurrentRegion
ThisWorkbook.Worksheets("B").Range("A1") _
.Resize(.Rows.Count, .Columns.Count).Value = .Value
End With
End Sub

Can't define workheet in VBA

Going crazy here. I use this definition of worksheet all the time. Copied every string to avoid typing errors. Still, the code below produces "Nothing" when I try to set FR worksheet. Pls help!
Sub FindReplace()
Dim FRep As Worksheet
Dim c As Range
Dim cText As TextBox
Dim i As Integer
Set FRep = ThisWorkbook.Worksheets("FindReplace")
For i = 1 To 23
cText = FRep.Cells(i, 3).Text
FRep.Cells(i, 2).NumberFormat = "#"
FRep.Cells(i, 2).Value = cText
Next i
The code as is seems correct. Make sure that "FindReplace" worksheet is in ThisWorkbook.
Also, you can try to get "FindReplace" worksheet by CodeName instead of by the name of the sheet. The advantage is that if the user changes the name of the worksheet, the CodeName will remain the same and you won't need to update your code to the new worksheet name.
Public Function GetWsFromCodeName(codeName As String, wb As Workbook) As Worksheet
Dim ws As Worksheet
For Each ws In wb.Worksheets
If ws.CodeName = codeName Then
Set GetWsFromCodeName = ws
Exit For
End If
Next ws
End Function
Add this function in your code:
Sub FindReplace()
Dim FRep As Worksheet
Set FRep = GetWsFromCodeName("YourCodeName", ThisWorkbook)

Extract data from one workbook and copy to another workbook

I am trying to copy the data from one workbook to another workbook.
I searched through Internet and came up with the below code. there is no error in the code.
The code works fine, but the Problem is, it is opening both the Sheets , but not copying the data in Destination sheet.
in the code below, I have considered x as source sheet and y as Destination sheet.
Could someone suggest, where i am wrong and what is the reason i am not able to copy.
Sub test()
Dim x As Workbook
Dim y As Workbook
Dim val As Variant
Dim filename As String
Set x = Workbooks.Open("D:\Mikz\xxx.xlsx")
Set y = Sheets("Sheet1").Select
val = x.Sheets("Sheet2").Range("A1").Value
y.Sheets("Sheet1").Range("A1").Value = val
x.Close
End Sub
The reason for your error, lies in the section below:
Dim y As Workbook
Set y = Sheets("Sheet1").Select
You defined y as workbook, but trying to assign a Worksheet object to it, and you added Select for some reason, which is defiantly not recommended.
It should be (if the workbook is open) :
Set y = Workbooks("YourBookName")
The rest of your code would work just fine.
However, reading your post, I think you meant to define y As Worksheet.
And then the rest of your code should be:
Set y = Sheets("Sheet1")
val = x.Sheets("Sheet2").Range("A1").Value
y.Range("A1").Value = val
Edit 1: Updated code (according to PO's new data)
Option Explicit
Sub test()
Dim x As Workbook
Dim y As Workbook
Dim Val As Variant
Dim filename As String
Set y = ThisWorkbook ' set ThisWorkbook object (where this code lies)
Set x = Workbooks.Open("D:\Mikz\xxx.xlsx")
Val = x.Sheets("Sheet2").Range("A1").Value
y.Sheets("Sheet1").Range("A1").Value = Val
x.Close
End Sub
Edit 2: Code to copy columns A:E till last row with data
Option Explicit
Sub test()
Dim x As Workbook
Dim y As Workbook
Dim Val As Variant
Dim filename As String
Dim LastCell As Range
Dim LastRow As Long
Set y = ThisWorkbook ' set ThisWorkbook object (where this code lies)
Set x = Workbooks.Open("D:\Mikz\xxx.xlsx")
With x.Sheets("Sheet2")
' use the find method to get the last row in column A:E
Set LastCell = .Columns("A:E").Find(What:="*", After:=.Cells(1), Lookat:=xlPart, LookIn:=xlFormulas, _
SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False)
If Not LastCell Is Nothing Then ' find was successful
LastRow = LastCell.Row ' get last Row with data
End If
Val = .Range("A1:E" & LastRow).Value ' save range in 2-D array
End With
' resize the range from A1 through column E and the last row with data in copied workbook
y.Sheets("Sheet1").Range("A1").Resize(LastRow, 5).Value = Val
x.Close
End Sub
Try:
Sub test()
Dim wb As Workbook
Dim sht As Worksheet, sht2 As Worksheet
Set wb = Workbooks.Open("Filename")
Set sht = wb.Worksheets("Sheet2")
Set sht2 = ThisWorkbook.Worksheets("Sheet1")
sht2.Range("A1").Value = sht.Range("A1").Value
wb.Close
End Sub
But it should throw syntax errors and type mismatches before. Dont use .Select, its not necessary for any functions or task, it can be done without.

Excel VBA code to return multiple and unique vlookup values for duplicate lookup values

I have an excel file with 3 worksheets: (1) Report, (2) category-1 and (3) category-2.
"Report" worksheet contains summary information of category-1 and category-2 data with unique ID of each category and grouping values. See attached example image.
I need to copy unique value from "Category1SubId" column of "Category1" worksheet to "Report" worksheet in "column-D" and then copy relevant value of "Category1Value" from "Category1" worksheet into "Report" worksheet in "Column-E".
For example, formula / VBA code to copy values from 1,2,3,4,5 for Apple into "Report" worksheet from "Category1" worksheet, and then copy "Breakfast" value for combination of "Apple and 1" into cell-E2 of Report worksheet from Category-1 worksheet and so on.
I tried combination of INDEX, VLOOKUP, ROWS and SEARCH formulas but none of them helped. I also tried VBA code to do it, but it didn't work.
Can anyone please help to solve this puzzle either through formula or VBA code?
Example of this worksheet is attached here.
I tried following VBA code
Sub CopyData()
Dim category1LookupValueRange As Range
Dim category2LookupValueRange As Range
Dim category1SourceRange As Range
Dim category2SourceRange As Range
Dim category1TargetRange As Range
Dim category2TargetRange As Range
Dim targetValue As String
Set category1LookupValueRange = Worksheets("Report").Range("C2:C30")
Set category2LookupValueRange = Worksheets("Report").Range("F2:F30")
Set category1SourceRange = Worksheets("Category1").Range("A2:C30")
Set category2SourceRange = Worksheets("Category2").Range("A2:C30")
Set category1TargetRange = Worksheets("Report").Range("D2:E30")
Set category2TargetRange = Worksheets("Report").Range("G2:H30")
Dim iRow As Integer
Dim category1LookupValue As Object
Dim category1Id As Object
Dim category1IdValue As Object
Dim category2LookupValue As Object
Dim category2Id As Object
Dim category2IdValue As Object
For iRow = 1 To category1LookupValueRange.Count
Set category1LookupValue = category1LookupValueRange.Cells(iRow, 1)
Set category2LookupValue = category2LookupValueRange.Cells(iRow, 1)
Set category1Id = category1SourceRange.Range.Cells(category1SourceRange.Find(category1LookupValue, LookAt:=xlWhole), 1)
Set category2Id = category2SourceRange.Range.Cells(category2SourceRange.Find(category2LookupValue, LookAt:=xlWhole), 1)
Set category1IdValue = category1SourceRange.Range.Cells(category1SourceRange.Find(category1LookupValue, LookAt:=xlWhole), 1)
Set category2IdValue = category2SourceRange.Range.Cells(category2SourceRange.Find(category2LookupValue, LookAt:=xlWhole), 1)
If Not (category1LookupValue Is Nothing) Then
If (category1SourceRange.Cells(iRow, 1) = category1LookupValue) Then
Set category1TargetRange.Range.Cells(iRow, 1) = category1Id
Set category2TargetRange.Range.Cells(iRow, 1) = category2Id
End If
End If
Next iRow
Following array formula in Cell range D2 to D30 in Report worksheet
{=IF(ISERROR(SMALL(IF(IF(ISERROR(SEARCH($C2,Category1!$A$2:$A$30)),FALSE,TRUE),ROW(Category1!$B$1:$B$30)),ROW(Category1!$B$1:$B$30))),"",INDEX(Category1!$A$2:$C$100,SMALL(IF(IF(ISERROR(SEARCH($C2,Category1!$A$1:$A$30)),FALSE,TRUE),ROW(Category1!$B$1:$B$30)),ROW(Category1!$B$1:$B$100)),1))}

How do I copy a range into a temp workbook and return a reference to it with a vba function?

I have the following which errors on the "rTemp.Value = vaTemp" line. What am I doing wrong here? Am I on the right track?
Function CreateTempRange(rSource As range) As range
' Declarations
Dim rTemp As range
Dim vaTemp As Variant
Dim wsTemp As Worksheet
Dim wbTemp As Workbook
' Open temp worksheet
Set wbTemp = Workbooks.Add
Set wsTemp = wbTemp.Worksheets.Add
' Copy range into it and get a reference to the temp range
vaTemp = rSource.Value
Set rTemp = wsTemp.range("A1").Resize(UBound(vaTemp, 1), UBound(vaTemp, 2))
rTemp.Value = vaTemp
' Return the temp range
Set CreateTempRange = rTemp
End Function
Note: This function is intended to be used by other functions and not called directly from a cell.
Set rTemp = wsTemp.range("A1").Resize(UBound(vaTemp, 1), UBound(vaTemp, 2)
There'll be a type mismatch here ... i'm not sure it really makes any sense. ubound(a,2) is used for multi-dimensional arrays not ranges.
I'm guessing you want to take the value in the cell specified then copy it many times depending on it's value. Is that correct?
Hopefully the below should give you an example to work with. If not edit your post and i'll see if i can help.
Function CreateTempRange(rSource As Range) As Range
'' Declarations
Dim rTemp As Range
Dim vaTemp As Variant
Dim wsTemp As Worksheet
Dim wbTemp As Workbook
'' Open temp worksheet
Set wbTemp = Workbooks.Add
Set wsTemp = wbTemp.Worksheets.Add
'' Copy range into it and get a reference to the temp range
vaTemp = rSource.Value
''Set rTemp = wsTemp.Range("A1").Resize(UBound(vaTemp, 1), UBound(vaTemp, 2))
Dim iTemp As Integer
On Error Resume Next
iTemp = CInt(vaTemp)
On Error GoTo 0
If iTemp < 1 Then
iTemp = 1
End If
Set rTemp = wsTemp.Range("A1:A" & iTemp)
rTemp.Value = vaTemp
'' Return the temp range
Set CreateTempRange = rTemp
End Function
Sub test()
Dim r As Range
Dim x As Range
Set r = ActiveSheet.Range("A1")
Set x = CreateTempRange(r)
End Sub
vaTemp = rSource.Value
As you aren't specifying the RangeValueDataType parameter to the Value method of the Range object, it will default to xlRangeValueDefault which, for non-empty ranges, will return an array of values. Therefore, the UBound(..., 1) and UBound(..., 2) parts make sense.
This would be easier:
Function CreateTempRange(rSource As range) As range
' Declarations
Dim rTemp As range
Dim wsTemp As Worksheet
Dim wbTemp As Workbook
' Open temp worksheet
Set wbTemp = Workbooks.Add
Set wsTemp = wbTemp.Worksheets.Add
' Create new range on that sheet starting at cell A1
Set rTemp = wsTemp.Range(Cells(1, 1), Cells(rSource.Rows.Count, _
rSource.Columns.Count))
rTemp.Value = rSource.Value
' Return the temp range
Set CreateTempRange = rTemp
End Function
You would still need some code to deal with ranges which consist of multiple areas (use the Areas.Count property to check for that)
I would do it like this
Function CreateTempRange(src As Range) As Range
Dim wbk As Workbook: Set wbk = Workbooks.Add
Dim sht As Worksheet: Set sht = wbk.Worksheets.Add
Call src.Copy(sht.Cells(1, 1))
Set CreateTempRange = Range(rSource.Address).Offset(1 - rSource.Row, 1 - rSource.Column)
End Function
Explanation of the last line of code (as requested):-
Range(rSource.Address) - this refers to the range on the current worksheet (containing the code) with the same local address as the source range, so if the the source range is C3:E5 on 'Sheet X' then Range(rSource.Address) refers to C3:E5 on the current sheet.
Since we pasted the copied range into the current sheet starting at cell A1 rather than cell C3 (I assume this is your requirement), we then need to offset this reference accordingly. The .Offset(1 - rSource.Row, 1 - rSource.Column) offsets this range negatively by both the row index (3) minus 1 and column index (C or 3) minus 1 of the source range, so that the final resulting reference starts with cell A1 and keeps the same dimensions as the source range.
Hope that helps.
Deano, that code works for me as written. What is the error you're getting?