I am attempting to select a dynamic range of filtered data that spans from col. A: col. J without selecting the header (in row 1). From there I need to copy and paste it into a new sheet where I will manipulate it further, but I cannot come up with an efficient or functional way to do this. Based on some code I found on another forum I was able to select all of the "visable cells" in a single column, but I am running into issues trying to select the whole range. I am still very new to vba so forgive my syntax, but my code posted below was an attempt to itterate through Rows.Count and i which was an integer 1-10. If you have any advice on how to do this better and more efficiently I would really appreciate it.
Sub SelectVisibleInColD()
Dim lRow As Long, i As Integer
Set i = 1
Do While i <= 10
With ActiveSheet
lRow = .Cells(.Rows.Count, i).End(xlUp).Row
If lRow < 3 Then Exit Sub
.Cells(1, 1).Offset(1, 0).Resize(lRow - 1).SpecialCells(xlCellTypeVisible).Select
End With
i = i + 1
Loop
End Sub
You can select a range by using Range property of ActiveSheet. You already have the last row and you know that the header is in the first row, so your range starts from position A2 and goes to the last row of column J
ActiveSheet.Range("A2:J"&lRow).SpecialCells(xlCellTypeVisible)
If you want to copy this range, use Copy function like
yourRangeAsAbove.Copy
This function only moves the selection to memory, to paste it, build your destination range and call PasteSpecial function.
I came across this answer googling my issue for: deleting of filtered selection in vba.
However trying your answer &lRow gives me an runtime error 1004, application-defineed or object-defined error
I got around it with this
ActiveSheet.Range("A2:G" & Range("A" & Rows.Count).End(xlUp).Row).SpecialCells(xlCellTypeVisible).Delete
For those that may also get the same issue.
Related
I am trying to clear a data in a worksheet in excel using vba. I want to clear the cells with data in them, not including Row 1. I am trying to get the variable of the last row and column with data but I keep getting an out of range error.
Dim lRow As Long
Dim lCol As Long
lRow = Sheets("Sheet1").Cells(Sheets("Sheet1".Rows.Count,1).End(xlUp).Row
lCol = Sheets("Sheet1").Cells(1, Sheets("Sheet1").Columns.Count).End(xlToLeft).Column
I want to use this logic to replace what I have hard coded:
Sheets("Sheet1").Range("A2:D1000").ClearContents
I am using multiple sheets so that's why I am specifying Sheet1. How can I do this?
Thanks.
You were missing a Parenthesis in the last row line
you do not need to find the last column unless you are limiting the clear contents to preserve data.
One more thing, you are finding the last row in column A only, so if there is data in another column lower that the last one in column A, you won't clear that data.
lRow = Sheets("Sheet1").Cells(Sheets("Sheet1").Rows.Count,1).End(xlUp).Row
Sheets("Sheet1").Rows("2:" & lRow).ClearContents
Dim ws As Worksheet
set ws = Sheets ("Sheet1")
ws.Range(ws.Cells(2,1),ws.Cells(ws.UsedRange.Rows.Count,1).EntireRow.Delete
should do the trick. UsedRange tracks the smallest rectangle in the worksheet containing all cells with data and starting from A1.
My issue now is with my conditional formatting rules - they are working as expected up to a certain point in column W, which is where the cells should be either highlighted or passed over. I have included a set of data from column W and column Z (the reference data) where there are matches that are not being highlighted. In the Column W data I have bolded the numbers that should be highlighted.
Column Z - Z506-Z550
233892
233899
959460
156311
515114
549794
562793
372953
230659
230717
2051205586
364834
790760
334588
538149
288261
19326
267428
Net 90
473853
3211221994
264556
260798
156271
509597
2211211506
800990
597593
431759
377289
224118
178966
276840
430269
431923
431986
547439
512399
234975
512203
602547
443537
376759
284287
608745
Column W - W1144-W1155
233892
367164
368384
344813
233899
233899
233895
-
233917
284287
376759
443537
The conditional formatting formula I have is =VLOOKUP($W4,$Z4:$Z922,1,FALSE) 'Applies To' =$W$4:$W$3600
I am not sure what is causing this conditional formatting to fail here.
Ignore below - now working with conditional formatting instead of vba
I am trying to automate a manual process of cross referencing data and highlighting a cell if the contents are found anywhere in another column of data. However, the amount of data in both of these columns is not the same. And unfortunately, the column I need to loop through and check each cell often has either blank cells or cells that are dashed ("---").
I started with conditional formatting but it was not working properly so I am now on VBA.
Private Sub Workbook_Open()
Dim LastRow As Long
Range("W4").Select
LastRow = Range("W4").End(xlDown).Row
Do Until ActiveCell.Row = LastRow
If Not IsEmpty(Application.Match(ActiveCell.Value, Range("Z:Z"), 0))
Then
ActiveCell.Interior.Color = vbGreen
ActiveCell.Offset(1, 0).Select
End If
Loop
End Sub
Right now the code has a couple issues. It is not finding the last row correctly - when debugging it shows as 65, but should be 3,535 in the test case I'm using. Additionally, my match statement is not working, as it is highlighting every cell instead of only those whose content is found in column Z. And, it highlights up to row 410, which means my Do Until loop must be wrong as well.
After figuring out the one column I eventually need to allow checking columns AA and AB for content matches.
Thanks!
As mentioned in the comment, conditional formatting is the way to go. I just tried the following as a conditional format.
=VLOOKUP($A2,$C$2:$C$7,1,FALSE)
A column of numbers in A as the numbers to be cross-referenced, and a list in column C which are the numbers to be checked. It works perfectly.
I recommend to use Conditional Formatting. The following is just to explain what was wrong with your code:
Always define which worksheet you mean and avoid using Select in Excel VBA.
Using End(xlDown) will find the next free cell (not the last used). Instead use End(xlUp) from the very last cell of the worksheet.
Application.Match does not return a cell but a row number. Therefore IsEmpty does not work.
In the end something like this should work:
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("SheetName")
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, "W").End(xlUp).Row
Dim MatchRow As Variant
Dim iRow As Long
For iRow = 4 To LastRow
MatchRow = 0 'initialize
MatchRow = Application.Match(ws.Cells(iRow, "W").Value, ws.Range("Z:Z"), 0)
If MatchRow > 0 Then
ws.Cells(iRow, "W").Interior.Color = vbGreen
End If
Next iRow
Note that Contidional Formatting would be a much better solution.
I have a table with column A containing incrementing numerical values, and column B being a bunch of names. I need to filter the table according the names, and have column C update with the difference between the value in column A in the current row and the cell above..
For example, I'd like to have something like this
which,
when filtered according to the Name column, should update the difference like so
I have tried to use SUBTOTAL function in a few different ways but to no avail. Ideally it'd update once the filter in the table is changed. I tried to do this in VBA but so far I've gotten macro that only filters with the hard-coded filter criteria.
Solutions in either excel formulas/python/vba are all welcomed and greatly appreciated!
I apologise in advance if this question isn't up to standards as Im new here :) Thank you in advance!
#JvdV: This is the outcome of me trying to implement your formula, This is after filtering.
REVISED ANSWER
So after your explenation I have looked into a formula that will give you the difference of the current row B-value minus the B-value of occurance of the A-value before that.
=IFERROR(B2-LOOKUP(2,1/($A$1:A1=A2),$B$1:B2),0)
Taking your sample data, it would look like this:
Then when you apply the filter, it would look like this:
So with this workaround you dont have the correct value when no filter is applied, but in this case I assumed you are interested in the difference when it IS filtered!
The formula is entered in cell C2 and dragged down.
EDIT
If this is not the answer you'r after and you DO need the values when it is not filtered, make use of a UDF like below:
Public Function LastVisibleCell(CL As Range) As Long
Dim RW As Long, X As Long
RW = CL.Row - 1
On Error GoTo 1
If RW > 1 Then
For X = RW To 1 Step -1
If ActiveSheet.Rows(X).EntireRow.Hidden Then
Else
LastVisibleCell = Cells(CL.Row, 2).Value - Cells(X, 2).Value
Exit For
End If
Next X
Else
1: LastVisibleCell = 0
End If
End Function
Call it from cell C2 like: =LastVisibleCell(A2) and drag down. When you apply your filter, the cells will update.
Beware, this will take ages to update on large datasets!
After 3 days of intense (albeit ineffective) Google-ing, I finally came across this answer also on stack overflow.
However, as I'm working on a large set of data (>150,000 rows), the method in the question uses too much memory. Using VBA to paste the formulas into visible cells only does not seem to alleviate the problem.
Sub CopyPasteFormula()
Dim Ws As Worksheet
Dim LRow As Long
Dim PasteRng As Range
Set Ws = Worksheets("Translated Data")
Ws.Range("$D$2:$D$200000").AutoFilter Field:=4, Criteria1:="<>-", Operator:=xlFilterValues
LRow = Ws.Range("D" & Rows.Count).End(xlUp).Row
Set PasteRng = Ws.Range("A3:A" & LRow).SpecialCells(xlCellTypeVisible)
Ws.Range("A3").Copy
PasteRng.PasteSpecial xlPasteFormulas
Application.CutCopyMode = False
End Sub
Above is my macro code to attempt reduce the memory use... Appreciate any feedback!
I'm creating an extract in Excel with data from a datatable in my vb.net application. It extracts everything correctly. Now I'm trying to do a bit of design work to make it all pretty. It seems like I'm having an issue with probably something every easy but for some reason I keep getting the below error.
Public member 'XlDirection' on type 'ApplicationClass' not found.
My goal is to find the last row of data in Column A, and then take all cells starting A4 and do .columns.autofit on all columns starting A4 The reason why I'm doing that is because cells A1 - A3 have some long text values in them and I want them to be as they are.
Code:
Dim wSheet As Microsoft.Office.Interop.Excel.Worksheet
Dim _excel As New Microsoft.Office.Interop.Excel.Application
wSheet = wBook.ActiveSheet()
Dim lRow As Long
With wSheet
lRow = .Range("A" & .Rows.Count).End(_excel.XlDirection.xlUp).Row
.Range("A4" & lRow).Columns.AutoFit()
End With
The original error was due to the fact that XlDirection is an enumeration in the Microsoft.Office.Interop.Excel namespace - it isn't a member of Excel.Application. The bit _excel.XlDirection.xlUp should be:
Microsoft.Office.Interop.Excel.XlDirection.xlUp
The second issue is that the Range you build here...
lRow = .Range("A" & .Rows.Count).End(_excel.XlDirection.xlUp).Row
.Range("A4" & lRow).Columns.AutoFit()
...just appends a row number to the end of "A4". So if the last row was 42, the range you would auto-fit would be "A442". It needs to be ("A4:A" & lRow).
But that still only auto-fits column A. If that's your intent, stop here. If you need to auto-fit all the columns (as indicated by the phrase "all columns starting A4" - my emphasis), read on.
First, you don't need to find the last row number - you're working with Columns when you're performing your auto-fit, so Rows.Count works as well as anything else. You really need to find the right-most column, but I'd skip all of that and just offset the used range down by 3 rows:
With wSheet
.UsedRange.Offset(3).Columns.AutoFit
End With
I think this is not a too difficult task to do, but the problem is that I actually don't know anything about programming and I need to do this on my current job. This is my issue:
The problem is that I have to develop a Macro, and assign it to a button, that copies range E3:K14 from Page 1(sheet1) and paste it on A1 on Page 2(sheet2). This first task is rather easy, but the problem comes when if I hit again the button's assigned Macro it has to copy the same range from Page 1 and paste it on Page 2 but if the first has to check if there already something pasted on A1, if there is, then it must copy it on cell I1 and if I click the button again to Q1 and so on.
When the range is pasted it must be pasted with "Paste Vales" option.
If someone could just put me the exact code (with some comments if possible) for me just to paste it would be really helpful.
Any help would be really appreciated!
Try below code :
Sub sample()
With Sheets("Sheet2")
Sheets("sheet1").Range("E3:K14").Copy .Cells(.Range("A" & .Rows.End(xlUp).Row) + 1, 1)
End With
End Sub
Explanation :
Have used the Range Copy Method and provided a destination where to
paste.
.Range("A" & .Rows.End(xlUp).Row) + 1 checks for last used cell in sheet2 column A and adds 1 so that data is pasted on last used row.(Assuming the column E does not have blank cells)
Dude you can use this code to get the last column with data, this is the key for solve your problem.
Sub SelectLast()
Dim LastColumn As Long
With ActiveSheet
LastColumn = .Range("A1").SpecialCells(xlCellTypeLastCell).Column
End With
MsgBox LastColumn
Cells(18, LastColumn + 2).Select
End Sub