VBA increment number in qualifying cell on paste - excel

I have a macro that pastes a number of rows from a "Template" sheet into the next blank row on the active sheet.
In column 2 of the first row is the value "variable".
In Column 6 of the first row is a 3 digit number.
What I am wanting to do is increment the number in Column 6 by 1 when it is pasted. If there is no previous number on the active sheet, then it starts with 001.
As the sheet has other rows that don't contain numbers, and the rows with numbers are not at regular intervals, I am thinking the cell to increment needs to be determined in the following way (unless there is an easier logic) :
In Active Sheet, find last row in Column 2 that has value "variable".
Offset Column by 4, to get to cell in Column 6.
Take active cell value and increment by 1 in the pasted rows, using
the same criteria as above to determine which cell.
If there is no previous value of "variable" in Column 2 then value=001.
Here is the code I use to paste below into the next blank row.
Sub Paste_New_Product_from_Template()
Application.ScreenUpdating = False
Dim copySheet As Worksheet
Dim pasteSheet As Worksheet
Set copySheet = Worksheets("Template")
Set pasteSheet = ActiveSheet
copySheet.Range("2:17").Copy
pasteSheet.Cells(Rows.Count, 1).End(xlUp).OFFSET(1, 0).PasteSpecial xlPasteAll
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
How could I incorporate the incrementing of numbers mentioned above?
EDIT
This is a sample of what the rows would look like on the Template sheet
And this is what the rows look like on Sheet1

Yes only incrementing Row 6. If no data in sheet then numbering starts from 001. Each sheet has independent numbering. If sheet has data then numbering starts from pasted row e.g. row 10. – aye cee
Let's say our sample data looks like this
LOGIC:
Set your input/output sheets.
Find the last cell to write to in the output sheet. Have to check if there is data previously or not.
If there is no data then copy across the header row.
Copy the range.
Ascertain the next number to be written in column 6.
Enter the number in the relevant cell in column 6 of the copied data and apply the 000 format.
CODE:
Is this what you are trying? I have commented the code so you should not have a problem understanding it but if you do them simply ask :)
Option Explicit
Sub Paste_New_Product_from_Template()
Dim copySheet As Worksheet
Dim pasteSheet As Worksheet
Dim LRow As Long, i As Long
Dim StartNumber As Long
Dim varString As String
'~~> This is your input sheet
Set copySheet = Worksheets("Template")
'~~> Variable
varString = copySheet.Cells(2, 2).Value2
'~~> Change this to the relevant sheet
Set pasteSheet = Sheet2
'~~> Initialize the start number
StartNumber = 1
With pasteSheet
'~~> Find the last cell to write to
If Application.WorksheetFunction.CountA(.Cells) = 0 Then
'~~> Copy header row
copySheet.Rows(1).Copy .Rows(1)
LRow = 2
Else
LRow = .Range("A" & .Rows.Count).End(xlUp).Row + 1
'~~> Find the previous number
For i = LRow To 1 Step -1
If .Cells(i, 2).Value2 = varString Then
StartNumber = .Cells(i, 6).Value2 + 1
Exit For
End If
Next i
End If
'~~> Copy the range
copySheet.Range("2:17").Copy .Rows(LRow)
'~~> Set the start number
.Cells(LRow, 6).Value = StartNumber
'~~> Format the number
.Cells(LRow, 6).NumberFormat = "000"
End With
End Sub
IN ACTION

Related

extend sum to dynamic range with excel vba macro

I am trying to extend a sum formula to a dynamic range. The sum includes all values from row 5 till the second last used row in the column, the sum is then in the last used row. However, the number of rows and columns vary, the only thing that stays the same is that the sum should always start in row 5. The sum starts also always in column C. I already managed to write a macro that puts the sum in the last row of column C. I am now working on a macro that extends this sum to all other used columns in the sheet, except for the last column (that contains another value and not a sum).
I am working with selection.autofill. However, I am having issues with declaring the range that i want to fill. VBA gives me an "expected: end of statement" error and I can't figure out why. Can somebody explain to me what I am doing wrong? Is there a better method than selection.autofill - i fear that it might not take over the columns, e.g. actually summing up column D when extended to the cell in column D ?
Here is what i already have:
'
' sumtest Macro
'
'
Dim Cell As Range, sRange As Range
Dim wsDestination As Worksheet
With ThisWorkbook
Set wsDestination = .Worksheets("Overview")
End With
FirstRow = Rows(5).EntireRow
lastRow = wsDestination.Cells(Rows.Count, "A").End(xlUp).Row
LastRow1 = wsDestination.Cells(Rows.Count, "A").End(xlUp).Row
LastColumn1 = wsDestination.Cells(4, wsDestination.Columns.Count).End(xlToLeft).Column
Worksheets("Overview").Select
wsDestination.Cells(lastRow, "C").Select
ActiveCell.Formula = "=SUM(C5:C" & lastRow - 1 & ")"
Range(wsDestination.Cells(LastRow1, 3)).Select
Selection.AutoFill Destination:=Range(wsDestination.Cells(LastRow1,3),wsDestination.Cells(LastRow1,LastColumn -1)) Type:=xlFillDefault
End Sub
This code would write the value of the sum in each column for the last row:
Option Explicit
Sub Sumtest()
With ThisWorkbook.Sheets("Overview")
Dim LastCol As Long: LastCol = .Cells(4, .Columns.Count).End(xlToLeft).Column
Dim Cell As Range
Dim LastRow As Long
For Each Cell In .Range("C4", .Cells(4, LastCol))
LastRow = .Cells(.Rows.Count, Cell.Column).End(xlUp).Row
.Cells(LastRow, Cell.Column) = Application.Sum(.Range(Cell.Offset(1), .Cells(LastRow - 1, Cell.Column)))
Next Cell
End With
End Sub
Note that the code will check the LastRow for every column, so if the columns have different amount of rows the total will be on the first row without data for each column.

How can I copy range from sheet to sheet based on column value?

I am trying to copy a specified range of cells from one sheet (Sheet2) to a specified range of cells in another sheet (Sheet1) based on a condition. There are hundreds of rows of data, and I would like VBA code that looks at each row, and if the condition is met for that row, copies the specified cell range from sheet2 to sheet1. It is not the entire row being copied, just four cells out of a row with many more cells that contain data.
In more specific terms, I would like to copy columns B through E for each row (starting at row 2) IF the value in column AK for each row is greater than 0. I would like for this data to be pasted into columns B through E in sheet1, starting at row 8. So, for example, if row 2 in Sheet 2 meets the criteria, I would like for B2 through E2 in sheet 2 to be copied to B8 through E8 in sheet 1.
I have tried to adapt code found in other questions on StackOverFlow and other sources but I am very new to VBA and have not been successful. Any help would be greatly appreciated.
Private Sub CopySomeCells()
Dim SourceSheet As Worksheet
Dim DestinationSheet As Worksheet
Dim SourceRow As Long
Dim DestinationRow As Long
Set SourceSheet = ActiveWorkbook.Sheets(2)
Set DestinationSheet = ActiveWorkbook.Sheets(1)
DestinationRow = 8
For SourceRow = 2 To SourceSheet.UsedRange.Rows.Count
If SourceSheet.Range("AK" & SourceRow).Value > 0 Then
SourceSheet.Range(SourceSheet.Cells(SourceRow, 2), SourceSheet.Cells(SourceRow, 5)).Copy _
DestinationSheet.Cells(DestinationRow, 2)
DestinationRow = DestinationRow + 1
End If
Next SourceRow
Application.CutCopyMode = False
Set SourceSheet = Nothing
Set DestinationSheet = Nothing
End Sub
If you just want to paste the values (and not the format) then change two rows by this:
SourceSheet.Range(SourceSheet.Cells(SourceRow, 2), SourceSheet.Cells(SourceRow, 5)).Copy
DestinationSheet.Cells(DestinationRow, 2).PasteSpecial Paste:=xlPasteValues
Or better by this (faster and without clipboard):
DestinationSheet.Cells(DestinationRow, 2).Resize(1, 4).Value = _
SourceSheet.Cells(SourceRow, 2).Resize(1, 4).Value

Use VBA to paste a formula if there is something in column A of that row

I'm trying to run some VBA that will count how many rows there are which are not empty in a given range, and then paste a formula in column 13 (M) the number of rows down which were not empty.
This is the code I have:
Sub CountCells()
MsgBox WorksheetFunction.CountA(Sheets("DATA").Range("A7:A750"))
Worksheets("DATA").Range("M7:M500").Formula = "=MYFORMULAR"
End Sub
This code currently counts the number of cells which are not empty in column A but then how do I take this number and use it for the next equation?
If there were 200 columns in range A7:A750 with content in, I would like to paste my formular from M7 to M207.
Option Explicit
Sub CountCells()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("DATA")
Dim LRow As Long
'Determine last row
LRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
'Apply formula from rows 7 to last row
ws.Range("M7:M" & LRow).Formula = "=MYFORULAR"
End Sub

Working with the Columns function - Excel VBA

I have been looking around the site for a while for an answer to this question but no luck just yet. I have this code where I loop through a row of numbers and depending on what number is in the cell at the time, determines what I copy and paste to the sheet. I am using Columns for this because it is the only way I can make my code dynamic. It works but when I paste I would like to paste in cells lower than where it's pasting right now. I was wondering if Columns had a way of specifying what column and where to paste my data.
Code:
Dim sh As Worksheet
Dim rw As Range
Dim row As Range
Dim cell As Range
Dim RowCount As Integer
Set rw = Range("A5:CG5")
Set sh = ActiveSheet
For Each row In rw.Rows
For Each cell In row.Cells
Select Case cell.Value
Case "2"
ThisWorkbook.Worksheets("Sheet1").Range("E27:E51").Copy Destination:=Sheets("Sheet2").Columns(4)
End Select
Next cell
Next row
Your problem can be solved as Jeeped said, use Destination:=Sheets("Sheet2").Cells(27, 5) or Destination:=Worksheets(2).Range("E27")
Since you want to learn a little bit more, i made an example explanation:
https://msdn.microsoft.com/en-us/vba/excel-vba/articles/range-column-property-excel
On the link it is explained that .Column:
Column A returns 1, column B returns 2, and so on.
And the same is with the .Rows
Use .Cells https://msdn.microsoft.com/pt-br/library/office/ff194567.aspx So you can use the .Cells(Rows,Columns) or .Cells(Index from a Range) or the entire Object:
With Worksheets("Sheet1").Cells.Font
.Name = "Arial"
.Size = 8
End With
So an example if you want to turn your spreadsheet dynamical: to copy from range $E$27 to last row with something written from column $E on Sheet1 To
the last column with nothing written on row 1 on Sheet2.
Sub test()
'Declare variables here
Dim sht1, sht2 As Worksheet
'sht1 has the data and sht2 is the output Worksheet, you can change the names
last_row = Worksheets(1).Range("E65536").End(xlUp).Row
last_column = Worksheets(2).Cells(1, sht1.Columns.Count).End(xlToLeft).Column
'Data add
For i = 27 To last_row
'Start from Row 27
Worksheets(2).Cells(i - 26, last_column + 1) = Worksheets(1).Cells(i, 5)
Next i
MsgBox "Data Updated"
End Sub
And an example of a basic dynamical workbook with i=i+1 and For loops split a single row of data into multiple unique rows into a new sheet to include headers as values and cell contents as values

copy data based on criteria to another sheet and clear the contents

This code is working to copy the filtered data of "Award" column marked "Yes" to another sheet; however, I'm receiving an error of "Type Mismatch." I'm not 100% now that the code is working properly to filter the data and copy correctly. I currently have 23 rows of test data for proper functionality. If I only put one row of data, then it doesn't copy and paste the data correctly. I am left with the copied 1st row of data plus the 2nd empty row of data. Additionally, it is not clearing the contents of the rows after the paste, so I may add new data as the days progress.
Sub CopySheet()
Dim i As Integer
Dim LastRow As Integer
Dim Search As String
Dim Column As Integer
Sheets("MasterData").Activate
Sheets("MasterData").Range("A1").Select
'Sets an Autofilter to sort out only your Yes rows.
Selection.AutoFilter
'Change Field:=5 to the number of the column with your Y/N.
Sheets("MasterData").Range("$A$1:$G$200000").AutoFilter Field:=7, Criteria1:="Yes"
'Finds the last row
LastRow = Sheets("MasterData").Cells(Sheets("MasterData").Rows.Count, "A").End(xlUp).row
i = 1
'Change the 3 to the number of columns you got in Sheet2
Do While i <= 11
Search = Sheets("ActiveJobStatus").Cells(1, i).Value
Sheets("MasterData").Activate
'Update the Range to cover all your Columns in MasterData.
If IsError(Application.Match(Search, Sheets("MasterData").Range("A1:G1"), 0)) Then
'nothing
Else
Column = Application.Match(Search, Sheets("MasterData").Range("A1:G1"), 0)
Sheets("MasterData").Cells(2, Column).Resize(LastRow, 1).Select
Selection.Copy
Sheets("ActiveJobStatus").Activate
Sheets("ActiveJobStatus").Cells(2, i).Select
ActiveSheet.Paste
End If
i = i + 1
Loop
'Clear all Y/N = Y
'Update the Range to cover all your Columns in MasterData.
Sheets("MasterData").Activate
Column = Application.Match("Award", Sheets("MasterData").Range("A1:F1"), 0)
Sheets("MasterData").Cells(2, Column).Resize(LastRow, 1).Select
Selection.ClearContents
End Sub
Sorry to change your code up so much, but it looks like you might be over-complicating how to do it.
This is some code from a previous question I answered where someone wanted to highlight a specific range whenever the word "Total" was found.
I changed the find to "Yes". Change the SearchRange to your column. (I think G is right).
Also, for future reference, Select should [almost never] be used.
It slows down code execution quite a bit and is not required.
I know the macro recorder likes to use it, but everything can be referenced without using select.
Brief example:
Sheets("ActiveJobStatus").Activate
Sheets("ActiveJobStatus").Cells(2, i).Select
ActiveSheet.Paste
Can Be replaced by:
Sheets("ActiveJobStatus").Cells(2, i).Paste
This code is working to copy the filtered data of "Award" column marked "Yes" to another sheet.
Sub CopyAwardsToActiveJobStatusSheet()
Dim SearchRange, First, Finder As Range
Dim PasteRow as Integer 'Add this to increment the rows we paste your data to
Set SearchRange = Sheets("MasterData").Range("G:G") 'Search This Range for "Yes"
Set Finder = SearchRange.Find("Yes") 'This is what we're looking for
If Finder Is Nothing Then Exit Sub 'We didn't find any "Yes" so we're done
'Drastically increases speed of every macro ever
'(well, when the sheets are modified at least - and it doesn't hurt)
Application.ScreenUpdating = False
First = Finder.Address 'Grab the address of the first "Yes" so we know when to stop
'Get the last row of column "A" on ActiveJobStatusSheet and start pasting below it
PasteRow = Sheets("ActiveJobStatus").Cells(Sheets("ActiveJobStatus").Rows.Count, "A").End(xlUp).Row + 1
Do
'Copy the entire row and paste it into the ActiveJobStatus sheet
'Column A and PasteRow (the next empty row on the sheet)
'You can change these if needed
Finder.EntireRow.Copy Sheets("ActiveJobStatus").Range("A" & PasteRow)
'If you just want A:G, you can use this instead:
'Finder returns the cell that contains "Yes",
'So we offset/resize to get the 6 cells before it and just copy that
'Resize doesn't like negative numbers so we have to combine:
'Finder.Offset(,-6).Resize(,7).Copy Sheets("ActiveJobStatus").Range("A" & PasteRow)
'Look for the next "Yes" after the one we just found
Set Finder = SearchRange.FindNext(after:=Finder)
PasteRow = PasteRow + 1 'Faster than looking for the end again
'Do this until we are back to the first address
Loop While Not Finder Is Nothing And Finder.Address <> First
'Clear MasterData
Sheets("MasterData").Range("A2:G" & Sheets("MasterData").UsedRange.Rows.Count).ClearContents
Application.ScreenUpdating = True 'Drastically increases speed of every macro ever.
End Sub
Just the code:
Sub CopyAwardsToActiveJobStatusSheet()
Dim SearchRange, First, Finder As Range
Dim PasteRow as Integer
Set SearchRange = Sheets("MasterData").Range("G:G")
Set Finder = SearchRange.Find("Yes")
If Finder Is Nothing Then Exit Sub
Application.ScreenUpdating = False
First = Finder.Address
PasteRow = Sheets("ActiveJobStatus").Cells(Sheets("ActiveJobStatus").Rows.Count, "A").End(xlUp).Row + 1
Do
Finder.EntireRow.Copy Sheets("ActiveJobStatus").Range("A" & PasteRow)
Set Finder = SearchRange.FindNext(after:=Finder)
PasteRow = PasteRow + 1
Loop While Not Finder Is Nothing And Finder.Address <> First
Sheets("MasterData").Range("A2:G" & Sheets("MasterData").UsedRange.Rows.Count).ClearContents
Application.ScreenUpdating = True
End Sub
Results:
MasterData Sheet:
ActiveJobStatus Sheet:

Resources