dynamic table references with Excel VBA - 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

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

Filter Table VBA

I am doing my project and I am encountering some problems. Moreover, my scope was to use VBA as a primary software to do my project.
As for now, I am hoping that I can use a drop down list to filter my table whereby it only shows the particular department and weeks I want to show.
From the image below, From the range("C7:L26"), whenever I filter cell(F2) or cell(J2), it will leave the data that I want from the dropdown list.
For example, if cell(F2) = 2 and cell J2 = e, From range("C7,L26"), it will only show department with value "e" and have week 2 in it. As for cells that does not have the department value or week value, it will be cleared or blank.
I also hope that if it is possible to press a button to return the table back to default.
Do guide me and I really need your help!!
[1]http://imgur.com/GNGyh91 [2]http://imgur.com/uuh2Y1u
Update: I have tried recording Macros
Sub Filter()
'
' Filter Macro
Range("B9:BR38").Select
ActiveWindow.ScrollRow = 32
ActiveWindow.ScrollRow = 5
ActiveWindow.ScrollRow = 1
Selection.AutoFilter
ActiveSheet.Range("$B$9:$BR$38").AutoFilter Field:=1, Criteria1:="e"
End Sub
Update 2: Instead of recording Macros, i decided to use a Textbox to filter my table data. However, i realised that my table is not filtering according to what i type in the Text Box.
Private Sub TextBox1_Change()
Dim Text
Text = TextBox1.Value
If Text <> "" Then
Sheet2.Range("A5:AV26").AutoFilter
Field = 1
criteria = "text,_"
visibledropdown = False
Else
Sheet2.AutoFilterMode = False
End If
End Sub
You need to keep the parameters on the same line separated by commas and it is Criteria1, not criteria. If you want to hide the drop-down arrows, you need to do each individually. The code below only hides the dropdown for the field being filtered. If course, if you are only filtering one field then you could just use Sheet2.Range("A5:A26") since filtering goes across all columns.
If True Then
Sheet2.Range("A5:AV26").AutoFilter Field:=1, Criteria1:="text,_", VisibleDropDown:=False
Else
If Sheet2.AutoFilterMode Then Sheet2.AutoFilterMode = False
End If
See Range.AutoFilter Method for more information.

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

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

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

Advance AutoFilter to exclude certain values

I want to filter a large list of names in a Sheet in excel. In another sheet I have contained a list of names that I want to filter out and exclude from the larger list. How would I use the advanced filter to do this? I have tried this below but it is not seeming to work. My big list is in K2:K5000 and my criteria is in H2:H3 (The criteria will grow but I kept the list small for testing). Any help would be greatly appreciated!
Sub Filter()
Sheet5.Range("K2:K5000").AdvancedFilter Action:=xlFilterInPlace, _
CriteriaRange:=Sheets("Sheet3").Range("H2:H3"), Unique:=False
End Sub
To exclude the values in H2:H3 from K2:K5000 using advanced filter you can use following approach:
Make sure cell K1 is not empty (enter any header)
Find 2 unused cells (e.g. I1:I2)
Leave I1blank
Enter the following formula in I2
=ISNA(MATCH(K2,$H$2:$H$3,0))
Use the following code to exclude rows
Sheet5.Range("K1:K5000").AdvancedFilter Action:=xlFilterInPlace, _
CriteriaRange:= Sheets("Sheet3").Range ("I1:I2"), Unique:=False
I am not sure off the top of my head how you would use advanced filter to exclude, but you can use formulas in your advanced filter (near the bottom). You can, however, just use a dictionary to store values you want to exclude, then exclude (hide rows, or autofilter on the ones not found in your exclusion list)
Sub Filter()
Dim i as integer
Dim str as string
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
With Worksheets("Sheet3")
For i = 2 To 3
str = CStr(.Range("H" & i).Value)
If Not dict.exists(str) Then
dict.Add str, vbNullString
End If
Next i
End With
With Sheet5
For i = 2 To 5000
str = CStr(.Range("K" & i).Value)
If Len(str) > 0 And dict.exists(str) Then
.Range("K" & i).EntireRow.Hidden = True
Elseif
'alternatively, you can add those that aren't found
'to an array for autofilter
End if
Next i
End With
'If building autofilter array, apply filter here.
End Sub
Using AutoFilter:
Use an array of strings as criteria to filter on with the "Operator:=xlFilterValues" argument of AutoFilter. Build your array however you want, I chose to do it by building a string with a for loop and splitting (quick to write and test, but not ideal for a number of reasons).
Note: AutoFilter is applied to the headers, not data.
With Sheet5
.AutoFilterMode = False
.Range("K1").AutoFilter _
Field:=1, _
Criteria1:=arr, _
Operator:=xlFilterValues
End With
I think you need to understand first how to use the Advance filter.
There is a good tutorial you can find HERE.
Now based on that, let us make an example. Suppose you have below data:
Now, let us say you want to filter out Data1 and Data2.
According, to the link you can use a formula as criteria but:
Note: always place a formula in a new column. Do not use a column label or use a column label that is not in your data set. Create a relative reference to the first cell in the column (B6). The formula must evaluate to TRUE or FALSE.
So in our case, our relative reference is A11(the first cell or item in the field you want filtered). Now we make a formula in B2 since we cannot use A2, it is a Column Label. Enter the formula: =A11<>"Data1".
Above took care of Data1 but we need to filter out Data2 as well.
So we make another formula in C2 which is: =A11<>"Data2"
Once properly set up, you can now apply Advance Filter manually or programmatically. A code similar to yours is found below:
With Sheets("Sheet1")
.Range("A10:A20").AdvancedFilter xlFilterInPlace, .Range("A1:C2")
End With
And Hola! We have successfully filtered out Data1 and Data2.
Result:
It took me a while to get a hang of it as well but thanks to that link above, I manage to pull it of. I have learned something new as well today :-). HTH.
Additional:
I see that you have your criteria on another Sheet so you have to just use that in your formula. So if in our example you have Data1 and Data2 in H2:H3 in Sheet2, your formula in B2 and C2 is: =A11<>Sheet2!H2 and =A11<>Sheet2!H3 respectively.
You don't really even need VBA for this... to achieve the same result:
Put the values into a separate spreadsheet, in the first column.
Create 2 new columns next to the data you want to filter in your original spreadsheet
In the first column next to your data to be filtered, use
=VLOOKUP(A2, [nameOfOtherSpreadSheet.xlsx/xlsm/xls/etc]sheetName!$A:$A,1, FALSE)
Where A2 is the value you're searching for, field 2 is the reference of the range in which you want to search for this value, 1 is the index of the column in which you're searching, and FALSE tells VLOOKUP to only return exact matches.
In the second column next to the data you want to filter, use
=IFERROR(G2, FALSE)
Where G2 is the reference of the function that might return an error, and FALSE is the value you want to return if that function throws an error.
Filter the second column next to the data you want to filter for FALSEs
This should return the original data set without the values you wanted to exclude.
Record a macro to do this it's one step instead of 5 for future uses.