Copy Range into Specific Row/Cell and avoid overwriting the data - vba

Fairly new to VBA Excel. I want to copy and paste a specific cell[B11 and so on) into a specific cell [E9 and so on] on my target sheet when conditions are met (when C column is equal to No). So far I was able to copy and paste the data on my target sheet. Having trouble when I run the command again. I don't want to overwrite my previous data. How can this be done? `
Private Sub CommandButton1_Click()
Dim RowGCnt As Long, CShtRow As Long
Dim LastRow As Long
Dim CellG As Range
'paste the first result to the 9th row
CShtRow = 9
LastRow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
For RowGCnt = 11 To LastRow
If Range("C" & RowGCnt).Value = "No" Then
MsgBox (CShtRow)
'Review Criteria
Worksheets("SHEET1").Range("B" & RowGCnt).Copy
Worksheets("REPORT").Range("E" & CShtRow).PasteSpecial xlPasteValues
CShtRow = CShtRow + 1
End If
Next RowGCnt
Application.CutCopyMode = False
End Sub

Untested:
Private Sub CommandButton1_Click()
Dim shtSrc As Worksheet '<< source sheet
Dim RowGCnt As Long
Dim LastRow As Long
Dim cDest As Range '<< copy destination
Set shtSrc = Worksheets("SHEET1")
'paste the first result to the first open row
With Worksheets("REPORT")
Set cDest = .Cells(.Rows.Count, "E").End(xlUp).Offset(1, 0) '<<EDIT
If cDest.Row < 9 Then Set cDest = .Range("E9")
End With
LastRow = shtSrc.Range("A" & shtSrc.Rows.Count).End(xlUp).Row
For RowGCnt = 11 To LastRow
If shtSrc.Range("C" & RowGCnt).Value = "No" Then
cDest.Value = shtSrc.Range("B" & RowGCnt).Value
Set cDest = cDest.Offset(1, 0)
End If
Next RowGCnt
End Sub

Using Tim Williams code. I got a workaround
Private Sub CommandButton1_Click()
Dim shtSrc As Worksheet '<< source sheet
Dim RowGCnt As Long
Dim LastRow As Long
Dim cDest As Range '<< copy destination
Dim vLastRow As Integer
Set shtSrc = Worksheets("SHEET1")
'paste the first result to the first open row
With Worksheets("REPORT")
Set cDest = .Cells(.Rows.Count, "E").End(xlUp)
If cDest.Row < 9 Then
Set cDest = .Range("E9")
Else
vLastRow = .Cells(.Rows.Count, 5).End(xlUp).Row
Set cDest = .Cells(vLastRow + 1, 5)
End If
End With
LastRow = shtSrc.Range("A" & shtSrc.Rows.Count).End(xlUp).Row
For RowGCnt = 11 To LastRow
If shtSrc.Range("C" & RowGCnt).Value = "No" Then
cDest.Value = shtSrc.Range("B" & RowGCnt).Value
Set cDest = cDest.Offset(1, 0)
End If
Next RowGCnt
End Sub

Related

Copy cells from a specific column to another worksheet based on criteria

I have two worksheets, "Signed" and "April". I want to copy Column "Y" from "Signed" based on certain criteria into column "A" of "April" starting from the next available/blank row. ( so right under the existing data).
My criteria for column Y is that if column L = month of cell "D2" from "April" AND the year of cell "D2" from "ApriL"...( so right now D2 is 4/30/2017).. then copy that cell in the next available row of Col A of "April" and keep adding on.
I've been trying several different things but just am not able to get it..any idea on how I can achieve this?
My code is below:
Set sourceSht = ThisWorkbook.Worksheets("Signed")
Set myRange = sourceSht.Range("Y1", Range("Y" & Rows.Count).End(xlUp))
Set ws2 = Sheets(NewSheet)
DestRow = ws2.Cells(Rows.Count, "A").End(xlUp).Row + 1
For Each rw In myRange.Rows
If rw.Cells(12).Value = "Month(Sheets(ws2).Range("D2"))" Then
myRange.Value.Copy Destinations:=Sheets(ws2).Range("A" & DestRow)
End If
Something like this should work for you:
Sub tgr()
Dim wb As Workbook
Dim wsData As Worksheet
Dim wsDest As Worksheet
Dim aData As Variant
Dim aResults() As Variant
Dim dtCheck As Date
Dim lCount As Long
Dim lResultIndex As Long
Dim i As Long
Set wb = ActiveWorkbook
Set wsData = wb.Sheets("Signed") 'This is your source sheet
Set wsDest = wb.Sheets("April") 'This is your destination sheet
dtCheck = wsDest.Range("D2").Value2 'This is the date you want to compare against
With wsData.Range("L1:Y" & wsData.Cells(wsData.Rows.Count, "L").End(xlUp).Row)
lCount = WorksheetFunction.CountIfs(.Resize(, 1), ">=" & DateSerial(Year(dtCheck), Month(dtCheck), 1), .Resize(, 1), "<" & DateSerial(Year(dtCheck), Month(dtCheck) + 1, 1))
If lCount = 0 Then
MsgBox "No matches found for [" & Format(dtCheck, "mmmm yyyy") & "] in column L of " & wsData.Name & Chr(10) & "Exiting Macro"
Exit Sub
Else
ReDim aResults(1 To lCount, 1 To 1)
aData = .Value
End If
End With
For i = 1 To UBound(aData, 1)
If IsDate(aData(i, 1)) Then
If Year(aData(i, 1)) = Year(dtCheck) And Month(aData(i, 1)) = Month(dtCheck) Then
lResultIndex = lResultIndex + 1
aResults(lResultIndex, 1) = aData(i, UBound(aData, 2))
End If
End If
Next i
wsDest.Cells(wsDest.Rows.Count, "A").End(xlUp).Offset(1).Resize(lCount).Value = aResults
End Sub
Alternate method using AutoFilter instead of iterating over an array:
Sub tgrFilter()
Dim wb As Workbook
Dim wsData As Worksheet
Dim wsDest As Worksheet
Dim dtCheck As Date
Set wb = ActiveWorkbook
Set wsData = wb.Sheets("Signed") 'This is your source sheet
Set wsDest = wb.Sheets("April") 'This is your destination sheet
dtCheck = wsDest.Range("D2").Value2 'This is the date you want to compare against
With wsData.Range("L1:Y" & wsData.Cells(wsData.Rows.Count, "L").End(xlUp).Row)
.AutoFilter 1, , xlFilterValues, Array(1, Format(WorksheetFunction.EoMonth(dtCheck, 0), "m/d/yyyy"))
Intersect(.Cells, .Parent.Columns("Y")).Offset(1).Copy wsDest.Cells(wsDest.Rows.Count, "A").End(xlUp).Offset(1)
.AutoFilter
End With
End Sub
Here's a generic script which you can easily modify to handle almost ANY criteria, as needed.
Sub Copy_If_Criteria_Met()
Dim xRg As Range
Dim xCell As Range
Dim I As Long
Dim J As Long
I = Worksheets("Sheet1").UsedRange.Rows.Count
J = Worksheets("Sheet2").UsedRange.Rows.Count
If J = 1 Then
If Application.WorksheetFunction.CountA(Worksheets("Sheet2").UsedRange) = 0 Then J = 0
End If
Set xRg = Worksheets("Sheet1").Range("A1:A" & I)
On Error Resume Next
Application.ScreenUpdating = False
For Each xCell In xRg
If CStr(xCell.Value) = "X" Then
xCell.EntireRow.Copy Destination:=Worksheets("Sheet2").Range("A" & J + 1)
xCell.EntireRow.Delete
J = J + 1
End If
Next
Application.ScreenUpdating = True
End Sub

Lock Entire Row Based On Date

I have Cell A1 with Month mentioned. I am trying to compare date in A2:last cell and wherever date > A1, I want the row to be unlocked, otherwise locked. The below code doesn't work"
Sub Lockrow()
Dim DestSh As Worksheet
Dim lastrow As Long
Dim i As Integer
Set DestSh = Sheets("Consultant & Volunteer")
With DestSh
'finds the last row with data on A column
lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
'parse all rows
For i = 6 To lastrow
'if your conditions are met
If Month(.Cells(i, 26)) > Month(.Cells(1, 1)) Then
.Range("A" & i).EntireRow.Cells.Locked = True 'lock the row
End If
Next i
End With
End Sub
This can be done simply with below, but you have to be careful that Year doesn't change... Also the lastrow should be on Column Z.
Also, if the worksheet isn't Protected, there is no effect.
Option Explicit
Sub Lockrow()
Dim DestSh As Worksheet
Dim lastrow As Long
Dim i As Long ' Integer
Set DestSh = Sheets("Consultant & Volunteer")
With DestSh
'finds the last row with data on A column
lastrow = .Range("Z" & .Rows.Count).End(xlUp).Row ' <-- EDIT
'parse all rows
For i = 6 To lastrow
'if your conditions are met
.Rows(i).Locked = Not (Month(.Cells(i, "Z")) > Month(.Range("A1")))
' If Month(.Cells(i, 26)) > Month(.Cells(1, 1)) Then
' .Range("A" & i).EntireRow.Cells.Locked = True 'lock the row
' End If
Next i
.Protect UserInterfaceOnly:=True
End With
Set DestSh = Nothing
End Sub
Alternative to loop.
Dim r As Range, DestSh As Worksheet, lastrow As Long
Set DestSh = Sheets("Consultant & Volunteer")
With DestSh
lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
Set r = .Range("A1:A" & lastrow)
r.EntireRow.Locked = False
r.AutoFilter 1, ">" & .Range("A1").Value2
r.SpecialCells(xlCellTypeVisible).EntireRow.Locked = True
.AutoFilterMode = False
.Protect UserInterfaceOnly:=True
End With

Iterate all rows in date and store the month value to the last column

I'm trying to loop through a column(A) that contains date and create an arbitrary column(lastcolumn+1) and store only the month value from the column(A) which contains the date. Please help me!
Code: what my code is doing is copying the column and paste it the specified can someone help me to improve my code?
Public Sub Selection()
Dim file1 As Excel.Workbook
Dim Sheet1 As Worksheet
Dim serviceIDRng As Range
Dim lngLastRow As Long
Dim rngSheet1 As Range
Dim NextRow As Long
Dim LastRow As Long
Dim LastCol As Long
Dim c As Long
Set Sheet1 = Workbooks.Open(TextBox1.Text).Sheets(1)
'lngLastRow = Sheet1.Range("A" & Sheet1.Rows.Count).End(xlUp).Row
'Set serviceIDRng = Sheet1.Range("T1:T" & lngLastRow)
Application.ScreenUpdating = False
With Sheet1
NextRow = .Cells(.Rows.Count, "E").End(xlUp).Row + 1
End With
With Sheet1
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
For c = 1 To LastCol
LastRow = .Cells(.Rows.Count, c).End(xlUp).Row
Set rngSheet1 = .Range(.Cells(3, c), .Cells(LastRow, c))
rngSource.Copy Sheet1.Range("E" & NextRow)
NextRow = NextRow + rngSheet1.Rows.Count
Next c
End With
Application.ScreenUpdating = True
MsgBox "Succes!", vbExclamation
End Sub
To extract the month from column "E" to a new column:
Public Sub Selection()
Dim ws As Worksheet, data(), i&
Set ws = Workbooks.Open(TextBox1.text).sheets(1)
' load the data from column E
data = Intersect(ws.Columns("E"), ws.UsedRange)
'set the title
data(1, 1) = "Month"
' extract the month
For i = 2 To UBound(data)
If VarType(data(i, 1)) = vbDate Then
data(i, 1) = Month(data(i, 1))
End If
Next
' write the data back to the sheet
ws.UsedRange.Columns(ws.UsedRange.Columns.count + 1) = data
MsgBox "Succes!", vbExclamation
End Sub

Separate Excel rows into individual sheets and retain header

I am trying to use VBA in Excel to separate rows into separate sheets and retain headers. Below is what I have so far. It works except I get the header row, then the individual row I want to move to the sheet is there BUT it's there three times instead of one. I am basically going by trial and error and I am stumped. Help please! I have no experience with this:
Sub DispatchTimeSeriesToSheets()
Dim ws As Worksheet
Set ws = Sheets("Scoring")
Dim LastRow As Long
LastRow = Range("A" & ws.Rows.Count).End(xlUp).Row
' stop processing if we don't have any data
If LastRow < 2 Then Exit Sub
Application.ScreenUpdating = False
SortScoring LastRow, ws
CopyDataToSheets LastRow, ws
ws.Select
Application.ScreenUpdating = True
End Sub
Sub SortScoring(LastRow As Long, ws As Worksheet)
ws.Range("A4:W" & LastRow).Sort Key1:=ws.Range("A4"), Key2:=ws.Range("W4")
End Sub
Sub CopyDataToSheets(LastRow As Long, src As Worksheet)
Dim rng As Range
Dim cell As Range
Dim Series As String
Dim SeriesStart As Long
Dim SeriesLast As Long
Set rng = Range("A4:A" & LastRow)
SeriesStart = 2
Series = Range("A" & SeriesStart).Value
For Each cell In rng
If cell.Value <> Series Then
SeriesLast = cell.Row - 1
CopySeriesToNewSheet src, SeriesStart, SeriesLast, Series
Series = cell.Value
SeriesStart = cell.Row
End If
Next
' copy the last series
SeriesLast = LastRow
CopySeriesToNewSheet src, SeriesStart, SeriesLast, Series
End Sub
Sub CopySeriesToNewSheet(src As Worksheet, Start As Long, Last As Long, _
name As String)
Dim tgt As Worksheet
If (SheetExists(name)) Then
MsgBox "Sheet " & name & " already exists. " _
& "Please delete or move existing sheets before" _
& " copying data from the Scoring.", vbCritical, _
"Time Series Parser"
End
End If
Worksheets.Add(After:=Worksheets(Worksheets.Count)).name = name
Set tgt = Sheets(name)
' copy header row from src to tgt
tgt.Range("A1:W1").Value = src.Range("A1:W1").Value
' copy data from src to tgt
tgt.Range("A4:W" & Last - Start + 2).Value = _
src.Range("A" & Start & ":W" & Last).Value
End Sub
Function SheetExists(name As String) As Boolean
Dim ws As Worksheet
SheetExists = True
On Error Resume Next
Set ws = Sheets(name)
If ws Is Nothing Then
SheetExists = False
End If
End Function
Try this:
Sub doitall()
Dim ows As Worksheet
Dim tws As Worksheet
Dim rng As Range
Dim cel As Range
Dim LastRow As Long
Dim tLastRow As Long
Set ows = Sheets("Scoring")
With ows
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
Set rng = .Range("A4:A" & LastRow)
For Each cel In rng
If Not SheetExists(cel.Value) Then
Set tws = Worksheets.Add(After:=Sheets(Worksheets.Count))
tws.Name = cel.Value
tws.Rows(1).Resize(3).Value = .Rows(1).Resize(3).Value
Else
Set tws = Sheets(cel.Value)
End If
tLastRow = tws.Range("A" & tws.Rows.Count).End(xlUp).Offset(1).Row
tws.Rows(tLastRow).Value = .Rows(cel.Row).Value
Next
End With
End Sub
Function SheetExists(SName As String, _
Optional ByVal WB As Workbook) As Boolean
On Error Resume Next
If WB Is Nothing Then Set WB = ActiveWorkbook
SheetExists = CBool(Len(WB.Sheets(SName).Name))
End Function
This will do what you are looking for
Const HeaderRow = 3
Sub MoveRecordsByValues()
Dim ws As Worksheet
Dim dws As Worksheet
Dim SheetName As String
Application.DisplayAlerts = False
For Each ws In Sheets
If ws.name <> "Scoring" Then ws.Delete
Next ws
Set ws = Sheets("Scoring")
StartRow = HeaderRow + 1
LastRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
For RowCounter = StartRow To LastRow
SheetName = ws.Cells(RowCounter, 1)
If Not SheetExists(SheetName) Then SetUpSheet SheetName, ws, HeaderRow
Set dws = Worksheets(SheetName)
DestLastRow = dws.Range("A" & dws.Rows.Count).End(xlUp).Row + 1
ws.Rows(RowCounter).Copy dws.Cells(DestLastRow, 1)
Next RowCounter
Application.DisplayAlerts = True
End Sub
Function SheetExists(name As String) As Boolean
SheetExists = True
On Error GoTo errorhandler
Sheets(name).Activate
Exit Function
errorhandler:
SheetExists = False
End Function
Sub SetUpSheet(name, SourceSheet, HeaderRow)
Dim DestSheet As Worksheet
Set DestSheet = Sheets.Add
DestSheet.name = name
SourceSheet.Rows(1).Copy DestSheet.Cells(1, 1)
SourceSheet.Rows(2).Copy DestSheet.Cells(2, 1)
SourceSheet.Rows(3).Copy DestSheet.Cells(3, 1)
End Sub

Excel VBA - Check Values in Sheet1 Against Sheet2, then Copy Notes If Matching

I have two sheets. I want to check the value in one column against the value in the same column in the second sheet. If they match, then I want to migrate the string data from the Notes column to the new sheet. (essentially I'm seeing if last week's ticket numbers are still valid this week, and carrying over the notes from last week).
I am trying to do this with the following code (using columns Z for the data, BE for the notes):
Sub Main()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
Dim partNo2 As Range
Dim partNo1 As Range
Dim partNo3 As Range
For Each partNo2 In ws1.Range("Z1:Z" & ws1.Range("Z" & Rows.Count).End(xlUp).Row)
For Each partNo1 In ws2.Range("Z1:Z" & ws2.Range("Z" & Rows.Count).End(xlUp).Row)
For Each partNo3 In ws1.Range("BE1:BE" & ws2.Range("BE" & Rows.Count).End(xlUp).Row)
If StrComp(Trim(partNo2), Trim(partNo1), vbTextCompare) = 0 Then
ws2.Range("BE" & partNo1.Row) = partNo3
End If
Next
Next
Next
'now if no match was found then put NO MATCH in cell
For Each partNo1 In ws2.Range("E1:F" & ws2.Range("A" & Rows.Count).End(xlUp).Row)
If IsEmpty(partNo1) Then partNo1 = ""
Next
End Sub
Untested:
Sub Main()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim rng1 As Range, rng2 As Range
Dim c As Range, f As Range
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
Set rng1 = ws1.Range("Z1:Z" & ws1.Range("Z" & Rows.Count).End(xlUp).Row)
Set rng2 = ws2.Range("Z1:Z" & ws2.Range("Z" & Rows.Count).End(xlUp).Row)
For Each c In rng1.Cells
Set f = rng2.Find(c.Value, , xlValues, xlWhole)
If Not f Is Nothing Then
f.EntireRow.Cells(, "BE").Value = c.EntireRow.Cells(, "BE").Value
End If
Next c
'now if no match was found then put NO MATCH in cell
For Each c In ws2.Range("E1:F" & ws2.Range("A" & Rows.Count).End(xlUp).Row)
If Len(c.Value) = 0 Then c.Value = "NO MATCH"
Next
End Sub
This accomplishes the same result (maybe with the exception of the columns E & F at the bottom with NO MATCH). It's just a different way of going about it. Instead of using ranges, I'm just looking at each cell and comparing it directly.
TESTED:
Sub NoteMatch()
Dim lastRow1 As Long
Dim lastRow2 As Long
Dim tempVal As String
lastRow1 = Sheets("Sheet1").Range("Z" & Rows.Count).End(xlUp).row
lastRow2 = Sheets("Sheet2").Range("Z" & Rows.Count).End(xlUp).row
For sRow = 2 To lastRow1
tempVal = Sheets("Sheet1").Cells(sRow, "Z").Text
For tRow = 2 To lastRow2
If Sheets("Sheet2").Cells(tRow, "Z") = tempVal Then
Sheets("Sheet2").Cells(tRow, "BE") = Sheets("Sheet1").Cells(sRow, "BE")
End If
Next tRow
Next sRow
Dim match As Boolean
'now if no match was found, then put NO MATCH in cell
For lRow = 2 To lastRow2
match = False
tempVal = Sheets("Sheet2").Cells(lRow, "Z").Text
For sRow = 2 To lastRow1
If Sheets("Sheet1").Cells(sRow, "Z") = tempVal Then
match = True
End If
Next sRow
If match = False Then
Sheets("Sheet2").Cells(lRow, "BE") = "NO MATCH"
End If
Next lRow
End Sub