Automatically Insert Row in Another Sheet If a row is added - excel

I have tables CustomerTable in Sheet1, and SalesTable in Sheet2.
CustomerTable has Customer_Code column (Col A), the formula is:
=[#[CustomerName ]] & [#[No order ]]
I want every time a new row is added in CustomerTable, the new record of Customer_Code in CustomerTable's Col A is added in SalesTable.
Like this:
MA18209 in CustomerTable's Col A appears in the last row of Customer_Code col (Col B) in SalesTable.
Code in Sheet1:
Sub CopyCustomerCode()
Dim A As String
Dim ws As Worksheet
Set ws = Sheets("Sheet2")
Dim otherRow As Long
otherRow = ws.Range("B" & Rows.Count).End(xlUp).Row + 1
ws.Cells(otherRow, 1).Value = b
End Sub
It does nothing.
The desirable state is for Excel to automatically copy the value in Col A, not by clicking a macro button.

How the row in CustomerTable is added? By inserting new row in the top of the table? Or by writing new info at the bottom and letting excel format is as new row?
You could write a macro for creating new row in CustomerTable and SalesTable at once. For some reason I like then newest entry is on top of the table so I always make button for inserting new rowo in row 2.
This code would add new row to SalesTable with on click_event (if your tables formatted as tables). If you want to avoid on click completely, you could try to use worksheet_change event.
Sub CopyCustomerCode()
Dim ws As Worksheet
Dim ws As Worksheet
Dim newRow As ListRow
Dim SalesTable As ListObject
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
'your table name here
Set SalesTable = ws2.ListObjects("Sales_Table")
'lines for determining last rows
With SalesTable.Range
LastRow .Rows(.Rows.Count).Row
End With
'add new row to bottom of the table
Set newRow = SalesTable.ListRow.Add
'copy info from column A in CustomerTable to SalesTable
With newRow
'if inserted row is row 2
.Range(2) = ws1.Range("A2").Value
End With
End Sub
Code for inserting new row for CustomerTable in row 2
Sub New_Row2()
Dim ws1 As Worksheet
Set ws1 = Sheets("Sheet1")
With ws1.Range("A2")
.EntireRow.Insert Shift:xlDown, CopyOrigin:xlFormatFromRightOrBelow
End With
End Sub
EDIT: If new entries in CutomerTable are added in the bottom, you could try finding last row of CustomerTable and using it in .Range(2) line.
Code should look something like this (you would have to add it to button_click procedure):
Sub CopyCustomerCode()
Dim ws As Worksheet
Dim ws As Worksheet
Dim newRow As ListRow
Dim CustomerTable As ListObject
Dim SalesTable As ListObject
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
'your table name here
Set SalesTable = ws2.ListObjects("Sales_Table")
'your table name here
Set CustomerTable = ws1.ListObjects("Cutomer Table")
'lines for determining last rows
With SalesTable.Range
LastRow = .Rows(.Rows.Count).Row
End With
With CustomerTable.Range
LastCusRow = .Rows(.Rows.Count).Row
End With
'add new row to bottom of the table
Set newRow = SalesTable.ListRow.Add
'copy info from column A in CustomerTable to SalesTable
With newRow
.Range(2) = ws1.Cells(LastCusRow, "A").Value
End With
End Sub

Related

Use VBA to copy entire row from one excel worksheet to another if match is not found in Column A

I have been running into some issues trying to use VBA to compare 2 tables in different worksheets, and then copy any rows in the "Master" sheet that are not found in the "New" sheet. Both tables are formatted as tables. The match is based on an "ID" column in Column A of both tables. If an ID is in the "Master" sheet, but not in the "New" sheet, than that entire row should be copy and pasted to the end of the table in the "New" sheet.
I updated some code found in another forum, which is almost working. However, it only seems to paste over the ID data into Column A, and not the entire corresponding row of data which is needed.
Sub compare()
Dim i As Long
Dim lrs As Long
Dim lrd As Long
With Worksheets("Master")
lrs = .Cells(.Rows.Count, 1).End(xlUp).Row
For i = 2 To lrs 'assumes header in row 1
If Application.IfError(Application.Match(.Cells(i, 1), Worksheets("New").Columns(1), 0), 0) = 0 Then
lrd = Worksheets("New").Cells(Worksheets("test").Rows.Count, 1).End(xlUp).Row
Worksheets("New").Cells(lrd + 1, 1).Value = .Cells(i, 1).Value
End If
Next i
End With
End Sub
I think the issue has to do with the "Cells" reference, instead of a range, but I do not know how to make that line dynamic.
Slightly different approach, but you need to use something like Resize() to capture the whole row, and not just the cell in Col A.
Sub compare()
Const NUM_COLS As Long = 10 'for example
Dim wb As Workbook, wsSrc As Worksheet, wsDest As Worksheet
Dim c As Range, cDest As Range
Set wb = ThisWorkbook 'or ActiveWorkbook for example
Set wsSrc = wb.Worksheets("Master")
Set wsDest = wb.Worksheets("New")
Set cDest = wsDest.Cells(Rows.Count, 1).End(xlUp).Offset(1) 'next empty row
For Each c In wsSrc.Range("A2:A" & wsSrc.Cells(Rows.Count, 1).End(xlUp).Row).Cells
If IsError(Application.Match(c.Value, wsDest.Columns(1), 0)) Then
cDest.Resize(1, NUM_COLS).Value = c.Resize(1, NUM_COLS).Value
Set cDest = cDest.Offset(1) 'next row
End If
Next c
End Sub

VBA Copy Pivot Data to next blank cell in column

A pivot table has been created and I need a macro that can pick up the Pivot body data, with no filters, from a specified worksheet (Pivot1) and copy the results into another sheet (Selection) on the next blank cell.
I've used and modified the below, which I found on this site, however its not picking up my sheets and I get a runtime error '424'
Any ideas on how this can be executed?
Sub PastePivot()
Dim i As Long
Dim LR As Long
Dim j As Long
Dim c As Long
'Find last used row in Pivot1
LR = Pivot1.Cells(Pivot1.Rows.Count, 1).End(xlUp).Row
'Find last used row in Selection
j = Selection.Cells(Selection.Rows.Count, 1).End(xlUp).Row
'Loop through rows on Pivot1
For i = 3 To LR
'Decide whether to copy the row or not
If Pivot1.Cells(i, 1).Value <> "0" Then
'Update pointer to the next unused row in Selection
j = j + 1
'Only copy used columns, to stop it thinking every cell in the
'destination row is "used"
c = Pivot1.Cells(i, Pivot1.Columns.Count).End(xlToLeft).Column
'Copy the values (without using Copy/Paste via the clipboard)
Selection.Rows(j).Resize(1, c).Value = Pivot1.Rows(i).Resize(1, c).Value
End If
Next i
End Sub
If you want to get the body of a pivot table use it's DataBodyRange property.
The below code assumes you have 1 pivot table on 'Sheet1' and you want to copy it to 'Sheet2'.
Sub CopyPivotBody()
Dim ws As Worksheet
Dim pt As PivotTable
Dim rngBody As Range
Set ws = Sheets("Sheet1")
Set pt = ws.PivotTables(1)
Set rngBody = pt.DataBodyRange
rngBody.Copy Sheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Offset(1)
End Sub
Note, if that doesn't give you the exact range you want you can offset/resize it like any other range.

Create sheets based on unique values in rows based on Primary Key

I am trying to populate multiple sheets based on the given data (attached Samplesheet SampleSheet.xlsx) as per the below rules:
Customer Code is the primary key, there should be each sheet for each unique customer code.
The new sheets should be named as "CustomerCode_Leads"
Every worksheet should have same headers.
I have started up with a logic and build a code behind but am lacking the knowledge on how to read the customer code data line by line, copy the rows with the same customer code and paste it in the sheet based on unique customer code.
Code written so far:
Sub Test()
Dim ws1 As Worksheet
Set ws1 = ThisWorkbook.Worksheets("Data")
ws1.Copy ThisWorkbook.Sheets(Sheets.Count)
Selection.AutoFilter
Selection.End(xlDown).Select
ActiveCell.Offset(1, 0).Select
ActiveCell.EntireRow.Select
Selection.Delete Shift:=xlUp
Application.Goto Reference:="R2C2"
ActiveCell.EntireColumn.Select
Selection.Copy
Sheets.Add After:=ActiveSheet
ActiveSheet.Paste
Application.CutCopyMode = False
ActiveSheet.Range("$A$1:$A$5000").RemoveDuplicates Columns:=1, Header:=xlYes
Dim CurSheet As Worksheet
Dim Source As Range
Dim c As Range
Set CurSheet = ActiveSheet
Set Source = Selection.Cells
Application.ScreenUpdating = False
For Each c In Source
sName = Trim(c.Text)
If Len(sName) > 0 Then
Worksheets.Add After:=Worksheets(Worksheets.Count)
ActiveSheet.Name = sName + "_Leads"
End If
Next c
End Sub
Output Desired:
Can someone advise how to read the data row by row and paste it in a new worksheet named "CustomerCode_Lead" where "CustomerCode" is a variable with some values in the Data sheet.
The algorithm that I am following is:
Copy the datasheet and paste it into a new worksheet
Sort the data in ascending order based on Customer Code (it'll bring all the similar customer code together and ease the row by row reading)
Read the data row by row and copy the entire row and paste into a new sheet until the customer code stays the same, once different code arrives in the next row, it creates a new sheet named "CustomerCode_Leads"
Do the reading of data until the end of the data in the "Data" sheet.
I would absolutely thank you in advance for the help I'll get here from the community. :)
This is all you need:
Get all unique values of customer ID column
Filter data and copy to another sheet
It could look like below:
Option Explicit
Public Sub SplitDataByCustomerIntoSheets()
Dim wsData As Worksheet
Set wsData = ThisWorkbook.Worksheets("Data")
Dim LastRow As Long
LastRow = wsData.Cells(wsData.Rows.Count, "A").End(xlUp).Row
'creat unique list of customer codes (https://stackoverflow.com/questions/36044556/quicker-way-to-get-all-unique-values-of-a-column-in-vba)
Dim UniqueValues() As Variant
UniqueValues = wsData.Range("A2:A" & LastRow).Value
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
Dim iRow As Long
For iRow = 1 To UBound(UniqueValues)
dict(UniqueValues(iRow, 1)) = Empty
Next
UniqueValues = WorksheetFunction.Transpose(dict.Keys())
'check if filter was already set
If wsData.FilterMode = False Then
wsData.Range("A1").AutoFilter
Else
wsData.ShowAllData
End If
Dim CustomerID As Variant
For Each CustomerID In UniqueValues 'loop through all customer IDs
With wsData.Range("A1:B" & LastRow) 'make sure to adjust B to the last column of your data
.AutoFilter Field:=1, Criteria1:=CustomerID 'filter by customer ID
'create a new sheet as last sheet and name it by customer ID
Dim NewSheet As Worksheet
Set NewSheet = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count))
NewSheet.Name = CustomerID & "_Leads"
'copy visible cells of filtered data to new sheet
.SpecialCells(xlCellTypeVisible).Copy NewSheet.Range("A1")
End With
Next CustomerID
End Sub
Data sheet:
It will create a sheet for each customer ID like this:

Copy cell values from one worksheet to another

I want to:
check cells in column E on sheet1 starting at ("E3")
if not empty, copy cell ("E3") to sheet2 on ("B21") and repeat with cell below them (E4, E5, ...) in sheet1 and (B22, B23, ...) sheet2, until cell on sheet1 (Ex) is empty.
write "complete" on sheet2 below last (Bx)
This code does not copy cell to sheet2.
Sub bla()
Set ar1 = Worksheets("sheet1").Range("E3")
Set ar2 = Worksheets("sheet2").Range("B21")
Do While Not IsEmpty(ar1)
Range(ar1).Copy Worksheets("sheet2").Range("ar2")
Set dr1 = ar1.Offset(1, 0)
Set dr2 = ar2.Offset(1, 0)
Set ar1 = dr1
Set ar2 = dr2
Loop
ar1.Value = "Complete"
End Sub
Try this code. It avoids loops and may be more simple to maintain/understand. End(xlDown) is the equivalent of using Ctrl + Down Arrow on keyboard against a range.
Sub bla()
Dim ws1 as Worksheet, ws2 as Worksheet
Set ws1 = Worksheets("Sheet1")
Set ws2 = Worksheets("Sheet2")
Dim copyRange as Range
With ws1
Set copyRange = .Range(.Range("E3"),.Range("E3").End(xlDown))
End With
With ws2.Range("B21")
.Resize(copyRange.Rows.Count).Value = copyRange.Value
.End(xlDown).Offset(1).Value = "Complete"
End With
End Sub
If i understood your code you can try this code:
I supposed that you can have the empty row in column E of the sheet1 and you don't want copy it in the sheet2...
Execute the macro in the sheet1
Sub test()
Dim ws2 As Worksheet
Dim numRowSheet1, rowSheet2, i As Long
Set ws2 = Worksheets("sheet2")
rowSheet2 = 21 'start from row 21 (sheet2)
'count how many rows there are in column E
numRowSheet1 = Cells(rows.count, 5).End(xlUp).Row
With ws2
For i = 3 To numRowSheet1
If Cells(i, 5) <> "" Then
'assign in cell B(sheet2) the value of the cell E of the sheet1
.Cells(rowSheet2, 2) = Cells(i, 5)
rowSheet2 = rowSheet2 + 1
End If
Next i
.Cells(rowSheet2,2)="complete"
End With
End Sub
Hope this helps

Cut rows to new sheet based on values in column

I have this list of products, and i want to:
Create new sheets based on the values on column C, if there's already a sheet with the same name as the cell value don't create a new sheet. (like "Abstract" in my example that already been created for row 2 and doesn't need to created again for row 3)
Cut the entire row to the matching sheet.
Make sure the first row is copied to all sheets.
This is a before picture
After Pic #1: new sheets created, nothing left on first sheet except the 1st row
After Pic #2: the sheet contains 2 products because there were 2 "Abstract" in column C
After Pic #3: the sheet contain 1 product because there was 1 "Plain" in column C
After Pic #4: the sheet contain 1 product because there was 1 "Shiny" in column C
This will get the job done.
I Named the first sheet to "Worksheet".
The code is dynamic, so you need to input 2 values by yourself:
Which range/names that should create the new worksheets:
Set myrange = ThisWorkbook.Sheets("Worksheet").Range("C2:C5") 'Set range that should create the new worksheet list
and how many columns you want to copy to the new sheets (it makes it more dynamic than take the whole row)
lastcol = Cells(1, "C").Column 'Set how many column that should be copied to new worksheet
VBA Code:
Sub AddNewSheetFromRange2()
Dim c As Range
Dim ws As Worksheet
Dim myrange As Range
Dim lastcol As Integer
Dim lrow As Integer
Dim lrow_newsheet As Integer
Dim i As Integer
Set myrange = ThisWorkbook.Sheets("Worksheet").Range("C2:C5") 'Set range that should create the new worksheet list
lastcol = Cells(1, "C").Column 'Set how many column that should be copied to new worksheet
lrow = Cells(Rows.Count, 3).End(xlUp).Row 'find last row for range that should create the new worksheet list
i = 1 'Set first index loop to 1
For Each c In myrange.Cells
i = i + 1 'Create index for each loop, used to know which row that should be copied
'Debug.Print c 'Print which Sheet Name that will be examine
Set ws = Nothing
On Error Resume Next
Set ws = Worksheets(c.Value)
On Error GoTo 0
If ws Is Nothing Then
With ThisWorkbook
Set ws = .Sheets.Add(After:=.Sheets(.Sheets.Count)) 'Add new sheet after (not before)
ws.Name = c.Value 'Rename the new sheet
End With
Dim WorksheetSheet As Worksheet 'Declare variable for Main worksheet
Set WorksheetSheet = ActiveWorkbook.Worksheets("Worksheet") 'Name the Main sheet
Dim NewSheet As Worksheet 'Declare variable for new worksheet
Set NewSheet = ActiveWorkbook.Worksheets(ws.Name) 'Make all new worksheets dynamic by taking name from range
'Copy Headers from Main sheet to New Worksheet
Worksheets("Worksheet").Activate
ThisWorkbook.Worksheets("Worksheet").Range(Cells(1, 1), Cells(1, 3)).Copy
Worksheets(ws.Name).Activate
ThisWorkbook.Worksheets(ws.Name).Range(Cells(1, 1), Cells(1, 3)).PasteSpecial
'Copy row from Main sheet to New Worksheet
Worksheets("Worksheet").Activate
ThisWorkbook.Worksheets("Worksheet").Range(Cells(i, 1), Cells(i, lastcol)).Copy
Worksheets(ws.Name).Activate
lrow_newsheet = Cells(Rows.Count, 3).End(xlUp).Row + 1
ThisWorkbook.Worksheets(ws.Name).Range(Cells(lrow_newsheet, 1), Cells(lrow_newsheet, lastcol)).PasteSpecial
'Clear row in Main sheet
Worksheets("Worksheet").Activate
ThisWorkbook.Worksheets("Worksheet").Range(Cells(i, 1), Cells(i, lastcol)).Clear
Else
'If worksheet already exists, then
'Copy row from Main sheet to existing worksheet with exactly the same name
Worksheets("Worksheet").Activate
ThisWorkbook.Worksheets("Worksheet").Range(Cells(i, 1), Cells(i, lastcol)).Copy
Worksheets(ws.Name).Activate
lrow_newsheet = Cells(Rows.Count, 3).End(xlUp).Row + 1
ThisWorkbook.Worksheets(ws.Name).Range(Cells(lrow_newsheet, 1), Cells(lrow_newsheet, lastcol)).PasteSpecial
'Clear row in Main sheet
Worksheets("Worksheet").Activate
ThisWorkbook.Worksheets("Worksheet").Range(Cells(i, 1), Cells(i, lastcol)).Clear
End If
Next c
End Sub
Visualizing the code in excel you will have to start with this:
and the final output will be this (the four rows into individual worksheets, if the name already exists, it will add to the already existing worksheet)

Resources