I'm very briefly familiar with vba and I cannot work out how to amend the following script to make it do what I expect.
Basically I have 5 column excel. Column A are the values I would like to sum, providing that B and C and D and E are unique as a row.
I found the following script, which does nearly what I need:
Option Explicit
Sub RedoDataset()
Dim LastCol As Long
Dim LastRowData As Long
Dim LastRow As Long
Dim Ctr As Long
Dim CompanyArr
Dim RowFoundArr
Dim SumArr
Dim Rng As Range
Dim SettingsArray(1 To 2) As Integer
On Error Resume Next
With Application
SettingsArray(1) = .Calculation
SettingsArray(2) = .ErrorCheckingOptions.BackgroundChecking
.Calculation = xlCalculationManual
.EnableEvents = False
.ErrorCheckingOptions.BackgroundChecking = False
.ScreenUpdating = False
End With
On Error GoTo 0
With ThisWorkbook
With .Sheets("Sheet1")
LastRowData = .Cells(Rows.Count, 1).End(xlUp).Row
LastCol = .Cells(1, Columns.Count).End(xlToLeft).Column
Set Rng = .Range(.Cells(1, 1), .Cells(1, LastCol))
.Columns(2).AdvancedFilter Action:=xlFilterCopy, _
CopyToRange:=.Cells(1, LastCol + 2), Unique:=True
LastRow = .Cells(Rows.Count, LastCol + 2).End(xlUp).Row
ReDim CompanyArr(1 To LastRow - 1)
ReDim RowFoundArr(1 To LastRow - 1)
ReDim SumArr(1 To LastRow - 1)
For Ctr = 1 To LastRow - 1
CompanyArr(Ctr) = .Cells(Ctr + 1, LastCol + 2)
RowFoundArr(Ctr) = Application.Match(CompanyArr(Ctr), .Columns(2), 0)
SumArr(Ctr) = Application.SumIf(.Columns(2), CompanyArr(Ctr), .Columns(1))
.Cells(RowFoundArr(Ctr), 1) = SumArr(Ctr)
Set Rng = Union(Rng, .Range(.Cells(RowFoundArr(Ctr), 1), _
.Cells(RowFoundArr(Ctr), LastCol)))
Next Ctr
.Columns(LastCol + 2).Delete
For Ctr = LastRowData To 2 Step -1
If IsError(Application.Match(Ctr, RowFoundArr, 0)) Then
.Rows(Ctr).Delete
End If
Next Ctr
End With
End With
On Error Resume Next
With Application
.Calculation = SettingsArray(1)
.ErrorCheckingOptions.BackgroundChecking = SettingsArray(2)
.EnableEvents = True
.ScreenUpdating = True
.ScreenUpdating = True
End With
On Error GoTo 0
End Sub
this sums values of column A leaving column B unique. How do I extend this so not only B is unique, but condition is - B and C and D and E are unique in combination as a row.
Basically where the whole row is unique comparing to other, but not necessary each column contain only unique values:
A B C D E
1 0.01 La Ba foo boo
2 0.03 La boo foo Ba
3 0.12 La foo Ba boo
4 1.05 Ba La foo boo
Try this code - it uses a different approach, that's more flexible:
Const cStrDelimiter As String = ";"
Sub Aggregate()
Dim dic As Object
Dim rng As Range
Dim strCompound As String
Dim varKey As Variant
Set dic = CreateObject("Scripting.Dictionary")
'Store all unique combinations in a dictionary
Set rng = Worksheets("Sheet1").Range("A1")
While rng <> ""
strCompound = fctStrCompound(rng.Offset(, 1).Resize(, 4))
dic(strCompound) = dic(strCompound) + rng.Value
Set rng = rng.Offset(1)
Wend
'Save all unique, aggregated elements in worksheet
Set rng = Worksheets("Sheet1").Range("G1")
For Each varKey In dic.Keys
rng = dic(varKey)
rng.Offset(, 1).Resize(, 4).Cells = Split(varKey, cStrDelimiter)
Set rng = rng.Offset(1)
Next
End Sub
Private Function fctStrCompound(rngSource As Range) As String
Dim strTemp As String
Dim rng As Range
For Each rng In rngSource.Cells
strTemp = strTemp & rng.Value & cStrDelimiter
Next
fctStrCompound = Left(strTemp, Len(strTemp) - Len(cStrDelimiter))
End Function
Related
I have multiple columns in an excel sheet...say A1:D10.
I want to find any blank cells in column C, delete that cell as well as the A,B, and D cells of that same row, then shift up. But only in the range of A1:D10. I have other information in this excel sheet outside this range that I want to perserve in its original position. Therefore I can not use somthing like this:
.SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Nor can I get something like the following to work, because it only shifts the single column up, not all four columns.
Set rng = Range("A1:D10").SpecialCells(xlCellTypeBlanks)
rng.Rows.Delete Shift:=xlShiftUp
If there is no data in columns A to D below row 10 that you don't want to move up, then SpecialCells and Delete Shift Up can be used like this
Sub Demo1()
Dim ws As Worksheet
Dim TestColumn As Long
Dim StartColumn As Long
Dim EndColumn As Long
Dim FirstRow As Long
Dim LastRow As Long
Dim i As Long
Dim rng As Range, arr As Range
' set up reference data
Set ws = ActiveSheet '<~~ update as required
TestColumn = 3 'C
StartColumn = 1 'A
EndColumn = 4 'D
FirstRow = 1
LastRow = 10
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
With ws
On Error Resume Next
Set rng = .Range(.Cells(FirstRow, TestColumn), .Cells(LastRow, TestColumn)).SpecialCells(xlCellTypeBlanks)
On Error GoTo 0
If Not rng Is Nothing Then
For Each arr In rng.Areas
arr.EntireRow.Resize(, EndColumn - StartColumn + 1).Delete Shift:=xlShiftUp
Next
End If
End With
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
If there is data in columns A to D below row 10 that you don't want to move up, then you can use Cut and Paste, like this
Sub Demo()
Dim ws As Worksheet
Dim TestColumn As Long
Dim StartColumn As Long
Dim EndColumn As Long
Dim FirstRow As Long
Dim LastRow As Long
Dim i As Long
' set up reference data
Set ws = ActiveSheet '<~~ update as required
TestColumn = 3 'C
StartColumn = 1 'A
EndColumn = 4 'D
FirstRow = 1
LastRow = 10
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
With ws
If IsEmpty(.Cells(LastRow, TestColumn)) Then
.Cells(LastRow, StartColumn).Resize(1, EndColumn - StartColumn + 1).Clear
End If
For i = LastRow - 1 To FirstRow Step -1
If IsEmpty(.Cells(i, TestColumn)) Then
.Range(.Cells(i + 1, StartColumn), .Cells(LastRow, EndColumn)).Cut .Cells(i, StartColumn)
End If
Next
End With
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Using Variant Array Method
Sub test2()
Dim rngDB As Range, vDB As Variant
Dim i As Integer, j As Integer, n As Integer
Dim k As Integer
Set rngDB = Range("a1:d10")
vDB = rngDB
n = UBound(vDB, 1)
For i = 1 To n
If IsEmpty(vDB(i, 3)) Then
For j = 1 To 4
If j <> 3 Then
vDB(i, j) = Empty
End If
Next j
End If
Next i
For j = 1 To 4
If j <> 3 Then
For i = 1 To n - 1
For k = i To n - 1
If vDB(k, j) = Empty Then
vDB(k, j) = vDB(k + 1, j)
vDB(k + 1, j) = Empty
End If
Next k
Next i
End If
Next j
rngDB = vDB
End Sub
The below will take care of your requirement by looking for an empty cell in column 3, and deleting the row and shifting up only in that row.
Sub deleteEmptyRow()
Dim i As Integer
For i = 1 To 10
If Cells(i, 3) = "" Then
Range(Cells(i, 1), Cells(i, 4)).delete Shift:=xlUp
End If
Next i
End Sub
I'm trying to build a macro which will iterate through Activeworkbook/Activeworksheet& Range("A1:" & LastColumn & LastRow) and merge all duplicates in each column. The best starting point I could find was this post --> fastest way to merge duplicate cells in without looping Excel
But, like the OP comments on #PEH's answer https://stackoverflow.com/a/45739951/5079799 I get the following error Application defined error on the line Set R = .Range(Join(arr, ",")).
Does anybody have the fix and/or a better/alternative way to merge duplicates in a column?
Code from answer:
Sub MergeCellsNew()
Application.DisplayAlerts = False
Dim n As Name
Dim fc As FormatCondition
Dim Rng As Range, R As Range
Dim lRow As Long
Dim I&, J&
Dim arr As Variant
ReDim arr(1 To 1) As Variant
With ThisWorkbook.Sheets("tst")
Set Rng = .Range("A2:D11")
lRow = Rng.End(xlDown).Row
For J = 1 To 4
I = 2 'I = Rng.Row to automatically start at the first row of Rng
Do While I <= lRow
Set R = .Cells(I, J) 'remember start cell
'run this loop as long as duplicates found next to the start cell
Do While Trim(UCase(.Cells(I, J))) = Trim(UCase(.Cells(I + 1, J)))
Set R = R.Resize(R.Rows.Count + 1) 'and resize R + 1
I = I + 1
Loop
'now if R is bigger than one cell there are duplicates we want to add to the arr
'this way single cells are not added to the arr
If R.Rows.Count > 1 Then
arr(UBound(arr)) = R.Address
ReDim Preserve arr(1 To UBound(arr) + 1)
End If
I = I + 1
Loop
Next J
ReDim Preserve arr(1 To UBound(arr) - 1)
Set R = .Range(Join(arr, ","))
With R
.Merge
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
End With
Stop
End With
Application.DisplayAlerts = True
End Sub
The problem I see with the methods outlined above is that it relies on duplicate data existing in an adjacent cell in the column. What if the duplicates are scattered in the column?
Here's an example where each column is examined by creating a Dictionary of all the values. Since each value must be unique (as the Key), then duplicates are removed with a list of just the unique Keys. Then it's just a matter of clearing the column of the previous data and copying the unique data back to the worksheet.
Option Explicit
Sub RemoveColumnDupes()
Dim lastCol As Long
With Sheet1
lastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
Dim c As Long
For c = 1 To lastCol
Dim columnDict As Dictionary
Set columnDict = CreateColumnDictionary(Sheet1, c)
If columnDict is Nothing then Exit For
'--- clear the existing data and replace with the cleaned up data
.Range("A1").Offset(, c - 1).Resize(.Rows.Count, 1).Clear
.Range("A1").Offset(, c - 1).Resize(columnDict.Count, 1) = KeysToArray(columnDict)
Next c
End With
End Sub
Private Function CreateColumnDictionary(ByRef ws As Worksheet, _
ByVal colIndex As Long) As Dictionary
Dim colDict As Dictionary
Dim lastRow As Long
With ws
lastRow = .Cells(.Rows.Count, colIndex).End(xlUp).Row
If lastRow = 1 Then
'--- can't create a dictionary with no data, so exit
Set colDict = Nothing
Else
Set colDict = New Dictionary
Dim i As Long
For i = 1 To lastRow
If Not colDict.Exists(.Cells(i, colIndex).Value) Then
colDict.Add .Cells(i, colIndex).Value, i
End If
Next i
End If
End With
Set CreateColumnDictionary = colDict
End Function
Private Function KeysToArray(ByRef thisDict As Dictionary) As Variant
Dim newArray As Variant
ReDim newArray(1 To thisDict.Count, 1 To 1)
Dim i As Long
For i = 1 To thisDict.Count
newArray(i, 1) = thisDict.Keys(i - 1)
Next i
KeysToArray = newArray
End Function
While I don't know the issue with the code I found and posted in OP. I did find awesome solutions on https://www.extendoffice.com and modified it to suit my needs as found below.
Test:
Sub MergeTest()
Dim wsrng As Range
Set wsrng = ActiveSheet.UsedRange
Call MergeWS(wsrng)
'Call UnMergeWS(wsrng)
End Sub
Merge:
https://www.extendoffice.com/documents/excel/1138-excel-merge-same-value.html
Function MergeWS(WorkRng As Range)
Dim Rng As Range, xCell As Range
Dim xRows As Integer
Application.ScreenUpdating = False
Application.DisplayAlerts = False
xRows = WorkRng.Rows.Count
For Each Rng In WorkRng.Columns
For i = 1 To xRows - 1
For j = i + 1 To xRows
If Rng.Cells(i, 1).Value <> Rng.Cells(j, 1).Value Then
Exit For
End If
Next
With WorkRng.Parent.Range(Rng.Cells(i, 1), Rng.Cells(j - 1, 1))
.Merge
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
End With
i = j - 1
Next
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Function
UnMerge:
https://www.extendoffice.com/documents/excel/1139-excel-unmerge-cells-and-fill.html
Function UnMergeWS(WorkRng As Range)
Dim Rng As Range, xCell As Range
xTitleId = "KutoolsforExcel"
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For Each Rng In WorkRng
If Rng.MergeCells Then
With Rng.MergeArea
.UnMerge
.Formula = Rng.Formula
End With
End If
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Function
https://www.freesoftwareservers.com/display/FREES/Merge+and+UnMerge+cells+-+Excel+VBA
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
I'm new here and at VBA.
My question goes:
I have 3 sheets(1, 2 and 3). At sheet 1 I have column A(range A2-end) with data that I want to compare with column A(range A2-end) and D(range D2-end) on sheet 2. If a value in sheet 1 column A is not found on sheet 2column A and D, then it should list the mismatched value in sheet 3 starting at Range A2.
Here is what I have:
Sub Makro5()
Dim lastRowE As Integer
Dim lastRowF As Integer
Dim lastRowM As Integer
Dim foundTrue As Boolean
Application.ScreenUpdating = False
lastRowE = Sheets("1").Cells(Sheets("1").Rows.Count, "A2").End(xlUp).row
lastRowE = Sheets("2").Cells(Sheets("2").Rows.Count, "A2").End(xlUp).row
lastRowF = Sheets("2").Cells(Sheets("2").Rows.Count, "D2").End(xlUp).row
lastRowM = Sheets("3").Cells(Sheets("3").Rows.Count, "A2").End(xlUp).row
For i = 1 To lastRowE
foundTrue = False
For j = 1 To lastRowF
If Sheets("1").Cells(i, 1).value = Sheets("2").Cells(j, 1).value Then
foundTrue = True
and
If Sheets("1").Cells(i, 1).value = Sheets("2").Cells(j, 4).value Then
foundTrue = True
Exit For
End If
Next j
If Not foundTrue Then
Sheets("3").Rows(i).Copy Destination:= _
Sheets("3").Rows(lastRowM + 1)
lastRowM = lastRowM + 1
End If
This reads col A and D from Sheet2 in a dictionary
Then searches for values in col A of Sheet1 in the dictionary
Items not found are placed in Sheet3, starting at cell A2
Option Explicit
Public Sub FindMissing()
Dim ws1 As Worksheet, colA1 As Variant, r As Long, d1 As Object, d2 As Object
Dim ws2 As Worksheet, colA2 As Variant, colD2 As Variant, ws3 As Worksheet
Set d1 = CreateObject("Scripting.Dictionary")
Set d2 = CreateObject("Scripting.Dictionary")
Set ws1 = ThisWorkbook.Worksheets("Sheet1")
Set ws2 = ThisWorkbook.Worksheets("Sheet2")
Set ws3 = ThisWorkbook.Worksheets("Sheet3")
colA1 = ws1.Range("A2:A" & ws1.Cells(ws1.Rows.Count, 1).End(xlUp).Row) 'Sheet1.colA
colA2 = ws2.Range("A2:A" & ws2.Cells(ws2.Rows.Count, 1).End(xlUp).Row) 'Sheet2.colA
colD2 = ws2.Range("D2:D" & ws2.Cells(ws2.Rows.Count, 4).End(xlUp).Row) 'Sheet2.colD
If Not IsArray(colA1) Then MakeArray colA1 'Sheet1.colA contains only 1 row
If Not IsArray(colA2) Then MakeArray colA2 'Sheet2.colA contains only 1 row
If Not IsArray(colD2) Then MakeArray colD2 'Sheet2.colD contains only 1 row
For r = 1 To UBound(colA2)
d1(colA2(r, 1)) = vbNullString 'read Sheet2.ColA in dictionary d1.Keys
Next
For r = 1 To UBound(colD2)
d1(colD2(r, 1)) = vbNullString 'read Sheet2.ColD in dictionary d1.Keys
Next
For r = 1 To UBound(colA1) 'search vals from Sheet1.colA in dictionary d1
If Not d1.Exists(colA1(r, 1)) Then d2(colA1(r, 1)) = vbNullString
Next
ws3.Columns(1).Delete
If d2.Count > 0 Then ws3.Cells(2, 1).Resize(d2.Count, 1) = Application.Transpose(d2.Keys)
End Sub
Private Sub MakeArray(ByRef arr As Variant)
Dim tmp As Variant
tmp = arr
ReDim arr(1 To 1, 1 To 1)
arr(1, 1) = tmp
End Sub
Try using this code below...
Public Function Find_First(FindString As String, WithinRange As Range) As Boolean
Dim rng As Range
Find_First = False
If Trim(FindString) <> "" Then
With WithinRange
Set rng = .Find(What:=FindString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not rng Is Nothing Then
Find_First = True
End If
End With
End If
End Function
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