Access remove line break in string, program tells it's NULL - ms-access

I have code that does something then you press enter in textfield, problem is when you use Ctrl+Enter, i can capture that event but access tells me in next line that that field is apparently NULL
Private Sub Text5_KeyPress(KeyAscii As Integer)
If KeyAscii = vbKeyReturn Or KeyAscii = 10 Then
If Len(Me.Text5) = 0 Then Exit Sub
If Val(Right(Me.Text5, 1)) > 2 Then Me.Text5 = Left(Me.Text5, Len(Me.Text5) - 1) & "0"
So 'Len' works fine, but the 'Right' function gives out 'Invalid use of null', when i hit debug and check the value it is NULL
I can't figure it out
I guess i need to remove new line characters but how to do that when the text box is null and every function for strings spits out that error

The problem with your check is that Len(Null) is not 0, it's Null.
There are a couple ways to get around this. First, as mentioned in the comments, you can simply add a check for IsNull:
If IsNull(Me.Text5) Or Len(Me.Text5) = 0 Then
The other way you can do this is force it to coalesce by concatenating vbNullString:
If Len(Me.Text5 & vbNullString) = 0 Then

Also you could use Nz and set a return value of your wish in case if the expression is null, in this example also vbNullString and check the result of this function:
If Nz(Me.Text5, vbNullString) = vbNullString Then
or
If Len(Nz(Me.Text5, vbNullString) = 0) Then
or
If Nz(Me.Text5, 0) = 0 Then
or
If Not Nz(Me.Text5, False) Then
For sure you can store the result in a variable first and then check and work with this later on.
Whatever fulfills your needs.

Well, i test it as much as i can and it's just that when you use Ctrl+Enter on a field and capture the key press, field will be null for some reason, i don't see possible way around this

Related

microsoft access Field must be blank or have a value that is a specific length

I have a field on a form and I need the user to leave it blank or enter a value that is a specific length (20 characters). Does anyone have code that may solve this need?
I have tried:
(Len([SIM / ENGRV]) = 20) or (isnull([SIM / ENGRV])) or ([SIM / ENGRV]="")
I assume the control (field) name in the form is Text1.
So you can use this code in the before update event .
Of course, the code can be much shorter,
But I think that's the clearest way to understand the logic.
Private Sub Text1_BeforeUpdate(Cancel As Integer)
Dim varTmp As Variant
' first check if [ENGRV] > 0 to avoid devision by zero error
If Not IsNumeric([ENGRV]) And [ENGRV] = 0 Then
Text1.Undo
Cancel = True
Else
' now avoid [SIM] is null error
If Nz([SIM], "") = "" Then
Text1.Undo
Cancel = True
Else
varTmp = [SIM] / [ENGRV]
' now we know that varTmp is somthing and not empty then check the length
If Len(Trim(str(varTmp))) <= 20 Then
Text1.Undo
Cancel = True
End If
End If
End If
End Sub
You can do that at the table level. Set the Validation Rule of the field to:
Len([SIM / ENGRV])=20 Or [SIM / ENGRV] Is Null

MS Access VBA, efficient way to enable a button only after all required textboxes contains valid data

My code is working, but I just want to know if there is a more efficient way to achieve the same effect.
I have this layout in a form:
In my effort to foolproof the record creation process, I would like to have the "Save and Clear fields" button enabled only after all but the 'Comment' textbox/combobox contains some valid data.
The text/combo boxes are called txtBatteryID, cmbModelNumber, cmbChemistryType, txtSpecVoltage, txtSpecCapacity.
My code is as follow
Private Sub EnableSaveBtnCheck()
'this checks if the required fields contains valid data, if so, enables the save button.
If Me.btnSaveAndCLear.Enabled = False Then
If IsNull(txtBatteryID) = False And IsNull(cmbModelNumber) = False And IsNull(cmbChemistryType) = False And IsNull(txtSpecVoltage) = False And IsNull(txtSpecCapacity) = False Then
Me.btnSaveAndCLear.Enabled = True
End If
End If
End Sub
As you can see, I did the most straightforward way of using AND to combine all must-have conditions in an IF statement. This sub is called in After_Update() event of each text/combo box. Like this:
Private Sub cmbChemistryType_AfterUpdate()
Call EnableSaveBtnCheck
End Sub
My question, in the end, is: Is there a more efficient way to setup the condition "all text/combo box need to have something valid in them"? And is there a more elaborate way to check if the condition is met (something like a event on the form itself)?
Add the values of those 5 fields. If any of them is Null, the sum will be Null. So you only need call IsNull() once.
If IsNull(txtBatteryID + cmbModelNumber + cmbChemistryType + txtSpecVoltage + txtSpecCapacity) = False Then

Incrementing textbox value up and down in vba does not cancel evenly

I can't figure out why my code isn't maintaining significant digits when incrementing a textbox value.
I have a spin control (textbox plus two small command buttons to move textbox value up or down in value) on a form.
The textbox default value is zero.
The up arrow command button should increment the textbox value by + 0.1. Here is the code:
Private Sub cmdIndexSpinUp_Click()
If Me!txtIndexSpin >= 1.5 Then
MsgBox "The maximum Index adjustment has been reached."
Exit Sub
Else
Me!txtIndexSpin = Me!txtIndexSpin + 0.1
End If
End Sub
The down arrow command button should increment the textbox value by -0.1. Here is the code:
Private Sub cmdIndexSpinDown_Click()
If Me!txtIndexSpin <= -1.5 Then
MsgBox "The minimum Index adjustment has been reached."
Exit Sub
Else
Me!txtIndexSpin = Me!txtIndexSpin - 0.1
End If
End Sub
So I would expect that from the default value of 0, if I spin up once and down once, I should return to 0. That works fine. If I spin up twice and then down twice, my textbox value suddenly becomes 2.77555756156289E-17 instead of 0.
After more testing, it does not consistently happen based on the number of clicks, but it may be related to the time between clicks. The more rapid, the more prone to this error it seems.
How could this be happening?
I am going to code around it, since I see nothing wrong, but am curious what I am missing.
As #HansUp says floating points aren't precise. Source. An easy solution that you could use is to round the number before putting it in the text box.
Example :
Private Sub cmdIndexSpinDown_Click()
Dim value As Double
value = Me!txtIndexSpin
If value <= -1.5 Then
MsgBox "The minimum Index adjustment has been reached."
Exit Sub
Else
value = Round(value - 0.1, 1)
Me!txtIndexSpin = value
End If
End Sub
Private Sub cmdIndexSpinUp_Click()
Dim value As Double
value = Me!txtIndexSpin
If value >= 1.5 Then
MsgBox "The maximum Index adjustment has been reached."
Exit Sub
Else
value = Round(value + 0.1,1)
Me!txtIndexSpin = value
End If
End Sub
Round() is a reasonable solution for your floating point precision problem. And it may well be exactly what you want. However, be aware that you will be using "banker's rounding", sometimes called "round to even". So you might not get what you expect from rounding to 1 decimal place when the second decimal place is 5:
? Round(1.15, 1)
1.2
? Round(1.25, 1)
1.2
If that is not what you want, you could use a different rounding strategy. Or you could switch to integer math instead of floating point math ... and then the floating point precision challenge goes away. That might sound challenging, but it's actually simple to implement. Add a hidden text box to your form and use it like this ...
Private Sub cmdIndexSpinDown_Click()
With Me!txtHidden
If .Value <= -15 Then
MsgBox "The minimum Index adjustment has been reached."
Else
.Value = .Value - 1
Me!txtIndexSpin.Value = .Value / 10
End If
End With
End Sub
If txtIndexSpin is bound to a field in the form's Record Source, you can load txtHidden from the form's Current event:
Me!txtHidden.Value = Me!txtIndexSpin.Value * 10
And if you also allow the users to edit txtIndexSpin directly (not just via those command buttons), do that again from its After Update event.

Global Date Variable Works Only for Entered Values

I'm currently working on what should be a relatively simple database, which is very close to being at its end, until I hit the inevitable problem.
I'm using Global Variables and a Form to collect parameters to pass into the Criteria portion of a Query, which works just fine for the first two, which are basic strings and integers.
Then comes the dates, which work, so long as you chose a date from the DatePicker that is entered into the query.
For example, if the query field holds 6/1/2014, 6/3/2014, and 6/8/2014, and the date 6/5/2014 is picked, the form will crash and go blank, though if you pick 6/8/2014, it'll go on as it should.
I had tried a variety of different forms of the code, but in the most basic form I simple have:
Between Get_Global('GBL_Start_Date_ID') AND Get_Global('GBL_End_Date_ID')
I'm not sure if I should be limiting the DatePicker based on the values entered in the query, or if there's a more robust way of going about this, or maybe I just completely missed a simple checkbox.
EDIT
My code for the Global Variables looks like this:
Option Compare Database
Global GBL_Start_Date_ID As Date
Global GBL_End_Date_ID As Date
Global GBL_Customer_ID As Long
Global GBL_Engineer_ID As Long
Public Function Init_Globals()
GBL_Start_Date_ID = #6/1/2014#
GBL_End_Date_ID = #6/30/2014#
GBL_Customer_ID = 1
GBL_Engineer_ID = 1
End Function
Public Function Get_Global(gbl_parm)
Select Case gbl_parm
Case "GBL_Customer_ID"
Get_Global = GBL_Customer_ID
Case "GBL_Engineer_ID"
Get_Global = GBL_Engineer_ID
Case "GBL_Start_Date_ID"
Get_Global = GBL_Start_Date_ID
Case "GBL_End_Date_ID"
Get_Global = GBL_End_Date_ID
End Select
End Function
And I just add a simple line to the AfterUpdate event of the ComboBoxes and TextBoxes to assign the variable:
GBL_Engineer_ID = Me.EngineerSelection
Thanks in advance,
Aaron
You can do two things. Fix the query as it is written or make it much more robust.
To fix it as written
Between "#" & Get_Global('GBL_Start_Date_ID') & "#" AND "#" & Get_Global('GBL_End_Date_ID') & "#"
OR
change your Get_Global function
Public Function Get_Global(gbl_parm)
Select Case gbl_parm
Case "GBL_Customer_ID"
Get_Global = GBL_Customer_ID
Case "GBL_Engineer_ID"
Get_Global = GBL_Engineer_ID
Case "GBL_Start_Date_ID"
Get_Global = "#" & GBL_Start_Date_ID & "#"
Case "GBL_End_Date_ID"
Get_Global = "#" & GBL_End_Date_ID & "#"
End Select
End Function
You are correctly specifying that the values of GBL_Start_Date_ID and GBL_End_Date_ID are dates by using #s when you create them however when you use them in your query they appear without them. You can prove to yourself this is what is happening by typing ?#1/1/2014# into the immediate window. The date is printed as 1/1/2014 which when used in your query, makes Between 6/1/2014 AND 6/30/2014 which is a syntax error.
To make things all that much better you need to parameterize this part of your query. Change this
Between Get_Global('GBL_Start_Date_ID') AND Get_Global('GBL_End_Date_ID')
to this
Between pStartDate AND pEndDate
Before you call your query you need to do your usual checks: are either of these null? is pStartDate < pEndDate?
By performing these checks and parameterizing this you ensure that you never end up with a query like this. Calling your query means you need to need to populate the parameters with DAO or ADO.
Between AND

Allow user to separate dates with period in MS Access

I am working with an Access database where I have a form that contains several date entry fields. I have a new user that is used to using a period as a delimiter for dates so instead of "6/22/11" or "6-22-11", they enter "6.22.11". I would like to continue to allow this type of entry, but Access converts "6.22.11" to a time instead of a date. I have tried setting the format on the text box to "Short Date" with no help. I have also tried adding code to the "Lost Focus" event but that is to late since Access has already done the conversion. The "Before Update" event fires before the conversion but will not allow me to change the text in the textbox. Any ideas on how I can allow all three forms of date entry?
your above example
Private Sub Texto0_KeyPress(KeyAscii As Integer)
If Chr(KeyAscii) = "." Then
KeyAscii = Asc("/")
End If
End Sub
works for me.
Another aproximation is play with the BeforeUpdate and AfterUpdate events.
In BeforeUpdate you cannot modify de content of the control, but you can set a flag (a variable defined at module/form level) in the AfterUpdate event and change the content: it will trigger again the BeforeUpdate, but in this case, because is flagged you sould ignore it and unflag.
http://office.microsoft.com/en-us/access-help/control-data-entry-formats-with-input-masks-HA010096452.aspx
Input Mask.
I wrote the following function for a user who was used to entering 6 and 8 digit dates in input masks by just typing a string of numbers with no delimiter. You should be able to modify it for your purposes:
'---------------------------------------------------------------------------
' Purpose : Enables entry of 8-digit dates with no delimiters: 12312008
' Usage : Set OnChange: =DateCtlChange([Form].[ActiveControl])
' 8/ 6/09 : Allow entry of 6-digit dates with no delimiters
' (year 2019 and 2020 must still be entered as 8-digit dates)
'---------------------------------------------------------------------------
Function DateCtlChange(DateCtl As TextBox)
Dim s As String, NewS As String
On Error GoTo Err_DateCtlChange
s = DateCtl.Text
Select Case Len(s)
Case 6
If s Like "######" Then
If Right(s, 2) <> "19" And Right(s, 2) <> "20" Then
NewS = Left(s, 2) & "/" & Mid(s, 3, 2) & "/" & Mid(s, 5, 2)
End If
End If
Case 8
If s Like "########" Then
NewS = Left(s, 2) & "/" & Mid(s, 3, 2) & "/" & Mid(s, 5, 4)
End If
End Select
If IsDate(NewS) Then
DateCtl.Text = NewS
DateCtl.SelStart = Len(DateCtl.Text)
End If
Exit_DateCtlChange:
Exit Function
Err_DateCtlChange:
Select Case Err.Number
'Error 2101 is raised when we try to set the text to a date
' that fails the date control's validation
Case 2101 'The setting you entered isn't valid for this property.
'Log error but don't show user
Case Else
'Add your custom error logging here
End Select
Resume Exit_DateCtlChange
End Function
Access uses the system date and time format to determine how to translate a value. Another option - that would affect every program on this user's computer - is this: http://office.microsoft.com/en-us/access-help/change-the-default-date-time-number-or-measurement-format-HA010351415.aspx?CTT=1#BM2
Alternatively you can use spaces instead of slashes in dates in Access. Thus the user can use the left hand on the space bar and use the right hand on the numeric keyboard. I feel this is much easier to use than either the slash or the hyphen.