MS-Access - select part of a string from email file - ms-access

I have set up a student database in ms-access 2016 to track students on support to study and imported all the emails from a folder related to students into a database called emails (I still need to work out the VBA code to update this folder on opening/closing a form). When a student emails me, I can match that email easily to the main database as it is just from them. However, when an email is sent to a student, often other staff members are cc'd in to the email. I therefore need to be able to select out just the student's email name from the To column. So it may be Jo Smith; Leah Jones; Jo Davies (UG) (or any combination of that depending on if the student is the main recipient or not. The name of the student will always have (UG) at the end of the name, so can be identified.
Is there a way of selecting out just the student name (with the (UG) at the end is fine) from the string of names into a new column using an update column? The recipient names are separated by a ; (but if the student is first or last on the list obviously won't have a ' before/after their name). I need this to link it to the name so I can see emails sent to and from the student in forms, alongside their other information.
Many thanks in advance
Ali

It's been over a decade since I wrote an Access VBA UDF and probably a year or 5 since I wrote VBA, so grain of salt here, but this should be in the ballpark:
Function getStudentEmail(emails as String) as String
'Declare array to hold emails
Dim emailsArr() as String
'Split delimited string of emails into the array with split() function
emailsArr = Split(emails, ";")
'Loop through array
For Each email in EmailsArr
'Check if email string has (UG) in it
If InStr(1, email, "(UG)", 1) Then
'Set the return to the email and break the for loop ending the function
getStudentEmail = email
Exit For
End If
Next email
End Function
How to use:
Open up the Visual Basic Editor (VBE) with the "Visual Basic" button in the ribbon under the "Database Tools" section:
Right-click on your database in the "project" pane and choose Insert>>Module:
Paste your code in:
Now you should be able to use this function in your SQL like SELECT getStudentEmail(yourEmailColumn) FROM yourtable;

Related

Customize auto-complete functionality on Microsoft Access datasheet

I have a main form tied to a User record, with a subform tied to a number of Client objects the user "owns." So, there is a one-to-many relationship between User and Client.
As the subform exists, the user can add, remove, and edit entries in the Clients subform. When a user adds an entry to the subform datasheet, there is an autocomplete functionality that kicks in the user types part of a Client name that matches any names in the Client database, thus saving the user a few keystrokes and ensuring that the user enters a name that exactly matches one in the Client database.
One thing to note with the Clients table is that in addition to each Client having a unique numerical ID, each Client has a full company name (Test Agency, Inc.), a colloquial name (Test Agency) and an abbreviated name (TA).
I am trying to edit the subform so that the autocomplete functionality will match against any of the three fields listed above (full name, colloquial name, and abbreviated name). Right now, the autocomplete only works against the full name, as that is the field linked to the subform. I would like the user to be able to type in a part of a string, the subform to try and match it to any of the three fields (full name, colloquial name, abbreviated name) and return a list of potential matches to any of the three fields. When the user selects the correct potential match for the Client they are trying to search for, then then full company name would be entered into the datsheet. Basically, these additional fields just make it easier for the user to find the Client they are looking for (imagine typing in AMD instead of Advanced Micro Devices, Inc.)
My first question--is this possible to do with a simple datasheet? I've looked into using lookup fields and multi-value lookup fields, but I'm not sure this is the right method. Or will I need to build myself a custom control that does this matching on multiple fields?
Made a query like this
SELECT *
FROM Company
WHERE fullName LIKE '*' & pCompany & '*'
OR Colloquial LIKE '*' & pCompany & '*'
OR Abbr LIKE '*' & pCompany & '*'
and on my form I did this
Private Sub cboCompany_KeyUp(KeyCode As Integer, Shift As Integer)
ClearCombo cboCompany
Dim sql As String
Dim rs As DAO.Recordset
Dim companySearch As DAO.QueryDef
Set companySearch = CurrentDb.QueryDefs("CompanySearch")
companySearch.Parameters("pCompany") = cboCompany.Text
Set rs = companySearch.OpenRecordset
Do While Not rs.EOF
cboCompany.AddItem rs("ID") & ";" & rs("FullName") & ";" & rs("Colloquial") & ";" & rs("Abbr")
rs.MoveNext
Loop
End Sub
Private Sub ClearCombo(cbo)
For i = cbo.ListCount - 1 To 0 Step -1
cbo.RemoveItem i
Next i
End Sub
It's not super fast at all but it works. I think what would make it faster is not cuing off the KeyUp event and instead on a timer once users start typing in that field. Then turn the timer off when they stop typing or focus leaves the combobox.
So you are already able to search with partial string - probably by means of a query with a like condition.
The next step is very easy. Do the search for every field, combine them by UNION, and remove duplicates by means of a SELECT DISTINCT.
Hope this succinct answer will suffice?

How to make MS Access run a query on focus lose event and take actions accordingly

I am creating a small Access DB for our Data Entry guys. Our main DB is mysql but due to ease of use we are creating an Access DB to make it easier for them to enter the Data. I have done most of it but am stuck with this problem (which I know how to solve in mysql+php) Please pardon my ignorance, but I have just started using MS Access.
I have two tables - ClientPhones and sales. The ClientPhones table has phone, clientid fields. sales table has salesid, clientid, date, etc fields.
I also have a Form which has all relevant fields for the sales table. I want to add a new field, phone_no in that form. When a user inputs the number and on focus lose event, I was access to run a query on the clients table to see if the phone number exists in any of the 3 phone number fields. If it finds a client with that phone number, the client ID should be populated, else a new form to input the client details should be shown.
Is this possible with MS access or am I doing this incorrectly?
Use the text box's After Update event to retrieve the clientid which matches the phone number the user entered.
If a clientid is found, store it in the text box which is bound to clientid.
If no match is found, ask whether the user wants to add a new client, and open that form if they respond yes.
This code outline assumes txtSearchPhone is the name of the text box where the user enters the target phone number, and txtClientId is the name of the text box where you want to store clientid.
Private Sub txtSearchPhone_AfterUpdate()
Dim varClientId As Variant
Dim strCriteria As String
strCriteria = "[phone]='" & Me.txtSearchPhone.Value & "'"
Debug.Print strCriteria '<-- inspect this in Immediate window; Ctrl+g will take you there
varClientId = DLookup("clientid", "ClientPhones", strCriteria)
If IsNull(varClientId) Then
If MsgBox("Add new user?", vbYesNo) = vbYes Then
'DoCmd.OpenForm ... (see Access help topic)
End If
Else
Me.txtClientId.Value = varClientId
End If
End Sub
Make sure the text in txtSearchPhone does not include a single quote character (') because the DLookup will break if it does. You can use the text box's Validation Rule and/or Before Update event to make sure a single quote is not present.

Can't add record with ID from another table

I have a database which functions similarly to a "help desk" system - an outside user creates a request ticket, then a consultant will use the database for various tracking and reporting.
There is a form that the consultant uses to display and work with the end user request. They select an existing record (request ticket) from a combo box. The form then populates with the information of the request, which the consultant can edit if needed.
I then have a series of buttons on this form that the consultant can use to open different forms (worksheets) and enter data in each one. These are all optional and will vary based on the type of request.
These worksheets all populate the "Consulting" table, while the initial requests are in a "Request" table. There is only one record in the "Consulting" table per record in "Request" (1:1 relationship).
Here is the code I have to open the forms (worksheets):
Private Sub ButtonGap_Click()
DoCmd.OpenForm "Gap Analysis", acNormal, , "[ID] = " & Me!ID, acFormEdit, acDialog
End Sub
This only partially works. If there is existing information in the "Consulting" table with an ID that corresponds to the ID from "Request" (what they selected in the combo box at the start), the worksheet will open pre-populated and editable. Great!
But... if there is no existing information in the "Consulting" table with an ID that corresponds to the ID from "Request", the worksheet opens blank, to a new record. This record autonumbers from where the "Consulting" table left off. This creates a problem if several requests have come in - we are not always working on them in order, so the new record ID in "Consulting" does not match the existing record from the "Request".
I'm sure it's something incredibly simple I'm overlooking. Can anyone help?
I was able to find a way to do this, it appears. If I missed something, please let me know! I don't want to break anything else. :)
I created a query to find the unmatched records, giving me a list of all IDs from Request without a matching ID in Consulting.
From there, I based an append query on these results, to append just the missing IDs to Consulting.
That query runs when the Request form is submitted:
Private Sub Form_AfterUpdate()
DoCmd.OpenQuery "Add Blank Consulting"
End Sub
Now my worksheets on the Consulting form are populating with the correct ID!

What are all the fields available in a Notes email document in VBA

I have written VBA code to send an email from a group mailbox. I set the principal field to say where the mail comes from. It almost works correctly, putting the message in the sent items of the group mailbox. Even though I have the group mailbox name in the Principal field, it still says it was sent my me. I discovered that whichever user looks at the message in sent items, it says it was sent by that user (it is a dynamic field). I want to set that From field, and I discovered I can do that with something like '.from = "(User Name)"'.
So I am aware of the basic variables available, such as .SendTo, .CopyTo, .Principal, .From. But I have done web searches and I can't figure out how to get a comprehensive list of all the variables available. Hopefully someone can point me to some documentation that lists these?
For reference here is my code:
Function EmailFromNotes(strSendTo As String, strCopy As String, strSubject As String, _
strText1 As String, strText2 As String, strText3 As String, _
strText4 As String, strText5 As String, strAttachment As String, strFrom as String)
Dim notesdb As Object
Dim notesdoc As Object
Dim notesrtf As Object
Dim notessession As Object
Dim i As Integer
Dim AttachME As Object 'The attachment richtextfile object
Dim EmbedObj As Object 'The embedded object (Attachment)
Set notessession = CreateObject("Notes.Notessession")
''''''''Group Mailbox'''''''''''''''''''''''''''''''''''''''''''''''''
Set notesdb = notessession.GetDatabase("Servername", "mailin\GroupMailbox.nsf")
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Open the mail database in notes
If notesdb.IsOpen = True Then
'Already open for mail
Else
notesdb.OPENMAIL
End If
Set notesdoc = notesdb.CreateDocument
Call notesdoc.ReplaceItemValue("Subject", strSubject)
Set notesrtf = notesdoc.CreateRichTextItem("body")
Call notesrtf.AppendText(strText1 & vbCrLf & strText2 & vbCrLf & strText3 & vbCrLf & strText4 & vbCrLf & strText5)
'''strCopy = "michael.thain#pnc.com"
notesdoc.SendTo = strSendTo
notesdoc.CopyTo = strCopy
notesdoc.from = strFrom
''''''''Group Mailbox'''''''''''''''''''''''''''''''''''''''''''''''''
notesdoc.principal = "Group Mailbox Name"
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
If strAttachment = "" Then
Else
Set AttachME = notesdoc.CreateRichTextItem(strAttachment)
Set EmbedObj = AttachME.EmbedObject(1454, "", strAttachment)
End If
Call notesdoc.Save(True, False)
notesdoc.SaveMessageOnSend = True
Call notesdoc.Send(False, strSendTo)
Set notessession = Nothing
End Function
Unlike many other mail systems, Lotus Notes is finicky about spoofing the From field. The NotesDocument.Send() method doesn't want you to do it, and will override what you put in there. The Principal field is provided so you can say who you are sending on behalf of, but the From is supposed to be the true name of the actual sender. If you look at the document properties for the message in your Sent folder, I believe you'll find that the From field does indeed contain your name, not the name that your code is trying to put in that field!
There is a way around this, at least for the Sent message. Instead of relying on the SaveMesasageOnSend property, you can just use NotesDocument.Save() to write the document directly to the group mailbox, making sure that you set the PostedDate and not the DeliveredDate so that it will appear in the Sent view. It will be missing other fields that the Domino router would normally have added for you, though, like the MessageID and a few others -- but that might not be important for you. The message should still be viewable. In any case, as complex as it is, the formulas in the fields on the Memo form and its associated subforms in the mail template are your ultimate guide for figuring out how what the user sees is related to the actual values that are stored in the document.
If you're also concerned about making sure that recipients don't see your name, there's another trick. It involves directly writing the message to the router mailbox (the mail.box file). I've seen some systems, however, where there's code in place to prevent spoofing even if you do this, so it's something you'll have to try and see if it will work.
BTW: Are you asking about what the users see when they look at the index of the Sent view? That should be showing the value in the Principal field. Or are you asking about what the users see when go the Sent view and open the message? That should display the Principal field, followed by a newline and then "Sent by:" the From field. (Bear in mind that the From field is not likely the value that your code set due to the anti-spoofing provisions that I described.) Does this match what you are seeing?
Mail fields are defined by an RFC for all mails in general.
http://en.wikipedia.org/wiki/Email#Message_header
RFC 5322 https://www.rfc-editor.org/rfc/rfc5322
In the RFC 5322 Standard the field From has a different purpose than in Lotus Notes, because it is always identifying the owner of the mail.box. Instead of using the field Principal to identify the owner of the mail.box in which an email was written, the field Sender is used to identify the effective user who produced the email.
The field Principal is not (or better said no longer) accepted in the email header by many email providers and bounced back referring to being not RFC 5322 compliant. In messages produced by LotusScript directly in a document saved in the mail.box, you should use the field From instead of the field Principal and add the field Sender for the email address of the effective sender (sent by), who in a regular Lotus Email would be in the field From. If you prefer to have all replies to the effective sender instead of the person identified in the field From (original LN field Principal), you need to add the field ReplyTo with the same address as in der field Sender.

MS Access - Mass Emailing?

I'm using MS Access to create a database with over 5000 contacts. These contacts are separated up into which employee the contact belongs to, and then again into categories for easy searching. What I want to do is create a button that will open up a query in table form (simple), then have check boxes so an employee can select, for example, 100 contacts to send an email to out of the 110 in the table, and then send a mass email such as a newsletter (not so simple!). I've been going nuts trying to work out how to do this as I don't really understand programming (I'm a temp thrown into this job and just doing the best I can) and all I can find on the matter is something about loops (no idea!) and that I need software to do this.
Any solutions for me please? I'd like to avoid buying/installing software if possible and if you do have an answer, please make it as simple as possible...
Thanks in advance!
Kate
I have just created the following working example in MS Access 97.
A sample table (I tested the code with valid e-mail addresses):
ID Name Email
1 Rics rics#stack.com
2 Kate kate#stack.com
3 X x#stack.com
A form with one button.
The following code is being performed when the button is clicked:
Private Sub Mail_Click()
Dim r As Recordset
Dim email As String
Set r = CurrentDb.OpenRecordset("select * from Addresses")
Do While Not r.EOF
email = r(2)
DoCmd.SendObject acSendNoObject, Null, Null, email, Null, Null, "Test subject", "Message body of the test letter", False, Null
r.MoveNext
Loop
r.Close
End Sub
I hope you could insert it into your application.
Got it working :)
The code was great but it needed some tweaking to work specifically with my data. After a lot of errors popping up this is what I finally came up with:
Dim r As Recordset
Dim Email As String
Set r = CurrentDb.OpenRecordset("select Email from FranksFinanceBrokers")
Do While Not r.EOF
Email = Email & r(0) & ";"
r.MoveNext
Loop
r.Close
DoCmd.SendObject acSendNoObject, Null, Null, "", "", Email, "", "", True, Null
End Sub
Thanks for ur helps guys!
I think you're going to need to learn some VBA coding to get this done. This tutorial might be useful.
Heres a way to send email from access.
Here's another resource for sending e-mail through MS Access
The answer that rics has supplied will send an e-mail to everyone in a recordset, but it sounds like maybe what you are wanting to do is send a single e-mail to a custom distribution list. To do that, tweak rics' code to build up the address string something like this:
Private Sub Mail_Click()
Dim r As Recordset
Dim email As String
Set r = CurrentDb.OpenRecordset("select * from Addresses")
Do While Not r.EOF
email = email & r(2) & ";"
r.MoveNext
Loop
r.Close
DoCmd.SendObject acSendNoObject, Null, Null, email, Null, Null, "Test subject", "Message body of the test letter", False, Null
End Sub
Kate,
Sorry to say that there is no specific "magic" code for what you plan to to. You will have to write something. My solution would be:
Create a form with 3 controls: 1 text control, 1 listbox control.,1 "send" button
The text control contains the text to send
The list control displays all my available emails (populated with a recordset)
Multiselect will be enabled, so that I can select multiple items in the list
By a click on the button, I will
Concatenate all selected emails to get a "sendTo" string such as
sendTo = "bla#bla.com;blo#blo.com".
Call the doCmd.sendObject method using sendTo + the text string as an argument
Options could be to
Have an extra control for email subject
Keep a trace of sent mails in a table (subject, text, date, people reached). It could be as basic as "one record per mail" with a memo field to record the sendTo text string (Of course you could build something smarter with multiple tables to stick to the many-to-many relation that can be established between your people table and your mail table, but you might not need it)
There are a couple of ways to get around the missing e-mail addresses. The easiest is to adjust your SQL to exclude them:
select Email from FranksFinanceBrokers WHERE (Email IS NOT NULL) AND (Email <> "")
The other approach would be to add an IF statement to the string building code:
IF Not IsNull(r(0)) AND r(0) <> "" THEN Email = Email & r(0) & ";"
I would just filter it at the SQL level -- more efficient and just easier.
Would it be easier to buy software to do this? Yes, but where's the challenge in that? :-) You are already most of the way there, so I'd stick with it.
Emailing from Access has a number of pitfalls, not least of which is that doing so can make you look like a spammer and cause problems with your email host. Plus, there are a bunch of security issues. The best source for information on this is Tony Toews's Email FAQ.