What is the best VB method to forward outlook emails attachments? - vba

I have an existing set of outlook vb codes that help me to forward emails but they do help to forward along with any attachments. any ideas how to include these attachments?
Private Const FORWARD_TO_EMAIL As String = "your_email#your_domain.com "
Private Const START_MESSAGE_HEADER As String = "--------StartMessageHeader--------"
Private Const END_MESSAGE_HEADER As String = "--------EndMessageHeader--------"
Private Const FROM_MESSAGE_HEADER As String = "From: "
Private Const DESKTOP_SWITCHDESKTOP As Long = &H100
Private Declare Sub LockWorkStation Lib "User32.dll" ()
Private Declare Function SwitchDesktop Lib "user32" (ByVal hDesktop As Long) As Long
Private Declare Function OpenDesktop Lib "user32" Alias "OpenDesktopA" _
(ByVal lpszDesktop As Any, _
ByVal dwFlags As Long, _
ByVal fInherit As Long, _
ByVal dwDesiredAccess As Long) As Long
Sub ForwardEmail(MyMail As MailItem)
On Error Goto EndSub
Dim strBody As String
Dim objMail As Outlook.MailItem
Dim MailItem As Outlook.MailItem
Set objMail = Application.Session.GetItemFromID(MyMail.EntryID)
' Initialize email to send
Set MailItem = Application.CreateItem(olMailItem)
MailItem.Subject = objMail.Subject
If (objMail.SenderEmailAddress <> FORWARD_TO_EMAIL) Then
' Only forward emails when the workstation is locked
If (Not IsWorkstationLocked()) Then
Return
End If
' Compose email and send it to your other email
strBody = START_MESSAGE_HEADER + Chr$(13) + _
FROM_MESSAGE_HEADER + objMail.SenderEmailAddress + Chr$(13) + _
"Name: " + objMail.SenderName + Chr$(13) + _
"To: " + objMail.To + Chr$(13) + _
"CC: " + objMail.CC + Chr$(13) + _
END_MESSAGE_HEADER + Chr$(13) + Chr$(13) + _
objMail.body
MailItem.Recipients.Add (FORWARD_TO_EMAIL)
' Do not keep email sent to your mobile account
MailItem.DeleteAfterSubmit = True
Else
' Parse the original mesage and reply to the sender
strBody = objMail.body
Dim posStartHeader As Integer
posStartHeader = InStr(strBody, START_MESSAGE_HEADER)
Dim posEndHeader As Integer
posEndHeader = InStr(strBody, END_MESSAGE_HEADER)
'Remove the message header from the body
strBody = Mid(strBody, 1, posStartHeader - 1) + _
Mid(strBody, posEndHeader + Len(END_MESSAGE_HEADER) + 4)
Dim originalEmailFrom As String
originalEmailFrom = GetOriginalFromEmail(posStartHeader, _
posEndHeader, objMail.body)
If (originalEmailFrom = "") Then
Return
End If
MailItem.Recipients.Add (originalEmailFrom)
' Delete email received from your mobile account
objMail.Delete
End If
' Send email
MailItem.body = strBody
MailItem.Send
' Set variables to null to prevent memory leaks
Set MailItem = Nothing
Set Recipient = Nothing
Set objMail = Nothing
Exit Sub
EndSub:
End Sub
Private Function GetOriginalFromEmail(posStartHeader As Integer, _
posEndHeader As Integer, strBody As String) As String
GetOriginalFromEmail = ""
If (posStartHeader < posEndHeader And posStartHeader > 0) Then
posStartHeader = posStartHeader + Len(START_MESSAGE_HEADER) + 1
Dim posFrom As Integer
posFrom = InStr(posStartHeader, strBody, FROM_MESSAGE_HEADER)
If (posFrom < posStartHeader) Then
Return
End If
posFrom = posFrom + Len(FROM_MESSAGE_HEADER)
Dim posReturn As Integer
posReturn = InStr(posFrom, strBody, Chr$(13))
If (posReturn > posFrom) Then
GetOriginalFromEmail = _
Mid(strBody, posFrom, posReturn - posFrom)
End If
End If
End Function
Private Function IsWorkstationLocked() As Boolean
IsWorkstationLocked = False
On Error Goto EndFunction
Dim p_lngHwnd As Long
Dim p_lngRtn As Long
Dim p_lngErr As Long
p_lngHwnd = OpenDesktop(lpszDesktop:="Default", _
dwFlags:=0, _
fInherit:=False, _
dwDesiredAccess:=DESKTOP_SWITCHDESKTOP)
If p_lngHwnd <> 0 Then
p_lngRtn = SwitchDesktop(hDesktop:=p_lngHwnd)
p_lngErr = Err.LastDllError
If p_lngRtn = 0 Then
If p_lngErr = 0 Then
IsWorkstationLocked = True
End If
End If
End If
EndFunction:
End Function

I think this is what you are looking for.
Set MailItem.Attachments = objMail.Attachments
Or better yet, why rebuild the whole mail object at all:
Set MailItem = objMail.Forward()
MailItem.Recipients.Add(FORWARD_TO_EMAIL)
MailItem.Send()

Related

Run code upon application startup, but after client rules are processed

I have a VBA script that needs to run upon application startup, but after client rules are processed.
I did what was suggested here:
How can I tell when Rules have finished processing?
I added the executing of all rules in Outlook before the rest of the script runs. It did not solve my issue. My script only can process new emails that are in the inbox, not ones that have a rule applied to them. The AdvancedSearch method does not pick them up, even after adding the rule execution lines before.
Option Explicit
Public blnSearchComp As Boolean
Private Sub Application_AdvancedSearchComplete(ByVal SearchObject As Search)
Debug.Print "The AdvancedSearchComplete Event fired"
If SearchObject.Tag = "Process_New_Items" Then
'm_SearchComplete = True` ' Use Option Explicit.
blnSearchComp = True
End If
End Sub
Private Sub Application_Startup()
Dim dmi As MailItem
Dim timeFol As Folder
Dim timeFilter As String
Dim lastclose As String
Dim utcdate As Date
Dim strFilter As String
Dim i As Object
Dim strScope As String
Dim SearchObject As Search
'----------------------------------------------------------------------
Dim olRules As Outlook.Rules
Dim myRule As Outlook.Rule
Set olRules = Application.Session.DefaultStore.GetRules()
For Each myRule In olRules
' Rules we want to run
myRule.Execute
Next
'----------------------------------------------------------------------
Set dmi = CreateItem(olMailItem)
Set timeFol = Session.GetDefaultFolder(olFolderNotes)
timeFilter = "[Subject] = 'App Close Time'"
For Each i In timeFol.Items.Restrict(timeFilter)
lastclose = i.CreationTime
Next i
Debug.Print lastclose
utcdate = dmi.PropertyAccessor.LocalTimeToUTC(lastclose)
'strFilter = "#SQL=""urn:schemas:httpmail:datereceived"" >= '" & Format(utcdate, "dd mmm yyyy hh:mm") & "'"
strFilter = "urn:schemas:httpmail:datereceived >= " & "'" & utcdate & "'"
Debug.Print strFilter
'strScope = "'" & Session.Folders(1).Folders("Inbox") & "'"
Debug.Print strScope
'strScope = "'" & Session.GetDefaultFolder(olFolderInbox) & "'"
Debug.Print strScope
strScope = "'Inbox'"
Debug.Print strScope
'strScope = "'" & Application.Session.GetDefaultFolder(olFolderInbox).FolderPath & "'"
'Sleep (20)
Set SearchObject = AdvancedSearch(Scope:=strScope, Filter:=strFilter, SearchSubFolders:=True, Tag:="Process_New_Items")
blnSearchComp = False
' Otherwise remains True.
' Search would work once until Outlook restarted.
While blnSearchComp = False
DoEvents
' Code should be in a class module such as ThisOutlookSession
Debug.Print "Wait a few seconds. Ctrl + Break if needed."
Wend
Debug.Print "SearchObject.results.count: " & SearchObject.Results.Count
For Each i In SearchObject.Results
If TypeName(i) = "MailItem" Then
Process_MailItem i
Debug.Print i.ReceivedTime, i.Subject
Else: End If
Next i
End Sub
You can use built-in Windows mechanisms via Windows API functions like SetTimer to set up a timer in VBA, see How to make safe API Timers in VBA? and Outlook VBA - Run a code every half an hour for more information. For example:
Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerfunc As Long) As Long
Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
Public TimerID As Long 'Need a timer ID to eventually turn off the timer. If the timer ID <> 0 then the timer is running
Public Sub ActivateTimer(ByVal nMinutes As Long)
nMinutes = nMinutes * 1000 * 60 'The SetTimer call accepts milliseconds, so convert to minutes
If TimerID <> 0 Then Call DeactivateTimer 'Check to see if timer is running before call to SetTimer
TimerID = SetTimer(0, 0, nMinutes, AddressOf TriggerTimer)
If TimerID = 0 Then
MsgBox "The timer failed to activate."
End If
End Sub
Public Sub DeactivateTimer()
Dim lSuccess As Long
lSuccess = KillTimer(0, TimerID)
If lSuccess = 0 Then
MsgBox "The timer failed to deactivate."
Else
TimerID = 0
End If
End Sub
Public Sub TriggerTimer(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idevent As Long, ByVal Systime As Long)
MsgBox "The TriggerTimer function has been automatically called!"
End Sub

Access VBA to delete a file to the recycle bin?

Using the following code delete's my file, but it doesn't go to the recycle bin - does code exist that will send it to the recycle bin? Should I use ".Move" ?
If MsgBox("DELETE:" & Chr(10) & Forms("frmtbl").f_FullPath & Me.f_FileName & " ?", vbYesNo) = vbYes Then
'Kill Forms("frmtbl").f_FullPath & Me.f_FileName
Dim objFSO As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.DeleteFile (Forms("frmtbl").f_FullPath & Me.f_FileName)
DoCmd.Close acForm, Me.Name
Else
MsgBox "FILE NOT DELETED:" & Chr(10) & Forms("frmtbl").f_FullPath & Me.f_FileName & ".", vbInformation,
End If
.MoveFile to the recycle bin requires permissions I don't have.
An integrated VBA-method seems not to exist. API call is needed.
Following code is copied from reddit. (solution by "Crushnaut")
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Windows API functions, constants,and types.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Declare PtrSafe Function SHFileOperation Lib "shell32.dll" Alias _
"SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) As LongPtr
Private Const FO_DELETE = &H3
Private Const FOF_ALLOWUNDO = &H40
Private Const FOF_NOCONFIRMATION = &H10
Private Type SHFILEOPSTRUCT
hwnd As LongPtr
wFunc As LongPtr
pFrom As String
pTo As String
fFlags As Integer
fAnyOperationsAborted As Boolean
hNameMappings As LongPtr
lpszProgressTitle As String
End Type
Public Function Recycle(FileSpec As String, Optional ErrText As String) As Boolean
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Recycle
' This function sends FileSpec to the Recycle Bin. There
' are no restriction on what can be recycled. FileSpec
' must be a fully qualified folder or file name on the
' local machine.
' The function returns True if successful or False if
' an error occurs. If an error occurs, the reason for the
' error is placed in the ErrText varaible.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim SHFileOp As SHFILEOPSTRUCT
Dim Res As LongPtr
Dim sFileSpec As String
ErrText = vbNullString
sFileSpec = FileSpec
If InStr(1, FileSpec, ":", vbBinaryCompare) = 0 Then
''''''''''''''''''''''''''''''''''''''
' Not a fully qualified name. Get out.
''''''''''''''''''''''''''''''''''''''
ErrText = "'" & FileSpec & "' is not a fully qualified name on the local machine"
Recycle = False
Exit Function
End If
If Dir(FileSpec, vbDirectory) = vbNullString Then
ErrText = "'" & FileSpec & "' does not exist"
Recycle = False
Exit Function
End If
''''''''''''''''''''''''''''''''''''
' Remove trailing '\' if required.
''''''''''''''''''''''''''''''''''''
If Right(sFileSpec, 1) = "\" Then
sFileSpec = Left(sFileSpec, Len(sFileSpec) - 1)
End If
With SHFileOp
.wFunc = FO_DELETE
.pFrom = sFileSpec
.fFlags = FOF_ALLOWUNDO
'''''''''''''''''''''''''''''''''
' If you want to supress the
' "Are you sure?" message, use
' the following:
'''''''''''''''''''''''''''''''
.fFlags = FOF_ALLOWUNDO + FOF_NOCONFIRMATION
End With
Res = SHFileOperation(SHFileOp)
If Res = 0 Then
Recycle = True
Else
Recycle = False
End If
End Function

VBA create log file

Hello can you help me please with code in VBA ? I would like create a log file from text in cells ("C2" and "C3 " + date and time ) when I press button "zadat" Thank you
My code for implementation is:
Module 1
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub zadat()
Dim reg, check As String
Dim i, j, done As Integer
reg = Cells(2, 3).Value
check = Cells(4, 3).Value
If check = "True" Then
i = 2
j = 1
done = 0
Do While Sheets("data").Cells(i, j) <> ""
If Sheets("data").Cells(i, j) = reg Then
vytisteno = ZkontrolovatAVytiskoutSoubor()
done = Sheets("data").Cells(i, j + 3)
done = done + 1
Sheets("data").Cells(i, j + 3) = done
Exit Do
End If
i = i + 1
Loop
Else
MsgBox ("Opravit, špatný štítek!!!")
End If
Cells(3, 3) = ""
Cells(3, 3).Select
ActiveWindow.ScrollRow = Cells(1, 1).row
End Sub
Module 2:
Option Explicit
Public Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _
ByVal hwnd As Long, _
ByVal lpOperation As String, _
ByVal lpFile As String, _
ByVal lpParameters As String, _
ByVal lpDirectory As String, _
ByVal nShowCmd As Long) As Long
Public Function PrintThisDoc(formname As Long, FileName As String)
On Error Resume Next
Dim x As Long
x = ShellExecute(formname, "Print", FileName, 0&, 0&, 3)
End Function
Public Function ZkontrolovatAVytiskoutSoubor() As Boolean
Dim printThis
Dim strDir As String
Dim strFile As String
strDir = "W:\Etikety\Štítky\Krabice\Testy"
strFile = Range("C2").Value & ".lbe"
If Not FileExists(strDir & "\" & strFile) Then
MsgBox "soubor neexistuje!"
ZkontrolovatAVytiskoutSoubor = False
Else
printThis = PrintThisDoc(0, strDir & "\" & strFile)
ZkontrolovatAVytiskoutSoubor = True
End If
End Function
Private Function FileExists(fname) As Boolean
'Returns TRUE if the file exists
Dim x As String
x = Dir(fname)
If x <> "" Then FileExists = True _
Else FileExists = False
End Function
If you don't want to use FSO, there is a simple solution using only VBA statements: Open, Print # and Close:
Sub Log2File(Filename As String, Cell1, Cell2)
Dim f As Integer
f = FreeFile
Open Filename For Append Access Write Lock Write As #f
Print #f, Now, Cell1, Cell2
Close #f
End Sub
I've put the filename and the cells refs as arguments of the sub for re-usability purpose. I also use default (local) formatting, but this can be easily changed.
Note that you don't have to check for existence of the file, it will be created if it doesn't exist.
Try this. Below code will create a new log file every time
Public Function LogDetails()
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim logFile As Object
Dim logFilePath As String
Dim logFileName As String
'Replace 'TestLog' with your desired file name
logFileName = "TestLog" & ".txt"
myFilePath = "C:\Users\..\Desktop\" & logFileName 'Modify the path here
If fso.FileExists(myFilePath) Then
Set logFile = fso.OpenTextFile(myFilePath, 8)
Else
' create the file instead
Set logFile = fso.CreateTextFile(myFilePath, True)
End If
logFile.WriteLine "[" & Date & " " & Time & "] " & Worksheet("yoursheetnamehere").Cells(2, 3) & " " & Worksheet("yoursheetnamehere").Cells(3, 3)
logFile.Close ' close the file
End Function

How do I program the command button to change the document format before attaching to an email?

Situation: I am trying to create a form that will automatically attach itself to an email when clicking the Submit button, but once the submit button is clicked, the macros are removed from the document.
Background: I have been able to create a code that will allow me to attach the document to an email; however, when the document attaches to the email, it still contains macros.
Here is the code I have so far:
Public newfilename As String
Private Declare Function GetTempPath Lib "kernel32" _
Alias "GetTempPathA" _
(ByVal nBufferLength As Long, _
ByVal lpBuffer As String) As Long
Private Declare Function GetTempFileName Lib "kernel32" _
Alias "GetTempFileNameA" _
(ByVal lpszPath As String, _
ByVal lpPrefixString As String, _
ByVal wUnique As Long, _
ByVal lpTempFileName As String) As Long
Public Function Get_Temp_File_Name( _
Optional sPrefix As String = "VBA", _
Optional sExtensao As String = "") As String
Dim sTmpPath As String * 512
Dim sTmpName As String * 576
Dim nRet As Long
Dim F As String
nRet = GetTempPath(512, sTmpPath)
If (nRet > 0 And nRet < 512) Then
nRet = GetTempFileName(sTmpPath, sPrefix, 0, sTmpName)
If nRet <> 0 Then F = Left$(sTmpName, InStr(sTmpName, vbNullChar) - 1)
If sExtensao > "" Then
Kill F
If Right(F, 4) = ".tmp" Then F = Left(F, Len(F) - 4)
F = F & sExtensao
End If
Get_Temp_File_Name = F
End If
End Function
Public Function Get_File_Name( _
Optional sPrefix As String = "VBA", _
Optional sFilename As String = "") As String
Dim sTmpPath As String * 512
Dim sTmpName As String * 576
Dim nRet As Long
Dim F As String
nRet = GetTempPath(512, sTmpPath)
a = Len(nRet)
F = Left$(sTmpPath, InStr(sTmpPath, vbNullChar) - 1)
Get_File_Name = F + sFilename
Debug.Print F
End Function
Private Sub CommandButton1_Click()
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
ActiveDocument.SaveAs2 (newfilename)
On Error Resume Next
With OutMail
.to = "me#me.com"
.CC = ""
.BCC = ""
.Subject = "Communication with Government Regulatory Agency Report"
.Body = "Attached is the Communication with Government Regulatory Agency report for the following location:"
.Attachments.Add ActiveDocument.FullName
'You can add other files also like this
'.Attachments.Add ("C:\test.txt")
.Display 'or use .Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Private Sub Document_Open()
newfilename = Get_File_Name("", "Communication with Government Regulatory Agency Report")
ActiveDocument.SaveAs2 (newfilename)
End Sub
Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, _
ByVal Shift As Integer)
If KeyCode = 13 Then
KeyCode = 0
TextBox1.Text = TextBox1.Text & vbCrLf & "• "
End If
End Sub
Private Sub TextBox2_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, _
ByVal Shift As Integer)
If KeyCode = 13 Then
KeyCode = 0
TextBox1.Text = TextBox1.Text & vbCrLf & "• "
End If
End Sub
I have tried to code for making the command button invisible when clicked, and removing macros when command button is invisible and I have tried to code for changing the format of the document before it saves to the email, but neither solution worked. I am stuck, and as long as the document has active macros when attaching to the email, I cannot publish the form. Any assistance would be greatly appreciated!

Excel VBA email creation, setting focus back to input box

the code below is creating an email, whilst searching through folders and attaching the relevant docs.
I have coded it to check whether the user has sent the email or closed it. I have put it so an input box gets displayed when the user closes the email. What i would like to happen is when the email gets closed, is the InputBox is set to focus, and after a reason why the email was sent have been entered then go back to the email to click on don't save draft.
Or even have the input box display after the email has been closed, after the save without changed dialog box.
Userform Code:
Dim OutApp As Object
Dim itmevt As New CMailItemEvents
Private Sub btnEMSent_Click()
Dim i, j, lastG, lastD As Long
Dim OutMail As Object
Dim sFName As String, colFiles As New Collection
Dim myDir As String, ChDir As String, attName As New Collection, attName2 As String
Dim dte As String
Dim greet As String, cntName As String, SigString As String, Signature As String
lastG = Sheets("File Locations").Cells(Rows.Count, "B").End(xlUp).Row
SigString = "H:\AppData\Roaming\Microsoft\Signatures\"
If Dir(SigString, vbDirectory) <> vbNullString Then
SigString = SigString & Dir$(SigString & "*.htm")
Else:
SigString = ""
End If
Signature = CreateObject("Scripting.FileSystemObject").GetFile(SigString).OpenAsTextStream(1, -2).readall
If Me.cmbMonth.Value = "" Then
Me.lblErrorMsg.Visible = True
Me.lblErrorMsg.Caption = "Payment Month Required!"
Me.cmbMonth.SetFocus
Exit Sub
ElseIf Me.txtbxYear.Value = "" Then
Me.lblErrorMsg.Visible = True
Me.lblErrorMsg.Caption = "Payment Year Required!"
Me.txtbxYear.SetFocus
Exit Sub
ElseIf Me.cmbSubbie.Value = "" Then
Me.lblErrorMsg.Visible = True
Me.lblErrorMsg.Caption = "Sub-Contractor Required!"
Me.cmbSubbie.SetFocus
Exit Sub
End If
For i = 1 To lastG
lookupVal = Sheets("File Locations").Cells(i, "B") ' value to find
If Dir(lookupVal, vbDirectory) = "" Then
Else
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
Set itmevt.itm = OutMail
dte = Me.cmbMonth.Value & " " & Me.txtbxYear.Text
myDir = lookupVal 'Set Dir to search
ChDir = (myDir & "\" & Me.cmbSubbie.Value & "\Remittance\") 'Change to that dir
sFName = Dir(ChDir & "*" & dte & "*") 'Set Search spec
While InStr(sFName, dte)
colFiles.Add (ChDir & sFName)
attName.Add (sFName)
sFName = Dir
Wend
End If
Next i
On Error Resume Next
With OutMail
If Me.txtbxSubNAME.Value <> "" Then
cntName = " " & Me.txtbxSubNAME.Value & ","
Else
cntName = ","
End If
If Time < TimeValue("12:00:00") Then
greet = "Good Morning" & cntName
Else
greet = "Good Afternoon" & cntName
End If
If colFiles.Count > 0 Then
For i = 1 To colFiles.Count
.Attachments.Add colFiles(i)
attName2 = attName(i) & "<br>" & attName2
Next i
End If
.To = Me.txtbxSubEMAIL.Value
.CC = ""
.BCC = ""
.Subject = Me.cmbMonth.Value & "'s Remittances"
.BodyFormat = olFormatHTML
.HTMLbody = "<HTML><BODY></BODY></HTML>" & .HTMLbody & Signature
.Display True
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
In the class module CMailItemEvents:
Option Explicit
Public WithEvents itm As Outlook.MailItem
Private Declare PtrSafe Function MessageBox _
Lib "User64" Alias "MessageBoxA" _
(ByVal hWnd As Long, _
ByVal lpText As String, _
ByVal lpCaption As String, _
ByVal wType As Long) _
As Long
Private Sub itm_Close(Cancel As Boolean)
Dim blnSent As Boolean
Dim lastG As Long
Dim myValue As Variant
lastG = Sheets("Report").Cells(Rows.Count, "A").End(xlUp).Row + 1
On Error Resume Next
blnSent = itm.Sent
If Err.Number = 0 Then
myValue = inputBox("Why was " & usrFrmEMAIL.cmbSubbie & " Remittance E-Mail not sent?", "Remittance Error")
Sheets("Report").Range("A" & lastG).Value = usrFrmEMAIL.cmbSubbie.Value
Sheets("Report").Range("B" & lastG).Value = usrFrmEMAIL.cmbMonth.Text & " " & usrFrmEMAIL.txtbxYear.Text
Sheets("Report").Range("C" & lastG).Value = Now
AppActivate (myValue.ActiveExplorer.CurrentItem)
Sheets("Report").Range("D" & lastG).Value = myValue
Exit Sub
Else
Sheets("Report").Range("A" & lastG).Value = usrFrmEMAIL.cmbSubbie.Value
Sheets("Report").Range("B" & lastG).Value = usrFrmEMAIL.cmbMonth.Text & " " & usrFrmEMAIL.txtbxYear.Text
Sheets("Report").Range("C" & lastG).Value = Now
End If
End Sub
sorry for taking so long to get back, i've been away on holiday.
I managed to figure out how to get this to work.
Class Module:
Option Explicit
Private Declare Function GetWindowThreadProcessId Lib _
"user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Private Declare Function AttachThreadInput Lib "user32" _
(ByVal idAttach As Long, ByVal idAttachTo As Long, _
ByVal fAttach As Long) As Long
Private Declare Function GetForegroundWindow Lib "user32" () As Long
Private Declare Function SetForegroundWindow Lib "user32" _
(ByVal hWnd As Long) As Long
Private Declare Function IsIconic Lib "user32" _
(ByVal hWnd As Long) As Long
Private Declare Function ShowWindow Lib "user32" _
(ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function FindWindowA Lib "user32" (ByVal lpClassName _
As Long, ByVal lpWindowName As String) As Long
Const SW_SHOW = 5
Const SW_RESTORE = 9
Public WithEvents itm As Outlook.MailItem
Function ForceForegroundWindow(ByVal hWnd As Long) As Boolean
Dim ThreadID1 As Long
Dim ThreadID2 As Long
Dim nRet As Long
If hWnd = GetForegroundWindow Then
ForceForegroundWindow = True
Else
ThreadID1 = GetWindowThreadProcessId( _
GetForegroundWindow, ByVal 0&)
ThreadID2 = GetWindowThreadProcessId(hWnd, ByVal 0&)
If ThreadID1 <> ThreadID2 Then
AttachThreadInput ThreadID1, ThreadID2, True
nRet = SetForegroundWindow(hWnd)
AttachThreadInput ThreadID1, ThreadID2, False
Else
nRet = SetForegroundWindow(hWnd)
End If
If IsIconic(hWnd) Then
ShowWindow hWnd, SW_RESTORE
Else
ShowWindow hWnd, SW_SHOW
End If
ForceForegroundWindow = CBool(nRet)
End If
End Function
Private Sub itm_Close(Cancel As Boolean)
Dim blnSent As Boolean
Dim lastG As Long, currentrow As Integer
Dim myValue As String
Dim bOK As Boolean
Dim idx As Long
idx = usrFrmEMAIL.cmbSubbie.ListIndex
lastG = Sheets("Report").Cells(Rows.Count, "A").End(xlUp).Row + 1
On Error Resume Next
blnSent = itm.Sent
If Err.Number = 0 Then
itm.Close olDiscard
ForceForegroundWindow FindWindowA(0, Application.Caption)
Do
myValue = inputBox("Why was " & usrFrmEMAIL.cmbSubbie & "'s Remittance E-Mail not sent?", "Remittance Error")
If StrPtr(myValue) = 0 Then
bOK = False
MsgBox "You cannot just press Cancel!" & vbLf & vbLf & "A reason is needed for not sending the email.", vbCritical
ElseIf myValue = "" Then
bOK = False
MsgBox "You didn't enter anything, but pressed OK" & vbLf & vbLf & "A reason is needed for not sending the email.", vbExclamation
ElseIf Len(Application.WorksheetFunction.Substitute(myValue, " ", "")) = 0 Then
bOK = False
MsgBox "You only entered spaces!" & vbLf & vbLf & "A reason is needed for not sending the email.", vbExclamation
Else
bOK = True
Exit Do
End If
Loop Until bOK = True
Sheets("Report").Range("A" & lastG).Value = usrFrmEMAIL.cmbSubbie.Value
Sheets("Report").Range("B" & lastG).Value = usrFrmEMAIL.cmbMonth.Text & " " & usrFrmEMAIL.txtbxYear.Text
Sheets("Report").Range("C" & lastG).Value = Now
Sheets("Report").Range("D" & lastG).Value = myValue
If idx <> usrFrmEMAIL.cmbSubbie.ListCount - 1 Then
usrFrmEMAIL.cmbSubbie.ListIndex = idx + 1
Else
usrFrmEMAIL.cmbSubbie.ListIndex = 0
End If
Else
For currentrow = 6 To lastG
Sheets("Report").Range("A" & lastG).Value = usrFrmEMAIL.cmbSubbie.Value
Sheets("Report").Range("B" & lastG).Value = usrFrmEMAIL.cmbMonth.Text & " " & usrFrmEMAIL.txtbxYear.Text
Sheets("Report").Range("C" & lastG).Value = Now
Sheets("Report").Range("D" & lastG).Value = "Sent"
Next
If idx <> usrFrmEMAIL.cmbSubbie.ListCount - 1 Then
usrFrmEMAIL.cmbSubbie.ListIndex = idx + 1
Else
usrFrmEMAIL.cmbSubbie.ListIndex = 0
End If
End If
End Sub
UserForm Code:
Dim OutApp As Object
Dim itmevt As New CMailItemEvents
Private Sub btnCreateEmail_Click()
Dim i, j, lastG, lastD As Long
Dim OutMail As Object
Dim sFName As String, colFiles As New Collection
Dim myDir As String, ChDir As String, attName As New Collection, attName2 As String
Dim dte As String
Dim greet As String, cntName As String, SigString As String, Signature As String
lastG = Sheets("File Locations").Cells(Rows.Count, "B").End(xlUp).Row
SigString = "H:\AppData\Roaming\Microsoft\Signatures\"
If Dir(SigString, vbDirectory) <> vbNullString Then
SigString = SigString & Dir$(SigString & "*.htm")
Else:
SigString = ""
End If
Signature = CreateObject("Scripting.FileSystemObject").GetFile(SigString).OpenAsTextStream(1, -2).readall
If Me.cmbMonth.Value = "" Then
Me.lblErrorMsg.Visible = True
Me.lblErrorMsg.Caption = "Required!"
Me.cmbMonth.SetFocus
Exit Sub
ElseIf Me.txtbxYear.Value = "" Then
Me.lblErrorMsg.Visible = True
Me.lblErrorMsg.Caption = "Required!"
Me.txtbxYear.SetFocus
Exit Sub
ElseIf Me.cmbSubbie.Value = "" Then
Me.lblErrorMsg.Visible = True
Me.lblErrorMsg.Caption = "Required!"
Me.cmbSubbie.SetFocus
Exit Sub
End If
For i = 1 To lastG
lookupVal = Sheets("File Locations").Cells(i, "B") ' value to find
If Dir(lookupVal, vbDirectory) = "" Then
Else
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
Set itmevt.itm = OutMail
dte = Me.cmbMonth.Value & " " & Me.txtbxYear.Text
myDir = lookupVal 'Set Dir to search
ChDir = (myDir & "\" & Me.cmbSubbie.Value & "\***\") 'Change to that dir
sFName = Dir(ChDir & "*" & dte & "*") 'Set Search spec
While InStr(sFName, dte)
colFiles.Add (ChDir & sFName)
attName.Add (sFName)
sFName = Dir
Wend
End If
Next i
On Error Resume Next
With OutMail
If Me.txtbxSubNAME.Value <> "" Then
cntName = " " & Me.txtbxSubNAME.Value & ","
Else
cntName = ","
End If
If Time < TimeValue("12:00:00") Then
greet = "Good Morning" & cntName
Else
greet = "Good Afternoon" & cntName
End If
If colFiles.Count > 0 Then
For i = 1 To colFiles.Count
.Attachments.Add colFiles(i)
attName2 = attName(i) & "<br>" & attName2
Next i
End If
.To = Me.txtbxSubEMAIL.Value
.CC = ""
.BCC = ""
.Subject = Me.cmbMonth.Value & "'s "
.BodyFormat = olFormatHTML
.HTMLbody = "<HTML><BODY STYLE='font-family:Calibri;font-size:14.5'>" & greet & "<br><br>" & "Thank for your . Please see the attached remittances." & "<br><br>" & "<b>" & attName2 & "</b>" _
& "<br>" & "Please submit if you are required to do so. In this email, could you please copy in:" & "<br><br>" & _
"" & "<br><br>" & _
"<b>" & "Please note: " & "</b>" & "If you need to supply a matching invoice and we do not receive one, your payment's will be held." & "<br><br>" & "Kind regards," & "</BODY></HTML>" & .HTMLbody & Signature
.Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub