I have a form that is selecting emails based on companies that have expired insurances. Some companies have both a Business and personal emails whilst others have one or the other.
I am using the DLookUp function to select the email based on Suppliers meeting the filter criteria.
Is there a way for me to select the BusinessEmail but if they don't have one it selects the PersonalEmail instead?
Currently I have started with =DLookUp("BusinessEmail","tblContacts","Supplier ID = " & [txtSupplierID] and then went to use an IIf statement in it but I was lost as to how it would then select the other email or if it would work that way.
contacts sample data
The DLookup() function returns null if the value was not found, so you can make use of the Nz() function to check for the personal email, if the business email is null.
Since we assign the return value to a string and strings cannot hold null values, we make use of the Nz() function again to return an empty string, if the personal email doesn't exists too (to avoid the error).
Dim criteria As String
criteria = "[Supplier ID] = " & [txtSupplierID]
Dim email As String
email = Nz(DLookup("BusinessEmail", "tblContacts", criteria), Nz(DLookup("PersonalEmail", "tblContacts", criteria), vbNullString))
Edit:
Adding a second rule to the DLookup to exclude null values, should work. See a helper function to get the email through an output parameter and report success/failure:
Private Function TryGetEmail(ByVal supplierId As Long, ByRef outEmail As String) As Boolean
Dim retValue As Variant
'try to get business
retValue = DLookup("BusinessEmail", "tblContacts", "[Supplier ID] = " & supplierId & " AND BusinessEmail Is Not Null")
If Not IsNull(retValue) Then
outEmail = retValue
TryGetEmail = True
Exit Function
End If
'try to get personal
retValue = DLookup("PersonalEmail", "tblContacts", "[Supplier ID] = " & supplierId & " AND PersonalEmail Is Not Null")
If Not IsNull(retValue) Then
outEmail = retValue
TryGetEmail = True
Exit Function
End If
'none found
outEmail = vbNullString
TryGetEmail = False
End Function
To call it:
Sub T()
Dim supplierId As Long
Dim email As String
supplierId = 19
If Not TryGetEmail(supplierId, email) Then
MsgBox "No email found"
Exit Sub
End If
'email now holds one of the two emails
End Sub
First, change the field "Supplier ID" to "SupplierID", it will make your development easier.
Here are some code using both Dlookup and IIf, putting the result in a textbox named txtEmail:
Private Sub getEmail()
txtEmail = DLookup("Iif(Isnull(BusinessEmail),PersonalEmail,BusinessEmail)", "tblContacts", "SupplierID = " & txtSupplierID)
End Sub
or this:
Private Sub getEmail()
Dim Email As Variant
Email = DLookup("BusinessEmail", "tblContacts", "SupplierID = " & txtSupplierID)
If IsNull(Email) Then Email = DLookup("PersonalEmail", "tblContacts", "SupplierID = " & txtSupplierID)
txtEmail = Email
End Function
Related
I have this complicated VBA function on a MSAccess form frm_DataEntry. It searches for values which are not in a list. The function is called on de NotInList event of the comboboxes.
When the typed string in combobox cbo_CustomerLocations is not in the list, it will ask if I want to add it to the table tbl_CustomerLocations by Yes/No question. After that it goes from 1st column to the last column and asks if I want to add some new data. The code below shows how to add a CustomerLocation.
The last field CustomerID of my table tbl_CustomerLocations is linked to the CustomerID field of table tbl_Customers
Now my question:
How do I alter my VBA code when the NotInList event is called, and when it reaches the CustomerID column (the last column), It must not ask 'What do you want for CustomerID', but rather automatically selects the CustomerID I previously selected on the same form frm_DataEntry on combobox cbo_Customers?
Private Sub cbo_CustomerLocationID_NotInList(NewData As String, Response As Integer)
Dim oRS As DAO.Recordset, i As Integer, sMsg As String
Dim oRSClone As DAO.Recordset
Response = acDataErrContinue
String_Value = Me.cbo_CustomerLocationID.Text
MsgBold = String_Value
MsgNormal = "Add to list with locations?"
Debug.Print
If Eval("MsgBox ('" & MsgBold & vbNewLine _
& "#" & MsgNormal & "##', " & vbYesNo & ", 'New Location')") = vbYes Then
Set oRS = CurrentDb.OpenRecordset("tbl_CustomerLocations", dbOpenDynaset)
oRS.AddNew
oRS.Fields(1) = NewData
For i = 2 To oRS.Fields.Count - 1
sMsg = "What do you want for " & oRS(i).Name
oRS(i).Value = InputBox(sMsg, , oRS(i).DefaultValue)
Next i
oRS.Update
cbo_CustomerLocationID = Null
cbo_CustomerLocationID.Requery
DoCmd.OpenTable "tbl_CustomerLocations", acViewNormal, acReadOnly
Me.cbo_CustomerLocationID.Text = String_Value
End If
End Sub
Use an If Then block within the loop to check for name of field.
If oRS(i).Name = "CustomerID" Then
oRS(i) = Me.cbo_Customers
Else
sMsg = "What do you want for " & oRS(i).Name
oRS(i).Value = InputBox(sMsg, , oRS(i).DefaultValue)
End If
I have a list of records that I can search by inputting various date or selecting between dates, and using sql script it returns the results. But I would like to know how can I use greater than symbol in the date textbox and have sql script recognize it and return dates greater than for example ">7/1/2021"
Thank you for your help.
The way that I would do this is to use a combo box that has the various operators (<=,<,=,>,>=) stored as a value list, in addition to the text box that has the date. This is a good idea as you limit the choices that the user can make for the comparison, and you still get to use the input mask for the date field in the combo box.
You can then concatenate the comparison and the date to a SQL string that provides the search. Something like:
Private Sub cmdSearch_Click()
On Error GoTo E_Handle
Dim strSQL As String
Const JetDateFmt = "\#mm\/dd\/yyyy\#;;;\N\u\l\l"
strSQL = "SELECT * " _
& " FROM TB_Edditions " _
& " WHERE ED_Start_Date " & Me!cboOperator & Format(Me!txtDate, JetDateFmt) _
& " ORDER BY ID ASC;"
Me!lstResult.RowSource = strSQL
sExit:
On Error Resume Next
Exit Sub
E_Handle:
MsgBox Err.Description & vbCrLf & vbCrLf & "frmDateSearch!cmdSearch_Click", vbOKOnly + vbCritical, "Error: " & Err.Number
Resume sExit
End Sub
In this instance I am using the SQL created to populate a list box. You will note that I am forcing the date entered to be in a specific format, so that it is interpreted correctly.
It is unclear how you are invoking the sql query and that matters, but one approach is you can access public functions anywhere in access. So if you have public functions GetOperator and GetDate you can either pass them as parameters to the sql query, bind them to the sql query directly, or use them in the designer:
For a case like < or > and a date you want to validate the textbox entry first. I tried to validate using the textbox validation rule but apparently this case was too complicated. I ended up having to use the textbox BeforeUpdate Event.
Private Sub txtFilter_BeforeUpdate(Cancel As Integer)
'text box name is txtFilter
If isValidOperator(Me.txtFilter) And isValidDate(Me.txtFilter) Then
Cancel = False
setmysearchcriteria = Me.txtFilter
Else
MsgBox "Search criteria must be in the form of operatordate such as <4/12/21", vbOKOnly
Cancel = True
Exit Sub
End If
End Sub
Public Function isValidOperator(strText As String) As Boolean
Dim operator As String
operator = Left(strText, 1)
If operator = ">" Or operator = "<" Then
SetOperator (operator)
isValidOperator = True
Else
isValidOperator = False
End If
End Function
Private Function isValidDate(strDate As String) As Boolean
strDate = Mid(strDate, 2)
If IsDate(strDate) Then
SetDate (strDate)
isValidDate = True
Else
isValidDate = False
End If
End Function
Here is the code for the public functions serving as synthetic properties. Just pass the Get functions as parameters or invoke them as functions directly in the sql.
Private strMyDate As String
Private myoperator As String
Public Function SetDate(strDate As String) As Boolean
strMyDate = "#" & strDate & "#"
SetDate = True
End Function
Public Function GetDate() As String
GetDate = strMyDate
End Function
Public Function SetOperator(operator As String) As Boolean
myoperator = operator
SetOperator = True
End Function
Public Function GetOperator() As String
GetOperator = myoperator
End Function
In most case you will want to trigger your sql in the textbox AfterUpdate event. For instance Changes to the form your textbox is in will not show if you trigger your sql in the BeforeUpdate event.
Private Sub txtFilter_AfterUpdate()
'trigger your sql here instead of setting the filter
Me.Filter = "ADate " & GetOperator & " " & GetDate
Debug.Print Me.Filter
Me.FilterOn = True
Me.Requery
End Sub
Like #braX said, enclose your date literals inside two # characters..
I have this skill checkboxlist which contains skills that can be selected by the user. If the user select two skills,two records will be inserted to the table.
I tried this one:
Dim varSkillID As Integer()
varSkillID = split(skills, ",")
If varSkillID(0).value > 0 Then
Dim sql As String = Nothing
For I = 0 To varSkillID()
sql = "INSERT INTO tblConstituentSkills (skillID) VALUES ( " & varSkillID.Value & ")"
Next I
end if
but its not working. Thanks!
I also tried this code.
Dim varSkillID() As String = Split(skillID, ",")
For i As Integer = 0 To varSkillID.Length - 1
If varSkillID(i) <> "" Then
Using sql As New SqlProcedure("spInsertSkill")
sql.AddParameter("#ConstituentIdNo", constituentIdNo)
sql.AddParameter("#skillID", varSkillID(i))
sql.ExecuteNonQuery()
End Using
End If
Next i
It works when I only select single skill. But if I select two or more skills this error appears "Nullable object must have a value."
please use the editor help to design your request. It is very hard to read.
What does the errormessage say?
There is an End If missing
Where does constituentIdNo.Value is coming from?
To call the Sub:
Call r101("123456", "1,2,3,4")
the Sub:
Public Sub r101(ByVal constituentIdNo As String, ByVal skills As String)
Dim varSkillID() As String = Split(skills, ",")
Dim sql As String = Nothing
For i As Integer = 0 To varSkillID.Length - 1
If varSkillID(i) <> "" Then sql = "INSERT INTO tblConstituentSkills (ConstituentIdNo, skillID) VALUES (" & constituentIdNo & ", " & varSkillID(i) & ")"
Next i
End Sub
This is not the cleanest code, but the best I could create from your given feedback.
I don't see why to convert skills to integer.
I just read this and saved me.separate comma separated values and store in table in sql server
Thanks stackoverflow!you're a savior!
Working in Excel VBA, I have a class module where I define my class 'Marker'. One of the properties of my class is TextLine(), which is an array that holds up to 5 strings. I have defined the two methods below in my class module. In another (regular) module, I fill markerArr() with my custom Marker objects. Loading each object's properties with data at each array index is working fine... However, after loading data into the object at each index, I try to use markerArr(count).ProcessLines but receive a type mismatch error. Since ProcessLines is a public sub in my class module, and markerArr(count) contains a Marker object, I can't seem to understand why this error is occurring... Am I overlooking something obvious?
'Serial number replacement processing function
Public Sub ProcessLines()
Dim strSerial As String
Dim toggle As Boolean
toggle = False
Dim i As Integer
For i = 0 To 4
If Trim(m_TxtLines(i)) <> "" Then
'Add linefeed char to non-empty text lines
m_TxtLines(i) = m_TxtLines(i) & Chr(10)
'Detect if it is a serialized line
If InStr(1, m_TxtLines(i), "XXXXXX-YYY") > 0 Then
m_Serial(i) = True
toggle = True
End If
End If
Next
'When at least one line on the marker is serialized, create and replace serial text
If toggle = True Then
'Only prompt for input once
If startSerNo < 1 And Num_Sers < 1 Then
startSerNo = InputBox("Enter the serial number to start printing at." & Chr(10) & _
"Entering 1 will result in -001, entering 12 will result in -012, etc.", "Starting Serial #", "1")
Num_Sers = InputBox("Enter the amount of serializations to perform." & Chr(10) & _
"This will control how many copies of the entire marker set are printed.", "Total Serializations", "1")
End If
strSerial = CreateSerial(startSerNo)
Dim j As Integer
For j = 0 To 4
If m_Serial(j) Then
m_TxtLines(j) = Replace(m_TxtLines(j), "XXXXXX-YYY", strSerial)
End If
Next
End If
End Sub
'Creates the string to replace XXXXXX-YYY by concatenating the SFC# with the starting serial number
Private Function CreateSerial(ByVal startNum As Integer)
Dim temp
temp = SFC_Num
Select Case Len(CStr(startNum))
Case 1
temp = temp & "-00" & startNum
Case 2
temp = temp & "-0" & startNum
Case 3
temp = temp & "-" & startNum
Case Else
temp = temp & "-001"
End Select
CreateSerial = temp
End Function
Your CreateSerial function takes an integer as a parameter, but you are attempting to pass a string. I've pointed out some problems:
If startSerNo < 1 And Num_Sers < 1 Then 'Here I assume, you have these semi-globals as a variant - you are using numeric comparison here
startSerNo = InputBox("Enter the serial number to start printing at." & Chr(10) & _
"Entering 1 will result in -001, entering 12 will result in -012, etc.", "Starting Serial #", "1") 'Here startSerNo is returned as a string from the inputbox
Num_Sers = InputBox("Enter the amount of serializations to perform." & Chr(10) & _
"This will control how many copies of the entire marker set are printed.", "Total Serializations", "1") 'here Num_Sers becomes a String too
End If
strSerial = CreateSerial(startSerNo) 'here you are passing a String to the CreateSerial function. Either pass an integer, or allow a variant as parameter to CreateSerial
'......more code.....
Private Function CreateSerial(ByVal startNum As Integer)
I am trying to search if a number exists in one of the 32 sheets I have in my workbook.
I have tried to use the below mentioned code but it's not working because VLOOKUP is not deciphering the variable(n). Kindly help:
Private Sub SearchAll_Click()
Dim SearchCriteria As Double, s As Integer
SearchCriteria = Me.SearchBox.Value
s = 0
For s = 0 To ThisWorkbook.Sheets.Count
s = s + 1
If Application.WorksheetFunction.VLookup(SearchCriteria, Sheets(s).Range("A:A").Value, 1, False) = SearchCriteria Then
MsgBox ("The Number " & SearchCriteria & " is available in list " & Sheets(s).Name)
Exit For
Else
MsgBox ("The Number is Unavailable")
End If
Next s
End Sub
Legend:
SearchAll is a button used to initiate the search.
SearchCriteria is a textbox used to input the value you want to search for.
There are a few problems in the way you use Application.WorksheetFunction.VLookup to determine if a specific value exists in your workbook. I have modified your code to the following:
Private Sub SearchAll_Click()
Dim SearchCriteria As Double, s As Integer
Dim Lookup As Variant
Dim Match As Boolean
SearchCriteria = Me.SearchBox.Value
For s = 1 To ThisWorkbook.Sheets.Count
Lookup = Application.VLookup(SearchCriteria, Sheets(s).Range("A:A"), 1, False)
If Not IsError(Lookup) Then
MsgBox ("The Number " & SearchCriteria & " is available in list " & Sheets(s).Name)
Match = True
Exit For
End If
Next s
If Match = False Then MsgBox ("The Number is Unavailable")
End Sub
Here I have, instead, made use of Application.VLookup which will return an error to the variant variable Lookup if the search value were not found in the specific sheet. Then, by looking at the error state of Lookup it can be determined if the search value were found. Also, I have moved the message The Number is Unavailable outside the loop in order to avoid it being triggered each time the value were not found in a specific sheet.