VBA return value from option button - vba

Okay I'm new to VBA and the solution is probably very simple.
I have an Option Button (named Matrix) and if the button is checked I want the global variable rdb to get the value from the Cell (5,2).
This is my attempt:
Public rdb as Integer
Public Sub Matrix_Change()
If Matrix.Value = True Then rdb = Cells(5, 2).Value
End Sub
I noticed that this only works if I switch between two radiobuttons. This is perhaps because I selected "Change". How can I create a sub that only checks if the option button is checked? Simply removing the "_Change" part will lead to an error. Also is it possible to return the value from the Sub instead of using global variables?
Help is much appreciated!

(First Question) Choose the MouseUp Event instead of the Change Event
(Second Question) A Sub is unable to return a value
You can simply Replace Your Code to this:
Public rdb As Integer
Public Sub Matrix__MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If Matrix.Value = True Then rdb = Cells(5, 2).Value
End Sub

Related

Empty pre-filled TextBox on MouseDown/MouseUp only FirstTime

I'm newbie in word-vba (just to let you know that my question could be really stupid).
I would like to clear a textbox only when I click in the textbox the first time.
I've tried For... Next but I wasn't able to comfigure it correctly
Private Sub SWName_Field_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
SWName_Field.Text = ""
End Sub
I would like that the code will work exactly the same way it works but when I put some text and for example the user make a mistake or typo error the second click in the textbox shouldn't clear the text inside.
Thank you for the support
There's no inbuilt activity state identifier in any UserForm control. So you need to use meta data to specify and identify whether or not your mousedown is happening for the first time.
Use Tag property of the control for that.
See the code comments for details.
Private Sub TextBox1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'/ Use the Tag field to determine and store the state of Text Box.
If Len(Me.TextBox1.Tag) < 1 Then
'/ If Mousedown for the very first time then TextBox's tag is empty.
'/ Go ahead, clean the textbox.
'/ And set a text in tag.
Me.TextBox1.Text = ""
Me.TextBox1.Tag = "Text Cleared"
End If
End Sub
You can use a Static local variable to "remember" whether the handler was executed at least once or not:
Private Sub SWName_Field_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Static executed As Boolean
If Not executed Then
SWName_Field.Text = ""
executed = True
End If
End Sub
The state of the Static local is tied to your UserForm instance - the value will be "remembered" for as long as the form instance is alive.
This means, if you're showing the form's default instance, the state won't necessarily be reset. You will want to ensure you get a fresh default form state every time the form is shown, not just the first time - to do this you New up the form:
With New UserForm1
.Show
End With
If you just do UserForm1.Show, then you don't control when the form instance gets created - VBA does.
You'll also want to control when the form instance gets destroyed - you can do that by handling the form's QueryClose event:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = VbQueryClose.vbFormControlMenu Then
Cancel = True ' cancel the destruction of the object
Me.Hide ' hide the instance instead
End If
End Sub
With that, the object will be destroyed when execution reaches End With. Without it, the object will be destroyed if the user clicks the "X" button, and you probably don't want that to happen (especially if you need to access the form's state after it's closed).

Issue setting the picture property of an image on a VBA form

I have 3 pictures on a vba form.
The images are (picture1, picture2, and selectedImage)
The VBA sets either picture1 or picture2 equal to selectedImage. Picture1 and Picture2 initialize to (none), and selectedImageis set to a local bitfile.
Private Sub updatePicture(position As Integer)
'This code works when un-commented out and run
'Picture1.Picture = selectedImage.Picture
'This code does not update the images
If position = 1 Then
Picture1.Picture = selectedImage.Picture
ElseIf position = 2 Then
Picture2.Picture = selectedImage.Picture
End If
End Sub
I debugged and confirmed position = 1, and the line 'Picture1.Picture = selectedImage.Picture' is being run, yet the image is not being updated...
Any help would be welcome. Using excel 2013.
This type of problem is often associated with the fact that a change to an Image picture does not fire an event. Assuming that you're definitely passing a 1 or 2 into the procedure (you should check for sure that you are), there are several ways you could handle the repaint issue:
One would be to add the Repaint method at the bottom of your code, so your procedure would read:
If position = 1 Then
Picture1.Picture = selectedImage.Picture
ElseIf position = 2 Then
Picture2.Picture = selectedImage.Picture
End If
Me.Repaint
However, this will repaint your entire Userform and can cause flicker if you are updating the picture rapidly (eg on a progress monitor or multiple click handling) or have a huge Userform.
The other way would be to create an event and run your new picture through that event. I can't say this from a position of authority, but my impression is that the Event will coerce a repaint and appears only to refresh that part of the Userform where a change is detected, so my experience is that this method is far smoother.
The way you'd do this is very simple. You insert a new Class and suitably name it (I called mine clsPicHandler). The code within that class could be a little as this:
Option Explicit
Public Event PictureChanged(img As MSForms.Image, pic As Object)
Public Sub SetPicture(img As MSForms.Image, pic As Object)
If img Is Nothing Or pic Is Nothing Then Exit Sub
If img.Picture Is pic Then Exit Sub
RaiseEvent PictureChanged(img, pic)
End Sub
The code behind your Userform, then, would trigger and handle the event, like so:
Option Explicit
Private WithEvents mPicHandler As clsPicHandler
Public Sub UpdatePicture(position As Integer)
If position = 1 Then
mPicHandler.SetPicture Picture1, selectedImage.Picture
ElseIf position = 2 Then
mPicHandler.SetPicture Picture2, selectedImage.Picture
End If
End Sub
Private Sub mPicHandler_PictureChanged(img As MSForms.Image, pic As Object)
img.Picture = pic
DoEvents
End Sub
Private Sub UserForm_Initialize()
Set mPicHandler = New clsPicHandler
End Sub

VBA Textbox's change affect second textbox and vice versa

On my form I have more textboxes, but two of them are special. It's textbox with name tbVolume and textbox with name tbWeight.
If I change tbVolume, by other parameters is computed value for tbWeight, but when I added same procedure to tbWeight (to compute value for tbVolume), it creates some kind of cyclically link, because change of volume changes weight, change of weight changes volume, etc...
Does it exist some argument of tbVolume_Changed() / tbWeight_Changed() which can tell to procedure if value is changed by user or by application?
Or do you have another idea how to solve this twin-textbox problem?
Oh.. Finally it was so easy, only two new booleans and everything works fine:
Dim editingVolumeByApp As Boolean
Dim editingWeightByApp As Boolean
Private Sub tbVolume_Change()
If editingVolumeByApp = False Then
'...
editingWeightByApp = True
tbWeight.Value = finalVolume * CDbl(tbMatDensi.Value)
editingWeightByApp = False
'...
End If
End Sub
Private Sub tbWeight_Change()
If editingWeightByApp = False Then
'...
editingVolumeByApp = True
tbVolume.Value = finalVolume * CDbl(tbMatComplCoef.Value)
editingVolumeByApp = False
'...
End If
End Sub
And it works fine :-)
Instead of tbWeight_Change() or tb_Volume_Change() you could use the following:
Private Sub tbWeight_Exit(ByVal Cancel As MSForms.ReturnBoolean)
' do everything you want to do
End Sub
and of course:
Private Sub tbVolume_Exit(ByVal Cancel As MSForms.ReturnBoolean)
' do everything you want to do
End Sub
You change the value of the textbox, exit it via tab or mouse click and the other value of the textbox will change.
If you want a parallel output while writing in the textbox you can use an extra textbox just for displaying the calculated value.

How To Make a Table for Controls (Excel VBA)

I hope you are enjoying your weekend!
I am here to ask if there is a way to initialize a table or list layout inside of the frame of a userform. And, if this is possible, whether or not I can place controls (text boxes and labels) into the cells instead of strings of text.
Thank you in advance for your answers/comments.
*Edit: Follow up question. Assuming the above is possible in Excel VBA, can I also set the table (only one column) or list to have its dimensions based on the control's width and height?
You can embed a Microsoft Office Spreadsheet. Go to tool box additional controls.
You can access ot just like you do an Excel WorkSheet.
Spreadsheet1.Range("A1")
You can also use Private WithEvents to hook it's events. Here I did it in the Userform, however, I could have do it from a class module if I wanted.
Private WithEvents MySpreadsheet1 As OWC11.Spreadsheet
Option Explicit
Private WithEvents MySpreadsheet1 As OWC11.Spreadsheet
Private Sub UserForm_Initialize()
Set MySpreadsheet1 = Spreadsheet1
End Sub
Private Sub MySpreadsheet1_BeforeContextMenu(ByVal x As Long, ByVal y As Long, ByVal Menu As OWC11.ByRef, ByVal Cancel As OWC11.ByRef)
End Sub
Private Sub Spreadsheet1_BeforeContextMenu(ByVal x As Long, ByVal y As Long, ByVal Menu As OWC11.ByRef, ByVal Cancel As OWC11.ByRef)
End Sub
It's not fully featured but you can do alot with it.
How To Use the Spreadsheet Web Component with Visual Basic
You can hide the columns and rows, but it's too slow to be practical.
Spreadsheet1.Columns("E:ZZZ").EntireColumn.Hidden = True
Spreadsheet1.Rows("10:262144").EntireRow.Hidden = True

How to Make Text Box Control Resizable in VBA

I am trying to modify an add-on for excel which takes data from each cell of the worksheet and puts it into text boxes where the information can more readily be read and modified.
Since some cells contain a great deal of text (and the text boxes are by default only large enough for one line), I am attempting to make the text boxes adjustable so that the user is able to see all the text in the cell.
The below link is a picture so you know exactly what I mean:
http://www.jibberjobber.com/blog/wp-content/chrome_resize_text_boxes.png
Please understand that I do not want the form to simply be enlarged to a specific size, as that is easy to accomplish, but I would prefer to allow the user to choose the size that best fits the amount of text, size, and font.
Thank you in advance for your answers!
A different approach. Change in run time the textbox settings. In this case
Private Sub TextBox2_Enter()
showTextbox2Text
End Sub
Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
returnOriginalTextbox2Text
End Sub
Sub showTextbox2Text()
TextBox3.Visible = False
TextBox2.MultiLine = True
TextBox2.Height = 75 'make some calculation to adapt to your with and text in textbox
End Sub
Sub returnOriginalTextbox2Text()
TextBox3.Visible = Visible 'original setting
TextBox2.MultiLine = False 'original setting
TextBox2.Height = 25 'original setting
End Sub
Before enter TextBox2
After enter Textbox2 ... in exit will return to the original
You want the user to see and edit the information in a better way?
You could make a trick ... that is open a new form with the information in the original text box now in a bigger textbox. This form could be generic to be used in all text box and could be called by a button.
following your original question, i.e.:
"...I would prefer to allow the user to choose the size that best fits the amount of text, size, and font"
you can place the following code in your userform code pane:
Option Explicit
Private mouseLeft As Single, mouseTop As Single
Private Sub TextBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) '<~~ change "TextBox1" to whatever the actual name of your textbox
If Button = 1 Then
mouseLeft = X
mouseTop = Y
End If
End Sub
Private Sub TextBox1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single) '<~~ change "TextBox1" to whatever the actual name of your textbox
If Button = 1 Then
With Me.TextBox1 '<~~ change "TextBox1" to whatever the actual name of your textbox
.Width = .Width + X - mouseLeft
.Height = .Height + Y - mouseTop
End With
mouseLeft = X
mouseTop = Y
End If
End Sub
and the user can drag textbox borders to desired sizes