Add 5 rows for each row using VBA Macros - excel

Hi All i have two worksheets from Sheet1 i am copying to Sheet2 which copy data to each row once now i want my data should be look like "To be Version" :
First column will be repeated 5 time and other column should be only once i am trying but it does not working ..
I am using Macros to do this
Function getLastRow(targetSheet As Worksheet, colLetter As String) As Integer
Dim lastRow As Integer
With targetSheet
getLastRow = .Cells(.Rows.count, colLetter).End(xlUp).Row
End With
End Function
Function getColumn(targetSheet As Worksheet, FindWord As String, Optional iRow As Integer = 1) As Integer
Dim iCol As Integer
Dim tmpString As String
For iCol = 1 To getLastColumn(targetSheet, 2)
'targetSheet.Activate
tmpString = VBA.Replace(targetSheet.Cells(iRow, iCol).Value, "", "")
If VBA.InStr(1, VBA.LCase(tmpString), VBA.Replace(VBA.LCase(FindWord), "", "")) Then
getColumn = iCol
Exit Function
End If
Next iCol
End Function
Sub ProcFile()
Dim wsRaw As Worksheet: Set wsRaw = ThisWorkbook.Sheets("Sheet1")
Dim wsAR As Worksheet: Set wsAR = ThisWorkbook.Sheets("Sheet2")
Dim iRow, x, LRow, sRow, col As Long
Dim Tes1, Test2, Test3 As String
sRow = getLastRow(wsAR, "E") + 1
LRow = getLastRow(wsRaw, "A")
If wsRaw.Range("A2").Value = "" Then MsgBox "Raw Data tab is Empty!!", vbCritical: Exit Sub
For x = 2 To LRow
Tes1 = wsRaw.Cells(x, getColumn(wsRaw, "Tes1")).Value
Test2 = wsRaw.Cells(x, getColumn(wsRaw, "Test2")).Value
Test3 = wsRaw.Cells(x, getColumn(wsRaw, "Test3")).Value
For col = 3 To 45 Step 2
If wsRaw.Cells(x, col).Value <> "" Then
wsAR.Range("A" & sRow).Value = Tes1
wsAR.Range("B" & sRow).Value = Test2
wsAR.Range("C" & sRow).Value = Test3
End If
Next col
sRow = sRow + 1
Next x
MsgBox "Done!!"
End Sub
Sheet 1 Raw Data
Sheet 2 Data in after macro excution
The Data i am getting in my Macro excution:

Repeat Rows
Quick Help (Not tested)
Replace the line
sRow = sRow + 1
with
sRow = sRow + 5
Instead of the lines:
wsAR.Range("A" & sRow).Value = Tes1
wsAR.Range("B" & sRow).Value = Test2
wsAR.Range("C" & sRow).Value = Test3
use the following:
wsAR.Range("B" & sRow).Value = Test2
wsAR.Range("C" & sRow).Value = Test3
For sRow = sRow To sRow + 4
wsAR.Range("A" & sRow).Value = Test1
Next sRow
sRow = sRow - 5
Initial Answer
The following will overwrite a range in the following way:
The first row (the headers) stays the same.
Every value in the first column will be written five times, one below the other.
The remaining columns will be written only once leaving four empty cells below.
Option Explicit
Sub repeatRows()
Const wsName As String = "Sheet2"
Const RowsCount As Long = 4
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim rg As Range: Set rg = wb.Worksheets(wsName).Range("A1").CurrentRegion
Dim Data As Variant: Data = rg.Value
Dim srCount As Long: srCount = UBound(Data, 1)
Dim cCount As Long: cCount = UBound(Data, 2)
Dim drCount As Long: drCount = (srCount - 1) * (RowsCount + 1) + 1
Dim Result As Variant: ReDim Result(1 To drCount, 1 To cCount)
Dim c As Long
For c = 1 To cCount
Result(1, c) = Data(1, c)
Next c
Dim n As Long: n = 1
Dim r As Long, i As Long
For r = 2 To srCount
n = n + 1
For c = 1 To cCount
Result(n, c) = Data(r, c)
Next c
For i = 1 To RowsCount
n = n + 1
Result(n, 1) = Data(r, 1)
Next i
Next r
rg.Resize(n).Value = Result
End Sub

Related

If 2 values from different sheets are equal, copy the rest of the row

I have 2 sheets with multiple rows and columns like this:
Sheet1:
I want to search each value from Sheet1, Column B in Sheet2, Column B then:
If the value is equal => Copy the rest of the row in sheet1.
At the end, sheet1 should look like this:
and Sheet2 the same, I don't modify in that, only I take from that the rest of the rows.
Thank you very much,
I have tried something like this:
Sub Compare()
Dim n As Integer
Dim sh As Worksheets
Dim r As Range
n = 1000
Dim match As Boolean
Dim valE As Double
Dim valI As Double
Dim I As Long, J As Long
For I = 2 To n
val1 = Worksheets("Sheet1").Range("B" & I).Value
val2 = Worksheets("Sheet2").Range("B" & I).Value
If val1 = val2 Then
Worksheets("Sheet1").Range("C" & I).Value = Worksheets("Sheet2").Range("C" & I)
Worksheets("Sheet1").Range("D" & I).Value = Worksheets("Sheet2").Range("D" & I)
Worksheets("Sheet1").Range("E" & I).Value = Worksheets("Sheet2").Range("E" & I)
I = I + 1
End If
Next I
Application.ScreenUpdating = True
End Sub
It works for 10 values or so, but I have 1200 values and it just doesn't do anything.
A VBA Lookup: Copy Rows
Type Wks
Name As String
LookupColumn As Long
FirstColumn As Long
End Type
Sub LookupData()
Dim Src As Wks
Src.Name = "Sheet2"
Src.LookupColumn = 2
Src.FirstColumn = 3
Dim Dst As Wks
Dst.Name = "Sheet1"
Dst.LookupColumn = 2
Dst.FirstColumn = 3
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Read source.
Dim sws As Worksheet: Set sws = wb.Worksheets(Src.Name)
Dim srg As Range, slData() As Variant, srCount As Long, cCount As Long
With sws.Range("A1").CurrentRegion
srCount = .Rows.Count - 1
cCount = .Columns.Count
If srCount = 0 Then Exit Sub
Set srg = .Resize(srCount).Offset(1)
End With
With srg.Columns(Src.LookupColumn)
If srCount = 1 Then
ReDim slData(1 To 1, 1 To 1): slData(1, 1) = .Value
Else
slData = .Value
End If
End With
Dim cOffset As Long: cOffset = Src.FirstColumn - 1
cCount = cCount - cOffset
Dim svData() As Variant
With srg.Resize(, cCount).Offset(, cOffset)
If srCount * cCount = 1 Then
ReDim svData(1 To 1, 1 To 1): svData = .Value
Else
svData = .Value
End If
End With
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Dim r As Long, cString As String
For r = 1 To srCount
cString = CStr(slData(r, 1))
If Not dict.Exists(cString) Then dict(cString) = r
Next r
' Read destination.
Dim dws As Worksheet: Set dws = wb.Worksheets(Dst.Name)
Dim drg As Range, dlData() As Variant, drCount As Long
With dws.Range("A1").CurrentRegion
drCount = .Rows.Count - 1
If drCount = 0 Then Exit Sub
Set drg = .Resize(drCount).Offset(1)
End With
With drg.Columns(Dst.LookupColumn)
If drCount = 1 Then
ReDim dlData(1 To 1, 1 To 1): dlData(1, 1) = .Value
Else
dlData = .Value
End If
End With
Dim dvData() As Variant: ReDim dvData(1 To drCount, 1 To cCount)
' Lookup and write to destination.
Dim dr As Long, c As Long
For r = 1 To drCount
cString = CStr(dlData(r, 1))
If dict.Exists(cString) Then
dr = dict(cString)
For c = 1 To cCount
dvData(r, c) = svData(dr, c)
Next c
End If
Next r
Dim dfCell As Range: Set dfCell = drg.Columns(Dst.FirstColumn).Cells(1)
Dim dvrg As Range: Set dvrg = dfCell.Resize(drCount, cCount)
dvrg.Value = dvData
' Inform.
MsgBox "Data copied.", vbInformation
End Sub

Transposing ranges separated by blanks rows

I've been trying to tinker with this source code that transposes 1 column separated by spaces.
Sub Transpose()
Dim lastrow As Long, i As Long, j As Long, iStart As Long, iEnd As Long
Dim ws As Worksheet
Application.ScreenUpdating = False
With Sheets("Sheet1")
Set ws = Sheets.Add(after:=Sheets(Sheets.Count))
lastrow = .Cells(Rows.Count, "A").End(xlUp).row
iStart = 1
For i = 1 To lastrow + 1
If .Range("A" & i).Value = "" Then
iEnd = i
j = j + 1
.Range(.Cells(iStart, 1), .Cells(iEnd, 1)).Copy
ws.Range("A" & j).PasteSpecial Paste:=xlPasteValues, Transpose:=True
iStart = iEnd + 1
End If
Next i
End With
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
I'm trying to take take 4 columns ranges with variable rows
[
And transpose each range adjacently so that it looks like this:
Any input appreciated.
Try this out:
Sub Transpose()
Dim ws As Worksheet, cCopy As Range, cPaste As Range
Set ws = Sheets("Sheet1")
Set cCopy = ws.Range("A1") 'top-left of first data block
Set cPaste = ws.Range("F1") 'first output cell
Do While Len(cCopy.Value) > 0 'while have data to transpose
With cCopy.CurrentRegion
Debug.Print "Copying", .Address, " to ", cPaste.Address
cPaste.Resize(.Columns.Count, .Rows.Count) = _
Application.Transpose(.Value)
Set cPaste = cPaste.Offset(.Columns.Count + 1) 'next paste position
Set cCopy = cCopy.Offset(.Rows.Count + 1) 'next data block
End With
Loop
End Sub
Took way too long to do this and the most atrocious architecture but it works.
r = 1
c = 1
cl = 6
rw = 1
For r = 1 To 13
For c = 1 To 4
If Cells(r, c) <> "" Then
Cells(rw, cl) = Cells(r, c)
rw = rw + 1
End If
Next
'If Cells(r, c) = "" Then cl = 6
rw = 1
cl = cl + 1
Next
rw = 5
cl = 6
For r = 1 To 4
For c = 10 To 12
Cells(rw, cl) = Cells(r, c)
cl = cl + 1
Next
rw = rw + 1
cl = 6
Next
rw = 9
cl = 6
For r = 1 To 4
For c = 14 To 18
Cells(rw, cl) = Cells(r, c)
cl = cl + 1
Next
rw = rw + 1
cl = 6
Next
Range("J1:R4").ClearContents
Try this code:
Sub SubRollData()
'Declarations.
Dim RngSource As Range
Dim RngTarget As Range
Dim DblRowOffset As Double
Dim DblColumnOffset As Double
'Settings.
Set RngSource = Range("A1")
Set RngTarget = Range("F1")
'Checkpoint for the block processing.
CP_Block:
'Covering each column.
For DblColumnOffset = 0 To 3
'Setting DblRowOffset to start covering for the first row of the block.
DblRowOffset = 0
'Covering each row of the block of the given column until an empty cell is fount.
Do Until RngSource.Offset(DblRowOffset, DblColumnOffset) = ""
'Reporting the data with switched offset.
RngTarget.Offset(DblColumnOffset, DblRowOffset).Value = RngSource.Offset(DblRowOffset, DblColumnOffset).Value
'Setting DblRowOffset for the next row.
DblRowOffset = DblRowOffset + 1
Loop
Next
'Setting RngSource to aim at the next block.
If RngSource.Offset(1, 0) = "" Then
Set RngSource = RngSource.Offset(2, 0)
Else
Set RngSource = RngSource.End(xlDown).Offset(2, 0)
End If
'Setting RngSource to aim at the next empty row to fill in with data.
If RngTarget.Offset(1, 0) = "" Then
Set RngTarget = RngTarget.Offset(1, 0)
Else
Set RngTarget = RngTarget.End(xlDown).Offset(1, 0)
End If
'If RngSource has no data, there is no more block to be processed. Otherwise, the next block is processed.
If RngSource.Value <> "" Then GoTo CP_Block
End Sub
It works with the example you've given and also with isoletd (single row) source data.
Just for fun, here is a possible formula based solution to be placed in cell F1 and dragged:
=IF(COLUMN(F1)-COLUMN($F1)+1>=AGGREGATE(15,6,1/($A:$A="")*ROW($A:$A),QUOTIENT(ROW(F1)-ROW(F$1),4)+1)-IF(QUOTIENT(ROW(F1)-ROW(F$1),4)=0,0,AGGREGATE(15,6,1/($A:$A="")*ROW($A:$A),QUOTIENT(ROW(F1)-ROW(F$1),4))),"",INDEX($A:$D,COLUMN(F1)-COLUMN($F1)+1+IF(QUOTIENT(ROW(F1)-ROW(F$1),4)=0,0,AGGREGATE(15,6,1/($A:$A="")*ROW($A:$A),QUOTIENT(ROW(F1)-ROW(F$1),4))),MOD(ROW(F1)-ROW(F$1),4)+1))
Naturally it's really heavy and stupidly complicated, but as i said: made it just for fun.
Transpose Groups of Data to a New Worksheet
Sub TransposeGroups()
' Source - use as-is (read (copy) from)
Const sName As String = "Sheet1"
Const sFirstRowAddress As String = "A1:D1"
Const sMandatoryColumnIndex As Long = 1 ' dictates if empty row (gap)
' Destination - delete if exists and put last (write (paste) to)
Const dName As String = "Result"
Const dFirstCellAddress As String = "A1"
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Write the values from the source range to a 2D one-based array
' and write its upper limits to variables.
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim sData As Variant
Dim srCount As Long
Dim scCount As Long
With sws.Range(sFirstRowAddress)
Dim lCell As Range
With .Columns(sMandatoryColumnIndex)
Set lCell = .Resize(sws.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
End With
If lCell Is Nothing Then
MsgBox "No data in column " & sMandatoryColumnIndex & ".", _
vbCritical
Exit Sub
End If
scCount = .Columns.Count
srCount = lCell.Row - .Row + 1
sData = .Resize(srCount).Value
End With
' Loop through the rows of the source array and map the first row,
' the last row and the following gap count (empty rows) in each row
' of three columns of another 2D one-based array.
' Note that this array has the same number of rows as the source array,
' but the data of interest will be in much fewer rows ('mr').
' (Probably a collection of collections (or three element arrays)
' would have been a better choice.)
Dim mArr() As Long: ReDim mArr(1 To srCount, 1 To 3)
Dim sr As Long
Dim sValueFound As Boolean
Dim mr As Long
Dim ccCount As Long
Dim dcCount As Long
Dim GapCount As Long
For sr = 1 To srCount
If Len(CStr(sData(sr, sMandatoryColumnIndex))) > 0 Then
If Not sValueFound Then
mr = mr + 1
mArr(mr, 1) = sr ' first row
sValueFound = True
End If
Else
If sValueFound Then
sValueFound = False
mArr(mr, 2) = sr - 1 ' last row
ccCount = sr - mArr(mr, 1)
If ccCount > dcCount Then dcCount = ccCount
End If
mArr(mr, 3) = mArr(mr, 3) + 1 ' gap
GapCount = GapCount + 1 ' to determine the number of rows of 'dData'
End If
Next sr
' The very last row (of interest).
mArr(mr, 2) = srCount
ccCount = sr - mArr(mr, 1)
If ccCount > dcCount Then dcCount = ccCount
' Using the source array and the information from the mapping array,
' write the results to the destination array.
Dim drCount As Long: drCount = mr * scCount + GapCount
Dim dData As Variant: ReDim dData(1 To drCount, 1 To dcCount)
Dim drFirst As Long
Dim sc As Long
Dim dc As Long
For mr = 1 To mr
For sc = 1 To scCount
For sr = mArr(mr, 1) To mArr(mr, 2)
dc = dc + 1
dData(drFirst + sc, dc) = sData(sr, sc)
Next sr
dc = 0
Next sc
drFirst = drFirst + sc + mArr(mr, 3) - 1
Next mr
' Write the values from the destination array to a new worksheet.
' Check if a sheet with the same name exists.
Dim dsh As Object
On Error Resume Next
Set dsh = wb.Sheets(dName)
On Error GoTo 0
' If it exists, delete it without confirmation.
If Not dsh Is Nothing Then
Application.DisplayAlerts = False
dsh.Delete
Application.DisplayAlerts = True
End If
' Add a new worksheet and rename it accordingly.
Dim dws As Worksheet
Set dws = wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count))
dws.Name = dName
' Write the values from the destination array to the destination worksheet.
With dws.Range(dFirstCellAddress)
.Resize(drCount, dcCount).Value = dData
End With
' Inform.
MsgBox "Groups transposed.", vbInformation
End Sub

ordering and filter in excel

Column A
Column B
Column C
Column D
John
22
David
87
Marcy
42
Kumar
23
Kumar
35
Marcy
42
David
21
John
33
In excel ordering Column C according Column A, the data of column C e D are to move together.
Ex: First row will be
Column A
Column B
Column C
Column D
John
22
John
33
I've tried excel functions like:
PROCV, VLOOKUP and the sort and filter button in excel with no luck.
Note:
All rows must be uniquely identified by the name in column a
You need to reference Microsoft Scripting Runtime
... anyway
Sub sheesh()
Set dict = CreateObject("Scripting.Dictionary")
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets(1)
Dim lastRow As Long: lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim i As Integer
For i = 1 To lastRow
dict.Add CStr(ws.Cells(i, 3).Value), CInt(ws.Cells(i, 4).Value)
Next i
For Each k In dict.Keys
Debug.Print k
Next
For i = 1 To lastRow
If dict.Exists(ws.Cells(i, 1).Value) Then
ws.Cells(i, 3).Value = ws.Cells(i, 1).Value
ws.Cells(i, 4).Value = dict(ws.Cells(i, 1).Value)
End If
Next i
End Sub
Align Data
Option Explicit
Sub AlignData()
Const fRow As Long = 1
Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
Dim Key As Variant
Dim r As Long
' Left two columns to left dictionary.
Dim llRow As Long: llRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Dim lCount As Long: lCount = llRow - fRow + 1
Dim lrg As Range: Set lrg = ws.Cells(fRow, "A").Resize(lCount, 2)
Dim lData As Variant: lData = lrg.Value
Dim lDict As Object: Set lDict = CreateObject("Scripting.Dictionary")
lDict.CompareMode = vbTextCompare
For r = 1 To lCount
Key = lData(r, 1)
If Not IsError(Key) Then ' exclude error values
If Len(Key) > 0 Then ' exclude blanks
lDict(lData(r, 1)) = lDict(lData(r, 1)) + lData(r, 2) ' Sum
End If
End If
Next r
Erase lData
lCount = lDict.Count
' Right two columns to right dictionary.
Dim rlRow As Long: rlRow = ws.Cells(ws.Rows.Count, "C").End(xlUp).Row
Dim rCount As Long: rCount = rlRow - fRow + 1
Dim rrg As Range: Set rrg = ws.Cells(fRow, "C").Resize(rCount, 2)
Dim rData As Variant: rData = rrg.Value
Dim rDict As Object: Set rDict = CreateObject("Scripting.Dictionary")
rDict.CompareMode = vbTextCompare
For r = 1 To rCount
Key = rData(r, 1)
If Not IsError(Key) Then ' exclude error values
If Len(Key) > 0 Then ' exclude blanks
rDict(rData(r, 1)) = rDict(rData(r, 1)) + rData(r, 2) ' Sum
End If
End If
Next r
Erase rData
rCount = rDict.Count
' Write to destination arrays.
ReDim lData(1 To lCount, 1 To 2) ' exact size
ReDim rData(1 To lCount + rCount, 1 To 2) ' oversized
r = 0
For Each Key In lDict.Keys
r = r + 1
lData(r, 1) = Key: lData(r, 2) = lDict(Key)
If rDict.Exists(Key) Then
rData(r, 1) = Key: rData(r, 2) = rDict(Key)
rDict.Remove Key
End If
Next Key
If rDict.Count > 0 Then
For Each Key In rDict.Keys
r = r + 1
rData(r, 1) = Key: rData(r, 2) = rDict(Key)
Next Key
End If
' Overwrite ranges.
With lrg
.Resize(lDict.Count).Value = lData
.Resize(ws.Rows.Count - .Row - lCount + 1).Offset(lCount).ClearContents
End With
With rrg
.Resize(r).Value = rData
.Resize(ws.Rows.Count - .Row - r + 1).Offset(r).ClearContents
End With
MsgBox "Data aligned.", vbInformation
End Sub

VBA to seperate and transpose data into rows [duplicate]

This question already has answers here:
Split comma separated entries to new rows [closed]
(2 answers)
Closed 1 year ago.
I currently have this data in a sheet
Col A Col B Col C
1 A angry birds, gaming
2 B nirvana,rock,band
What I want to do is split the comma separated entries in the third column and insert in new rows like below:
Col A Col B Col C
1 A angry birds
1 A gaming
2 B nirvana
2 B rock
2 B band
I am sure this can be done with VBA but couldn't figure it out myself.
variant using Scripting.Dictionary
Sub ttt()
Dim dic As Object: Set dic = CreateObject("Scripting.Dictionary")
Dim x&, cl As Range, rng As Range, k, s
Set rng = Range([C1], Cells(Rows.Count, "C").End(xlUp))
x = 1 'used as a key for dictionary and as row number for output
For Each cl In rng
For Each s In Split(cl.Value2, ",")
dic.Add x, Cells(cl.Row, "A").Value2 & "|" & _
Cells(cl.Row, "B").Value2 & "|" & LTrim(s)
x = x + 1
Next s, cl
For Each k In dic
Range(Cells(k, "A"), Cells(k, "C")).Value2 = Split(dic(k), "|")
Next k
End Sub
source:
result:
If you have a substantial amount of data, you willfind working with arrays beneficial.
Sub Macro2()
Dim i As Long, j As Long, rws As Long
Dim inp As Variant, outp As Variant
With Worksheets("sheet2")
inp = .Range(.Cells(1, "A"), .Cells(.Rows.Count, "C").End(xlUp)).Value2
For i = LBound(inp, 1) To UBound(inp, 1)
rws = rws + UBound(Split(inp(i, 3), ",")) + 1
Next i
ReDim outp(1 To rws, 1 To 3)
rws = 0
For i = LBound(inp, 1) To UBound(inp, 1)
For j = 0 To UBound(Split(inp(i, 3), ","))
rws = rws + 1
outp(rws, 1) = inp(i, 1)
outp(rws, 2) = inp(i, 2)
outp(rws, 3) = Trim(Split(inp(i, 3), ",")(j))
Next j
Next i
.Cells(1, "A").Resize(UBound(outp, 1), UBound(outp, 2)) = outp
End With
End Sub
This is not a polished solution, but I need to spend some time with the wife.
But still another way of thinking about it.
This code assumes that the sheet is called Sheet4 and the range that needs to be split is col C.
Dim lastrow As Integer
Dim i As Integer
Dim descriptions() As String
With Worksheets("Sheet4")
lastrow = .Range("C1").End(xlDown).Row
For i = lastrow To 2 Step -1
If InStr(1, .Range("C" & i).Value, ",") <> 0 Then
descriptions = Split(.Range("C" & i).Value, ",")
End If
For Each Item In descriptions
.Range("C" & i).Value = Item
.Rows(i).Copy
.Rows(i).Insert
Next Item
.Rows(i).EntireRow.Delete
Next i
End With
This will do what you want.
Option Explicit
Const ANALYSIS_ROW As String = "C"
Const DATA_START_ROW As Long = 1
Sub ReplicateData()
Dim iRow As Long
Dim lastrow As Long
Dim ws As Worksheet
Dim iSplit() As String
Dim iIndex As Long
Dim iSize As Long
'Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
With ThisWorkbook
.Worksheets("Sheet1").Copy After:=.Worksheets("Sheet1")
Set ws = ActiveSheet
End With
With ws
lastrow = .Cells(.Rows.Count, ANALYSIS_ROW).End(xlUp).Row
End With
For iRow = lastrow To DATA_START_ROW Step -1
iSplit = Split(ws.Cells(iRow, ANALYSIS_ROW).Value2, ",")
iSize = UBound(iSplit) - LBound(iSplit) + 1
If iSize = 1 Then GoTo Continue
ws.Rows(iRow).Copy
ws.Rows(iRow).Resize(iSize - 1).Insert
For iIndex = LBound(iSplit) To UBound(iSplit)
ws.Cells(iRow, ANALYSIS_ROW).Offset(iIndex).Value2 = iSplit(iIndex)
Next iIndex
Continue:
Next iRow
Application.CutCopyMode = False
Application.Calculation = xlCalculationAutomatic
'Application.ScreenUpdating = True
End Sub

Excel macro -Split comma separated entries to new rows [duplicate]

This question already has answers here:
Split comma separated entries to new rows [closed]
(2 answers)
Closed 1 year ago.
I currently have this data in a sheet
Col A Col B Col C
1 A angry birds, gaming
2 B nirvana,rock,band
What I want to do is split the comma separated entries in the third column and insert in new rows like below:
Col A Col B Col C
1 A angry birds
1 A gaming
2 B nirvana
2 B rock
2 B band
I am sure this can be done with VBA but couldn't figure it out myself.
variant using Scripting.Dictionary
Sub ttt()
Dim dic As Object: Set dic = CreateObject("Scripting.Dictionary")
Dim x&, cl As Range, rng As Range, k, s
Set rng = Range([C1], Cells(Rows.Count, "C").End(xlUp))
x = 1 'used as a key for dictionary and as row number for output
For Each cl In rng
For Each s In Split(cl.Value2, ",")
dic.Add x, Cells(cl.Row, "A").Value2 & "|" & _
Cells(cl.Row, "B").Value2 & "|" & LTrim(s)
x = x + 1
Next s, cl
For Each k In dic
Range(Cells(k, "A"), Cells(k, "C")).Value2 = Split(dic(k), "|")
Next k
End Sub
source:
result:
If you have a substantial amount of data, you willfind working with arrays beneficial.
Sub Macro2()
Dim i As Long, j As Long, rws As Long
Dim inp As Variant, outp As Variant
With Worksheets("sheet2")
inp = .Range(.Cells(1, "A"), .Cells(.Rows.Count, "C").End(xlUp)).Value2
For i = LBound(inp, 1) To UBound(inp, 1)
rws = rws + UBound(Split(inp(i, 3), ",")) + 1
Next i
ReDim outp(1 To rws, 1 To 3)
rws = 0
For i = LBound(inp, 1) To UBound(inp, 1)
For j = 0 To UBound(Split(inp(i, 3), ","))
rws = rws + 1
outp(rws, 1) = inp(i, 1)
outp(rws, 2) = inp(i, 2)
outp(rws, 3) = Trim(Split(inp(i, 3), ",")(j))
Next j
Next i
.Cells(1, "A").Resize(UBound(outp, 1), UBound(outp, 2)) = outp
End With
End Sub
This is not a polished solution, but I need to spend some time with the wife.
But still another way of thinking about it.
This code assumes that the sheet is called Sheet4 and the range that needs to be split is col C.
Dim lastrow As Integer
Dim i As Integer
Dim descriptions() As String
With Worksheets("Sheet4")
lastrow = .Range("C1").End(xlDown).Row
For i = lastrow To 2 Step -1
If InStr(1, .Range("C" & i).Value, ",") <> 0 Then
descriptions = Split(.Range("C" & i).Value, ",")
End If
For Each Item In descriptions
.Range("C" & i).Value = Item
.Rows(i).Copy
.Rows(i).Insert
Next Item
.Rows(i).EntireRow.Delete
Next i
End With
This will do what you want.
Option Explicit
Const ANALYSIS_ROW As String = "C"
Const DATA_START_ROW As Long = 1
Sub ReplicateData()
Dim iRow As Long
Dim lastrow As Long
Dim ws As Worksheet
Dim iSplit() As String
Dim iIndex As Long
Dim iSize As Long
'Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
With ThisWorkbook
.Worksheets("Sheet1").Copy After:=.Worksheets("Sheet1")
Set ws = ActiveSheet
End With
With ws
lastrow = .Cells(.Rows.Count, ANALYSIS_ROW).End(xlUp).Row
End With
For iRow = lastrow To DATA_START_ROW Step -1
iSplit = Split(ws.Cells(iRow, ANALYSIS_ROW).Value2, ",")
iSize = UBound(iSplit) - LBound(iSplit) + 1
If iSize = 1 Then GoTo Continue
ws.Rows(iRow).Copy
ws.Rows(iRow).Resize(iSize - 1).Insert
For iIndex = LBound(iSplit) To UBound(iSplit)
ws.Cells(iRow, ANALYSIS_ROW).Offset(iIndex).Value2 = iSplit(iIndex)
Next iIndex
Continue:
Next iRow
Application.CutCopyMode = False
Application.Calculation = xlCalculationAutomatic
'Application.ScreenUpdating = True
End Sub

Resources