I'm stuck on this, I don't understand why the code adds those extra zeros in column D; What am I doing wrong?
Code: https://pastebin.com/ccpqPJdz
last = Range("B" & Rows.Count).End(xlUp).Row
'Insert 3 columns on left. Add information in Row 1, add data in column D.
Columns("A:A").Select
Selection.Insert Shift:=xlToRight
Columns("A:A").Select
Selection.Insert Shift:=xlToRight
Columns("A:A").Select
Selection.Insert Shift:=xlToRight
Columns("E:E").Copy Destination:=Columns("C:C")
Columns("E:E").Select
Selection.Delete Shift:=xlToLeft
Range("D2:D2" & last).Select
Selection.SpecialCells(xlCellTypeBlanks).Select
Selection.FormulaR1C1 = "=R[-1]C[6]"
Columns("D").Copy
Columns("D").PasteSpecial xlPasteValues
Range("D1") = Time
Range("D1").NumberFormat = "h:mm:ss"
Input:
Output:
Avoid the Selection object. It's created as a medium of communication between the user and VBA via the screen. VBA has direct access to the Excel workbook and therefore doesn't need it. Please try this code.
Private Sub InsertThreeColumns()
Dim Rl As Long ' last used row
Dim Rng As Range
With Worksheets("NewTest") ' change to suit
Rl = .Cells(.Rows.Count, "B").End(xlUp).Row
.Columns(2).Copy
.Columns(1).Insert Shift:=xlToRight
Application.CutCopyMode = False
.Columns("A:B").Insert Shift:=xlToRight
.Columns(5).EntireColumn.Delete
On Error Resume Next
' next line will cause a crash if there are no blanks
Set Rng = .Range(.Cells(2, "D"), .Cells(Rl, "D")).SpecialCells(xlCellTypeBlanks)
If Err = 0 Then
Rng.FormulaR1C1 = "=R[-1]C[6]"
Rng.Copy
Rng.PasteSpecial xlPasteValues
End If
On Error GoTo 0
With .Cells(1, "D")
.Value = Time
.NumberFormat = "h:mm:ss"
End With
End With
End Sub
The extra zeroes that troubled you were caused by the method of defining the range where you wanted the formula to supply cell content. In your code that range is a derivative of a Selection. In the above code it's defined by starting cell and end cell. The result should be the same. It isn't because the route via the Selection object is circuitous and difficult to follow.
Related
I am trying to write a macro that removes unnecessary columns and copies/ pastes data from one column next to another. I then want it to take the worksheet name (which is variable) and concatenate it with the values in a static range of cells, but only after the columns have been modified.
The macro runs without error until the concatenate step.
Is there a better way to write this or what am I doing incorrectly? The error is "Object variable or With block not set". The error occurs at "Set rngTemp = ws.Range("A21", "H21")" line.
Thank you in advance for your consideration.
Sheets("Channel-0").Select
Range("F21:F62").Select
Selection.Delete Shift:=xlToLeft
Range("G21:H62").Select
Selection.Delete Shift:=xlToLeft
Range("H21:L62").Select
Selection.Delete Shift:=xlToLeft
Columns("G:G").Select
Range("G11").Activate
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Range("E21:E62").Select
Selection.Copy
ActiveWindow.SmallScroll Down:=-39
Range("G21").Select
ActiveSheet.Paste
Range("G19").Select
Application.CutCopyMode = False
ActiveWorkbook.Save
Dim ws As Worksheet
Dim rngCell, rngTemp As Range
Set rngTemp = ws.Range("A21", "H21")
For Each cell In rngTemp
cell.Value = ActiveSheet.Name & cell.Value
Next cell
End Sub
I currently have code that inserts two columns, and copies values from two other columns into these two new columns.
'Insert 2 Column to the Left of S
Columns("S:T").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeft
'Copy Column J into Column S
Columns("J:J").Select
Selection.Copy
Columns("S:S").Select
Selection.PasteSpecial Paste:=xlPasteValues
Selection.PasteSpecial Paste:=xlFormats
'Copy Column Q into Column T
Columns("Q:Q").Select
Selection.Copy
Columns("T:T").Select
Selection.PasteSpecial Paste:=xlPasteValues
Selection.PasteSpecial Paste:=xlFormats
However, I want to change it so that the value in Column J is only copied IF the value next to it in Column I is not "DoNotCopy" (or another specific text).
I know, as a workaround, I could insert another column and have an IF statement to only show the value if blah blah... and copy that column value over instead. But this is not as "pretty" as VBA doing the work. Or would you disagree, and this is the better way to do it?
Insert Column and Copy Conditionally to It
Sub InsertData()
Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
Dim rg As Range: Set rg = ws.UsedRange
With Intersect(rg.EntireRow, ws.Columns("S:T"))
.Insert Shift:=xlShiftToRight, CopyOrigin:=xlFormatFromLeftOrAbove
' Formats
Intersect(rg, ws.Columns("J")).Copy
.Columns(1).Offset(, -2).PasteSpecial xlPasteFormats
' Values
.Columns(1).Offset(, -2).Value = ws.Evaluate("IF(" _
& Intersect(rg, ws.Columns("I")).Address & "<>""DoNotCopy""," _
& Intersect(rg, ws.Columns("J")).Address & ","""")")
' Formats
Intersect(rg, ws.Columns("Q")).Copy
.Columns(2).Offset(, -2).PasteSpecial xlPasteFormats
' Values
.Columns(2).Offset(, -2).Value = Intersect(rg, ws.Columns("Q")).Value
Application.CutCopyMode = False
End With
End Sub
Place the IF function into your target column. This logic assumes the first row is the beginning of the data, adjust as needed.
Dim r As Range, idx As Long
'identify the last cell with a value
idx = Cells(Rows.Count, "S").End(xlUp).Row
'set the range to the target column
Set r = Range("J1:J" & idx)
'value the target column with the IF function
Cells(1, "J").Formula = "=IF(T1=""DoNotCopy"","""",S1)"
r.FillDown
r.copy
r.PasteSpecial xlPasteValues
I have a list of names vertically consisting of 500+ rows on sheet1 as follow
Bill no (002, 003) Name (john, james ) Amount (455, 55)
whereas, I have a bill invoice shaped format on sheet2 and need to substitute the sheet 1 data on it.
the below vba code works perfectly for one particular row (A3:C3) but the problem im facing is that the list on sheet1 has 500 plus rows.
so kindly help me with an alternative where I can mouse click a random cell (A3) and the vba code copies the entire row (A3:C3) from sheet1 to sheet 2 to their respective places
Sub Macro13()
'Macro13 Macro
Range("A3").Select
Selection.Copy
Sheets("Sheet3").Select
Range("C4").Select
ActiveSheet.Paste
Sheets("Sheet2").Select
Range("B3").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Sheet3").Select
ActiveCell.Offset(0, 4).Range("A1").Select
ActiveSheet.Paste
Sheets("Sheet2").Select
Range("C3").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Sheet3").Select
ActiveCell.Offset(17, 3).Range("A1").Select
ActiveSheet.Paste
Range("c4").Select
End Sub
Please, test the next code:
Sub CopyCellsSpecificPlaces()
Dim sh2 As Worksheet, sh3 As Worksheet, aC As Range
Set sh2 = Sheets("Sheet2")
Set sh3 = Sheets("Sheet3")
Set aC = ActiveCell
If (Not aC.Parent Is sh2) Or (aC.Column <> 1) Then
MsgBox "You must run the code after selecting a cell in A:A column of ""Sheet1""...": Exit Sub
End If
sh3.cells(4, "C").Value = aC.Value
sh3.cells(4, "G").Value = aC.Offset(0, 1).Value
sh3.cells(21, "J").Value = aC.Offset(0, 2).Value
End Sub
you can refer to the following code and modify as you want.
Sub Macro13()
Sheets("Sheet2").Range("A3").Copy
Sheets("Sheet3").Range("C4").Paste
Sheets("Sheet2").Range("B3").Copy
Sheets("Sheet3").Range("A5").Paste
Sheets("Sheet2").Range("C3").Copy
Sheets("Sheet3").Range("D18").Paste
End Sub
I need some advice to rectify the code below. I have this code to copy paste lines to another sheet for data compilation purpose. And I'm running well using the with statement below, the problem is, when there's no data to paste, I do not know how to end the code with message box.
I see the similar question above, but how to comply the code into the With statement of VBA below?
Following is the code I read from other user, to return message box if error.
If Err Then
MsgBox "Nothing to paste!"
Err.Clear
End If
My original code, without the Message box return.
*Sub FnLstRow()
Application.ScreenUpdating = False
Dim LR As Long
ThisWorkbook.Worksheets("Data").Select
LR = Cells(Rows.Count, "AO").End(xlUp).Row
Cells(LR, 1).Offset(1, 0).EntireRow.Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
With Sheets("LatestData")
.Cells(.Rows.Count, "A").End(xlUp).Offset(1, 0).PasteSpecial Paste:=xlPasteValues
End With
Application.CutCopyMode = False
Range("A1").Select
Application.ScreenUpdating = True
End Sub**
this is a suboptimal solution that might not work but you could try: I created a dynamic array and tried to pass your entire selection into it. If the selection had no values, it will select all of the remaining cells in the sheet, and it is likely too large to pass into the array, resulting in a run time error. I didn't touch your code except for creating the array and adding the error handling section. I hope it works lol
Sub FnLstRow()
Application.ScreenUpdating = False
Dim LR As Long
Dim Arr() As Variant
ThisWorkbook.Worksheets("Data").Select
LR = Cells(Rows.Count, "AO").End(xlUp).Row
Cells(LR, 1).Offset(1, 0).EntireRow.Select
Range(Selection, Selection.End(xlDown)).Select
On Error GoTo Handler
Arr = Selection
On Error GoTo 0
Selection.Copy
With Sheets("LatestData")
.Cells(.Rows.Count, "A").End(xlUp).Offset(1, 0).PasteSpecial Paste:=xlPasteValues
End With
Application.CutCopyMode = False
Range("A1").Select
Application.ScreenUpdating = True
Exit Sub
Handler:
MsgBox "Nothing to paste!"
End Sub
I'm trying to stop using ActiveCell etc as StackOverflow has very much declared this a "nono"
My current code is:
Sub SitesAndProd()
Set wb = ActiveWorkbook
Set ws = Worksheets("Data")
Set rng = ws.Cells(1, 13)
LastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
rng.FormulaR1C1 = "SitesAndProd" 'Rename Cell SitesAndProd
Set rng = ws.Cells(2, 13)
rng.FormulaR1C1 = "=RC[-12]&RC[-4]"
rng.Offset(0, -1).Select 'Move left 1 column
Selection.End(xlDown).Select 'Go to bottom of column
rng.Offset(0, 1).Select 'Move right 1 column
Range(Selection, Selection.End(xlUp)).Select 'Go to top of Column
Selection.FillDown 'Copy Formula Down "Fill"
Selection.Copy 'Ctrl + C
Selection.PasteSpecial xlPasteValues 'Right click + V
Application.CutCopyMode = False 'Esc (stops the crawling ants
End Sub
When using Selection.End(xlDown).Select and xlUp later - it's not saving the range position
What's the best way to make sure the range is kept here?
When using the following:
Range("M2").Select
ActiveCell.FormulaR1C1 = "=RC[-12]&RC[-4]"
Range("M2").Select
ActiveCell.Offset(0, -1).Select
Selection.End(xlDown).Select
ActiveCell.Offset(0, 1).Select
Range(Selection, Selection.End(xlUp)).Select
Selection.FillDown
The code will pull the correct form - going left 1, to the bottom, right 1, selecting up to to the, then copying down
Any chance that someone can point me in the right direction to be able to do this without ActiveCell, Selection and Select?
This is supposing the LastRow you calculated on column A equals the same amount of rows in column M
Option Explicit
Sub SitesAndProd()
Dim wb As Workbook, ws As Worksheet, LastRow As Long
Set wb = ThisWorkbook
Set ws = Worksheets("Data")
ws.Cells(1, 13) = "SitesAndProd"
LastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
With ws.Range(ws.Cells(2, 13), ws.Cells(LastRow, 13))
.FormulaR1C1 = "=RC[-12]&RC[-4]"
.Value = .Value
End With
End Sub
I've tweaked some of your code. You need to declare your variables, wb As Workbook and ws As Worksheet. If workbook is the one you got your code in, use ThisWorkbook instead ActiveWorkbook you will get less errors from that.
Edit: Try to avoid as much the global variables. Pass them on your subs or functions as variables.
I expect your code:
Range("M2").Select
ActiveCell.FormulaR1C1 = "=RC[-12]&RC[-4]"
Range("M2").Select
ActiveCell.Offset(0, -1).Select
Selection.End(xlDown).Select
ActiveCell.Offset(0, 1).Select
Range(Selection, Selection.End(xlUp)).Select
Selection.FillDown
can be replaced with:
Range(Range("M2"), Range("M" & ActiveSheet.Rows.Count).End(xlUp)).Formula = "=RC[-12]&RC[-4]"
If the column which you would like to use to determine the last filled cell is column Q:
Range(Range("M2"), Range("Q" & ActiveSheet.Rows.Count).End(xlUp).Row).Formula = "=RC[-12]&RC[-4]"