Split a single Excel row into multiple based on columns - excel

I need to create multiple Excel rows based off of a single row. For example, I currently have a single row for each personnel and there are dozens of columns that are "grouped" so to speak. So say column K is its own group, then columns M, N, O are a group, P, Q, R, are a group, etc. I need that single row to become multiple rows - one row per group of columns. So the current situation is:
1 | Smith, John | Column K | Column M | Column N | Column O | Column P | Column Q| Column R
And I need that to become:
1 | Smith, John | Column K
2 | Smith, John | Blank | Column M | Column N | Column O
3 | Smith, John | Blank | Blank | Blank | Blank | Column P | Column Q | Column R

Here's a solution. You probably can do that math a bit smarter. I can't right now. ;)
Sub splitRows()
Dim i As Integer
With Sheets(1)
For i = 2 To (.UsedRange.Columns.Count / 3)
.Range(Cells(i, 1), Cells(i, 3)).Value = .Range(Cells(1, 1), Cells(1, 3)).Value
.Range(Cells(i, (i - 1) * 3 + 1), Cells(i, (i - 1) * 3 + 3)).Value = .Range(Cells(1, (i - 1) * 3 + 1), Cells(1, (i - 1) * 3 + 3)).Value
Next
End With
End Sub
This will only work correctly for sheets where there are always groups of three columns. If not, you have to change that .UsedRange.Columns.Count / 3 part.
Cheers.

Related

Count if current row and next row meet the criteria

For example, I have a table in with thousands of row:
| col
row 1 | NN
row 2 | NNP
row 3 | VB
row 4 | NNP
row 5 | NN
row 6 | NNP
row 7 | JJ
row 8 | NUM
row 9 | CW
.....
row 10000 | NNP
Can I count with condition :
IF (row 1 = NN AND row 2= NNP) AND (row 2 = NN AND row 3= NNP) AND ... AND (row 9999 = NN and row 10000 = NNP) THEN count?
Try -
=SUMPRODUCT((A1:A10000="NN")*(A2:A10001="NNP"))
This should also work:
=COUNTIFS(A1:A999,"NN",A2:A1000,"NNP")

Get Unique Value list in excel

I am quite novice at Excel formulas, so could anyone help me
I have elements as follows
+----+---------+------------+
| A | B | C |
| nr | car | model |
| 1 | Ford | Mustang |
| 2 | Ford | Focus |
| 3 | Ford | Focus |
| 4 | Ferrari | 458 |
| 5 | Ferrari | Testarossa |
+----+---------+------------+
How could I get the results as follows
+---+---------+-----------------+
| 1 | Ford | Mustang, Focus |
| 2 | Ferrari | 458, Testarossa |
+---+---------+-----------------+
Where every value is unique. I Tried Vlookup, but it only returns 1 element with 1 value. Example: VLookup with Ford would return only the first result Mustang, but not Focus
If possible, please use only Formulas :)
I've seen similar questions but no answers
Now if you don't mind them being in different cells then:
=IFERROR(INDEX($C$2:$C$6,MATCH(1,IF(($B$2:$B$6=$F1)*(COUNTIF($F1:F1,$C$2:$C$6)=0),1,0),0)),"")
This is an array formula and as such must be confirmed with Ctrl-Shift-Enter instead of Enter or Tab to exit edit mode.
This can be done in an extra step. As in you will need an intermediate table.
So in my example, I take the data you have given (which seems sorted for Column car), but assume that it is not sorted (unsorted data in the screenshot).
Step 1:
Unsorted data is sorted, and table formed in rows 9-14. Add a column in D9, and in cell D10 put this formula:
=IF(B10=B9,CONCATENATE(VLOOKUP(B9,B9:D10,3,0),", ",C10),C10)
What this formula does is it looks up and concatenates values at the same time.
I find no of unique entries in the table in rows 9 and 14 with a formula in row 16. (This is just for convenience)
B16 =SUMPRODUCT(1/COUNTIF($B$10:$B$14,$B$10:$B$14))
Step 2:
In rows 18-20 (the no of unique entries kind of gave an idea how big this table will be),
B19=INDEX($B$10:$B$14,MATCH(0,INDEX(COUNTIF($B$18:B18,$B$10:$B$14),0,0),0))
This formula lists out unique car names in colB. In colC, you LOOKUP the last concatenated value for a car name (because we had kept on concatenating earlier, the last entry for a car name would have your result)
C19=LOOKUP(2,1/($B$9:$B$14=B19),$D$9:$D$14)
That should give you the resultant table! (Have pasted all of them as values in colG onwards so that you see the output)
Put this in D2
=IF(B2<>B1,C2,IF(C2<>C1,IF(D1="",C2,D1&", "&C2),""))
Drag down
nr car model ColD
1 Ford Mustang Mustang
2 Ford Focus Mustang, Focus
3 Ford Focus
4 Ferrari 458 458
5 Ferrari Testarossa 458, Testarossa
first occurrence of the last model per car has the data you want.
This would be a lot easier if you could kill column A and use Excel's remove dupes function.
If you want to do it with code, this will work:
Sub ConcatByMasterColumn()
Dim X As Long, MyString As String
Range("F1:G1").Formula = Array("Car", "Model")
For X = 2 To Range("A" & Rows.Count).End(xlUp).Row + 1
If Range("B" & X) <> Range("B" & X - 1) And X > 2 Then 'MyString = Range("B" & X).Text
Range("F" & Range("F" & Rows.Count).End(xlUp).Offset(1, 0).Row).Formula = Range("B" & X - 1).Text
Range("G" & Range("G" & Rows.Count).End(xlUp).Offset(1, 0).Row).Formula = Right(MyString, Len(MyString) - 2)
MyString = ""
End If
If Range("C" & X) <> Range("C" & X - 1) Then MyString = MyString & ", " & Range("C" & X).Text
Next
End Sub
Results:
Car Model
Ford Mustang, Focus
Ferrari 458, Testarossa

Shuffle values to a new row two cells at a time

To explain it in the easiest way possible:
| 1 | 2 | 3 | 4 |
| 5 | 6 | 7 | 8 |
... needs to look like:
| 1 | 2 |
| 3 | 4 |
| 5 | 6 |
| 7 | 8 |
I've tried using the TRANSPOSE() function, but it doesn't seem to work in this situation.
How can I accomplish this simple task?
In an unused cell to the right use this formula,
=OFFSET($A$1, INT((ROW(1:1)-1)/2), COLUMN(A:A)-1+MOD((ROW(1:1)-1), 2)*2)
Fill right one column and fill down as far as necessary. Your results should resemble the following.
      
You put excel-vba in your tags, so I'll post the vba code for you. I don't know how to do it with simple cell formulas. Hopefully it's configurable enough to get what you want, beyond the simple example you gave:
START_ROW = 1
START_COL = 1
STEP_COL = 2
OUTPUT_ROW = 3
OUTPUT_COL = 10
Row = START_ROW
Col = START_COL
Out_Row = OUTPUT_ROW
While Cells(Row, Col).Value <> ""
While Cells(Row, Col).Value <> ""
For step = 0 To STEP_COL - 1
Cells(Out_Row, OUTPUT_COL + step).Value = Cells(Row, Col + step).Value
Cells(Out_Row, OUTPUT_COL + step).Value = Cells(Row, Col + step).Value
Next step
Out_Row = Out_Row + 1
Col = Col + STEP_COL
Wend
Col = START_COL
Row = Row + 1
Wend

Move data onto blank row below Excel from multiple columns with VBA macro

I currently have data in the following format:
Name 1 | Email 1 | ID 1 | Address 1 Street | Address 1 Suburb | Address 1 City | Address 2 Street | Address 2 Suburb | Address 2 City | Address 3 Street | Address 3 Suburb | Address 3 City
<NEW LINE>
Name 2 | Email 2 | ID 2 | Address 1 Street | Address 1 Suburb | Address 1 City | Address 2 Street | Address 2 Suburb | Address 2 City
etc.
And I need it to look like the following:
Name 1 | Email 1 | ID 1 | Address 1 Street | Address 1 Suburb | Address 1 City
<NEW LINE>
Name 1 | Email 1 | ID 1 | Address 2 Street | Address 2 Suburb | Address 2 City
<NEW LINE>
Name 1 | Email 1 | ID 1 | Address 3 Street | Address 3 Suburb | Address 3 City
<NEW LINE>
Name 2 | Email 2 | ID 2 | Address 1 Street | Address 1 Suburb | Address 1 City
<NEW LINE>
Name 2 | Email 2 | ID 2 | Address 2 Street | Address 2 Suburb | Address 2 City
etc.
What I have so far in my spreadsheet is in column A is a COUNTA formula to work out the number of rows we need to insert below each row to allow for the data to be duplicated which is calculating fine. From this I have used the following code to insert these number of lines which is also working fine.
Sub ProcessAddressLabels()
For N = Cells(Rows.Count, 1).End(xlUp).Row To 1 Step -1
If Cells(N, 1) <> "" And Cells(N, 1) <> 1 Then
Rows(N + 1 & ":" & N + Cells(N, 1) - 1).Insert
NumValues = Cells(N, 1)
End If
Next N
End Sub
What I am not sure from here is how to copy each set of 3 cells from the end and place it along with the duplicated user data onto the lines below!
Any help is much appreciated and I hope I explained this simply enough!
Give this a try:
Sub Test()
Dim rw As Range, n As Long, i As Long, x As Long
Set rw = ActiveSheet.Rows(1) 'starting row
Do While rw.Cells(1).Value <> ""
'how many sets of addresses to move?
x = Application.Ceiling((Application.CountA(rw) - 6) / 3, 1)
If x > 0 Then
'insert required rows
rw.Offset(1, 0).Resize(x).Insert
For i = 1 To x
'copy common cells
rw.Cells(1).Resize(1, 3).Copy rw.Cells(1).Offset(i, 0)
'cut each address block
rw.Cells(7 + ((i - 1) * 3)).Resize(1, 3).Cut rw.Cells(1).Offset(i, 3)
Next i
End If
'move to next "new" row
Set rw = rw.Offset(1 + x, 0)
Loop
End Sub
I cannot say I fully understood all your needs, however
would something like this help:
Dim sht As Worksheet
Set sht = ActiveSheet
' copy the range C1:F1 to the start of the third row.
sht.range("C1:F1").Copy Destination:=Worksheets("Sheet1").range("A3")

Excel to calculate if values in ranges meet certain criteria using VBA

I have two ranges in excel, say:
x | y
------------
5 | -1
46 | -4
2 | 1
67 | -1
22 | 1
6 | 0
34 | 0
7 | -2
I want calculate the sum of the second column for values less than O only if the respective values in the first column is less than 10 (i.e sum(y(i) for i<0 and x(i)<10) . Hence in this case the sum will be -3.
Assuming your headers are in A1:B1 and your data is A2:B9 use this:
=SUMIFS(B2:B9,A2:A9,"<10",B2:B9,"<0")
Try something like
Function calc() AS Integer
Dim sum AS Integer: sum = 0
Dim c AS Range
For Each c In ThisWorkbook.Worksheets(1).Range("A1:A15")
If c.Value < 10 And c.Offset(0, 1).Value < 0 Then
sum = sum + c.Offset(0, 1).Value
End If
Next c
calc = sum
End Function

Resources