I have the code working exactly the way I'd like to, however I don't want it to skip onto another column. I just want my macro to run inside column C then exit.
I am new to VBA in excel, so please pardon my faults.
Any help would be much appreciated.
Thanks in advance.
Sub CopyValuetoRange()
'
' CopyValuetoRange Macro
Dim search_range As Range, Block As Range, last_cell As Range
Dim first_address$
Set search_range = ActiveSheet.UsedRange
Set Block = search_range.Find(what:="*", _
after:=search_range.SpecialCells(xlCellTypeLastCell), _
LookIn:=xlValues, searchorder:=xlColumns, searchdirection:=xlDown)
If Block Is Nothing Then Exit Sub
Set Block = Block.CurrentRegion
first_address$ = Block.Address
Do
Block.Select
Selection.End(xlDown).Select
ActiveCell.CurrentRegion.Rows(2).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.FormulaR1C1 = "=R[-1]C"
'MsgBox "Next Block Range"
Set last_cell = Block.Cells(Block.Rows.Count)
Set Block = search_range.FindNext(after:=last_cell).CurrentRegion
Loop Until Block.Address = first_address$ 'ActiveSheet.Range("C26").End(xlDown).Row
End Sub
Here is something I modified from something I found that will essentially do the same thing, however it puts the first cells value into all cells in the range. And this macro actually stays in Column C, since I found recently because it's not a region, it's a range.
Is there a way to change the following to add a formula to all cells in the range that points to the first cell in the range?
Sub Macro5()
Dim Rng As Range
Dim RngEnd As Range
Dim rngArea As Range
Set Rng = Range("C1")
Set RngEnd = Cells(Rows.Count, Rng.Column).End(xlDown)
If RngEnd.Row < Rng.Row Then Exit Sub
Set Rng = Range(Rng, RngEnd)
On Error GoTo ExitSub
Set Rng = Rng.SpecialCells(xlCellTypeConstants)
For Each rngArea In Rng.Areas
rngArea.Value = rngArea.Cells(Rng.Rows.Count, 1).Value
Next rngArea
ExitSub:
' Macro will exit here if the range is empty.
End Sub
How about you change your search_range, so that you only search Column C?
Set search_range = ActiveSheet.Range("C:C")
Set Block = search_range.Find(what:="*", _
LookIn:=xlValues, searchorder:=xlColumns, searchdirection:=xlDown)
Here's what I have, it's not pretty but it works. I added a column on both sides then removed them after the macro went through the entire column:
Sub CopyFirstCellInRangeInOneColumn()
'
' CopyValuetoRange Macro
Dim search_range As Range, Block As Range, last_cell As Range
Dim first_address$
''
Columns("C:C").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Columns("E:E").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
''
Set search_range = ActiveSheet.Range("D:D")
Set Block = search_range.Find(what:="*", _
LookIn:=xlValues, searchorder:=xlColumns, searchdirection:=xlDown)
'Set search_range = ActiveSheet.UsedRange
'Set Block = search_range.Find(What:="*", _
' After:=search_range.SpecialCells(xlCellTypeLastCell), _
' LookIn:=xlValues, SearchOrder:=xlColumns, SearchDirection:=xlDown)
If Block Is Nothing Then Exit Sub
Set Block = Block.CurrentRegion
first_address$ = Block.Address
Do
Block.Select
Selection.End(xlDown).Select
ActiveCell.CurrentRegion.Rows(2).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.FormulaR1C1 = "=R[-1]C"
MsgBox "Next Block Range"
Set last_cell = Block.Cells(Block.Rows.Count)
Set Block = search_range.FindNext(After:=last_cell).CurrentRegion
Loop Until Block.Address = first_address$ 'ActiveSheet.Range("C26").End(xlDown).Row
Columns("C:C").Select
Selection.Delete Shift:=xlToLeft
Columns("D:D").Select
Selection.Delete Shift:=xlToLeft
End Sub
Related
I have 2 wb to_update_example_1 and purchasing_list
basically what I am trying to do is to a loop row by row on workbook to_update_example_1 if the same name is found to copy the a variable to the purchasing_list workbook.
However it keeps giving me error 91 at the searching portion and I would need an advice how do I write vVal2(which is the Qty) to Purchasing list workbook the column is just beside the found name so I tried to use active cell offset but didn't work too
any advice is appreciated thanks
Sub Macro1()
Application.ScreenUpdating = False
Dim x As Integer
Dim vVal1, vVal2 As String
Numrows = Range("A1", Range("A1").End(xlDown)).Rows.Count ' Set numrows = number of rows of data.
Range("A1").Select ' Select cell a2.
For x = 1 To Numrows ' Establish "For" loop to loop "numrows" number of times.
vVal1 = Cells(x, 8)
vVal2 = Cells(x, 7)
Windows("Purchasing List.xls").Activate
ActiveSheet.Cells.Find(What:=vVal1, After:=ActiveCell, LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Row
''write to Qty cell beside the found name ActiveCell.Offset(0, -2) = vVal2
Windows("To_update_example_1.xlsm").Activate
''''''''ActiveCell.Offset(1, 0).Select
Next
Application.ScreenUpdating = True
End Sub
When using the Find function, it's recommended if you set a Range object to the Find result, and also prepare your code for a scenario that Find didn't find vVal1 in "Purchasing List.xls" workbook. You can achieve it by using the following line If Not FindRng Is Nothing Then.
Note: avoid using Select, Activate and ActiveSheet, instead fully qualify all your Objects - see in my code below (with comments).
Modified Code
Option Explicit
Sub Macro1()
Application.ScreenUpdating = False
Dim x As Long, Numrows As Long
Dim vVal1 As String, vVal2 As String
Dim PurchaseWb As Workbook
Dim ToUpdateWb As Workbook
Dim FindRng As Range
' set workbook object of "Purchasing List" excel workbook
Set PurchaseWb = Workbooks("Purchasing List.xls")
' set workbook object of "To_update_example_1" excel workbook
Set ToUpdateWb = Workbooks("To_update_example_1.xlsm")
With ToUpdateWb.Sheets("Sheet1") ' <-- I think you are trying to loop on "To_update_example_1.xlsm" file , '<-- change "Sheet1" to your sheet's name
' Set numrows = number of rows of data.
Numrows = .Range("A1").End(xlDown).Row
For x = 1 To Numrows ' Establish "For" loop to loop "numrows" number of times
vVal1 = .Cells(x, 8)
vVal2 = .Cells(x, 7)
' change "Sheet2" to your sheet's name in "Purchasing List.xls" file where you are looking for vVal1
Set FindRng = PurchaseWb.Sheets("Sheet2").Cells.Find(What:=vVal1, LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns)
If Not FindRng Is Nothing Then '<-- make sure Find was successful finding vVal1
' write to Qty cell beside the found name ActiveCell.Offset(0, -2) = vVal2
' Not sure eactly what you want to do now ???
Else ' raise some kind of notification
MsgBox "Unable to find " & vVal1, vbInformation
End If
Next x
End With
Application.ScreenUpdating = True
End Sub
Edited to account for OP's comment about where to search and write values
ShaiRado already told you where the flaw was
here's an alternative code
Option Explicit
Sub Macro1()
Dim cell As Range, FindRng As Range
Dim purchListSht As Worksheet
Set purchListSht = Workbooks("Purchasing List.xls").Worksheets("purchaseData") '(change "purchaseData" to your actual "purchase" sheet name)
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
With Workbooks("to_update_example_1").Sheets("SourceData") ' reference your "source" worksheet in "source" workbook (change "SourceData" to your actual "source" sheet name)
For Each cell In .Range("H1", .Cells(.Rows.Count, 8).End(xlUp)).SpecialCells(xlCellTypeConstants) ' loop through referenced "source" sheet column "H" not empty cells
Set FindRng = purchListSht.Columns("G").Find(What:=cell.Value, LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns) ' try finding current cell content in "purchase" sheet column "G"
If Not FindRng Is Nothing Then FindRng.Offset(, -2).Value = cell.Offset(, -1).Value ' if successful, write the value of the cell one column left of the current cell to the cell two columns to the left of found cell
Next
End With
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
I am using the following code to loop through sheets 1-31 filtering each sheet by the value in a cell("E1") in sheets("RunFilter_2") and then copy the filtered range and copy to the next empty row in sheets("RunFilter_2").
The code errors when it doesn't find the value of sheets("RunFilter_2").Range("E1") in column 18 of the active sheet.
So I added a range check, that checks if sheets("RunFilter_2").Range("E1").Value is found in column Range("R:R").
But, how do I move to the Next I If rngFound Is Nothing?
Sub RunFilter2()
Rows("5:5").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Delete Shift:=xlUp
Range("A1").Select
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
Set ws = wb.sheets("01")
Dim WS_Count As Integer
Dim I As Integer
WS_Count = ActiveWorkbook.Worksheets.Count - 3
For I = 1 To WS_Count
Dim LastRow As Long
LastRow = ActiveSheet.UsedRange.Rows.Count
sheets(I).Select
Columns("A:U").Select
Dim rng As Range
Dim rngFound As Range
Set rng = Range("R:R")
Set rngFound = rng.Find(sheets("RunFilter_2").Range("E1").Value)
If rngFound Is Nothing Then
'----------------------------------
' How do I code ... GO TO Next I
'----------------------------------
Else:
Selection.AutoFilter
ActiveSheet.Range("$A$1:$U" & LastRow).AutoFilter Field:=18, Criteria1:=sheets("RunFilter_2").Range("E1").Value
Range("A1").Offset(1, 0).Select
Rows(ActiveCell.Row).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
sheets("RunFilter_2").Select
If Range("A4").Value = "" Then
Range("A4").Select
Else
Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Select
End If
ActiveSheet.Paste
ws.Select
Application.CutCopyMode = False
Selection.AutoFilter
Range("A1").Select
sheets("RunFilter_2").Select
Next I
End Sub
You can do it like this:
For I = 1 To WS_Count
If rngFound Is Nothing Then goto NextIPlace
your code
NextIPlace:
Next I
But you should reconsider writing like this, it is not a good VBA practice to use GoTo. The whole code should be changed. Check more here. Once your code works, feel free to submit it at https://codereview.stackexchange.com/, they would give you good ideas.
There is no need to use GoTo here. The simple way to accomplish this is with the following:
For I = 1 To WS_Count
' do stuff
If Not rngFound is Nothing
'execute desired action
End If
' do more stuff
Next i
You can also place the do more stuff inside the first if block if needed. The code in your post was kind of messy and I didn't take time to dissect fully.
Place some label before Next I:
NextI:
Next I
Then you can do this:
If rngFound Is Nothing Then
Goto NextI
Else
....
Alternatively you can simplify it without needing the else statement
If rngFound Is Nothing Then Goto NextI
.... ' Proceed without the need for `Else` and `End If`
EDIT.. Some more
While it is generally considered bad programming practice to use Goto statements, it is not the case in this specific situation. It is just used as a workaround for the lack of the continue statement that exists in the C and derived languages.
you should add a marker before Next I
MARKER:
Next I
So after If rngFound Is Nothing Then you add GoTo MARKER
I'm trying to write a macro to do the following:
from Sheet1 watch the A column for the data I input;
when I write something in a cell in the A column use that value to filter Sheet2;
after the filter is done, copy everything except the column header from the second sheet into the first one, even if there are multiple values.
I tried writing this:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Set KeyCells = Range("A:A")
If Not Application.Intersect(KeyCells, Range(Target.Address)) _
Is Nothing Then
copy_filter Target
End If
End Sub
Sub copy_filter(Changed)
Set sh = Worksheets("Sheet2")
sh.Select
sh.Range("$A$1:$L$5943") _
.AutoFilter Field:=3, _
Criteria1:="=" & Changed.Value, _
VisibleDropDown:=False
Set rang = sh.Range("$A$1:$L$5943") _
.SpecialCells(xlCellTypeVisible)
rang.Offset(0, 0).Select
Selection.Copy
Worksheets("Sheet1").Select
Worksheets("Sheet1").Range(Changed.Address).Offset(0, 1).Select
Selection.PasteSpecial Paste:=xlPasteValues
sh.Range("$A$1:$L$5943").AutoFilter
Application.CutCopyMode = False
End Sub
However when I copy the selection the header row gets copied as well, but using .Offset(1, 0) cuts the header and 1 additional row and doesn't account for cases when the filter returns no results.
How can I select every filtered rows except for the header?
Use sh.UsedRange will give you a dynamic range. Where as, sh.Range("$A$1:$L$5943") will not shrink and grow to match your dataset.
We can trim the header row off like this:
Set rang = sh.UsedRange.Offset(1, 0)
Set rang = rang.Resize(rang.Rows.Count - 1)
But SpecialCells(xlCellTypeVisible) will throw a No cells were found. error if there is no data to return. So we'll have to trap the error like this:
On Error Resume Next
Set rang = rang.SpecialCells(xlCellTypeVisible)
If Err.Number = 0 Then
End If
On Error GoTo 0
Sub copy_filter(Changed)
Dim rang As Range
Set sh = Worksheets("Sheet2")
sh.UsedRange.AutoFilter Field:=3, _
Criteria1:="=" & Changed.Value, _
VisibleDropDown:=False
Set rang = sh.UsedRange.Offset(1, 0)
Set rang = rang.Resize(rang.Rows.Count - 1)
On Error Resume Next
Set rang = rang.SpecialCells(xlCellTypeVisible)
If Err.Number = 0 Then
rang.Copy
Worksheets("Sheet1").Range(Changed.Address).Offset(0, 1).PasteSpecial Paste:=xlPasteValues
End If
On Error GoTo 0
sh.Cells.AutoFilter
Application.CutCopyMode = False
End Sub
i need some help as i am experienceing a problem, pretty new to VBA. i want to copy that data from L5-L18, excluding some cells and paste it to column B of sheet(In) and create a button that every time i push it to copy the data from column B ,sheet(Data) to the sheet(in) and move columnto the right. like first time column b, next time column c...every time i push the button.. much appreciated
Sub Macro2()
Sheets("Data").Select
Range("L5,L6,L7,L8,L9,L10,L13,L14,L15,L16,L17,L18").Select
Range("L18").Activate
Selection.Copy
Sheets("In").Select
Range("B5").Select
ActiveSheet.Paste
Range("B5").Offset(0, 1).Select
End Sub
Method A
To insert into column B and shift everything else to the right try this:
Sub offsetCol()
Dim wksData As Worksheet
Set wksData = Sheets("Data")
Dim wksIn As Worksheet
Set wksIn = Sheets("In")
Application.CutCopyMode = False
Columns("B:B").Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
wksIn.Range("B5:B10").Value = wksData.Range("L5:L10").Value
wksIn.Range("B11:B16").Value = wksData.Range("L13:L18").Value
End Sub
Method B
Find last column in sheet and tack on information to next available:
Sub offsetCol()
Dim wksData As Worksheet
Set wksData = Sheets("Data")
Dim wksIn As Worksheet
Set wksIn = Sheets("In")
Set rLastCell = wksIn.Cells.Find(What:="*", After:=wksIn.Cells(1, 1), LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False)
wksIn.Range(Cells(5, rLastCell.Column + 1), Cells(10, rLastCell.Column + 1)).Value = wksData.Range("L5:L10").Value
wksIn.Range(Cells(11, rLastCell.Column + 1), Cells(16, rLastCell.Column + 1)).Value = wksData.Range("L13:L18").Value
End Sub
Method C
Find last column in row 5 and tack on info in next available column:
Sub offsetCol()
Dim wksData As Worksheet
Set wksData = Sheets("Data")
Dim wksIn As Worksheet
Set wksIn = Sheets("In")
Dim rLastCol As Integer
rLastCol = wksIn.Cells(5, wksIn.Columns.Count).End(xlToLeft).Column + 1
wksIn.Range(Cells(5, rLastCol), Cells(10, rLastCol)).Value = wksData.Range("L5:L10").Value
wksIn.Range(Cells(11, rLastCol), Cells(16, rLastCol)).Value = wksData.Range("L13:L18").Value
End Sub
Starting Data:
Results (Method C):
Part of the question - copy from location A to location B, is not very clear, but I am guessing this is what you need. Put this under a macro of a button:
Sub Macro2()
Dim rng As Range
Sheets("IN").Range("B:B").Insert Shift:=xlToRight
Sheets("Data").Select
Set rng = Range("L5,L6,L7,L8,L9,L10,L13,L14,L15,L16,L17,L18")
rng.Copy Sheets("IN").Range("B:B")
End Sub
Please advise me how to change my code to select rows only if they have a value in BC column (ignore complete row if cell in BC column is blank):
Private Sub CommandButton3_Click()
Range("A:a,b:b,c:c,e:e,bc:bc").Select
Selection.Copy
Workbooks.Add
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=True, Transpose:=False
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, SkipBlanks:=True, Transpose:=False
End Sub
First run your code as is. Then perform the row deletions in the added workbook:
Sub dural()
Dim N As Long, I As Long, r As Range
N = Cells(Rows.Count, "BC").End(xlUp).Row
For I = N To 1 Step -1
Set r = Cells(I, "BC")
If IsEmpty(r) Then
r.EntireRow.Delete
End If
Next
End Sub
You could do this by using a filter:
Filter on column BC by unchecking (Blanks)
Copy the columns
Paste into a new worksheet or workbook
If it has to be VBA, here are two codes that will perform as desired.
This first code uses the autofilter:
Private Sub CommandButton3_Click()
Dim wsData As Worksheet
Dim wsNew As Worksheet
Set wsData = ActiveSheet
Set wsNew = Sheets.Add
With Intersect(wsData.UsedRange, wsData.Columns("BC"))
.Parent.AutoFilterMode = False
.AutoFilter 1, "<>"
Intersect(.SpecialCells(xlCellTypeVisible).EntireRow, wsData.Range("A:A,B:B,C:C,E:E,BC:BC")).Copy
wsNew.Range("A1").PasteSpecial xlPasteValues
wsNew.Range("A1").PasteSpecial xlPasteFormats
.AutoFilter
End With
wsNew.Move
Set wsData = Nothing
Set wsNew = Nothing
End Sub
This second, alternative code uses a find loop:
Private Sub CommandButton3_Click()
Dim rngFound As Range
Dim rngCopy As Range
Dim strFirst As String
Set rngFound = Columns("BC").Find("*", Cells(Rows.Count, "BC"), xlValues, xlWhole)
If Not rngFound Is Nothing Then
strFirst = rngFound.Address
Set rngCopy = rngFound
Do
Set rngCopy = Union(rngCopy, rngFound)
Set rngFound = Columns("BC").Find("*", rngFound, xlValues, xlWhole)
Loop While rngFound.Address <> strFirst
End If
If Not rngCopy Is Nothing Then
Sheets.Add
Intersect(rngCopy.Parent.Range("A:A,B:B,C:C,E:E,BC:BC"), rngCopy.EntireRow).Copy
Range("A1").PasteSpecial xlPasteValues
Range("A1").PasteSpecial xlPasteFormats
ActiveSheet.Move
End If
Set rngFound = Nothing
Set rngCopy = Nothing
End Sub