In an earlier post I showed a number of ways to export Outlook messages to Excel. Mitesh saw that post and asked if it’d be possible to adapt it to export Outlook tasks instead of messages. The answer of course is “yes”. In fact you could adapt the code from the original post to export any of Outlook’s basic item types (i.e. appointments, contacts, messages, notes, tasks). All Mitesh needs to do is change the list of item properties the code will export. Where an email has properties called “Subject”, “ReceivedTime”, and “SenderEmailAddress” (to name a few), a task has “Subject”, “StartDate”, and “DueDate”. In order to change the script to handle a different item type you need to know what properties an Outlook item of that type has. Microsoft has pages on its site that list the complete set of a task item’s properties for Outlook 2007, Outlook 2010, and Outlook 2013. For this example I’ve chosen a subset of task properties. You can add, delete, and/or rearrange them to suit your needs.
Some properties (e.g. DelegationState, Ownership) are enumerations. An enumeration stores a numeric value that equates to something. For example, a 0 in DelegationState means the task is not delegated while a 2 means that the task has been delegated and the person it is delegated to has accepted it. Rather than exporting the numeric value stored in an enumerated property, I wrote functions that returns a more meaningful value in plain English. I only wrote those functions for enumerated fields I used in this example. There are other enumerated fields that would benefit from a similar conversion if you include them in your export. Once again, you can refer to Microsoft’s documentation to see which properties are enumerated and to get the available values and what they stand for.
Adding the code to Outlook.
- Start Outlook
- Press ALT+F11 to open the Visual Basic Editor
- If not already expanded, expand Microsoft Office Outlook Objects
- If not already expanded, expand Modules
- Select an existing module (e.g. Module1) by double-clicking on it or create a new module by right-clicking Modules and selecting Insert > Module.
- Copy the code from the code snippet box and paste it into the right-hand pane of Outlook’s VB Editor window
- Click the diskette icon on the toolbar to save the changes
- Close the VB Editor
Sub ExportTasksToExcel()
Const SCRIPT_NAME = "Export Tasks to Excel"
Dim olkTsk As Object, _
excApp As Object, _
excWkb As Object, _
excWks As Object, _
lngRow As Long, _
lngCnt As Long, _
strFilename As String
strFilename = InputBox("Enter a filename (including path) to save the exported tasks to.", SCRIPT_NAME)
If strFilename = "" Then
MsgBox "The filename is blank. Export aborted.", vbInformation + vbOKOnly, SCRIPT_NAME
Else
Set excApp = CreateObject("Excel.Application")
Set excWkb = excApp.Workbooks.Add()
Set excWks = excWkb.ActiveSheet
'Write Excel Column Headers
With excWks
.Cells(1, 1) = "Subject"
.Cells(1, 2) = "Created On"
.Cells(1, 3) = "Start Date"
.Cells(1, 4) = "Due Date"
.Cells(1, 5) = "Date Complete"
.Cells(1, 6) = "% Complete"
.Cells(1, 7) = "Delegation State"
.Cells(1, 8) = "Delegator"
.Cells(1, 9) = "Owner"
.Cells(1, 10) = "Ownership"
.Cells(1, 11) = "Role"
.Cells(1, 12) = "Response State"
End With
lngRow = 2
'Write tasks to spreadsheet
For Each olkTsk In Application.ActiveExplorer.CurrentFolder.Items
'Add a row for each task item property you want to export. Rearrange the rows as desired. Remember to edit the column number you want each property to appear in.
excWks.Cells(lngRow, 1) = olkTsk.Subject
excWks.Cells(lngRow, 2) = olkTsk.CreationTime
excWks.Cells(lngRow, 3) = olkTsk.StartDate
excWks.Cells(lngRow, 4) = olkTsk.DueDate
excWks.Cells(lngRow, 5) = olkTsk.DateCompleted
excWks.Cells(lngRow, 6) = olkTsk.PercentComplete
excWks.Cells(lngRow, 7) = GetDelegationState(olkTsk.DelegationState)
excWks.Cells(lngRow, 8) = olkTsk.Delegator
excWks.Cells(lngRow, 9) = olkTsk.Owner
excWks.Cells(lngRow, 10) = GetOwnership(olkTsk.Ownership)
excWks.Cells(lngRow, 11) = olkTsk.Role
excWks.Cells(lngRow, 12) = GetResponseState(olkTsk.ResponseState)
lngRow = lngRow + 1
lngCnt = lngCnt + 1
Next
Set olkTsk = Nothing
excWkb.SaveAs strFilename
excWkb.Close
MsgBox "Process complete. A total of " & lngCnt & " tasks were exported.", vbInformation + vbOKOnly, SCRIPT_NAME
End If
Set excWks = Nothing
Set excWkb = Nothing
Set excApp = Nothing
End Sub
Function GetDelegationState(intState As Integer) As String
Select Case intState
Case 0
GetDelegationState = "Not delegated"
Case 1
GetDelegationState = "Unknown"
Case 2
GetDelegationState = "Accepted"
Case 3
GetDelegationState = "Declined"
End Select
End Function
Function GetOwnership(intState As Integer) As String
Select Case intState
Case 0
GetOwnership = "New Task"
Case 1
GetOwnership = "Delegated Task"
Case 2
GetOwnership = "Own Task"
End Select
End Function
Function GetResponseState(intState As Integer) As String
Select Case intState
Case 0
GetResponseState = "Simple"
Case 1
GetResponseState = "Reassigned"
Case 2
GetResponseState = "Accepted"
Case 3
GetResponseState = "Declined"
End Select
End Function
Using the Code.
- With Outlook open select a folder that contains tasks.
- Run the macro ExportTasksToExcel.
- When prompted, enter a file name to save the export to. You can cancel the export by leaving the file name blank.
- The macro will display a dialog-box when it’s finished. The dialog-box includes a count of the number of tasks exported.
Notes.
- This code can easily be modified to export a different set of fields. To do that, change the headings written to the spreadsheet (lines 19-30) and the message fields (lines 36-47).
- If you don’t want the macro to prompt for a file name each time, then you can change line 10 to strFilename = “Path_and_File_Name”
Hey- thanks for your code, it is working great on my end— One question – I want it to skip tasks that have been marked as completed. I know the easy fix would be to delete items when completed, but I need to go back to review completion time at a later date. I am guessing an If … Then statement based on the value of the complete field….
You’re welcome, Tim!
That’s simple enough to do. Insert this line of code after line 34
and this line after the current line 49
With those two lines added in the script will now ignore any task that’s complete.
Great work!
This works perfect, BUT…
I would also like to have all the data in the “message/textbox” for each task exported.
My scripting skills are at a copt/paste level so I appreciate all help!
Best regards,
Per
Hi, Per.
That’s simple enough. Add a line like this somewhere between lines 36 and 47 of the original code. Add a corresponding header somewhere between lines 19 and 30. Just copy one of the headers in that range and change the column title as desired.
Hi David
I have kept the names of the UDF and the property of the control are exactly the same. Are there any declarations that need to be done before hand? Kind regards
Mitesh,
No, there are no declarations involved. Are you sure about the property name? The property name is whatever appears next to “Choose Field” on the “Value” tab of the control’s properties.
Hi David,
Thats the name I have selected. It’s a list box for which I have entered possible values, which will allow the user to select a value (I have entered these in the possible value field section in the value tab)- I’m not sure if this has affected it
Secondly, within the field chooser where you can choose fields from various, my UDF’s appear under the ‘User Defined Fields in this folder’
Best Regards
Mitesh
Mitesh,
Do all the tasks your exporting use that same form? If not, then that would explain the error.
Yep, that’s the right place.
Hi David
Yes, the task uses that form, when you select ‘New Task’ from the group inbox it selects the form that I have created. Although there are 2 other task forms previously used, the current task from (the one for which I’d like to export data from) comes up as default
Is there any other way of ensuring that i.e. in the VBA to look in the specfic task form
Best Regards
Mitesh
Hi, Mitesh.
Yes, we can restrict the code to working against that one form type. Replace the subroutine ExportTasksToExcel with the version below. Please be sure to edit the name of you form as per the comment I included in the code. You’ll also need to add the code for exporting your custom form fields.
Sub ExportTasksToExcel() Const SCRIPT_NAME = "Export Tasks to Excel" Dim olkTsk As Outlook.TaskItem, _ excApp As Object, _ excWkb As Object, _ excWks As Object, _ lngRow As Long, _ strFilename As String strFilename = InputBox("Enter a filename (including path) to save the exported tasks to.", SCRIPT_NAME) If strFilename <> "" Then Set excApp = CreateObject("Excel.Application") Set excWkb = excApp.Workbooks.Add() Set excWks = excWkb.ActiveSheet 'Write Excel Column Headers With excWks .Cells(1, 1) = "Subject" .Cells(1, 2) = "Created On" .Cells(1, 3) = "Start Date" .Cells(1, 4) = "Due Date" .Cells(1, 5) = "Date Complete" .Cells(1, 6) = "% Complete" .Cells(1, 7) = "Delegation State" .Cells(1, 8) = "Delegator" .Cells(1, 9) = "Owner" .Cells(1, 10) = "Ownership" .Cells(1, 11) = "Role" .Cells(1, 12) = "Response State" End With lngRow = 2 'Write tasks to spreadsheet For Each olkTsk In Application.ActiveExplorer.CurrentFolder.Items 'On the next line replace YourFormName with the name of your form If Item.MessageClass = "IPM.Task.YourFormName" Then 'Add a row for each task field you want to export excWks.Cells(lngRow, 1) = olkTsk.Subject excWks.Cells(lngRow, 2) = olkTsk.CreationTime excWks.Cells(lngRow, 3) = olkTsk.StartDate excWks.Cells(lngRow, 4) = olkTsk.DueDate excWks.Cells(lngRow, 5) = olkTsk.DateCompleted excWks.Cells(lngRow, 6) = olkTsk.PercentComplete excWks.Cells(lngRow, 7) = GetDelegationState(olkTsk.DelegationState) excWks.Cells(lngRow, 8) = olkTsk.Delegator excWks.Cells(lngRow, 9) = olkTsk.Owner excWks.Cells(lngRow, 10) = GetOwnership(olkTsk.Ownership) excWks.Cells(lngRow, 11) = olkTsk.Role excWks.Cells(lngRow, 12) = GetResponseState(olkTsk.ResponseState) lngRow = lngRow + 1 End If Next Set olkTsk = Nothing excWkb.SaveAs strFilename excWkb.Close End If Set excWks = Nothing Set excWkb = Nothing Set excApp = Nothing MsgBox "Process complete. A total of " & lngRow - 2 & " tasks were exported.", vbInformation + vbOKOnly, SCRIPT_NAME End SubThanks a lot that David
Just one final query, I have a custom Task form made with user defined fields. Everytime I list the user defined field in the code, it doesn’t recongise the field.
I’m assuming it needs to be delcared but I have no knowledge of the syntax
Best Regards
You’re welcome, Mitesh.
You can include user-defined fields by adding a line like this for each one.
'On the next line replace X with a column number and UDF Name with the name of the user-defined field excWks.Cells(lngRow, X) = olkTsk.UserProperties.Item("UDF Name").ValueHi David, VBA doesn’t seem to recongise the object
I get an error:
Run-time error ’91′
Object Variable or With Block variable not set
Mitesh,
My best guess is that the UDF Name is wrong. Did you use the name of the control on the form or the name of the property the control is bound to? You want the latter. Controls don’t store information, they only display it.
Sorry to keep bombarding you with questions David, when exporting tasks, is it possible to only select upon criteria, for example, only export tasks which have the ‘red’ category?
Many Thanks in advance
Mitesh,
Yes, that’s possible. Assuming that the category name (e.g. “Red”) is unique (i.e. does not appear as a substring of another category name), then we accomplish this by enclosing lines 36-49 in an IF … END IF statement. Something like this
If InStr(1, olkTsk.Categories, "Red") > 0 Then (lines 36-49) End IfHi David
Is there any way for getting the code to point to a Shared inbox, I have tried selecting the shared inbox when running the code but it seems to only export my personal tasks rather than the inbox tasks
Many Thanks
Mitesh,
Using which code, the version I posted or the code after you made the change?
Hi David
To the code where the alteration was made on line 34
Best Regards
Mitesh,
Yes, but it’d be simpler to go back to the original code and simply select the folder you want to export from instead of making that change in code. That said, you’ll need to add the following bit of code to what you already have.
Function OpenOutlookFolder(strFolderPath As String) As Outlook.MAPIFolder ' Purpose: Opens an Outlook folder from a folder path. ' Written: 4/24/2009 ' Author: David Lee ' Outlook: All versions Dim arrFolders As Variant, _ varFolder As Variant, _ bolBeyondRoot As Boolean On Error Resume Next If strFolderPath = "" Then Set OpenOutlookFolder = Nothing Else Do While Left(strFolderPath, 1) = "\" strFolderPath = Right(strFolderPath, Len(strFolderPath) - 1) Loop arrFolders = Split(strFolderPath, "\") For Each varFolder In arrFolders Select Case bolBeyondRoot Case False Set OpenOutlookFolder = Outlook.Session.Folders(varFolder) bolBeyondRoot = True Case True Set OpenOutlookFolder = OpenOutlookFolder.Folders(varFolder) End Select If Err.Number <> 0 Then Set OpenOutlookFolder = Nothing Exit For End If Next End If On Error GoTo 0 End FunctionOnce you’ve added that code, then modify line 34 to this
'On the next line enter the path to the shared task folder. The path must point to a task folder, not an inbox. For Each olkTsk In OpenOutlookFolder("path to the shared task folder").ItemsIn case you aren’t familiar with Outlook paths, here’s how they work. A folder path in Outlook is essentially the same as a folder path in the file system. The one difference being that Outlook folder paths do not include a drive letter. The path to a folder is a list of all the folders from the root to the target folder with each folder name separated from the preceding folder name by a backslash (i.e. \). Consider the following folder structure:
Mailbox – Doe, John
– Calendar
– Inbox
– Tasks
Personal Folders
+ Marketing
+ Proposals
+ Reviews
+ Projects
+ Project 1
+ Project 2
The path to “Inbox” is “Mailbox – Doe, John\Inbox”.
The path to “Reviews” is “Personal Folders\Marketing\Reviews”.
The path to “Project 1″ is “Personal Folders\Projects\Project 1″.
Hi David
Good Result! I found the error,
Line 34 needs to be changed to the following
For Each olkTsk In Session.GetDefaultFolder(olFolderTasks).Items
Thanks a lot for your help
Mitesh
Hi, Mitesh.
Changing line #34 from
For Each olkTsk In Application.ActiveExplorer.CurrentFolder.Items
to
For Each olkTsk In Session.GetDefaultFolder(olFolderTasks).Items
restricts the code to operating against just the default task folder. Leaving the code as I posted it allows the code to work against any task folder. You just need to remember to select a task folder before running the code.
Hi David
Many Thanks for your invaluable support for taking the time out and posting this solution
I am trying to execute the code but keep getting the folowing error message;
Run Time Error ’438′:
Object doesn’t support this property or Method
These were basically Outlook items that it didn’t recongise, for example the following fine,
1) Subject
2) Creation Time
The rest of the properties i.e. StartDate, DueDate, DateCompleted etc. were the properties that were causing the code to fail. I removed these from the code and it seemed to have worked, however when I opened up the exported Excel file, I found that my Email messages were copied over rather than the tasks
I suspect that somewhere in the code, its pointing at Email items rather than Tasks?
Many Thanks in Advance
Mitesh