VBA - Change Outlook Subject Line on Receipt Of Email - vba

I have written a script that's intended behaviour is supposed to change the Subject Line of a received email.
This is because a Third Party Program monitors an Outlook Folder and posts it to a Virtual Cabinet based on the Subject line being a certain fashion.
I have written the code below that all changes out OK however the Subject Line does not get changed - can anyone shed any light on this at all?
Sub AmendSubject(myItem As Outlook.MailItem)
Dim strBranch As String
Dim strPolRef As String
Dim strTo As String
Dim cnn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim rsSQL As String
Dim strSubject As String
Set cnn = New ADODB.Connection
Set rs = New ADODB.Recordset
'Places the Customer Email Address in a string
strTo = myItem.To
strTo = Replace(strTo, "'", "")
cnn.Open "Provider=SQLOLEDB;Data Source=my-srv;Initial Catalog=DB;User ID=xxxx;Password=xyz;"
'SQL Statement
rsSQL = "SELECT TOP 1 [c].[B#] AS [Branch], p.[PolRef#] AS [Ref] FROM [dbo].[ic_yyclient] AS c" & _
" INNER JOIN [dbo].[ic_brpolicy] AS p ON [c].[B#] = [p].[B#] AND [c].[Ref#] = [p].[Ref#]" & _
" LEFT OUTER JOIN [dbo].[ic_BD_ATS1] AS ats1 ON [p].[B#] = [ats1].[B#] AND [p].[PolRef#] = [ats1].[PolRef#]" & _
" WHERE [Ptype] IN ('PC','TW') AND (c.[Email] = '" & strTo & "' OR ats1.[Email] = '" & strTo & "' OR ats1.[Parents_email] = '" & strTo & "') AND [Term_code] IS NULL" & _
" ORDER BY [ats1].[PolRef#] desc"
Debug.Print rsSQL
rs.Open rsSQL, cnn, adOpenForwardOnly
With rs
While Not .EOF
strBranch = !Branch
strPolRef = !Ref
.MoveNext
Wend
End With
strSubject = "REF: 0" & strBranch & "-" & strPolRef & "-C<Email To Client>NB Documentation Email"
myItem.Subject = strSubject
myItem.Save
rs.Close
Set rs = Nothing
Set cnn = Nothing
End Sub

Related

I keep getting error 3061 Too few parameters. Expected 1

I have tried adding brackets to my stated parameters to show that they are separate but I still get the error, I checked all the "&" but to no avail.
Here is the code. Thanks in advance.
Option Compare Database
Public Function SendMail()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim emailTo As String
Dim emailSubject As String
Dim emailText As String
Dim outApp As Outlook.Application
Dim outMail As Outlook.MailItem
Dim outlookStarted As Boolean
On Error Resume Next
Set outApp = GetObject("Outlook.Application")
On Error GoTo 0
If outApp Is Nothing Then
Set outApp = CreateObject("Outlook.Application")
outlookStarted = True
End If
Set db = CurrentDb
strSQL = "SELECT DATE, COMPANY, CUSTOMER, EMAIL, FUP, [SAMPLES
REQUESTED]" & _
" FROM Sample Query WHERE DATE = Date()"
Set rs = db.OpenRecordset(strSQL, dbOpenDynaset)
Do Until rs.EOF
emailTo = rs.Fields("EMAIL").Value
emailSubject = "Proposal Follow Up"
If IsNull(rs.Fields("COMPANY").Value) Then
emailSubject = emailSubject & " for " & _
rs.Fields("COMPANY").Value & " " &
rs.Fields("CUSTOMER").Value
End If
emailText = Trim("Hello " & rs.Fields("COMPANY").Value) & "!" & vbCrLf
emailText = emailText & _
"Hello, " & rs.Fields("Name").Value & _
rs.Fields("CUSTOMER").Value & " ordered " & rs.Fields("SAMPLES
REQUESTED").Value & _
" on " & rs.Fields("Date").Value & " its been about a month. A
follow up would be good about now."
Set outMail = outApp.CreateItem(olMailItem)
outMail.To = emailTo
outMail.Subject = emailSubject
outMail.Body = emailText
outMail.Send
rs.Edit
rs("FUP") = Now()
rs.Update
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
If outlookStarted Then
outApp.Quit
End If
Set outMail = Nothing
Set outApp = Nothing
End Function
You miss brackets around the reserved word Date:
strSQL = "SELECT [DATE], COMPANY, CUSTOMER, EMAIL, FUP, [SAMPLES REQUESTED]" & _
" FROM [Sample Query] WHERE [DATE] = Date()"
Date is a protected word in Access. If you need to use that exact field name, put it in brackets like Gustav suggests. You can also rename the field, like TheDate or DateStart.
Here's a full list of protected words:
https://support.microsoft.com/en-us/help/286335/list-of-reserved-words-in-access-2002-and-in-later-versions-of-access

VBA macro save SQL query in a csv file

I am working on a VBA macro which connects to my database on SQL Server and run some queries and save the results on CSV files... it works fine just when the queries returns data but i have days where the query doesn't return any results, just an empty table. I made a temporary solution based on checking the date and according it the macro runs that query or no... I want to make it other way now in my code so that i don't need to change the date everytime manually...
I tried these solutions :
If (objMyRecordset.EOF = False) Or (objMyRecordset.BOF = False) Then
Also this
If objMyRecordset.RecordCount <> 0 Then
but the problem is my Recordset is empty because the query doesn't return any rows so it shows me error in objMyRecordset.Open
I want to add a line of code like this for example :
'// Pseudo Code
If (the query doesn't return result) Then
( just the headers will be save on my file )
Else
(do the rest of my code)
End If
Here is my code. Any suggestions please ? Thank you very much.
Sub Load_after_cutoff_queryCSV()
Dim objMyConn As ADODB.Connection
Dim objMyCmd As ADODB.Command
Dim objMyRecordset As ADODB.Recordset
Dim fields As String
Dim i As Integer
Set objMyConn = New ADODB.Connection
Set objMyCmd = New ADODB.Command
Set objMyRecordset = New ADODB.Recordset
'Open Connection
objMyConn.ConnectionString = "Provider=SQLOLEDB;Data Source=*****;User ID=*****;Password=*****;"
objMyConn.Open
'Set and Excecute SQL Command
Set objMyCmd.ActiveConnection = objMyConn
objMyCmd.CommandText = "SELECT * FROM [vw_X86_LOAD_AFTER_CUTOFF_REPORT_GAMMA]"
objMyCmd.CommandType = adCmdText
'Open Recordset
Set objMyRecordset.Source = objMyCmd
objMyRecordset.Open
Workbooks.Open Filename:="C:\Reports\load_after_cutoff_postGamma.csv"
Workbooks("load_after_cutoff_postGamma.csv").Sheets("load_after_cutoff_postGamma").Activate
ActiveSheet.Range("A2").CopyFromRecordset objMyRecordset
For i = 0 To objMyRecordset.fields.Count - 1
Worksheets("load_after_cutoff_postGamma").Cells(1, i + 1) = objMyRecordset.fields(i).name
Next i
Workbooks("load_after_cutoff_postGamma.csv").Sheets("load_after_cutoff_postGamma").Cells.EntireColumn.AutoFit
Workbooks("load_after_cutoff_postGamma.csv").Close SaveChanges:=True
MsgBox "Your file has been saved as load_after_cutoff_postGamma.csv"
If you experience problems connecting to your server then this is due to any of the following:
an incorrect connection string
incorrect credentials
the server is not reachable (for example: network cable disconnected)
the server is not up and running
Sending a query to a server which results in an empty recordset is not a reason for an ADODB.Connection to fail.
Here is a little bit of code for you to try and debug the connection in a first step and then the query in a second step:
Option Explicit
Public Sub tmpSO()
Dim strSQL As String
Dim strServer As String
Dim strDatabase As String
Dim OutMail As Outlook.MailItem
Dim rstResult As ADODB.Recordset
Dim conServer As ADODB.Connection
Dim OutApp As Outlook.Application
strServer = "."
strDatabase = "master"
Set conServer = New ADODB.Connection
conServer.ConnectionString = "PROVIDER=SQLOLEDB; " _
& "DATA SOURCE=" & strServer & ";" _
& "INITIAL CATALOG=" & strDatabase & ";" _
& "User ID='UserNameWrappedInSingleQuotes'; " _
& "Password='PasswordWrappedInSingleQuotes'; "
On Error GoTo SQL_ConnectionError
conServer.Open
On Error GoTo 0
strSQL = "set nocount on; "
strSQL = strSQL & "select * "
strSQL = strSQL & "from sys.tables as t "
strSQL = strSQL & "where t.name = ''; "
Set rstResult = New ADODB.Recordset
rstResult.ActiveConnection = conServer
On Error GoTo SQL_StatementError
rstResult.Open strSQL
On Error GoTo 0
If Not rstResult.EOF And Not rstResult.BOF Then
ThisWorkbook.Worksheets(1).Range("A1").CopyFromRecordset rstResult
' While Not rstResult.EOF And Not rstResult.BOF
' 'do something
' rstResult.MoveNext
' Wend
Else
'https://msdn.microsoft.com/en-us/library/windows/desktop/ms675546(v=vs.85).aspx
Select Case conServer.State
'adStateClosed
Case 0
MsgBox "The connection to the server is closed."
'adStateOpen
Case 1
MsgBox "The connection is open but the query did not return any data."
'adStateConnecting
Case 2
MsgBox "Connecting..."
'adStateExecuting
Case 4
MsgBox "Executing..."
'adStateFetching
Case 8
MsgBox "Fetching..."
Case Else
MsgBox conServer.State
End Select
End If
Set rstResult = Nothing
Exit Sub
SQL_ConnectionError:
MsgBox "Couldn't connect to the server. Please make sure that you have a working connection to the server."
Set OutApp = New Outlook.Application
Set OutMail = OutApp.CreateItem(0)
With OutMail
.Subject = "Problems connecting to database '" & strDatabase & "' hosted on the server '" & strServer & "'"
.HTMLBody = "<span style=""font-size:10px"">---Automatically generated Error-Email---" & _
"</span><br><br>Error report from the file '" & _
"<span style=""color:blue"">" & ThisWorkbook.Name & _
"</span>' located and saved on '<span style=""color:blue"">" & _
ThisWorkbook.Path & "</span>'.<br>" & _
"Excel is not able to establish a connection to the server. Technical data to follow." & "<br><br>" & _
"Computer Name: <span style=""color:green;"">" & Environ("COMPUTERNAME") & "</span><br>" & _
"Logged in as: <span style=""color:green;"">" & Environ("USERDOMAIN") & "/" & Environ("USERNAME") & "</span><br>" & _
"Domain Server: <span style=""color:green;"">" & Environ("LOGONSERVER") & "</span><br>" & _
"User DNS Domain: <span style=""color:green;"">" & Environ("USERDNSDOMAIN") & "</span><br>" & _
"Operating System: <span style=""color:green;"">" & Environ("OS") & "</span><br>" & _
"Excel Version: <span style=""color:green;"">" & Application.Version & "</span><br>" & _
"<br><span style=""font-size:10px""><br>" & _
"<br><br>---Automatically generated Error-Email---"
.Display
End With
Set OutMail = Nothing
Set OutApp = Nothing
Exit Sub
SQL_StatementError:
MsgBox "There seems to be a problem with the SQL Syntax in the programming."
Set OutApp = New Outlook.Application
Set OutMail = OutApp.CreateItem(0)
With OutMail
.Subject = "Problems with the SQL Syntax in file '" & ThisWorkbook.Name & "'."
.HTMLBody = "<span style=""font-size:10px"">" & _
"---Automatically generated Error-Email---" & _
"</span><br><br>" & _
"Error report from the file '" & _
"<span style=""color:blue"">" & _
ActiveWorkbook.Name & _
"</span>" & _
"' located and saved on '" & _
"<span style=""color:blue"">" & _
ActiveWorkbook.Path & _
"</span>" & _
"'.<br>" & _
"It seems that there is a problem with the SQL-Code within trying to upload an extract to the server." & _
"SQL-Code causing the problems:" & _
"<br><br><span style=""color:green;"">" & _
strSQL & _
"</span><br><br><span style=""font-size:10px"">" & _
"---Automatically generated Error-Email---"
.Display
End With
Set OutMail = Nothing
Set OutApp = Nothing
Exit Sub
End Sub
Note, that the above code clearly distinguishes between (first) connecting to the server and then (afterwards) issuing a query to the server to retrieve some data. Both steps are separated and there is a different error handler for either case.
Furthermore, the above sample code also results in an empty recordset being returned. But the code is able to handle that incident with yet another error handler.
If the connection fails or if the SQL syntax being sent to the server contains error(s) then the above code will automatically generate an error email (using Outlook) with some details for you to check the connection and the SQL syntax.
you should go with your .EOF solution. Here is an example of mine, which I use regularly.
Sub AnySub()
''recordsets
Dim rec as ADODB.Recordset
''build your query here
sSql = "SELECT * FROM mytable where 1=0" ''just to have no results
''Fire query
Set rec = GetRecordset(sSql, mycnxnstring)
''and then loop throug your results, if there are any
While rec.EOF = False
''do something with rec()
rec.MoveNext
Wend
End sub
Here the Function GetRecordset() is given by:
Function GetRecordset(strQuery As String, connstring As String) As Recordset
Dim DB As ADODB.Connection
Dim rs As ADODB.Recordset
Set DB = New ADODB.Connection
With DB
.CommandTimeout = 300
.ConnectionString = connstring
.Open
End With
Set GetRecordset = DB.Execute(strQuery)
End Function
Hope this helps.

Syntax error in dynamic SQL string

Please help to fix the following syntax error with Like statement. The query works with = but I need to use Like to search in the AAchange field. I think the problem is here "WHERE [AAchange] LIKE '" & "%" & _
but I'm not sure how to correct this syntax. Please see the code below:
Sub ColorNewVariant()
Dim PolicyNum As Variant
Dim bFound As Boolean
Dim cnn As ADODB.Connection 'dim the ADO collection class
Dim rs As ADODB.Recordset 'dim the ADO recordset class
Dim dbPath As String
Dim strSQL As String
Dim r As Range, cell As Range
Dim LastRow As Long
LastRow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
Application.EnableEvents = False
Set r = ThisWorkbook.ActiveSheet.Range("G3:G" & LastRow)
For Each cell In r
If cell.Value <> "" Then
PolicyNum = cell.Value
dbPath = PATH_MAIN & "\Report\MDL_IonTorrent.accdb"
Set cnn = New ADODB.Connection ' Initialise the collection class variable
'Connection class is equipped with a -method- Named Open
'--4 aguments-- ConnectionString, UserID, Password, Options
'ConnectionString formula--Key1=Value1;Key2=Value2;Key_n=Value_n;
cnn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dbPath
strSQL = "SELECT [AAchange] " & _
"FROM [MDL_Table1] " & _
"WHERE [AAchange] LIKE '" & "%" & _
Replace(PolicyNum, """", """""", , , vbTextCompare) & _
""""
'Create the ADODB recordset object.
Set rs = New ADODB.Recordset 'assign memory to the recordset
'ConnectionString Open '--5 aguments--
'Source, ActiveConnection, CursorType, LockType, Options
rs.Open strSQL, cnn
bFound = Not rs.EOF
'Check if the recordset is empty.
'Close the recordet and the connection.
rs.Close
cnn.Close
'clear memory
Set rs = Nothing
Set cnn = Nothing
'Enable the screen.
If bFound Then
'MsgBox "Record exists."
Else
'MsgBox "Record not found."
'cell.Interior.ColorIndex = 8
cell.Interior.Color = RGB(255, 217, 218)
'cell.ClearComments
'cell.AddComment "New Variant"
'Fits shape around text
'cell.Comment.Shape.TextFrame.AutoSize = True
End If
End If
Next cell
Application.EnableEvents = True
End Sub
Change the quoting in your query's WHERE clause.
If you use single quotes to start and end the string value you build, you needn't bother with Replace() of double quotes within the PolicyNum value. That should make this task simpler and less confusing ...
strSQL = "SELECT [AAchange] " & _
"FROM [MDL_Table1] " & _
"WHERE [AAchange] LIKE '%" & PolicyNum & "'"
Debug.Print strSQL

VBA Moving MailItem after Subject Line Change

I have a query below, I am trying to amend the Subject Line of an incoming email and then move it to a Folder within the Mailbox (Not the Inbox).
I need to do this because an external program watches this folder and files the emails accordingly.
I can find plenty on how to move an Item systematically externally, or moving an object within an Inbox Sub Folder but not a folder under the main 'Mailbox'.
Can anyone shed any light for me please, bear in mind this runs as a 'Run As Script' when the mail comes in.
Sub AmendSubject(myItem As Outlook.MailItem)
Dim strBranch As String
Dim strPolRef As String
Dim strTo As String
Dim cnn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim rsSQL As String
Dim objNS As Outlook.NameSpace
'Set objNS = Application.GetNamespace("MAPI")
'Set myInbox = objNS.GetDefaultFolder(olFolderInbox)
Dim strSubject As String
Set cnn = New ADODB.Connection
Set rs = New ADODB.Recordset
'Places the Customer Email Address in a string
strTo = myItem.To
strTo = Replace(strTo, "'", "")
cnn.Open "Provider=SQLOLEDB;Data Source=xxx;Initial Catalog=xxxx;User ID=xxxxx;Password=xxx;"
'SQL Statement
rsSQL = "SELECT TOP 1 [c].[B#] AS [Branch], p.[PolRef#] AS [Ref] FROM [dbo].[ic_yyclient] AS c" & _
" INNER JOIN [dbo].[ic_brpolicy] AS p ON [c].[B#] = [p].[B#] AND [c].[Ref#] = [p].[Ref#]" & _
" LEFT OUTER JOIN [dbo].[ic_BD_ATS1] AS ats1 ON [p].[B#] = [ats1].[B#] AND [p].[PolRef#] = [ats1].[PolRef#]" & _
" WHERE [Ptype] IN ('PC','TW') AND (c.[Email] = '" & strTo & "' OR ats1.[Email] = '" & strTo & "' OR ats1.[p_email] = '" & strTo & "') AND [Term_code] IS NULL" & _
" ORDER BY [ats1].[PolRef#] desc"
Debug.Print rsSQL
rs.Open rsSQL, cnn, adOpenForwardOnly
With rs
While Not .EOF
strBranch = !Branch
strPolRef = !Ref
.MoveNext
Wend
End With
strSubject = "REF: 0" & strBranch & "-" & strPolRef & "-C<Email To Client>NB Documentation Email"
'myItem.Display
myItem.Subject = strSubject
myItem.Save
rs.Close
'myItem.Move fldrOAtt
Set rs = Nothing
Set cnn = Nothing
End Sub
If the folder is on the same level as the Inbox, retrieve its parent, then go down one level:
set subfolder = myInbox.Parent.Folders.Item("the folder name")

How to read XML into an ADODB.Stream object from the output of a SQL stored procedure that execs query FOR XML Auto

I have a stored procedure that returns a recordset (one column that has an XSLT stored in it) and an XML document.
The query is basically:
SELECT abc, 123
FROM TABLE_A
FOR XML AUTO
I need to call the stored procedure from a VBA application, presumably using ADO. I only found a couple examples doing a google search and none seemed to work.
Here's my "code":
Dim oConn As New ADODB.Connection
Dim oRS As New ADODB.Recordset
Dim oStream As New ADODB.Stream
Dim xml As MSXML2.DOMDocument60
Dim strXSLT As String
Dim strXML As String
Dim oFSO As New FileSystemObject
Dim TS As TextStream
oConn.ConnectionString = "Provider='sqloledb';Data Source='[myServer]';" & _
"Initial Catalog='[myDB]';Integrated Security='SSPI';"
oConn.Open
Set oRS = oConn.Execute("exec dbo.sp_mySproc #Person ='" & gStrUserID & "', #Dash='Main'")
If Not (oRS.BOF And oRS.EOF) Then
Set TS = oFSO.CreateTextFile("M:\Desktop\testMain.XSL", True)
TS.Write oRS(0).Value
TS.Close
Set oRS = oRS.NextRecordset
xml.loadXML oRS.Fields(oRS.Fields(0).Name)
Set pi = xml.createProcessingInstruction("xml", _
"version=""1.0"" encoding=""" & rst.Fields("XMLEncoding") & """")
xml.insertBefore pi, xml.firstChild
xml.Save "M:\Desktop\testMain.XML"
Set TS = oFSO.CreateTextFile("M:\Desktop\testMain.XML", True)
TS.Write "<?xml version=" & Chr(22) & "1.0" & Chr(22) & "?>" & vbCrLf & "<?xml-stylesheet type=" & Chr(22) & "text/xsl" & Chr(22) & " href=" & Chr(22) & "testmain.xsl" & Chr(22) & "?>" & vbCrLf
TS.Write oStream.ReadText
TS.Close
Everything works fine in that it will execute the stored procedure, get the XSL from the recordset and save it to disk but dies miserably after I do the oRS.NextRecordset.
Actually my code has two different attempts to save the XML; using a TextStream and a DOMDocument60 (neither work). Any ideas would be appreciated...
Mike
After a lot of trial and error I found a solution:
Private Function GetXML(myConnection As ADODB.Connection, Sproc As String, XSLSuccess As Boolean, GUID As String, Optional Param2 As String = "") As Boolean
Dim sStreamQuery As New ADODB.Stream
Dim cmCmd As New ADODB.Command
Dim strQuery As String
Dim sResponseStream As New ADODB.Stream
Dim strXML As String
Dim oFSO As New FileSystemObject
Dim TS As TextStream
Set cmCmd.ActiveConnection = myConnection
' Set up the Template Query
strQuery = "<ROOT xmlns:sql='urn:schemas-microsoft-com:xml-sql'>"
strQuery = strQuery & "<sql:header>"
strQuery = strQuery & "<sql:param name='Param1'>" & gStrParam1 & "</sql:param>"
If gStrParam2 <> "" Then
strQuery = strQuery & "<sql:param name='Param2'>" & gStrParam2 & "</sql:param>"
End If
strQuery = strQuery & "</sql:header>"
strQuery = strQuery & "<sql:query >"
If gStrParam2 <> "" Then
strQuery = strQuery & "exec dbo." & Sproc & " #Param1, #Param2"
Else
strQuery = strQuery & "exec dbo." & Sproc & " #Param1"
End If
strQuery = strQuery & "</sql:query>"
strQuery = strQuery & "</ROOT>"
' Read the template query into the Stream
'Set sStreamQuery = New Stream
sStreamQuery.Open
sStreamQuery.WriteText strQuery, adWriteChar
sStreamQuery.Position = 0
' Associate the stream with the command and set the
' dialect to XML to interpret it
Set cmCmd.CommandStream = sStreamQuery
cmCmd.Dialect = "{5D531CB2-E6Ed-11D2-B252-00C04F681B71}"
' Create a stream to handle the response
sResponseStream.Open
' Can also be a response object in an ASP page
cmCmd.Properties("Output Stream") = sResponseStream
cmCmd.Execute , , adExecuteStream
strXML = Replace(sResponseStream.ReadText, "<ROOT xmlns:sql=" & Chr(34) & "urn:schemas-microsoft-com:xml-sql" & Chr(34) & ">", "", 1)
strXML = Replace(strXML, "</ROOT>", "", 1)
Set TS = oFSO.CreateTextFile(gstrPath & GUID & ".XML", True)
TS.Write "<?xml version=" & Chr(34) & "1.0" & Chr(34) & "?>" & vbCrLf
If XSLSuccess Then
TS.Write "<?xml-stylesheet type=" & Chr(34) & "text/xsl" & Chr(34) & " href=" & Chr(34) & GUID & ".xsl" & Chr(34) & "?>" & vbCrLf
End If
TS.Write strXML
TS.Close
Set TS = Nothing
Set oFSO = Nothing
sResponseStream.Close
sStreamQuery.Close
Set responseStream = Nothing
Set sStreamQuery = Nothing
Set cmCmd = Nothing
End Function