How do I get all values from a range - excel

I have a column(missing col) that gets all the missing numbers from my id column. So from the entire range of cells most are empty, I want to make another column of just the values that are not empty - mainly cause there are thousands or rows and I need to see those numbers at the top. I have not seen two missing in a row, but that would make a comma separated id cell - i.e. PW140000024,PW140000025 - which may need to dealt with at some point.
Function that makes the missing col:
=IF(MID(E2,3,99)-MID(E1,3,99)>2,"PW"&MID(E1,3,99)+1&",PW"&MID(E2,3,99)-1,IF(MID(E2,3,99)-MID(E1,3,99)>1,"PW"&MID(E1,3,99)+1,""))
Example:
id column | missing col | missing without empty rows
PW140000023 | | PW140000024
PW140000025 | PW140000024 | PW140000027
PW140000026 | PW140000027 | PW140000029
PW140000028 | PW140000029,PW140000030 | PW140000030
PW140000031 | |
PW140000032 | |
Thanks

Assuming your data looks like this with the header row in row 1 and your data starting in row 2, the id columns is Column E and you want the "Missing" column to be column F:
In cell F2 and copied down is this formula:
=IFERROR("PW"&INDEX(SUBSTITUTE($E$2,"PW","")+ROW(INDIRECT("1:"&MAX(INDEX(--(SUBSTITUTE($E$2:$E$7,"PW","")),))-SUBSTITUTE($E$2,"PW","")+1))-1,
MATCH(1,
INDEX(
(COUNTIF(F$1:F1,"*"&INDEX(SUBSTITUTE($E$2,"PW","")+ROW(INDIRECT("1:"&MAX(INDEX(--(SUBSTITUTE($E$2:$E$7,"PW","")),))-SUBSTITUTE($E$2,"PW","")+1))-1,))=0)
*
(COUNTIF($E$2:$E$7,"*"&INDEX(SUBSTITUTE($E$2,"PW","")+ROW(INDIRECT("1:"&MAX(INDEX(--(SUBSTITUTE($E$2:$E$7,"PW","")),))-SUBSTITUTE($E$2,"PW","")+1))-1,))=0)
,)
,0))
,"")
The formula will work great for small sets of data like this sample, but I can see how it would start slowing down Excel drastically for larger data sets. Because of this complication, I would instead recommend creating a VBA subroutine to get the results for you.
Something like this should work:
Sub tgr()
Const strIDcol As String = "E" 'Change to the actual column containing the id's
Const strOPcol As String = "F" 'Change to the actual column you want to OutPut results to
Const lStartRow As Long = 2 'Change to the row your data actually starts on (NOT the header row)
Dim ws As Worksheet
Dim rngIDs As Range
Dim IDCell As Range
Dim arrMissing() As String
Dim MissingIndex As Long
Dim IDMin As Long
Dim IDMax As Long
Dim i As Long
Set ws = ActiveWorkbook.ActiveSheet 'Assuming we're working with the active workbook and active worksheet
Set rngIDs = Range(strIDcol & lStartRow, ws.Cells(Rows.Count, strIDcol).End(xlUp))
IDMin = Val(Replace(rngIDs.Cells(1).Value, "PW", vbNullString))
IDMax = Val(Replace(rngIDs.Cells(rngIDs.Cells.Count).Value, "PW", vbNullString))
ReDim arrMissing(1 To IDMax - IDMin + 1 - rngIDs.Cells.Count, 1 To 1)
For i = IDMin To IDMax
If WorksheetFunction.CountIf(Columns(strIDcol), "*" & i) = 0 Then
MissingIndex = MissingIndex + 1
arrMissing(MissingIndex, 1) = "PW" & i
End If
Next i
Range(strOPcol & lStartRow).Resize(MissingIndex).Value = arrMissing
End Sub

An equivalent result seems possible by creating a list of ids starting PW140000023 (say with ="PW"&140000022+row() in Row1), matching these to id column (say with =MATCH(A1,Sheet1!A:A,0) copying both down to suit, fixing those results as values and then filtering to delete numeric results for matches.

Related

How to check if a row in an excel table has certain values in it using VBA

As the title states I have a table in excel and I want to check if a row in that table contains certain values in it. For example: Table1 has
pid | F_Name | L_Name
0 | Bob | Stoops
1 | Mike | Gundy
2 | Dabo | Swinney
And I want my script to search pid = 0, and L_Name = Stoops, and I want it to return what row in excel that is located.
Also If I were to search pid = 2, and F_Name = Bob and essentially do nothing.
All I can find is the function 'find' when giving it a range object, but I need something a little more than just that. Not sure how to do multiple conditions for a search in vba and return the row.
Thanks and all help is appreciated !
You will need to update a few things here
Update sheet name in 2nd line
Find a more systematic way to assign values to pid and L_Name variables. InputBox?
Create your action statement when your criteria is matched. Note that i denotes the row you are on
Sub Nest()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1")
Dim i As Long
Dim pid As String 'If always # change to Long and change "0" to 0 below
Dim L_Name As String
pid = "0"
L_Name = "Stoops"
For i = 2 To ws.Range("A" & ws.Rows.Count).End(xlUp).Row
If ws.Range("A" & i) = pid And ws.Range("C" & i) = L_Name Then
'Do what when your criteria is matched?
End If
Next i
End Sub
I also assumed your data covers columns A:C so you will need to adjust this as well to reflect your accurate data

Excel Split Single Column Into Multiple Columns Based on Header Rows

I have an excel file that contains data exported from LTSpice simulations. There are 280 different runs however the data is exported as two columns (time and voltage) with a run cell at the start of a new run. The number of data points in each run varies. Looks something like this:
Run 1/280
Time1 Voltage1
Time2 Voltage2
Run 2/280
Time1 Voltage1
Time2 Voltage2
Time3 Voltage3
Run 3/280
I would like to have the run cells as row and the time and voltage columns beneath them.
Run 1/280 Run 2/280 Run 3/280
Time1 Voltage1 Time1 Voltage1
Time2 Voltage2 Time2 Voltage2
Time3 Voltage3
I haven't found an easy way to do this yet, so any help would be appreciated.
Thanks
Without VBA...
For each row of your input list, you need to identify its type (Run x/xxx header or terminal, voltage pair) and the row and pair of columns in the output where this input row belongs.
In the picture below, columns A and B perform this task. Column A identifies the output column pair and B the output row, where row 0 indicates the header row of the output.
The header row of the output utilises the fact that if an array is sorted in ascending order and has repeated values then MATCH(x,array,0) finds the index of the first element in array equal to x. The cumbersome repetition of the SUMPRODUCT term in the formulae for the other rows is necesssary for the following reason. If there is no matching pair in columns A and B to the current output row and column pair number then the SUMPRODUCT delivers 0 and, unfortunately, the INDEX(array,SUMPRODUCT()) term evaluates to INDEX(array,0) which delivers the first element of array (*) - which is not what is wanted.
You obviously need sufficient helper values in row 1 and column E of the worksheet in the output area - the maximum values of columns B and A, respectively determine the requirements. Oversizing the output (as the picture has done) is not a problem as the formulae in any redundant positions simply evaluate to "".
(*) In fact, for a single column array the formula =INDEX(array,0) evaluates to the array itself. When used as cell formula (rather than being used as an array formula across a range of cells) formula simply picks the first value from array.
Please try this code.
Sub SplitToColumns()
' 16 Sep 2017
Dim WsS As Worksheet ' S = "Source"
Dim WsD As Worksheet ' D = "Destination"
Dim WsDName As String
Dim RunId As String ' first word in "Run 1/280"
Dim RowId As Variant ' value in WsS.Column(A)
Dim Rl As Long ' last row (WsS)
Dim Rs As Long, Rd As Long ' row numbers
Dim Cd As Long ' column (WsD)
WsDName = "RemoteMan" ' change to a valid tab name
Application.ScreenUpdating = False
On Error Resume Next
Set WsD = Worksheets(WsDName)
If Err Then
' create WsD if it doesn't exist:
Set WsD = Worksheets.Add(After:=Worksheets(Worksheets.Count))
WsD.Name = WsDName
Cd = -1
Else
' continue adding new data to the right of existing,
With WsD.UsedRange
Cd = .Columns.Count - 1
If Cd = 1 And .Rows.Count = 1 Then Cd = -1
End With
End If
Set WsS = Worksheets("Remote") ' change to a valid tab name
With WsS
' presume "Run" & Time in column A, Voltage in Column B
' presume: no blank rows
Rl = .Cells(Rows.Count, "A").End(xlUp).Row
RunId = .Cells(2, 1).Value ' row 2 must have the RunId
RunId = Left(RunId, InStr(RunId, " ") - 1)
For Rs = 2 To Rl ' assume data start in row 2 (A1 may not be blank!)
RowId = .Cells(Rs, "A").Value
If InStr(1, RowId, RunId, vbTextCompare) = 1 Then
Rd = 1 ' first row to use in WsD
Cd = Cd + 2 ' determine next columns
End If
WsD.Cells(Rd, Cd).Value = RowId
WsD.Cells(Rd, Cd + 1).Value = .Cells(Rs, "B").Value
Rd = Rd + 1 ' next row to use
Next Rs
End With
Application.ScreenUpdating = True
End Sub

Excel formula to space out range depending on other variable

Right - this is a tricky one to phrase so I'm going to use a couple of images to help me.
In Columns A and B is a varying list of team names and the number of players each team has.
Column D contains the desired output.
I need a formula, to be inserted into Cell D2 and dragged down as far as the total of Column B, to return the team names - but crucially to allow a number of rows beneath which return blank. The number of blank rows beneath is effectively equal to 1 - the number of players in that team.
I have given it some thought, but can't come up with a suitable formula. Any ideas?
Also suggestions for a better title are welcome.
The following VBA function will do exactly what you want. Let me know if any part of it is not clear to you.
Sub teamRows()
Dim colDRowNumber As Integer
Dim i As Integer
Dim teamName As String
Dim numberOfRows As Integer
Dim HowFar As Integer
' Loop through the teams in column A
HowFar = Application.WorksheetFunction.CountA(Range("A:A"))
' Variable to keep count of rows in column D
colDRowNumber = 2
For i = 2 To HowFar
' Get the team's name and number of rows
teamName = Range("A" & i).Value
numberOfRows = Range("B" & i).Value
' Fill in the team's name in column D
Range("D" & colDRowNumber).Value = teamName
' Increase the row number by the number of empty rows required
colDRowNumber = colDRowNumber + numberOfRows
Next i
End Sub
A complex but short attempt - I wanted to avoid loops.
Example below works on A2 to A20
y = Split(Join(Application.Transpose(Application.Evaluate("=index(substitute(substitute(substitute(REPT(A2:A20 &"","",B2:B20),A2:A20&"","",""X"",1),A2:A20,""""),""X"",A2:a20),0,1)")), ","), ",")
[d2].Resize(UBound(y)) = Application.Transpose(y)

Copying content from one worksheet to another if value matches another value?

I'm trying to import product variants and their prices with two csv files:
config.csv (where I'm trying to place the variants/prices)
variants.csv (where the information on the variants exists)
The format I need is size::3' x 5':-120 for example.
This is what config.csv looks like:
SKU super_attribute_pricing
VTG100-130
VTG100-730
....
This is what variants.csv looks like:
sku size price
VTG100-130 3' x 5' -120
VTG100-130 4' x 6' -80
VTG100-130 5' x 8' 0
VTG100-730 3' x 5' -120
VTG100-730 4' x 6' -80
....
How can I use the 3 values above and put it in the format size::3' x 5':-120 as long as the sku in variants.csv matches the sku in config.csv?
I tried this for value in super_attribute_pricing column:
="size::"&[variants.csv]variant!B2&":"&[variants.csv]variant!C2&";"
But the above does not consider whether the value in sku column in variants.csv matches the sku in config.csv. I want to copy those values as long as the SKU's match up - otherwise I want to move to the next row and coninue comparing until it ends.
How to do this with VBA?
Here's the VBA code to solve your problem. Call it by using a function in the cell you want the description based in by using the following format:
=GetSizes(A2,[variants.csv]variant!$A$2:$A$6)
The first parameter is the part to lookup and the second parameter is the absolute list of parts from your sizes table (variants)
This function call is assuming you are calling it from the config.csv sheet and that your table's first data row is in A2 on each workbook respectively. Change sheets or cell addresses appropriately. The way the code is written you only need to pass the list of Part numbers. The offset will look up the information from the size and price columns for you.
Function GetSizes(rngValue As Range, rngLookup As Range) As String
Dim strSizes As String
Dim strLookup As String
Dim rngTemp As Range
Dim cellval As Range
Set rngTemp = rngLookup
strLookup = rngValue.Value
strSizes = "size::"
For Each cellval In rngTemp
If cellval.Value = strLookup Then
strSizes = strSizes & cellval.Offset(0, 1).Value & ":" & cellval.Offset(0, 2).Value & ";"
End If
Next
If strSizes = "size::" Then strSizes = ""
If Right(strSizes, 1) = ";" Then strSizes = Left(strSizes, Len(strSizes) - 1)
GetSizes = strSizes
End Function
Note that if there is no matching part number it will return an empty string.
Good luck.

VBA call to get value of entire row in Excel

I am quite new in excel macros and need to extract data from entire row, if you select any row. Suppose there is a sheet having following data:
s.no amount account
1 1234 1234
2 2345 6359
If I select 1st row 1 then it gives value of entire row :
1 1234 1234
I have tried a lot to extract value but I am unable to get value.
You will have to loop through the cells in the row and concatenate the values. There is no function that I'm aware of that returns the "value" of the row. For example:
Dim objSheet As Worksheet
Set objSheet = Sheets(1)
Dim intLastCellIndexInRow As Integer
intLastCellIndexInRow = ActiveCell.SpecialCells(xlLastCell).Column
Dim i As Integer
Dim strRowValue As String
For i = 1 To intLastCellIndexInRow
strRowValue = strRowValue & " " & objSheet.Cells(ActiveCell.Row, i)
Next
MsgBox strRowValue
The Value of a row is an array of the values in that Row
RowData = Range("A1:C1").Value
would fill the Array "RowData" the same as the code
RowData = Array(1,1234,1234)
If you wanted a String like what rory.ap had answered, you use Join
'Same Msgbox result as rory.ap's Answer
strRowValue = Join(RowData, " ")
MsgBox strRowValue
So to get a row as a Space (" ") separated string in one line
strRowValue = Join(Range("A1:C1").Value, " ")
Now I put in the Range "A1:C1" because your data is Columns A thru C
The Entire Row 1 is the Code
Rows(1)
But that Includes EVERY Column until the MAX, Which we really don't want in our string or even need to deal with.
Excel can Detect your data by using the .CurrentRegion from a Starting Point. So if we use A1 as our starting point, get the CurrentRegion and then limit it to the first row we'll only get the Columns used.
Cell("A1").CurrentRegion.Rows(1)
'Is Equivalent to Range(A1:C1) on your Data Example
Cell("A1").CurrentRegion.Rows(2)
'Is Equivalent to Range(A2:C2) on your Data Example

Resources