How to get a name of control by name? - excel

I have a simple function where there's a combo box. If combo box's value is equal to "Disable", I'll disable textbox B. There are many combo boxes with their corresponding textbox B, arranged in rows and named by hand. If combo box A is named Product1, textbox B will be named Product1_status
I was thinking something like:
If value_of_a = "disable" Then
Dim name_of_b as String
name_of_b = Me.Combo.Name + "_status"
get_object_by_name(name_of_b).Enabled = False
End If
How do I do this?

I'm not sure how you are calling this, but here's a self-contained procedure that should help:
Sub test()
Dim ws As Excel.Worksheet
Dim ProductCombo As OLEObject
Dim ProductText As OLEObject
Set ws = ThisWorkbook.Sheets(1)
With ws
Set ProductCombo = .OLEObjects("Product1")
Set ProductText = .OLEObjects(ProductCombo.Name & "_status")
ProductText.Enabled = ProductCombo.Object.Text <> "Disabled"
End With
End Sub
EDIT: I really hate worksheet controls - I start from scratch every time I program them! Nonetheless, I thought I'd add this subroutine which resets every textbox whose name fits the patter Product#_status, according to its paired combobox. The logic does assume the names start with Product1, Product2, etc., without a gap in the numbering:
Sub test2()
Dim ws As Excel.Worksheet
Dim ctl As OLEObject
Dim i As Long
Dim ProductComboboxesCount
Dim ProductCombo As OLEObject
Dim ProductText As OLEObject
Const ControlPrefix As String = "Product"
Set ws = ThisWorkbook.Sheets(1)
With ws
For Each ctl In .OLEObjects
If TypeOf ctl.Object Is MSForms.ComboBox And Left(ctl.Name, Len(ControlPrefix)) = ControlPrefix Then
ProductComboboxesCount = ProductComboboxesCount + 1
End If
Next ctl
For i = 1 To ProductComboboxesCount
Set ProductCombo = .OLEObjects(ControlPrefix & i)
Set ProductText = .OLEObjects(ControlPrefix & i & "_status")
ProductText.Enabled = ProductCombo.Object.Text <> "Disabled"
Next i
End With
End Sub

VBA
Edit: (Change for an actual VBA macro)
Sub Macro1()
'
' GetControl By Name
'
If value_of_a = "disable" Then
GetControl(ComboBox1.Name + "_status").Enabled = False
End If
End Sub
Function GetControl(nameOfControl As String) As OLEObject
Dim ctrl As OLEObject
For Each ctrl In ActiveSheet.OLEObjects
If ctrl.Name = nameOfControl Then
Set GetControl = ctrl
End If
Next ctrl
End Function
VB.Net
Code for VB.Net if anyone wants it for that reason:
Sub Main()
If value_of_a = "disable" Then
GetControl(ComboBox_1.Name + "_status").Enabled = False
End If
End Sub
Function GetControl(nameOfControl As String) As Control
For Each ctrl In Me.Controls
If ctrl.Name = nameOfControl Then
Return ctrl
End If
Next ctrl
Return Nothing
End Function

Related

How to delete added value in cells in Excel Worksheet

From the picture on the left side, it is the input and after the user presses the button the output will appear on the right side.
My problem is that after the user presses the button and the result appears. I want the inputted data on the left side to disappear so that the user can re-input the data again and again
What do I need to add in my code so that it will give the result I want.
This is my code:
Private Sub CommandButton1_Click()
Dim i As Long, j As Long
Dim wks As Worksheet
Set wks = Worksheets("Sheet1")
Set AddNew = wks.Range("M65356").End(xlUp).Offset(5, 0)
For i = 1 To 15
For j = 1 To 7
AddNew.Cells(i, j) = wks.Range("B1").Cells(i, j)
Next j
Next i
End Sub
Just add :
wks.Range("B1").Cells(i, j) = ""
After your AddNew line
Your current code skips over the last inputline (15). But maybe consider to not use loops but to transfer the data in one go:
Private Sub CommandButton1_Click()
Dim wks As Worksheet: Set wks = Worksheets("Sheet1")
Dim AddNew As Range: Set AddNew = wks.Range("M65356").End(xlUp).Offset(5, 0)
AddNew.Resize(16, 7).Value = wks.Range("B1:H16").Value
wks.Range("B1:H16").Value = ""
End Sub

How to link each items in a combobox to a specific row?

I am creating a userform that is entering data on a form. And in that userform I have a Combobox that list out all the products. For each product there a row and the data that is being inputted in would only be on that row.
Private sub cwbSave_Click()
Dim ws as Worksheet
Set ws = ActiveWorkbook.ActiveSheet
with ws
Select Case cbProduct
Case Is = "Apple"
With ActiveSheet.Range("A14:P14")
.Font.Bold = True
End With
ws.Cell(14,4) = Me.tbPrice
ws.Cell(14,5) = Me.tbColor
ws.Cell(14,6) = Me.tbSell
Case Is = "Pineapple"
With ActiveSheet.Range("A15:P15")
.Font.Bold = True
End With
ws.Cell(15,4) = Me.tbPrice
ws.Cell(15,5) = Me.tbColor
ws.Cell(15,6) = Me.tbSell
End Select
End With
End Sub
But the thing is, I got like 30 products. And it a lot of manually putting in. I was wondering if there an easier way to code this.
Thank you
There are several ways to do this.. here is one:
In the UserForm_Initialize, add the below code:
Private Sub UserForm_Initialize()
Dim aValues As Variant: aValues = WorksheetFunction.Transpose(ThisWorkbook.Worksheets("Sheet2").Range("A2:A5")) ' Change sheet name and range to where your products are
Dim iRow As Long
' Clear combobox
Me.cmbCmbBox.Clear
' Fill combobox with the values from product range
For iRow = LBound(aValues) To UBound(aValues)
Me.cmbCmbBox.AddItem aValues(iRow)
Next
End Sub
Above code uses your product range to populate the combobox. Now in cmbCmbBox_Change, add the following code:
Private Sub cmbCmbBox_Change()
Dim oWS As Worksheet: Set oWS = ThisWorkbook.Worksheets("Sheet2")
Dim rProdRange As Range: Set rProdRange = oWS.Range("A2:A5")
Dim rItemRange As Range
' Find the selected item
Set rItemRange = rProdRange.Find(Me.cmbCmbBox.Value)
' Set value in the sheet
If Not rItemRange Is Nothing Then
oWS.Cells(rItemRange.Row, 4) = Me.tbPrice
oWS.Cells(rItemRange.Row, 5) = Me.tbColor
oWS.Cells(rItemRange.Row, 6) = Me.tbSell
End If
End Sub
You can add validation for when product is not found

Using CheckBox as autofilter buttons (excel VBA)

I am looking to use multiple (5) checkboxes to filter a single column in an excel table. The column to be filtered contains several markers namely
"","r","x","s","t"
Here a picture of the boxes:
My aim is to tick several boxes and include all the columns with said marker. Using straightforward methods results in the previous filter being cleared instead of being "added".
Here a picture of my (now two) tracking columns, one containing the identifier and another hidden converting that too the checkbox captions using ifs statements so #zac's solution works.
I have a looked around a lot and found a thread on MrExcel where some code was provided however I was unable to adapt it to my exact needs. Sadly whichever button I press it keeps defaulting to the blank ("") marker.
Below is my code for a sub that should be called by each checkbox.
Background info:
The identifier value are defined in a table and assigned a dynamic named range "tracking"
The column to be filtered is called ("Project Flag")
The code is contained in a seperate module
Sub Project_Filter()
Dim objcBox As Object
Dim cBox As Variant
Set Dbtbl = Sheets("Database").ListObjects("Entire")
ReDim cBox(0)
Dim trackers() As String
Dim i As Integer
Dim x As Variant
i = -1
For Each x In Range("Tracking").Cells 'reading named range into array
i = i + 1
ReDim Preserve trackers(i) As String
trackers(i) = x.Value
Next x
Application.ScreenUpdating = False
With Sheets("Database")
For Each objcBox In .OLEObjects
If TypeName(objcBox.Object) = "CheckBox" Then 'looking for checkboxes
If objcBox.Object.Value = True Then
cBox(UBound(cBox)) = trackers(i) 'setting cbox array as nth trackers value
i = i + 1
ReDim Preserve cBox(UBound(cBox) + 1)
End If
End If
Next
If IsError(Application.Match((cBox), 0)) Then
MsgBox "Nothing Selected"
Exit Sub
End If
ReDim Preserve cBox(UBound(cBox))
If Not .AutoFilterMode Then
Dbtbl.Range.AutoFilter
Dbtbl.Range.AutoFilter Field:=Dbtbl.HeaderRowRange.Find("Project Flag").Column, Criteria1:=Array(cBox)
End If
End With
Application.ScreenUpdating = True
End Sub
So after some trial and error i found out that the array cbox() only contains the first value of my trackers array, hence it only filtering the blank entries. No idea what causes that but thought it might be noteworthy
Based on our conversation and the picture of your checkboxes in your description, we can get the filter text from the caption:
Option Explicit
Sub Project_Filter()
Dim oOLE As Object
Dim oWS As Worksheet: Set oWS = ThisWorkbook.Worksheets("Sheet1") ' <--- Remeber to change this
Dim aFilter As Variant
Dim sFilterChar As String
' Referenc the sheet
With oWS
' If 'All Projects' checkbox is selected, unselect all other checkboxes
If .OLEObjects("chkAll").Object.Value Then
ClearCheckboxes
End If
' Loop to capture all selected check boxes
For Each oOLE In .OLEObjects
If TypeName(oOLE.Object) = "CheckBox" And oOLE.Object.Value And oOLE.Object.Caption <> "All Projects" Then
If Not IsArray(aFilter) Then
ReDim aFilter(0)
Else
ReDim Preserve aFilter(UBound(aFilter) + 1)
End If
sFilterChar = Mid(oOLE.Object.Caption, 2, 1)
If sFilterChar = "]" Then
aFilter(UBound(aFilter)) = ""
Else
aFilter(UBound(aFilter)) = sFilterChar
End If
End If
Next
' Set the filter based on selection
If IsArray(aFilter) Then
.ListObjects("Table1").Range.AutoFilter field:=2, Criteria1:=aFilter, Operator:=xlFilterValues
Else
.ListObjects("Table1").Range.AutoFilter
End If
End With
' Clear Object
Set oWS = Nothing
End Sub
' Clear all checkboxes other than 'All Projects' checkbox
Private Sub ClearCheckboxes()
Dim oOLE As Object
Dim oWS As Worksheet: Set oWS = ThisWorkbook.Worksheets("Sheet1") ' <--- Remeber to change this
With oWS
' Clear checkboxes
For Each oOLE In .OLEObjects
If TypeName(oOLE.Object) = "CheckBox" And oOLE.Object.Caption <> "All Projects" Then
If oOLE.Object.Value Then
oOLE.Object.Value = False
End If
End If
Next
End With
' Clear object
Set oWS = Nothing
End Sub
NOTE: I have All Projects as a checkbox as well

Using Excel VBA Combo Box to Draw A Chart From Different Sheets

Okay so what I am trying to do is have a userform with a combobox that displays each sheet as an option. I got that down. I want to be able to select a sheet and draw a chart from certain ranges on said sheet on my userform. I hope that makes sense.... Here is what I have got so far. It works with the first combobox selection, but once I change sheets and try to draw a chart from a different worksheet I get an error, "Method 'Values' of object 'series' failed. Any help would be greatly appreciated. Thanks in advance =)
Private Sub ComboBox1_Change()
End Sub
Private Sub CommandButton1_Click()
If ComboBox1.Text = "Select A Client" Then
MsgBox "You Must Select a Name to Continue.", , "ERROR:Select A Name"
ComboBox1.SetFocus
Exit Sub
End If
Dim MyChart As Chart
Dim ChartData As Range
Dim chartIndex As Integer
Dim ChartName As String
chartIndex = ComboBox1.ListIndex
Select Case chartIndex
Case 1
Set ChartData = ActiveSheet.Range("L4:L103")
ChartName = ActiveSheet.Range("A1")
End Select
Application.ScreenUpdating = False
Set MyChart = ActiveSheet.Shapes.AddChart(xlXYScatterLines).Chart
MyChart.SeriesCollection.NewSeries
MyChart.SeriesCollection(1).Name = ChartName
MyChart.SeriesCollection(1).Values = ChartData
MyChart.SeriesCollection(1).XValues = ActiveSheet.Range("J4:J103")
Dim imageName As String
imageName = Application.DefaultFilePath & Application.PathSeparator & "TempChart.gif"
MyChart.Export Filename:=imageName
ActiveSheet.ChartObjects(1).Delete
Application.ScreenUpdating = True
UserForm1.Image1.Picture = LoadPicture(imageName)
End Sub
Private Sub UserForm_Click()
End Sub
Private Sub UserForm_Initialize()
Dim sht As Worksheet, txt As String
For Each sht In ActiveWorkbook.Sheets
Me.ComboBox1.AddItem sht.Name
Next sht
End Sub
The only time you are defining ChartData is if the ComboBox ListIndex is 1. Any other selection and the ChartData object will remain Nothing. Therefore when you try to set your chart values to ChartData you'll receive an error.
It's difficult to tell what you're trying to do with the Ranges. If you want to define the Range on whichever sheet is selected in the ComboBox then you're code would need to look like this:
Dim ws as Worksheet
Set ws = ThisWorkbook.Worksheets(ComboBox1.Text)
And delete your Select block.
All of your code is referencing the ActiveSheet which is probably not what you want, so you would need to replace all references to that with this new variable ws.

Creating checkboxes in userform depending on parameters

I want an user to select on which sheets he wants to create a new line of text. But the number of sheets he is able to select may vary over time and I don't want to hardcode the sheets' name.
Here is an example ("o" represents the checkbox) of what I aim to do:
o 01.2013
o 07.2013
o 01.2014
o 07.2014
I created an userform with an empty frame to put my checkboxes, and added this bit of code to the userform:
Private Tck(10) As MSForms.CheckBox
Private Sub UserForm_Initialize()
Dim ws As Worksheet
Dim i As Long
i = 1
For Each ws In ActiveWorkbook.Worksheets
If Left(ws.Name, 3) = "T2M" Then
Set Tck(i) = Frame1.Controls.Add("Forms.Checkbox.1", "Checkbox" & i)
Tck(i).Caption = Right(ws.Name, 7)
i=i+1
End If
Next
End Sub
But it only adds one checkbox with the last sheet which validates the if test.
I tried to make an offset between the two iterations but I can't modify the position of the Tck(i) using Tck(i).top for example.
I also tried the method from the answer of this question : Adding controls to a frame in an Excel userform with VBA but it dosen't work either.
Your checkboxes are there, you just can't see them because they're overlayed on top of each other. You had the right idea with changing the 'Top' value.
Public Sub addCheckboxes()
Dim ws As Worksheet
Dim i As Integer
Dim tck As MSForms.CheckBox
Dim offset As Integer: offset = 5
For i = 1 To Worksheets.Count
Set ws = Worksheets(i)
Set tck = Frame1.Controls.Add("Forms.Checkbox.1", "Checkbox" & i, True)
tck.Top = offset
offset = offset + 15
Next i
End Sub

Resources