mikel948
asked on
Compare follow-up completed date with received date
Experts,
I am running Exchange Server 2003 SP1 and Outlook 2003. I have a number of group mailboxes each one assigned to a specific client. My team of CSR's open the emails, take action on them, and then mark the email as completed by double-clicking on the flag icon. At the end of the month, the project leader goes into the mailbox and manually opens each email and compares the completed date on the email to the received date of the email to verify that the response was completed within a 24 hour period. This is extremely tedious and is not at all productive as there are about 2000 emails per month per account. Is there some way to automate this process? As usual, thanks for your help in advance.
Mikel948
I am running Exchange Server 2003 SP1 and Outlook 2003. I have a number of group mailboxes each one assigned to a specific client. My team of CSR's open the emails, take action on them, and then mark the email as completed by double-clicking on the flag icon. At the end of the month, the project leader goes into the mailbox and manually opens each email and compares the completed date on the email to the received date of the email to verify that the response was completed within a 24 hour period. This is extremely tedious and is not at all productive as there are about 2000 emails per month per account. Is there some way to automate this process? As usual, thanks for your help in advance.
Mikel948
ASKER
Hey BlueDevilFan,
Thanks for the script. As soon as I get it working, you'll get the 500 points. I am getting a run-time error 91, Object variable or With block variable not set. It breaks at objFile.Close.
Best regards,
mikel948
Thanks for the script. As soon as I get it working, you'll get the 500 points. I am getting a run-time error 91, Object variable or With block variable not set. It breaks at objFile.Close.
Best regards,
mikel948
That's indicative that the main portion of the code (i.e. the portion within the IF ... END IF in the subroutine ShowCompletionInterval) never ran. That would mean that the store and/or root folder name weren't found. We can avoid the error message in this situation by moving the line of code cauing the error inside the IF ... END IF. Move this line of code
objFile.Close
immediately after
ProcessFolder objRootFolder
objFile.Close
immediately after
ProcessFolder objRootFolder
ASKER
Hey BlueDevilFan,
I have been out of town so I haven't been able to test this until now. I no longer receive the error message and the script seems to run; however, no output file is created.
Mikel948
I have been out of town so I haven't been able to test this until now. I no longer receive the error message and the script seems to run; however, no output file is created.
Mikel948
ASKER
Hello. Anyone, a little help getting this to work?
Mikel948,
Sorry, somehow I missed your 6/16 message. Have you adjusted the file name and path per the comments in the code?
Sorry, somehow I missed your 6/16 message. Have you adjusted the file name and path per the comments in the code?
ASKER
Hey BlueDevilFan,
In the Sub ShowCompletionInterval() routine I entered:
objCDO.Logon "Outlook", "mydomainpassword"
If GetStartingFolder("mailbox ", "inbox") I have also tried "mailbox-mikel948", "mikel948", "Outlook" as the mystore entry
Set objFile = objFSO.CreateTextFile("C:\ report (" & Replace(Date, "/", "-") & ").txt")
What am I doing wrong?
Mikel948
In the Sub ShowCompletionInterval() routine I entered:
objCDO.Logon "Outlook", "mydomainpassword"
If GetStartingFolder("mailbox
Set objFile = objFSO.CreateTextFile("C:\
What am I doing wrong?
Mikel948
> objCDO.Logon "Outlook", "mydomainpassword"
You don't need your password. Since you're already singed into Outlook when this runs it's not necessary. There can only be one profile logged in, all additional sessions use that profile and it's already been authenticated. THis just satellites off of it.
> If GetStartingFolder("mailbox ", "inbox")
"mailbox" should be the name of the default mail delivery location. If you're on Exchange, then that'd be something like "Mailbox - Doe, John". If you're using POP instead, then it'd be the name, inside Outlook, not the file name, of the PST file containing your inbox. Inbox will normally be just that, Inbox.
You don't need your password. Since you're already singed into Outlook when this runs it's not necessary. There can only be one profile logged in, all additional sessions use that profile and it's already been authenticated. THis just satellites off of it.
> If GetStartingFolder("mailbox
"mailbox" should be the name of the default mail delivery location. If you're on Exchange, then that'd be something like "Mailbox - Doe, John". If you're using POP instead, then it'd be the name, inside Outlook, not the file name, of the PST file containing your inbox. Inbox will normally be just that, Inbox.
Hi, mikel948.
Any progress?
Any progress?
ASKER
Hey BlueDevilFan,
I am sorry I haven't got back to you sooner; I am getting slammed all over the board. I still cannot get the report to generate. AT first I though it was because I was trying to access a mailbox that I have access to through Outlook, but I also tried it on my own mailbox and It still does't work. Here is a copy of the code I am trying to use to access a project mailbox:
'Include a project reference to Microsoft CDO 1.21 Library
Option Explicit
Dim objCDO As New MAPI.Session, _
objRootFolder As MAPI.Folder, _
objFolder As MAPI.Folder, _
objInfoStore As MAPI.InfoStore, _
objFSO As Object, _
objFile As Object
Sub ShowCompletionInterval()
'Replace MyProfileName and MyProfilePassword with your profile name and password
objCDO.Logon "outlook"
'Replace MyStore with the name of a mailbox or personal folder and MyFolder with the name
'of a folder within that store that you want as your starting point. All folders below this point
'will be processed.
If GetStartingFolder("Mailbox -xxxxxxxxx xx", "RESOLVED EMAIL") Then
'Create a text file to hold the output
Set objFSO = CreateObject("Scripting.Fi leSystemOb ject")
'Replace the file name and path on the next line with those you want to use.
Set objFile = objFSO.CreateTextFile("C:\ testing\re port (" & Replace(Date, "/", "-") & ").txt")
objFile.WriteLine "Age" & vbTab & "Message Subject"
objFile.WriteLine ""
'Call the folder check begining with the root folder
ProcessFolder objRootFolder
objFile.Close
End If
'Log out from CDO
objCDO.Logoff
'Destroy the CDO objects to avoid memory leaks
Set objFolder = Nothing
Set objRootFolder = Nothing
Set objInfoStore = Nothing
Set objCDO = Nothing
'Close the text file and destroy those objects too
'objFile.Close
Set objFile = Nothing
Set objFSO = Nothing
MsgBox "All done!"
End Sub
Function GetStartingFolder(strStore Name As String, strFolderName As String) As Boolean
Dim bolFound As Boolean
GetStartingFolder = False
For Each objInfoStore In objCDO.InfoStores
If objInfoStore.Name = strStoreName Then
For Each objRootFolder In objInfoStore.RootFolder.Fo lders
If objRootFolder.Name = strFolderName Then
bolFound = True
GetStartingFolder = True
Exit For
End If
Next
If bolFound Then
Exit For
End If
End If
Next
End Function
Sub ProcessFolder(objFolder As MAPI.Folder)
Dim objSubFolders As MAPI.Folders, _
objSubFolder As MAPI.Folder, _
objMessages As MAPI.Messages, _
objMessage As MAPI.Message, _
objFields As MAPI.Fields, _
objField As MAPI.Field, _
intAgeInHours As Integer
'Does this folder contain any messages
If objFolder.Messages.Count > 0 Then
'Get the messages collection
Set objMessages = objFolder.Messages
'Process the messages
For Each objMessage In objMessages
Set objFields = objMessage.Fields
On Error Resume Next
Set objField = objFields.Item(&H10910040)
If Err.Number = 0 Then
'Calculate the difference between arrival and being marked complete
intAgeInHours = DateDiff("h", objMessage.TimeReceived, objField.Value)
'Was it more then 24 hours
If intAgeInHours > 24 Then
objFile.WriteLine PadLeft(Val(intAgeInHours) , 4) & vbTab & objMessage.Subject
End If
'Give the OS a chance to do something
DoEvents
End If
On Error GoTo 0
Set objField = Nothing
Next
End If
'Does this folder have subfodlers
If objFolder.Folders.Count > 0 Then
'Grab the subfolders
Set objSubFolders = objFolder.Folders
'Loop through those subfolders
For Each objSubFolder In objSubFolders
'Recursively call this subroutine
ProcessFolder objSubFolder
Next
End If
'Destroy the CDO objects to avoid memory leaks
Set objFolder = Nothing
Set objSubFolders = Nothing
Set objMessage = Nothing
Set objMessages = Nothing
End Sub
Function PadLeft(strValue As String, intLength As Integer)
Dim intActualLength As Integer
intActualLength = Len(Trim(strValue))
If intActualLength < intLength Then
PadLeft = String(intLength - intActualLength, " ") & Trim(strValue)
Else
PadLeft = strValue
End If
End Function
Thanks,
Mikel948
I am sorry I haven't got back to you sooner; I am getting slammed all over the board. I still cannot get the report to generate. AT first I though it was because I was trying to access a mailbox that I have access to through Outlook, but I also tried it on my own mailbox and It still does't work. Here is a copy of the code I am trying to use to access a project mailbox:
'Include a project reference to Microsoft CDO 1.21 Library
Option Explicit
Dim objCDO As New MAPI.Session, _
objRootFolder As MAPI.Folder, _
objFolder As MAPI.Folder, _
objInfoStore As MAPI.InfoStore, _
objFSO As Object, _
objFile As Object
Sub ShowCompletionInterval()
'Replace MyProfileName and MyProfilePassword with your profile name and password
objCDO.Logon "outlook"
'Replace MyStore with the name of a mailbox or personal folder and MyFolder with the name
'of a folder within that store that you want as your starting point. All folders below this point
'will be processed.
If GetStartingFolder("Mailbox
'Create a text file to hold the output
Set objFSO = CreateObject("Scripting.Fi
'Replace the file name and path on the next line with those you want to use.
Set objFile = objFSO.CreateTextFile("C:\
objFile.WriteLine "Age" & vbTab & "Message Subject"
objFile.WriteLine ""
'Call the folder check begining with the root folder
ProcessFolder objRootFolder
objFile.Close
End If
'Log out from CDO
objCDO.Logoff
'Destroy the CDO objects to avoid memory leaks
Set objFolder = Nothing
Set objRootFolder = Nothing
Set objInfoStore = Nothing
Set objCDO = Nothing
'Close the text file and destroy those objects too
'objFile.Close
Set objFile = Nothing
Set objFSO = Nothing
MsgBox "All done!"
End Sub
Function GetStartingFolder(strStore
Dim bolFound As Boolean
GetStartingFolder = False
For Each objInfoStore In objCDO.InfoStores
If objInfoStore.Name = strStoreName Then
For Each objRootFolder In objInfoStore.RootFolder.Fo
If objRootFolder.Name = strFolderName Then
bolFound = True
GetStartingFolder = True
Exit For
End If
Next
If bolFound Then
Exit For
End If
End If
Next
End Function
Sub ProcessFolder(objFolder As MAPI.Folder)
Dim objSubFolders As MAPI.Folders, _
objSubFolder As MAPI.Folder, _
objMessages As MAPI.Messages, _
objMessage As MAPI.Message, _
objFields As MAPI.Fields, _
objField As MAPI.Field, _
intAgeInHours As Integer
'Does this folder contain any messages
If objFolder.Messages.Count > 0 Then
'Get the messages collection
Set objMessages = objFolder.Messages
'Process the messages
For Each objMessage In objMessages
Set objFields = objMessage.Fields
On Error Resume Next
Set objField = objFields.Item(&H10910040)
If Err.Number = 0 Then
'Calculate the difference between arrival and being marked complete
intAgeInHours = DateDiff("h", objMessage.TimeReceived, objField.Value)
'Was it more then 24 hours
If intAgeInHours > 24 Then
objFile.WriteLine PadLeft(Val(intAgeInHours)
End If
'Give the OS a chance to do something
DoEvents
End If
On Error GoTo 0
Set objField = Nothing
Next
End If
'Does this folder have subfodlers
If objFolder.Folders.Count > 0 Then
'Grab the subfolders
Set objSubFolders = objFolder.Folders
'Loop through those subfolders
For Each objSubFolder In objSubFolders
'Recursively call this subroutine
ProcessFolder objSubFolder
Next
End If
'Destroy the CDO objects to avoid memory leaks
Set objFolder = Nothing
Set objSubFolders = Nothing
Set objMessage = Nothing
Set objMessages = Nothing
End Sub
Function PadLeft(strValue As String, intLength As Integer)
Dim intActualLength As Integer
intActualLength = Len(Trim(strValue))
If intActualLength < intLength Then
PadLeft = String(intLength - intActualLength, " ") & Trim(strValue)
Else
PadLeft = strValue
End If
End Function
Thanks,
Mikel948
Mikel948,
> I am getting slammed all over the board
No problem. I understand.
Replace the ShowCompletionInterval subroutine with the one below. I added a couple of commands to display information about what's going on and help us figure this out. Try running it again and let me know what message you receive.
Sub ShowCompletionInterval()
'Replace MyProfileName and MyProfilePassword with your profile name and password
objCDO.Logon "outlook"
'Replace MyStore with the name of a mailbox or personal folder and MyFolder with the name
'of a folder within that store that you want as your starting point. All folders below this point
'will be processed.
If GetStartingFolder("Mailbox -xxxxxxxxx xx", "RESOLVED EMAIL") Then
MsgBox "The mailbox was found."
'Create a text file to hold the output
Set objFSO = CreateObject("Scripting.Fi leSystemOb ject")
'Replace the file name and path on the next line with those you want to use.
Set objFile = objFSO.CreateTextFile("C:\ testing\re port (" & Replace(Date, "/", "-") & ").txt")
objFile.WriteLine "Age" & vbTab & "Message Subject"
objFile.WriteLine ""
'Call the folder check begining with the root folder
ProcessFolder objRootFolder
objFile.Close
Else
MsgBox "The mailbox was not found."
End If
'Log out from CDO
objCDO.Logoff
'Destroy the CDO objects to avoid memory leaks
Set objFolder = Nothing
Set objRootFolder = Nothing
Set objInfoStore = Nothing
Set objCDO = Nothing
'Close the text file and destroy those objects too
'objFile.Close
Set objFile = Nothing
Set objFSO = Nothing
MsgBox "All done!"
End Sub
> I am getting slammed all over the board
No problem. I understand.
Replace the ShowCompletionInterval subroutine with the one below. I added a couple of commands to display information about what's going on and help us figure this out. Try running it again and let me know what message you receive.
Sub ShowCompletionInterval()
'Replace MyProfileName and MyProfilePassword with your profile name and password
objCDO.Logon "outlook"
'Replace MyStore with the name of a mailbox or personal folder and MyFolder with the name
'of a folder within that store that you want as your starting point. All folders below this point
'will be processed.
If GetStartingFolder("Mailbox
MsgBox "The mailbox was found."
'Create a text file to hold the output
Set objFSO = CreateObject("Scripting.Fi
'Replace the file name and path on the next line with those you want to use.
Set objFile = objFSO.CreateTextFile("C:\
objFile.WriteLine "Age" & vbTab & "Message Subject"
objFile.WriteLine ""
'Call the folder check begining with the root folder
ProcessFolder objRootFolder
objFile.Close
Else
MsgBox "The mailbox was not found."
End If
'Log out from CDO
objCDO.Logoff
'Destroy the CDO objects to avoid memory leaks
Set objFolder = Nothing
Set objRootFolder = Nothing
Set objInfoStore = Nothing
Set objCDO = Nothing
'Close the text file and destroy those objects too
'objFile.Close
Set objFile = Nothing
Set objFSO = Nothing
MsgBox "All done!"
End Sub
ASKER
OK. No matter which mailbox I try to access, including my own, I first get the mailbox not found msg box, then the all done msg box.
Sorry to be slow. What we have is a path problem. I put this routine together so you can list the names of the stores in you profile. Copy and paste this code in with what you already have. When you run it a dialog-box will pop up showing the names of your information stores as Outlook sees them.
Sub ListMAPIStores()
Dim objCDO As Object, _
objStore As Object, _
strStores As String
Set objCDO = CreateObject("MAPI.Session ")
'Change the profile name as needed
objCDO.Logon "Outlook"
For Each objStore In objCDO.InfoStores
strStores = strStores & objStore.Name & vbCrLf
Next
MsgBox strStores, vbInformation + vbOKOnly, "Your Information Stores"
Set objCDO = Nothing
Set objStore = Nothing
End Sub
Sub ListMAPIStores()
Dim objCDO As Object, _
objStore As Object, _
strStores As String
Set objCDO = CreateObject("MAPI.Session
'Change the profile name as needed
objCDO.Logon "Outlook"
For Each objStore In objCDO.InfoStores
strStores = strStores & objStore.Name & vbCrLf
Next
MsgBox strStores, vbInformation + vbOKOnly, "Your Information Stores"
Set objCDO = Nothing
Set objStore = Nothing
End Sub
ASKER
Finally! I got my report to print.
I have an email that I received on July 1 at 11:21 AM and it was completed on July 6 4:40 PM. The age column shows 125 What is the Age column showing?
I have an email that I received on July 1 at 11:21 AM and it was completed on July 6 4:40 PM. The age column shows 125 What is the Age column showing?
Great news.
> The age column shows 125 What is the Age column showing?
It's showing the age of the item in hours.
> The age column shows 125 What is the Age column showing?
It's showing the age of the item in hours.
ASKER
Hey BlueDevilFan,
You rock. Before I close this out and give you the points, I want to know if you can tweak the report a little more. (you know how end-users are, give them an inch and they scream for a mile). If you could make these changes for me, I'll give you another 250 points.
Ideally, they would like to have the report show received date, completion date, total time difference in days not hours and subject line. The reason they want all this is if an email comes in on Saturday it won't be looked at for a minimum of 48 hours and they don't want to penalize the CSR who responds to the email. Let me know if this is possible.
Best regards,
Mikel948
You rock. Before I close this out and give you the points, I want to know if you can tweak the report a little more. (you know how end-users are, give them an inch and they scream for a mile). If you could make these changes for me, I'll give you another 250 points.
Ideally, they would like to have the report show received date, completion date, total time difference in days not hours and subject line. The reason they want all this is if an email comes in on Saturday it won't be looked at for a minimum of 48 hours and they don't want to penalize the CSR who responds to the email. Let me know if this is possible.
Best regards,
Mikel948
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hey BlueDevilFan,
Again I want to let you know that you rock! I really appreciate the way that you worked through this with me. I am sure I will have more questions for you in the future.
Best regards,
Mikel948
Again I want to let you know that you rock! I really appreciate the way that you worked through this with me. I am sure I will have more questions for you in the future.
Best regards,
Mikel948
Thanks, Mikel948! I appreciate that.
Here's a script for doing this. I wrote and tested this using Outlook 2003. Follow these instructions to use it.
1. Start Outlook
2. Click Tools->Macro->Visual Basic Editor
3. If not already expanded, expand Modules and click on Module1
4. Copy the code below and paste it into the right-hand pane of the VB editor window.
5. Edit the code as needed. There are comments where things should be changed.
6. Click Tools->References
7. Scroll through the list of references until you find "Microsoft CDO 1.21 Library"
8. Check the box next to it.
9. Click OK.
10. Click the diskette icon on the toolbar to save changes
11. Close the VB Editor
12. Click Tools->Macro->Security
13. Set the Security Level to Medium
14. Run the macro. It will produce a text file listing the messages that are more than 24 hours old along with their actual age in hours.
'Include a project reference to Microsoft CDO 1.21 Library
Option Explicit
Dim objCDO As New MAPI.Session, _
objRootFolder As MAPI.Folder, _
objFolder As MAPI.Folder, _
objInfoStore As MAPI.InfoStore, _
objFSO As Object, _
objFile As Object
Sub ShowCompletionInterval()
'Replace MyProfileName and MyProfilePassword with your profile name and password
objCDO.Logon "MyProfileName"
'Replace MyStore with the name of a mailbox or personal folder and MyFolder with the name
'of a folder within that store that you want as your starting point. All folders below this point
'will be processed.
If GetStartingFolder("MyStore
'Create a text file to hold the output
Set objFSO = CreateObject("Scripting.Fi
'Replace the file name and path on the next line with those you want to use.
Set objFile = objFSO.CreateTextFile("C:\
objFile.WriteLine "Age" & vbTab & "Message Subject"
objFile.WriteLine ""
'Call the folder check begining with the root folder
ProcessFolder objRootFolder
End If
'Log out from CDO
objCDO.Logoff
'Destroy the CDO objects to avoid memory leaks
Set objFolder = Nothing
Set objRootFolder = Nothing
Set objInfoStore = Nothing
Set objCDO = Nothing
'Close the text file and destroy those objects too
objFile.Close
Set objFile = Nothing
Set objFSO = Nothing
MsgBox "All done!"
End Sub
Function GetStartingFolder(strStore
Dim bolFound As Boolean
GetStartingFolder = False
For Each objInfoStore In objCDO.InfoStores
If objInfoStore.Name = strStoreName Then
For Each objRootFolder In objInfoStore.RootFolder.Fo
If objRootFolder.Name = strFolderName Then
bolFound = True
GetStartingFolder = True
Exit For
End If
Next
If bolFound Then
Exit For
End If
End If
Next
End Function
Sub ProcessFolder(objFolder As MAPI.Folder)
Dim objSubFolders As MAPI.Folders, _
objSubFolder As MAPI.Folder, _
objMessages As MAPI.Messages, _
objMessage As MAPI.Message, _
objFields As MAPI.Fields, _
objField As MAPI.Field, _
intAgeInHours As Integer
'Does this folder contain any messages
If objFolder.Messages.Count > 0 Then
'Get the messages collection
Set objMessages = objFolder.Messages
'Process the messages
For Each objMessage In objMessages
Set objFields = objMessage.Fields
On Error Resume Next
Set objField = objFields.Item(&H10910040)
If Err.Number = 0 Then
'Calculate the difference between arrival and being marked complete
intAgeInHours = DateDiff("h", objMessage.TimeReceived, objField.Value)
'Was it more then 24 hours
If intAgeInHours > 24 Then
objFile.WriteLine PadLeft(Val(intAgeInHours)
End If
'Give the OS a chance to do something
DoEvents
End If
On Error GoTo 0
Set objField = Nothing
Next
End If
'Does this folder have subfodlers
If objFolder.Folders.Count > 0 Then
'Grab the subfolders
Set objSubFolders = objFolder.Folders
'Loop through those subfolders
For Each objSubFolder In objSubFolders
'Recursively call this subroutine
ProcessFolder objSubFolder
Next
End If
'Destroy the CDO objects to avoid memory leaks
Set objFolder = Nothing
Set objSubFolders = Nothing
Set objMessage = Nothing
Set objMessages = Nothing
End Sub
Function PadLeft(strValue As String, intLength As Integer)
Dim intActualLength As Integer
intActualLength = Len(Trim(strValue))
If intActualLength < intLength Then
PadLeft = String(intLength - intActualLength, " ") & Trim(strValue)
Else
PadLeft = strValue
End If
End Function
Cheers!