I am using this code which works fine, however it messes up conditional formatting in my table. Is there a way to insert a new row in table via VBA without affecting conditional formatting?
Public Sub insertRowBelow()
ActiveCell.Offset(1).EntireRow.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromRightOrBelow
ActiveCell.EntireRow.Copy
ActiveCell.Offset(1).EntireRow.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
End Sub
This Will Work:
Public Sub insertRowBelow()
ActiveCell.Offset(1).EntireRow.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
ActiveCell.EntireRow.Copy
ActiveCell.Offset(1).EntireRow.PasteSpecial xlPasteAllMergingConditionalFormats
ActiveCell.Offset(1).EntireRow.Clear
Application.CutCopyMode = False
End Sub
Try:
Option Explicit
Sub test()
'Change Sheet name if needed
With ThisWorkbook.Worksheets("Sheet1").ListObjects("Table1")
If Not Intersect(ActiveCell, .DataBodyRange) Is Nothing Then
'Change table name if needed - Insert one row above active cell
.ListRows.Add ((ActiveCell.Row - ActiveCell.ListObject.Range.Row))
'Change table name if needed - Insert one row below active cell
.ListRows.Add ((ActiveCell.Row - ActiveCell.ListObject.Range.Row + 1))
End If
End With
End Sub
Add the row only within the ListObject not within the whole sheet (see The VBA Guide To ListObject Excel Tables)
Option Explicit
Public Sub AddRowInListObject()
Dim ActTable As ListObject
On Error Resume Next 'next line throws error if ActiveCell is not in a table
Set ActTable = ActiveCell.ListObject
On Error GoTo 0 're-activate error reporting!
If Not ActTable Is Nothing Then 'only add row if ActiveCell is within a table
ActTable.ListRows.Add ActiveCell.Row - ActTable.Range.Row
End If
End Sub
Note that there are 2 differnt row counting systems:
ActiveCell.Row which returns the absolute row number of the worksheet
ListRows.Add which awaits the row number relatively to the beginning of the ListObject
So for example if the ListObject starts in row 5 of the worksheet then row number 1 of the ListObject is row number 5 of the worksheet.
Related
I would like the user to be able to click the green button on the right of each named range to insert a new data entry row below the named range header. The code I have hard codes the insert row number for the first named range. I need a way to have the code to be smart enough to know that the first row below the header of the second, third, & forth named range will changed.
Another big part is that the inserted row needs to have the same formatting (dropdowns, formulas, color, etc.) as the rows below.
First named range button code:
Sub BidSheetAddRow_Materials()
' BidSheetAddRow_Materials Macro
Rows("19:19").Select
Selection.Copy
Rows("19:19").Select
Selection.Insert Shift:=xlDown
Range("A19").Select
Application.CutCopyMode = False
Selection.ClearContents
Range("C19").Select
Selection.ClearContents
Range("K19").Select
Selection.ClearContents
End Sub
Based on the screenshot all table headers are in colA, the first input row is 3 cells below the header, and the first input cell on each table row is a merged cell.
So this works for me:
Sub AddMaterial()
AddRow "MATERIALS"
End Sub
Sub AddRate()
AddRow "RATE"
End Sub
Sub AddRow(TableHeader As String)
Dim f As Range, ws As Worksheet, c As Range
Set ws = ThisWorkbook.Worksheets("Input") 'or whatever
Set f = ws.Columns("A").Find(what:=TableHeader, lookat:=xlWhole) 'find the header
If Not f Is Nothing Then
Set c = f.Offset(3) 'step down to first input row below header
Do While c.Offset(1).MergeArea.Cells.Count > 1 'keep looping while `c` is merged
Set c = c.Offset(1)
Loop
c.Offset(1).EntireRow.Insert shift:=xlDown 'insert
c.EntireRow.Copy c.Offset(1) 'copy
c.Offset(1).EntireRow.ClearContents 'clear new row
Else
MsgBox "Table header '" & TableHeader & "' not found!"
End If
End Sub
Before/after:
I am attempting to create a new column on a different sheet and then copy data into that column.
Below is the code I have written. The first sub is a new column to the left and the second sub is the column to the right.
The insert column part is working. I hid a column and have a cell in there as a named range which I used to select in my macro. The data I want to copy is on the Input sheet and is named InputData.
Dim sourceSheet As Worksheet
Set sourceSheet = ActiveSheet
Sheets("Data").Activate
Sheets("Data").Range("DividerColumn").Select
Selection.EntireColumn.Offset(0, 0).Insert Shift:=xlToLeft
'Sheets("Input").Activate
'Range("InputData").Copy
'Sheets("Data").Activate
'ActiveCell offset maybe?
'Range().PasteSpecial xlPasteValues
Call sourceSheet.Activate
End Sub
Dim sourceSheet As Worksheet
Set sourceSheet = ActiveSheet
Sheets("Data").Activate
Sheets("Data").Range("DividerColumn").Select
Selection.EntireColumn.Offset(0, 1).Insert Shift:=xlToRight
Call sourceSheet.Activate
End Sub
Oh I didn't see your copy range. In that case this could probably work. I see you just got the answer, but this would be a good way to avoid select.
Sub copyToLeft()
Call doTheCopy(False)
End Sub
Sub CopyToRight()
Call doTheCopy(True)
End Sub
Private Sub doTheCopy(goRightIsTrue As Boolean)
With Sheets("Data").Range("DividerColumn").EntireColumn.Offset(0, IIf(goRightIsTrue, 1, 0))
.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
.Offset(0, -1).Value = Sheets("Input").Range("InputData").EntireColumn.Value
End With
End Sub
I found the solution by using an offset function. Below is my code. Hope this helps someone with a similar situation.
Dim sourceSheet As Worksheet
Set sourceSheet = ActiveSheet
Sheets("Data").Activate
Sheets("Data").Range("DividerColumn").Select
Selection.EntireColumn.Offset(0, 0).Insert
Shift:=xlToLeft
Sheets("Input").Activate
Range("InputData").Copy
Sheets("Data").Activate
Range("DividerColumn").Select
ActiveCell.Offset(0, -1).PasteSpecial
xlPasteValues
Call sourceSheet.Activate
End Sub
-1 in the offset function moves your active cell to the left one cell and then 1 moves it to the right. So once the column is created, either right or left, my macro goes and copies the information and then goes back to the sheet I want it to and selects my named range again and then it gets moved to the left and pastes my data.
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...
I'm looking for a VBA Macro script that will locate the last row in a worksheet and then insert a new row below it, copying only the format and formula from the row above without the text. I've been able to get so far as locating the last row and copying the entire cell above, text included, but have not been able to figure out the last part of not carrying over the text.
I'm wondering if there isn't some way to macro the process of creating the new row at the end of the sheet and then recreating the formula in that row?
Any help is greatly appreciated!
This is what I have so far that works:
Sub New_Formatted_Row_With_Formula
'Locates Last Cell
Cells(Rows.Count, 1).End(xlUp).Offset(1,0).Select
'Inserts Row Below
Rows(Selection.Row).Insert shift:=xlDown
End Sub
Sub New_Formatted_Row_With_Formula()
Dim rActive As Range
Set rActive = ActiveCell
Application.ScreenUpdating = False
With Cells(Rows.Count, "A").End(xlUp)
.EntireRow.Copy
With .Offset(1, 0).EntireRow
.PasteSpecial xlPasteFormats
.PasteSpecial xlPasteFormulas
On Error Resume Next
.SpecialCells(xlCellTypeConstants).ClearContents
On Error GoTo 0
End With
End With
rActive.Select
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
I'm stuck with this problem. I need to run a macro that will do the following:
Find the last line in a table on the worksheet called "Baseline".
Add a row to that table
Copy the formats and formulas (but not values) from the row above to the new row.
Repeat the process for the other worksheets (called Quarter 1, Quarter 2 etc), that have the same structure as the worksheet called Baseline.
My problem is that the process only seems to work on the first worksheet, Baseline, but not on any of the other worksheets. I wonder if the problem is the way I have tried to get the code to copy formulas and formats only.
Here is the code, just for the Baseline and Quarter 1 worksheets:
Public Sub AddRow()
On Error GoTo errhandler
Worksheets("Baseline").Activate
'Find Last Row in Service User Details
Dim rgeLastRowBaseline As Range
Set rgeLastRowBaseline = ActiveWorkbook.Worksheets("Baseline").Cells.Find("Cost")
' Select and Copy Last Row
rgeLastRowBaseline.End(xlDown).EntireRow.Select
Selection.Offset(1).EntireRow.Insert
rgeLastRowBaseline.End(xlDown).EntireRow.Select
Selection.Copy
rgeLastRowBaseline.End(xlDown).Offset(1).EntireRow.Select
rgeLastRowBaseline.End(xlDown).Offset(1).EntireRow.PasteSpecial
Application.CutCopyMode = False
Selection.SpecialCells(xlCellTypeConstants, 23).Select
Selection.ClearContents
'Quarter 1
Worksheets("Quarter 1").Activate
Dim rgeLastRowQ1 As Range
Set rgeLastRowQ1 = ActiveWorkbook.Worksheets("Quarter 1").Cells.Find("Cost")
' Select and Copy Last Row
rgeLastRowQ1.End(xlDown).EntireRow.Select
Selection.Offset(1).EntireRow.Insert
rgeLastRowQ1.End(xlDown).EntireRow.Select
Selection.Copy
rgeLastRowQ1.End(xlDown).Offset(1).EntireRow.Select
rgeLastRowQ1.End(xlDown).Offset(1).EntireRow.PasteSpecial
Application.CutCopyMode = False
Selection.SpecialCells(xlCellTypeConstants, 23).Select
Selection.ClearContents
Exit Sub
errhandler:
Application.CutCopyMode = False
End Sub
Does anyone have any suggestions please?
Thanks
You'll need to use Worksheet type variables. I did not correct your technical solutions even though I don't completely agree with selecting everything.
Sub onesheet(ws As Worksheet)
On Error GoTo errhandler
ws.Activate
Dim rgeLastRowQ1 As Range
Set rgeLastRowQ1 = ws.Cells.Find("Cost")
' Select and Copy Last Row
rgeLastRowQ1.End(xlDown).EntireRow.Select
Selection.Offset(1).EntireRow.Insert
rgeLastRowQ1.End(xlDown).EntireRow.Select
Selection.Copy
rgeLastRowQ1.End(xlDown).Offset(1).EntireRow.Select
rgeLastRowQ1.End(xlDown).Offset(1).EntireRow.PasteSpecial
Application.CutCopyMode = False
Selection.SpecialCells(xlCellTypeConstants, 23).Select
Selection.ClearContents
Exit Sub
errhandler:
Application.CutCopyMode = False
End Sub
Sub sheetloop()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
If ws.Name = "Baseline" Or ws.Name Like "Quarter*" Then Call onesheet(ws)
Next ws
End Sub