Populate a range when cell value is changed (VBA) - excel

Update
I was able to get the code to run, but I still think i'm doing something wrong. It's not copying and pasting the right value, just pasting the original value over and over. New code below.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Set KeyCells = Range("X2")
Dim rb As Worksheet
Set rb = ThisWorkbook.Worksheets("RB_Cur")
Dim dp As Worksheet
Set dp = ThisWorkbook.Worksheets("Dispatch Plan")
If Not Application.Intersect(KeyCells, Range(Target.Address)) _
Is Nothing Then
dp.Range("V4:V16").ClearContents
With rb.Range("E1:AA1000" & rb.Range("E" & Rows.Count).End(xlUp).Row)
.AutoFilter Field:=1, Criteria1:=dp.Range("X2").Value
.AutoFilter Field:=7, Criteria1:=dp.Range("W1").Value
If .SpecialCells(xlCellTypeVisible).Count > 0 Then
rb.Range("AA1").Offset(1).Resize(10, 1).Copy
dp.Range("V4").PasteSpecial xlPasteValues
End If
End With
End If
End Sub
Original Post
I am trying to create a table where someone can input a route number into a cell and it will populate with the stops on that route. However, i'm running into some trouble getting the stop list to populate when the cell value is changed.
Picture example: When the highlighted cell (X2) is changed, I have a code that searches it in a different sheet and copies over the stops into the Stop column. The code to lookup and copy works, but it doesn't change when the number is changed.
RouteLookup code (this works)
Sub RouteLookup()
Dim rb As Worksheet
Set rb = ThisWorkbook.Worksheets("RB_Cur")
Dim dp As Worksheet
Set dp = ThisWorkbook.Worksheets("Dispatch Plan")
With rb.Range("E1:AA1000" & rb.Range("E" & Rows.Count).End(xlUp).Row)
.AutoFilter Field:=1, Criteria1:=dp.Range("X2").Value, Criteria1:="EARLY BIRD"
If .SpecialCells(xlVisible).Count > 0 Then
rb.Range("AA1").Offset(1).Resize(10, 1).Copy Destination:=dp.Range("V4")
End If
.AutoFilter Field:=1
End With
End Sub
Worksheet SelectionChange code - Whenever I try to test it, it pops up a box asking me to select the macro. I don't understand why because the code calls the RouteLookup already.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("X2")) Is Nothing Then
Application.EnableEvents = False
Call RouteLookup
Application.EnableEvents = True
End If
End Sub

Related

VBA code to automatically copy a row and paste to another sheet based off one columns entry

First of all I am super new to VBA and coding in general, however, I am building an excel workbook to automatically transfer a row in a table based off a single cell in a row. when this happens I need it to copy only the values in the cells as I have several formulas. when the copy paste operation is done I need to delete the row and re-order everything to the top while not deleting the formulas of the row. below is what I have got so far which mostly works for what I need. the only issues are it copies the entire row so I cant have a merged group of cells to the right of the row and it deletes the formulas from the cells.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 8 Then
If Target = "COMPLETED" Then
Set Tbl = Sheets("PMI ARCHIVE").ListObjects("Table3")
Tbl.ListRows.Add
nxtTblRow = Tbl.ListColumns(9).Range.Rows.Count
Target.EntireRow.Copy _
Destination:=Tbl.Range(nxtTblRow, 1)
Application.EnableEvents = False
Target.Row.ClearContents
Application.EnableEvents = True
Range("A1", Range("A1").End(xlDown)).Sort Key1:=Range("A1"), Order1:=xlAscending, Header:=xlYes
End If
End If
End Sub
Try the next code, please. It assumes that you need to copy all existing values of the Target row and then clear contents of the cells not having a formula:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim arrCopy As Variant, lastColT As Long
If Target.Column = 8 Then
If Target = "COMPLETED" Then
Set tbl = Sheets("PMI ARCHIVE").ListObjects("Table3")
tbl.ListRows.aDD
nxtTblRow = tbl.ListColumns(9).Range.Rows.Count
lastColT = Cells(Target.row, Columns.Count).End(xlToLeft).Column
arrCopy = Range(Target.row, lastColT).Value
tbl.Range(nxtTblRow, 1).Resize(, UBound(arrCopy, 2)).Value = arrCopy
Application.EnableEvents = False
Range(Target.row, lastColT).SpecialCells(xlCellTypeConstants).ClearContents
Application.EnableEvents = True
'If in column A:A, an empty cell will exist (because of the above code), the range will be set up to that empty cell.
'The next way, goes to the last cell:
Range("A1", Range("A" & Rows.Count).End(xlUp)).Sort Key1:=Range("A1"), _
Order1:=xlAscending, Header:=xlYes
End If
End If
End Sub
I am not sure you need to sort only A:A column, but I kept the code as it was, from this point of view...

How do I print/save only the visible columns and rows to an XLSX file in VBA?

I have a macro-enabled spreadsheet that allows me to hide various columns and rows based on certain criteria I select and trigger on the sheet.
First I select the relevant columns by marking that column with a "Y", and hiding the remaining columns with a "N" with the following routine:
Sub Hidecolumn()
Dim p As Range
For Each p In Range("H1:BN1").Cells
If p.Value = "N" Then
p.EntireColumn.Hidden = True
End If
Next p
End Sub
Please note that Columns("A:G") will always be visible. Only Columns("H:BN") can be hidden based on the above. This works perfectly.
Then, I will hide the the various rows that do not have a value in the remaining visible columns for Columns("H:BN"), which is 59 possible columns. If any column within that row has a value, then that row will remain visible. If there are NO values in any of the visible columns for that row, then I hide that row. It is entirely possible that the 59 columns could reduce to 7. I do this with the following routine:
Sub HideRowsSecond()
Module2.Unhiderow
Dim srcRng As Range, ws As Worksheet
Set ws = ActiveSheet
Set srcRng = ws.Rows("5:" & ws.Cells(ws.Rows.Count, 4).End(xlUp).Row)
Dim R As Range, hideRng As Range
For Each R In srcRng
If Application.CountA(R.Columns("H:BN").SpecialCells(xlCellTypeVisible)) = 0 Then
If hideRng Is Nothing Then
Set hideRng = R.EntireRow
Else
Set hideRng = Application.Union(hideRng, R.EntireRow)
End If
End If
Next R
If Not hideRng Is Nothing Then hideRng.EntireRow.Hidden = True
MsgBox ("Complete")
End Sub
Please note that the starting row is Row("5"), and we use Column("D") as the counting column because it has a value in every cell down to the bottom of the data set. This works perfectly.
Now that I have my desired data set, I need to save this visible data set to a new XLSX file that the user can name themselves and save in the directory of their choice. The target range will begin with cell "C3" and we need to save however many visible columns there are to the right and however many visible rows there are down to the bottom of the data set.
Can someone please help me with this final step?
Here is the solution.
Sub exportToFile()
Dim rng As Range
With ActiveSheet
Set rng = Application.Intersect(.UsedRange, .Cells.Resize(.Rows.Count - 2, .Columns.Count - 2).Offset(2, 2))
End With
rng.Select
rng.SpecialCells(xlCellTypeVisible).copy
Workbooks.Add
Selection.PasteSpecial Paste:=xlPasteColumnWidths, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
ActiveSheet.Paste
Range("A" & Row & ":N" & Row).EntireRow.AutoFit
ActiveSheet.Range("A1").Select
Application.Dialogs(xlDialogSaveAs).Show ("c:\")
End Sub

Automatically creating worksheets based on a list in excel

I want to create a new sheet(Slave) with the name as entered in the cells A5:A50 in (master) sheet and copy the contents of the (template)sheet in the newly created slave sheet. I have got one program as below which closely matched with my requirement but 1) it doesnt take new values which i edit and create a new slave in the range provided i.e it is not dynamic and 2) i want to run the macro everytime i enter the value in the specified range.
Help would be highly appreciated
Sub CreateAndNameWorksheets()
Dim c As Range
Application.ScreenUpdating = False
For Each c In Sheets("Master").Range("A5:A50")
Sheets("Template").Copy After:=Sheets(Sheets.Count)
With c
ActiveSheet.Name = .Value
.Parent.Hyperlinks.Add Anchor:=c, Address:="", SubAddress:= _
"'" & .Text & "'!A1", TextToDisplay:=.Text
End With
Next c
Application.ScreenUpdating = True
End Sub
Put this code in the "Master" Sheet, every time you change a cell in the Range("A5:A50") it will run the desired code
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If (Target.Parent.Name = Range("A1:A50").Parent.Name) Then
Dim ints As Range
Set ints = Application.Intersect(Target, Range("A5:A50"))
If (Not (ints Is Nothing)) Then
'insert code here
End If
End If
End Sub

Filter cells using cell value as reference

i need to filter an excel worksheet using a cell value as reference..
Right now what i found was using vba, so this is my code
Private Sub Worksheet_Change(ByVal Target As Range)
If (Intersect(Target, Range("f2")) Is Nothing) _
Then
Exit Sub
End If
Cells.AutoFilter Field:=2, Criteria1:=Range("f2").Value
End Sub
But everytime i change value of cell f2 it hides all cells and excel crashes, somehow...
So what i need is:
Use cell f2 as reference for criteria, to filter data in range a1:d100, so that when value in cell f2 changes, a1:d100 only shows lines in which the the criteria is true...
field 2 is the description of a product, like a computer, so every time i write in f2 the text "HP", it show only HP computers for example...
Thanks to all, but i solved my problem, if anyone is interested here is my code
Private Sub Worksheet_Change(ByVal Target As Range)
If (Intersect(Target, Range("f1")) Is Nothing) _
Then
Exit Sub
End If
Cells.AutoFilter Field:=2, Criteria1:="*" & Range("f1")
Cells.AutoFilter Field:=2, Criteria1:="*" & Range("f1") & "*"
End Sub
Try the following:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Tbl As Range
Set Tbl = Range("A1:D100")
If Intersect(Range("F2"), Target) Is Nothing Then Exit Sub
Tbl.AutoFilter Field:=2, Criteria1:=Range("F2").Value
End Sub
NOTE: The filter may hide row #2. This may make it a little difficult to change cell F2.

Does vba care about autofilter?

If I apply auto-filter on my input sheet and then run VBA code, the code does not care about the auto-filter.
But, sometimes running VBA code on an auto-filtered sheet messes up the results of the program.
So, my question is; does VBA care about auto-filter?
For example:
Sub check()
Dim rng as range
Set rng = Sheets("input").Range("A1")
row = 0
Do until rng.offset(row,0) = ""
row = row + 1
Loop
End Sub
In the above code, VBA does not care if auto-filter is applied on column A, and it still iterates through all the rows. However, if I try to write on cells where there is auto-filter, it messes up.
VBA Doesn't care about Autofilter unless you "tell it" to or are trying to perform actions which can get affected by the Autofilter.
Your above code will work with any sheet and not just with "Input" Sheet.
Here is another method where it works beautifully (in fact I use it all the time)
'~~> Remove any filters
ActiveSheet.AutoFilterMode = False
'~~> Filter, offset(to exclude headers) and delete visible rows
With rRange
.AutoFilter Field:=1, Criteria1:=strCriteria
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
'~~> Remove any filters
ActiveSheet.AutoFilterMode = False
And here is a scenario when it doesn't work.
Charts don't show data which were filtered by Autofilter. But then the chart also doesn't show data which is present in hidden rows. This applies to both VBA and Non VBA methods of showing data in the chart.
but if i try to write on particular cells where autofiler is applied it messes up.
It depends on how and where you are writing it.
This works very nicely. Note in the below code, row has been filtered and is not visible. However, we can still write to it.
Option Explicit
Sub Sample()
Dim rng As Range
Set rng = Sheets("Sheet1").Range("A1")
rng.AutoFilter Field:=1, Criteria1:="<>1", Operator:=xlAnd
rng.Offset(1, 0).Value = "Sidd"
End Sub
Now let's take another case. This will not work. Let's say you have a range A2 to A10 (A1 has Header) which has various values ranging from 1 to 3. Now you want to replace all the values in A2:A10 by say 1000. This code will not give you the expected output if there is an Autofilter. It will not change all the cells.
Option Explicit
Sub Sample()
Dim rng As Range
Set rng = Sheets("Sheet1").Range("A1:A10")
rng.AutoFilter Field:=1, Criteria1:="<>1", Operator:=xlAnd
rng.Value = "1000"
End Sub
Why does it ignore the cells which have "1" (i.e the rows which were filtered out) and writes to rest of the rows? In fact it messes up with the header as well???
It's quite simple. The idea of having Autofilter is get the relevant data as per what our requirement is (at the moment it is data which is <> 1). When you write to the range rng then it will write to all cells which are visible (including the cell which has header) in that range.
So what do we do in this case?
You have two options
1) Remove the Autofilter - Do the necessary actions - Put the filter back
Sub Sample()
Dim rng As Range
Set rng = Sheets("Sheet1").Range("A1:A10")
'~~> Put Filter
rng.AutoFilter Field:=1, Criteria1:="<>1", Operator:=xlAnd
'~~> Remove Filter
ActiveSheet.AutoFilterMode = False
'~~> Write value to the cells (See how we ignore the header)
Sheets("Sheet1").Range("A2:A10").Value = "1000"
'~~> Put Filter back
rng.AutoFilter Field:=1, Criteria1:="<>1", Operator:=xlAnd
End Sub
2) Loop the range as you did in your question
Sub Sample()
Dim rng As Range, cl As Range
Set rng = Sheets("Sheet2").Range("A1:A10")
rng.AutoFilter Field:=1, Criteria1:="<>1", Operator:=xlAnd
For Each cl In rng
'~~> Ignoring the Header
If cl.Row <> 1 then _
cl.Value = "1000"
Next
End Sub
When you run the above code, it writes to all the cells except the header.
I would recommend you to read Excel's inbuilt help to understand how AutoFilters actually work. That would help you understand them which will in turn help you handle sheets which have Autofilter turned on.
HTH

Resources