{"id":54523,"date":"2009-01-27T21:01:00","date_gmt":"2009-01-27T21:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/01\/27\/hey-scripting-guy-how-do-i-determine-how-many-office-outlook-e-mail-messages-i-sent-in-a-week\/"},"modified":"2009-01-27T21:01:00","modified_gmt":"2009-01-27T21:01:00","slug":"hey-scripting-guy-how-do-i-determine-how-many-office-outlook-e-mail-messages-i-sent-in-a-week","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-do-i-determine-how-many-office-outlook-e-mail-messages-i-sent-in-a-week\/","title":{"rendered":"Hey, Scripting Guy! How Do I Determine How Many Office Outlook E-Mail Messages I Sent in a Week?"},"content":{"rendered":"<h2><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> <\/h2>\n<p>Hey, Scripting Guy! The <a href=\"http:\/\/dictionary.reference.com\/browse\/pointy%20headed\" target=\"_blank\">Pointy Headed Boss (PHB)<\/a> just got back from some kind of stupid management summit, and he has decided he needs to track our work activities more closely. As a result, we now have to give him a weekly progress report. Seems to me that, if he would pay attention, he would know what we do, but then that would require effort on his part. <\/p>\n<p>Here is the problem, I send hundreds of e-mail messages a week to customers. In fact, this is one of my primary duties. The PHB has no idea of the magnitude of my weekly correspondence, and so it is imperative that I correctly report this number to him. Last week I spent 30 minutes in my Sent Items folder trying to count all those messages. The problem is that, unlike Windows Explorer, I cannot simply select the messages from this week and have Office Outlook tell me how many there are. So I am stuck scrolling up and down, and hoping I do not lose my place (which I do every time the phone rings or the PHB comes by to show he cares). I looked around, but did not see an example of what I need on the Script Center. Can you help me? I am a customer service rep, not a computer guru. Also, if it is not too much trouble, could you ask the Scripting Wife if she would be willing to share her chili recipe? <br \/>&#8211; PD<\/p>\n<p><img decoding=\"async\" height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"><\/p>\n<p>Hi PD,<\/p>\n<p>That is one of the good things about working for Microsoft. I have never seen a PHB here. I think we have excellent management, but because I have not always worked for Microsoft, I have had experience with both the <a href=\"http:\/\/encarta.msn.com\/encnet\/features\/dictionary\/DictionaryResults.aspx?refid=1861632717\" target=\"_blank\">nefarious<\/a> and the <a href=\"http:\/\/encarta.msn.com\/dictionary_1861621115\/infamous.html\" target=\"_blank\">infamous<\/a> types of PHB, so I can empathize.<\/p>\n<table class=\"dataTable\" id=\"EFD\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p>This week we are looking at scripting Office Outlook. Interestingly enough, the Office Outlook object model is not as rich as you might suspect. Certainly Office Word and Office Excel have far more capability for automation than Office Outlook. This having been said, a basic familiarity with Office Outlook automation can lend rich results for the enterprising network administrator, consultant, or power user. <\/p>\n<p>If you are interested in VBScript examples of working with Office Outlook, start with the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/all.mspx\" target=\"_blank\">&#8220;Hey, Scripting Guy!&#8221; archive<\/a>, and then move on to the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/officetips\/archive.mspx\" target=\"_blank\">Office Space archive<\/a>. Finally, you would probably like to see some examples of scripts for automating Office Outlook. You are in luck here because we have dozens of well-written scripts in the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/all.mspx\" target=\"_blank\">Community-Submitted Scripts Center<\/a>. Read on, this is going to be a cool week. If you need help with Windows PowerShell, you can find download links and getting started information in the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/msh.mspx\" target=\"_blank\">Windows PowerShell technology hub<\/a>.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>To find out how many e-mail messages you sent in a week, you can use the <b>CountSentEmailForWeek.ps1<\/b> script. Be sure you have Windows PowerShell installed and configured to allow scripts to run. Here is a link that talks about running <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/winpsh\/manual\/run.mspx\" target=\"_blank\">Windows PowerShell scripts<\/a>.<\/p>\n<p><b>CountSentEmailForWeek.ps1<\/b><\/p>\n<pre class=\"codeSample\">$dte = Get-date\n$thisWeek = $dte.AddDays(-7)\n$i = $j = $null\n[Reflection.Assembly]::LoadWithPartialname(\"Microsoft.Office.Interop.Outlook\") |\nout-null\n$olFolders = \"Microsoft.Office.Interop.Outlook.OlDefaultFolders\" -as [type]\n$outlook = new-object -comobject outlook.application\n$namespace = $outlook.GetNameSpace(\"MAPI\")\n$folder = $namespace.getDefaultFolder($olFolders::olFolderSentMail)\n$items = $folder.items\n$items |\nForEach-Object {\n Write-Progress -activity \"Inspecting $($items.count) email messages\"  -Status \"Processing ...\" `\n-PercentComplete ($i\/$items.count*100)\n if($_.ReceivedTime -ge $thisWeek) { $j++}\n$i++\n}\n\"Total email sent this week is $j\"\n<\/pre>\n<p>The&nbsp;first thing we need to do is to get the current date. To do this, we can use the <b>Get-Date<\/b> cmdlet. This is the same as the VBScript <b>Date<\/b> function, except that the <b>Get-Date<\/b> cmdlet returns a <b>System.DateTime<\/b> object instead of merely a string. We store the <b>DateTime<\/b> object in the <b>$dte<\/b> variable:<\/p>\n<pre class=\"codeSample\">$dte = Get-date<\/pre>\n<p>Because we have a <b>DateTime<\/b> object, it means that there are methods and properties associated with it. We can use the <b>Get-Member<\/b> cmdlet to explore this information. In this command, we limit the data returned to only&nbsp;methods: <\/p>\n<pre class=\"codeSample\">PS C:\\&gt; $dte = Get-Date\nPS C:\\&gt; $dte | Get-Member \u2013membertype method\n   TypeName: System.DateTime\nName                 MemberType     Definition\n----                 ----------     ----------\nAdd                  Method         System.DateTime Add(TimeSpan value)\nAddDays              Method         System.DateTime AddDays(Double value)\nAddHours             Method         System.DateTime AddHours(Double value)\nAddMilliseconds      Method         System.DateTime AddMilliseconds(Double value)\nAddMinutes           Method         System.DateTime AddMinutes(Double value)\nAddMonths            Method         System.DateTime AddMonths(Int32 months)\nAddSeconds           Method         System.DateTime AddSeconds(Double value)\nAddTicks             Method         System.DateTime AddTicks(Int64 value)\nAddYears             Method         System.DateTime AddYears(Int32 value)\nCompareTo            Method         System.Int32 CompareTo(Object value), System.Int32 CompareTo(DateTime value)\nEquals               Method         System.Boolean Equals(Object value), System.Boolean Equals(DateTime value)\nGetDateTimeFormats   Method         System.String[] GetDateTimeFormats(), System.String[] GetDateTimeFormats(IFormat...\nGetHashCode          Method         System.Int32 GetHashCode()\nGetType              Method         System.Type GetType()\nGetTypeCode          Method         System.TypeCode GetTypeCode()\nget_Date             Method         System.DateTime get_Date()\nget_Day              Method         System.Int32 get_Day()\nget_DayOfWeek        Method         System.DayOfWeek get_DayOfWeek()\nget_DayOfYear        Method         System.Int32 get_DayOfYear()\nget_Hour             Method         System.Int32 get_Hour()\nget_Kind             Method         System.DateTimeKind get_Kind()\nget_Millisecond      Method         System.Int32 get_Millisecond()\nget_Minute           Method         System.Int32 get_Minute()\nget_Month            Method         System.Int32 get_Month()\nget_Second           Method         System.Int32 get_Second()\nget_Ticks            Method         System.Int64 get_Ticks()\nget_TimeOfDay        Method         System.TimeSpan get_TimeOfDay()\nget_Year             Method         System.Int32 get_Year()\nIsDaylightSavingTime Method         System.Boolean IsDaylightSavingTime()\nSubtract             Method         System.TimeSpan Subtract(DateTime value), System.DateTime Subtract(TimeSpan value)\nToBinary             Method         System.Int64 ToBinary()\nToFileTime           Method         System.Int64 ToFileTime()\nToFileTimeUtc        Method         System.Int64 ToFileTimeUtc()\nToLocalTime          Method         System.DateTime ToLocalTime()\nToLongDateString     Method         System.String ToLongDateString()\nToLongTimeString     Method         System.String ToLongTimeString()\nToOADate             Method         System.Double ToOADate()\nToShortDateString    Method         System.String ToShortDateString()\nToShortTimeString    Method         System.String ToShortTimeString()\nToString             Method         System.String ToString(), System.String ToString(String format), System.String T...\nToUniversalTime      Method         System.DateTime ToUniversalTime()\n<\/pre>\n<p>After we have the <b>DateTime<\/b> object stored in the <b>$dte<\/b> variable, we can subtract seven days from it. This will represent a date that is a week from the current date. We use the <b>AddDays<\/b> method to add a negative seven days to the date. This is how we subtract dates and is shown here: <\/p>\n<pre class=\"codeSample\">$thisWeek = $dte.AddDays(-7)<\/pre>\n<p>Now we need to initialize a couple of counter variables. We use a shortcut method that declares the variables and sets their value to null: <\/p>\n<pre class=\"codeSample\">$i = $j = $null<\/pre>\n<p>After initializing the variables, we need to load the <b>Microsoft.Office.Interop.Outlook<\/b> interop assembly. This was discussed in a fair amount of detail&nbsp;<a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/jan09\/hey0126.mspx\" target=\"_blank\">yesterday<\/a>: <\/p>\n<pre class=\"codeSample\">[Reflection.Assembly]::LoadWithPartialname(\"Microsoft.Office.Interop.Outlook\") |\nout-null\n<\/pre>\n<p>When we have loaded the assembly, we can create the enumeration. This was also discussed fairly well yesterday, and is shown here: <\/p>\n<pre class=\"codeSample\">$olFolders = \"Microsoft.Office.Interop.Outlook.OlDefaultFolders\" -as [type]<\/pre>\n<p>Then we need to create an instance of the <b>Outlook.Application<\/b> object. The <b>Outlook.Aplication<\/b> object is the main object that allows us to work with Office Outlook. To create it, we use the <b>New-Object<\/b> cmdlet and use the <b>comobject<\/b> parameter. We store the returned object in the <b>$outlook<\/b> variable as seen here:<\/p>\n<pre class=\"codeSample\">$outlook = new-object -comobject outlook.application<\/pre>\n<p>After we have created an instance of the <b>Outlook.Application<\/b> object, we can use the <b>Ge<\/b><b>t<\/b><b>NameSpace<\/b> method. There is only one value allowed for the <b>GetNameSpace<\/b> method\u2014MAPI. This line of code will always be the same when working with Office Outlook folders:<\/p>\n<pre class=\"codeSample\">$namespace = $outlook.GetNameSpace(\"MAPI\")<\/pre>\n<p>Then we need to connect to one of the default Office Outlook folders. To connect to a particular folder, we use the <b>GetDefaultFolder<\/b> method from the <b>NameSpace<\/b> object. We give it the <b>OlDefaultFolders<\/b> enumeration of <b>olFoldersSentMail<\/b> to refer to the Sent items folder. This is seen here: <\/p>\n<pre class=\"codeSample\">$folder = $namespace.getDefaultFolder($olFolders::olFolderSentMail)<\/pre>\n<p>We now want to obtain a collection of items from the Sent e-mail folder. We obtain this collection of e-mail items by querying the <b>items<\/b> property. This is not a method, even though the word <b>item<\/b> is often used as a method. (Of course, the word is <b>items<\/b> and not <b>item<\/b>, but, hey, you never know. The good thing about Windows PowerShell is we always know if we are using a method or a property, because all method calls use a set of parentheses, and properties do not.) This is seen here: <\/p>\n<pre class=\"codeSample\">$items = $folder.items<\/pre>\n<p>When we have the collection of items from the Sent e-mail folder, we pipeline the collection to the <b>For<\/b><b>E<\/b><b>ach-Object<\/b> cmdlet. We could have stored the collection into a variable, the way we would have needed to do with VBScript. But that would have been much less efficient. <\/p>\n<pre class=\"codeSample\">$items | <\/pre>\n<p>When we get to the other side of the pipeline character &#8220;|&#8221;, we send the <b>$items<\/b> to the <b>F<\/b><b>o<\/b><b>r<\/b><b>E<\/b><b>ach-Object<\/b> cmdlet. This cmdlet acts in a similar fashion as the <b>ForEach<\/b> statement. The big difference is we can use it in the middle of a pipeline to work with individual items as they come across the pipeline: <\/p>\n<pre class=\"codeSample\">Foreach-Object { <\/pre>\n<p>You can use the <b>Write-Progress<\/b> cmdlet to provide progress feedback. The <b>Write-Progress<\/b> cmdlet will display a progress bar such as the one seen in the image just below. Use of this cmdlet is a best practice when providing feedback to the user. This is because it automatically tracks the progress across the screen and allows the user to estimate if they have time to go make a pot of Darjeeling tea, which is what I did while running this script (yes, Jit, I still drink Darjeeling).<\/p>\n<p><img decoding=\"async\" height=\"427\" alt=\"Spacer\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/january\/hey0127\/hsg-1-27-09-01.jpg\" width=\"500\" border=\"0\"><\/p>\n<p>&nbsp;<\/p>\n<p>There are three parameters you need to specify when using the <b>Write-Progress<\/b> cmdlet. The first is the activity you are doing. This shows up on the first line. The next is the status message, which is used to let the user know what you are currently working on. The last is the <b>percentcomplete<\/b> parameter. There are other ways of using this cmdlet that are detailed in the online Help, but I find myself using these three parameters at least 99 percent of the&nbsp;time: <\/p>\n<pre class=\"codeSample\"> Write-Progress -activity \"Inspecting $($items.count) email messages\"  -Status \"Processing ...\" `\n-PercentComplete ($i\/$items.count*100)\n<\/pre>\n<p>Next we need to examine each piece of e-mail in the collection. We are only interested in an e-mail message if it was sent within the past week. We use one of our counter variables that we earlier initialized to keep track of the number of e-mail messages we sent this week. Because we are receiving the e-mail via the pipeline, we need to use the <b>$_<\/b> automatic variable to inspect each e-mail message as it comes along the pipeline. The <b>\u2013ge<\/b> is the greater than or equal operator. To increment the <b>$j<\/b> counter variable, we use the <b>++<\/b> operator, which means to add one to the value of the <b>$j<\/b> variable. This is the same as the <b>a = a+1<\/b> syntax of VBScript fame. The <b>$j<\/b> variable keeps track of all the e-mail messages we found that match our filter. The <b>$i<\/b> variable tracks all the e-mail messages that are processed and is used by the <b>Write-Progress<\/b> cmdlet. This section of the code is seen&nbsp;here: <\/p>\n<pre class=\"codeSample\"> if($_.ReceivedTime -ge $thisWeek) { $j++}\n$i++\n}\n<\/pre>\n<p>Now we are ready to display the total number of messages. We use a simple expanding string as seen here. The cool thing about expanding strings (double quotation marks) is that the value of the <b>$j<\/b> variable is expanded and allows us to avoid concatenation: <\/p>\n<pre class=\"codeSample\">\"Total email sent this week is $j\"<\/pre>\n<p>The output from the script is seen here: <\/p>\n<p><img decoding=\"async\" height=\"427\" alt=\"Spacer\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/january\/hey0127\/hsg-1-27-09-02.jpg\" width=\"500\" border=\"0\"><\/p>\n<p>&nbsp;<\/p>\n<p>Well, PD, that is all for the <b>CountSentEmailForWeek.ps1<\/b> script. If it saves you even 30 minutes a week, that is 26 hours a year. Make sure you include this script in your PHB report. If you use an hourly rate of $50.00 USD per hour, the script saves $1,300.00 USD per year. PHBs love that bottom line stuff, as well as <a href=\"http:\/\/en.wikipedia.org\/wiki\/Return_on_investment\" target=\"_blank\">return on investment (ROI)<\/a> using scripts. <\/p>\n<p>I asked the Scripting Wife about her chili recipe. She said she just throws whatever is left in the refrigerator into the pot. Today&#8217;s chili had mushrooms, peppers, roast beef, navy beans, pinto beans, tomatoes, and various spices. I\u2019m salivating. See you tomorrow as Office Outlook Week continues. <\/p>\n<p>&nbsp;<\/p>\n<p><b>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/b><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! The Pointy Headed Boss (PHB) just got back from some kind of stupid management summit, and he has decided he needs to track our work activities more closely. As a result, we now have to give him a weekly progress report. Seems to me that, if he would pay attention, he would [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[212,49,3,45],"class_list":["post-54523","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-microsoft-outlook","tag-office","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! The Pointy Headed Boss (PHB) just got back from some kind of stupid management summit, and he has decided he needs to track our work activities more closely. As a result, we now have to give him a weekly progress report. Seems to me that, if he would pay attention, he would [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54523","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=54523"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54523\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=54523"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=54523"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=54523"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}