Excel Sequential Numbering order based on hierarchy position of data - excel

I need to add sequential numbering order in excel based on the list position of data within excel. I have tried many things to get this right but surely there must be an easy solution.
As you can see my data is an ordered list of text where you can see the hierarchy in the offset of data down the rows. I am trying to automatically create the yellow picture based on the data from the left side.
The only solution I have come up with is to add columns in front of each column, filter the records based on non-blanks then work from left to right manually adding the sequence, but even this is too time intensive.
Ill be working on a macro next but thought there may be an easier solution using a formula. - will update if found.

This is probably not the most efficient solution, but it works:
Formula in G2 (fill the rest of the area with it):
=IF(ISBLANK(A2),IF(ISBLANK(B2),G1,G1+1),0)
Formula in L2 (fill the rest of the area with it):
=IF(G2>0,K2&"."&G2,"")
Formula in Q2 (fill the rest of the area with it):
=IF(ISBLANK(B2),"",MID(L2,2,LEN(L2))&" - "&B2)
You can easily use it for any depth by increasing the areas size, but you need an empty top row and empty column on the left of each area to make it work.
You could probably skip L:O area by combining the last two formulas.

Result:
Formulas: (blue are constants, orange are for the first hierarchy level, green are dragged in the box)

Sub Sequential_Numbering()
Dim tmpRange As Range, tmpArray(1 To 4) As Integer, x As Integer
Set tmpRange = Range("A1")
tmpArray(1) = 1
tmpRange.Value = tmpArray(1) & " - " & tmpRange.Value
For x = 2 To 13
Set tmpRange = Rows(x).Find(What:="*")
Select Case tmpRange.Column
Case 1
tmpArray(1) = tmpArray(1) + 1
tmpArray(2) = 0
tmpArray(3) = 0
tmpArray(4) = 0
tmpRange.Value = tmpArray(1) & " - " & tmpRange.Value
Case 2
tmpArray(2) = tmpArray(2) + 1
tmpArray(3) = 0
tmpArray(4) = 0
tmpRange.Value = tmpArray(1) & "." & tmpArray(2) & " - " & tmpRange.Value
Case 3
tmpArray(3) = tmpArray(3) + 1
tmpArray(4) = 0
tmpRange.Value = tmpArray(1) & "." & tmpArray(2) & "." & tmpArray(3) & " - " & tmpRange.Value
Case 4
tmpArray(4) = tmpArray(4) + 1
tmpRange.Value = tmpArray(1) & "." & tmpArray(2) & "." & tmpArray(3) & "." & tmpArray(4) & " - " & tmpRange.Value
End Select
Next x
End Sub

Related

VBA code to create 2 graphs from overlapping, discontinuous arrays

I am trying to automate a process to generate 2 XYScatter graphs from 1 table and seem to be making a mess of it. There are multiple issues I'm hitting so I will try to describe 1 at a time.
The first issue is setting the X & Y ranges. The table could contain anywhere from 4 to a few hundred rows. Column A = X values, column F says if it is level 1/graph 1 or level 2/graph 2, & column J = Y value. I created 4 Range variables, RngL1X, RngL1Y, RngL2X & RngL2Y. Then I wrote some code to loop through column F and fill the data ranges (see below).
What is the correct syntax to make an empty range? Before I can use them, the ranges need to have initial values. I would like to set them to "Empty" but VBA doesn't like any of the syntax I have tried: Set RngL1X = " ", RngL1X = IsNull, RngL1X = IsEmpty, etc.
Here's the loop code for filling the variables. I can't tell how well it will work until I solve the problem of the initial values.
Range("F2").Select
Do While IsEmpty(ActiveCell) = False
If ActiveCell Like "*Level 1*" Then
RngL1X = RngL1X & ", " & ActiveCell.Offset(0, -5)
RngL1Y = RngL1Y & ", " & ActiveCell.Offset(0, 4)
Else
RngL2X = RngL2X & ", " & ActiveCell.Offset(0, -5)
RngL2Y = RngL2Y & ", " & ActiveCell.Offset(0, 4)
End If
Debug.Print RngL2Y
ActiveCell.Offset(1, 0).Select
Loop
When I tested the loop with the variables as a string (not a range) it worked well.

Find and replace values after looking up table

I have a sheet called "Table" where I have the table I'm looking up its A2:B20,
A2:A20 contains numbers in "XX" format these are the numbers I will be looking up.
The B2:B20 part of the table contains text is this text I want to use to replace values with.
I have my main sheet (currently called "Test") which contains my data, I want to look in Column M and check if I can find a value where the first 2 chars match any one of the values in A2:A20, if I do find a match I then want to replace the value of column F on my data sheet (Test) with the corresponding value from B2:B20 if not I want to leave it as is and move on.
I'm running into problems as the data in column M is numbers stored as text and it is replacing the wrong value when the table list 1 or 11 or 2 and 22.
'
Dim MyString As String
Counter = 2
1:
MyString = Sheets("Table").Range("A" & Counter).Value
For X = 1 To Range("M" & Rows.Count).End(xlUp).Row
If Replace(MyString, Left(Sheets("TEST").Range("M" & X).Value, 2), "") <> MyString Then Sheets("TEST").Range("F" & X).Value = Sheets("Table").Range("B" & Counter).Value
Next
Counter = Counter + 1
If Counter <= Range("M" & Rows.Count).End(xlUp).Row Then
GoTo 1:
Else
End If
End Sub
I solved my own problem, I was doing too much - simplified it forces values to .text and my issues went away.
Sub BBK_Name()
'Checks column U for start of data (1st 2 chars)
' if they match an entry in bank table changes entry in column G to match table entry.
'
Dim MyString As String
Counter = 2
1:
MyString = Sheets("Table").Range("A" & Counter).Text
RplcValue = Sheets("Table").Range("B" & Counter).Text
For X = 1 To Range("M" & Rows.Count).End(xlUp).Row
If Left(Sheets("TEST").Range("M" & X).Value, 2) = MyString Then _
Sheets("TEST").Range("F" & X).Value = RplcValue
Next
Counter = Counter + 1
If Counter <= Range("M" & Rows.Count).End(xlUp).Row Then
GoTo 1:
Else
End If
End Sub

Join rows based on unique ID

I have 32.000 rows with data. Some data are in a different place and I want to join them with something that I can apply to all rows and not manually. Each "group" have the same ID, in this example is "XPTO"
I have something like this now (but with more columns):
I want it to be like this:
The problem is that I need a clever way, because they are not always exactly like this example. Some of them have 10 rows with the same ID "XPTO" (example)
I am struggling with this =/ ty
Here's how I would approach this.
1) From your comment, I understand that the logic is positional (the first one on the left (Casteloes de) goes with the first one on the right (R Dr Antonio) for the matching value in column A. If that is true, then I would insert a column where you start numbering sequentially, then Fill Down to get sequential numbers all the way to the end. This will help preserve the positional logic if you need to sort or rearrange your data. It will also help you with the logic of "first match", "second match", etc.
2) My next step would be to separate the two sets of data into separate tables/tabs (with the sequentially numbered column appearing in each) and use INDEX/MATCH. The recent answer here will help you with how to increment the match: Is there such thing as a VLOOKUP that recognises repeated numbers?
3) Alternative - this may even be easier, although you'll want to do extensive data checking to make sure nothing got screwed up. With the two tables from step 2, sort by any column with data in it, then delete the blank rows from each table. Then, sort each by the sequentially numbered column to return to the original order. At that point you may be able to just copy and paste. Check carefully for errors if you do this.
I am positive that the solution above given by CriketBird work, at least it has a good logic to solve it, but since I am a newbie in excel, I couldn't figure it out how to solve it that way.
So I solved it by using VBA in excel...(maybe I went too far for this simple problem, but it was my only option).
I will leave the code here if someone want it for a similar situation. (just select the first column and row your table starts and hit run)
Function Area(medico As String) As Integer
Do While countOk < 1
If medico = ActiveCell.Value Then
ActiveCell.Offset(1, 0).Select
rowCount = rowCount + 1
Else: countOk = 1
End If
Loop
Area = rowCount
End Function
Sub Teste()
Dim PaginaMedico As String
Dim totalrowCount As Integer
Dim rowCount As Integer
Dim countOk As Integer
Dim right As Integer
Dim left As Integer
Dim listaleft As New Collection
Dim listaright As New Collection
rowCount = 1
rowOk = 0
totalrowCount = 0
right = 0
left = 0
Do While ActiveCell.Value <> 0
PaginaMedico = ActiveCell.Value
rowCount = Area(PaginaMedico)
totalrowCount = totalrowCount + rowCount
Range("A" & (totalrowCount - (rowCount - 1))).Select
For i = ((totalrowCount + 1) - rowCount) To totalrowCount
If IsEmpty(Range("E" & (i)).Value) And IsEmpty(Range("F" & (i)).Value) Then
Range("T" & (i)).Value = "Empty"
ElseIf Not IsEmpty(Range("E" & (i)).Value) And Not IsEmpty(Range("F" & (i)).Value) Then
Range("T" & (i)).Value = "Full"
ElseIf Not IsEmpty(Range("E" & (i)).Value) And IsEmpty(Range("F" & (i)).Value) Then
left = left + 1
listaleft.Add i
ElseIf IsEmpty(Range("E" & (i)).Value) And Not IsEmpty(Range("F" & (i)).Value) Then
right = right + 1
listaright.Add i
End If
Next i
If Not (right = left) Then
Range("T" & totalrowCount).Value = "BOSTA"
right = 0
left = 0
End If
If listaleft.Count = listaright.Count Then
For i = 1 To listaleft.Count
Range("F" & listaright(1) & ":" & "S" & listaright(1)).Cut Range("F" & listaleft(1) & ":" & "S" & listaleft(1))
listaright.Remove (1)
listaleft.Remove (1)
Next i
End If
Set listaleft = New Collection
Set listaright = New Collection
Range("A" & (totalrowCount + 1)).Select
Loop
End Sub

replace string in cell range with part of the original text

I have an excel sheet with a column for Car number. It is currently downloaded as a report with the format "58 58" for car number 58.
I would like to replace each occurrence down column H and replace "58 58" with a numeric "58" | "60 60" with "a numeric "60" | "90 90" with a numeric "90" and so on.
This is all done in VBA.
Thank you
UPDATED CODE:
Dim X As Long
For X = 2 To Range("I" & Rows.Count).End(xlUp).Row 'Change 1 to 2 if you have a heading in row 1
Range("I" & X).Formula = Split(Range("I" & X).Text, " ")(0)
I used the above code, but it gave me runtime error (9) subscript out of range
Probably the easiest way is to loop. Going backwards alleviates possible issues with 101 being messed up if you start at 1.
Sub DoubleToSingle()
Dim X As Long
For X = 100 To 1 Step -1
Cells.Replace X & " " & X, X
Next
End Sub
This works on all cells, if you want it on just a column replace Cells. with Columns(2). where 2 is column B and 3 would be C etc.
Edit: use this code for your updated questions:
Sub DoubleToSingle2()
Dim X As Long
For X = 2 To Range("I" & Rows.Count).End(xlUp).Row
If InStr(1, Range("I" & X).text, " ") > 0 Then Range("I" & X).Formula = Split(Range("I" & X).text, " ")(0)
Next
End Sub
How it works: It polls through all cells in column I that have data and for each cell it splits the text of the cell into an array using space, then it takes just the first element in the array (basically everything before the first space) and posts that back to the cell.

Calculating Data in VBA Excel Where conditions can vary

I am coaching a rifle shooting team and I am designing a program to analyse the data, all the data required is stored in a large denormalized on a sheet in excel. I am hoping to calculate statistics for each shooter such as Average Score, Top Score, Std Dev etc. How ever on my summary sheet I also need a bunch of variables to filter the data with such as Day of the year, time of day, distance shot, the year.
I am attempting to design my own fuctions such as
Public Function AveScore(ShooterID As String, YearShot As Integer, Optional Day As String = "All Year", Optional TimeOfDay As String = "All Day", Optional Distance As String = "All", Optional OutOf As Integer = 40, Optional TopShots As Integer = 0, Optional AdjOutOf As Boolean = True) As Double
This then I will be able to call easily on my sheets and allow me to easily adapt my format. However due to the nature of the filters they will sometimes filter some data and other times I would like all data in those areas. Each filter corresponds to a field in the table.
I found that using loops to calculate the results ended up with many many overwhelming if statements which was unrealistic because I had to account for each eventuality for when certain conditions were needed or not
the following is my attempt as writing it by creating an excel formula through if statements then evaluating this
Public Function AveScore(ShooterID As String, YearShot As Integer, Optional Day As String = "Al Year", Optional TimeOfDay As String = "All Day", Optional Distance As String = "All", Optional OutOf As Integer = 40, Optional TopShots As Integer = 0, Optional AdjOutOf As Boolean = True) As Double
'if TopShots is 0 then no top and show all shots
Dim formula As String: formula = "{=AVERAGE("
Dim top As Boolean: top = False
Dim i As Integer
'check if they want to look at the top shots
If TopShots <> 0 Then
top = True
formula = formula + "LARGE("
End If
'add 2 if statements that check year and shooterID
formula = formula + "IF(DenormalizedTable[Year]=" & YearShot & ",IF(DenormalizedTable[ShooterID]=" & Chr(34) & ShooterID & Chr(34) & ","
Dim counter As Integer: counter = 2
'check if its a day or period the add the IF statement
If Day <> "All Year" Then
Set c = Lists.Range("PeriodList").Find(Day, LookIn:=xlValues, lookat:=xlWhole)
If Not c Is Nothing Then
formula = formula + "IF(DenormalizedTable[Period]=" & Chr(34) & Day & Chr(34) & ","
counter = counter + 1
Else
Set c = Lists.Range("DayList").Find(Day, LookIn:=xlValues, lookat:=xlWhole)
If Not c Is Nothing Then
formula = formula + "IF(DenormalizedTable[Day]=" & Chr(34) & Day & Chr(34) & ","
counter = counter + 1
End If
End If
End If
'and the time of day if
If TimeOfDay <> "All Day" Then
formula = formula + "IF(DenormalizedTable[TimeOfDay]=" & Chr(34) & TimeOfDay & Chr(34) & ","
counter = counter + 1
End If
'Add the distance IF
If Distance <> "All" Then
formula = formula + "IF(DenormalizedTable[Distance]=" & Distance & ","
counter = counter + 1
End If
formula = formula + "DenormalizedTable[%Score]"
'add the brackets for the IFs
For i = 1 To counter
formula = formula + ")"
Next i
If top Then
formula = formula + ",{"
For i = 1 To TopShots
formula = formula + i
If i <> TopShots Then
formula = formula + ","
End If
Next i
formula = formula + "})"
End If
formula = formula + ")*" & OutOf & "}"
MsgBox formula
AveScore = Evaluate(formula)
End Function
How ever this function also seems very impractical and unextendable for the other functions I wish to write
I was hoping someone would be able to suggest a way I might achieve this analysis that is practical
I am only new to coding and do not have the best knowledge of prebuilt functions however I have done lots of research and could not find anything that would help me

Resources