Setting the minimum width of a ComboBox & AutoSize - excel

I was wondering if this is possible to do or not. I am pretty sure it’s not, but wanted to see if it was and someone else might know how. I am using Excel 2010 and everything is being done with VBA. What I would like to do is set a ComboBox with a minimum width size and then AutoSize if typed data becomes longer than the length of the ComboBox.
OK, so let me clarify some misconceptions or questions that I am going to get asked about, such as why I would want to allow users to type in a ComboBox. On another sheet, apart from the sheet that the ComboBox is on, I have a list of items. As items are typed in here the ComboBox is populated with the new item, I also have it sorting the list in alphabetical order and it spell checks them too, as they are being added.
I then have the code to also check for the longest length of text in each cell and the ComboBox will size to the longest length of text within its list, so it can fully be read in the dropdown.
I also want users to be able to type in the ComboBox for items that are not in the list already. The list is for just the most common items used, but often other miscellaneous stuff needs to be entered. I don’t want the miscellaneous stuff added to the list within the ComboBox, so I just want the user to be able to type in data within the ComboBox, but if it is used a lot they can add it to the list on the other sheet.
In case someone is wondering, I do have spellcheck working for the ComboBox when users type data in. All I did was make the cell that the ComboBox is over equal to the text in the ComboBox when the ComboBox is deactivated (LostFocus), then I spellcheck that cell, followed by making the ComboBox equal to the cell that was just spellchecked.
Anyway, as already mentioned I do have the ComboBox’s width set to the longest item in the list using code. Is there a way that I can somehow keep the ComboBox’s minimum width set to this size, but then the width will increase when the user is typing data in that becomes longer than what the box is currently set to? I am guessing this would be easy to do if I was to adjust it after the user finished typing (when the ComboBox LostFocus), but is it possible to do this while they are typing? Setting the AutoSize will not work, because it will ignore the size of the longest item in the list, and shrink to almost nothing, making it impossible to see the items in the list. The other issue with AutoSize is that you can’t read items in the list as you are typing. Like when you are typing it will prefill items from the list as you are typing, but the prefilled items can’t be read when using AutoSize.

I guess it is possible to do, I just figured it out. The iLength is what determines the default minimum width size should be, which is slightly larger than the size of a column in a different sheet where the ComboBox is pulling its data from. I just did some basic calculations to figure that the length (character count) of text being typed in the notes field is about 4.5 times smaller than the default length. Of course, the 4.5 would change if I used a different sized font. If the typed text (based on the calculation) becomes greater than the default size, I set the ComboBox to AutoSize, otherwise AutoSize was set to False. Then when I cleared the data from the field I just have the code in the clear button to reset the ComboBox back to the default size and to set AutoSize to False. This works perfectly.
Private Sub cboNotes_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Dim iLength As Integer
iLength = Sheets("Notes").Range("A1").Columns.Width + 20
If Len(cboNotes.Value) * 4.5 < iLength Then
cboNotes.Width = Sheets("Notes").Range("A1").Columns.Width + 20
cboNotes.AutoSize = False
Exit Sub
Else
cboNotes.AutoSize = True
Exit Sub
End If
End Sub

Related

VBA How to determine which row was selected in a Listbox?

How to determine, which row was selected in a ListBox? I'm asking here because, all I have found so far, requires to loop through all rows to check if was selected or not, but I was wondering if something simple exists, as I'm using mode MultiSelect 0-fmMultiSelectSingle only an integer is expected...
If you filled the list box using the ListFillRange property, or otherwise used a contiguous worksheet range, the 3rd item in the listbox will be from the row of the 3rd cell in the range.
R = Range(ListFillRange).Rows([Listindex]).Row
where [Listindex] is the ListIndex of the selected list box item.
If this easy way isn't available, f.i. because the list was created using a filter, the thing to do is to create a multicolumn list box with an extra, hidden, column and record the row number there at the time of list creation.
You would need to loop only if the items in the list box were not extracted from the worksheet in the first place, and this is the reason why doing so wouldn't be the best solution for creating the list box's list.

ListBox Form Control Scrolling

I've been doing a ton of research and I'm finally giving in and hoping the community can help. I have a FORM CONTROL list box, not an active x. I'm intentionally using form control for a variety of reasons that are not necessarily important (unless you can guide me how to 100% ensure activeX controls don't resize themselves on workbook open). I cannot, for the life of me, figure out how to get the form control list box to scroll to the selected value and put it in view. Here is what I have:
ActiveSheet.ListBoxes("List Box 13").Selected = 100
The list has 1000 values in it to be selected. When this runs, #100 is selected, but is not in view. The list box does not move.
How can I get the scrolling to occur so the selected value is at the top?
ActiveX would be:
.TopIndex
But that is not available for form controls.
Scroll to given listbox index to be displayed on top of visible list
I cannot, for the life of me, figure out how to get the form control list box to scroll to the selected value and put it in view.
Seems that actually there's no standard method (leaving aside API calls) to control the visibility of the listbox interior display for a form control list box as opposed to a Userform's ActiveX control list box.
Additional hints
For the sake of completeness (and due to comment) I demonstrate how to scroll into view in a Userform's listbox by combining both navigation properties - i.e. by setting .ListIndex as well as .TopIndex together with a defined index value :-), e.g. via a procedure as follows:
Example calls
ScrollTo 100 ' attention: zerobased
or
ScrollTo ActiveSheet.ListBoxes("List Box 13").Selected
Helper procedure
... sets the current ListIndex to e.g. 100 AND defines it as .TopIndex.
(Side note: of course targets at the very list end could be displayed even below .TopIndex depending on the actual .ListCount)
Private Sub ScrollTo(ByVal idx&)
' Purpose: Scroll to given target index to be displayed on top of visible list
' Site: https://stackoverflow.com/questions/56813550/listbox-form-control-scrolling
' Author: https://stackoverflow.com/users/6460297/t-m
Me.ListBox1.TopIndex = idx
Me.ListBox1.ListIndex = idx
End Sub

Generate comboboxes depending on number inserted in first combobox

I'm doing an userform where in one of the fields (lets say its combobox1) the user is asked for the number of failures, and for each failure he has to put the type of failure, number of part and in another field the type of rework (3 fields to fill for each failure). And what I would like to know if that if it's possible to generate comboboxes depending on the number of failures made. For example: if the user puts 3 in the field of failures, 9 comboboxes should appear and so on.
I also think that maybe another way would be to have the standards 3 comboboxes and clear the fields each time the user press a button and a counter appears indicating which failure description he is filling, but I would also like to know how this could integrate into the whole userform, which already has a "submit" button.
Maybe there could be another reasoning for this, and I would greatly appreciate any help.
I don't really have much experience using dynamically created tabstrips, but they may be helpful with creating the layout you're describing. I would recommended in the base userform, include a tabstrip with a single tab and the 3 comboboxes/textboxes that are needed for a single failure. (You could keep it invisible until after "combobox1" has a value, if desired) Then use the number from the combobox to dynamically create the additional tabs on the tabstrip:
Private Sub ComboBox_Change()
'To remove previous tabs if combobox changed
For i = 1 To TabStrip1.Tabs.Count - 1
TabStrip1.Tabs.Remove(i)
Next i
'Adding additional tabs to tabstrip
For i = 1 To ComboBox.Value - 1
TabStrip1.Tabs.Add
Next i
End Sub
The tab currently selected can be identified by using the TabStrip1.Value property. I think the change event is queued by the TabStrip1.Value changing.
You will have to manually clear out any values when the tab strip changes (or fill back in values they previously filled out but want to view again).
However, since you'd be determining which tab you're on by "index" (the .value property) you could create a 2d array (redim it to correct rows/columns based off combobox1's value) and use the tab "index" to store combobox values and retrieve existing values for when the user switches back to an existing tab.
And maybe consider "locking" the combobox1 so the value can't be changed by accident. This could be accomplished by having a variable initialized to, maybe -1, which gets set to the combobox value after they've started adding infor to the incidents. Or don't remove any tabstrip tabs, only add if the number is greater than the existing count. (If you want them to put in whatever value they'd like, maybe consider using a textbox?)

Scroll then lock row

I have a worksheet that has header data in the first few rows, followed by a table with column headers. The header data includes parameters that are used to calculate values in the table.
What I want is to allow the user to scroll the sheet so that the header data is no longer visible but then freeze the table heading row when it becomes the first row. Then if they need to change a parameter, they can scroll back up and the top few rows come back into view.
I thought this was fairly easy to do but I can't remember how to do it. The only option I can find is the Freeze Panes option, but that freezes everything and I only want it to freeze when the header row is at the top.
Is this even possible?
Edited - To add a little more clarification, the freeze panes option freezes everything above the selected row (unless I have missed it), which is not what I am looking for. I want the sheet to behave similar to a website where there may be an ad banner at the top, followed by a navigation bar/logo/etc., then the content. As you scroll down, the ad banner moves out of view but when the nav bar is at the top, it stops and remains in view while the content continues to scroll.
Let's say I have the first 5 rows that have cells to capture input values. Then row 6 is a table heading and rows 7-100 are the table data. I want the user to be able to hit the scroll down button 5 times to move past the input values. Then I want row 6 to freeze at the top so that as the user continues scrolling, the table heading is visible. Conversely, when the user scrolls up, row 6 remains at the top until the user gets to row 7, then if they continue scrolling, the input values move into view.
Excel does something similar if you use the "format as table" function and indicate that the selection has a header row. Then when scrolling, the column headers will replace the "A", "B", "C", etc. address labels. This won't work directly for me because the table structure is a little more complex.
As far as i understood you want to keep visible a row or column thats not first. Which is kinda exotic.
If you want to hide configureables to save visual space and keep headers at all times:
Simply freeze as many rows/columns as you need for both your configs and headers. And then HIDE the rows/columns you won't want always in view.
You can even have a simple button that does this hiding and unhiding via one click:
Sub transaction1()
Rows("10:50").Hidden = Not Rows("10:50").Hidden
End Sub
As for the freeze panes, in case someone doesn't know you can freeze as many as you want. If you want to freeze columns A and B and rows 1 and 2 simply click on C3 and then use the freeze function. If you want to freeze 10 rows only - click on A11 and then use the freeze.
Though i usually just offload my service space to elsewhere and quickly jump to and from it with =HYPERLINK()
In any event your required result isn't any more convenient than the other ways you can achieve navigational ease. So if I've scrolled to row 14000 if i want to scroll back to the beginning to view my settings i still have to go through 14k rows. Having an always frozen settings area as well as headers is quicker to navigate. And if your settings area takes that much space either move it and create more compact navigations for it or simply hide/show it on demand.
There is no doubt you can have even more exotic ways to achieve the effect, but is it mandatory to do it that way?
Use this in the worksheet's code page (right-click worksheet name tab, View Code).
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim iVISROWS As Long
Dim iHDRROWS As Long
iVISROWS = 5
iHDRROWS = 3
Cells(1, 1).Resize(iHDRROWS, 1).EntireRow.Hidden = _
Target(Target.Rows.Count).Row > iVISROWS
End Sub
Optionally, take out the declaration and assignment of iVISROWS and iHDRROWS and out the following into the declaration area (top) of a module code sheet.
Option Explicit
Public Const iVISROWS As Long = 5
Public Const iHDRROWS As Long = 3
Play with the number of header rows (iHDRROWS) and the bottom of the current selection that triggers hiding the header rows (iVISROWS) untilo you get the results you are looking for.
I had the same problem and have much less tech savvy to do all the coding above.
My workaround is very simple.
Insert a new row right at the top of the sheet.
Copy the headings of the table to the new row 1 and then freeze the top row as normal.
As you scroll the top dummy row stays above your table and the rest disapears.
Your original headings still stay in place for filtering as needed if you scroll up.

Clear Selections of a Combobox

I have a combobox with values that when selected, lead to other questions.
I have a button that I want to be an "Up one level" button that clears all the following questions. It should reset the display of of the combobox to nothing, like before any options were selected, so the user can make a selection.
I tried setting the Value = 0, the ListIndex = -1.
I don't want to use "Clear" because I want to preserve the values in the combobox.
I looked through the properties of a combobox and I can't pick out which one will do what I want.
Listbox.Value=null
should do the trick.
If you use: ComboBox1.ListIndex = -1 with no list items then there will be no effect. This is a problem if you're dynamically loading the items. Use: ComboBox1.Value = Null to clear the value as mentioned above.
I faced the same problem and possibly we have the same scenario.
I understand that you don’t want to run clear method and make the current listed items vanish, but just make the combo having no value.
In case just before the attempt of making combo value null or blank string ("") or ListIndex=-1 you had repopulated the combo with new set of items this might happen. Before repopulating the combo with new items, you should call the clear method and then repopulate the combo with the new items and after that set the value to null or blank string ("") value.

Resources