I have data ranges in Row 1,2,3 and 4 for columns A:Q. I am trying to create a VBA so it does the following:
Copy Row 1 A:Q, drag and paste n number of rows based on cell O12 starting on Cell A17.
Copy Row 2 A:Q, drag and paste n number of rows based on cell O12 but the paste range should be after what has been pasted for Row 1 range.
Repeat for Row 3 and 4.
So for say of cell O12 states 4, i should be getting 16 rows 4 for each row dragged down.
Any help would be appreciated.
Sub CopyJournalLines()
' Works out last cell with data in columns A or B, copys row 2 and paste within that range (from startrow)
Dim ws As Worksheet
Dim rng1 As Range
Dim LastRow As String
Dim StartRow As String
Dim Copyrange As String
Dim LastYRow As String
Application.ScreenUpdating = False
' Find the last row of data on Concur Extract sheet
Set ws = Sheets("Invoicing")
Set rng1 = ws.Columns("A:B").Find("*", ws.[a1], xlValues, , xlByRows, xlPrevious)
' Setting range on Test to copy formulas accross into
StartRow = 17
LastRow = rng1.Row + 1
LastYRow = rng1.Row + 2
If LastYRow < 21 Then
LastYRow = 19
End If
Set ws = Sheets("Vision Import Sheet")
Let Copyrange = StartRow & ":" & LastRow
Let LastYCell = "AB" & LastYRow
' Clear previous content - limited to clear first 1000rows
Rows("17:5000").Cells.Clear
'Selection.ClearContents
If LastRow < 17 Then
GoTo End1
End If
' Copying & pasting row with correct formulas
Rows("1:5").Select
Selection.EntireRow.Hidden = False
Rows("1:1").Select
Selection.Copy
Rows("17:17").Select
ActiveSheet.Paste
Rows("17:17").Select
Selection.Replace What:="#", Replacement:="=", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Rows("17:17").Select
Selection.Copy
Rows(Copyrange).Select
ActiveSheet.Paste
Rows("1:5").Select
Selection.EntireRow.Hidden = True
End1:
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
The copy/paste method should be put in two loops corresponding to two parameters: the number of lines to copy and the number of copies per line.
For the following code, you can choose to copy in the format 111222333 or in the format 123123123 by commenting and un-commenting the two lines that calculate the iCopyRow parameter.
Sub CopyJournalLines2()
Dim wsInv As Worksheet
Dim i As Integer
Dim j As Integer
Dim iStartRow As Integer
Dim iNumCopies As Integer
Dim iNumLines As Integer
Dim iCopyRow As Integer
Dim CopyRange As Range
Dim PasteRange As Range
Set wsInv = ThisWorkbook.Sheets("Invoice Upload")
With wsInv
.Rows("17:5000").Cells.Clear
iStartRow = 17
iNumCopies = .Range("O12").Value
iNumLines = .Range("P12").Value
For i = 1 To iNumLines
Set CopyRange = .Range(.Cells(i, 1), .Cells(i, 17))
iCopyRow = iStartRow + (i - 1) * iNumCopies '---Copies lines in order 111222333444 etc.
'iCopyRow = iStartRow + (i - 1) '---Copies lines in order 123412341234 etc.
Set PasteRange = .Range(.Cells(iCopyRow, 1), .Cells(iCopyRow, 17))
PasteRange.Formula = CopyRange.Formula
If iNumCopies > 1 Then
For j = 2 To iNumCopies
iCopyRow = iStartRow + j - 1 + (i - 1) * iNumCopies '---Copies lines in order 111222333444 etc.
'iCopyRow = iStartRow + i - 1 + ((j - 1) * iNumLines) '---Copies lines in order 123412341234 etc.
.Range(.Cells(iCopyRow, 1), .Cells(iCopyRow, 17)).Formula = PasteRange.Formula
Next j
End If
Next i
End With
End Sub
Related
I want to copy duplicate rows from a sheet to another by analyzing multiple columns in excel, I can do it by applying Nested For loops to compare multiple columns but number of rows in my sheet is around 6000. So if I apply nested For loop to compare rows by analyzing 2 columns it requires around 17991001 iterations, which slows down my System. Is there any fast way to do that???
my Function is
Sub findDuplicates(ByVal sheet As Worksheet, name As String, ByRef row As Integer, ByVal Sheet2 As Worksheet)
Dim i As Integer
Dim numRow As Integer
'Dim matchFound As Long
'Dim myRange1 As Range
'Dim myRange2 As Range
numRow = sheet.Range("J2", sheet.Range("J2").End(xlDown)).Rows.Count
With Sheet2
Range(Cells(row, "A"), Cells(row, "N")).MergeCells = True
With Cells(row, "A")
.Font.name = "Bell MT"
.Font.FontStyle = "Bold Italic"
.Font.Size = 20
.Font.Color = RGB(255, 99, 71)
.Value = "Multiple Forms Found in " & name & " for single household"
End With
row = row + 1
End With
For i = 1 To numRow + 1
'matchFound
'If i <> matchFound Then
sheet.Rows(i).Copy Sheet2.Rows(row)
row = row + 1
'sheet.Rows(matchFound).Copy Sheet2.Rows(row)
'row = row + 1
'End If
Next i
End Sub
Note - I added some comments to make you understand what I want to do.
The Summery of my function is to take two sheets and check the J and K columns of sheet 1, If two rows found same J and K column's value then both rows are copied to sheet2 (next to each other)
Try this. Modified from Siddharth Rout's answer here.
Private Sub CommandButton2_Click()
Dim col As New Collection
Dim SourceSheet As Worksheet
Dim DestSheet As Worksheet
Dim i As Long
Dim lLastRow As Long
Application.ScreenUpdating = False
Set SourceSheet = ThisWorkbook.Sheets("Sheet1")
Set DestSheet = Worksheets("Sheet2")
lLastRow = SourceSheet.Cells(Rows.Count, 10).End(xlUp).row
DestSheetLastRow = 1
With SourceSheet
For i = 1 To lLastRow
On Error Resume Next
col.Add i, CStr(.Range("J" & i).Value) 'Add elements to collection
If Err.Number <> 0 Then 'If element already present
TheVal = CStr(SourceSheet.Range("J" & i).Value) 'Get the duplicate value
TheIndex = col(TheVal) 'Get the original position of duplicate value in the collection (i.e., the row)
If (.Cells(i, 11).Value = .Cells(TheIndex, 11).Value) Then 'Check the other column (K). If same value...
SourceSheet.Range(Cells(TheIndex, 1), Cells(TheIndex, 20)).Copy DestSheet.Cells(DestSheetLastRow, 1) 'Set your range according to your needs. 20 columns in this example
SourceSheet.Range(Cells(i, 1), Cells(i, 20)).Copy DestSheet.Cells(DestSheetLastRow, 21)
DestSheetLastRow = DestSheetLastRow + 1
Err.Clear
End If
End If
Next i
End With
Application.ScreenUpdating = True
End Sub
Finally, This Works for me
Sub findDuplicates(ByVal sheet As Worksheet, name As String, ByRef row As Integer, ByVal Sheet2 As Worksheet)
Dim i As Integer
Dim j As Integer
Dim numRow As Integer
Dim count As Integer
Dim myRange1 As Range
Dim myRange2 As Range
Dim myRange3 As Range
Set myRange1 = sheet.Range("J2", sheet.Range("J2").End(xlDown)).Rows
Set myRange2 = sheet.Range("K2", sheet.Range("K2").End(xlDown)).Rows
numRow = sheet.Range("J2", sheet.Range("J2").End(xlDown)).Rows.count
With Sheet2
Range(Cells(row, "A"), Cells(row, "N")).MergeCells = True
With Cells(row, "A")
.Font.name = "Bell MT"
.Font.FontStyle = "Bold Italic"
.Font.Size = 20
.Font.Color = RGB(255, 99, 71)
.Value = "Multiple Forms Found in " & name & " for single household"
End With
sheet.Rows(1).Copy .Rows(row + 1)
.Rows(row + 1).WrapText = False
row = row + 2
End With
j = row
For i = 1 To numRow + 1
count = WorksheetFunction.CountIfs(myRange1, sheet.Cells(i, "J"), myRange2, sheet.Cells(i, "K"))
If count > 1 Then
sheet.Rows(i).Copy Sheet2.Rows(row)
row = row + 1
End If
Next i
Set myRange3 = Sheet2.Range(Cells(j, 1), Cells(row - 1, 192))
With Sheet2.Sort
.SortFields.Add Key:=Range("J1"), Order:=xlAscending
.SortFields.Add Key:=Range("K1"), Order:=xlAscending
.SetRange myRange3
.Header = xlNo
.Orientation = xlTopToBottom
.Apply
End With
End Sub
Layout of Excel Sheets
Problem:
I have to find the superset of all strings from the first column of two sheets. These may be present in one or both sheets. Based upon the string which is present, copy that string to the third sheet. Then copy the data in the next column from one or both sheets. Then find out the difference. Repeat. This code works if the string is present in both the sheets. How do I make it work if the string in the first column is not present in one or both? I want to include all the data from the two sheets.
This is the code:
Sub Macro5()
'
' Macro5 Macro
'
'
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim ws3 As Worksheet
Dim coli As Double
Dim Coli3 As Double
Dim rowy As Double
Dim numCols As Double
Dim startRow As Double
Dim lastRow As Double
Dim dict As Scripting.Dictionary
startRow = 6 'assuming data starts here
Coli3 = 2 ' start the columns out on ws3
Set ws1 = ThisWorkbook.Worksheets("sheet1")
Set ws2 = ThisWorkbook.Worksheets("sheet2")
Set ws3 = ThisWorkbook.Worksheets("sheet3")
Application.ScreenUpdating = False
ws3.Cells.Clear
'ws1.Range("A1").EntireColumn.Copy Destination:=ws3.Range("A1")
'Find how many columns there are in sheet1 based on data in row 1
numCols = ws1.Cells(7, Columns.Count).End(xlToLeft).Column
For coli = 2 To numCols
'Find last Data row in the given column in sheet1
lastRow = ws1.Cells(ws1.Rows.Count, coli).End(xlUp).Row
For rowy = 6 To lastRow
'perform calculation and place in the right spot on sheet 3
If rowy = "6" Then
ws3.Cells(rowy, Coli3) = ws1.Cells(rowy, coli) & "-sheet1" ' copy sheet 1 to the right spot of sheet 3
ws3.Cells(rowy, Coli3 + 1) = ws2.Cells(rowy, coli) & "-sheet2" 'copy sheet 2 to the right spot of sheet 3
ws3.Cells(rowy, Coli3 + 2) = "Difference"
Else
If ws1.Cells(rowy, 1) = ws2.Cells(rowy, 1) Then
ws3.Cells(rowy, 1) = ws1.Cells(rowy, 1)
ws3.Cells(rowy, Coli3) = Format(ws1.Cells(rowy, coli).Value, "#,##0") ' copy sheet 1 to the right spot of sheet 3
ws3.Cells(rowy, Coli3 + 1) = Format(ws2.Cells(rowy, coli).Value, "#,##0") 'copy sheet 2 to the right spot of sheet 3
ws3.Cells(rowy, Coli3 + 2) = Format((ws1.Cells(rowy, coli).Value) - (ws2.Cells(rowy, coli).Value), "#,##0")
Else
ws3.Cells(rowy, 1) = ws1.Cells(rowy, 1)
ws3.Cells(rowy, Coli3) = Format(ws1.Cells(rowy, coli).Value, "#,##0") ' copy sheet 1 to the right spot of sheet 3
ws3.Cells(rowy, Coli3 + 1).Value = 0 'copy sheet 2 to the right spot of sheet 3
ws3.Cells(rowy, Coli3 + 2) = Format((ws1.Cells(rowy, coli).Value) - (ws2.Cells(rowy, coli).Value), "#,##0")
End If
End If
Next rowy ' move to the next row on ws1, ws2, ws3
'Since we are placing 3 cols at a time in sheet 3 we increment differently
Coli3 = Coli3 + 3 '1 becomes 4, 4 becomes 7, 7 becomes 10 and so on
Next coli 'move to next column on ws1, ws2
End Sub
Please assist.
Give it a try. The strategy is to collect all unique string values in a buffer and store their row values in an index buffer (supposing one string occures only once on one sheet). Then take all row values from index buffer and copy values from that row to ws3.
N.B.: i replaced the type of loop and lastrow counters to long.
Sub Macro5()
'
' Macro5 Macro
'
'
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim ws3 As Worksheet
Dim coli As Long
Dim Coli3 As Long
Dim rowy As Long
Dim numCols As Long
Dim lastRow1 As Long ' last row on sheet1 in the actual data column
Dim lastRow2 As Long ' last row on sheet2 in the actual data column
Dim r1stSheet As Range ' string column range on sheet1
Dim r2ndSheet As Range ' string column range on sheet2
Dim rFnd As Range ' aux for search
Const MAXROW = 100 ' max number of rows
Const HDRROW = 6 ' row where the header is
Dim aStr(1 To MAXROW) As String ' strings in col1
Dim aNdx(1 To MAXROW, 1 To 2) As Long ' col1: row on sheet1 or 0, col2: row on sheet2 or 0
Dim iCnt As Long ' last valid entry in aNdx
' Dim dict As Scripting.Dictionary
startRow = 6 'assuming data starts here
Coli3 = 2 ' start the columns out on ws3
Set ws1 = ThisWorkbook.Worksheets("sheet1")
Set ws2 = ThisWorkbook.Worksheets("sheet2")
Set ws3 = ThisWorkbook.Worksheets("sheet3")
' Application.ScreenUpdating = False
ws3.Cells.Clear
' make a unique list of all strings on sheet1 and sheet2
lastRow1 = ws1.Cells(ws1.Rows.Count, 1).End(xlUp).Row
lastRow2 = ws2.Cells(ws2.Rows.Count, 1).End(xlUp).Row
Set r1stSheet = Range(ws1.Cells(6, 1), ws1.Cells(lastRow1, 1))
Set r2ndSheet = Range(ws2.Cells(6, 1), ws2.Cells(lastRow2, 1))
iCnt = 0
For rowy = HDRROW + 1 To lastRow1 ' process sheet1 against sheet2
If ws1.Cells(rowy, 1) <> vbNullString Then
iCnt = iCnt + 1
Set rFnd = r2ndSheet.Find(What:=ws1.Cells(rowy, 1), LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlRows, SearchDirection:=xlNext, MatchCase:=False)
aStr(iCnt) = ws1.Cells(rowy, 1)
aNdx(iCnt, 1) = rowy
If rFnd Is Nothing Then ' not found matching string
aNdx(iCnt, 2) = 0
Else ' match found
aNdx(iCnt, 2) = rFnd.Row
End If
End If
Next rowy ' on sheet1
For rowy = HDRROW + 1 To lastRow2 ' process sheet2 against sheet1: find nonmatching values
If ws2.Cells(rowy, 1) <> vbNullString Then
Set rFnd = r1stSheet.Find(What:=ws2.Cells(rowy, 1), LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlRows, SearchDirection:=xlNext, MatchCase:=False)
If rFnd Is Nothing Then ' not found matching string
iCnt = iCnt + 1
aStr(iCnt) = ws2.Cells(rowy, 1)
aNdx(iCnt, 1) = 0
aNdx(iCnt, 2) = rowy
End If
End If
Next rowy ' on sheet2
rFnd = Nothing
For i = 1 To iCnt
ws3.Cells(i + HDRROW, 1) = aStr(i) ' strings
Next i
'Find how many columns there are in sheet1 based on data in row 1
numCols = ws1.Cells(HDRROW + 1, Columns.Count).End(xlToLeft).Column
For coli = 2 To numCols
ws3.Cells(HDRROW, Coli3) = "sheet1" ' copy sheet 1 to the right spot of sheet 3
ws3.Cells(HDRROW, Coli3 + 1) = "sheet2" 'copy sheet 2 to the right spot of sheet 3
ws3.Cells(HDRROW, Coli3 + 2) = "Difference"
For i = 1 To iCnt
If aNdx(i, 1) = 0 Then
ws3.Cells(i + HDRROW, Coli3) = 0
Else
ws3.Cells(i + HDRROW, Coli3) = ws1.Cells(aNdx(i, 1), coli).Value ' val1
End If
If aNdx(i, 2) = 0 Then
ws3.Cells(i + HDRROW, Coli3 + 1) = 0
Else
ws3.Cells(i + HDRROW, Coli3 + 1) = ws2.Cells(aNdx(i, 2), coli).Value ' val2
End If
ws3.Cells(i + HDRROW, Coli3 + 2) = ws3.Cells(i + HDRROW, Coli3) - ws3.Cells(i + HDRROW, Coli3 + 1) ' diff
Next i
' finished with data, format columns
Range(ws3.Cells(HDRROW + 1, Coli3), ws3.Cells(iCnt + HDRROW, Coli3 + 2)).NumberFormat = "#.##0"
'Since we are placing 3 cols at a time in sheet 3 we increment differently
Coli3 = Coli3 + 3 '1 becomes 4, 4 becomes 7, 7 becomes 10 and so on
Next coli 'move to next column on ws1, ws2
End Sub
I need help to copy and paste a single row for every cell in another column multiple times starting in the second row.
The raw data looks like this
I need it to look like this
ActiveWorkbook.Names.Add Name:="data1", RefersToR1C1:="=Sheet2!R2C5:R2C7"
ActiveWorkbook.Names("data1").Comment = "" Range("data1").Copy
Range("B1").Select ActiveCell.Offset(1, 0).Select ActiveCell.PasteSpecial
Here is where I get lost. I am not sure how to loop it down and then keep it going and copy column a down and then the defined range again.
I also tried this:
Dim LastRow As Variant
Dim LastRowA As Variant
Dim Row As Range
Dim i As Integer
With Sheets("Store_Item_copy")
LastRow = .Range("A2" & Row.Count).End(xlUp).Row
End With
Range("A2" & LastRow).Copy
For i = 2 To LastRow
i = i + 1
With Sheets("Store_Item_copy")
LastRowA = .Range("A" & .Rows.Count).End(xlUp).Row
End With
LastRowA.Offset(1, 0).Select
ActiveCell.PasteSpecial
Next i
Here is one way to do it using arrays.
Option Explicit
Public Sub PopulateColumns()
Dim wb As Workbook
Dim wsSource As Worksheet
Set wb = ThisWorkbook
Set wsSource = wb.Worksheets("Sheet1") 'Change as appropriate
Dim yearArr()
yearArr = wsSource.Range("E2:F" & wsSource.Cells(wsSource.Rows.Count, "E").End(xlUp).Row).Value
Dim storesArr()
storesArr = wsSource.Range("A2:C" & wsSource.Cells(wsSource.Rows.Count, "A").End(xlUp).Row).Value
Dim resultArr()
ReDim resultArr(1 To UBound(storesArr, 1) * UBound(yearArr, 1), 1 To 3)
Dim counter As Long
Dim counter2 As Long
Dim x As Long, y As Long
For x = 1 To UBound(yearArr, 1)
counter2 = counter2 + 1
For y = 1 To UBound(storesArr, 1)
counter = counter + 1
resultArr(counter, 1) = storesArr(y, 1)
resultArr(counter, 2) = yearArr(counter2, 1)
resultArr(counter, 3) = yearArr(counter2, 2)
Next y
Next x
wsSource.Range("A2").Resize(UBound(resultArr, 1), UBound(resultArr, 2)).Value = resultArr
End Sub
I need to compare 1 worksheet (Sheet1) to another similar worksheet (Sheet2)
Sheet2 contains up to date information,which needs to be transferred to Sheet1.
However, I've run into a couple of problems:
There are some rows in Sheet1 that are not Sheet2. These need to be ignored/skipped over
There are some rows in Sheet2 that are not Sheet1. These need to be appended to the end of Sheet1
If a row exists in both Sheets, the information from the row sheet 2 needs to be transferred to the corresponding row in Sheet1
For what its worth, they have same number of columns and the column titles are exactly the same.
I've tried using a dictionary object to accomplish this but am still having all sorts of trouble.
Here's the code I have tried thus far:
Sub createDictionary()
Dim dict1, dict2 As Object
Set dict1 = CreateObject("Scripting.Dictionary")
Set dict2 = CreateObject("Scripting.Dictionary")
Dim maxRows1, maxRows2 As Long
Dim i, ii, j, k As Integer
maxRows1 = Worksheets("Sheet1").Range("A65000").End(xlUp).Row
For i = 2 To maxRows1
Dim cell1 As String
cell1 = Worksheets("Sheet1").cells(i, 2).Text & " " & Worksheets("Sheet1").cells(i, 11).Text
If Not dict1.Exists(cell1) Then
dict1.Add cell1, cell1
End If
Next i
maxRows2 = Worksheets("Sheet2").Range("A65000").End(xlUp).Row
For ii = 2 To maxRows2
Dim cell2 As String
cell2 = Worksheets("Sheet2").cells(ii, 11).Text
If Not dict2.Exists(cell2) Then
dict2.Add cell2, cell2
End If
Next ii
Dim rngSearch1, rngFound1, rngSearch2, rngFound2 As Range
For j = 2 To maxRows1
Dim Sheet1Str, Sheet2Str As String
Sheet1Str = Worksheets("Sheet1").cells(j, 2).Text & " " & Worksheets("Sheet1").cells(j, 11).Text
Sheet2Str = Worksheets("Sheet2").cells(j, 11).Text
If dict2.Exists(Sheet1Str) = False Then
'ElseIf Not dict1.Exists(Sheet2) Then
'
' Worksheets("Sheet2").Range("A" & j & ":" & "Z" & j).Copy
' Worksheets("Sheet1").Range("A" & maxRows1 + 1).Insert
' Worksheets("Sheet1").Range("A" & maxRows1 + 1).Interior.Color = RGB(255, 255, 0)
' Worksheets("Sheet1").Range("U" & maxRows1 + 1) = "INCH"
' Worksheets("Sheet1").Range("Q" & maxRows1 + 1) = "FPM"
' Worksheets("Sheet1").Range("S" & maxRows1 + 1) = "INCHES WIDE"
' Worksheets("Sheet2").Range("K" & j) = Replace(Worksheets("Sheet2").Range("K" & j), Worksheets("Sheet2").Range("B" & j), "")
' Worksheets("Sheet1").Range("K" & maxRows1 + 1) = Trim(Worksheets("Sheet2").Range("K" & j))
Else
For k = 3 To 6
If Not k = 11 Then
If Not UCase(Worksheets("Sheet1").cells(j, k).Value) = UCase(Worksheets("Sheet2").cells(j, k).Value) Then
Worksheets("Sheet1").cells(j, k).Value = Worksheets("Sheet2").cells(j, k).Value
End If
End If
Next k
End If
Next j
End Sub
Cool question, and the "does row order matter" question above lends itself nicely to using Excel's built in Range.RemoveDuplicates method. Let's get into it...
Suppose Sheet1 looks like this:
Let's say Sheet2 looks like this:
All the conditions that are described in your original question are met here. Namely:
There are rows on Sheet1 that are not on Sheet2 (row 2, for example). These will be left alone.
There are rows on Sheet2 that are not on Sheet1 (row 2, for example). These will be added to Sheet1.
There are rows that are the same on Sheet2 and Sheet1, save for a single update. (Row 7 on Sheet2, for example.) These rows will be updated on Sheet1. Of course, your situation will be different -- perhaps more columns might be updated, or they might not be in column E like my example -- you'll need to do a bit of customization here.
The following heavily-commented script walks through copying data from Sheet2 to Sheet1, then letting Excel's built-in Range.RemoveDuplicates method kill all of the rows that have been updated in column E. The script also makes use of a couple handy functions: LastRowNum and LastColNum.
Option Explicit
Sub MergeSheetTwoIntoSheetOne()
Dim Range1 As Range, Range2 As Range
Dim LastRow1 As Long, LastRow2 As Long, _
LastCol As Long
'setup - set references up-front
LastRow2 = LastRowNum(Sheet2)
LastRow1 = LastRowNum(Sheet1)
LastCol = LastColNum(Sheet1) '<~ last col the same on both sheets
'setup - identify the data block on sheet 2
With Sheet2
Set Range2 = .Range(.Cells(2, 1), .Cells(LastRow2, LastCol))
End With
'setup - identify the data block on sheet 1
With Sheet1
Set Range1 = .Range(.Cells(2, 1), .Cells(LastRow1, LastCol))
End With
'step 1 - move the data block on sheet 1 down the sheet
' to allow room for the data block from sheet 2
Range1.Cut Destination:=Sheet1.Cells(LastRow2 + 1, 1)
'step 2 - move the data block from sheet 2 into the recently-
' cleared space on sheet 1
Range2.Copy Destination:=Sheet1.Cells(2, 1)
'step 3 - find the NEW last row on sheet 1
LastRow1 = LastRowNum(Sheet1)
'step 4 - use excel's built-in duplicate removal to
' kill all dupes on every column EXCEPT for those
' that might have been updated on sheet 2...
' in this example, Column E is where updates take place
With Sheet1
Set Range1 = .Range(.Cells(2, 1), .Cells(LastRow1, LastCol))
Range1.RemoveDuplicates Columns:=Array(1, 2, 3, 4), Header:=xlYes
End With
End Sub
'this handy function allows us to find the last row with a one-liner
Public Function LastRowNum(Sheet As Worksheet) As Long
If Application.WorksheetFunction.CountA(Sheet.Cells) <> 0 Then
LastRowNum = Sheet.Cells.Find(What:="*", _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious).Row
Else
LastRowNum = 1
End If
End Function
'this handy function allows us to find the last column with a one-liner
Public Function LastColNum(Sheet As Worksheet) As Long
If Application.WorksheetFunction.CountA(Sheet.Cells) <> 0 Then
LastColNum = Sheet.Cells.Find(What:="*", _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious).Column
Else
LastColNum = 1
End If
End Function
Running this script results in the following:
I have this problem in Excel that I want to solve using Macros in VBA. I have a sheet that contains data in this format:
separator
1
2
6
3
8
342
532
separator
72
28
10
21
separator
38
23
234
What I want to do is to create a VBA macro that creates a new sheet for every series of data (a series starts from the "separator" and ends before the next one or at the end of the initial sheet) and copy respective data in the new sheets.
Example:
1
2
6
3
8
342
532
in sheet1
72
28
10
21
in sheet2 etc.
Thank you very much, I appreciate it!
This copies data from beginning to the first separator ("q"):
Sub macro1()
Dim x As Integer
x = 1
Sheets.Add.Name = "Sheet2"
'Get cells until first q
Do Until Sheets("Sheet1").Range("A" & x).Value = "q"
Sheets("Sheet2").Range("A" & x).Value = Sheets("Sheet1").Range("A" & x).Value
x = x + 1
Loop
End Sub
Try this... (UNTESTED)
Const sep As String = "q"
Sub Sample()
Dim ws As Worksheet, wsNew As Worksheet
Dim lRow As Long, i As Long, rw As Long
'~~> Set this to the relevant worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
'~~> Add a new temp sheet
Set wsNew = ThisWorkbook.Sheets.Add
'~~> Set row for the new output sheet
rw = 1
With ws
'~~> Get the last row
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
'~~> Loop through the cells from row 2
'~~> assuming that row 1 has a spearator
For i = 2 To lRow
If .Range("A" & i).Value = sep Then
Set wsNew = ThisWorkbook.Sheets.Add
rw = 1
Else
wsNew.Cells(rw, 1).Value = .Range("A" & i).Value
rw = rw + 1
End If
Next i
End With
End Sub
You could use this to avoid Looping every row. As long as you want to delete the original data as well.
SubSample()
Dim x As Integer
Dim FoundCell As Range
Dim NumberOfQs As Long
Dim SheetWithData As Worksheet
Dim CurrentData As Range
Set SheetWithData = Sheets("Sheet4")
NumberOfQs = WorksheetFunction.CountIf(SheetWithData.Range("A:A"), "q")
x = 1
Set FoundCell = SheetWithData.Range("A1", SheetWithData.Range("A" & Rows.Count)).Find("q", , , , , xlPrevious)
If Not FoundCell Is Nothing Then
Set LastCell = FoundCell.End(xlDown)
Set CurrentData = SheetWithData.Range(FoundCell, LastCell)
Sheets.Add.Name = "QSheetNumber" & x 'Get cells until first q
CurrentData.Cut Sheets("QSheetNumber" & x).Range("A1")
Sheets("QSheetNumber" & x).Rows(1).Delete
x = x + 1
Set FoundCell = SheetWithData.Range("A1", SheetWithData.Range("A" & Rows.Count)).Find("q", FoundCell, , , , xlPrevious)
If Not FoundCell Is Nothing Then
Set LastCell = FoundCell.End(xlDown)
Set CurrentData = SheetWithData.Range(FoundCell, LastCell)
Sheets.Add.Name = "QSheetNumber" & x 'Get cells until first q
CurrentData.Cut Sheets("QSheetNumber" & x).Range("A1")
Sheets("QSheetNumber" & x).Rows(1).Delete
x = x + 1
Else
Exit Sub
End If
Else
Exit Sub
End If
End Sub