Multiple instances of a single Userform / the need for pointers - vba

I have created a Userform that lets the user pick a worksheet from a list of open worksheets. I need this Userform in various places of my macro, for various purposes; for example, to specify the worksheet containing "sales" data, and to specify the worksheet containing "stock" data. The objects wsSales and wsStock should point to the appropriate worksheets, so that my macro can later work on these.
How can I give each instance of my Userform a different behavior? One instance should set wsSales to the user-selected worksheet, the other instance should set wsStock to the user-selected worksheet.
I have thought about putting several "OK" buttons on my Useform, and making only one visible per instance. Each OK button would have different code. But that's not very elegant, because I would have to put as much "OK" buttons as there are possible uses for my Userform and it would become quite a mess in more complex situations. So, ideally, I would use a property of my Userform as a pointer to either wsSales or wsStock, but I've read that pointers don't exist in VBA. Then, what's the best way to have two instances of a Userform behave differently?

Are you actually declaring variables as instances of the userform? If not, you should. You might want to look at this post: yoursumbuddy.com/a-flexible-vba-chooser-form.

I am using a kind of common approach by means one can practically use any kind of information to create and uniquely identify one of multiple instances of a UserForm - which doesn't even require a variable for an instance. See https://warbe-maker.github.io/vba/common/2021/11/09/UserForm-Instances.html.

Related

View names of controls in worksheet

So I feel a little foolish asking this question. I have spent plenty of time searching and only found a crude work-around. I have given this due diligence before posting.
For controls placed within a worksheet I cannot pull up the properties or even view the name to reference in code. The work-around I came across is if you right-click on the control (listbox in this case) and choose assign macro. It will suggest a macro name with the control name (e.g. ListBox13_change). In the code I refer to this listbox as Sheet2.ListBox13, but getting an error message for missing object.
With ActiveX controls or controls within a userform I can view the properties. I don't know why I am having trouble with this case.
Any guidance is much appreciated.
You can get the real name of the form control from the Immediate Window in the VBE by executing this line:
?Sheet2.Shapes(1).Name
Form controls are actually shapes in the object model.
The above assumes you have no other shapes on the worksheet.
Of course you can also see the name (and edit it) from the Name Box if the control is selected.
Once you have the name you can use it in code like so:
MsgBox Sheet2.Shapes("List Box 1").Top

Why does Delete works for ActiveWindow but not ActiveWorkbook?

I don't know why this doesn't work...
Sheets("SampleSheet").Select
ActiveWorkbook.SelectedSheets.Delete
But this works...
Sheets("SampleSheet").Select
ActiveWindow.SelectedSheets.Delete
In both situations, the sheet "SampleSheet" was selected, right?
As GSerg commented, it doesn't work because there is no ActiveWorkbook.SelectedSheets property. Someone on the Excel team wanted to make a property that returned an array of all the selected sheets. But where to put it? They could have put it at the Workbook level, but what if the user had two windows open for the same workbook? They could have different sheets selected in each window. Which window to use? So they decided to make it a property of the Window object instead.
A fine idea, maybe, but they could have put it in both places. Both the Workbook and Window object have an ActiveSheet property. When you reference ActiveWorkbook.ActiveSheet it appears to be the same as ActiveWorkbook.Windows(1).ActiveSheet and Windows(1) is always the active window. They could have done the same thing for SelectedSheets and I'd argue that they should have.
In the meantime, you can use ActiveWorkbook.Windows(1).SelectedSheets to overcome the Excel team's lack of consistency.

Using FarPoint Spreads in User Controls

i am using FarPoint Spreads in a Windows Forms Application.
To show a spread on several Forms, I created a user control which contains one of my spreads and manages the representation.
However the ActiveSheet Property of the Spread seems to always return the first sheet when my user control is not focused - no matter which sheet is actually selected.
Since the Spread still has the "correct" Sheet selected when the user control is out of focus, the information which was the last active spread has to be accessible somehow. Do you have any ideas how i can get (and modify) the active sheet?
Thank you!
Turns out i called the constructor of the User Control multiple times on accident and thus was using the wrong references. The Properties work like desired - i was just showing the wrong control on my interface.

referring to different textboxes on each iteration

I'm making a Visual Basic program. I have a page where I want to be able to scale anywhere from 1 set of two textboxes and a label all the way up to 30. I'd really like to keep the display as simple as possible, So I'm trying to make buttons like add batch and remove batch that lets me adjust the boxes shown from 1 to 30.
I know that I can use a case statement or a if statement or even making a function that does one of those for me so I don't clutter up the main code, but that just seems so klunky. Any suggestions on a way that I can refer to one set at one time and another set at one time?
I ended up creating a class that and passed references ByRef to the class. Created methods of Show*( and Hide() that show and hide all objects that were passed to the class (just changing the Visible property)
Created one object of my new class for each batch set. Made an array with those objects in it, now I can call BatchGroups(3).Show() and iterate through my batches.
Still a bit of setup in my FormLoad event, but BatchGroup(txtBat1,txtBatQty1,lblBat1) and filling an array with those objects allows me to iterate through my batches whether I am adding, removing, adding 5 at a time, removing all but one... take your pick.
Could probably build an array with groupboxes as easily to refer to the whole group at once, but groupboxes would have looked somewhat tacky in this situation, I preferred to create my own object oriented groups.

Create a shared copy and paste menu for my grids

I have 20 or so grids in my application suite. I'd like to create a global copy/paste context menu which I can bind to every single grid rather than code in each form.
I am unsure what is the best way to achieve this, I have started to create a class with my menu in it, but get stuck at the point of adding the actual menu options. For example I know I'll need to call a "copy" event, but I also know I'll need to tell it what I am copying, and I cannot see how that is done in vb.net when you can only add the address of a method minus parameters.
e.g.
.MenuItems.Add("Copy Cell", New System.EventHandler(AddressOf CopyCell))
Obviously I want "CopyCell" to only be coded in one place as well, rather than repeated in each form. I will always be copying the same object (SelectedCellCollection).
I am not sure how to make the menu have an event with parameters, or how to make it "know" that I want to always copy the selected items. I'm aware that I'd have to do some coding in the form but just trying to work out the way to minimize it.
I have created my own context menu class (via inheritance) with specific copy and paste functionality / options tailored to the grid I am using. It works fine and only needs one line of code per form/grid to activate.