Dynamic Ranges in two workbooks - vba

I am trying to compare a column in a master sheet to a column in sheet that is being opened via a request box. I would like the ranges to be dynamic compared to what I have currently in the code. In the master sheet I would like for it to look a column A starting in cell A2 and go to the last entry and in the opened sheet it should look at column E starting in cell C2 and go to the last entry. Code I am currently using is below:
Sub InspectionCheck()
Dim colI_Cell As Range
Dim colI_Range As Range
Dim rngLookupRange As Range
Dim rngFound As Range
Dim rngInspected As Range
Dim FileName As Variant
Dim wb As Workbook
Set colI_Range = ActiveSheet.Range("A2:A350").Cells
FileName = Application.GetOpenFilename(filefilter:="Excel Files(*.xlsx),*.xlsx")
Set wb = Workbooks.Open(FileName)
Set rngLookupRange = wb.Worksheets("owssvr").Range("E2:E350")
ThisWorkbook.Activate
For Each colI_Cell In colI_Range
With rngLookupRange
Set rngFound = .Find(What:=colI_Cell.Value, LookIn:=xlValues, LookAt:=xlWhole)
If Not rngFound Is Nothing Then
colI_Cell.Offset(0, 1) = "Yes"
Else: colI_Cell.Offset(0, 1) = "No"
End If
End With
Next
Set rngLookupRange = Nothing
wb.Close False
Set wb = Nothing
Set colI_Range = Nothing
End Sub

This is quite easily done if you use the following module code to find the last row that is not blank:
Function FindLastRowNotBlank(ByRef ws As Worksheet, ByRef firstRow As Long, _
ByRef column As Long) As Long
Dim lastRow As Long
lastRow = firstRow
If ws.Cells(lastRow, column).Value <> "" Then
Do While ws.Cells(lastRow, column).Value <> ""
lastRow = lastRow + 1
Loop
FindLastRowNotBlank = lastRow - 1 'the last entry is the blank row so needs to subtract 1 from the result
Else
FindLastRowNotBlank = 0 'Returns 0 if the firstRow is empty
Exit Function
End If
End Function
Then you can use the number obtained in your code like this:
Sub InspectionCheck()
Dim colI_Cell As Range
Dim colI_Range As Range
Dim rngLookupRange As Range
Dim rngFound As Range
Dim rngInspected As Range
Dim FileName As Variant
Dim wb As Workbook
Dim i as Long, rngStr as String
i = FindLastRowNotBlank(ActiveSheet, 2,1) 'I have added this
rngStr = "A2:A" & i 'I have added this
Set colI_Range = ActiveSheet.Range(rngStr).Cells 'I have modified this
FileName = Application.GetOpenFilename(filefilter:="Excel Files(*.xlsx),*.xlsx")
Set wb = Workbooks.Open(FileName)
i = FindLastRowNotBlank(wb.Worksheets("yoursheetnamehere"), 2,5) 'I have added this you need to fill in the worksheet name
rngStr = "E2:E" & i 'I have added this
Set rngLookupRange = wb.Worksheets("owssvr").Range(rngStr) ' I have modified this
ThisWorkbook.Activate
For Each colI_Cell In colI_Range
With rngLookupRange
Set rngFound = .Find(What:=colI_Cell.Value, LookIn:=xlValues, LookAt:=xlWhole)
If Not rngFound Is Nothing Then
colI_Cell.Offset(0, 1) = "Yes"
Else: colI_Cell.Offset(0, 1) = "No"
End If
End With
Next
Set rngLookupRange = Nothing
wb.Close False
Set wb = Nothing
Set colI_Range = Nothing
End Sub
Let me know how it works. Thanks,
Clint

Related

How to make an noncontiguous range of cells work for every cell referenced

I have a noncontiguous range and I want whatever the user writes in each cell in the range to show up in a column in a table I made. In the first column of my table I'm having the program number each generated entry in the table when the user adds a value in one of the specified cells all the way up to 18. I renamed each cell in the range to be "Space_ (some number)". Even though I have written in three of the specified cells, my table only shows me the first value in the first specified cell.
Here is my code so far:
Sub test2()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Sheets("Sheet1")
Dim i As Integer
Dim rng As Range
Set rng = ws.Range("Space_7, Space_10, Space_13, Space_16, Space_19, Space_22, Space_25, Space_28, Space_31, Space_34, Space_37, Space_40, Space_53, Space_56, Space_59, Space_62, Space_65, Space_68")
ws.Range("A13:A31,B13:B31").ClearContents
For i = 1 To 18
If Not IsEmpty("rng") Then
ws.Range("A12").Offset(1).Value = i
End If
Exit For
Next i
If Not IsEmpty("rng") Then
ws.Range("B12").Offset(1).Value = rng.Value
End If
End Sub
This should address the various issues I mentioned in my comment:
Sub test2()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Sheets("Sheet1")
Dim i As Long
Dim rng As Range, r As Range
With ws
Set rng = .Range("Space_7, Space_10, Space_13, Space_16, Space_19, Space_22, Space_25, Space_28, Space_31, Space_34, Space_37, Space_40, Space_53, Space_56, Space_59, Space_62, Space_65, Space_68")
.Range("A13:B31").ClearContents
For Each r In rng.Areas
If Not IsEmpty(r) Then
.Range("A13").Offset(i).Value = i + 1
.Range("B13").Offset(i).Value = r.Value
i = i + 1
End If
Next r
End With
End Sub
A couple things here - Instead of trying to put all your named ranges into a Range, put them individually in an Array and cycle through them - If they're not blank, put the value into the cell.
Your .Offset is always going 1 below row 12, so that's why you're only seeing one row of data.
Sub test2()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Sheets("Sheet1")
Dim i As Long, j As Long
Dim rngarray As Variant
rngarray = Array("Space_7", "Space_10", "Space_13", "Space_16", "Space_19", "Space_22", "Space_25", "Space_28", "Space_31", "Space_34", "Space_37", "Space_40", "Space_53", "Space_56", "Space_59", "Space_62", "Space_65", "Space_68")
j = 12
ws.Range("A13:B31").ClearContents
For i = 0 To UBound(rngarray)
If ws.Range(rngarray(i)).Value <> "" Then
ws.Range("A12").Offset(j - 11).Value = i + 1
ws.Range("B12").Offset(j - 11).Value = ws.Range(rngarray(i)).Value
j = j + 1
End If
Next i
End Sub
I'd go as follows:
Sub test2()
Dim i As Integer
Dim rng As Range, cell As Range
With ThisWorkbook.Sheets("Sheet1")
.Range("A13:A31,B13:B31").ClearContents
Set rng = .Range("Space_7, Space_10, Space_13, Space_16, Space_19, Space_22, Space_25, Space_28, Space_31, Space_34, Space_37, Space_40, Space_53, Space_56, Space_59, Space_62, Space_65, Space_68")
For Each cell In rng.SpecialCells(xlCellTypeConstants).Areas
ws.Range("A12:B12").Offset(i).Value = Array(i + 1, cell(1, 1).Value)
i = i + 1
Next
End With
End Sub

Match and replace a string from a column in multiple ranges on multiple sheets

I am trying to write a code that will search multiple ranges and match the first half of a string. if the match is true it would them replace the cell in the range with the cell in the column.
I found this code and made some changes to search multiple columns in multiple ranges on different sheets and simply replace if the first part of the string matches.
The other problem I have is that I need it to search part of the string in the cell for example
In the range; 879841.42859-MD_42885
From the column; 879841.42859-MD_43
I want it to match 879841.42859-MD then replace 879841.42859-MD_43885 with 879841.42859-MD_43
' Matchandreplace1 Macro
' Code from stack overflow cut down, no sheets involved.
'
Dim ShSrc As Worksheet, ShTar As Worksheet
Dim SrcLRow As Long, TarLRow As Long, NextEmptyRow As Long
Dim RefList As Range, TarList As Range, RefCell As Range, RefColC
Dim TarCell As Range, TarColC As Range
Dim IsFound As Boolean
Dim ToFind As String
With ThisWorkbook
Set ShSrc = .Sheets("Sheet1")
Set ShTar1 = .Sheets("Sheet2")
Set ShTar2 = .Sheets("Sheet3")
End With
'Get the last rows for each sheet.
SrcLRow = ShSrc.Range("A" & Rows.Count).End(xlUp).Row
TarLRow = ShTar1.Range("A" & Rows.Count).End(xlUp).Row
TarLRow = ShTar2.Range("A" & Rows.Count).End(xlUp).Row
'Set the lists to compare.
Set RefList = ShSrc.Range("A2:A" & SrcLRow)
Set TarList = ShTar1.Range("A2:A" & TarLRow)
Set TarList = ShTar2.Range("A2:A" & TarLRow)
'Initialize boolean, just for kicks.
IsFound = False
'Speed up the process.
Application.ScreenUpdating = False
'Create the loop.
For Each RefCell In RefList
ToFind = RefCell.Value
'Look for the value in our target column.
On Error Resume Next
Set TarCell = TarList.Find(ToFind)
If Not TarCell Is Nothing Then IsFound = True
On Error GoTo 0
'If value exists in target column...
If IsFound Then
'set the value to match and highlight.
TarColC.Value = RefColC.Value
TarColC.Interior.ColorIndex = 4
End If
'Set boolean check to False.
IsFound = False
Next RefCell
Application.ScreenUpdating = True
End Sub
Thanks,
Jerome
A few snips to better describe
The code you have pasted has lot of syntax errors. Excel has got find and replace function which can replace the string it has found. Your requirement is to find a portion of a cell ( from source) and replace the whole cell in target
You have to append a * before and after the find string and it will replace the whole cell. Am assuming that you need to match first 15 letters of the "Find" String
Sub FindReplaceAll1()
Dim sht As Worksheet
Dim fnd As Variant
Dim rplc As Variant
Dim Found As Range
Dim Checkcol As Integer, rowcount As Integer, TcurrentRow As Integer, currentRow As Integer, Targrowcount As Integer
Checkcol = 1 'Denotes A column
Sheets("Sheet1").Select
rowcount = Cells(Rows.Count, Checkcol).End(xlUp).Row
For currentRow = 1 To rowcount
'Find the substring for which you need to match. Am taking first 15 characters.
fnd = Left$(Cells(currentRow, Checkcol).Value, 15)
rplc = Cells(currentRow, Checkcol).Value
For Each sht In ActiveWorkbook.Worksheets
If sht.Name = "Sheet2" Or sht.Name = "Sheet3" Then
'Replace the whole string when a partial match is achieved
sht.Cells.Replace what:="*" & fnd & "*", Replacement:=rplc, LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False
End If
Next sht
Next
End Sub

Extracting data from one workbook and pasting in another with comments

I would like to copy the data from one workbook to another.
My source workbook has some comments listed in each row. When I use my code to copy, it does not copy the comments accordingly. Could any one help, how I could copy from one workbook to another with the comment field ? my comments are in Column P.
Sub Extract()
Dim DestinationWB As Workbook
Dim OriginWB As Workbook
Dim path1 As String
Dim FileWithPath As String
Dim lastRow As Long, i As Long, LastCol As Long
Dim TheHeader As String
Dim cell As Range
Set DestinationWB = ThisWorkbook
path1 = DestinationWB.Path
FileWithPath = path1 & "\Downloads\CTT.xlsx"
Set OriginWB = Workbooks.Open(filename:=FileWithPath)
lastRow = OriginWB.Worksheets("Report").Cells(Rows.count, 1).End(xlUp).Row
LastCol = OriginWB.Worksheets("Report").Cells(22, Columns.count).End(xlToLeft).Column
For i = 1 To LastCol
'get the name of the field (names are in row 22)
TheHeader = OriginWB.Worksheets("Report").Cells(22, i).Value
With DestinationWB.Worksheets("CTT").Range("A4:P4")
'Find the name of the field (TheHeader) in the destination (in row 4)
Set cell = .Find(TheHeader, LookIn:=xlValues)
End With
If Not cell Is Nothing Then
OriginWB.Worksheets("Report").Range(Cells(23, i), Cells(lastRow, i)).Copy Destination:=DestinationWB.Worksheets("CTT").Cells(5, cell.Column)
Else
'handle the error
End If
Next i
OriginWB.Close SaveChanges:=False
End Sub
I refactored your code correcting the unqualified references and printing the Source and Destination range addresses to the Immediate window. This should give you an idea of what is going on.
Sub Extract()
Dim DestinationWB As Workbook
Dim OriginWB As Workbook
Dim FileWithPath As String, path1 As String, TheHeader As String
Dim lastRow As Long, col As Long
Dim cell As Range, Source As Range
Set DestinationWB = ThisWorkbook
path1 = DestinationWB.Path
FileWithPath = path1 & "\Downloads\CTT.xlsx"
Set OriginWB = Workbooks.Open(Filename:=FileWithPath)
With OriginWB.Worksheets("Report")
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
For col = 1 To .Cells(22, .Columns.Count).End(xlToLeft).Column
'get the name of the field (names are in row 22)
TheHeader = OriginWB.Worksheets("Report").Cells(22, col).Value
With DestinationWB.Worksheets("CTT").Range("A4:P4")
'Find the name of the field (TheHeader) in the destination (in row 4)
Set cell = .Find(TheHeader, LookIn:=xlValues)
End With
If Not cell Is Nothing Then
Set Source = .Range(.Cells(23, col), .Cells(lastRow, col))
Source.Copy Destination:=cell.Offset(1)
Debug.Print Source.Address(External:=True), "Copied to ", cell.Offset(1).Address(External:=True)
Else
'handle the error
End If
Next
End With
OriginWB.Close SaveChanges:=False
End Sub

VBA TreeView_NodeCheck: Search for Match in Column and post in row beneath if empty

I am trying to work around the tough task to save selected nodes from a TreeView (tough due to my limited VBA knowledge) by first saving a UserID with a TextBox_AfterUpdate Event and subsequently saving the checked node's full path in the rows below when a match is found. Multiple checks are possible, that's why I approached it the way I did below.
I am working on this Problem for 2 working-days now and pray that one of you can help me out of my misery here haha
No Error is produced and a look at the Debugger Shows me that each column in found correctly. Also, the saving user ID via TextBox_AfterUpdate Event works like a treat and should stay this way. It simply does not copy it - please Help.
Thank you in advance!
Private Sub SuppNo_AfterUpdate()
'########Save SuppNo for CG-entry-saving########
Dim wb As Workbook
Set wb = ActiveWorkbook
Dim ws As Worksheet
Set ws = wb.Worksheets("Supplier Skills")
Dim lastcol As Long
With ws
lastcol = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With
'Copy Supplier No into Row 1 and next empty column
ws.Cells(1, lastcol).Offset(0, 1).Value = Me.SuppNo.Value
End Sub
'------------------------------------------------------------------------------------------
Private Sub CGTreeView_NodeCheck(ByVal Node As MSComctlLib.Node)
Dim wb As Workbook
Set wb = ActiveWorkbook
Dim ws As Worksheet
Set ws = wb.Worksheets("Supplier Skills")
Dim myNode As Node
'1. - - Copy Supplier No into Row 1 and next empty column
'Done in SuppNo_Change event
'2.1. - - Find matching entry
Dim aCell As Range
Dim col As Long, lRow As Long, i As Long
Dim colName, NodePath As String
strFind = Me.SuppNo
NodePath = Me.CGTreeView.SelectedItem.FullPath
With ws
Set aCell = .Range("A1:ZZ1").Find(What:=Me.SuppNo, LookIn:=xlValues, LookAt:=xlWhole, _
SearchOrder:=xlByColumns, MatchCase:=False, SearchFormat:=False)
'~~> If Found
If Not aCell Is Nothing Then
col = aCell.Column
colName = Split(.Cells(, col).Address, "$")(1)
lRow = .Range(colName & .Rows.Count).End(xlUp).Row
'2.2. - - Find the last empty row and copy each new FullPath when checked
For i = 2 To 50
If Cells(i, col) Is Nothing Then
ws.Cells(i, col) = NodePath
i = i + 1
End If
Next i
'~~> If not found
Else
Exit Sub
End If
End With
End Sub
I added a few features to eliminate duplicates.
Private Sub SuppNo_AfterUpdate()
'########Save SuppNo for CG-entry-saving########
Dim IDColumn As Long
Dim dItems As Object
Dim c As Range, ItemsRange As Range
Dim n As Node
Set dItems = CreateObject("Scripting.Dictionary")
With ActiveWorkbook.Worksheets("Supplier Skills")
IDColumn = getSuppNoColumn
.Cells(1, IDColumn).Value = Me.SuppNo.Value
Set ItemsRange = .Range(.Cells(2, IDColumn), .Cells(.Rows.count, IDColumn).End(xlUp))
If Not ItemsRange Is Nothing Then
For Each c In ItemsRange
dItems(c.text) = vbNullString
Next
End If
End With
For Each n In CGTreeView.Nodes
n.Checked = dItems.exists(n.FullPath)
Next
End Sub
'------------------------------------------------------------------------------------------
Private Sub CGTreeView_NodeCheck(ByVal Node As MSComctlLib.Node)
Dim IDColumn As Long
Dim dItems As Object
Dim n As Node
If Me.SuppNo.Value <> "" Then
IDColumn = getSuppNoColumn
With ActiveWorkbook.Worksheets("Supplier Skills")
.Range(.Cells(1, IDColumn), .Cells(.Rows.count, IDColumn).End(xlUp)).Offset(1).Clear
Set dItems = CreateObject("Scripting.Dictionary")
For Each n In CGTreeView.Nodes
If n.Checked Then dItems(n.FullPath) = vbNullString
Next
If dItems.count > 0 Then .Cells(2, IDColumn).Resize(dItems.count) = Application.Transpose(dItems.Keys)
End With
End If
End Sub
Function getSuppNoColumn() As Long
Dim f As Range
With ActiveWorkbook.Worksheets("Supplier Skills")
Set f = .Range("1:1").Find(What:=Me.SuppNo, LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False)
If f Is Nothing Then
getSuppNoColumn = IIf(.Cells(1, 1) = "", 1, .Cells(1, .Columns.count).End(xlToLeft).Offset(0, 1).Column)
Else
getSuppNoColumn = f.Column
End If
End With
End Function

Vba copy row to another workbook based on condition

I have 2 wb and need to copy value to another wb based on condition:
If the value in the column F of wb2 appears in column F of wb1, then I need to copy value in the column G of wb2 to column G of wb1. The code is below:
Dim LtRow As Long
Dim m As Long, n As Long
With wb2.Worksheets.Item(1)
LtRow = .Cells(.Rows.Count, "G").End(xlUp).Row
End With
With ThisWorkbook.Sheets.Item(2)
n = .Cells(.Rows.Count, "G").End(xlUp).Row + 1
End With
For m = 1 To LtRow
With wb2.Worksheets.Item(1)
If .Cells(m, 6).Value = ThisWorkbook.Sheets.Item(2).Cells(m, 6).Value Then
.Rows(m).Copy Destination:=ThisWorkbook.Sheets.Item(2).Range("G" & n)
n = n + 1
End If
End With
Next m
I don't know why the code didn't work at all! Where is the problem in my code?
EDIT:
To see what your excel files look like wasn't an option for what you are trying to do. Especially because in you have many empty rows. Anyway, this works for me:
Sub CopyConditions()
Dim Wb1 As Workbook
Dim Wb2 As Workbook
Dim Wb1Ws2 As Worksheet
Dim Wb2Ws1 As Worksheet
Set Wb1 = ThisWorkbook
Set Wb1Ws2 = ThisWorkbook.Sheets("Differences")
'open the wb2
Dim FullFilePathAndName As Variant
Dim StrOpenFileTypesDrpBx As String
Let StrOpenFileTypesDrpBx = "xls (*.xls),*.xls,CSV (*.CSV),*.CSV,Excel (*.xlsx),*.xlsx,OpenOffice (*.ods),*.ods,All Files (*.*),*.*,ExcelMacros (*.xlsm),.xlsm"
Let FullFilePathAndName = Application.GetOpenFilename(StrOpenFileTypesDrpBx, 1, "Compare this workbook ""(" & Wb1.Name & ")"" to...?", , False) 'All optional Arguments
If FullFilePathAndName = False Then
MsgBox "You did't select a file!", vbExclamation, "Canceled"
Exit Sub
Else
Set Wb2 = Workbooks.Open(FullFilePathAndName)
Set Wb2Ws1 = Wb2.Sheets("Sheet1")
End If
Dim rCell As Range
Dim sCell As Range
'loop through each cell in column F until row30 because with the empty cells in the column we can't use Rows.count
For Each rCell In Wb1Ws2.Range(Wb1Ws2.Cells(1, 6), Wb1Ws2.Cells(30, 6)) 'Wb1Ws2.Cells(Wb1Ws2.Rows.Count, 6).End(xlUp))
'if the cell column F is equal to a cell in wb2 sheet1 column L
For Each sCell In Wb2Ws1.Range(Wb2Ws1.Cells(3, 12), Wb2Ws1.Cells(Wb2Ws1.Rows.Count, 12).End(xlUp))
If sCell = rCell Then
rCell.Offset(0, 1) = sCell.Offset(0, 1)
End If
Next sCell
Next rCell
End Sub
How does it go for you?