VBA - Based on User Input - look up value in table - vba

I have created a form that asks for two user inputs, site location and sku. Site location is a drop down and SKU is a text box. Below it there is a textbox which I want to populate based on user input after they hit the "whats my price?" button.user form
I have a matrix of prices with the SKU in column B and the sites across the top in row 1 with their respective prices in the matrix(columns D-H). I have attached a sample of the table. Please note that the "SKU" and "Site" titles will not be in my actual matrix.
pricing table
I need assistance coding the "What's my price?" button in the user form.
I feel as though I would need an if statement using some sort of look up but i'm a little lost as to how to start the code.

Here is what you have to do:
Read the value from the site field;
Read the value from the SKU field;
Display the matching in the Your Price is field, using the following formula:
WorksheetFunction.Index(Range,site field, sku field)
More about WorksheetFunction.Index here:
https://msdn.microsoft.com/en-us/library/office/ff197581.aspx

You need to use Application.Match on the row and the column independently, then get the corresponding cell. Try the following code, but replace the control's names (txtSku, cmbSite) and the sheet's code name (mySheet) with yours.
Sub WhatsMyPrice_Click()
Dim rowNum, colNum
rowNum = Application.Match(txtSku.Value, MySheet.Range("B:B"), 0)
If IsError(rowNum) Then MsgBox "SKU not found": Exit Sub
colNum = Application.Match(cmbSite.Value, MySheet.Rows(2), 0)
If IsError(rowNum) Then MsgBox "Site not found": Exit Sub
txtPrice.Value = MySheet.Cells(rowNum, colNum).Value2
End Sub

Related

Get Pivot Table data into userform VBA

I am trying to fill out a userform with data from an existing Pivot table.
If you see the included image you can see a selection of the pivot table.
In column “A” I have “week number” in Column “B” I have “Booking number”
I have managed to list all the “week number” (A) in a combobox by doing the following.
Dim pt As PivotTable
Set pt = ActiveSheet.PivotTables(1)
SendMailWindow.ComboBox_booking.Clear
pt.PivotSelect Name:="Uge nr.[All]", Mode:=xlLabelOnly, UseStandardName:=True
For Each c In Selection
If c <> "" Then
SendMailWindow.ComboBox_Uge.AddItem c.Value
End If
Next c
My problem now is that I want to have another combobox showing only the “Booking number” from column “B” there are within the select “weeknumber” that the user selects in the first Combobox.
In other words I want to filter Combobox no. 2 so that it only shows booking numbers from the selected week.
Hope one of you have an idea how to do this.
This would be much simpler if you changed the PivotTable Layout to Tablular (or made a copy of the PivotTable, and changed the copy's layout). Then you could simply use the type of syntax at https://peltiertech.com/referencing-pivot-table-ranges-in-vba/
In Jon's example, he does this:
Intersect(pt.PivotFields("Years").Pivotitems("2004").DataRange.EntireRow, pt.PivotFields("Order Date").DataRange).Select
In your case, that would translate to something like:
Intersect(pt.PivotFields("Week Number").Pivotitems(SomeVariable).DataRange.EntireRow, pt.PivotFields("Booking Number").DataRange).Select

How to autocomplete a line with data suggestion?

Context:
In my company, some assistants fill out an Excel table, which is a users list (First Names, Last name, ID number). After, I use this list with a PowerShell script. But very often the users list is not correctly completed. For example, assistants forget to input ID number... .So i would like help assitants to fill this Excel with data suggestions/autocomplete.
Technical:
In the "Data" sheet, I have all data possible (First Names, Last name, ID number).
With the "Name Manager" I created:
d_FirstName to select the first cell
c_FirstName to select all column,
l_FirstName to apply function: =OFSSET(d_FirstName;0;0;COUNTA(c_FirstName)-1;1)
In "Form" sheet, I created drop-down list with function: =IF(A1<>"";OFSSET(d_FirstName;MATCH(A1&"*";l_FirstName;0)-1;;SUMPRODUCT((MID(l_FirstName;1;LEN(A1))=TEXT(A1;"0"))*1));l_FirstName)
So, when the user types a letter, the drop down list "suggest" a correct FirstName.
Question:
How to adapt the last query, to complete a line with First Name and Last name and ID number corresponding if user type only First Name ?
For example:
If user select a First Name in drop down list, Excel complete the lign with Last name and ID number corresponding .
If user select a ID number in drop down list, Excel complete the lign with Last name and First Name corresponding.
In second time, how to show dropdown list automatically when user type one letter ?
Thank you
You can accomplish this using the combobox's properties and change event. The combobox will take a 1 or 2 dimensional named range or a formula that returns a range as it's RowSource. Here I have the text column set to the 3rd column.
Private Sub cboEmpID_Change()
With cboEmpID
If Not IsNull(.Value) Then
lblEmployee.Caption = .List(.ListIndex, 1) & ", " & .List(.ListIndex, 0)
End If
End With
End Sub
Private Sub UserForm_Initialize()
Dim ColumnWidths As String
With Worksheets("Sheet1")
ColumnWidths = .Columns(1).Width & ";" & .Columns(2).Width & ";" & .Columns(3).Width
End With
With cboEmpID
.ColumnHeads = True
.ColumnCount = 3
.ColumnWidths = ColumnWidths
.TextColumn = 3
.ListWidth = Range("Sheet1!A:C").Width
.RowSource = "OFFSET(Sheet1!$A$1,1,0,COUNTA(Sheet1!$A:$A)-1,3)"
End With
End Sub
You need making a cascading dependent Excel drop down list.See

Data Validation of a Filtered table

I have a Data table with an Auto Filter (shown Below).
Sub Tariff_Filter()
Dim columnNumber, tableRow, tableColumn, tableWidth As Integer
Dim tableName, columnName As String
tableName = "Tariff_Table"
columnName = ActiveSheet.Range("A1").Value
'This clears the existing filter
ActiveSheet.ListObjects(tableName).Range.AutoFilter
'Assign some numbers we need to know about the table to check the headers
tableRow = ActiveSheet.ListObjects(tableName).Range.Row
tableColumn = ActiveSheet.ListObjects(tableName).Range.Column
tableWidth = ActiveSheet.ListObjects(tableName).Range.Columns.Count
'If a column title with the specified value does not exist VBA throws an error which we need to catch
On Error GoTo ErrorHandler
'Search through the table column header row to find the specified column and assign the number to columnNumber
columnNumber = Application.WorksheetFunction.Match(columnName, Range(Cells(tableRow, tableColumn), Cells(tableRow, tableColumn + tableWidth)), 0)
'Apply the filter "1" to the found columnNumber
ActiveSheet.ListObjects(tableName).Range.AutoFilter field:=columnNumber, Criteria1:="1"
'Exit the sub otherwise the "error handling" will be provoked
Exit Sub
ErrorHandler:
MsgBox columnName & "Please Specify Required Channel"
End Sub
As i cant seem to figure out how to get my combo-box's to show only the visible cells after filtering the table i was wondering if there is a way i can create a a validation box to show the visible cells or copy the visible data into a seperate table underneath. I can then use the validation box/ secondary table as a focus point for the combo-box's on the user-form.
Thanks in advance
If I'm understanding your question correctly, you would like to have a data-validation drop-down list that updates as the table is filtered and only displays visible items for a given column.
You can do this by using the following formula in Data Validation (I'm assuming your table header row starts in A1 and it's col A you need to display):
=OFFSET($A$2,,,SUBTOTAL(103,TableName[column name]))
This formula expands from the starting cell (A2) by a specified height in number of rows. We are defining the height using SUBTOTAL with function number 103 - this means that the height is defined using COUNTA, but only on visible cells, so it will expand and collapse as the table is filtered.
Be aware: since the height is defined using a counta function, it will only count cells containing data, therefore if you have blanks in your table, the range will not be defined correctly. Also if you have any repeated data, these will be repeated in your drop-down box, this method will not condense them into a neat, unique list.
Hope this is helpful.
D

dynamic table references with Excel VBA

I have an Excel table called "groups" where the headers are group names. In the column below the group name are the members of that specific group.
In another table I have all member names in the first column and the group names in the first row. And I want to check for each member name whether it is in the group above.
To check whether Tim is in the group "guys" I could use the formula:
=if( countif( groups[guys];"Tim")>0;"yes";"no")
But I have a command button "add group" which opens a userform where I can enter a new group + members. The name of the new group is entered into textbox1. The group and member are added to the groups table.
I want the 2nd table to update as well. What I would like to do is something like this:
With Worksheets("Overview").ListObjects("PersonIsInGroupTab")
.ListColumns.Add Position:=3
.HeaderRowRange(3).Value = TextBox1.Value
.DataBodyRange(1, 3).formula= "=if( countif( groups[textbox1.value];""Tim"")>0;""yes"",""no"")"
End With
Unfortunately, this doesn't work.
textbox1.value is the name of the new group (also added to the groups tab).
Is there a way I can make this work?
EDIT:
I tried another approach that didn't work either but might help answering the question.
In the table that checks whether a certain person is a member of a group I start by default with one group. And manually enter the formula
=if(countif(groups[guys],"Tim")>0,"yes","no")
into the cell (in my case J4). When I add a group "gals" using the userform I get a second column "gals" in my table. When I manually drag the formula from the [guys] cell to the [gals] cell (K4) it works just as I want it to. And I get the formula
=if(countif(groups[gals],"Tim)>0,"yes","no")
in the gals cell (K4)
So I figured I could just do this autofill in VBA as part of the "add group" routine. This is the code I used:
Range("groups[guys]").Select
Selection.AutoFill Destination:=Range("J4:K4"), Type:=xlFillDefault
I got this code from recording the autofill as a macro. But when I run it the formula in K4 is just as in J4, with groups[guys] instead of groups[gals].
I cant do Destination:=Range("groups[[guys]:[gals]]") as I want it to be working with any groupname not only gals.
I was able to fix the problem by writing a VBA function instead of using countif.
The function is:
Function IsInGroup(group, member As String) As Boolean
For Each Item In group
If Item = member Then
IsInGroup = True
Exit Function
End If
Next Item
IsInGroup = False
End Function
And I used it like this:
temparray = ActiveSheet.ListObjects("groups").ListColumns(2).Range
With Worksheets("Overview").ListObjects("PersonIsInGroupTab")
tempmember = .DataBodyRange(1, 1).Value
.ListColumns.Add Position:=3
.HeaderRowRange(3).Value = TextBox1.Value
.DataBodyRange(1, 3).Value = IsInGroup(temparray, tempmember)
End With

Macro query spread over multiple-sheets

Wording my question is slightly tricky so I've included screen-shots to make this easier. I have 2 separate spreadsheets which are currently not linked together in anyway. What I've been asked to do is:
For the drop-downs which have a * next to them, have this * drop-down get converted into a acronym (I.e. If it's Home Visit *, then this will be converted to HV), and have it automatically entered into Cell Position X. Please refer to Image 1 then Image 2)
So the user would click on Sheet one, select the relevant drop-down field and then assign how much time that task took. The second sheet would then update itself with this information - it would insert the users name, program and activities. This is where it gets very tricky. Based off the drop-down selection, if it is asterisked (*), then based off the field-type it will convert it into a set acronym which would then be placed in one of the data fields based off the entry date that has been provided.
I designed both spread-sheets and they have macros in the background, but I can't seem to work out how to best perform this. Would you suggest a transpose function which checks firstly the date criteria and then an INDEX(MATCH) function to match the criteria against a pre-defined name-range which converts Home Visit etc. to HV automatically? I'm also unsure of how to insert delimiters for each new entry that is read. If anyone can provide help I would be very grateful.
I'm not 100% sure I understand your question, but here goes:
What about adding a Worksheet_Change event to look for changes in the drop-down's cell, and then converting it to an acronym?
Place the following code inside the sheet of interest:
Private Sub Worksheet_Change(ByVal Target As Range)
'If Cell A1 is changed, put the acronym into A2
If Target.Row = 1 And Target.Column = 1 Then
Cells(2, 1) = GetAcronym(Target.Value)
End If
End Sub
Function GetAcronym(TheText As String) As String
Dim result As String
Dim x As Long
'Always grab the first letter
result = Mid(TheText, 1, 1)
'Get the other letters
For x = 2 To Len(TheText) - 1
If Mid(TheText, x, 1) = " " Then result = result & Mid(TheText, x + 1, 1)
Next x
GetAcronym = UCase(result)
End Function