Excel 2016 ComboBox Date Display versus Number - excel

This seems to be a simplistic task to get the actual date to display in the combobox versus 43466 (a number). The code that everyone seems to be using is the following with
.Text:
Private Sub ComboBox20_Change()
ComboBox20.Text = format(ComboBox20.Text, "dd/mm/yyyy")
End Sub
OR . Value
Private Sub ComboBox20_Change()
ComboBox20.Value = format(ComboBox20.Value, "dd/mm/yyyy")
End Sub
I have even tried with .text and .value. Either one keeps giving me the following error:
Compile Error:
Wrong number of arguments or invalid property assignment
Any thoughts on what I must be missing, having a brain meltdown on the most mundane and seemingly easy task.

Problem approach
The problem seems to be when you are attempting to change the value in the combobox, is there a value to begin with? If it is empty, it is taking the default version of the date.
Solution approach
Try to set the value before it goes into the Change event.
Sample code and demonstration
Private Sub ComboBox1_Change()
ComboBox1.Value = Format(ComboBox1.Value, "dd/mm/yyyy")
End Sub
Private Sub UserForm_Activate()
Dim CounterDate As Long
Dim TxtDate As String
For CounterDate = 1 To 2
TxtDate = DateAdd("d", CounterDate, Now)
ComboBox1.AddItem (TxtDate)
ComboBox1.Value = TxtDate
Next CounterDate
End Sub
Further comments
As you may see as soon as you change it, it enters again the "Change" event, you may turn off the events as soon as you enter the cycle and then turn them on again if it is causing erratic behaviour on your pc -sometimes it does-.

Related

Excel global variable reseted to empty when navigating through workbooks

I encounter a weird problem that I believe is related to Excel behavior, rather than to my code.
I have a global variable named "numEtape", which is an integer. My code consists in several steps where the user has to type data on a sheet, then press a button which saves the data in an array and increments the "numEtape", before going to the next step.
The code (simplified) looks like this :
Dim numEtape As Integer
Sub AjoutEssai()
numEtape = 2
UFPreAjoutInfos.Show 'Unrelated Userform that asks user for more informations, but doesn't modify "numEtape" or call any other macro
Call InterfaceFiller
End Sub
Sub InterfaceFiller()
Dim rangedubtn As Range
Dim btnPrecedent As Button
Select Case numEtape
Case 2
'Change value of some cells
Case 3
'Change value of some cells
Case 4
'Change value of some cells
Case Is >= 5
'Change value of some cells
Case Else
Debug.Print "Error"
End Select
Set rangedubtn = Sheets("Interface").Range("M3")
Set btnPrecedent = Sheets("Interface").Buttons.Add(rangedubtn.Left, rangedubtn.Top,rangedubtn.Width, rangedubtn.Height)
With btnPrecedent
.OnAction = "mSuivant"
.Caption = "Suivant"
.Name = "btnSuivant"
End With
End Sub
Sub mSuivant()
numEtape = numEtape + 1
Call InterfaceFiller
End Sub
I don't think the code itself is important, what I can expect from it, since I first call AjoutEssai(), is for numEtape to always be greater than 2.
However, when during the steps the user opens and close other excel/office files (that don't have any vba code/macros in it), excel seems to empty numEtape, which makes the Select Case go to the Case Else.
When does excel remove global variables from memory, and is there a way to prevent this behavior from happening?
Public numEtape As Long
A viable option is to use the word public like public numEtape As Long.
Then the variable will be saving its value for as long as the Excel workbook is opened. In older versions of VBA the word was Global (What is the difference between Dim, Global, Public, and Private as Modular Field Access Modifiers?)
Dim numEtape As Long
For using Dim outside of Sub or Function, the variable will be emptied, after the code is over. Take this snippet only:
Dim numEtape As Long
Sub MainTest()
numEtape = 23
End Sub
Once you run it and you hit End Sub the variable would be emptied as well. Check after running the MainTest():
Sub PrintingVariable()
Debug.Print numEtape
End Sub
If you want to save the value, there are 2 basic ways that work:
Write the value in an excel cell
Write the value in a database

Format of value in ComboBox is not showing correctly

So I have a ComboBox with a list of times on it, the ComboBox obtains the values from a sheet in the workbook and uses RowSource to put them on the ComboBox. (These cells are formatted as hh:mm)
Originally the ComboBox would display the values in the correct format but then when selecting one of these values it would show the selected time as a number rather than a time
For Example, 9:00 would show as 9:00 on the list of times but when selected would convert it to 0.375
To solve this issue I used the following code
Private Sub ComboBox5_Change()
ComboBox5.Value = VBA.Format$(ComboBox5.Value, "hh:mm")
End Sub
So now 9:00 is shown this way
This works perfectly for all of the times that I have on my list except for 12:00, when I select 12:00 it shows an error of
Does anybody know why this is only giving me an error when I select 12:00 as the time?
Try, please the next approach. It adds a small value (equivalent of a second), in case of 0.5...
Private Sub ComboBox5_Change()
Me.ComboBox2.Value = Format(IIf(Me.ComboBox5.Value = "0.5", _
"0.500011574074074", Me.ComboBox5.Value), "hh:mm")
End Sub
If you still have a problem, this can only be the result of the second time Change event being triggered by event itself code.
Since Application.EnableEvents = False does not work for form controls, we must build our own way of making the event to be triggered only once:
Create a Private variable on top of the form module:
Private NoEvents As Boolean
Adapt the Change event in the next way:
Private Sub ComboBox5_Change()
If Not NoEvents Then
NoEvents = True
Me.ComboBox5.Value = Format(IIf(Me.ComboBox5.Value = "0.5", _
"0.500011574074074", Me.ComboBox5.Value), "hh:mm")
End If
End Sub
Make the boolean variable false in an event being triggered after the Change one:
Private Sub ComboBox5_Click()
NoEvents = False
End Sub

Userform initialize without rewriting data in the cell

I have been wondering about this one for a while now.
Let's say I have a formula in A1, Worksheet("Main")
=IF(B2="English";"Good morning";"Guten Morgan")
Then I have userform with code:
Private Sub TextBox1_Change()
ThisWorkbook.Worksheets("Main").Range("A1").Value = Me.TextBox1.Text
End Sub
Private Sub UserForm_Initialize()
Me.TextBox1.Text = ThisWorkbook.Worksheets("Main").Range("A1").Value
End Sub
How can I make it work so, that if I don't input anything into textbox, it will keep displaying functions result. If I will start to type text into textbox it will input my typed text to A1. Now if I open the userform it will overwrite A1 with the text in textbox and there will be no formula anymore. So if I change language in B2 result will no longer be interfaced into textbox.
Can be also some other approach with VBA. Everything is acceptable as long as logic will work.
I have tried to use textbox properly, something like linkedsource or similar, but it is crashing excel workbook sometimes. That's why I am trying to avoid it.
EDIT:
Thank you for suggestions! I have tried to implement this somehow but still don't get it. I am creating variable where I want to store result from ThisWorkbook.Worksheets("Other Data").Range("L49").Value then I would like to use it in Userform Me.TextBox14.Text to be displayed. Then once it is changed in Me.TextBox14.Text and Enter button has been pressed it should change also in ThisWorkbook.Worksheets("Other Data").Range("L49").Value.
Here is my current code I am trying to play with:
Private ProjectClass As String
Private Sub TextBox14_Enter()
ThisWorkbook.Worksheets("Other Data").Range("L49").Value = ProjectClass
End Sub
Private Sub UserForm_Initialize()
Me.TextBox14.Text = ProjectClass
End Sub
The TextBox.Enter event isn't fired when the user presses Enter, but when the control is entered - that is, when it gets the focus and a caret/cursor starts blinking inside it. You'll want to update the backing variable when the value is modified:
Private Sub TextBox14_Enter()
'runs when the control gets focus
End Sub
Private Sub TextBox14_Exit()
'runs when the control loses focus
End Sub
Private Sub TextBox14_Change()
'runs whenever the value changes (real-time)
End Sub
So in this case I'd go with the TextBox.Change event handler, and make it update the variable (not the worksheet):
Private ProjectClass As String
Private Sub TextBox14_Change()
ProjectClass = TextBox14.Text
End Sub
Now the problem is that the ProjectClass value needs to be accessible from outside the form, so that the caller can set an initial value. One way to do this could be to expose it as a property - one property (get+let) for each field you want to seed a value for:
Public Property Get ProjClass() As String
ProjClass = ProjectClass
End Property
Public Property Let ProjClass(ByVal value As String)
ProjectClass = value
ApplyModelProperties
End Property
Private Sub ApplyModelProperties()
TextBox14.Text = ProjectClass
'...
End Sub
Now from outside the form, at the call site (the code that's showing this dialog), you can seed the value from the worksheet, and the form never needs to know or care that a worksheet was involved:
With New UserForm1
.ProjClass = ThisWorkbook.Worksheets("Other Data").Range("L49").Value
.Show
MsgBox .ProjClass
End With
Note that because the value is exposed as a property, the calling code doesn't need to know about TextBox14 anymore.

Make judgement and give reminder based on date (failed)

I am trying to judge whether today's date is later than any date specified in a column of a worksheet everytime the workbook is opened to decide whether will give user a reminder. I use debug.print to make sure the condition I set was correct but there was no reminder popped out everytime I open the file. Could anyone point out where did I make the mistake? Thanks.
I used cdbl to convert date to double and compare between today and the date in the column. If anyone of them is earlier than today it will give user a reminder.
Private Sub UserForm_Initialize()
Dim i As Integer
Dim cnt As Integer
Count = 0
With ThisWorkbook.Worksheets("Gun Inventory")
For i = 2 To .Cells(Rows.Count, "A").End(xlUp).row
If Int(CDbl(Date)) > Int(CDbl(.Cells(i, "J").Value)) Or Int(CDbl(Date)) = Int(CDbl(.Cells(i, "J").Value)) Then
.Cells(i, "I") = "Needs Test"
Count = Count + 1
Else: Exit Sub
End If
Next i
If Count <> 0 Then MsgBox "You have guns needs check ASAP. Please review 'gun inventory' tab to see which gun it is."
End With
End Sub
I expect there should be a reminder but there is nothing. Not even an error, which is weird.
If you want to execute that portion of code when the workbook is opened you should use:
Sub Auto_Open()
Insert code here
End Sub
Or use Workbook_Open() but you will have to add it in ThisWorkbook class.

Events not triggering in MonthView

So, I'm kind of an amateur at VBA.
I'm doing an userform for many users to use at my company.
I need the user to pick a Date.
First, I tried with DTPicker, but that didn't work on the other computer I tried, so my collegue suggested I used a MonthView instead.
I put it in the form, dropping it from the Toolbox, and used this simple code:
Private Sub UserForm_Initialize()
MonthView1.Value = Date
End Sub
Private Sub cmdClose_Click()
Unload Me
End Sub
Private Sub MonthView1_DateClick(ByVal DateClicked As Date)
On Error Resume Next
Dim cell As Object
For Each cell In Selection.Cells
cell.Value = DateClicked
Next cell
Unload Me
End Sub
Worked perfectly.
Then I tried to open the file in another computer and got the 'some objects are not available, blah blah' message. The calendar didn't show up even though I tried registering the OCX file and stuff, and I even could put a new MonthView calendar in the form, but the "existing" one didn't load.
Sooo, I tried adding the object with code, to try and avoid this, I used this code:
Private Sub UserForm_Initialize()
Dim PruebaCal As Object
Set PruebaCal = Controls.Add("MSComCtl2.MonthView.2", "PruebaCal")
PruebaCal.Value = Date
End Sub
Private Sub cmdClose_Click()
Unload Me
End Sub
Private Sub PruebaCal_DateClick(ByVal DateClicked As Date)
On Error Resume Next
Dim cell As Object
For Each cell In Selection.Cells
cell.Value = DateClicked
Next cell
Unload Me
End Sub
This worked for the 'some objects are not available' problem, it loaded perfectly in both computers, but the Click event is not working and I have no idea how to fix that, maybe when adding controls with code the triggering events are different? I don't know.

Resources