My question is very similar to the following:
Excel VBA code to select non empty cells
However, I have some empty cells in between. In particular, I'm trying to define a range where the first row needs to be excluded, since it's a header. I also have to exclude the empty cells that follow. I was trying something like
Dim wb as workbook, ws as worksheet
Dim myrange as range
'Defined reference wb and ws
myrange=ws.range("B2",range("B2"),end(xldown))
But this only works if there are not empty cells in between. So, is there a fast and simple way to dynamically select a range that includes non-empty cells, excepted the header?
Try this
'Defined reference wb and ws
Set myrange = ws.range("B2", ws.Range("B" & Rows.Count).End(xlUp))
Don't forget to use the Set keyword
Try the next way, please:
Sub testDefineRange()
Dim ws As Worksheet, lastRow As Long, myrange As Range
Set ws = ActiveSheet 'use here what you need
lastRow = ws.Range("B" & ws.rows.count).End(xlUp).row
'Defined reference ws
Set myrange = ws.Range("B2:B" & lastRow)
myrange.Select
End Sub
I have found this link to be very useful on MANY occasions.
https://www.thespreadsheetguru.com/blog/2014/7/7/5-different-ways-to-find-the-last-row-or-last-column-using-vba
Ways To Find The Last Row
Sub FindingLastRow()
'PURPOSE: Different ways to find the last row number of a range
'SOURCE: www.TheSpreadsheetGuru.com
Dim sht As Worksheet
Dim LastRow As Long
Set sht = ActiveSheet
'Using Find Function (Provided by Bob Ulmas)
LastRow = sht.Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row
'Using SpecialCells Function
LastRow = sht.Cells.SpecialCells(xlCellTypeLastCell).Row
'Ctrl + Shift + End
LastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
'Using UsedRange
sht.UsedRange 'Refresh UsedRange
LastRow = sht.UsedRange.Rows(sht.UsedRange.Rows.Count).Row
'Using Table Range
LastRow = sht.ListObjects("Table1").Range.Rows.Count
'Using Named Range
LastRow = sht.Range("MyNamedRange").Rows.Count
'Ctrl + Shift + Down (Range should be first cell in data set)
LastRow = sht.Range("A1").CurrentRegion.Rows.Count
End Sub
Ways To Find The Last Column
Sub FindingLastColumn()
'PURPOSE: Different ways to find the last column number of a range
'SOURCE: www.TheSpreadsheetGuru.com
Dim sht As Worksheet
Dim LastColumn As Long
Set sht = ThisWorkbook.Worksheets("Sheet1")
'Ctrl + Shift + End
LastColumn = sht.Cells(7, sht.Columns.Count).End(xlToLeft).Column
'Using UsedRange
sht.UsedRange 'Refresh UsedRange
LastColumn = sht.UsedRange.Columns(sht.UsedRange.Columns.Count).Column
'Using Table Range
LastColumn = sht.ListObjects("Table1").Range.Columns.Count
'Using Named Range
LastColumn = sht.Range("MyNamedRange").Columns.Count
'Ctrl + Shift + Right (Range should be first cell in data set)
LastColumn = sht.Range("A1").CurrentRegion.Columns.Count
End Sub
If it suits your case, I like to use CurrentRegion with Intersect to eliminate the title row.
with ws.range("b2")
set myRange = intersect(.currentregion, .currentregion.offset(1,0))
end with
debug.print myRange.address
Related
I am new to VBA and normally source VBA codes from online to automate manual works. I am looking for VBA code for vlookup. I have recorded a macro with column contains 356 line of records, but when I run the macro next time with less number of rows. It still look up for 356. How do I lookup only for the cells which has values in reference cell. Please advice
Well, since you didn't post your code here, all I can do is guess what you are trying to do. You probably need to find the last used row before implementing your vlookup methodology. Something like this should help.
Sub FindingLastRow()
'PURPOSE: Different ways to find the last row number of a range
'SOURCE: www.TheSpreadsheetGuru.com
Dim sht As Worksheet
Dim LastRow As Long
Set sht = ActiveSheet
'Using Find Function (Provided by Bob Ulmas)
LastRow = sht.Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row
'Using SpecialCells Function
LastRow = sht.Cells.SpecialCells(xlCellTypeLastCell).Row
'Ctrl + Shift + End
LastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
'Using UsedRange
sht.UsedRange 'Refresh UsedRange
LastRow = sht.UsedRange.Rows(sht.UsedRange.Rows.Count).Row
'Using Table Range
LastRow = sht.ListObjects("Table1").Range.Rows.Count
'Using Named Range
LastRow = sht.Range("MyNamedRange").Rows.Count
'Ctrl + Shift + Down (Range should be first cell in data set)
LastRow = sht.Range("A1").CurrentRegion.Rows.Count
End Sub
Sub Macro1()
Dim sht As Worksheet
Dim LastRow As Long
Set sht = ActiveSheet
LastRow = sht.Cells(sht.Rows.Count, "E").End(xlUp).Row
Range("F1").Select
ActiveCell.FormulaR1C1 = "=VLOOKUP(RC[-1],C[-5]:C[-4],2,FALSE)"
Range("F1").Select
Selection.AutoFill Destination:=Range("F1:F" & LastRow)
End Sub
I'm trying to make excel focus on the cell that contains what I've searched. So if the cell is out of view in my excel spreadsheet after the search the screen auto adjusts to that specific cell. Then, I need to take everything in that cell's row and have it automatically copy into a new tab within the same excel spreadsheet. But the rows copied in the second tab need to start with Column A in row #5 and continue on. Below is the code I have so far, I'm not too familiar with VBA but I've been working at it. Any help or insight would be greatly appreciated.
`Option Explicit
Sub FindWhat()
Dim sFindWhat As String
Dim sh1 As Worksheet
Dim sh2 As Worksheet
Dim sh3 As Worksheet
Dim Search As Range
Dim Addr As String
Dim NextRow As Long
Dim cl As Range
Set sh1 = ThisWorkbook.Sheets("Sheet1")
Set sh2 = ThisWorkbook.Sheets("Sheet2")
Set sh3 = ThisWorkbook.Sheets("Sheet3")
'// This will be the row you start pasting data on Sheet3
NextRow = 5
For Each cl In Intersect(sh1.UsedRange, sh1.Columns("A")).Cells
'// the value we're looking for
sFindWhat = cl.Value
'// Find this value in Sheet2:
With sh2.UsedRange
Set Search = .Find(sFindWhat, LookIn:=xlValues,
SearchOrder:=xlByRows, SearchDirection:=xlNext)
If Search Is Nothing Then
'// Get out of here if the value is not found
'// Do NOT Exit the sub, we'll just proceed to next cell in column A
'Exit Sub
Else
'// Make sure next row in Sh3.Column("K") is empty
While sh3.Range("K" & NextRow).Value <> ""
NextRow = NextRow + 1
Wend
'// Paste the row in column K of sheet 3:
Search.Resize(1, 12).Copy Destination:=sh3.Range("K" & NextRow)
End If
End With
Next
End Sub
Try that:
Dim sh1 As Worksheet
Dim sh2 As Worksheet
Dim sh3 As Worksheet
Dim rng As Range
Dim IdRng As Range
Dim SrcRng As Range
Dim Search As Range
Dim lRow1 As Long
Dim lRow2 As Long
Dim lRow3 As Long
Set sh1 = ThisWorkbook.Sheets("Plan1")
Set sh2 = ThisWorkbook.Sheets("Plan2")
Set sh3 = ThisWorkbook.Sheets("Plan3")
lRow1 = sh1.Range("A" & Rows.Count).End(xlUp).Row
If lRow1 < 4 Then lRow1 = 4
Set IdRng = sh1.Range("A4:A" & lRow1) 'Dynamic ID's Range
lRow2 = sh2.Range("L" & Rows.Count).End(xlUp).Row
If lRow2 < 4 Then lRow2 = 4
Set SrcRng = sh2.Range("L3:L" & lRow2) 'Dynamic sheet2 search range
For Each rng In IdRng
Set Search = SrcRng.Find(What:=rng, LookIn:=xlValues)
If Not Search Is Nothing Then
lRow3 = sh3.Range("K" & Rows.Count).End(xlUp).Row
If lRow3 < 5 Then lRow3 = 5
sh2.Range(Search.Address).EntireRow.Copy sh3.Range("K" & lRow3) 'dynamic paste range
Else
MsgBox rng & " was not found.", vbInformation, sh1.Name
End If
Next rng
Remember to change Set sh1 = ThisWorkbook.Sheets("Plan1"), Set sh2 = ThisWorkbook.Sheets("Plan2") and Set sh3 = ThisWorkbook.Sheets("Plan3") to the name of your sheets.
This code has dynamic ranges for your Id's column (sheet1), search's column (sheet2) and paste's column (sheet3), so it will identify automatically in which range the last data is.
I'm trying to write a macro in VBA that will compare values in two different columns, find the mismatches and then copy and paste the entire row of the mismatched value to a new worksheet. My code is below.
My code works doing this with the individual values (which I commented out below) but when I try to copy and paste the entire row, that's when things don't work.
Public Sub CompareNumber(sh1 As Worksheet, sh2 As Worksheet, sh3 As Worksheet)
Dim lr1 As Long, lr2 As Long, rng1 As Range, rng2 As Range, c As Range
lr1 = sh1.Cells(Rows.Count, 2).End(xlUp).Row 'Get the last row with data for both list sheets
lr2 = sh2.Cells(Rows.Count, 2).End(xlUp).Row
Set rng1 = sh1.Range("B2:B" & lr1) 'Establish the ranges on both sheets
Set rng2 = sh2.Range("B2:B" & lr2)
For Each c In rng1 'Run a loop for each list, ID mismatches and paste to sheet 3.
If WorksheetFunction.CountIf(rng2, c.Value) = 0 Then
c.EntireRow.Copy sh3.Range("A" & Rows.Count).EntireRow.End(xlUp)(2)
'sh3.Cells(Rows.Count, 2).End(xlUp)(2) = c.Value
End If
Next
For Each c In rng2
If Application.CountIf(rng1, c.Value) = 0 Then
c.EntireRow.Copy sh3.Range("A" & Rows.Count).EntireRow.End(xlUp)(2)
'sh3.Cells(Rows.Count, 2).End(xlUp)(2) = c.Value
End If
Next
End Sub
Any help is greatly appreciated!
In the source data is ColumnA always populated? If not that will cause problems when pasting rows to sh3 - an empty cell in colA will cause the next-pasted row to overwrite the previous one.
Something like this is a bit safer (plus a little refactoring to abstract out the repeated loop):
Public Sub CompareNumber(sh1 As Worksheet, sh2 As Worksheet, sh3 As Worksheet)
Dim rng1 As Range, rng2 As Range, rngDest As Range
'Establish the ranges on both sheets
Set rng1 = sh1.Range(sh1.Range("B2"), sh1.Cells(Rows.Count, 2).End(xlUp))
Set rng2 = sh2.Range(sh2.Range("B2"), sh2.Cells(Rows.Count, 2).End(xlUp))
Set rngDest = sh3.Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
CopyMismatches rng1, rng2, rngDest
CopyMismatches rng2, rng1, rngDest
End Sub
Private Sub CopyMismatches(rngSrc As Range, rngMatch As Range, rngDest As Range)
Dim c As Range
For Each c In rngSrc
If Application.CountIf(rngMatch, c.Value) = 0 Then
c.EntireRow.Copy rngDest
Set rngDest = rngDest.Offset(1, 0) '<< safer if could be empty colA values
End If
Next
End Sub
Try
"sh1.rows(c1.row).EntireRow.Copy sh3.Range("A" & Rows.Count).EntireRow.End(xlUp)(2)"
instead of
"c.EntireRow.Copy sh3.Range("A" & Rows.Count).EntireRow.End(xlUp)(2)"
This may work
I wrote a very simple macro, that opens another workbook and select range of data from this workbook.
However, I keep receiving this warning: object doesn't support this property or method
What is wrong?
Sub data()
Dim wb As Workbook
Dim ws As Worksheet
Dim filename As String
Dim lastrow As Integer
Dim lastcolumn As Integer
Dim range_to_copy As Range
'open workbook
filename = "C:\Users\mk\Desktop\sales report\Sales Report.xls"
Set wb = Workbooks.Open(filename)
Set ws = wb.Sheets("data")
lastcolumn = wb.ws.Cells(1, wb.ws.Columns.Count).End(xlToLeft).Column
lastrow = wb.ws.Cells(wb.ws.Roows.Count, 1).End(xlToLeft).Row
range_to_copy = Range("Cells(1,1):Cells(lastrow,lastcolumn)")
End sub
A number of things wrong.
Edit:
Dim lastrow As Integer
Dim lastcolumn As Integer
An Integer can store numbers up to 32,767. This won't be a problem for columns, but will throw an overflow error on the row number. It's better to use the Long data type - numbers up to 2,147,486,647.
The ws variable already references the workbook so you just need:
lastcolumn = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
lastrow = wb.ws.Cells(wb.ws.Roows.Count, 1).End(xlToLeft).Row
Rows only has one o in it.
Edit: xlToLeft looks at the right most cell and works to the left. As you're looking for rows you need to use xlUp which looks at the last cell and works up.
range_to_copy = Range("Cells(1,1):Cells(lastrow,lastcolumn)")
This is an object so you must Set it. The cells references are separated by a comma and should not be held as a string.
Sub data()
Dim wb As Workbook
Dim ws As Worksheet
Dim filename As String
Dim lastrow As Long
Dim lastcolumn As Long
Dim range_to_copy As Range
'open workbook
filename = "C:\Users\mk\Desktop\sales report\Sales Report.xls"
Set wb = Workbooks.Open(filename)
Set ws = wb.Sheets("data")
lastcolumn = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
lastrow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Set range_to_copy = ws.Range(ws.Cells(1, 1), ws.Cells(lastrow, lastcolumn))
End Sub
Note: Every range reference is preceded by the worksheet reference. Without this it will always look at the currently active sheet so if you aren't on the data sheet the following will fail as the second cell reference will look at the activesheet.
ws.Range(ws.Cells(1, 1), Cells(lastrow, lastcolumn))
It might be worth checking out the With....End With code block.
There are several errors in your code.
Try
lastcolumn = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Set range_to_copy = Range(ws.Cells(1, 1), ws.Cells(lastRow, lastcolumn))
Once you defined and set your ws worksheet object, you don't need to refer to the wb object anymore, since your ws worksheet object is fully quallified with Sheets("data") in wb workbook.
Now, all you need to do is use the With statement, like in the code below:
Set ws = wb.Sheets("data")
With ws
lastcolumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
lastrow = .Cells(.Rows.Count, 1).End(xlUp).Row
Set range_to_copy = .Range(.Cells(1, 1), .Cells(lastrow, lastcolumn))
End With
I am fairly new in excel VBA and would really appreciate any help on this matter.
The workbook includes data from range A5:AZ1000 (new client info is inputted in new rows, but some cells may be empty depending on the nature of the case). When a user inputs new client info (begins a new row) I would like the existing data (range A5:AZ1000) to shift down one row, and a blank row to appear in range A5:AZ:5. I would like users to be able to click a macro "New Client" for this to happen.
It should be noted that this is a shared workbook and therefore I cannot have macro that adds a new row.
Here is the code I'm working with:
Sub shiftdown()
' shiftdown Macro
Dim lastRow As Long
Dim lastColumn As Long
Dim rngToCopy As Range
Dim rng As Range
Set rng = ActiveSheet.Range("A1").Value
lastColumn = ActiveSheet.Cells(4, Columns.Count).End(xlToLeft).Column
lastRow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
If rng > 0 Then
ActiveSheet.Range("A5" & lastRow).Select
Selection.Copy
PasteSelection.Offset(1, 0).PasteSpecial xlPasteValues
'Error Object Required
End If
End Sub
Normally I wouldn't answer if the question doesn't include any code to show effort, but I started writing the below while the question actually did show code so I may as well provide it. It may achieve what you are after.
Sub shiftdown()
' shiftdown Macro
Dim rng As Range
With ActiveSheet
If .Range("A1").Value > 0 Then
Set rng = .Range(.Cells(5, 1), _
.Cells(.Cells(.Rows.Count, 1).End(xlUp).Row, _
.Cells(4, .Columns.Count).End(xlToLeft).Column))
rng.Offset(1, 0).Value = rng.Value
.Rows(5).EntireRow.ClearContents
End If
End With
End Sub
Set rng = ActiveSheet.Range("A1").Value ???
if rng is a range, then replace it by :
Set rng = ActiveSheet.Range("A1")
or if rng is a variable, replace
Dim rng As Range
by
Dim rng As variant
rng = ActiveSheet.Range("A1").Value
another error :
you declared rng as range and then you test if it is > 0
If rng > 0 Then ...
it is not possible