'Find & Copy Column for Actual Curtailed
Dim ws As Worksheet
Set ws = Worksheets("Report")
Range("A2:AC2").Find(What:="Actual Curtailed").ActiveCell.Select
Range("S20") = Application.WorksheetFunction.Sum(ws.Range(Column(ActiveCell.Column))).Copy
This code brings a compile error, I am presuming that I am doing some wrong by summing the column with where the active cell is.
I am trying to fine "actual curtailed", get the column number, and put the summation of that column in row S20.
Thanks
This code will do what you intend.
Dim SumClm As Variant
Dim SumRng As Range
With Worksheets("Report")
SumClm = Application.Match("Actual Curtailed", .Rows(2), 0)
If Not IsError(SumClm) Then
' from row 3 to the end of the column
Set SumRng = .Range(.Cells(3, SumClm), .Cells(.Rows.Count, SumClm).End(xlUp))
.Cells(20, "S").Value = WorksheetFunction.Sum(SumRng)
End If
End With
If the column isn't found S20 will remain blank.
I just did few edits to your code
Dim ws As Worksheet
Set ws = Worksheets("Report")
Range("A2:AC2").Find(What:="Actual Curtailed").Activate
Range("S20") = WorksheetFunction.Sum(Columns(ActiveCell.Column))
I've been struggling with this all day and I'm sure there's a really simple answer that I'm just not finding so hoping someone can point me in the right direction!
What I want to achieve is:
see if a value (R.BName) from sheet1 (wsResults) can be found in column c of sheet2 (wsSchedule);
if found, paste a value from sheet1 (that I've already copied) into
the next empty cell of that row;
if not found, insert a value into a specific cell in sheet1
The 2 issues I'm having are that:
If there is a match - the paste location is the last cell in row1 - yes, I know that this be because my code has (1,columns.count) but I don't know how to get it to select the cell of the match!
"broker name not found on review schedule" is being added to wsResults even if a match was on wsSchedule
Here is my defective code:
'copy result from wsresults
wsResults.range("R.Result").Copy
'find broker & add result to review schedule sheet
Dim wsSchedule As Worksheet
Dim rSearch As range
Dim c As range
Set wsSchedule = Worksheets("Review Schedule")
Set rSearch = wsSchedule.range("C5:C400")
For Each c In rSearch
If c.Value = wsResults.range("R.BName").Value Then
wsSchedule.Cells(1, Columns.count).End(xlToLeft).Offset(0, 1).PasteSpecial xlPasteValues
Else
With wsResults
.range("AP2:AP2").Value = "Broker name not found on review schedule"
End With
End If
Next c
Any assistance that can be offered would be greatly appreciated!
I believe this is what you had in mind. Please try it.
Sub Test()
' 009
Dim wsSchedule As Worksheet
Dim wsResults As Worksheet
Dim searchCrit As Variant
Dim lastR As Long
Dim R As Long
Set wsSchedule = Worksheets("Review Schedule")
Set wsResults = Worksheets("Results")
' try to access sheet values as little as possible: it's slow
' here, once is enough. No need to do it on every loop
searchCrit = wsResults.Range("R.BName").Value
With wsSchedule
lastR = .Cells(.Rows.Count, "C").End(xlUp).Row
For R = 5 To lastR
If .Cells(R, "c").Value = searchCrit Then
.Cells(R, Columns.Count).End(xlToLeft).Offset(0, 1) = wsResults.Range("R.Result")
Exit For
End If
Next R
End With
' R will be <=lastR if a match was found
If R > lastR Then
wsResults.Cells(2, "AP").Value = "Broker name not found on review schedule"
End If
End Sub
However, #SJR is right: using Find in place of the loop would be more efficient.
I want to copy all filled cells starting from C5 to column F of a different worksheet.
I referred to another post: Excel - Combine multiple columns into one column
Modified the code based on my needs.
Sub CombineColumns()
Dim Range1 As Range, iCol As Long, Range2 As Range, Check As Range, wks As Worksheets
Set Range1 = wks("T(M)").Range(Cells(5, 3), Cells(Cells(5, 3).End(xlDown).Row, Cells(5, 3).End(xlToRight).Column))
Set Check = wks("csv").Range("F1")
If IsEmpty(Check.Value) = True Then
Set Range2 = Check
Else
LastRow = wks("csv").Range("F" & Rows.Count).End(xlUp).Row
Set Range2 = wks("csv").Cells(LastRow, 6).Offset(1, 0)
End If
For iCol = 3 To Range1.Columns.Count
wks("T(M)").Range(Cells(5, iCol), Cells(Range1.Columns(iCol).Rows.Count, iCol)).Copy
wks("csv").Range2.PasteSpecial Paste:=xlPasteValuesAndNumberFormats
Next iCol
End Sub
But I kept getting the error message
"object doesn't support this method or property"
at the step of pasting. After I tried to qualify all the ranges, It says I didn't set the object variable.
Thank you so much for the help!
How about this?
Sub Transposes()
' Example just for hardcoded data
Dim inputRange As Range
Set inputRange = Sheets("Sheet1").Range("C5:F10").SpecialCells(xlCellTypeConstants)
Dim outputCell As Range
Set outputCell = Sheets("Sheet2").Range("A1")
Dim cell As Range
For Each cell In inputRange
Dim offset As Long
outputCell.offset(offset).Value = cell.Value
offset = offset + 1
Next cell
End Sub
Set the last row in ColumnF to be whatever you want, and if that changes dynamically, just use any one of the multiple techniques out there to find the last cell you need to copy/paste.
I'm begginer in VBA and looking for a solution to check something in a table. I would like to create a function that tells if cells in a certain column (range) is not empty only then if the cell in the title column (range) equals something. I tried with a combination of isempty and vlookup but it didn't work.
I hope the description is clear, anyway I attached a simplified table with the problem. Thank you in advance!
enter image description here
Not sure i have understood your problem 100% but lets begin with what i think i understood, and start with the below:
Sub isitEmpty()
With Sheets("Sheet1")
If IsEmpty(.Range("B1:E2")).Value Then
'do something
Else
'do something
End If
End With
End Sub
What do you want to do if the cell is/isnot empty?
Below code works with following assumptions:
Project Type are listed in Column A starting from Cell A4
A,B,C,D category could vary but will always have headings in Row 3
Project Type for which you want the participation as Y, are listed in a column that appear after the last column with headings A,B,C,D. So as per your image its Column F
Sub Demo()
Dim ws As Worksheet
Dim lRProject As Long, lRMatch As Long, lastColumn As Long, i As Long
Dim rngProject As Range, celPro As Range, rngMatch As Range, celMatch As Range
Set ws = ThisWorkbook.Sheets("Sheet5") 'change to your sheet
With ws
lastColumn = .Cells(3, Columns.count).End(xlToLeft).Column 'gives last column with A,B,C,D
lRProject = .Cells(.Rows.count, "A").End(xlUp).Row 'last row in Column A
lRMatch = .Cells(.Rows.count, lastColumn + 1).End(xlUp).Row 'last row in Column F
Set rngMatch = .Range(.Cells(1, lastColumn + 1), .Cells(lRMatch, lastColumn + 1))
Set rngProject = .Range("A4:A" & lRProject)
For Each celMatch In rngMatch
For Each celPro In rngProject
For i = 2 To lastColumn
If celPro.Value = celMatch Then
If .Cells(celPro.Row, i) = "X" Then
.Cells(celMatch.Row, i) = "Y"
End If
End If
Next i
Next celPro
Next celMatch
End With
End Sub
See image for reference.
I'm having a little trouble with finding the last row.
What I am trying to do is find the last row in column "A", then use that to find the last row within a range.
Example of Data:
1) LR_wbSelect = wbshtSelect.cells(Rows.count, "A").End(xlUp).Row - 22
2) LR_wbSelectNew = wbshtSelect.cells(LR_wbSelect, "A").End(xlUp).Row
I am using the last row in column "A" as the data from row 29 down will always be the same length, the rows used in column "B" from row 29 can be a varying number of rows.
So I am trying to use LR_wbSelect in column "A" to get my starting last Row, then within LR_wbSelectNew using it as the starting point to look up from.
This works when the column I set to "A", LR_wbSelectNew gives me the row of "17", but when I change the column in LR_wbSelectNew to "B" it doesn't give the correct last row of "18".
I can change the column to "C, D, E, F" and the code works fine, but the only column that I can use is "B" because it will always have data in it, where the rest of that row could have a blank cell.
After doing some testing on the sheet, by pressing CRTL & Up from the lastring point of LR_wbSelect column "B" ignores the data in the rows and go to the row where it find data. I can't see a reason why Excel doesn't think there is data in these cells?
There are mulitple results and methods when searching for the LastRow (in Column B).
When using Cells(.Rows.Count, "B").End(xlUp).Row you will get the last row with data in Column B (it ignores rows with spaces, and goes all the way down).
When using:
With wbshtSelect.Range("B10").CurrentRegion
LR_wbSelectNew = .Rows(.Rows.Count).Row
End With
You are searching for the last row with data in Column B of the CurrentRegion, that starts from cell B10, untill the first line without data (it stops on the first row with empty row).
Full Code:
Sub GetLastRow()
Dim wbshtSelect As Worksheet
Dim LR_wbSelectNew As Long
' modify "Sheet2" to your sheet's name
Set wbshtSelect = Sheets("Sheet2")
' find last row with data in Column B
With wbshtSelect
LR_wbSelectNew = .Cells(.Rows.Count, "B").End(xlUp).Row
End With
' for debug only
Debug.Print LR_wbSelectNew ' >>result 31
' find last row with data in Column B at current regioun starting at cell B10
With wbshtSelect.Range("B10").CurrentRegion
LR_wbSelectNew = .Rows(.Rows.Count).Row
End With
' for debug only
Debug.Print LR_wbSelectNew ' >> result 18
End Sub
Edit1: code searches for last row for cells with values (it ignores blank cells with formulas inside).
Sub GetLastRow()
Dim wbshtSelect As Worksheet
Dim LR_wbSelectNew As Long
' modify "Sheet2" to your sheet's name
Set wbshtSelect = Sheets("Sheet2")
' find last row with data in Column B at current regioun starting at cell B10
With wbshtSelect.Range("B10").CurrentRegion
LR_wbSelectNew = .Rows(.Rows.Count).Row
End With
Dim Rng As Range
Set Rng = wbshtSelect.Range("B10:B" & LR_wbSelectNew)
' find last row inside the range, ignore values inside formulas
LR_wbSelectNew = Rng.Find(What:="*", _
After:=Range("B10"), _
LookAt:=xlPart, _
LookIn:=xlValues, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
' for debug
Debug.Print LR_wbSelectNew ' << result 18 (with formulas in the range)
End Sub
Hope this piece of code helps !
Sub LastRowInOneColumn()
'Find the last used row in a Column: column A in this example
Dim LastRow As Long
With ActiveSheet
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
MsgBox LastRow
End Sub
I came here looking for a way to find the last row in a non-contiguous range. Most responses here only check one column at a time so I created a few different functions to solve this problem. I will admit, though, that my .Find() implementation is essentially the same as Shai Rado's answer.
Implementation 1 - Uses Range().Find() in reverse order
Function LastRowInRange_Find(ByVal rng As Range) As Long
'searches range from bottom up stopping when it finds anything (*)
Dim rngFind As Range
Set rngFind = rng.Find( What:="*", _
After:=rng.Parent.Cells(rng.row, rng.Column), _
LookAt:=xlWhole, _
LookIn:=xlValues, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious)
If Not rngFind Is Nothing Then
LastRowInRange_Find = rngFind.row
Else
LastRowInRange_Find = rng.row
End If
End Function
Implementation 2 - Uses Range().End(xlUp) on each column
Function LastRowInRange_xlUp(ByVal rng As Range) As Long
Dim lastRowCurrent As Long
Dim lastRowBest As Long
'loop through columns in range
Dim i As Long
For i = rng.Column To rng.Column + rng.Columns.count - 1
If rng.Rows.count < Rows.count Then
lastRowCurrent = Cells(rng.row + rng.Rows.count, i).End(xlUp).row
Else
lastRowCurrent = Cells(rng.Rows.count, i).End(xlUp).row
End If
If lastRowCurrent > lastRowBest Then
lastRowBest = lastRowCurrent
End If
Next i
If lastRowBest < rng.row Then
LastRowInRange_xlUp = rng.row
Else
LastRowInRange_xlUp = lastRowBest
End If
End Function
Implementation 3 - Loops through an Array in reverse order
Function LastRowInRange_Array(ByVal rng As Range) As Long
'store range's data as an array
Dim rngValues As Variant
rngValues = rng.Value2
Dim lastRow As Long
Dim i As Long
Dim j As Long
'loop through range from left to right and from bottom upwards
For i = LBound(rngValues, 2) To UBound(rngValues, 2) 'columns
For j = UBound(rngValues, 1) To LBound(rngValues, 1) Step -1 'rows
'if cell is not empty
If Len(Trim(rngValues(j, i))) > 0 Then
If j > lastRow Then lastRow = j
Exit For
End If
Next j
Next i
If lastRow = 0 Then
LastRowInRange_Array = rng.row
Else
LastRowInRange_Array = lastRow + rng.row - 1
End If
End Function
I have not tested which of these implementations works fastest on large sets of data, but I would imagine that the winner would be _Array since it is not looping through each cell on the sheet individually but instead loops through the data stored in memory. However, I have included all 3 for variety :)
How to use
To use these functions, you drop them into your code sheet/module, specify a range as their parameter, and then they will return the "lowest" filled row within that range.
Here's how you can use any of them to solve the initial problem that was asked:
Sub answer()
Dim testRange As Range
Set testRange = Range("A1:F28")
MsgBox LastRowInRange_Find(testRange)
MsgBox LastRowInRange_xlUp(testRange)
MsgBox LastRowInRange_Array(testRange)
End Sub
Each of these will return 18.
If your wbshtSelect is defined as worksheet and you have used set to define the specific worksheet, you can use this.
Dim LastRow As Long
wbshtSelect.UsedRange ' Refresh UsedRange
LastRow = wbshtSelect.UsedRange.Rows(wbshtSelect.UsedRange.Rows.Count).Row
Otherwise take a look here http://www.ozgrid.com/VBA/ExcelRanges.htm
LR_wbSelectNew = wbshtSelect.cells(LR_wbSelect, "B").End(xlUp).Row
Why are you using "LR_wbSelect" as the row counter? If you want to know the last row of column 'B', you should use Rows.count
Rows.count --> Returns maximum number of rows (which is 1048576 for Excel 2007 and up)
End(xlUp) --> Moves the pointer upward to the last used row
So,
cells(Rows.count, "A").End(xlUp).Row --> This moves the pointer to the last row if the column 'A' (as if you are pressing Crtl+Up keys when A1048576 cell is selected)
So, use Rows.count to select the last row for column 'B' as well. If you have some specific requirement related to LR_wbSelect, please mention it.
Alternatively, if you want to know the last row used in a sheet, you may use the below:
mySheet.Cells.SpecialCells(xlCellTypeLastCell).Row
LR_wbSelect = ThisWorkbook.Sheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row
Simple function that return last row no. in specific sheet.
It takes the last address in UsedRange and retrieve last row number.
Feel to free change the code and use standard range insead of UsedRange.
Function FindLastRow(wsToCheck As Worksheet) As Long
Dim str As String
str = wsToCheck.UsedRange.AddressLocal()
FindLastRow = Right(str, InStr(1, StrReverse(str), "$") - 1)
End Function
Range().End will bring you to the end of a code block. If the starting cell is empty, it brings you the the first used cell or the last cell. It the cells is not empty it brings you to the last used cell. For this reason, you need to test whether or not the cell in column B is to determine whether to use LR_wbSelectNew as the last row.
With wbshtSelect
LR_wbSelect = .Cells(Rows.Count, "A").End(xlUp).Row - 22
If .Cells(LR_wbSelect, "B") <> "" Then
LR_wbSelectNew = LR_wbSelect
Else
LR_wbSelectNew = .Cells(LR_wbSelect, "B").End(xlUp).Row
End If
End With
This code defines a Target range that extends from A1 to the last row in column a - 22 and extends 10 columns.
Dim Target As Range
With wbshtSelect
Set Target = .Range("A1", .Cells(Rows.Count, "A").End(xlUp).Offset(-22)).Resize(, 10)
End With
'This is sure method to find or catch last row in any column even 'if some cell are blank in-between. (Excel-2007)`
'This works even if sheet is not active
'mycol is the column you want to get last row number
for n=1048575 to 1 step -1
myval=cells(n,mycol)
if myval<>"" then
mylastrow=n 'this is last row in the column
exit for
end if
next
ret=msgbox("Last row in column-" & mycol & "is=" & mylastrow)
Dim rng As Range
Dim FirstRow, LastRow As long
Set rng = Selection
With rng
FirstRow = ActiveCell.Row
LastRow = .Rows(.Rows.Count).Row
End With
Shai Rado's first solution is a great one, but for some it might need a bit more elaboration:
Dim rngCurr, lastRow
rngCurr = wbshtSelect.Range("B10").CurrentRegion
lastRow = rngCurr.Rows(rngCurr.Rows.Count).Row
If you want to know the last used row in the entire worksheet:
Dim rngCurr, lastRow
rngCurr = Range("A1").CurrentRegion
lastRow = rngCurr.Rows(rngCurr.Rows.Count).Row
Backing off from the range to the worksheet will get you the whole sheet extents of the range used on the sheet (which may be smaller than you expect if the sheet doesn't have data in the top rows; but it does include internal blanks)
TheRange.Worksheet.UsedRange.Rows.Count
If there is no data in the top rows, the following will get you the first row which you need to add to the above to get the highest row number
TheRange.End(xlDown).Row
So
Dim TheRange as Range
Dim MaxRow as Long
MaxRow = TheRange.Worksheet.UsedRange.Rows.Count + TheRange.End(xlDown).Row
Will get the highest row number with data (but not the whole sheet)
Before getting into complex coding why not build something on the below principle:
MaxRow = Application.Evaluate("MIN(ROW(A10:C29)) + ROWS(A10:C29) - 1")