How To Make a Table for Controls (Excel VBA) - 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

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).

Detect click on textbox in form

I want a certain function to be run every time someone clicks on a textbox in my form. So far I have managed to detect when it gets focus and when it is doubleclicked, using the following two eventhandlers, but I am unsure about how to catch when it is clicked once while it already has focus.
Does anyone here have any experience with catching such an event? I don't seem to find any obvious suspects in the dropdown-menus of the VBA editor.
Private Sub tbxTil_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Me.tbxTil = format(oppdater_dato(CDate(Me.tbxTil)), "dd.mm.yy", vbMonday, vbFirstFourDays)
End Sub
Private Sub tbxTil_Enter()
Me.tbxTil = format(oppdater_dato(CDate(Me.tbxTil)), "dd.mm.yy", vbMonday, vbFirstFourDays)
End Sub
You can use the Mouse events, something like this:
Private Sub tbxTil_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
MsgBox "Click"
End Sub

VBA return value from option button

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

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

Datagridview (on usercontrol) painted cell revert to defaultstyle

In my program (Winforms), i use usercontrols as pages. I do this in the following way:
I have a panel on my Form1 in which i load usercontrols, on these usercontrols are my actual controls (buttons, labels, checkboxes etc). So actually i'm using the user controls as "sub" pages in my form.
The usercontrols are declared at the start of runtime, so they are "live" when i load them into the panel. This has allways worked fine, untill i ran into a problem yesterday.
Yesterday I used a datagridview on one of those usercontrols and during the ParentChanged of this control i call a Sub which changes the backcollor of this data grid view. (The sub itself is a public sub which is located in a module)
Like this:
Private Sub Init_ParentChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.ParentChanged
GetRecipe(RecipeDGV, "Bla")
End Sub
Public Sub GetRecipe(ByVal Data As DataGridView, ByVal RecipeID As String)
For r As Integer = 0 To Recipe_Mem.Rows.Count - 1
For c As Integer = 0 To Recipe_Mem.Columns.Count - 1
Data(c, r).Style.BackColor = getPresetColorByID(CInt(Data(c, r).Value))
Data(c, r).ToolTipText = getPresetNameByID(CInt(Data(c, r).Value))
NEXT
NEXT
End Sub
When i run my program, i can see that my dgv gets the data from the database (which happens in the same Sub). But there is no color change in the cells.
Now, something i've noticed is that when i add a button to the user control, and use the click event of this button to call the same sub for the coloring, it does work).
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
GetRecipe(RecipeDGV, "Bla")
End Sub
Any idea why this works on a button click event, but it doesn't in the usercontrol parent changed event? it looks like during the parent changed event there is some kind of repaint event of the dgv. how do i solve this?
Have you tried wrapping the gridview in an ajax control ( with triggers on the ParentChanged event?
I'm a little puzzled by the "RecipeID" argument being passed as it isn't used.