<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>Code For Excel And Outlook</title>
	
	<link>http://www.codeforexcelandoutlook.com</link>
	<description>Automation and VBA code for Microsoft® Excel and Outlook</description>
	<lastBuildDate>Tue, 07 Sep 2010 11:00:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/CodeForExcelAndOutlook" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="codeforexcelandoutlook" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" /><image><link>http://www.codeforexcelandoutlook.com/</link><url>http://s929.photobucket.com/albums/ad137/jp2112jp/xo.png</url><title>Logo</title></image><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">CodeForExcelAndOutlook</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Link Excel cells to Outlook data fields</title>
		<link>http://www.codeforexcelandoutlook.com/blog/2010/09/link-excel-cells-to-outlook-data-fields/</link>
		<comments>http://www.codeforexcelandoutlook.com/blog/2010/09/link-excel-cells-to-outlook-data-fields/#comments</comments>
		<pubDate>Tue, 07 Sep 2010 11:00:14 +0000</pubDate>
		<dc:creator>JP</dc:creator>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[contact]]></category>
		<category><![CDATA[link]]></category>

		<guid isPermaLink="false">http://www.codeforexcelandoutlook.com/?p=1217</guid>
		<description><![CDATA[Have you ever wanted to link Excel data to Outlook contacts? Here is a simple event handler that links cells on your Excel worksheet to data fields in Outlook's address book. We'll use the Worksheet_Change Event to look up contact details for a given name in a cell. This is a "live" link because whenever [...]<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/09/link-excel-cells-to-outlook-data-fields/">Link Excel cells to Outlook data fields</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
]]></description>
			<content:encoded><![CDATA[<p>Have you ever wanted to link Excel data to Outlook contacts? Here is a simple event handler that links cells on your Excel worksheet to data fields in Outlook's address book.</p>
<p><span id="more-1217"></span></p>
<p>We'll use the Worksheet_Change Event to look up contact details for a given name in a cell. This is a "live" link because whenever we change the cell and enter a new name, the event handler fires and looks up the phone number, address and email and returns it to Excel. In this example, it's put into a <a href="http://www.contextures.com/xlcomments02.html">cell comment</a>, but we'll also show how we can return this information into adjacent cells.</p>
<p>Since the event fires whenever the worksheet is changed, we'll set up Outlook as a module-level variable, so it will be instantiated the first time the event fires and stay open throughout the life of the workbook. That should speed up the operation of the workbook somewhat.</p>
<p>As a bonus, we'll also check the Global Address List (GAL) for contact details, if the name isn't in the local address book! <img src='http://www.codeforexcelandoutlook.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' title="icon smile Link Excel cells to Outlook data fields" /> </p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Dim</span> Outlook <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
<span style="color: #000080;">Const</span> olFolderContacts <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span> = 10<br />
<br />
<span style="color: #000080;">Private</span> <span style="color: #000080;">Sub</span> Worksheet_Change(<span style="color: #000080;">ByVal</span> Target <span style="color: #000080;">As</span> Range)<br />
<br />
<span style="color: #000080;">Dim</span> contactName <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #000080;">Dim</span> contacts <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
<span style="color: #000080;">Dim</span> contact <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
<span style="color: #000080;">Dim</span> comment <span style="color: #000080;">As</span> Excel.Comment<br />
<span style="color: #000080;">Dim</span> contactInfo <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #000080;">Dim</span> addressLists <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> &nbsp;<span style="color: #008000;">' Outlook.AddressLists<br />
</span><span style="color: #000080;">Dim</span> GAL <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> &nbsp;<span style="color: #008000;">' Outlook.AddressList<br />
</span><span style="color: #000080;">Dim</span> addressEntries <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> &nbsp;<span style="color: #008000;">' Outlook.AddressEntries<br />
</span><span style="color: #000080;">Dim</span> addressEntry <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> &nbsp;<span style="color: #008000;">' Outlook.AddressEntry<br />
</span><br />
&nbsp; <span style="color: #008000;">' get target cell value ONLY if single cell selected<br />
</span> &nbsp;<span style="color: #000080;">If</span> Target.Cells.Count = 1 <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; contactName = Target.Value<br />
&nbsp; <span style="color: #000080;">Else</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Exit</span> <span style="color: #000080;">Sub</span><br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; <span style="color: #008000;">' ignore blanks<br />
</span> &nbsp;<span style="color: #000080;">If</span> Len(contactName) = 0 <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Exit</span> <span style="color: #000080;">Sub</span><br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; <span style="color: #008000;">' grab Outlook, if not already instantiated previously<br />
</span> &nbsp;<span style="color: #000080;">If</span> Outlook <span style="color: #000080;">Is</span> <span style="color: #000080;">Nothing</span> <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> Outlook = GetOutlookApp<br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; <span style="color: #008000;">' get contacts<br />
</span> &nbsp;<span style="color: #000080;">Set</span> contacts = GetItems(GetNS(Outlook), olFolderContacts)<br />
&nbsp; <span style="color: #008000;">' try to grab target contact<br />
</span> &nbsp;<span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">Resume</span> <span style="color: #000080;">Next</span><br />
&nbsp; <span style="color: #000080;">Set</span> contact = contacts.Item(contactName)<br />
&nbsp; <span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">GoTo</span> 0<br />
<br />
&nbsp; <span style="color: #008000;">' remove existing comment, if any<br />
</span> &nbsp;<span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">Resume</span> <span style="color: #000080;">Next</span><br />
&nbsp; <span style="color: #000080;">Set</span> comment = Target.comment<br />
&nbsp; comment.Delete<br />
&nbsp; <span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">GoTo</span> 0<br />
<br />
&nbsp; <span style="color: #000080;">If</span> contact <span style="color: #000080;">Is</span> <span style="color: #000080;">Nothing</span> <span style="color: #000080;">Then</span><br />
<br />
&nbsp; &nbsp; <span style="color: #008000;">' try to find in GAL<br />
</span> &nbsp; &nbsp;<span style="color: #000080;">Set</span> addressLists = GetNS(Outlook).AddressLists<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> GAL = addressLists.Item(<span style="color: #800000;">&quot;Global Address List&quot;</span>)<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> addressEntries = GAL.AddressEntries<br />
&nbsp; &nbsp; <span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">Resume</span> <span style="color: #000080;">Next</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> addressEntry = addressEntries.Item(Target.Value)<br />
&nbsp; &nbsp; <span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">GoTo</span> 0<br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">If</span> addressEntry <span style="color: #000080;">Is</span> <span style="color: #000080;">Nothing</span> <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">' nothing in Contacts Folder or GAL<br />
</span> &nbsp; &nbsp; &nbsp;contactInfo = <span style="color: #800000;">&quot;No contact found with this name.&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Else</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">' in GAL but not Contacts Folder<br />
</span> &nbsp; &nbsp; &nbsp;contactInfo = addressEntry.Name &amp; Chr(10) &amp; addressEntry.Address &amp; Chr(10) &amp; _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Chr(10) &amp; <span style="color: #800000;">&quot;This information came from the Global Address List.&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; <span style="color: #000080;">Else</span><br />
&nbsp; &nbsp; <span style="color: #008000;">' in Contacts Folder<br />
</span> &nbsp; &nbsp;contactInfo = contact.FullName &amp; Chr(10) &amp; contact.BusinessTelephoneNumber _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp; Chr(10) &amp; contact.Department &amp; Chr(10) &amp; _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; contact.BusinessAddress &amp; Chr(10) &amp; contact.Email1Address<br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; <span style="color: #008000;">' add comment and put contact info<br />
</span> &nbsp;Target.AddComment Text:=contactInfo<br />
&nbsp; <span style="color: #000080;">Set</span> comment = Target.comment<br />
&nbsp; comment.Shape.TextFrame.AutoSize = <span style="color: #000080;">True</span><br />
<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span><br />
<br />
<span style="color: #000080;">Function</span> GetOutlookApp() <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
&nbsp; <span style="color: #000080;">Set</span> GetOutlookApp = CreateObject(<span style="color: #800000;">&quot;Outlook.Application&quot;</span>)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<span style="color: #000080;">Function</span> GetNS(<span style="color: #000080;">ByRef</span> app <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
&nbsp; <span style="color: #000080;">Set</span> GetNS = app.GetNamespace(<span style="color: #800000;">&quot;MAPI&quot;</span>)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<span style="color: #000080;">Function</span> GetItems(olNS <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>, folder <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
&nbsp; <span style="color: #000080;">Set</span> GetItems = olNS.GetDefaultFolder(folder).Items<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<p>This event should be placed in the <a href="http://www.rondebruin.nl/code.htm#Sheet">Sheet module</a> for the sheet you want to monitor. It checks any changed cell; you probably want to change this behavior to only check the one or two cells you'll put contact names into.</p>
<p>Outlook is instantiated the first time the event fires, but is kept open by the module-level variable so we don't have to keep instantiating it every time the event fires. Of course, if you change the event handler to ONLY fire when certain cells are changed, you can change the Outlook variable scope to local (by moving it into the event handler) since it won't be instantiated as often.</p>
<p>First we try and get the contact from the local Address Book. If the contact does not exist, we check the GAL. Either way, we put the contact details into a comment for the given cell. The contents will vary, and that is reflected in the way the cell is commented.</p>
<p>This technique would work well if you have a sales worksheet with a <a href="http://office.microsoft.com/en-us/excel-help/apply-data-validation-to-cells-HP010072600.aspx">data validated list</a> of sales or customer service people. As you select each name, that person's contact details are filled in on the worksheet. It's best if you have them set up as Contacts, since more information is available through the <a href="http://msdn.microsoft.com/en-us/library/aa210907(v=office.11).aspx">ContactItem Object</a> than the <a href="http://msdn.microsoft.com/en-us/library/aa210891(office.11).aspx">AddressEntry Object</a> (using the Outlook Object Model).</p>
<h2>Return phone number to adjacent cell</h2>
<p>A slight alteration of this function is needed to return specific information to the worksheet. We don't check the GAL anymore, because it only returns name and email address. So the contact name must be in the Address Book for this event handler to be successful.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Private</span> <span style="color: #000080;">Sub</span> Worksheet_Change(<span style="color: #000080;">ByVal</span> Target <span style="color: #000080;">As</span> Range)<br />
<br />
<span style="color: #000080;">Dim</span> contactName <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #000080;">Dim</span> contacts <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
<span style="color: #000080;">Dim</span> contact <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
<span style="color: #000080;">Dim</span> contactInfo <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<br />
&nbsp; <span style="color: #008000;">' get target cell value ONLY if single cell selected<br />
</span> &nbsp;<span style="color: #000080;">If</span> Target.Cells.Count = 1 <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; contactName = Target.Value<br />
&nbsp; <span style="color: #000080;">Else</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Exit</span> <span style="color: #000080;">Sub</span><br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; <span style="color: #008000;">' ignore blanks<br />
</span> &nbsp;<span style="color: #000080;">If</span> Len(contactName) = 0 <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Exit</span> <span style="color: #000080;">Sub</span><br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; <span style="color: #008000;">' grab Outlook, if not already instantiated previously<br />
</span> &nbsp;<span style="color: #000080;">If</span> Outlook <span style="color: #000080;">Is</span> <span style="color: #000080;">Nothing</span> <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> Outlook = GetOutlookApp<br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; <span style="color: #008000;">' get contacts<br />
</span> &nbsp;<span style="color: #000080;">Set</span> contacts = GetItems(GetNS(Outlook), olFolderContacts)<br />
&nbsp; <span style="color: #008000;">' grab target contact<br />
</span> &nbsp;<span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">Resume</span> <span style="color: #000080;">Next</span><br />
&nbsp; <span style="color: #000080;">Set</span> contact = contacts.Item(contactName)<br />
&nbsp; <span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">GoTo</span> 0<br />
<br />
&nbsp; <span style="color: #000080;">If</span> contact <span style="color: #000080;">Is</span> <span style="color: #000080;">Nothing</span> <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; <span style="color: #008000;">' nothing in Contacts Folder<br />
</span> &nbsp; &nbsp;contactInfo = <span style="color: #800000;">&quot;No contact found with this name.&quot;</span><br />
&nbsp; <span style="color: #000080;">Else</span><br />
&nbsp; &nbsp; <span style="color: #008000;">' in Contacts Folder<br />
</span> &nbsp; &nbsp;contactInfo = contact.BusinessTelephoneNumber<br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; <span style="color: #008000;">' put contact info into adjacent cell<br />
</span> &nbsp;<span style="color: #008000;">' turn off Events to avoid event firing again<br />
</span> &nbsp;Application.EnableEvents = <span style="color: #000080;">False</span><br />
&nbsp; &nbsp; Target.Offset(0, 1).Value = contactInfo<br />
&nbsp; Application.EnableEvents = <span style="color: #000080;">True</span><br />
<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span><br />
<br />
<span style="color: #000080;">Function</span> GetOutlookApp() <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
&nbsp; <span style="color: #000080;">Set</span> GetOutlookApp = CreateObject(<span style="color: #800000;">&quot;Outlook.Application&quot;</span>)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<span style="color: #000080;">Function</span> GetNS(<span style="color: #000080;">ByRef</span> app <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
&nbsp; <span style="color: #000080;">Set</span> GetNS = app.GetNamespace(<span style="color: #800000;">&quot;MAPI&quot;</span>)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<span style="color: #000080;">Function</span> GetItems(olNS <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>, folder <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
&nbsp; <span style="color: #000080;">Set</span> GetItems = olNS.GetDefaultFolder(folder).Items<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/09/link-excel-cells-to-outlook-data-fields/">Link Excel cells to Outlook data fields</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=pmEqVYmNxmw:p64AhqPOxfc:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?i=pmEqVYmNxmw:p64AhqPOxfc:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=pmEqVYmNxmw:p64AhqPOxfc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/CodeForExcelAndOutlook/~4/pmEqVYmNxmw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.codeforexcelandoutlook.com/blog/2010/09/link-excel-cells-to-outlook-data-fields/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Exploring the NOAA API</title>
		<link>http://www.codeforexcelandoutlook.com/blog/2010/09/exploring-the-noaa-api/</link>
		<comments>http://www.codeforexcelandoutlook.com/blog/2010/09/exploring-the-noaa-api/#comments</comments>
		<pubDate>Fri, 03 Sep 2010 11:00:55 +0000</pubDate>
		<dc:creator>JP</dc:creator>
				<category><![CDATA[VBA]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[MSXML2]]></category>
		<category><![CDATA[XMLHTTP]]></category>

		<guid isPermaLink="false">http://www.codeforexcelandoutlook.com/?p=1196</guid>
		<description><![CDATA[The National Weather Service's National Hurricane Center tracks storms that occur in the Atlantic and Eastern Pacific oceans. Starting in July 2010, weather advisories were made available via RSS. Let's take a look at one and see what we can do with it. A list of available RSS feeds from NHC is here. The one [...]<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/09/exploring-the-noaa-api/">Exploring the NOAA API</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
]]></description>
			<content:encoded><![CDATA[<p><img src="http://i929.photobucket.com/albums/ad137/jp2112jp/NOAA_logo.gif" alt="NOAA logo" title="NOAA logo" /></p>
<p>The National Weather Service's <a href="http://www.nhc.noaa.gov/index.shtml">National Hurricane Center</a> tracks storms that occur in the Atlantic and Eastern Pacific oceans. Starting in July 2010, weather advisories were made available via RSS. Let's take a look at one and see what we can do with it.</p>
<p><span id="more-1196"></span></p>
<p>A list of available RSS feeds from NHC is <a href="http://www.nhc.noaa.gov/aboutrss.shtml#rsslist">here</a>.</p>
<p>The one we'll parse is the Atlantic (English) feed from the "Specific Tropical Cyclone Feeds by Basin" section. Here's an example of what it looks like when this article was written:</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;iso-8859-1&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;rss</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;2.0&quot;</span> <span style="color: #000066;">xmlns:dc</span>=<span style="color: #ff0000;">&quot;http://purl.org/dc/elements/1.1/&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;channel<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pubDate<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Tue, 27 Jul 2010 00:02:56 GMT<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/pubDate<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>National Hurricane Center (Atlantic)<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Active tropical cyclones in the Atlantic, Caribbean, and the Gulf of Mexico<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;link<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://www.nhc.noaa.gov/<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/link<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;copyright<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>none<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/copyright<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;managingEditor<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>nhcwebmaster@noaa.gov (nhcwebmaster)<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/managingEditor<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;language<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>en-us<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/language<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;webMaster<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>nhcwebmaster@noaa.gov (nhcwebmaster)<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/webMaster<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;image<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://www.nhc.noaa.gov/gifs/xml_logo_nhc.gif<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;link<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://www.nhc.noaa.gov/<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/link<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>NOAA logo<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>National Hurricane Center (Atlantic)<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;width<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>95<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/width<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;height<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>45<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/height<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/image<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>There are no tropical cyclones at this time.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>No tropical cyclones as of Tue, 27 Jul 2010 00:02:56 GMT<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pubDate<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Tue, 27 Jul 2010 00:02:56 GMT<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/pubDate<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;link<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://www.nhc.noaa.gov/<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/link<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;guid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://www.nhc.noaa.gov/<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/guid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;author<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>nhcwebmaster@noaa.gov (nhcwebmaster)<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/author<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Atlantic Tropical Weather Outlook<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">&lt;![CDATA[</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 000&lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ABNT20 KNHC 262336&lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TWOAT &lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TROPICAL WEATHER OUTLOOK&lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NWS TPC/NATIONAL HURRICANE CENTER MIAMI FL&lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 800 PM EDT MON JUL 26 2010&lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FOR THE NORTH ATLANTIC...CARIBBEAN SEA AND THE GULF OF MEXICO...&lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TROPICAL CYCLONE FORMATION IS NOT EXPECTED DURING THE NEXT 48 HOURS.&lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $$&lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FORECASTER CANGIALOSI/STEWART&lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;br/&gt;</span><br />
<span style="color: #339933;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ]]&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pubDate<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Mon, 26 Jul 2010 23:36:56 GMT<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/pubDate<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;link<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://www.nhc.noaa.gov/gtwo_atl.shtml<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/link<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;guid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://www.nhc.noaa.gov/gtwo_atl.shtml?201007262336<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/guid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;author<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>nhcwebmaster@noaa.gov (nhcwebmaster)<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/author<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/item<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/channel<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/rss<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>Because of the way items are listed in the feed, we'll need to start parsing from the ninth node. Of course, you can grab more information, but I felt that the first eight nodes were useless.</p>
<h2>The NOAAWeather Function</h2>
<p>This function returns all weather items available in the Atlantic (English) RSS feed from NHC/NOAA as a String array. As usual, I've preserved the early bound references so you can study the MSXML object model if you wish.</p>
<p>The API response is cached, so you'll need to pass a parameter of <strong>True</strong> (or clear your temp folder) to force a requery. And don't forget to include the <a href="#helper">helper functions</a> in your project.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> NOAAWeather(<span style="color: #000080;">Optional</span> forceRequery <span style="color: #000080;">As</span> <span style="color: #000080;">Boolean</span> = <span style="color: #000080;">False</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>()<br />
<span style="color: #008000;">' Atlantic, Caribbean, and Gulf of Mexico tropical cyclones in English<br />
</span><span style="color: #008000;">' http://www.nhc.noaa.gov/aboutrss.shtml<br />
</span> &nbsp;<span style="color: #000080;">Dim</span> xml <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSXML2.XMLHTTP<br />
</span> &nbsp;<span style="color: #000080;">Dim</span> result <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
&nbsp; <span style="color: #000080;">Dim</span> tempFile <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
&nbsp; <span style="color: #000080;">Dim</span> xmlDoc <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">'MSXML2.DOMDocument<br />
</span> &nbsp;<span style="color: #000080;">Dim</span> xmlDocRoot <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">'MSXML2.IXMLDOMNode<br />
</span> &nbsp;<span style="color: #000080;">Dim</span> rss <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">'MSXML2.IXMLDOMNode<br />
</span> &nbsp;<span style="color: #000080;">Dim</span> channel <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">'MSXML2.IXMLDOMNodeList<br />
</span> &nbsp;<span style="color: #000080;">Dim</span> item <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">'MSXML2.IXMLDOMNode<br />
</span> &nbsp;<span style="color: #000080;">Dim</span> subNodes <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">'MSXML2.IXMLDOMNodeList<br />
</span> &nbsp;<span style="color: #000080;">Dim</span> i <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span>, j <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
&nbsp; <span style="color: #000080;">Dim</span> tempString() <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
&nbsp; <span style="color: #000080;">Dim</span> numRows <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
<br />
&nbsp; <span style="color: #000080;">Const</span> numCols <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span> = 6<br />
<br />
&nbsp; <span style="color: #000080;">Set</span> xml = CreateObject(<span style="color: #800000;">&quot;MSXML2.XMLHTTP&quot;</span>)<br />
<br />
&nbsp; tempFile = Environ(<span style="color: #800000;">&quot;temp&quot;</span>) &amp; Application.PathSeparator &amp; <span style="color: #800000;">&quot;weather.xml&quot;</span><br />
<br />
&nbsp; <span style="color: #000080;">If</span> (Len(Dir(tempFile)) = 0 <span style="color: #000080;">Or</span> forceRequery) <span style="color: #000080;">Then</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">With</span> xml<br />
&nbsp; &nbsp; &nbsp; .<span style="color: #000080;">Open</span> <span style="color: #800000;">&quot;GET&quot;</span>, <span style="color: #800000;">&quot;http://www.nhc.noaa.gov/index-at.xml&quot;</span><br />
&nbsp; &nbsp; &nbsp; .send<br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">With</span><br />
<br />
&nbsp; &nbsp; result = xml.responseText<br />
<br />
&nbsp; &nbsp; <span style="color: #008000;">' create XML file from result<br />
</span> &nbsp; &nbsp;<span style="color: #000080;">Call</span> CreateXMLFile(tempFile, result)<br />
<br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; <span style="color: #000080;">Set</span> xmlDoc = CreateObject(<span style="color: #800000;">&quot;MSXML2.DOMDocument&quot;</span>)<br />
<br />
&nbsp; <span style="color: #000080;">With</span> xmlDoc<br />
&nbsp; &nbsp; .async = <span style="color: #000080;">False</span><br />
&nbsp; &nbsp; .validateOnParse = <span style="color: #000080;">False</span><br />
&nbsp; &nbsp; .Load tempFile<br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">With</span><br />
<br />
&nbsp; <span style="color: #008000;">' check that the XML doc loaded<br />
</span> &nbsp;<span style="color: #000080;">If</span> LoadError(xmlDoc) <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Exit</span> <span style="color: #000080;">Function</span><br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; <span style="color: #008000;">' get root node<br />
</span> &nbsp;<span style="color: #000080;">Set</span> xmlDocRoot = GetRootNode(xmlDoc)<br />
&nbsp; <span style="color: #000080;">Set</span> rss = xmlDocRoot.childNodes(0)<br />
&nbsp; <span style="color: #000080;">Set</span> channel = GetChildNodes(rss)<br />
<br />
&nbsp; numRows = channel.Length - 9<br />
<br />
&nbsp; <span style="color: #008000;">' resize array<br />
</span> &nbsp;<span style="color: #000080;">ReDim</span> tempString(1 <span style="color: #000080;">To</span> numRows, 1 <span style="color: #000080;">To</span> numCols)<br />
<br />
&nbsp; <span style="color: #000080;">For</span> i = 9 <span style="color: #000080;">To</span> channel.Length - 1<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> item = channel.item(i)<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> subNodes = GetChildNodes(item)<br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">For</span> j = 1 <span style="color: #000080;">To</span> subNodes.Length<br />
&nbsp; &nbsp; &nbsp; tempString(i - 8, j) = subNodes.item(j - 1).nodeTypedValue<br />
&nbsp; &nbsp; <span style="color: #000080;">Next</span> j<br />
&nbsp; <span style="color: #000080;">Next</span> i<br />
<br />
&nbsp; NOAAWeather = tempString<br />
<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<p>As I mentioned earlier, I felt the first nine nodes were useless, so the number of "rows" in the array is nine less than the total. Since there are eleven nodes, the total output will be two "records", with six pieces of information each. Then it's a "simple" matter of parsing the XML to grab the data we want.</p>
<h2>Sample usage</h2>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Sub</span> TestNOAAWebsite()<br />
<br />
&nbsp; <span style="color: #000080;">Dim</span> results() <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
&nbsp; <span style="color: #000080;">Dim</span> i <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span>, j <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
<br />
&nbsp; results = NOAAWeather<br />
<br />
&nbsp; <span style="color: #000080;">For</span> i = <span style="color: #000080;">LBound</span>(results) <span style="color: #000080;">To</span> <span style="color: #000080;">UBound</span>(results)<br />
&nbsp; &nbsp; <span style="color: #000080;">For</span> j = <span style="color: #000080;">LBound</span>(results, 2) <span style="color: #000080;">To</span> <span style="color: #000080;">UBound</span>(results, 2)<br />
&nbsp; &nbsp; &nbsp; Debug.<span style="color: #000080;">Print</span> results(i, j)<br />
&nbsp; &nbsp; <span style="color: #000080;">Next</span> j<br />
&nbsp; <span style="color: #000080;">Next</span> i<br />
<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span></div></div>
<h2>Output</h2>
<p>The output looks like this:</p>
<blockquote><p>There are no tropical cyclones at this time.<br />
No tropical cyclones as of Mon, 26 Jul 2010 21:55:14 GMT<br />
Mon, 26 Jul 2010 21:55:14 GMT</p>
<p>http://www.nhc.noaa.gov/</p>
<p>http://www.nhc.noaa.gov/</p>
<p>nhcwebmaster@noaa.gov (nhcwebmaster)<br />
Atlantic Tropical Weather Outlook</p>
<p><br/><br />
000<br/><br />
ABNT20 KNHC 261747<br/><br />
TWOAT <br/><br />
TROPICAL WEATHER OUTLOOK<br/><br />
NWS TPC/NATIONAL HURRICANE CENTER MIAMI FL<br/><br />
200 PM EDT MON JUL 26 2010<br/><br />
<br/><br />
FOR THE NORTH ATLANTIC&#8230;CARIBBEAN SEA AND THE GULF OF MEXICO&#8230;<br/><br />
<br/><br />
TROPICAL CYCLONE FORMATION IS NOT EXPECTED DURING THE NEXT 48 HOURS.<br/><br />
<br/><br />
$$<br/><br />
FORECASTER ROBERTS/PASCH<br/><br />
<br/></p>
<p>Mon, 26 Jul 2010 17:47:23 GMT</p>
<p>http://www.nhc.noaa.gov/gtwo_atl.shtml</p>
<p>http://www.nhc.noaa.gov/gtwo_atl.shtml?201007261747</p>
<p>nhcwebmaster@noaa.gov (nhcwebmaster)</p></blockquote>
<h2 id="helper">Helper Functions</h2>
<p>These functions should be pasted into a standard module in the same project as the code above.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> GetChildNodes(node <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
<span style="color: #008000;">' returns child nodes for a given MSXML2.IXMLDOMNode<br />
</span> &nbsp;<span style="color: #000080;">Set</span> GetChildNodes = node.childNodes<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<br />
<span style="color: #000080;">Function</span> CreateXMLFile(fileName <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, contents <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #008000;">' creates XML file from string contents<br />
</span><br />
&nbsp; <span style="color: #000080;">Dim</span> tempFile <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
&nbsp; <span style="color: #000080;">Dim</span> nextFileNum <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
<br />
&nbsp; nextFileNum = FreeFile<br />
<br />
&nbsp; tempFile = fileName<br />
<br />
&nbsp; <span style="color: #000080;">Open</span> tempFile <span style="color: #000080;">For</span> <span style="color: #000080;">Output</span> <span style="color: #000080;">As</span> #nextFileNum<br />
&nbsp; <span style="color: #000080;">Print</span> #nextFileNum, FixAngleBrackets(contents)<br />
&nbsp; <span style="color: #000080;">Close</span> #nextFileNum<br />
<br />
&nbsp; CreateXMLFile = tempFile<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<br />
<span style="color: #000080;">Function</span> GetRootNode(xmlDoc <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
<span style="color: #008000;">' returns root node<br />
</span> &nbsp;<span style="color: #000080;">Set</span> GetRootNode = xmlDoc.documentElement<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<br />
<span style="color: #000080;">Function</span> LoadError(xmlDoc <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Boolean</span><br />
<span style="color: #008000;">' checks if a xml file load error occurred<br />
</span> &nbsp;LoadError = (xmlDoc.parseError.errorCode &lt;&gt; 0)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<br />
<span style="color: #000080;">Function</span> FixAngleBrackets(textString <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
&nbsp; FixAngleBrackets = Replace(Replace(textString, <span style="color: #800000;">&quot;&amp;lt;&quot;</span>, <span style="color: #800000;">&quot;&lt;&quot;</span>), <span style="color: #800000;">&quot;&amp;gt;&quot;</span>, <span style="color: #800000;">&quot;&gt;&quot;</span>)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<br />
<span style="color: #000080;">Function</span> ConvertAccent(<span style="color: #000080;">ByVal</span> inputString <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #008000;">' http://www.vbforums.com/archive/index.php/t-483965.html<br />
</span><br />
&nbsp; <span style="color: #000080;">Const</span> AccChars <span style="color: #000080;">As</span> <span style="color: #000080;">String</span> = _<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #800000;">&quot;ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðñòóôõöùúûüýÿ&quot;</span><br />
&nbsp; <span style="color: #000080;">Const</span> RegChars <span style="color: #000080;">As</span> <span style="color: #000080;">String</span> = _<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #800000;">&quot;SZszYAAAAAACEEEEIIIIDNOOOOOUUUUYaaaaaaceeeeiiiidnooooouuuuyy&quot;</span><br />
<br />
&nbsp; <span style="color: #000080;">Dim</span> i <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span>, j <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
&nbsp; <span style="color: #000080;">Dim</span> tempString <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
&nbsp; <span style="color: #000080;">Dim</span> currentCharacter <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
&nbsp; <span style="color: #000080;">Dim</span> found <span style="color: #000080;">As</span> <span style="color: #000080;">Boolean</span><br />
&nbsp; <span style="color: #000080;">Dim</span> foundPosition <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
<br />
&nbsp; tempString = inputString<br />
<br />
&nbsp; <span style="color: #008000;">' loop through the shorter string<br />
</span> &nbsp;<span style="color: #000080;">Select</span> <span style="color: #000080;">Case</span> <span style="color: #000080;">True</span><br />
&nbsp; <span style="color: #000080;">Case</span> Len(AccChars) &lt;= Len(inputString)<br />
&nbsp; &nbsp; <span style="color: #008000;">' accent character list is shorter (or same)<br />
</span> &nbsp; &nbsp;<span style="color: #008000;">' loop through accent character string<br />
</span> &nbsp; &nbsp;<span style="color: #000080;">For</span> i = 1 <span style="color: #000080;">To</span> Len(AccChars)<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">' get next accent character<br />
</span> &nbsp; &nbsp; &nbsp;currentCharacter = Mid$(AccChars, i, 1)<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">' replace with corresponding character in &quot;regular&quot; array<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #000080;">If</span> InStr(tempString, currentCharacter) &gt; 0 <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; tempString = Replace(tempString, currentCharacter, Mid$(RegChars, i, 1))<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">Next</span> i<br />
&nbsp; <span style="color: #000080;">Case</span> Len(AccChars) &gt; Len(inputString)<br />
&nbsp; &nbsp; <span style="color: #008000;">' input string is shorter<br />
</span> &nbsp; &nbsp;<span style="color: #008000;">' loop through input string<br />
</span> &nbsp; &nbsp;<span style="color: #000080;">For</span> i = 1 <span style="color: #000080;">To</span> Len(inputString)<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">' grab current character from input string and<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #008000;">' determine if it is a special char<br />
</span> &nbsp; &nbsp; &nbsp;currentCharacter = Mid$(inputString, i, 1)<br />
&nbsp; &nbsp; &nbsp; found = (InStr(AccChars, currentCharacter) &gt; 0)<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000080;">If</span> found <span style="color: #000080;">Then</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">' find position of special character in special array<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp;foundPosition = InStr(AccChars, currentCharacter)<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">' replace with corresponding character in &quot;regular&quot; array<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp;tempString = Replace(tempString, currentCharacter, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Mid$(RegChars, foundPosition, 1))<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Next</span> i<br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">Select</span><br />
<br />
&nbsp; ConvertAccent = tempString<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/09/exploring-the-noaa-api/">Exploring the NOAA API</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=0Z3np1oXcs8:Og5yLxMAga4:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?i=0Z3np1oXcs8:Og5yLxMAga4:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=0Z3np1oXcs8:Og5yLxMAga4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/CodeForExcelAndOutlook/~4/0Z3np1oXcs8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.codeforexcelandoutlook.com/blog/2010/09/exploring-the-noaa-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mailto Links in VBA</title>
		<link>http://www.codeforexcelandoutlook.com/blog/2010/08/mailto-links-in-vba/</link>
		<comments>http://www.codeforexcelandoutlook.com/blog/2010/08/mailto-links-in-vba/#comments</comments>
		<pubDate>Tue, 31 Aug 2010 11:00:02 +0000</pubDate>
		<dc:creator>JP</dc:creator>
				<category><![CDATA[VBA]]></category>
		<category><![CDATA[hyperlink]]></category>
		<category><![CDATA[mailto]]></category>

		<guid isPermaLink="false">http://www.codeforexcelandoutlook.com/?p=1200</guid>
		<description><![CDATA[On Jon Fournier's blog there's a VBA procedure to create a mailto: link in a macro. I like it but I feel it could use some more detail. I'll present an alternate with a few changes. Default Subject and Body His procedure allows you to specify a blank subject and body when calling it. I [...]<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/mailto-links-in-vba/">Mailto Links in VBA</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
]]></description>
			<content:encoded><![CDATA[<p><img src="http://i929.photobucket.com/albums/ad137/jp2112jp/MAILTO-icon.png" alt="mailto" title="mailto" /></p>
<p>On Jon Fournier's blog there's a VBA procedure to create a <a href="http://jon-fournier.blogspot.com/2010/03/using-mailto-in-vba-macro.html">mailto: link in a macro</a>. I like it but I feel it could use some more detail. I'll present an alternate with a few changes.</p>
<p><span id="more-1200"></span></p>
<h2>Default Subject and Body</h2>
<p>His procedure allows you to specify a blank subject and body when calling it. I prefer to use a default subject and body, especially since the procedure is part of a larger tool. I can prefill in the subject and body with information I (as the developer) need.</p>
<h2>Email Validation</h2>
<p>There is no validation on the email address whatsoever. I've already written code that <a href="http://www.codeforexcelandoutlook.com/blog/2010/02/email-validation-in-vba/">validates email addresses</a> and we'll put it to good use here.</p>
<h2>URL Encoding</h2>
<p>The body is not URL encoded, so (when I tested it) words will drop off the body and not appear in the email. We're going to URL encode the body string so that the entire text will appear in the message.</p>
<h2>API Usage</h2>
<p>The code uses a Windows API to run the mailto link. I prefer the Windows Script Host Object Model (WSHOM) to run the link. To me it's simpler. I didn't check if there's a difference in speed, it's just a personal preference.</p>
<h2>The StartEmail Procedure</h2>
<p>The code starts by assuming a subject and body. I tried using a constant to define the name of the app (as the subject) but VBA won't allow that. See below for additional functions needed by this procedure.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Sub</span> StartEmail(toAddr <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, <span style="color: #000080;">Optional</span> subject <span style="color: #000080;">As</span> <span style="color: #000080;">String</span> = <span style="color: #800000;">&quot;My App&quot;</span>, _<br />
&nbsp; &nbsp; <span style="color: #000080;">Optional</span> body <span style="color: #000080;">As</span> <span style="color: #000080;">String</span> = <span style="color: #800000;">&quot;Hello World!&quot;</span>)<br />
<span style="color: #000080;">Dim</span> URL <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #000080;">Dim</span> oShell <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
<br />
&nbsp; <span style="color: #008000;">' validate email<br />
</span> &nbsp;<span style="color: #000080;">If</span> IsValidEmail(ToAddr) <span style="color: #000080;">Then</span><br />
<br />
&nbsp; &nbsp; URL = <span style="color: #800000;">&quot;mailto:&quot;</span> &amp; toAddr<br />
&nbsp; &nbsp; URL = URL &amp; <span style="color: #800000;">&quot;?subject=&quot;</span> &amp; subject<br />
&nbsp; &nbsp; URL = URL &amp; <span style="color: #800000;">&quot;&amp;body=&quot;</span> &amp; URLEncode(body)<br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> oShell = GetShell<br />
&nbsp; &nbsp; oShell.Run URL<br />
<br />
&nbsp; <span style="color: #000080;">Else</span><br />
&nbsp; &nbsp; MsgBox <span style="color: #800000;">&quot;email address invalid.&quot;</span><br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span></div></div>
<p>After validating the email address (see <a href="#IsValidEmail">Validate email address</a> below), the URL to be run is constructed. The message body is URL encoded so that nothing is dropped. For example, if I pass "Hello World" to the original procedure, the body will say "Hello" and "World" will be dropped because the space in the URL isn't encoded.</p>
<p>Finally, to run the URL I use the WSHOM's shell scripting abilities. See <a href="http://www.codeforexcelandoutlook.com/vba/shell-scripting-using-vba-and-the-windows-script-host-object-model/">Shell Scripting using VBA and the Windows Script Host Object Model</a> for more code samples. Like I said earlier, I find it simpler than the Windows API.</p>
<p>To URL encode the message body, download the <a href="http://www.freevbcode.com/ShowCode.Asp?ID=5137">URLEncode function</a> and change this line:</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">erg = Replace(erg, Chr(i), <span style="color: #800000;">&quot;+&quot;</span>)</div></div>
<p>to this:</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">erg = Replace(erg, Chr(i), <span style="color: #800000;">&quot;%20&quot;</span>)</div></div>
<h2 id="IsValidEmail">Validate email address</h2>
<p>To validate email addresses, I use a <a href="http://www.codeforexcelandoutlook.com/blog/2010/02/email-validation-in-vba/">web API</a>. This goes further than <a href="http://www.msofficegurus.com/post/How-to-VBA-email-validation.aspx">Regex</a> (or trying to <a href="http://simoncpage.co.uk/blog/2009/07/07/excel-vb-validate-email-address/">hardcode valid domains</a>) by actually asking the <em>mail server</em> if the email address is valid.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> IsValidEmail(emailAddress <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Boolean</span><br />
<span style="color: #000080;">Dim</span> xml <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
<span style="color: #000080;">Dim</span> result <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
&nbsp; <span style="color: #000080;">Set</span> xml = CreateObject(<span style="color: #800000;">&quot;MSXML2.XMLHTTP&quot;</span>)<br />
<br />
&nbsp; xml.<span style="color: #000080;">Open</span> <span style="color: #800000;">&quot;GET&quot;</span>, _<br />
&nbsp; &nbsp; <span style="color: #800000;">&quot;http://www.webservicex.net/ValidateEmail.asmx/IsValidEmail?Email=&quot;</span> &amp; emailAddress, <span style="color: #000080;">False</span><br />
&nbsp; xml.send<br />
<br />
&nbsp; result = xml.responseText<br />
<br />
&nbsp; <span style="color: #008000;">' parse result for response<br />
</span> &nbsp;IsValidEmail = (InStr(result, <span style="color: #800000;">&quot;true&quot;</span>) &gt; 0)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<h2>WSHOM Shell Object</h2>
<p>To return the Shell Object I use this function.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> GetShell() <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
&nbsp; <span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">Resume</span> <span style="color: #000080;">Next</span><br />
&nbsp; <span style="color: #000080;">Set</span> GetShell = CreateObject(<span style="color: #800000;">&quot;WScript.Shell&quot;</span>)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<h2>Sample usage</h2>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Sub</span> TestStartEmail()<br />
&nbsp; StartEmail (<span style="color: #800000;">&quot;someone@somewhere.com&quot;</span>, <span style="color: #800000;">&quot;Excel Application&quot;</span>, <span style="color: #800000;">&quot;My Support Question:&quot;</span>)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span></div></div>
<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/mailto-links-in-vba/">Mailto Links in VBA</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=26GHS2JTY0g:xfpiA3hFEW4:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?i=26GHS2JTY0g:xfpiA3hFEW4:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=26GHS2JTY0g:xfpiA3hFEW4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/CodeForExcelAndOutlook/~4/26GHS2JTY0g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.codeforexcelandoutlook.com/blog/2010/08/mailto-links-in-vba/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Calculate Working Hours In Reverse</title>
		<link>http://www.codeforexcelandoutlook.com/blog/2010/08/calculate-working-hours-in-reverse/</link>
		<comments>http://www.codeforexcelandoutlook.com/blog/2010/08/calculate-working-hours-in-reverse/#comments</comments>
		<pubDate>Fri, 27 Aug 2010 11:00:26 +0000</pubDate>
		<dc:creator>JP</dc:creator>
				<category><![CDATA[Excel]]></category>
		<category><![CDATA[working hours]]></category>

		<guid isPermaLink="false">http://www.codeforexcelandoutlook.com/?p=1212</guid>
		<description><![CDATA[Problem: Every day I come in to work and intend to work eight hours. If I come in at 8:30 AM, and given an hour lunch, what time do I need to leave to work exactly eight hours? Furthermore, if I come in a different time (or take a shorter lunch break), I still need [...]<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/calculate-working-hours-in-reverse/">Calculate Working Hours In Reverse</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
]]></description>
			<content:encoded><![CDATA[<p><img src="http://i929.photobucket.com/albums/ad137/jp2112jp/clock.gif" alt="clock" title="clock" /></p>
<p>Problem: Every day I come in to work and intend to work eight hours. If I come in at 8:30 AM, and given an hour lunch, <strong>what time do I need to leave to work exactly eight hours?</strong></p>
<p><span id="more-1212"></span></p>
<p>Furthermore, if I come in a different time (or take a shorter lunch break), I still need to know what time to leave.</p>
<h2>Calculate Elapsed Time</h2>
<p>Figuring out the number of hours I worked is simple. Just subtract my start time from my lunch start time, and subtract my lunch ending time from the time I leave.</p>
<p><img src="http://i929.photobucket.com/albums/ad137/jp2112jp/HoursWorked.png" alt="hours worked" title="hours worked" /></p>
<p>In this example, the formula in E2 is:</p>
<h3><strong>=((B2-A2)*24)+((D2-C2)*24)</strong></h3>
<p>The problem is that this method requires trial and error to guess the correct time to leave. You have to repeatedly enter a time value into cell D2 and see if cell E2 equals eight. There has to be a better way.</p>
<p><strong>Turns out there is!</strong></p>
<p>We can calculate the time we need to leave using a formula. All you need to do is change E2 to a value (i.e. just enter the number of hours to be worked in cell E2) and use this formula to calculate the end time.</p>
<p><img src="http://i929.photobucket.com/albums/ad137/jp2112jp/whattimetoleave.png" title="whattimetoleave Calculate Working Hours In Reverse" alt="whattimetoleave" /></p>
<p>The formula in cell D2 is:</p>
<h3><strong>=C2+((E2-((B2*24)-(A2*24)))/24)</strong></h3>
<p>(it can also be written simply as <strong>=C2+((E2-((B2-A2)*24))/24)</strong>)</p>
<p>So you enter your start time, the time you leave for lunch and the time you come back from lunch, and the formula tells you what time you can leave!</p>
<p>The way it works is simple: We start with the ending lunch time, and we need to add a certain amount of hours to it to reach eight total hours. How many hours do we add? <em>The difference between 8 and the number of hours we've already worked.</em></p>
<p>In the above example, I've already worked four hours, so to get to eight I need four more hours added to the end of my lunch break (because eight minus four equals four): 1:30 PM + 4 hours = 5:30 PM.</p>
<p>Note that cells A2:D2 are formatted as Time values. The division by 24 in the examples above is necessary due to the way Excel treats time values.</p>
<h2>Named Cells</h2>
<p>The hardcoded values and vague cell references are pretty scary. So I named the cells (and added a <a href="http://www.bettersolutions.com/excel/EFC133/QL325782331.htm">constant</a> called HoursPerDay which equals 24). Here's what the final formula looks like:</p>
<h3><strong>=LunchEnd+((NumHours-((LunchStart-StartTime)*HoursPerDay))/HoursPerDay)</strong></h3>
<p>All of you clock punchers out there may start heaping praise in 3 &#8230; 2 &#8230; 1 &#8230; go!</p>
<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/calculate-working-hours-in-reverse/">Calculate Working Hours In Reverse</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=WQM28ARo6GU:-CemQSHhfGc:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?i=WQM28ARo6GU:-CemQSHhfGc:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=WQM28ARo6GU:-CemQSHhfGc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/CodeForExcelAndOutlook/~4/WQM28ARo6GU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.codeforexcelandoutlook.com/blog/2010/08/calculate-working-hours-in-reverse/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Get Data Validation Range</title>
		<link>http://www.codeforexcelandoutlook.com/blog/2010/08/get-data-validation-range/</link>
		<comments>http://www.codeforexcelandoutlook.com/blog/2010/08/get-data-validation-range/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 11:00:54 +0000</pubDate>
		<dc:creator>JP</dc:creator>
				<category><![CDATA[Excel]]></category>
		<category><![CDATA[range]]></category>
		<category><![CDATA[validation]]></category>

		<guid isPermaLink="false">http://www.codeforexcelandoutlook.com/?p=1203</guid>
		<description><![CDATA[In Add Data Validation to any worksheet using VBA I demonstrated a technique for &#8230; adding data validation to any range. Surprise! Now we'll try and do something with those data validation ranges. What I'd like to do is select a cell that has data validation on it and return the list of valid members [...]<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/get-data-validation-range/">Get Data Validation Range</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
]]></description>
			<content:encoded><![CDATA[<p><img src="http://i929.photobucket.com/albums/ad137/jp2112jp/checkmark2.png" alt="valid" title="valid" /></p>
<p>In <a href="http://www.codeforexcelandoutlook.com/blog/2010/08/add-data-validation-to-any-worksheet-using-vba/">Add Data Validation to any worksheet using VBA</a> I demonstrated a technique for &#8230; adding data validation to any range. Surprise! <img src='http://www.codeforexcelandoutlook.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' title="icon wink Get Data Validation Range" /> </p>
<p>Now we'll try and do something with those data validation ranges. What I'd like to do is select a cell that has data validation on it and return the list of valid members (assuming that the source data is a Range or name that refers to a Range).</p>
<p><span id="more-1203"></span></p>
<p>For example, if cell A1 has the 'List'-style data validation applied to it, and the source data is H1:H10, I want to return the values in H1:H10.</p>
<p><img src="http://i929.photobucket.com/albums/ad137/jp2112jp/GetDataValRange1.png" alt="data validation range" title="data validation range" /></p>
<p>So I wrote a function that takes a <a href="http://msdn.microsoft.com/en-us/library/aa174290(v=office.11).aspx">Range Object</a> as an argument and returns the source data for the Data Validation as a Range Object.</p>
<h2 id="GetValidationRange">The GetValidationRange Function</h2>
<p>This function isn't as robust as it could be. For example, if you choose the "List" option and enter a set of values directly into the dialog box, the function will fail because it's expecting a Range or a name that points to a Range. We'll work on another version in a bit. But here goes:</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> GetValidationRange(rng <span style="color: #000080;">As</span> Excel.Range) <span style="color: #000080;">As</span> Excel.Range<br />
<br />
<span style="color: #000080;">Dim</span> currentValidation <span style="color: #000080;">As</span> Excel.Validation<br />
<span style="color: #000080;">Dim</span> targetRange <span style="color: #000080;">As</span> Excel.Range<br />
<span style="color: #000080;">Dim</span> validationType <span style="color: #000080;">As</span> Excel.XlDVType<br />
<br />
&nbsp; <span style="color: #008000;">' grab Validation object and type<br />
</span> &nbsp;<span style="color: #000080;">Set</span> currentValidation = rng.validation<br />
&nbsp; <span style="color: #008000;">' check for no existing validation, or multiple validation criteria<br />
</span> &nbsp;<span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">Resume</span> <span style="color: #000080;">Next</span><br />
&nbsp; &nbsp; validationType = currentValidation.<span style="color: #000080;">Type</span><br />
&nbsp; &nbsp; <span style="color: #000080;">If</span> Err.number &lt;&gt; 0 <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000080;">Exit</span> <span style="color: #000080;">Function</span><br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; <span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">GoTo</span> 0<br />
<br />
&nbsp; <span style="color: #008000;">' formulas only used in List and Custom types<br />
</span> &nbsp;<span style="color: #000080;">If</span> (validationType = xlValidateList <span style="color: #000080;">Or</span> validationType = xlValidateCustom) <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #008000;">' test for range reference and not a list of values<br />
</span> &nbsp; &nbsp;<span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">Resume</span> <span style="color: #000080;">Next</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> targetRange = Excel.Range(currentValidation.Formula1)<br />
&nbsp; &nbsp; <span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">GoTo</span> 0<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000080;">If</span> <span style="color: #000080;">Not</span> targetRange <span style="color: #000080;">Is</span> <span style="color: #000080;">Nothing</span> <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000080;">Set</span> GetValidationRange = targetRange<br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<h2>Sample usage</h2>
<p>Now I can retrieve all possible valid values for a given data validation cell. Suppose I have a cell with data validation applied (cell A1) and it's linked to a chart on the worksheet. I want to cycle through all the values and print the newly updated chart each time the source data (the cell with data validation) changes.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Sub</span> TestValidation()<br />
<br />
<span style="color: #000080;">Dim</span> wkshtChart <span style="color: #000080;">As</span> Excel.Chart<br />
<span style="color: #000080;">Dim</span> wksht <span style="color: #000080;">As</span> Excel.Worksheet<br />
<span style="color: #000080;">Dim</span> rng <span style="color: #000080;">As</span> Excel.Range<br />
<span style="color: #000080;">Dim</span> targetRange <span style="color: #000080;">As</span> Excel.Range<br />
<span style="color: #000080;">Dim</span> arrData <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span><br />
<span style="color: #000080;">Dim</span> i <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
<br />
&nbsp; <span style="color: #008000;">' assume active sheet<br />
</span> &nbsp;<span style="color: #000080;">Set</span> wksht = ActiveSheet<br />
&nbsp; <span style="color: #008000;">' chart to be printed, assume it's the only chart object on the sheet<br />
</span> &nbsp;<span style="color: #000080;">Set</span> wkshtChart = wksht.ChartObjects(1).Chart<br />
&nbsp; <span style="color: #008000;">' validation cell linked to chart<br />
</span> &nbsp;<span style="color: #000080;">Set</span> rng = wksht.Range(<span style="color: #800000;">&quot;A1&quot;</span>)<br />
&nbsp; <span style="color: #008000;">' get data validation range<br />
</span> &nbsp;<span style="color: #000080;">Set</span> targetRange = GetValidationRange(rng)<br />
&nbsp; <br />
&nbsp; <span style="color: #000080;">If</span> targetRange <span style="color: #000080;">Is</span> <span style="color: #000080;">Nothing</span> <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; MsgBox <span style="color: #800000;">&quot;could not get validation range&quot;</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Exit</span> <span style="color: #000080;">Sub</span><br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; <span style="color: #008000;">' assign validation values to array<br />
</span> &nbsp;<span style="color: #000080;">ReDim</span> arrData(1 <span style="color: #000080;">To</span> targetRange.count)<br />
&nbsp; arrData = Application.WorksheetFunction.Transpose(targetRange.value)<br />
<br />
&nbsp; <span style="color: #008000;">' put each array value into worksheet, chart will auto-update<br />
</span> &nbsp;<span style="color: #000080;">For</span> i = 1 <span style="color: #000080;">To</span> targetRange.count<br />
&nbsp; &nbsp; rng.value = arrData(i)<br />
<br />
&nbsp; &nbsp; <span style="color: #008000;">' print chart<br />
</span> &nbsp; &nbsp;wkshtChart.PrintOut<br />
<br />
&nbsp; &nbsp; <span style="color: #008000;">' pause 2 seconds to allow for printing<br />
</span> &nbsp; &nbsp;Application.Wait (Now + TimeValue(<span style="color: #800000;">&quot;0:00:02&quot;</span>))<br />
&nbsp; <span style="color: #000080;">Next</span> i<br />
<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span></div></div>
<h2>Retrieve Data Validation Values</h2>
<p>Instead of a Range Object, let's retrieve the <em>values</em> associated with a data validation range. The advantage of this function is that it will return the possible values available to a cell regardless of where those values come from &#8212; a range, a range name, a formula, or a literal list of values.</p>
<p>Because of this, the function is declared As Variant. If the type is "List" or "Custom" and the source is a formula or range name, the range <em>values</em> are put into a Variant.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> GetValidationRange2(rng <span style="color: #000080;">As</span> Excel.Range) <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span><br />
<br />
<span style="color: #000080;">Dim</span> currentValidation <span style="color: #000080;">As</span> Excel.validation<br />
<span style="color: #000080;">Dim</span> targetRange <span style="color: #000080;">As</span> Excel.Range<br />
<span style="color: #000080;">Dim</span> validationType <span style="color: #000080;">As</span> Excel.XlDVType<br />
<span style="color: #000080;">Dim</span> tempValues() <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span><br />
<br />
&nbsp; <span style="color: #008000;">' grab Validation object and type<br />
</span> &nbsp;<span style="color: #000080;">Set</span> currentValidation = rng.validation<br />
&nbsp; <span style="color: #008000;">' check for no existing validation, or multiple validation criteria<br />
</span> &nbsp;<span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">Resume</span> <span style="color: #000080;">Next</span><br />
&nbsp; &nbsp; validationType = currentValidation.<span style="color: #000080;">Type</span><br />
&nbsp; &nbsp; <span style="color: #000080;">If</span> Err.number &lt;&gt; 0 <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000080;">Exit</span> <span style="color: #000080;">Function</span><br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; <span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">GoTo</span> 0<br />
<br />
&nbsp; <span style="color: #008000;">' formulas only used in List and Custom types<br />
</span> &nbsp;<span style="color: #000080;">If</span> (validationType = xlValidateList <span style="color: #000080;">Or</span> validationType = xlValidateCustom) <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #008000;">' test for range reference<br />
</span> &nbsp; &nbsp;<span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">Resume</span> <span style="color: #000080;">Next</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Set</span> targetRange = Excel.Range(currentValidation.Formula1)<br />
&nbsp; &nbsp; <span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">GoTo</span> 0<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #008000;">' get values from range, or directly from data validation dialog box<br />
</span> &nbsp; &nbsp;<span style="color: #000080;">If</span> <span style="color: #000080;">Not</span> targetRange <span style="color: #000080;">Is</span> <span style="color: #000080;">Nothing</span> <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; tempValues = WorksheetFunction.Transpose(targetRange.value)<br />
&nbsp; &nbsp; <span style="color: #000080;">Else</span><br />
&nbsp; &nbsp; &nbsp; tempValues = Split(currentValidation.Formula1, <span style="color: #800000;">&quot;,&quot;</span>)<br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; GetValidationRange2 = tempValues<br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<p>The only difference here is that the <em>values</em> from the range, or the <em>values</em> typed directly into the source box, are put into the array.</p>
<h2>Sample usage</h2>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Sub</span> LoopThroughValidation2()<br />
<br />
<span style="color: #000080;">Dim</span> wkshtChart <span style="color: #000080;">As</span> Excel.Chart<br />
<span style="color: #000080;">Dim</span> wksht <span style="color: #000080;">As</span> Excel.Worksheet<br />
<span style="color: #000080;">Dim</span> rng <span style="color: #000080;">As</span> Excel.Range<br />
<span style="color: #000080;">Dim</span> dataValidationValues() <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span><br />
<span style="color: #000080;">Dim</span> i <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
<br />
&nbsp; <span style="color: #000080;">Set</span> wksht = ActiveSheet<br />
&nbsp; <span style="color: #008000;">' chart to be printed<br />
</span> &nbsp;<span style="color: #008000;">' assume one embedded chart<br />
</span> &nbsp;<span style="color: #000080;">Set</span> wkshtChart = wksht.ChartObjects(1).Chart<br />
&nbsp; <span style="color: #008000;">' validation cell<br />
</span> &nbsp;<span style="color: #000080;">Set</span> rng = wksht.Range(<span style="color: #800000;">&quot;A1&quot;</span>)<br />
&nbsp; <span style="color: #008000;">' get possible cell values<br />
</span> &nbsp;dataValidationValues = GetValidationRange2(rng)<br />
&nbsp; <br />
&nbsp; <span style="color: #000080;">For</span> i = <span style="color: #000080;">LBound</span>(dataValidationValues) <span style="color: #000080;">To</span> <span style="color: #000080;">UBound</span>(dataValidationValues)<br />
&nbsp; &nbsp; rng.value = dataValidationValues(i)<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #008000;">' print chart<br />
</span> &nbsp; &nbsp;<span style="color: #000080;">With</span> wkshtChart<br />
&nbsp; &nbsp; &nbsp; .PrintOut<br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">With</span><br />
<br />
&nbsp; &nbsp; <span style="color: #008000;">' pause 2 seconds to allow for printing<br />
</span> &nbsp; &nbsp;Application.Wait (Now + TimeValue(<span style="color: #800000;">&quot;0:00:02&quot;</span>))<br />
&nbsp; <span style="color: #000080;">Next</span> i<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span></div></div>
<p><a class="filedl" href="http://www.codeforexcelandoutlook.com/wkbks/DataValidationLoop.xls">Download sample workbook</a> with all of these functions and procedures.</p>
<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/get-data-validation-range/">Get Data Validation Range</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=lJ3f6D4GAhI:bmkob0t0JnE:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?i=lJ3f6D4GAhI:bmkob0t0JnE:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=lJ3f6D4GAhI:bmkob0t0JnE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/CodeForExcelAndOutlook/~4/lJ3f6D4GAhI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.codeforexcelandoutlook.com/blog/2010/08/get-data-validation-range/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Documentation Best Practices for Web APIs</title>
		<link>http://www.codeforexcelandoutlook.com/blog/2010/08/documentation-best-practices-for-web-apis/</link>
		<comments>http://www.codeforexcelandoutlook.com/blog/2010/08/documentation-best-practices-for-web-apis/#comments</comments>
		<pubDate>Fri, 20 Aug 2010 11:00:28 +0000</pubDate>
		<dc:creator>JP</dc:creator>
				<category><![CDATA[Rant]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[best practice]]></category>

		<guid isPermaLink="false">http://www.codeforexcelandoutlook.com/?p=1215</guid>
		<description><![CDATA[Programmable Web has a nice article called Web API Documentation Best Practices. It brings up several important points about how API developers should document their APIs. Consider this article a call to API developers &#8212; maintain your documentation! According to the article, API developers should Auto-generate Documentation Include Sample Code Show Example Requests and Responses [...]<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/documentation-best-practices-for-web-apis/">Documentation Best Practices for Web APIs</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
]]></description>
			<content:encoded><![CDATA[<p>Programmable Web has a nice article called <a href="http://blog.programmableweb.com/2010/08/12/web-api-documentation-best-practices/">Web API Documentation Best Practices</a>. It brings up several important points about how API developers should document their APIs. Consider this article a call to API developers &#8212; maintain your documentation!</p>
<p><span id="more-1215"></span></p>
<p>According to the article, API developers should</p>
<ul>
<li>Auto-generate Documentation</li>
<li>Include Sample Code</li>
<li>Show Example Requests and Responses</li>
<li>Explain Authentication and Error Handling</li>
</ul>
<p>They also provide an example site that follows these guidelines. I'd like to add some more best practices, and also discuss a few sites who don't play nice.</p>
<h2>1. Readability</h2>
<p><img src="http://i929.photobucket.com/albums/ad137/jp2112jp/blurry-vision.jpg" alt="blurry vision" title="blurry" /></p>
<p>One of the most important aspects of documentation is <strong>readability</strong>. If your documentation (visually) is difficult to follow, I won't be able to understand or implement it. The <a href="http://docs.flightcaster.com/">FlightCaster developer docs</a> are an example of this. They've done a great job cleaning up the documentation (see my <a href="http://www.codeforexcelandoutlook.com/blog/2010/05/flightcaster-api-examples-in-vba/">FlightCaster article</a>), but there are no tables or lines delimiting each section, and links are duplicated on other pages. It took hours to sort out what methods I had already implemented when going through it.</p>
<h2>2. Accuracy</h2>
<p><img src="http://i929.photobucket.com/albums/ad137/jp2112jp/Graphic_Crosshairs.gif" alt="crosshairs" title="crosshairs" /></p>
<p>This is by far the most important attribute your documentation can have &#8212; it must be exhaustive, and it MUST reflect the way the API currently works.</p>
<p>The worst examples of API documentation I've found so far are:</p>
<ol>
<li>
<h3><a href="http://data.worldbank.org/developers">World Bank</a></h3>
</li>
<p>The documentation is organized and includes sample method calls, but has a few drawbacks:</p>
<ul>
<li>Uses two different API endpoint URLs (api.worldbank.org and open.worldbank.org) at different times</li>
<li>Inaccurate URLs (some methods indicate an API key, while the documentation says no key is required)</li>
<li>Inconsistent results format</li>
</ul>
<p>Let me explain that last one. The <a href="http://data.worldbank.org/node/18">Country Query page</a> describes the return results from a Countries query:</p>
<ul>
<li>3 letter ISO 3166-1 alpha-3 code code</li>
<li>2 letter ISO 3166-1 alpha-2 code code</li>
<li>Name</li>
<li>Region id</li>
<li>Region Name</li>
<li>Income Level</li>
<li>Lending Type</li>
<li>Capital City</li>
<li>Longitude</li>
<li>Latitude</li>
</ul>
<p>That's ten data points, but if you look at the example query, there are only eight nodes:</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wb:countries</span> <span style="color: #000066;">page</span>=<span style="color: #ff0000;">&quot;1&quot;</span> <span style="color: #000066;">pages</span>=<span style="color: #ff0000;">&quot;1&quot;</span> <span style="color: #000066;">per_page</span>=<span style="color: #ff0000;">&quot;50&quot;</span> <span style="color: #000066;">total</span>=<span style="color: #ff0000;">&quot;1&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wb:country</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;BRA&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wb:iso2Code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>BR<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/wb:iso2Code<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wb:name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Brazil<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/wb:name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;wb:region</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;LCR&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Latin America <span style="color: #ddbb00;">&amp; Caribbean&lt;/wb:region&gt;</span><br />
<span style="color: #ddbb00;"> &nbsp; &nbsp;&lt;wb:incomeLevel id=&quot;UMC&quot;&gt;Upper middle income&lt;/wb:incomeLevel&gt;</span><br />
<span style="color: #ddbb00;"> &nbsp; &nbsp;&lt;wb:lendingType id=&quot;IBD&quot;&gt;IBRD only&lt;/wb:lendingType&gt;</span><br />
<span style="color: #ddbb00;"> &nbsp; &nbsp;&lt;wb:capitalCity&gt;Brasilia&lt;/wb:capitalCity&gt;</span><br />
<span style="color: #ddbb00;"> &nbsp; &nbsp;&lt;wb:longitude&gt;-47.9291687&lt;/wb:longitude&gt;</span><br />
<span style="color: #ddbb00;"> &nbsp; &nbsp;&lt;wb:latitude&gt;-15.7801476&lt;/wb:latitude&gt;</span><br />
<span style="color: #ddbb00;"> &nbsp;&lt;/wb:country&gt;</span><br />
<span style="color: #ddbb00;">&lt;/wb:countries&gt;</span></div></div>
<p>If you look carefully, the 3 letter ISO 3166-1 alpha-3 code code (BRA) is actually an attribute of the country tag, <strong>not a tag in itself</strong>. Same for the Region ID (LCR). This means that to extract the information that the documentation says the API returns, you need to do a traditional loop <em>plus additional parsing</em>. You'll see the awkwardness when I finally post my World Bank API VBA sample code.</p>
<p>Also, and I realize this is nitpicking, but who writes tags like that? It looks more like a WSDL document than XML. While technically correct, it's an odd implementation.</p>
<li>
<h3><a href="http://hueniverse.com/oauth/guide/">OAuth</a></h3>
</li>
<p>The self-described <a href="http://hueniverse.com/oauth/guide/">Authoritative Guide to OAuth 1.0</a> has very little instructions on how to actually implement it on any given platform. It's more of an "About" page than a "How To" page. The history of OAuth doesn't belong in a guide explaining how to use it; put it in a FAQ or somewhere else on the site for those that care. The "Beginner's" guide actually contains more sample code than the "Authoritative" Guide, but most of the Beginner's guide is lost in a wordy, generic explanation of how OAuth operates (and I do mean <strong>wordy</strong>).  You have to read through the <a href="http://oauth.net/core/1.0a/">Core</a> (whatever that means) if you want any hope of understanding how to implement it.</p>
<p>I still do plan on posting detailed walkthroughs for using OAuth with VB(A) for services like Twitter. But they aren't making it easy to learn how!</p>
<p>Both guides are in love with their own terminology and makes wild assumptions about the technical expertise of their readers. For example, the Beginner's guide instructions for <a href="http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iv-signing-requests/">signing requests</a> starts off with the following:</p>
<blockquote><p>In the following walkthrough, the Consumer would like to access a Protect Resource located at http://photos.example.net/photos with the parameters size=original, file=vacation.jpg</p></blockquote>
<p>Simple enough, right? Even if you don't know what "Consumer" means. But immediately following, it continues as follows:</p>
<blockquote><p>The Consumer has previously registered with the Service Provider and obtained the Consumer Key dpf43f3p2l4k3l03 and Consumer Secret kd94hf93k423kf44. It has executed the OAuth workflow and obtained a Token nnch734d00sl2jdk and Token Secret pfkkdhi9sl3r4s00. To sign the request, the Consumer is using the HMAC-SHA1 signature method and generated a nonce string kllo9940pd9333jh and timestamp 1191242096.</p></blockquote>
<p>Huh? How do I register and how do I get a consumer key? What is the "OAuth workflow" and how to I obtain a token and token secret? How do I use the HMAC-SHA1 signature method with OAuth? How do I generate a nonce string, what is the syntax and how long does it have to be? Why does the timestamp look like that? These are major assumptions that are casually glossed over by the guide. Nowhere in the guide (or anywhere else I looked on the site) are there links to any other resources, nor are there any links to service providers like Twitter or Google that use OAuth. I would be (extremely) grateful to hear otherwise.</p>
<p>The comments on the guides left by visitors are a mix of fanboy-praise and people who can't implement their code.</p>
</ol>
<p>So my search for OAuth sample code, or some kind of walkthrough, will continue. I may just be bitter because Twitter requires OAuth now, and my <a href="http://www.codeforexcelandoutlook.com/blog/2009/02/excel-to-twitter/">userforms</a> all broke, but as I mentioned <a href="http://www.codeforexcelandoutlook.com/blog/2010/05/office-links-for-april/">earlier</a>, I think using OAuth to protect something as silly as tweets is excessive. A tweet and $2.25 will get you on the subway.</p>
<p>Here are some great APIs I've had the pleasure of writing code for.</p>
<h3><a href="http://business.gov/about/features/api/">Business.Gov</a></h3>
<p>This API is well documented with method calls and sample URLs. It lists return data formats as well as the format for individual return values. It is consistent and cleanly formatted. The first of a large volume of sample VBA code for this API may be found at <a href="http://www.codeforexcelandoutlook.com/vba/business-gov-web-api-financing/">Business.gov Web API – Financing</a>.</p>
<h3><a href="http://www.abbreviations.com/api.asp">Abbreviations</a></h3>
<p>The documentation for this API is beautifully simple, yet complete. Sample XML responses are even included, so you don't even need to run test queries. VBA code for this API may be found at <a href="http://www.codeforexcelandoutlook.com/vba/abbreviations-com-api/">Abbreviations.com API Code Samples</a>.</p>
<p><strong>Any other APIs you'd like to mention, for better or worse?</strong></p>
<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/documentation-best-practices-for-web-apis/">Documentation Best Practices for Web APIs</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=e2vFSNocjf8:cL_eIFVYIKw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?i=e2vFSNocjf8:cL_eIFVYIKw:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=e2vFSNocjf8:cL_eIFVYIKw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/CodeForExcelAndOutlook/~4/e2vFSNocjf8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.codeforexcelandoutlook.com/blog/2010/08/documentation-best-practices-for-web-apis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An exploration of IE browser methods, part III</title>
		<link>http://www.codeforexcelandoutlook.com/blog/2010/08/an-exploration-of-ie-browser-methods-part-iii/</link>
		<comments>http://www.codeforexcelandoutlook.com/blog/2010/08/an-exploration-of-ie-browser-methods-part-iii/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 11:00:02 +0000</pubDate>
		<dc:creator>JP</dc:creator>
				<category><![CDATA[Internet Explorer]]></category>
		<category><![CDATA[Automation]]></category>
		<category><![CDATA[MSHTML]]></category>
		<category><![CDATA[MSXML2]]></category>
		<category><![CDATA[XMLHTTP]]></category>

		<guid isPermaLink="false">http://www.codeforexcelandoutlook.com/?p=1199</guid>
		<description><![CDATA[In previous articles I've written about how to extract information from webpages, and interact with them to navigate through a website. This article won't strictly focus on IE, but on several collections available through the MSHTML Object Model. Previous articles: An exploration of IE browser methods, part I An exploration of IE browser methods, part [...]<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/an-exploration-of-ie-browser-methods-part-iii/">An exploration of IE browser methods, part III</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
]]></description>
			<content:encoded><![CDATA[<p><img src="http://i929.photobucket.com/albums/ad137/jp2112jp/imageview.gif" alt="digital circuit" title="digital circuit" /></p>
<p>In previous articles I've written about how to extract information from webpages, and interact with them to navigate through a website.</p>
<p>This article won't strictly focus on IE, but on several collections available through the MSHTML Object Model.</p>
<p><span id="more-1199"></span></p>
<h2>Previous articles:</h2>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/blog/2010/06/an-exploration-of-ie-browser-methods-part-i/">An exploration of IE browser methods, part I</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/2010/06/an-exploration-of-ie-browser-methods-part-ii/">An exploration of IE browser methods, part II</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/excel-vba/automate-internet-explorer/">Automate Internet Explorer</a></li>
</ul>
<h2>The GetMSXML Function</h2>
<p>I've started using this function to return the XMLHTTP object. Hopefully I'll remember to use it consistently.</p>
<p>We'll use it because it's much faster than automating IE, as we learned <a href="http://www.codeforexcelandoutlook.com/blog/2010/06/an-exploration-of-ie-browser-methods-part-ii/">previously</a>, and we're more concerned with the HTML document once it's created rather than the method of actually creating it.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> GetMSXML() <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSXML2.XMLHTTP<br />
</span> &nbsp;<span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">Resume</span> <span style="color: #000080;">Next</span><br />
&nbsp; <span style="color: #000080;">Set</span> GetMSXML = CreateObject(<span style="color: #800000;">&quot;MSXML2.XMLHTTP&quot;</span>)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<h2>Creating MSHTML Documents</h2>
<p>Another function we'll need creates the HTML document which we'll load the HTML into. We also saw this code in <a href="http://www.codeforexcelandoutlook.com/blog/2010/06/an-exploration-of-ie-browser-methods-part-ii/">An exploration of IE browser methods, part II</a>.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> CreateHTMLDoc() <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSHTML.HTMLDocument<br />
</span> &nbsp;<span style="color: #000080;">Set</span> CreateHTMLDoc = CreateObject(<span style="color: #800000;">&quot;htmlfile&quot;</span>)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<h2>HTML Document Object Collections</h2>
<p>These are the three collections we'll be working with here: <strong>Anchors</strong>, <strong>Images</strong>, <strong>Links</strong>. We dealt with them in <a href="http://www.codeforexcelandoutlook.com/blog/2010/06/an-exploration-of-ie-browser-methods-part-ii/">An exploration of IE browser methods, part II</a>, but here I'll be going into a bit more detail.</p>
<p>Each one accepts a HTML Document Object (which we've already loaded with content from a website) and returns a reference to the relevant collection. The collection can then be iterated to look for a value, compare values, and so on.</p>
<h3>Anchors Collection</h3>
<p>The Anchors Collection "retrieves a collection of all a objects that have a name and/or id property. Objects in this collection are in HTML source order."</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> GetHTMLAnchors(htmlDoc <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSHTML.IHTMLElementCollection<br />
</span> &nbsp;<span style="color: #000080;">Set</span> GetHTMLAnchors = htmlDoc.anchors<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<h3>The Images Collection</h3>
<p>The Images Collection "retrieves a collection, in source order, of img objects in the document."</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> GetHTMLImages(htmlDoc <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSHTML.IHTMLElementCollection<br />
</span> &nbsp;<span style="color: #000080;">Set</span> GetHTMLImages = htmlDoc.images<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<h3>The Links Collection</h3>
<p>The Links Collection "retrieves a collection of all a objects that specify the href property and all area objects in the document.".</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> GetHTMLLinks(htmlDoc <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSHTML.IHTMLElementCollection<br />
</span> &nbsp;<span style="color: #000080;">Set</span> GetHTMLLinks = htmlDoc.links<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<p>Note that each collection returns objects "in source order", which means that the first link you see on a page will be the first link in the Anchors/Links Collection. Also, all three Collections have <strong>Length</strong> and <strong>Item</strong> Properties, which let you check the amount of items in the collection and return each individual item, respectively.</p>
<h2>Looping through each collection</h2>
<p>In the sample procedure below, we create a new HTML document and populate it with the source code from Google's homepage (hey, got a better site to test? Leave a comment!). Then we grab each collection in turn and print various attributes from each member.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Sub</span> TestHTMLCollections()<br />
<br />
<span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">GoTo</span> ErrorHandler<br />
<br />
<span style="color: #000080;">Dim</span> xml <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSXML2.XMLHTTP<br />
</span><span style="color: #000080;">Dim</span> htmlDoc <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSHTML.HTMLDocument<br />
</span><span style="color: #000080;">Dim</span> htmlBody <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSHTML.HTMLBody<br />
</span><span style="color: #000080;">Dim</span> anchors <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSHTML.IHTMLElementCollection<br />
</span><span style="color: #000080;">Dim</span> anchor <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSHTML.IHTMLElement<br />
</span><span style="color: #000080;">Dim</span> images <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSHTML.IHTMLElementCollection<br />
</span><span style="color: #000080;">Dim</span> image <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSHTML.IHTMLElement<br />
</span><span style="color: #000080;">Dim</span> links <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSHTML.IHTMLElementCollection<br />
</span><span style="color: #000080;">Dim</span> link <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSHTML.IHTMLElement<br />
</span><br />
<span style="color: #000080;">Set</span> xml = GetMSXML<br />
<span style="color: #000080;">Set</span> htmlDoc = CreateHTMLDoc<br />
<span style="color: #000080;">Set</span> htmlBody = htmlDoc.body<br />
<br />
<span style="color: #000080;">With</span> xml<br />
&nbsp; .<span style="color: #000080;">Open</span> <span style="color: #800000;">&quot;GET&quot;</span>, <span style="color: #800000;">&quot;http://www.google.com/&quot;</span>, <span style="color: #000080;">False</span><br />
&nbsp; .send<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">With</span><br />
<br />
&nbsp; <span style="color: #008000;">' put xml response into HTML document<br />
</span> &nbsp;htmlBody.innerHTML = xml.responseText<br />
<br />
&nbsp; <span style="color: #008000;">' get all anchors<br />
</span> &nbsp;<span style="color: #000080;">Set</span> anchors = GetHTMLAnchors(htmlDoc)<br />
<br />
&nbsp; <span style="color: #008000;">' number of anchor tags<br />
</span> &nbsp;Debug.<span style="color: #000080;">Print</span> anchors.Length<br />
&nbsp; <br />
&nbsp; <span style="color: #008000;">' print each anchor tag contents<br />
</span> &nbsp;<span style="color: #000080;">For</span> <span style="color: #000080;">Each</span> anchor <span style="color: #000080;">In</span> anchors<br />
&nbsp; &nbsp; Debug.<span style="color: #000080;">Print</span> anchor.innerHTML<br />
&nbsp; <span style="color: #000080;">Next</span> anchor<br />
&nbsp; <br />
&nbsp; <span style="color: #008000;">' get all images<br />
</span> &nbsp;<span style="color: #000080;">Set</span> images = GetHTMLImages(htmlDoc)<br />
&nbsp; <br />
&nbsp; <span style="color: #008000;">' number of images<br />
</span> &nbsp;Debug.<span style="color: #000080;">Print</span> images.Length<br />
&nbsp; <br />
&nbsp; <span style="color: #008000;">' print each image URL (img 'src' attribute)<br />
</span> &nbsp;<span style="color: #000080;">For</span> <span style="color: #000080;">Each</span> image <span style="color: #000080;">In</span> images<br />
&nbsp; &nbsp; Debug.<span style="color: #000080;">Print</span> image.getAttribute(<span style="color: #800000;">&quot;src&quot;</span>)<br />
&nbsp; <span style="color: #000080;">Next</span> image<br />
&nbsp; <br />
&nbsp; <span style="color: #008000;">' get links collection<br />
</span> &nbsp;<span style="color: #000080;">Set</span> links = GetHTMLLinks(htmlDoc)<br />
&nbsp; <br />
&nbsp; <span style="color: #008000;">' number of links<br />
</span> &nbsp;Debug.<span style="color: #000080;">Print</span> links.Length<br />
&nbsp; <br />
&nbsp; <span style="color: #008000;">' print link target<br />
</span> &nbsp;<span style="color: #000080;">For</span> <span style="color: #000080;">Each</span> link <span style="color: #000080;">In</span> links<br />
&nbsp; &nbsp; Debug.<span style="color: #000080;">Print</span> link.getAttribute(<span style="color: #800000;">&quot;href&quot;</span>)<br />
&nbsp; <span style="color: #000080;">Next</span> link<br />
<br />
ProgramExit:<br />
&nbsp; <span style="color: #000080;">Exit</span> <span style="color: #000080;">Sub</span><br />
ErrorHandler:<br />
&nbsp; MsgBox Err.number &amp; <span style="color: #800000;">&quot; - &quot;</span> &amp; Err.description<br />
&nbsp; <span style="color: #000080;">Resume</span> ProgramExit<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span></div></div>
<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/an-exploration-of-ie-browser-methods-part-iii/">An exploration of IE browser methods, part III</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=GKPr6cKNKd8:UCPZiZdpUj8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?i=GKPr6cKNKd8:UCPZiZdpUj8:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=GKPr6cKNKd8:UCPZiZdpUj8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/CodeForExcelAndOutlook/~4/GKPr6cKNKd8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.codeforexcelandoutlook.com/blog/2010/08/an-exploration-of-ie-browser-methods-part-iii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>State Weather Advisories available by RSS</title>
		<link>http://www.codeforexcelandoutlook.com/blog/2010/08/state-weather-advisories-available-by-rss/</link>
		<comments>http://www.codeforexcelandoutlook.com/blog/2010/08/state-weather-advisories-available-by-rss/#comments</comments>
		<pubDate>Fri, 13 Aug 2010 11:00:27 +0000</pubDate>
		<dc:creator>JP</dc:creator>
				<category><![CDATA[Automation]]></category>
		<category><![CDATA[VBA]]></category>
		<category><![CDATA[MSXML2]]></category>
		<category><![CDATA[weather]]></category>
		<category><![CDATA[XMLHTTP]]></category>

		<guid isPermaLink="false">http://www.codeforexcelandoutlook.com/?p=1198</guid>
		<description><![CDATA[In Exploring the NOAA API I posted code for consuming the NOAA RSS feed for Atlantic storms. I also posted weather-finding functions using the Geonames API, the WebserviceX.NET API and even a cheap formula for opening weather.com. Now let's explore even more weather-related functions (I'm sure you're as excited as I am!). This one is [...]<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/state-weather-advisories-available-by-rss/">State Weather Advisories available by RSS</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
]]></description>
			<content:encoded><![CDATA[<p><img src="http://i929.photobucket.com/albums/ad137/jp2112jp/0511-0901-1901-2128_Television_Weat.png" alt="weather" title="weather" /></p>
<p>In <a href="http://www.codeforexcelandoutlook.com/blog/2010/08/exploring-the-noaa-api/">Exploring the NOAA API</a> I posted code for consuming the NOAA RSS feed for Atlantic storms.</p>
<p>I also posted weather-finding functions using the <a href="http://www.codeforexcelandoutlook.com/blog/2010/05/geonames-api-puts-geographical-data-at-your-fingertips/">Geonames API</a>, the <a href="http://www.codeforexcelandoutlook.com/blog/2010/03/got-weather/">WebserviceX.NET API</a> and even a cheap formula for <a href="http://www.codeforexcelandoutlook.com/blog/2009/03/weather-formula/">opening weather.com</a>.</p>
<p><span id="more-1198"></span></p>
<p>Now let's explore even more weather-related functions (I'm sure you're as excited as I am!). This one is an API from <a href="http://www.weather.gov/alerts-beta/">weather.gov</a> that provides state-by-state weather advisories which you can use in your VBA programs.</p>
<p>I noticed that in addition to providing a RSS feed, the feed URL itself only differs by the state abbreviation. So all we need to do is prompt for the state abbreviation and we can return any weather advisories in any state! And if you check weather.gov for all the state abbreviations, you can also look at weather for other U.S. territories and provinces.</p>
<h2 id="GetStateAdvisories">The GetStateAdvisories Function</h2>
<p>The following function takes a state abbreviation and returns any weather advisories issued by weather.gov for that state. Queries are cached, so the second parameter must be <strong>True</strong> to requery the API.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> GetStateAdvisories(state <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, _<br />
&nbsp; &nbsp; <span style="color: #000080;">Optional</span> forceRequery <span style="color: #000080;">As</span> <span style="color: #000080;">Boolean</span> = <span style="color: #000080;">False</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>()<br />
<span style="color: #008000;">' see http://www.weather.gov/alerts-beta/ for list of states/provinces<br />
</span><span style="color: #000080;">Dim</span> xml <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSXML2.XMLHTTP<br />
</span><span style="color: #000080;">Dim</span> result <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #000080;">Dim</span> tempFolder <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #000080;">Dim</span> tempFile <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #000080;">Dim</span> tempString() <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #000080;">Dim</span> xmlDoc <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSXML2.DOMDocument<br />
</span><span style="color: #000080;">Dim</span> xmlDocRoot <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSXML2.IXMLDOMNode<br />
</span><span style="color: #000080;">Dim</span> feed <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSXML2.IXMLDOMNodeList<br />
</span><span style="color: #000080;">Dim</span> i <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span>, j <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
<span style="color: #000080;">Dim</span> numberOfEntries <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
<span style="color: #000080;">Dim</span> entry <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSXML2.IXMLDOMNodeList<br />
</span><br />
<span style="color: #000080;">Const</span> XML_FILE_EXTENSION <span style="color: #000080;">As</span> <span style="color: #000080;">String</span> = <span style="color: #800000;">&quot;.xml&quot;</span><br />
<br />
&nbsp; tempFolder = environ(<span style="color: #800000;">&quot;temp&quot;</span>)<br />
<br />
&nbsp; <span style="color: #000080;">Set</span> xml = CreateObject(<span style="color: #800000;">&quot;MSXML2.XMLHTTP&quot;</span>)<br />
<br />
&nbsp; tempFile = tempFolder &amp; Application.PathSeparator &amp; <span style="color: #800000;">&quot;stateweather_&quot;</span> &amp; _<br />
&nbsp; &nbsp; state &amp; XML_FILE_EXTENSION<br />
<br />
&nbsp; <span style="color: #008000;">' query website if cache is empty or we are forced to<br />
</span> &nbsp;<span style="color: #000080;">If</span> (Len(Dir(tempFile)) = 0 <span style="color: #000080;">Or</span> forceRequery) <span style="color: #000080;">Then</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000080;">With</span> xml<br />
&nbsp; &nbsp; &nbsp; .<span style="color: #000080;">Open</span> <span style="color: #800000;">&quot;GET&quot;</span>, <span style="color: #800000;">&quot;http://www.weather.gov/alerts-beta/&quot;</span> &amp; _<br />
&nbsp; &nbsp; LCase$(state) &amp; <span style="color: #800000;">&quot;.php?x=0&quot;</span>, <span style="color: #000080;">False</span><br />
&nbsp; &nbsp; &nbsp; .send<br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">With</span><br />
<br />
&nbsp; &nbsp; result = ConvertAccent(xml.responseText)<br />
<br />
&nbsp; &nbsp; <span style="color: #008000;">' create XML file from result<br />
</span> &nbsp; &nbsp;<span style="color: #000080;">Call</span> CreateXMLFile(tempFile, result)<br />
<br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; <span style="color: #000080;">Set</span> xmlDoc = CreateObject(<span style="color: #800000;">&quot;MSXML2.DOMDocument&quot;</span>)<br />
<br />
&nbsp; <span style="color: #000080;">With</span> xmlDoc<br />
&nbsp; &nbsp; .async = <span style="color: #000080;">False</span><br />
&nbsp; &nbsp; .validateOnParse = <span style="color: #000080;">False</span><br />
&nbsp; &nbsp; .Load tempFile<br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">With</span><br />
<br />
&nbsp; <span style="color: #008000;">' check that the XML doc loaded<br />
</span> &nbsp;<span style="color: #000080;">If</span> LoadError(xmlDoc) <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Exit</span> <span style="color: #000080;">Function</span><br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; <span style="color: #008000;">' get root node<br />
</span> &nbsp;<span style="color: #000080;">Set</span> xmlDocRoot = GetRootNode(xmlDoc)<br />
&nbsp; <span style="color: #008000;">' get first level nodes<br />
</span> &nbsp;<span style="color: #000080;">Set</span> feed = GetChildNodes(xmlDocRoot)<br />
&nbsp; <br />
&nbsp; <span style="color: #008000;">' count number of entries to figure out<br />
</span> &nbsp;<span style="color: #008000;">' how many rows in the array<br />
</span> &nbsp;<span style="color: #000080;">For</span> i = 1 <span style="color: #000080;">To</span> feed.Length<br />
&nbsp; &nbsp; <span style="color: #000080;">If</span> feed.item(i - 1).nodeName = <span style="color: #800000;">&quot;entry&quot;</span> <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; numberOfEntries = numberOfEntries + 1<br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; <span style="color: #000080;">Next</span> i<br />
&nbsp; <br />
&nbsp; <span style="color: #008000;">' resize array<br />
</span> &nbsp;<span style="color: #008000;">' there are four nodes of information per entry<br />
</span> &nbsp;<span style="color: #000080;">ReDim</span> tempString(1 <span style="color: #000080;">To</span> numberOfEntries, 1 <span style="color: #000080;">To</span> 4)<br />
&nbsp; <br />
&nbsp; <span style="color: #008000;">' start grabbing!<br />
</span> &nbsp;<span style="color: #000080;">For</span> i = 1 <span style="color: #000080;">To</span> feed.Length<br />
&nbsp; &nbsp; <span style="color: #000080;">If</span> feed.item(i - 1).nodeName = <span style="color: #800000;">&quot;entry&quot;</span> <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">' it's an entry<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #000080;">Set</span> entry = feed.item(i - 1).childNodes<br />
&nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">' check for no watches<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #000080;">If</span> InStr(entry.item(3).nodeTypedValue, <span style="color: #800000;">&quot;There are no active watches&quot;</span>) &gt; 0 <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; tempString(1, 1) = entry.item(1).nodeTypedValue<br />
&nbsp; &nbsp; &nbsp; &nbsp; tempString(1, 2) = entry.item(3).nodeTypedValue<br />
&nbsp; &nbsp; &nbsp; &nbsp; tempString(1, 3) = entry.item(4).Attributes.getNamedItem(<span style="color: #800000;">&quot;href&quot;</span>).nodeTypedValue<br />
&nbsp; &nbsp; &nbsp; &nbsp; tempString(1, 4) = entry.item(5).nodeTypedValue<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000080;">Else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">For</span> j = 1 <span style="color: #000080;">To</span> numberOfEntries<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempString(j, 1) = entry.item(1).nodeTypedValue<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempString(j, 2) = entry.item(4).nodeTypedValue<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempString(j, 3) = entry.item(5).Attributes.getNamedItem(<span style="color: #800000;">&quot;href&quot;</span>).nodeTypedValue<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempString(j, 4) = entry.item(6).nodeTypedValue<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">Next</span> j<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; <span style="color: #000080;">Next</span> i<br />
&nbsp; <br />
&nbsp; GetStateAdvisories = tempString<br />
<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<p>Because there is a series of irrelevant nodes that appear before the weather entries, we need to loop through the nodes to find out how many entries there are. After sizing the temporary array we'll use to hold the entry information, we loop again through the nodes.</p>
<p>If there are no active weather advisories, there will be one node and we don't really need to loop. Otherwise we loop through each entry and grab the weather advisory along with the URL from weather.gov.</p>
<h2>Sample usage</h2>
<p>This procedure will return and iterate through any available weather advisories for New York State.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Sub</span> TestGetAdvisories()<br />
<br />
<span style="color: #000080;">Dim</span> results() <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #000080;">Dim</span> i <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span>, j <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
<br />
&nbsp; results = GetStateAdvisories(<span style="color: #800000;">&quot;NY&quot;</span>)<br />
<br />
&nbsp; <span style="color: #000080;">For</span> i = <span style="color: #000080;">LBound</span>(results) <span style="color: #000080;">To</span> <span style="color: #000080;">UBound</span>(results)<br />
&nbsp; &nbsp; <span style="color: #000080;">For</span> j = <span style="color: #000080;">LBound</span>(results, 2) <span style="color: #000080;">To</span> <span style="color: #000080;">UBound</span>(results, 2)<br />
&nbsp; &nbsp; &nbsp; Debug.<span style="color: #000080;">Print</span> results(i, j)<br />
&nbsp; &nbsp; <span style="color: #000080;">Next</span> j<br />
&nbsp; <span style="color: #000080;">Next</span> i<br />
<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span></div></div>
<h2 id="helper">Helper Functions</h2>
<p>These are the ancillary functions used by the <a href="#GetStateAdvisories">GetStateAdvisories</a> function.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> GetChildNodes(node <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
<span style="color: #008000;">' returns child nodes for a given MSXML2.IXMLDOMNode<br />
</span> &nbsp;<span style="color: #000080;">Set</span> GetChildNodes = node.childNodes<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<br />
<span style="color: #000080;">Function</span> CreateXMLFile(fileName <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, contents <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #008000;">' creates XML file from string contents<br />
</span><br />
<span style="color: #000080;">Dim</span> tempFile <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #000080;">Dim</span> nextFileNum <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
<br />
&nbsp; nextFileNum = FreeFile<br />
<br />
&nbsp; tempFile = fileName<br />
<br />
&nbsp; <span style="color: #000080;">Open</span> tempFile <span style="color: #000080;">For</span> <span style="color: #000080;">Output</span> <span style="color: #000080;">As</span> #nextFileNum<br />
&nbsp; <span style="color: #000080;">Print</span> #nextFileNum, FixAngleBrackets(contents)<br />
&nbsp; <span style="color: #000080;">Close</span> #nextFileNum<br />
<br />
&nbsp; CreateXMLFile = tempFile<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<br />
<span style="color: #000080;">Function</span> GetRootNode(xmlDoc <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
<span style="color: #008000;">' returns root node<br />
</span> &nbsp;<span style="color: #000080;">Set</span> GetRootNode = xmlDoc.documentElement<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<br />
<span style="color: #000080;">Function</span> LoadError(xmlDoc <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Boolean</span><br />
<span style="color: #008000;">' checks if a xml file load error occurred<br />
</span> &nbsp;LoadError = (xmlDoc.parseError.errorCode &lt;&gt; 0)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<br />
<span style="color: #000080;">Function</span> FixAngleBrackets(textString <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
&nbsp; FixAngleBrackets = Replace(Replace(textString, <span style="color: #800000;">&quot;&amp;lt;&quot;</span>, <span style="color: #800000;">&quot;&lt;&quot;</span>), <span style="color: #800000;">&quot;&amp;gt;&quot;</span>, <span style="color: #800000;">&quot;&gt;&quot;</span>)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span><br />
<br />
<span style="color: #000080;">Function</span> ConvertAccent(<span style="color: #000080;">ByVal</span> inputString <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #008000;">' http://www.vbforums.com/archive/index.php/t-483965.html<br />
</span><br />
<span style="color: #000080;">Const</span> AccChars <span style="color: #000080;">As</span> <span style="color: #000080;">String</span> = _<br />
&nbsp; &nbsp; &nbsp; <span style="color: #800000;">&quot;ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðñòóôõöùúûüýÿ&quot;</span><br />
<span style="color: #000080;">Const</span> RegChars <span style="color: #000080;">As</span> <span style="color: #000080;">String</span> = _<br />
&nbsp; &nbsp; &nbsp; <span style="color: #800000;">&quot;SZszYAAAAAACEEEEIIIIDNOOOOOUUUUYaaaaaaceeeeiiiidnooooouuuuyy&quot;</span><br />
<br />
<span style="color: #000080;">Dim</span> i <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span>, j <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
<span style="color: #000080;">Dim</span> tempString <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #000080;">Dim</span> currentCharacter <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #000080;">Dim</span> found <span style="color: #000080;">As</span> <span style="color: #000080;">Boolean</span><br />
<span style="color: #000080;">Dim</span> foundPosition <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
<br />
&nbsp; tempString = inputString<br />
<br />
&nbsp; <span style="color: #008000;">' loop through the shorter string<br />
</span> &nbsp;<span style="color: #000080;">Select</span> <span style="color: #000080;">Case</span> <span style="color: #000080;">True</span><br />
&nbsp; &nbsp; <span style="color: #000080;">Case</span> Len(AccChars) &lt;= Len(inputString)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">' accent character list is shorter (or same)<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #008000;">' loop through accent character string<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #000080;">For</span> i = 1 <span style="color: #000080;">To</span> Len(AccChars)<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">' get next accent character<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp;currentCharacter = Mid$(AccChars, i, 1)<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">' replace with corresponding character in &quot;regular&quot; array<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000080;">If</span> InStr(tempString, currentCharacter) &gt; 0 <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempString = Replace(tempString, currentCharacter, Mid$(RegChars, i, 1))<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000080;">Next</span> i<br />
&nbsp; &nbsp; <span style="color: #000080;">Case</span> Len(AccChars) &gt; Len(inputString)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">' input string is shorter<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #008000;">' loop through input string<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #000080;">For</span> i = 1 <span style="color: #000080;">To</span> Len(inputString)<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">' grab current character from input string and<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">' determine if it is a special char<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp;currentCharacter = Mid$(inputString, i, 1)<br />
&nbsp; &nbsp; &nbsp; &nbsp; found = (InStr(AccChars, currentCharacter) &gt; 0)<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">If</span> found <span style="color: #000080;">Then</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">' find position of special character in special array<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;foundPosition = InStr(AccChars, currentCharacter)<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">' replace with corresponding character in &quot;regular&quot; array<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;tempString = Replace(tempString, currentCharacter, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Mid$(RegChars, foundPosition, 1))<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000080;">Next</span> i<br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">Select</span><br />
<br />
&nbsp; ConvertAccent = tempString<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/state-weather-advisories-available-by-rss/">State Weather Advisories available by RSS</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=cArVUswpZIc:jVNZWJif-5M:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?i=cArVUswpZIc:jVNZWJif-5M:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=cArVUswpZIc:jVNZWJif-5M:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/CodeForExcelAndOutlook/~4/cArVUswpZIc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.codeforexcelandoutlook.com/blog/2010/08/state-weather-advisories-available-by-rss/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Random Data Generator Add-In Issues</title>
		<link>http://www.codeforexcelandoutlook.com/blog/2010/08/random-data-generator-add-in-issues/</link>
		<comments>http://www.codeforexcelandoutlook.com/blog/2010/08/random-data-generator-add-in-issues/#comments</comments>
		<pubDate>Thu, 12 Aug 2010 12:00:30 +0000</pubDate>
		<dc:creator>JP</dc:creator>
				<category><![CDATA[AddIns]]></category>
		<category><![CDATA[Administrative]]></category>
		<category><![CDATA[Excel]]></category>

		<guid isPermaLink="false">http://www.codeforexcelandoutlook.com/?p=1213</guid>
		<description><![CDATA[Just a quick note to let everyone know that I'm aware of several issues with the Random Data Generator. Access to the files has been removed until further notice. Thanks Random Data Generator Add-In Issues is Copyright &#169; Code For Excel And Outlook. All Rights Reserved. More stuff: Where do I put my Outlook code? [...]<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/random-data-generator-add-in-issues/">Random Data Generator Add-In Issues</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
]]></description>
			<content:encoded><![CDATA[<p>Just a quick note to let everyone know that I'm aware of several issues with the Random Data Generator.</p>
<p>Access to the files has been removed until further notice.</p>
<p>Thanks</p>
<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/random-data-generator-add-in-issues/">Random Data Generator Add-In Issues</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=Q3eOA4S4Q24:y86tT2q9P4Q:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?i=Q3eOA4S4Q24:y86tT2q9P4Q:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=Q3eOA4S4Q24:y86tT2q9P4Q:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/CodeForExcelAndOutlook/~4/Q3eOA4S4Q24" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.codeforexcelandoutlook.com/blog/2010/08/random-data-generator-add-in-issues/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Screen Scraping 101 with VBA</title>
		<link>http://www.codeforexcelandoutlook.com/blog/2010/08/screen-scraping-101-with-vba/</link>
		<comments>http://www.codeforexcelandoutlook.com/blog/2010/08/screen-scraping-101-with-vba/#comments</comments>
		<pubDate>Tue, 10 Aug 2010 11:00:16 +0000</pubDate>
		<dc:creator>JP</dc:creator>
				<category><![CDATA[VBA]]></category>
		<category><![CDATA[download]]></category>
		<category><![CDATA[scraping]]></category>

		<guid isPermaLink="false">http://www.codeforexcelandoutlook.com/?p=1197</guid>
		<description><![CDATA[No, not that kind of scraping. You can capture and download virtually any webpage using VBA. Here's one method for doing so. I've written a simple function that lets you screen scrape almost any webpage you can pass as a parameter. I say "almost" because some pages are rendered in Javascript or Flash (or frames!) [...]<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/screen-scraping-101-with-vba/">Screen Scraping 101 with VBA</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
]]></description>
			<content:encoded><![CDATA[<p><img src="http://i929.photobucket.com/albums/ad137/jp2112jp/scraper.jpg" alt="scraper" title="scraper" /></p>
<p>No, not that kind of scraping. You can capture and download virtually any webpage using VBA. Here's one method for doing so.</p>
<p><span id="more-1197"></span></p>
<p>I've written a simple function that lets you screen scrape almost any webpage you can pass as a parameter. I say "almost" because some pages are rendered in Javascript or Flash (or frames!) and don't really reveal any useful source code. The function will return the raw client-side output as a String with no parsing whatsoever. How you choose to parse the information is up to you.</p>
<h2>The GetWebpage Function</h2>
<p>This function should be familiar to anyone who has read any of my articles on <a href="http://www.codeforexcelandoutlook.com/blog/tag/xmlhttp/">XMLHTTP</a> parsing. It uses the MSXML.XMLHTTP object to open and grab a web page. Simple as that. If you specify a filename as the second parameter, the webpage contents are written to a file.</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> GetWebpage(url <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, <span style="color: #000080;">Optional</span> fileName <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<br />
<span style="color: #000080;">Dim</span> xml <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span> <span style="color: #008000;">' MSXML2.XMLHTTP<br />
</span><span style="color: #000080;">Dim</span> result <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<br />
&nbsp; <span style="color: #000080;">Set</span> xml = GetMSXML<br />
<br />
&nbsp; <span style="color: #008000;">' grab webpage<br />
</span> &nbsp;<span style="color: #000080;">With</span> xml<br />
&nbsp; &nbsp; .<span style="color: #000080;">Open</span> <span style="color: #800000;">&quot;GET&quot;</span>, url, <span style="color: #000080;">False</span><br />
&nbsp; &nbsp; .send<br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">With</span><br />
<br />
&nbsp; GetWebpage = xml.responseText<br />
<br />
&nbsp; <span style="color: #008000;">' write to file?<br />
</span> &nbsp;<span style="color: #000080;">If</span> Len(fileName) &gt; 0 <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; <span style="color: #000080;">If</span> <span style="color: #000080;">Not</span> FileExists(fileName) <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000080;">Call</span> CreateFile(fileName, GetWebpage)<br />
&nbsp; &nbsp; <span style="color: #000080;">Else</span> <span style="color: #008000;">' file exists<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #000080;">If</span> MsgBox(<span style="color: #800000;">&quot;File already exists, overwrite?&quot;</span>, vbYesNo) = vbYes <span style="color: #000080;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000080;">Call</span> CreateFile(fileName, GetWebpage)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; &nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
&nbsp; <span style="color: #000080;">End</span> <span style="color: #000080;">If</span><br />
<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<p>To create an instance of the XMLHTTP Object, I've started using this function:</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Function</span> GetMSXML() <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span><br />
&nbsp; <span style="color: #000080;">On</span> <span style="color: #000080;">Error</span> <span style="color: #000080;">Resume</span> <span style="color: #000080;">Next</span><br />
&nbsp; <span style="color: #000080;">Set</span> GetMSXML = CreateObject(<span style="color: #800000;">&quot;MSXML2.XMLHTTP&quot;</span>)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<p>If you do choose to write the output to a file, you'll need these two functions:</p>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Sub</span> CreateFile(fileName <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, contents <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>)<br />
<span style="color: #008000;">' create file from string contents<br />
</span><br />
<span style="color: #000080;">Dim</span> tempFile <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<span style="color: #000080;">Dim</span> nextFileNum <span style="color: #000080;">As</span> <span style="color: #000080;">Long</span><br />
<br />
&nbsp; nextFileNum = FreeFile<br />
<br />
&nbsp; tempFile = fileName<br />
<br />
&nbsp; <span style="color: #000080;">Open</span> tempFile <span style="color: #000080;">For</span> <span style="color: #000080;">Output</span> <span style="color: #000080;">As</span> #nextFileNum<br />
&nbsp; <span style="color: #000080;">Print</span> #nextFileNum, contents<br />
&nbsp; <span style="color: #000080;">Close</span> #nextFileNum<br />
<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span><br />
<br />
<span style="color: #000080;">Function</span> FileExists(fileName <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Boolean</span><br />
&nbsp; FileExists = (Len(Dir(fileName)) &gt; 0)<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></div></div>
<h2>Sample usage</h2>
<div class="codecolorer-container vb default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:630px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000080;">Sub</span> TestGetWebpage()<br />
<br />
<span style="color: #000080;">Dim</span> webpage <span style="color: #000080;">As</span> <span style="color: #000080;">String</span><br />
<br />
webpage = GetWebpage(<span style="color: #800000;">&quot;http://www.codeforexcelandoutlook.com/blog/&quot;</span>)<br />
<br />
Debug.<span style="color: #000080;">Print</span> webpage<br />
<br />
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span></div></div>
<p><a href="http://www.codeforexcelandoutlook.com/blog/2010/08/screen-scraping-101-with-vba/">Screen Scraping 101 with VBA</a> is Copyright &copy; <a href="http://www.codeforexcelandoutlook.com/">Code For Excel And Outlook</a>. All Rights Reserved.

<h3>More stuff:</h3>
<ul>
<li><a href="http://www.codeforexcelandoutlook.com/outlook-vba/where-do-i-put-my-outlook-vba-code/">Where do I put my Outlook code?</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/blog/contribute/">Contribute to this blog</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/vba-search-engine/">VBA Search Engine</a></li>
<li><a href="http://www.codeforexcelandoutlook.com/site-map/">Site Map</a></li>
</ul>
</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=nJeXiGGpPW8:neACacTkHdc:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?i=nJeXiGGpPW8:neACacTkHdc:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?a=nJeXiGGpPW8:neACacTkHdc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/CodeForExcelAndOutlook?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/CodeForExcelAndOutlook/~4/nJeXiGGpPW8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.codeforexcelandoutlook.com/blog/2010/08/screen-scraping-101-with-vba/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
