I would like to get the unique values from column A and all the corresponding values from column B in excel. So transform this:
Into that:
Is it possible in Excel?
With data like this in Sheet1:
running this macro:
Sub dural()
Dim s1 As Worksheet, s2 As Worksheet
Dim i As Long, j As Long, st As String
Set s1 = Sheets("Sheet1")
Set s2 = Sheets("Sheet2")
s1.Range("A:A").Copy s2.Range("A1")
s2.Range("A:A").RemoveDuplicates Columns:=1, Header:=xlNo
For Each r In s2.Range("A:A")
v = r.Value
If v = "" Then Exit Sub
For Each rr In s1.Range("A:A")
vv = rr.Value
If vv = "" Then Exit For
If v = vv Then
If r.Offset(0, 1).Value = "" Then
r.Offset(0, 1).Value = rr.Offset(0, 1).Value
Else
r.Offset(0, 1).Value = r.Offset(0, 1).Value & " ," & rr.Offset(0, 1).Value
End If
End If
Next rr
Next r
End Sub
Will produce this in Sheet2:
NOTE:
The data in Sheet1 is not required to be sorted.
Try this one:
Sub Test()
Dim objIds, arrData, i, strId
Set objIds = CreateObject("Scripting.Dictionary")
arrData = Range("A1:B8").Value ' put here your source range
For i = LBound(arrData, 1) To UBound(arrData, 1)
If IsEmpty(objIds(arrData(i, 1))) Then
objIds(arrData(i, 1)) = arrData(i, 2)
Else
objIds(arrData(i, 1)) = objIds(arrData(i, 1)) & ", " & arrData(i, 2)
End If
Next
i = 1 ' first row for output
For Each strId In objIds
Cells(i, 3) = strId ' first column for output
Cells(i, 4) = objIds(strId) ' second column for output
i = i + 1
Next
End Sub
This is all you need and nothing must be sorted:
Sub Sam()
Dim c&, i&, d$, s$, v, w
v = [a1].CurrentRegion.Resize(, 2)
ReDim w(1 To UBound(v), 1 To 2)
For i = 1 To UBound(v)
d = ", "
If s <> v(i, 1) Then d = "": c = c + 1: s = v(i, 1): w(c, 1) = s
w(c, 2) = w(c, 2) & d & v(i, 2)
Next
[d1:e1].Resize(UBound(w)) = w
End Sub
This code is extremely fast. If you were to process a large list, the efficiency here would be appreciated.
You can manage where the source data is and where the output should be written by adjusting the addresses in the square brackets at the top and bottom of the procedure.
Looking at how to solve this using Excel formulae only (I know there is a VBA tag in the OP), but here is another option.
Adding 2 additional columns with formulae we get this result:
By filtering on the finalList column where the value = 1 we get the desired result:
The formula that are required are as follows:
Cell C1 : =B2
Cell C2 (And copied down to all cells in Column C) : =IF(A3=A2,C2&","&B3,B3)
Cell D1 (And copied down to all cells in Column D) : =IF(A2=A3,0,1)
NOTE: This will only work when Column A is sorted.
Related
I have 6 cells A1 to F1 (Shown below) in excel
How to concatenate all six cells but my cells with numbers should be subscript. Finally, I should get something like below for each row.
It is a lot of work to do subscript on each and every cell.
Previously I found a VBA code to combine two cells (Concatenation of 2 strings and superscript).
Option Explicit
Sub test()
Call SubscriptIt(Range("A1:H9"))
End Sub
Sub SubscriptIt(rng As Range)
Dim row As Range, cell As Range
Dim col As New Collection, v, ar
Dim i As Integer, s As String
For Each row In rng.Rows
Set col = Nothing
s = ""
' determine position,length of numbers
For Each cell In row.Cells
If IsNumeric(cell) Then
col.Add Len(s) & ":" & Len(cell)
End If
s = s & cell
Next
' output in next column
Set cell = row.Cells(1, rng.Columns.Count + 1)
cell = s
cell.Font.Subscript = False
' apply formatting
For Each v In col
ar = Split(v, ":")
cell.Characters(ar(0) + 1, ar(1)).Font.Subscript = True
Next
Next
MsgBox rng.Rows.Count & " rows updated"
End Sub
Please try this code. It presumes that your 6 cells start in column A and inserts the result in column G.
Sub CombineAndFormat()
' 212
Dim Fun As String ' output string
Dim Arr As Variant ' one row's data
Dim Chars() As Integer ' element length
Dim n As Integer ' character count
Dim i As Long ' loop counter: index
Dim R As Long ' loop counter: rows
Application.ScreenUpdating = False ' speeds up execution
With Worksheets("Sheet1") ' change to suit
' loop through rows 2 to end of column A
For R = 2 To .Cells(.Rows.Count, "A").End(xlUp).Row
Arr = .Range(.Cells(R, 1), .Cells(R, 6)).Value
ReDim Chars(1 To UBound(Arr, 2))
Fun = ""
n = 0
For i = 1 To UBound(Arr, 2)
Chars(i) = Len(Arr(1, i))
Fun = Fun & CStr(Arr(1, i))
Next i
With .Cells(R, 7)
.Value = Fun
With .Font ' this is the base font
' .Name = "Calibri" ' specify to suit
' .FontStyle = "Regular"
.Size = 11
.Subscript = False
End With
For i = 1 To 6 Step 2
With .Characters(Start:=n + Chars(i) + 1, Length:=Chars(i + 1)).Font
' this is the subscripted font:-
' .Name = "Calibri" ' specify to suit
' .FontStyle = "Regular"
.Subscript = True
End With
n = n + Chars(i) + Chars(i + 1)
Next i
End With
Next R
End With
Application.ScreenUpdating = True
End Sub
Function Subscript()
'Define Variables
Dim A, B, C, D, E, F As String
Dim l_A, l_B, l_C, l_D, l_E, l_F As Integer
'Read the content of the cells in row 2
A = Worksheets("Sheet14").Cells(2, 1).Value
B = Worksheets("Sheet14").Cells(2, 2).Value
C = Worksheets("Sheet14").Cells(2, 3).Value
D = Worksheets("Sheet14").Cells(2, 4).Value
E = Worksheets("Sheet14").Cells(2, 5).Value
F = Worksheets("Sheet14").Cells(2, 6).Value
'Get the length of each string in the second row
l_A = Len(A)
l_B = Len(B)
l_C = Len(C)
l_D = Len(D)
l_E = Len(E)
l_F = Len(F)
'Write the content of all cells together in the second row in the column G
Worksheets("Sheet14").Cells(2, 7).Value = A & B & C & D & E & F
'Write the content of Cell B as Subscript in Column G
Worksheets("Sheet14").Cells(2, 7).Characters(l_A + 1, l_B).Font.Subscript = True
'Write the content of Cell D as Subscript in Column G
Worksheets("Sheet14").Cells(2, 7).Characters(l_A + l_B + l_C + 1, l_D).Font.Subscript = True
'Write the content of Cell F as Subscript in Column G
Worksheets("Sheet14").Cells(2, 7).Characters(l_A + l_B + l_C + l_D + l_E + 1, l_F).Font.Subscript = True
End Function
Need any help on how I can achieve as in the image below.
I want to combine multiple rows of the same person into one while transposing the column value of the person into a single row. I would like to achieve doing it preferable via VBA but if not then by formula.
Sorry I don't have anything to show. I already have the codes to generate a unique list for the names but I don't know how to transpose the data in the respective columns. I don't have any idea on how to approach this problem. Seeking any guidance or even ideas.
Public Sub extractUniques(rngSource As Range, rngTarget As Range)
Application.ScreenUpdating = False
rngSource.AdvancedFilter Action:=xlFilterCopy, _
copytorange:=rngTarget, Unique:=True
Application.ScreenUpdating = True
End Sub
Try this!
Sub specialTransfer()
Dim inp As Range, outp As Range, rng As Range, c As Range, data(), u, r, x, i, j
Set inp = [A1] 'Change this to the top left cell of your input
Set outp = [F1] 'Change this to the top left cell of your output
Set rng = Range(inp.Offset(1, 1), Cells(Rows.Count, 2).End(xlUp))
data = rng.Value
Set u = CreateObject("Scripting.Dictionary")
For r = 1 To UBound(data)
u(data(r, 1)) = Empty
Next r
x = u.Keys()
'Option to clear out everything past the outputcell
'Range(outp, Cells(Rows.Count, Columns.Count)).ClearContents
outp = "Name"
For i = 0 To u.Count - 1
j = 1
outp.Offset(i + 1) = x(i)
For Each c In rng
Range(outp.Offset(, j), outp.Offset(, j + 2)) = Array("Day", "Time out", "Time in")
If WorksheetFunction.CountA(c.Offset(, -1).Resize(, 4)) = 4 Then
If c = x(i) Then
outp.Offset(i + 1, j).Value = Format(Mid(c.Offset(, -1), 4, 10), "General Number")
outp.Offset(i + 1, j + 1).Value = Format(c.Offset(, 1), "h:mm AM/PM")
outp.Offset(i + 1, j + 2).Value = Format(c.Offset(, 2), "h:mm AM/PM")
j = j + 3
End If
End If
Next c
Next i
End Sub
Hoping to be able to achieve it via VBA but don't think that I can. It's not the exact result I was hoping for but it works. Did it using array formula below.
=IFERROR(INDEX("table data",MATCH(1,("criteria1 column"="criteria1")*("criteria2 column"="criteria2")*("criteria3 column"<>""),0), "criteria3 colNum"),"")
Ctrl + Shift + Enter
multiple row into one
With this code I'm trying to search cells in a column where there is a comma character, and divide it into 2 new cells.
Next I want to Delete the original line, but it seems impossible as the value is used in FindNext operation.
What I have :
Column D Column E
Carrot Vegetable
Apple,Banana Fruit
What I need :
Column D Column E
Carrot Vegetable
Apple Fruit
Banana Fruit
What I've done :
Sub newentry()
'
' newentry Macro
'
Dim line
Dim col
Dim content
With Sheets("Feuil3").Columns("D")
Set c = .Find(",", LookIn:=xlValues)
If Not c Is Nothing Then
firstAddress = c.Address
Do
c.Select
line = ActiveCell.Row
col = ActiveCell.Column
content = ActiveCell
category = Cells(line, "E")
Dim Table() As String
Dim i As Integer
'split content in a table
Table = Split(content, ",")
'loop on table
For i = 0 To UBound(Table)
'copy result on next line
Rows(line + 1).Insert
Tableau(i) = Application.WorksheetFunction.Trim(Table(i))
Cells(line + 1, col).Value = Table(i)
Cells(line + 1, "E").Value = category
Next i
Set c = .FindNext(c)
If c Is Nothing Then
GoTo DoneFinding
End If
'where/how to do this ?
Rows(c.Row).Delete Shift:=xlUp
Loop While Not c Is Nothing And c.Address <> firstAddress
End If
DoneFinding:
End With
End Sub
How can I delete the line that I just found ?
Thanks.
Say we have data in column D like:
Running this short macro:
Sub Restructure()
Dim N As Long, i As Long, j As Long
Dim arr1, arr2, arr3, a1, s As String
N = Cells(Rows.Count, "D").End(xlUp).Row
j = 1
arr1 = Range("D1:D" & N)
For Each a1 In arr1
s = Mid(a1, 2, Len(a1) - 2)
If InStr(s, ",") = 0 Then
Cells(j, "E").Value = "[" & s & "]"
j = j + 1
Else
arr2 = Split(s, ",")
For Each a2 In arr2
Cells(j, "E").Value = "[" & a2 & "]"
j = j + 1
Next a2
End If
Next a1
End Sub
will produce this in column E:
NOTE:
The original data is not disturbed.
insert as many lines as needed minus one below the found cell,
then simply write needed data including found cell row
don't rely on any ActiveCell, just use the c range object you found
Sub newentry()
'
' newentry Macro
'
Dim content As String, Category As String
Dim c As Range
Dim Table() As String
With Sheets("Feuil3").Columns("D")
Set c = .Find(",", LookIn:=xlValues)
If Not c Is Nothing Then
Do
content = c
Category = c.Offset(, 1).Value2
'split content in a table
Table = Split(content, ",")
c.Offset(1).EntireRow.Resize(UBound(Table)).Insert ' insert as many rows needed minus one below the found cell
c.Resize(UBound(Table) + 1).Value = Application.Transpose(Table) ' write contents in as many cells as needed, including the found one
c.Offset(, 1).Resize(UBound(Table) + 1).Value = Array(Category, Category) ' write category in as many cells as needed one column to the right of found one
Set c = .FindNext(c)
Loop While Not c Is Nothing
End If
End With
End Sub
Try this code
Sub Test()
Dim a, b, x, i As Long, j As Long, k As Long
a = Range("D1:E" & Cells(Rows.Count, 1).End(xlUp).Row).Value
ReDim b(1 To UBound(a) * 3, 1 To UBound(a, 2))
For i = LBound(a) To UBound(a)
If InStr(a(i, 1), ",") > 0 Then
x = Split(a(i, 1), ",")
For j = LBound(x) To UBound(x)
k = k + 1
b(k, 1) = Trim(x(j))
b(k, 2) = a(i, 2)
Next j
Else
k = k + 1
b(k, 1) = a(i, 1)
b(k, 2) = a(i, 2)
End If
Next i
Columns("D:E").ClearContents
Range("D1").Resize(k, UBound(b, 2)).Value = b
End Sub
Please see the attach image which shows my data and expected data after running the macro,
I would like to split the multi line cell in column B and listed in separate rows and removed text from first space. This values will be called as SESE_ID and should have the RULE from column C for each SESE_ID from the same row.
If there is more than one prefix in column A separated by a comma or space-comma, then repeat the above values for each prefix.
Please someone help me in the macro...
Attached 1st image is the sample source:
And following is the macro:
Sub Complete_sepy_load_macro()
Dim ws, s1, s2 As Worksheet
Dim rw, rw2, rw3, col1, count1, w, x, y, z, cw As Integer
Dim text1 As String
Dim xwalk As String
Dim TOSes As Variant
Application.DisplayAlerts = False
For Each ws In Sheets
If ws.Name = "CMC_SEPY_SE_PYMT" Then Sheets("CMC_SEPY_SE_PYMT").Delete
Next
Application.DisplayAlerts = True
Set s2 = ActiveSheet
g = s2.Name
Sheets.Add.Name = "CMC_SEPY_SE_PYMT"
Set s1 = Sheets("CMC_SEPY_SE_PYMT")
s1.Cells(1, 1) = "SEPY_PFX"
s1.Cells(1, 2) = "SEPY_EFF_DT"
s1.Cells(1, 3) = "SESE_ID"
s1.Cells(1, 4) = "SEPY_TERM_DT"
s1.Cells(1, 5) = "SESE_RULE"
s1.Cells(1, 6) = "SEPY_EXP_CAT"
s1.Cells(1, 7) = "SEPY_ACCT_CAT"
s1.Cells(1, 8) = "SEPY_OPTS"
s1.Cells(1, 9) = "SESE_RULE_ALT"
s1.Cells(1, 10) = "SESE_RULE_ALT_COND"
s1.Cells(1, 11) = "SEPY_LOCK_TOKEN"
s1.Cells(1, 12) = "ATXR_SOURCE_ID"
s1.Range("A:A").NumberFormat = "#"
s1.Range("B:B").NumberFormat = "m/d/yyyy"
s1.Range("C:C").NumberFormat = "#"
s1.Range("D:D").NumberFormat = "m/d/yyyy"
s1.Range("E:E").NumberFormat = "#"
s1.Range("F:F").NumberFormat = "#"
s1.Range("G:G").NumberFormat = "#"
s1.Range("H:H").NumberFormat = "#"
s1.Range("I:I").NumberFormat = "#"
s1.Range("J:J").NumberFormat = "#"
s1.Range("K:K").NumberFormat = "0"
s1.Range("L:L").NumberFormat = "m/d/yyyy"
rw2 = 2
x = 1
y = 1
z = 1
'service id column
Do
y = y + 1
Loop Until s2.Cells(1, y) = "Service ID"
'Rule column
Do
w = w + 1
Loop Until Left(s2.Cells(1, w), 4) = "Rule"
'Crosswalk column
Do
cw = cw + 1
Loop Until Left(s2.Cells(1, cw).Value, 9) = "Crosswalk"
'Alt rule column (location derived from rule column)
'counts # of cells between "rule" and "alt rule", used as precedent for rest of "alt rule" cells
ar = w
Do
ar = ar + 1
Loop Until Left(s2.Cells(1, ar).Value, 3) = "Alt"
ar = ar - w
'prefix row
Do
x = x + 1
Loop Until s2.Cells(x, w) ""
'first service id row
Do
z = z + 1
Loop Until s2.Cells(z, y) ""
'change rw = z + 2 to rw = z, was skipping first two rows
For rw = z To s2.Range("a65536").End(xlUp).Row
If s2.Cells(rw, y) "" Then
If InStr(1, s2.Cells(rw, y), Chr(10)) 0 Then
TOSes = Split(s2.Cells(rw, y).Value, Chr(10)) 'Chr(10) is the "new line" character
count1 = 0
Do
If Trim(TOSes(count1)) "" Then
For col1 = w To s2.UsedRange.Columns.Count
If Left(s2.Cells(1, col1), 4) = "Rule" Then
If InStr(1, TOSes(count1), " ") > 0 Then
s1.Cells(rw2, 3) = Trim(Left(TOSes(count1), InStr(1, TOSes(count1), " "))) 'sese
Else
s1.Cells(rw2, 3) = TOSes(count1)
End If
s1.Cells(rw2, 1) = s2.Cells(x, col1) 'prefix
s1.Cells(rw2, 5) = s2.Cells(rw, col1) 'rule
'use crosswalk service id to populate alt rule
If s2.Cells(rw, cw).Value "" Then
If xwalk = "" Then
Match = False
xwalk = Trim(s2.Cells(rw, cw)) & " "
rwcw = z
Do
If InStr(1, s2.Cells(rwcw, y).Value, xwalk, vbTextCompare) > 0 Then
'obtain rule and write to alt rule column of current row
s2.Cells(rw, col1).Offset(0, ar).Value = s2.Cells(rwcw, w).Value
Match = True
End If
rwcw = rwcw + 1
Loop Until Match = True
End If
End If
s1.Cells(rw2, 9) = s2.Cells(rw, col1).Offset(0, ar) 'alt rule
s1.Cells(rw2, 7) = "TBD" 'cac
s1.Cells(rw2, 13) = s2.Name 'file
rw2 = rw2 + 1
End If
xwalk = ""
Next col1
End If
count1 = count1 + 1
Loop Until count1 = UBound(TOSes) + 1
Else
For col1 = w To s2.UsedRange.Columns.Count
If Left(s2.Cells(1, col1), 4) = "Rule" Then
If InStr(1, s2.Cells(rw, y), " ") > 0 Then
s1.Cells(rw2, 3) = Trim(Left(s2.Cells(rw, y), 4)) 'sese
Else
s1.Cells(rw2, 3) = s2.Cells(rw, y)
End If
s1.Cells(rw2, 1) = s2.Cells(x, col1) 'prefix
s1.Cells(rw2, 5) = s2.Cells(rw, col1) 'rule
s1.Cells(rw2, 9) = s2.Cells(rw, col1).Offset(0, ar) 'alt rule
s1.Cells(rw2, 7) = "TBD" 'cac
s1.Cells(rw2, 13) = s2.Name 'file
rw2 = rw2 + 1
End If
Next col1
End If
ElseIf s2.Cells(rw, y) = "" And Trim(s2.Cells(rw, w)) "" Then
If Len(s2.Cells(rw, 1)) >= 10 Then
text1 = Left(s2.Cells(rw, 1), 10) & " |row: " & rw 'sese
Else
text1 = s2.Cells(rw, 1) & " row: " & rw 'sese
End If
For col1 = w To s2.UsedRange.Columns.Count
If Left(s2.Cells(1, col1), 4) = "Rule" Then
s1.Cells(rw2, 3) = text1 'sese
s1.Cells(rw2, 3).Interior.ColorIndex = 6
s1.Cells(rw2, 1) = s2.Cells(x, col1) 'prefix
s1.Cells(rw2, 5) = s2.Cells(rw, col1) 'rule
s1.Cells(rw2, 9) = s2.Cells(rw, col1).Offset(0, ar) 'alt rule
s1.Cells(rw2, 7) = "TBD" 'cac
s1.Cells(rw2, 13) = s2.Name 'file
rw2 = rw2 + 1
End If
Next col1
End If
Next
For rw3 = 2 To s1.UsedRange.Rows.Count
s1.Cells(rw3, 2) = "1/1/2009"
s1.Cells(rw3, 4) = "12/31/9999"
s1.Cells(rw3, 11) = 1
s1.Cells(rw3, 12) = "1/1/1753"
Next rw3
Dim wb As Workbook
Dim wss, wsSepy, wsSID As Worksheet 'SID = Serivce ID Spreadsheet
Dim sepyRow, sepyCol, acctCol, sidSeseCol, sidAcctCol, j As Long
Dim cell As Range
Dim cellRange As Range
Dim topRow As Range
Dim sepySese As String
MsgBox "All set, make sure there is no #N/A in SESE_RULE column"
End Sub
Below image is the output I got:
Problem: If you see the source data, I have SEPY_PFX in column A. I wanted every row to be repeated for each SEPY. Currently my code gave me RULE as SEPY_PFX, I am still working on it BUT it will be glad if someone help me on this quickly, it is already going above my head.
This code will work on the first example you posted to give the output you wanted:
Original Source:
Original Results:
It works by using Class and Collections, creating each entry one at a time, and then putting it together for the results.
I use arrays to collect and output the data, because this will work much faster. In your original you had some font coloring, which I have carried over.
You should be able to adapt it to your real data, but, if you cannot, I suggest you post a "sanitized" copy of your original data, with the correct columns and so forth, on some file sharing web site such as DropBox, OneDrive, etc; and post a link here so we can see the "real stuff"
With regard to the use of classes, please see Chip Pearson's web site
Also, please read the comments in the code for explanations and suggestions.
First insert a Class Module, ReNAME it cOfcCode and paste the code below into it:
'Will need to add properties for the additional columns
Option Explicit
Private pSEPY As String
Private pFontColor As Long
Private pSESE As String
Private pRule As String
Public Property Get SEPY() As String
SEPY = pSEPY
End Property
Public Property Let SEPY(Value As String)
pSEPY = Value
End Property
Public Property Get FontColor() As Long
FontColor = pFontColor
End Property
Public Property Let FontColor(Value As Long)
pFontColor = Value
End Property
Public Property Get Rule() As String
Rule = pRule
End Property
Public Property Let Rule(Value As String)
pRule = Value
End Property
Public Property Get SESE() As String
SESE = pSESE
End Property
Public Property Let SESE(Value As String)
pSESE = Value
End Property
Then, in a regular module:
Option Explicit
Sub ReformatData()
Dim wsSrc As Worksheet, wsRes As Worksheet
Dim rSrc As Range, rRes As Range
Dim vSrc As Variant, vRes As Variant
Dim vSEPY As Variant, vSESE As Variant
Dim cOC As cOfcCode
Dim colOC As Collection
Dim lRGB As Long
Dim I As Long, J As Long, K As Long
'Change Sheet references as needed
Set wsSrc = Worksheets("Sheet2")
Set wsRes = Worksheets("Sheet3")
'Assuming Data is in Columns A:C
With wsSrc
Set rSrc = .Range("A1", .Cells(.Rows.Count, "C").End(xlUp))
End With
Set rRes = wsRes.Range("A1")
vSrc = rSrc
Set colOC = New Collection 'Collection of each "to be" row
For I = 2 To UBound(vSrc, 1)
'Split SEPY_PFX into relevant parts
vSEPY = Split(vSrc(I, 1), ",")
For J = 0 To UBound(vSEPY)
'Get the font color from the original cell
With rSrc(I, 1)
lRGB = .Characters(InStr(1, .Value, vSEPY(J), vbTextCompare), 1).Font.Color
End With
'Split SESE_ID into relevant parts
vSESE = Split(vSrc(I, 2), vbLf)
'Iterate through each SESE_ID, picking up the SEPY_PFX, and RULE
For K = 0 To UBound(vSESE)
Set cOC = New cOfcCode
'Will need to adjust for the extra columns
With cOC
.FontColor = lRGB
.Rule = vSrc(I, 3)
.SEPY = vSEPY(J)
.SESE = vSESE(K)
colOC.Add cOC '<-- ADD to the collection
End With
Next K
Next J
Next I
'Put together the Results
ReDim vRes(0 To colOC.Count, 1 To UBound(vSrc, 2))
'Copy the column headings from the source
For I = 1 To UBound(vRes, 2)
vRes(0, I) = vSrc(1, I)
Next I
'Will need to add entries for the other columns
For I = 1 To colOC.Count
With colOC(I)
vRes(I, 1) = .SEPY
vRes(I, 2) = .SESE
vRes(I, 3) = .Rule
End With
Next I
'Clear the results worksheet and write the results
wsRes.Cells.Clear
Set rRes = rRes.Resize(UBound(vRes, 1) + 1, UBound(vRes, 2))
rRes = vRes
'Add the correct font color and format
For I = 1 To colOC.Count
rRes.Rows(I + 1).Font.Color = colOC(I).FontColor
Next I
With rRes.Rows(1)
.Font.Bold = True
.HorizontalAlignment = xlCenter
End With
rRes.EntireColumn.AutoFit
End Sub
Make the changes to the Worksheet references in the code (only need to do that at the beginning of the regular module.
Try this first on your original example, so you can see how it works, then add in the extra columns and processing to the Class and the Collection, or post back here with more details
I assume the original data is in worksheet "DATA", and worksheet "Expected Output" which is used to store processed data , exist already.
Your code will be: Operation of most lines are explained by comments (right of "'")
Sub processData()
Dim oWS As Worksheet, pWS As Worksheet
Dim oRow As Long, pRow As Long
Dim splitMultiLine As String, splitPerfix As String
Dim c As Long, i As Long, j As Long, k As Long
Dim prefixes As Variant, lines As Variant
Dim dataACol As String, dataBCol As String, dataCCol As String
Set oWS = Worksheets("DATA") 'original data
Set pWS = Worksheets("Expected Output") 'processed data
'Copy title row
For c = 1 To 3
pWS.Cells(1, c) = oWS.Cells(1, c)
Next c
oRow = 2 ' row of oWS
pRow = 2 ' row of pWS
With oWS
While (.Cells(oRow, 1) <> "") 'Loop while A colmn has value
dataACol = .Cells(oRow, 1) 'data in A column
dataBCol = .Cells(oRow, 2) 'data in B column
dataCCol = .Cells(oRow, 3) 'data in C colum
prefixes = Split(dataACol, ",") ' split prefixes by comma
lines = Split(dataBCol, Chr(10)) ' split multi lines in a cell by newline (Char(10))
For i = LBound(prefixes) To UBound(prefixes)
For j = LBound(lines) To UBound(lines)
pWS.Cells(pRow, 1) = Trim(prefixes(i)) ' A column of output
k = InStr(lines(j), " ")
pWS.Cells(pRow, 2) = Left(lines(j), k - 1) ' B column of output
pWS.Cells(pRow, 3) = dataCCol ' C column of output
pRow = pRow + 1
Next j
Next i
oRow = oRow + 1
Wend
End With
End Sub
I have data that I need to split into individual points. My macro charts the data, as a scatter plot, with: Column A as the title of the chart, Column B as the X axis, and Columns C and D as the Y axis. What I need is for when the Product ID has more than 1 number listed to split the numbers out into their own rows and keep the columns B, C, and D the same for each row created form the original. So for row 167, I would want 3 rows (001,002,003) each with packaging, 200, and 100, in B, C, and D respectively. I am not sure where to begin. I tried to build a macro but, I immediately got tripped up when I tried to record a "Find" Formula to run on the data. Any help would be greatly appreciated.
Column A: 001, 002, 003 // Column B:packaging // Column C:200 // Column D:100
Sorry I couldn't post a screenshot of my data, the forum won't let me. If you have any questions please let me know, I will be sure to check in frequently.
Thanks in advance.
I worte this VERY quickly and without much care for efficiency, but this should do the trick:
Sub SplitUpVals()
Dim i As Long
Dim ValsToCopy As Range
Dim MaxRows As Long
Dim ValToSplit() As String
Dim CurrentVal As Variant
MaxRows = Range("A1").End(xlDown).Row
For i = 1 To 10000000
ValToSplit = Split(Cells(i, 1).Value, ",")
Set ValsToCopy = Range("B" & i & ":D" & i)
For Each CurrentVal In ValToSplit
CurrentVal = Trim(CurrentVal)
Cells(i, 1).Value = CurrentVal
Range("B" & i & ":D" & i).Value = ValsToCopy.Value
Cells(i + 1, 1).EntireRow.Insert
i = i + 1
MaxRows = MaxRows + 1
Next
Cells(i, 1).EntireRow.Delete
If i > MaxRows Then Exit For
Next i
End Sub
As a note, make sure there's no data in cells beneath your data as it might get deleted.
You will need to parse the data in column A. I would do this by splitting the string in to an array, and then iterate over the array items to add/insert additional rows where necessary.
Without seeing your worksheet, I would probably start with something like this, which will split your cell value from column A in to an array, and then you can iterate over the items in the array to manipulate the worksheet as needed.
Sub TestSplit()
Dim myString as String
Dim myArray() as String
Dim cell as Range
Dim i as Long
For each cell in Range("A2",Range("A2").End(xlDown))
myString = cell.Value
myArray = Split(myString, ",") '<-- converts the comma-delimited string in to an array
For i = lBound(myArray) to uBound(myArray)
If i >= 1 Then
'Add code to manipulate your worksheet, here
End If
Next
Next
End Sub
This is a better solution (now that I had more time :) ) - Hope this does the trick!
Sub SplitUpVals()
Dim AllVals As Variant
Dim ArrayIndex As Integer
Dim RowLooper As Integer
AllVals = Range("A1").CurrentRegion
Range("A1").CurrentRegion.Clear
RowLooper = 1
For ArrayIndex = 1 To UBound(AllVals, 1)
ValToSplit = Split(AllVals(ArrayIndex, 1), ",")
For Each CurrentVal In ValToSplit
CurrentVal = Trim(CurrentVal)
Cells(RowLooper, 1).Value = CurrentVal
Cells(RowLooper, 2).Value = AllVals(ArrayIndex, 2)
Cells(RowLooper, 3).Value = AllVals(ArrayIndex, 3)
Cells(RowLooper, 4).Value = AllVals(ArrayIndex, 4)
RowLooper = RowLooper + 1
Next
Next ArrayIndex
End Sub
Sub DivideData()
'This splits any codes combined into the same line, into their own separate lines with their own separate data
Dim a, b, txt As String, e, s, x As Long, n As Long, i As Long, ii As Long
With Range("a1").CurrentRegion
a = .Value
txt = Join$(Application.Transpose(.Columns(1).Value))
x = Len(txt) - Len(Replace(txt, ",", "")) + .Rows.Count
ReDim b(1 To x * 2, 1 To UBound(a, 2))
For i = 1 To UBound(a, 1)
For Each e In Split(a(i, 1), ",")
If e <> "" Then
For Each s In Split(e, "-")
n = n + 1
For ii = 1 To UBound(a, 2)
b(n, ii) = a(i, ii)
Next
b(n, 1) = s
Next
End If
Next
Next
With .Resize(n)
.Columns(1).NumberFormat = "#"
.Value = b
End With
End With
End Sub