<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:a10="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title> Matt's TipTopBlog</title><link>http://matthewrathbone.com/Blog/Default.aspx</link><description>Matthew Rathbone's blog on VBA, .NET, general tech and other related topics</description><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/matthewrathbone" /><feedburner:info uri="matthewrathbone" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">25</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/yemF2WEsMm8/counting-sort-in-c-and-python--operation-algorithm-2.aspx</link><title>Counting Sort in C and Python: Operation Algorithm 2</title><description>&lt;p&gt;This is the second in my series of algorithm posts in trying to &lt;a href="http://matthewrathbone.com/Blog/view/post/20091119/operation-algorithm--introduction.aspx"&gt;become a better programmer&lt;/a&gt;. Counting sort is possibly my favorite of the sorting algorithms because it looks so complicated at first glance, but its actually very simple and graceful.&lt;/p&gt;
&lt;p&gt;The principle behind counting sort is to store a count of each value that appears in the array and use that as a way to place the original value in the resulting array. It's generally used for fairly low numbered positive integer values, and the running time of the algorithm depends on both the number of elements, and the range of values within the array. For example, a simple array with the values (1, 6, 1000000000) will take a LONG time to be sorted, even though there are only three elements because at some point there will be a loop from 0 to 1000000000. Also note that the sort method requires a parameter k, which is the maximum value contained in the array.&lt;/p&gt;
&lt;p&gt;If you don't understand the algorithm, it would probably be better to read the &lt;a href="http://en.wikipedia.org/wiki/Counting_sort"&gt;wikipedia article&lt;/a&gt;&amp;nbsp;instead of trying to rely on my brief and badly written version.&lt;/p&gt;
&lt;h3&gt;Language Choice&lt;/h3&gt;
&lt;p&gt;I decided to do a version in Python because I've never really used the language much and I figured it was a good way to give it a try. My first impressions are pretty positive, and I love how it uses indenting as part of the language semantics.&lt;/p&gt;
&lt;h3&gt;My C Implementation:&lt;/h3&gt;
&lt;script type="syntaxhighlighter" class="brush: cpp"&gt;&lt;![CDATA[
//B contains the sorted output
void CountingSort(int A[] ,int B[], int arraySize,int k){
	int C[k+1];
	int i, aLen, j;

	for(i = 0; i&lt;= k; i++)
		C[i] = 0;
	aLen = arraySize;
	
	// C gets a count for each integer i in A
	for(i = 0; i&lt;aLen; i++)
		C[A[i]]++;
	
	// C now contains a count for all intergers less than or equal to i;
	for(i = 1;i&lt;=k; i++){
		C[i]+=C[i-1];
	}
	printf("C contains: \n");
	for(i = 0;i&lt;=k; i++){
		printf("%d \n", C[i]);
	}	


	for(j = 1; j&lt;= aLen; j++)
	{
		i = aLen-j;
		B[ C[A[i]]-1 ] = A[i];
		C[A[i]]--;
	}
}
]]&gt;&lt;/script&gt;
&lt;h3&gt;My Python Implementation&lt;/h3&gt;
&lt;script type="syntaxhighlighter" class="brush: python"&gt;&lt;![CDATA[
class CountingSorter:
    def Sort(self, A, k):
        C = []
        B = []
                
        for i in range(0, k+1):
            C.append(0)

        aLen = len(A)
        for j in range(0, aLen):
            B.append(0)
            C[A[j]]+=1

        for i in range(1, k+1):
            C[i] = C[i] + C[i-1]

        for i in range(0, aLen):
            j = (aLen-1) - i
            B[C[A[j]]-1] = A[j]
            C[A[j]] -=1
        return B
]]&gt;&lt;/script&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/yemF2WEsMm8" height="1" width="1"/&gt;</description><a10:updated>2010-01-11T10:54:09-05:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20091213/counting-sort-in-c-and-python--operation-algorithm-2.aspx</feedburner:origLink></item><item><guid isPermaLink="false">24</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/WLS2m3HC-6U/quicksort-in-c-and-scheme---operation-algorithm-1.aspx</link><title>Quicksort in C and Scheme : Operation Algorithm 1</title><description>&lt;p&gt;This is the first post in &lt;a href="http://matthewrathbone.com/Blog/view/post/20091119/operation-algorithm--introduction.aspx"&gt;my quest to be a better programmer&lt;/a&gt;. Quicksort is one of the 'standard' sorting algorithms. Its fairly easy to implement, and normally runs fairly quickly. I've implemented quicksort in both C and Scheme, although I think my Scheme implementation is more of a pseudo-quicksort due to a reluctance to break from the functional style encouraged by Scheme syntax.&lt;/p&gt;
&lt;h3&gt;Quicksort Overview&lt;/h3&gt;
&lt;p&gt;The 'Partition' algorithm is at the core of a quicksort implementation, and this partitions an array into groups of 'less than x' and 'more than x', with x itself being placed inbetween. The final position of x is the value returned by the partition function. In my simple implementation, the choice of x remains constant (either the first or last element). Randomizing this is the main way to increase the worst case speed of this algorithm.&lt;/p&gt;
&lt;p&gt;After partitioning the initial input, quicksort recursivly calls itself on the 'less-than' and 'more-than' groups returned from partition. The result is a chain of recursive calls which continues until quicksort is trying to sort a single number.&lt;/p&gt;
&lt;p&gt;Check out Wikipedia to get a more in-depth understanding of quicksort.&lt;/p&gt;
&lt;h3&gt;Special Property&lt;/h3&gt;
&lt;p&gt;Quicksort is good because it sorts 'in-place'. In other words it doesn't use a secondary array to sort the elements into. This can save a lot of memory, especially if you are sorting a list of complicated data structures which are a few KB each.&lt;/p&gt;
&lt;h3&gt;My C Implementation&lt;/h3&gt;
&lt;script type="syntaxhighlighter" class="brush: cpp"&gt;&lt;![CDATA[
void Quicksort(int A[], int p, int r){
	
	if(p&lt;r){
		int q = Partition(A, p, r);
		Quicksort(A, p, q-1);
		Quicksort(A, q+1, r);
	}
}

int Partition(int A[], int p, int r){
	int j, temp;
	
	int x = A[r];
	int i = p -1;
	
	for(j = p;j&lt;r;j++){
		if(A[j]&lt;= x)
		{
			i++;
			temp = A[i];
			A[i] = A[j];
			A[j] = temp;
		}
	}
	temp = A[r];
	A[r] = A[i +1];
	A[i+1] = temp;
	
	return i+1;
	
	
]]&gt;&lt;/script&gt;
&lt;h3&gt;My Scheme Implementation&lt;/h3&gt;
&lt;p&gt;I think its worth noting that the scheme implementation doesn't exactly sort 'in-place'. Instead it recursivly builds up secondary lists then joins them together at the end as the return value instead of moving the elements around in a single list. However the amount of memory used should still be in the order of the number of elements in the input array unlike other sorting algorithms (counting-sort, and bucket-sort come to mind) which use secondary arrays which do not form part of the solution.&lt;/p&gt;
&lt;pre class="clojure" name="code"&gt;
(define pHelper (lambda (all chk l m)
                  (cond ((null? all) (cons l (cons chk (cons m '()))))
                        (else
                        (let ((x (car all)))
                          (if (&lt;= x chk) 
                              (pHelper (cdr all) chk (cons x l) m)
                              (pHelper (cdr all) chk l (cons x m))))))))

(define partition (lambda (l)
                      (pHelper (cdr l) (car l) '() '())))



(define quicksort (lambda (l)
                    (cond ((null? l) l)
                          (else
                          (let ((lx (partition l)))
                            (append (quicksort (car lx)) (cons (cadr lx) (quicksort (caddr lx)))))))))&lt;/pre&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/WLS2m3HC-6U" height="1" width="1"/&gt;</description><a10:updated>2009-12-13T20:41:30-05:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20091123/quicksort-in-c-and-scheme---operation-algorithm-1.aspx</feedburner:origLink></item><item><guid isPermaLink="false">20</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/pILMrGidGXA/operation-algorithm--introduction.aspx</link><title>Operation Algorithm: Introduction</title><description>&lt;p&gt;In an attempt to &lt;strong&gt;be a better programmer&lt;/strong&gt;, and even better student, I'm undertaking a new mini-project: I will make a series of blog posts whereby I describe a particular (well known) algorithm, then provide an implementation in 2 different programming languages.&lt;/p&gt;
&lt;h2&gt;Skills++&lt;/h2&gt;
&lt;p&gt;Doing this should help with two things.&lt;/p&gt;
&lt;p&gt;1) It should make me remember these algorithms in more detail. Most of these algorithms are so very clever that it will certainly help if I know them by heart.&lt;/p&gt;
&lt;p&gt;2) At a time when I don't need to use anything other than Java it will help to keep me comfortable with other languages.&lt;/p&gt;
&lt;h2&gt;Languages&lt;/h2&gt;
&lt;p&gt;I'm certainly going to do every algorithm in C, probably not with the best C code, but certainly C code that works. Also I'll probably switch in and out of a functional language such as Scheme and something like VBA to keep it old-school.&lt;/p&gt;
&lt;h2&gt;Algorithms and Links&lt;/h2&gt;
&lt;p&gt;I will update this post with links when I make each post. Also check out the Operation-Algorithm tag in my tag cloud for easy access.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://matthewrathbone.com/Blog/view/post/20091123/quicksort-in-c-and-scheme---operation-algorithm-1.aspx"&gt;Quicksort&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://matthewrathbone.com/Blog/view/post/20091213/counting-sort-in-c-and-python--operation-algorithm-2.aspx"&gt; Counting Sort&lt;/a&gt;&lt;br /&gt;
BucketSort (love this one)&lt;br /&gt;
Heapsort (including the making of a Max-heap)&lt;br /&gt;
Binary Search Tree creation and traversal&lt;/p&gt;
&lt;p&gt;Stay tuned!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/pILMrGidGXA" height="1" width="1"/&gt;</description><a10:updated>2009-12-13T20:53:36-05:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20091119/operation-algorithm--introduction.aspx</feedburner:origLink></item><item><guid isPermaLink="false">19</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/tkWboBcMhQQ/what-is-twitter--the-new-forum-for-pyramid-schemes-apparently.aspx</link><title>What Is Twitter? The New Forum for Pyramid Schemes Apparently</title><description>&lt;p&gt;&lt;img alt="Pyramid scheme picture" src="http://matthew.rathbone.googlepages.com/pyramid.JPG" /&gt; So I was casually browsing blogs and twitter posts this morning and came across a bunch of links to a new twitter application called &lt;a href="http://tweetergetter.com/rathboma"&gt;Tweeter Getter&lt;/a&gt;. Essentially this is a twitter pyramid scheme to get you *thousands* of followers.&lt;/p&gt;
&lt;h2&gt;Pyramids&lt;/h2&gt;
&lt;p&gt;Here is an apt description of the pyramid business model from Wikipedia:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The essential idea is that the mark, Mr. X, makes only one payment. To start earning, Mr. X has to recruit others like him who will also make one payment each. Mr. X gets paid out of receipts from those new recruits. They then go on to recruit others. As each new recruit makes a payment, Mr. X gets a cut. He is thus promised exponential benefits as the &amp;quot;business&amp;quot; expands.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Twitter + Pyramid&lt;/h2&gt;
&lt;p&gt;In our case the business is twitter followers, and the payments are follows.&lt;/p&gt;
&lt;p&gt;By following the first 6 users on the list, and retweeting your own &lt;a href="http://tweetergetter.com/rathboma"&gt;link&lt;/a&gt;, you start your own little pyramid coming in under the 6 people above you. They get a new follower, and on the assumption that people ACTUALLY follow your link you could get the same.&lt;/p&gt;
&lt;p&gt;Each subsequent person that joins the pyramid from either your link, or a derivative of your link will add you as another follower.&lt;/p&gt;
&lt;h2&gt;Lots of People&lt;/h2&gt;
&lt;p&gt;Of course this model is not sustainable in the long term, and the more people join the lower the 'returns' are likely to be. By the time the pyramid is 13 layers deep, it will need more than the entire population of the globe to participate in order to continue.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/tkWboBcMhQQ" height="1" width="1"/&gt;</description><a10:updated>2009-06-03T05:25:54-04:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20090603/what-is-twitter--the-new-forum-for-pyramid-schemes-apparently.aspx</feedburner:origLink></item><item><guid isPermaLink="false">18</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/vVw3dsURYVs/moving-countries-is-not-so-fun.aspx</link><title>Moving Countries is not so fun</title><description>&lt;p&gt;I move to &lt;a href="http://maps.google.co.uk/maps?q=new+york+city&amp;amp;oe=utf-8&amp;amp;client=firefox-a&amp;amp;ie=UTF8&amp;amp;split=0&amp;amp;gl=uk&amp;amp;ei=5qIfSoPyK4PSjAfEyKS8Bg&amp;amp;ll=40.78678,-73.854218&amp;amp;spn=0.671698,1.224976&amp;amp;z=10&amp;amp;iwloc=A"&gt;New York City&lt;/a&gt; in July with my soon-to-be fiance and while we're very excited, the amount work required in order to make it happen is staggering&lt;/p&gt;
&lt;p&gt;I'm doing a masters in computer science, and its already taken me about 9 months to pull that off, but we still have to:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Get the university documentation I need for a visa&lt;/li&gt;
    &lt;li&gt;Get a Visa&lt;/li&gt;
    &lt;li&gt;Work out if shipping all our stuff to the USA is cost effective&lt;/li&gt;
    &lt;li&gt;Realize it isn't&lt;/li&gt;
    &lt;li&gt;Sell everything we can't fit into 4 (large) suitcases&lt;/li&gt;
    &lt;li&gt;Sell more stuff when we realize the suitcases weigh three times the allowed limit&lt;/li&gt;
    &lt;li&gt;Cancel all our phone bills / electricitiy bills / internet bills / etc&lt;/li&gt;
    &lt;li&gt;Sell the car (already done!)&lt;/li&gt;
    &lt;li&gt;Move out of our London flat&lt;/li&gt;
    &lt;li&gt;Find somewhere to stay until our flights (Thanks Rob)&lt;/li&gt;
    &lt;li&gt;Fly out&lt;/li&gt;
    &lt;li&gt;Move in&lt;/li&gt;
    &lt;li&gt;Realize we forgot something important&lt;/li&gt;
    &lt;li&gt;Realize we're going to have about 1/2 the space we had in London&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Costs&lt;/h3&gt;
&lt;p&gt;We thought it would be pretty cost effective to ship all our stuff by freight, you know because it takes 2-3 months and your stuff could get covered in sea water, but we were quoted &amp;pound;400 just to ship 5 regular moving boxes. Thats insane.&lt;/p&gt;
&lt;p&gt;Bearing in mind that its costing us $30,000 a year for me to do a masters we need every penny we can get.&lt;/p&gt;
&lt;h3&gt;Crazy&lt;/h3&gt;
&lt;p&gt;You'd also think that a university such as NYU (which has 45% international students) would have a process in place for registering with various national governments as a provider of education. Apparently they missed that lecture, and instead I have to deal with administration offices who have absolutely no idea.&lt;/p&gt;
&lt;p&gt;I'm trying to get them to register with the &lt;a href="http://www.lsc.gov.uk/"&gt;UK Learning and skills council &lt;/a&gt;(so the UK government will give me an interest-paid loan). Its already taken me a month of talking to one office after another, and they still haven't managed to fill in the 2 page form. I keep getting responses like &lt;em&gt;&amp;quot;we don't think we can participate in that scheme&amp;quot;&lt;/em&gt; and &lt;em&gt;&amp;quot;we don't understand the requirements&amp;quot;&lt;/em&gt;, but what they really mean is &lt;em&gt;&lt;strong&gt;&amp;quot;We can't be bothered&amp;quot;&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Excited Regardless&lt;/h3&gt;
&lt;p&gt;All this stuff will go away in a few months so I'm not going to let myself get worked up. Instead I think I'll just dig in the the final push, because this next year could well be the best year of my life.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/vVw3dsURYVs" height="1" width="1"/&gt;</description><a10:updated>2009-05-29T05:01:57-04:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20090529/moving-countries-is-not-so-fun.aspx</feedburner:origLink></item><item><guid isPermaLink="false">17</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/NMqk_Ydl6KA/all-quiet-on-the-western-front.aspx</link><title>All Quiet on the Western Front</title><description>&lt;p&gt;I've been working on a personal project: &lt;a href="http://www.tiptoptweet.com"&gt;http://www.tiptoptweet.com&lt;/a&gt; which has taken up a whole lot of my time. Because of that I've been neglecting this site somewhat. Well, the site is now finished and I could do with some feedback, but equally I should be able to pick up the blogging slack a bit too.&lt;/p&gt;
&lt;h3&gt;What Is TipTopTweet?&lt;/h3&gt;
&lt;p&gt;Its a twitter application that lets you &lt;strong&gt;vote&lt;/strong&gt; for other &lt;strong&gt;@users&lt;/strong&gt; or &lt;strong&gt;URL&lt;/strong&gt;'s by simply adding a #hashtag to a message.&lt;/p&gt;
&lt;p&gt;By adding either #voteup or #votedown to a message which contains a user or a link, tiptoptweet will pick up your vote and record it. The website then shows top ranked links and users over a week / a day / a month in any vote category.&lt;/p&gt;
&lt;p&gt;You could say that its basically a Digg or Reddit for twitter.&lt;/p&gt;
&lt;h3&gt;Why?&lt;/h3&gt;
&lt;p&gt;I was getting a little fed up of all the sites which track a user's popularity on twitter by simply measuring how many other people are following them. I want to know who people actually think are interesting, letting users vote is an obvious way to do that.&lt;/p&gt;
&lt;p&gt;Technically speaking I also wanted to get some good experience with ASP.NET MVC, which the whole site is built in. I've learned an aweful lot about MVC actually, so I'm glad I did it.&lt;/p&gt;
&lt;h3&gt;What's Next?&lt;/h3&gt;
&lt;p&gt;I need feedback! I don't really care whether or not it becomes super-popular, but I do want to know if its useful, if it works properly, and how I could improve it.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you're reading this and it sounds even vaguely interesting, then please &lt;a href="http://www.tiptoptweet.com"&gt;check it out and let me know what you think!&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/NMqk_Ydl6KA" height="1" width="1"/&gt;</description><a10:updated>2009-05-29T05:03:42-04:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20090521/all-quiet-on-the-western-front.aspx</feedburner:origLink></item><item><guid isPermaLink="false">16</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/qpSNa-H7WD8/sending-emails-using-vba-in-excel--outlook--lotus-notes--and-smtp.aspx</link><title>Sending Emails using VBA in Excel: Outlook, Lotus Notes, and SMTP</title><description>&lt;p&gt;Love it or hate it, email is everywhere, so the demand for integrating email into simple applications can be pretty strong. I thought I'd share three simple methods by which you can send emails using VBA in any Microsoft office product. Thus allowing your users can annoy everyone with lovingly crafted emails at the push of a button.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I will outline two approaches to sending emails, advise as to best practice, and provide full code for implementation. Its all very simple, so all skill-levels should find it easy enough to follow (despite the horribly confusing articles on other websites).&lt;/p&gt;
&lt;h4&gt;The Two Approaches to Sending Email&lt;/h4&gt;
&lt;p&gt;The two approaches are: 1. Communicating directly with a mail server (such as Microsoft Exchange Server), or 2. using the API of a client application (such as Lotus Notes or Outlook).&lt;/p&gt;
&lt;p&gt;Using the client API binds your code to the email application running on a user's machine. The danger of this is that if you move from Lotus Notes to Microsoft Outlook the emailing routine is no longer going to work!&lt;/p&gt;
&lt;p&gt;The benefit of going directly to the server is that how you communicate with the server doesn't change regardless of whether you're using Microsoft Exchange, Google Apps, or Lotus Domino. However, some companies heavily lock-down their mail servers as a way to increase security, so this type of communication is not always an option (although it is in most cases if you ask the right person).&lt;/p&gt;
&lt;p&gt;Clearly the ideal way to send an email is to communicate directly with the mail server. SMTP is the ideal protocol for doing this (Simple Mail Transfer Protocol), so that is what I'll show you.&lt;/p&gt;
&lt;p&gt;For the sake of completeness I will also demonstrate how to send an email with both the Microsoft Outlook and IBM Lotus Notes APIs. Although let me stress again that these should NOT be used by default.&lt;/p&gt;
&lt;h4&gt;SMTP (The Best Way)&lt;/h4&gt;
&lt;p&gt;All windows distributions from Windows 2000 onwards include a COM API component called Collaboration Data Objects (CDO). This api wraps the underlying messaging API and allows us to very simply manipulate email objects.&lt;/p&gt;
&lt;p&gt;Here is the code:&lt;/p&gt;
&lt;pre name="code" class="vb"&gt;
Public Sub EmailViaCDO()


Dim sentFrom        As String
Dim serverAddress   As String
Dim messageBody     As String
Dim sendTo          As String
Dim userName        As String
Dim password        As String
Dim subject         As String

'This stuff would normally be passed into the method as parameters
sentFrom = &amp;quot;matthew.rathbone@example.com&amp;quot;
serverAddress = &amp;quot;server.example.com&amp;quot;
sendTo = &amp;quot;example@email.com&amp;quot;
messageBody = &amp;quot;This is a test email&amp;quot;
subject = &amp;quot;message subject&amp;quot;

Dim message As New CDO.message
Dim config As New CDO.Configuration

'set up the configuration for the email server
config.Fields(cdoSendUsingMethod).value = cdoSendUsingPort
config.Fields(cdoSMTPServer).value = serverAddress
config.Fields(cdoSMTPUseSSL).value = False
config.Fields(cdoSMTPConnectionTimeout).value = 10


'Only use these if the server requires authentication
' config.Fields(cdoSMTPAuthenticate).Value = cdoBasic
' config.Fields(cdoSendUserName).value = userName
' config.Fields(cdoSendPassword).value = password
'---------------

'update the config before using it
config.Fields.Update



Set message.Configuration = config
message.To = sendTo
message.from = sentFrom
message.subject = subject
message.TextBody = messageBody
message.AddAttachment (&amp;quot;C:\attachment.txt&amp;quot;)

'Away goes our message!
message.Send


End Sub

&lt;/pre&gt;
&lt;h4&gt;Microsoft Outlook&lt;/h4&gt;
&lt;p&gt;Because Outlook also has VBA, using outlook from any VBA-enabled application is actually very easy, see below:&lt;/p&gt;
&lt;pre name="code" class="vb"&gt;
Public Sub EmailViaOutlook()

' requires a reference to the Microsoft Outlook 8.0 Object Library

' creates and sends a new e-mail message with Outlook
Dim outlookFolder As Outlook.MAPIFolder
Dim recipient As Outlook.recipient
Dim mailItem As Outlook.mailItem

'this gets an existing outlook
Set outlookFolder = GetObject(&amp;quot;&amp;quot;, _
        &amp;quot;Outlook.Application&amp;quot;).GetNamespace(&amp;quot;MAPI&amp;quot;).GetDefaultFolder(olFolderInbox)
    
    ' lets create a new email message
    Set mailItem = outlookFolder.Items.Add
    
    mailItem.subject = &amp;quot;this is the subject&amp;quot;
    mailItem.Body = &amp;quot;This is the message I'm sending!&amp;quot;
    mailItem.Attachments.Add &amp;quot;C:\attachment.txt&amp;quot;
    
    'SOME OPTIONAL STUFF
    mailItem.OriginatorDeliveryReportRequested = True ' delivery receipt
    mailItem.ReadReceiptRequested = True ' read receipt
    
    
    'simply add a recipient
    mailItem.recipients.Add &amp;quot;someoneelse@example.com&amp;quot;
    
    'or add one then set some properties
    Set recipient = mailItem.recipients.Add(&amp;quot;someone@example.com&amp;quot;)
    recipient.Type = olCC
    
    
    'Finally, send our email
    mailItem.Send
    
    'or save it for later
    'mailItem.Save
End Sub
&lt;/pre&gt;
&lt;h4&gt;Lotus Notes&lt;/h4&gt;
&lt;p&gt;After using SMTP and Outlook, using the lotus API is not quite as pretty. Lets be honest, its down-right horrible. Regardless of this, here is the code:&lt;/p&gt;
&lt;pre name="code" class="vb"&gt;

Sub SendMailViaLotusNotes()
   
    'Method:
    ' open a lotus notes session
    ' open the notes database
    ' use the db to create a new mail document
    ' assign the key properties to the mail document
    ' create a rich-text item for the mail body (this allows us to have nicer emails)
    ' write our email body
    ' send the document
   
   'Requires reference to: &amp;quot;Lotus Domino Objects&amp;quot;
   
    Dim dominoSession As New NotesSession
    Dim mailDatabase As NotesDatabase
    Dim newMemo As NotesDocument
    Dim richText As NotesRichTextItem
    Dim strAttachment As String
    dominoSession.Initialize (&amp;quot;&amp;quot;)    'Prompts user for Password
    
    Set mailDatabase = dominoSession.GetDatabase(&amp;quot;&amp;quot;, &amp;quot;names.nsf&amp;quot;)
    Set newMemo = mailDatabase.CreateDocument
   
   
    newMemo.AppendItemValue &amp;quot;Form&amp;quot;, &amp;quot;Memo&amp;quot;
    newMemo.AppendItemValue &amp;quot;SendTo&amp;quot;, &amp;quot;matthew.rathbone@example.co.uk&amp;quot;
    newMemo.AppendItemValue &amp;quot;Subject&amp;quot;, &amp;quot;This is the subject&amp;quot;
    
    Set richText = newMemo.CreateRichTextItem(&amp;quot;Body&amp;quot;)
   
    richText.AppendText &amp;quot;This is my email text&amp;quot;
    
    newMemo.Send False

End Sub
&lt;/pre&gt;
&lt;p&gt;There's probably a better way to do this using the lotus API, or at least I hope there is!&lt;/p&gt;
&lt;p&gt;Hopefully these snippets of code have proven useful, feel free to use them in anyting you wish, although whenever possible please credit me with a link. If you have any questions, feel free to contact me.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/qpSNa-H7WD8" height="1" width="1"/&gt;</description><a10:updated>2009-04-26T11:09:39-04:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20090320/sending-emails-using-vba-in-excel--outlook--lotus-notes--and-smtp.aspx</feedburner:origLink></item><item><guid isPermaLink="false">15</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/HOUwWeBXqkI/a-list-of-useful-things-to-know-when-dealing-with-bloomberg-as-a-developer.aspx</link><title>A List of Useful Things to Know When Dealing With Bloomberg as a Developer</title><description>&lt;p&gt;&lt;img src="http://matthew.rathbone.googlepages.com/Bloomberg_Terminal.jpg" alt="" /&gt;&lt;br /&gt;
As the snappy title implies, the following items I consider to be useful pieces of information when working with Bloomberg.&lt;/p&gt;
&lt;h4&gt;1. Don't store any data retrieved via the Bloomberg Client Terminal API&lt;/h4&gt;
&lt;p&gt;Don't put it in a database, pass it around on excel sheets, use it as a data source for internal systems, or anything like this at all. Doing so will land you in a lot of trouble with Bloomberg for breaking your license agreement, something they take very seriously (can you say 'lawsuit'?)&lt;/p&gt;
&lt;h4&gt;2. Get end users to upgrade their aging terminal software to take advantage of Bloomberg's real-time Excel formulas.&lt;/h4&gt;
&lt;p&gt;If your users are still using spreadsheets filled with =BLP() formulas then a huge portion of CPU power on their machines is dedicated to continually refreshing 'static' data. Bloomberg had to use a series of macros and elaborate hacks to simulate real-time data feeds to excel before Microsoft included support for real-time data streaming ( =RTD() ).&lt;/p&gt;
&lt;p&gt;Newer versions of Bloomberg software include the =BDP() function which is simply a nice wrapper for Excel's build-in data streaming functionality. Using these new formulas will significantly improve the performance of Excel, and the PC as a whole. Plus sheets with the legacy =BLP formula will still work if you are not going to be able to migrate them.&lt;/p&gt;
&lt;h4&gt;3. Get a Bloomberg Developer License&lt;/h4&gt;
&lt;p&gt;Bloomberg offers a special cut-down license for IT professionals who work a lot with the Bloomberg Client Terminal API. This provides you with a limited amount of data through the API and some basic terminal software functionality. It's far from the ideal development environment (I hit my daily data limit by about 11am normally), but it's good enough to make sure what you're doing actually works.&lt;/p&gt;
&lt;p&gt;It costs around 1/3 as much as a 'real' terminal license, so you can save a lot of dough.&lt;/p&gt;
&lt;h4&gt;4. Really understand what fields you're looking at.&lt;/h4&gt;
&lt;p&gt;Get yourself on a bloomberg terminal, navigate to the main page of an instrument (use &amp;quot;GOOG EQUITY&amp;quot; for a good example) then type &amp;quot;FLDS&amp;quot;. You can now search for any field you want and see what value is assigned to it for the current instrument.&lt;/p&gt;
&lt;p&gt;If you don't have access to the terminal (hi to fellow developers with restricted licenses) just go to the bloomberg menu in excel and use the 'field search' functionality. It basically does the same thing, except you don't get instrument values, merely a text description of the field.&lt;/p&gt;
&lt;h4&gt;5. You can use the API for 2 or 3 Days after last logging-in to the Terminal&lt;/h4&gt;
&lt;p&gt;So you closed your bloomberg Terminal window? Never mind, you can still get data via the API! This data connection stays active until a few days have passed or you log on somewhere else (if you've got an anywhere license).&lt;/p&gt;
&lt;p&gt;This means you don't have to have a Bloomberg loaded to use bloomberg-enriched Excel sheets or applications using the API, saving memory, desktop space, and processing power.&lt;/p&gt;
&lt;h4&gt;6. The bloomberg buttons map to the function keys&lt;/h4&gt;
&lt;p&gt;Don't put up with a clunky Bloomberg Keyboard if you don't have to, as a developer you can just use your regular keyboard and ask Bloomberg to send you some keyboard stickers. These stickers go around your keys to show you the special bloomberg keys.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/HOUwWeBXqkI" height="1" width="1"/&gt;</description><a10:updated>2009-02-03T12:00:34-05:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20090203/a-list-of-useful-things-to-know-when-dealing-with-bloomberg-as-a-developer.aspx</feedburner:origLink></item><item><guid isPermaLink="false">14</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/ecH1yv59ClM/the-importance-of-ui-prototyping.aspx</link><title>The Importance of UI Prototyping</title><description>&lt;p&gt;User interface prototyping is a powerful tool, the effective use of which can save hundreds of man-hours, increase the quality of applications and enable better application architecture. The importance of prototyping should not be understated, I've worked on several projects where we wasted a lot of time 'fixing' and 'improving' the look and feel of the application during user testing, this could easily have been avoided if we'd simply PROTOTYPED the user interface first.&lt;/p&gt;
&lt;p&gt;In one of these projects our prototyping phase was axed due to tight project deadlines and a perceived user confidence about what they wanted to see and how they wanted it to act. Of course the project ran well over its deadline, and the users had many (many) UI changes once they got their hands on a working copy. These changes were not only to do with application usability, but the organization of key elements, things they now realized were missing, and sometimes fundamental changes to the way things needed to work. Instead of sitting on user confidence at the project outset we should have &lt;a href="http://www.useit.com/alertbox/20010805.html"&gt;ignored&lt;/a&gt; &lt;a href="http://www.codinghorror.com/blog/archives/001063.html"&gt;them completely&lt;/a&gt;, pushed back our deadlines and designed the interface properly.&lt;/p&gt;
&lt;p&gt;The benefits of prototyping an application are &lt;a href="http://www.useit.com/alertbox/20030414.html"&gt;well&lt;/a&gt; &lt;a href="http://www.informit.com/articles/article.aspx?p=463939"&gt;documented&lt;/a&gt;. &lt;a href="http://www.informit.com/articles/article.aspx?p=463939"&gt;Jakob Nielson &lt;/a&gt;notes that even simple paper based prototyping can dramatically increase ROI, it can also &lt;a href="http://www.informit.com/articles/article.aspx?p=463939"&gt;solicit feedback&lt;/a&gt;, meaning you can fix problems early, adapt your architecture, or even switch to a different technology.&lt;/p&gt;
&lt;p&gt;An argument against prototyping would be that it can take a lot of time or is an unnecessary cost. But think about it this way, if you do simple prototyping it will cost you the time of 1 analyst with basic developer input, alterations are easy to make as you don't have to change any code. In contrast, if UI issues come out in testing you need to document what's wrong, create time-consuming code changes, and retest. In my example, this happened 3 or 4 times before the users were even slightly happy. We could have made an awful lot of paper prototypes with that kind of time investment!&lt;/p&gt;
&lt;p&gt;I guess my point is, PROTOTYPE THE UI BEFORE TOUCHING YOUR CODE. The UI is what the user sees, the UI represents your final app. If your UI is terrible, the user won't care how intricate or well made it is underneath the surface and you'll waste a lot of time setting it right. I've learnt the hard way, hopefully you won't have to!&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmatthewrathbone.com%2fBlog%2fview%2fpost%2f20090120%2fthe-importance-of-ui-prototyping.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmatthewrathbone.com%2fBlog%2fview%2fpost%2f20090120%2fthe-importance-of-ui-prototyping.aspx" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/ecH1yv59ClM" height="1" width="1"/&gt;</description><a10:updated>2009-01-20T08:30:04-05:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20090120/the-importance-of-ui-prototyping.aspx</feedburner:origLink></item><item><guid isPermaLink="false">13</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/g-GvrgQkJ3A/5-useful-free-windows-power-user---developer-tools.aspx</link><title>5 Useful Free Windows Power User / Developer Tools</title><description>&lt;p&gt;Lots of tools are useful, but here's my favourite 5 tools which I install on every pc I use regularly.&lt;/p&gt;
&lt;h3&gt;1. Notepad ++&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://notepad-plus.sourceforge.net/uk/site.htm"&gt;LINK&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;An extremely useful application which replaces the regular notepad. It has tonnes of language support so that you get colored code in everything from perl to caml to xml. It's VERY quick to load, has a tabbed interface, and is generally lovely to use.&lt;/p&gt;
&lt;h3&gt;2. Tail&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://tailforwin32.sourceforge.net/"&gt;LINK&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I'm jealous of a whole bunch of UNIX stuff I don't get access to on a daily basis and tail is one of those things. This windows app lets you 'tail' text files (such as log files), updating the view every time the file changes and always scrolling to the bottom. Debugging through log files is made 100x easier!&lt;/p&gt;
&lt;h3&gt;3. Winmerge&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://winmerge.org/"&gt;LINK&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Winmerge is the open-source version of 'Beyond Compare' style applications. It allows you to easily compare and merge documents. It's not as feature-rich as beyond compare, but for what this type of tool is typically used for it's absolutely perfect.&lt;/p&gt;
&lt;h3&gt;4. Google Desktop&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://desktop.google.com/"&gt;LINK&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Stay with me on this one! This has improved my productivity 300%, being able to instantly open applications and common files is fantastic. I guess you could also use &lt;a href="http://www.microsoft.com/windows/products/winfamily/desktopsearch/default.mspx"&gt;Windows Live Desktop&lt;/a&gt;, or switch to &lt;a href="http://www.microsoft.com/windows/windows-vista/default.aspx"&gt;Vista&lt;/a&gt;. Personally, I found Google Desktop much faster than the Microsoft alternative.&lt;/p&gt;
&lt;p&gt;The most useful bit: Simply press CTRL twice and type:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://matthew.rathbone.googlepages.com/googleDesktopPic.jpg" alt="" /&gt;&lt;/p&gt;
&lt;h3&gt;5. TortoiseSVN&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://tortoisesvn.tigris.org/"&gt;LINK&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is a no-brainer. TortoiseSVN provides incredible Subversion integration into the Windows Shell, it changes folder icons based on item status' handles conflict resolution well, allows you to compare files (even better with Winmerge(see above)), and even enables comparison of Microsoft Office Documents (which is the REAL killer feature. Imagine lengthy functional requirements documents).&lt;/p&gt;
&lt;h3&gt;BONUS: PuTTY&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/"&gt;LINK&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SSH into a networked / remote Linux box with ease, you can even do it over &lt;a href="http://en.wikipedia.org/wiki/Tinternet"&gt;t'internet&lt;/a&gt; with some help from &lt;a href="http://www.dyndns.com/"&gt;a dynamic DNS Provider&lt;/a&gt;. Not only can you control your 'nix machine, but if you set up some &lt;a href="http://oldsite.precedence.co.uk/nc/putty.html"&gt;Tunnels&lt;/a&gt; you can use it as a http proxy, access the machine's local drives, access shared music and more.&lt;/p&gt;
&lt;p&gt;Plus you can make the Windows command prompt extremely jealous.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmatthewrathbone.com%2fBlog%2fview%2fpost%2f20081205%2f5-useful-free-windows-power-user---developer-tools.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmatthewrathbone.com%2fBlog%2fview%2fpost%2f20081205%2f5-useful-free-windows-power-user---developer-tools.aspx" border="0" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/g-GvrgQkJ3A" height="1" width="1"/&gt;</description><a10:updated>2008-12-05T08:24:26-05:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20081205/5-useful-free-windows-power-user---developer-tools.aspx</feedburner:origLink></item><item><guid isPermaLink="false">12</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/3t_28lQXBT0/be-careful-of-data-obtained-from-bloomberg-using-rtd-or-bdp-functions.aspx</link><title>Be Careful of Data Obtained From Bloomberg using RTD or BDP Functions</title><description>&lt;p&gt;The RTD / BDP functions provide real-time data from bloomberg directly to an excel sheet. However if you're subscribing to fields which Bloomberg hasn't designated to be 'real-time enabled' you have to manually refresh bloomberg data for it to have any effect.&lt;/p&gt;
&lt;h3&gt;&lt;br /&gt;
Let's look at an example&lt;/h3&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;FUT_CTD_PX (Cheapest to deliver price) is a static FIELD for a real-time VALUE. IE, if you check in the BB terminal this value will be constantly changing, but excel sees it as a static field.&lt;/p&gt;
&lt;p&gt;To get the CTD price for a future we can use the following formula:&lt;/p&gt;
&lt;p&gt;=BDP(&amp;quot;SOME FUTURE'S TICKER&amp;quot;, &amp;quot;FUT_CTD_PX&amp;quot;)&lt;/p&gt;
&lt;p&gt;This field will never update, it will stay static with it's initial value. If the spreadsheet has been open for 5 days, it's the price from 5 days ago which will be displayed.&lt;/p&gt;
&lt;p&gt;Microsoft's RTD server model is event driven, in that the data-source notifies the RTD server when a new value is available and that value is picked up by a spreadsheet when excel calls it's RTD.RefreshData method (which it does every 2 seconds by default). In our example, Bloomberg's data-source never notifies the RTD server of a change in value for any of it's STATIC fields, and they therefore remain the same indefinitely.&lt;/p&gt;
&lt;p&gt;This also explains why calling RTD.RefreshData from VBA code has no effect, as the RTD server has no new value to pass forwards.&lt;/p&gt;
&lt;h3&gt;Solutions&lt;/h3&gt;
&lt;p&gt;The only REAL solution is for Bloomberg to provide such key fields as real-time. Static fields should be reserved for values which do not change on a regular basis, such as instrument name, maturity date, ISIN, and so forth.&lt;/p&gt;
&lt;p&gt;As a manual solution, Bloomberg does provide a Excel menu containing data-refresh commands. Clicking 'refresh entire workbook' will eventually update all static values (it can take up to 10 seconds), but only for the =BDP formula. If you're using =RTD you'll have to re-open your workbook or delete and re-type the formulas.&lt;/p&gt;
&lt;p&gt;&amp;quot;Can I do this Programatically?&amp;quot; I hear you cry.... Why yes you can!&lt;/p&gt;
&lt;p&gt;It's not a graceful solution by any means but you can use one of the following to activate the respective bloomberg command:&lt;/p&gt;
&lt;pre class="vb" name="code"&gt;
Application.Run (&amp;quot;bloombergui.xla!RefreshData&amp;quot;) [Default]

Application.Run (&amp;quot;bloombergui.xla!RefreshCurrentSelection&amp;quot;)

Application.Run (&amp;quot;bloombergui.xla!RefreshEntireWorksheet&amp;quot;)

Application.Run (&amp;quot;bloombergui.xla!RefreshEntireWorkbook&amp;quot;)

Application.Run (&amp;quot;bloombergui.xla!RefreshAllWorkbooks&amp;quot;)
&lt;/pre&gt;
&lt;p&gt;be sure to wrap any use of these in good error checking to avoid Excel getting mad at the user.&lt;/p&gt;
&lt;h3&gt;&lt;br /&gt;
Summary&lt;/h3&gt;
&lt;p&gt;It's important to be aware that some bloomberg fields are not real-time. If you're using one of these fields for a key calculation you'll have to make sure that you manually refresh regularly, or that you have integrated a crude automation into your code.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/3t_28lQXBT0" height="1" width="1"/&gt;</description><a10:updated>2008-12-03T10:41:28-05:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20081203/be-careful-of-data-obtained-from-bloomberg-using-rtd-or-bdp-functions.aspx</feedburner:origLink></item><item><guid isPermaLink="false">11</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/xJ2Lv7TaBr0/some-easy-ways-to-reduce-excel-file-size-and-increase-reliability.aspx</link><title>Some Easy Ways to Reduce Excel File Size and Increase Reliability</title><description>&lt;p&gt;If you have an excel file over 10mb in size excel could become unstable and it will take forever to save, backup, or pretty much do anything with. It will also use significantly more memory, degrading the performance of your machine as a whole.&lt;/p&gt;
&lt;p&gt;I've worked in several offices dealing with excel files pushing 30mb. The reality is that these files need only be around 3 or 4mb. Regardless of how many rows of data you may be storing.&lt;/p&gt;
&lt;p&gt;Here are my key tips to reducing the size of your excel file:&lt;/p&gt;
&lt;h3&gt;1. Remove pictures&lt;/h3&gt;
&lt;p&gt;Shadows, images, and drawings all increase file size, drawing objects created by adding 3d effects or shadows have the worst effect as they're just stored as (large) pictures. If you've added shadows to some cells, remove them.&lt;/p&gt;
&lt;p&gt;Coloring cells also has a negative effect on file size, although more limited.&lt;/p&gt;
&lt;h3&gt;2. Delete unwanted Rows&lt;/h3&gt;
&lt;p&gt;This sounds silly, but it has a massive effect on file size.&lt;/p&gt;
&lt;p&gt;Here's a really simple example:&lt;br /&gt;
I've created a workbook with 3 sheets, each with 1000 records covering 18 columns. if I write some simple text to cell 65000 in each sheet the file size jumps by 500kb.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://matthew.rathbone.googlepages.com/filesize.jpg" alt="Excel File size comparison" /&gt;&lt;/p&gt;
&lt;p&gt;Excel sometimes seems to extend the lower boundry of worksheets without any real reason, so if you're working with large files I suggest you check to see if there are reams of unused rows.&lt;br /&gt;
I've reduced the size of one particular file from 24mb to 1.5mb using only this tactic.&lt;/p&gt;
&lt;p&gt;This also leads me on to my third point&lt;/p&gt;
&lt;h3&gt;3. Don't let macro's loop over every cell in a row / column&lt;/h3&gt;
&lt;p&gt;There are plenty of macros that will perform an assessment on every single cell in a particular column, all the way down to row 65k&lt;/p&gt;
&lt;p&gt;Not only will this make it take about 20 minutes to run, but it can easily trick excel into thinking that it needs to save the contents of every single row (see point 2).&lt;br /&gt;
Here's a simple loop which will only iterate over cells if they're occupied (your data will have to be in a proper table-structure):&lt;/p&gt;
&lt;pre name="code" class="vb"&gt;
dim usefulCell as Range 

set usefulCell = SampleSheet.Range(col1_header_range_name)

Do until usefulCell.Value = &amp;quot;&amp;quot;

	'Do some stuff here, for example:

	CustomerObject.Name = usefulcell.Value

	CustomerObject.Address = usefulcell.offset(0, 1).Value

	CustomerObject.Age = usefulcell.offset(0, 2).Value

	'etc

	set usefulCell = usefulCell.offset(1, 0)

Loop

&lt;/pre&gt;
&lt;h3&gt;4. Don't do things twice&lt;/h3&gt;
&lt;p&gt;Don't have more formulae than you have to. If you're relying on a specific calculation multiple times, only calculate it once, then refer to that calculation in subsequent cells.&lt;/p&gt;
&lt;p&gt;Don't replicate data, there's no point copying huge wads of data from one worksheet to another, reorganize so that you only need it in one place&lt;/p&gt;
&lt;p&gt;Use static values wherever possible: If data comes from some external source, milk that source to the max. Anything you are calculating which could be imported SHOULD be imported, calculations increase file size and reduce performance.&lt;/p&gt;
&lt;p&gt;I hope these tips help to make your excel user experience a better one. Please email me with any questions or comments.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/xJ2Lv7TaBr0" height="1" width="1"/&gt;</description><a10:updated>2008-12-02T05:47:58-05:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20081201/some-easy-ways-to-reduce-excel-file-size-and-increase-reliability.aspx</feedburner:origLink></item><item><guid isPermaLink="false">10</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/3aST33blfcQ/dependency-injection---inversion-of-control-with-vba.aspx</link><title>Dependency Injection / Inversion of Control with VBA</title><description>&lt;p&gt;Regardless of how much time Microsoft invests into developing Visual Studio Tools for Office there&amp;rsquo;s still going to be a market for VBA, but that doesn&amp;rsquo;t mean we have to compromise our methodologies or best practices.&lt;/p&gt;
&lt;p&gt;Dependency injection in VBA is not only possible, but it&amp;rsquo;s not as much work to implement as you might think. Sure VB6&amp;rsquo;s system for Interface implementation leaves a lot to be desired, and it&amp;rsquo;s a whole lot less flexible than modern languages, but you can still add a massive amount of flexibility and control to your code through a little thought and planning.&lt;/p&gt;
&lt;p&gt;There are a few key things we need for a basic IoC implementation.&lt;/p&gt;
&lt;p&gt;1.	Interfaces for key dependencies that we want to &amp;lsquo;inject&amp;rsquo; (for example a data-repository)&lt;br /&gt;
2.	A centralized way to change what concrete object is mapped to that interface by default&lt;br /&gt;
3.	A way to inject that concrete object upon creation of a dependant object (as VBA does not allow you to pass parameters on construction)&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s address how to do each of these things in turn:&lt;/p&gt;
&lt;h3&gt;Interfaces&lt;/h3&gt;
&lt;p&gt;Interfaces in VBA are created by making a class and populating it with stub methods and properties which don&amp;rsquo;t do anything, that&amp;rsquo;s it. You don&amp;rsquo;t have to declare it as an interface, but it would probably make sense to prefix the name with an &amp;lsquo;I&amp;rsquo;.&lt;br /&gt;
For example, here&amp;rsquo;s an interface for IDataSource:&lt;/p&gt;
&lt;pre class="vb" name="code"&gt;

Option Explicit
Public Function GetOrders(customerID As String) As collection
End Function
Public Function GetAllOrders() As collection

End Function

&lt;/pre&gt;
&lt;p&gt;Easy!&lt;/p&gt;
&lt;p&gt;And here&amp;rsquo;s a basic example implementation of that interface:&lt;/p&gt;
&lt;pre class="vb" name="code"&gt;
Option Explicit
Implements IDatasource
Public Function IDatasource_GetOrders(customerID As String) As collection
	Dim returnCollection As New collection

	returnCollection.Add (&amp;quot;Item1&amp;quot;)
	'Collection logic here
	Set IDatasource_GetOrders = returnCollection
End Function

Public Function IDatasource_GetAllOrders() As collection
	Dim returnCollection As New collection

	returnCollection.Add (&amp;quot;Item1&amp;quot;)
	returnCollection.Add (&amp;quot;Item2&amp;quot;)
	'Collection logic here
	Set IDatasource_GetAllOrders = returnCollection

End Function
&lt;/pre&gt;
&lt;h3&gt;&lt;br /&gt;
Object Mapping&lt;/h3&gt;
&lt;p&gt;Because we don&amp;rsquo;t have use of Unity, Spring.net, or any other IoC framework, the simplest thing to do is to completely dedicate a module to the job of being an &amp;lsquo;object provider&amp;rsquo;&lt;/p&gt;
&lt;p&gt;Because VBA doesn&amp;rsquo;t need to be compiled, it&amp;rsquo;s almost as easy as using a configuration file as you can change it on the fly without having to recompile and redeploy.&lt;/p&gt;
&lt;p&gt;Additionally, if you want to externalize the assignment of concrete objects to a configuration file, you can just extend this basic object.&lt;/p&gt;
&lt;p&gt;Here is an example of a simple object provider:&lt;/p&gt;
&lt;pre class="vb" name="code"&gt;
Option Explicit
'set your bindings here
Private mDataSource As New SqlDataSource
Public Property Get DataSource() As IDatasource
Set DataSource = mDataSource
End Property
&lt;/pre&gt;
&lt;p&gt;All you have to do is chage the type of the private members to switch the default concrete class.&lt;/p&gt;
&lt;h3&gt;Dependency Injection&lt;/h3&gt;
&lt;p&gt;VBA doesn&amp;rsquo;t allow us to have non-default class constructors, which means we cannot construct objects like below:&lt;/p&gt;
&lt;pre class="vb" name="code"&gt;
Dim dataService as new OrderService(SqlRepository)
&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;
Instead we simple have to be a little more creative with our objects, I tend to add a method called Initialize which takes a IDataRepository class. If you haven&amp;rsquo;t initialized the class, no methods that rely on this private member will work, which acts as a failsafe:&lt;/p&gt;
&lt;pre class="vb" name="code"&gt;
Dim repository as IOrderRepository
Dim dataService as new ObjectService
Set repository = ObjectProvider.OrderRepository
dataService.Initialize repository
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Coding VBA can be frustrating and confusing when one is used to more elegant languages and frameworks, but that doesn&amp;rsquo;t mean it&amp;rsquo;s impossible to import modern programming strategies and methodologies.&lt;/p&gt;
&lt;p&gt;Using inversion of control in any framework promotes code reuse, separates concerns, and makes for more manageable maintenance going forwards. Working with an outdated framework does not mean one has to write code like it&amp;rsquo;s 1995. &lt;br /&gt;
&amp;nbsp;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/3aST33blfcQ" height="1" width="1"/&gt;</description><a10:updated>2009-05-29T05:17:00-04:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20081110/dependency-injection---inversion-of-control-with-vba.aspx</feedburner:origLink></item><item><guid isPermaLink="false">9</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/wfex08OeYLE/stack-overflow-is-fantastic.aspx</link><title>Stack Overflow is Fantastic</title><description>&lt;p&gt;I've just started delving into &lt;a href="http://www.stackoverflow.com"&gt;StackOverflow.com&lt;/a&gt;, and I think it's great! Good job all involved!&lt;/p&gt;
&lt;p&gt;I know it's made by mr &lt;a href="http://www.codinghorror.com"&gt;Coding Horror&lt;/a&gt; himself, so it always had a lot of promise, but it's easy to use, responsive, well thought out, and ADDICTIVE!&lt;/p&gt;
&lt;p&gt;For those who don't know, it's basically the Yahoo Answers for programmers, except that it has extra addictive features, it's very fast and some of the answers that come out of it are just pure quality.&lt;/p&gt;
&lt;p&gt;The idea of the 'badges' is great, makes you almost feel like you're in a game trying to score points, you earn a badge when you accomplish something, it's like being in a MMORPG but instead of killing 3000 lizards you're letting someone know how to write graceful REGEX patterns.&lt;/p&gt;
&lt;p&gt;I suggest everyone check it out&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/wfex08OeYLE" height="1" width="1"/&gt;</description><a10:updated>2008-10-09T18:29:20-04:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20081009/stack-overflow-is-fantastic.aspx</feedburner:origLink></item><item><guid isPermaLink="false">8</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/Ho90y6HvcYM/using-range-offset-in-vsto-for-excel.aspx</link><title>Using Range.offset in VSTO for Excel</title><description>&lt;p&gt;Range.Offset[a, b].value , when using VBA is a great way to add values to adjacent cells without having to actually select every cell you write to (which is very slow as it requires the UI). When I started using VSTO I could only find the Offset method attached to the strongly typed Named_Range object.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
Luckily, it does exist for a regular range, except the method is called get_Offset (obviously).&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
So there you have it. Sounds simple, but this has been frustrating me for a couple of weeks now.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;br /&gt;
rangeObject.get_Offset[1, 2];&lt;br /&gt;
&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/Ho90y6HvcYM" height="1" width="1"/&gt;</description><a10:updated>2008-09-16T01:58:40-04:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20080916/using-range-offset-in-vsto-for-excel.aspx</feedburner:origLink></item><item><guid isPermaLink="false">7</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/IyFWQ0qcBFA/why-you-should-use-recordsets-and-object-orientation-in-vba-instead-of-arrays.aspx</link><title>Why You Should Use Recordsets and Object Orientation in VBA Instead of Arrays</title><description>&lt;p&gt;When I starting working with VBA 4 years ago arrays were my best friends, they&amp;rsquo;re easy to use, easy to understand, and getting data to / from an Excel sheet is a piece of cake as cell (0, 1) can map nicely to array position 0, 1. However I&amp;rsquo;ve developed the opinion that arrays should be avoided in favour of other forms of data lists / collections.&lt;/p&gt;
&lt;h3&gt;What&amp;rsquo;s Wrong With Arrays&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s not that arrays are particularly wrong, it&amp;rsquo;s more that in comparison to the alternatives they&amp;rsquo;re limited and frustrating to use and support;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;middot;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Size declaration &amp;ndash; You have to declare how big you&amp;rsquo;re array is going to be, even if you don&amp;rsquo;t know yet. This is a key limitation regardless of the fact you can &amp;lsquo;re-declare&amp;rsquo; to increase the size.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;middot;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;No in-built sorting / filters / search functions. An array is an array, it doesn&amp;rsquo;t have any methods associated with it. It doesn&amp;rsquo;t even have it&amp;rsquo;s only object type.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;middot;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;It can only hold strings, numeric values, characters etc.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;middot;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Moving through an array is arduous with large amounts of data and there&amp;rsquo;s no standard &amp;lsquo;structure&amp;rsquo; an array must take (I can declare a 0 based array, a co-worker may declare a 1 based array, and there&amp;rsquo;s no standard slot for each piece of information etc)&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;h3&gt;So What are the Alternatives?&lt;/h3&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;strong&gt;ADODB.RECORDSETS&lt;/strong&gt;&lt;/div&gt;
&lt;p&gt;Instead of using arrays to store string and numerical values I&amp;rsquo;ve recently been using ADODB.recordsets (recordsets).&lt;/p&gt;
&lt;p&gt;Recordsets are slightly more object oriented than arrays, as in essence they are collections of record objects, although they can be manipulated without even using or referring to the record object.&lt;/p&gt;
&lt;div&gt;Benefits of Recordsets:&lt;/div&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;middot;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;No size declaration, you can type myRecordset.AddNew to create a new record and populate it with values.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;middot;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;You define fields to specify what data is where, instead of having to remember which position in the array the address is you can just move to a record and use myRecordset.Fields(&amp;ldquo;myField&amp;rdquo;).value to retrieve it.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;middot;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;You also don&amp;rsquo;t have to iterate through a recordset to output the contents to a worksheet:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;lsquo; Move to the beginning of the recordset&lt;/p&gt;
&lt;div&gt;myRecordset.MoveFirst&lt;/div&gt;
&lt;p&gt;&amp;lsquo;output the contents to a worksheet starting at cell A1&lt;/p&gt;
&lt;p&gt;someWorksheet.Range(&amp;ldquo;A1&amp;rdquo;).value = myRecordset.GetRows()&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;middot;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;They have inbuilt search functions&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;middot;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;They&amp;rsquo;re easier to iterate over if you need to, or you can do bulk updates&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;middot;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;The list goes on....&lt;/p&gt;
&lt;p&gt;There are of course limitations to recordsets, they&amp;rsquo;re frustrating to work out at times, and can be counter intuitive, but I&amp;rsquo;ve found the benefits of having a more structured set of data are fantastic.&lt;/p&gt;
&lt;p&gt;Add Microsoft ActiveX Data Objects Library 2.8 to your VBA references and have a play.&lt;/p&gt;
&lt;div&gt;&lt;strong&gt;OBJECTS AND COLLECTIONS&lt;/strong&gt;&lt;/div&gt;
&lt;p&gt;If you&amp;rsquo;ve declared a customer object and given that customer properties such as FirstName, LastName and CustomerID there&amp;rsquo;s no confusion on how to find that information.&lt;/p&gt;
&lt;p&gt;If you combine that benefit with the use of the Collection object you make your code so much easier to understand, use and support.&lt;/p&gt;
&lt;p&gt;Collections and object lists figure more in strongly typed object oriented languages such as C# than in VBA, but we can still take advantage of VBA&amp;rsquo;s generic collection object.&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;Dim c as New Collection&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;The more you object orient your code in VBA the more you&amp;rsquo;ll use collections, and the easier your life will become, you won&amp;rsquo;t have to pass around huge arrays and remember between procedures which attribute is where, as you&amp;rsquo;ll have strongly typed objects to work from and the re-use and quality of your code will vastly improve.&lt;/p&gt;
&lt;p&gt;In the near future I&amp;rsquo;ll post a getting started guide to object orientation in VBA so that these benefits can reveal themselves more clearly.&lt;/p&gt;
&lt;p&gt;Overall object orientation is the best path to take for storing data, however, even the use of recordsets can drastically improve the speed, reliability, supportability and expandability of your code.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/IyFWQ0qcBFA" height="1" width="1"/&gt;</description><a10:updated>2008-08-17T15:37:23-04:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20080817/why-you-should-use-recordsets-and-object-orientation-in-vba-instead-of-arrays.aspx</feedburner:origLink></item><item><guid isPermaLink="false">6</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/cKl2-0Oi-qE/asp-net-rejects-the-google-crawler-with--network-unavailable--error.aspx</link><title>ASP.NET rejects the google crawler with 'NETWORK UNAVAILABLE' error</title><description>&lt;p&gt;This has happened to me with this site, and seems to be a common problem, but fear not, help is at hand.&lt;/p&gt;
&lt;p&gt;According to &lt;a href="http://www.kowitz.net"&gt;Brendan Kowitz&lt;/a&gt; this is due to ASP.NET being unable to match the googlebot's browser signiture and thus defaulting it to the 'MOZILLA 1.0' setting.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.kowitz.net/archive/2006/12/11/asp.net-2.0-mozilla-browser-detection-hole.aspx"&gt;He's posted a solution to the problem&lt;/a&gt;, and you know what, it works! The solution is a simple genericMozilla.browser file which you need to include in your site. It also solves similar problems with other search engines.&lt;/p&gt;
&lt;p&gt;You can check what response google will receive from your site with &lt;a href="http://www.asymptoticdesign.com/aux/header-viewer.cgi"&gt;this tool.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Through the tool I can see that my site now returns the correct &lt;em&gt;HTTP/1.1 200 OK &lt;/em&gt;status message, whereas before it was returning a 500 error.&lt;/p&gt;
&lt;p&gt;Hope this helps someone.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/cKl2-0Oi-qE" height="1" width="1"/&gt;</description><a10:updated>2008-12-04T05:06:23-05:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20080815/asp-net-rejects-the-google-crawler-with--network-unavailable--error.aspx</feedburner:origLink></item><item><guid isPermaLink="false">5</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/FSlqsdgGWBE/comparing-the-contents-of-two-tables-from-two-different-databases-in-sql-server.aspx</link><title>Comparing the contents of two tables from two different databases in SQL Server</title><description>&lt;p&gt;&lt;span&gt;When you don't have any sql server analysis tools to hand comparing the data from two tables can be a pain, especially when those tables are in different databases, or even completely different servers. I've found myself in this position several times so eventually I decided to just write myself a small VBScript which can extract the data for me and load up my favourite diff tool to compare the contents.&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;&lt;span&gt;Using the VB Script:&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;First you need to set the constants at the top of the vbs file to tell it where to get the data and where to find the compare engine exe:&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;'Table 2--------------------------------------------------------------------------------------------&lt;/div&gt;
&lt;p&gt;const t2Server&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;= &amp;quot;ExampleSqlServer2&amp;quot;&lt;/p&gt;
&lt;p&gt;const t2Database&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;= &amp;quot;MyExampleDatabase2&amp;quot;&lt;/p&gt;
&lt;p&gt;const t2Table&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;= &amp;quot;ReplicatedCustomerOrders&amp;quot;&lt;/p&gt;
&lt;p&gt;const t2Columns&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;= &amp;quot;OrderID, ProductID, OriginalQty&amp;quot;&lt;/p&gt;
&lt;p&gt;const t2WhereClause&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;= &amp;quot;ProductID is not null&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ' comment out one or the other of below depending on how you plan to connect. Default is windows authentication&lt;/p&gt;
&lt;p&gt;const t2Security&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;= &amp;quot;Trusted_Connection=Yes&amp;quot;&lt;/p&gt;
&lt;p&gt;'const t2Security&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;= &amp;quot;User ID =enterusernamehere; Password=mypassword &amp;quot;&lt;/p&gt;
&lt;div&gt;'------------------------------------------------------------------------------------------------&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;'Export Options&lt;/div&gt;
&lt;p&gt;const defaultExportLocation = &amp;quot;C:\databasecompareexports\&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;'Comparison Application-------------------------------------------------------------&lt;/p&gt;
&lt;div&gt;const comparisonEngine = &amp;quot;C:\windiff.exe&amp;quot;&lt;/div&gt;
&lt;div&gt;'-------------------------------------------------------------------------------------------&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;Secondly you need to make sure the execution string for the comparison tool is correct, I&amp;rsquo;ve tested it working with &lt;a href="http://www.grigsoft.com/download-windiff.htm"&gt;Windiff&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;If you need to change the execution string it&amp;rsquo;s on line 115:&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;sCompare = comparisonEngine &amp;amp; &amp;quot; &amp;quot; &amp;amp; defaultExportLocation &amp;amp;&amp;nbsp;&amp;quot;1.output &amp;quot; &amp;amp; defaultExportLocation &amp;amp;&amp;nbsp;&amp;quot;2.output&amp;quot;&lt;/p&gt;
&lt;div&gt;wShell.Run(sCompare)&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;That's it! If you're using it with WinDiff it will work using only step 1!&lt;/p&gt;
&lt;h3&gt;Debugging&lt;/h3&gt;
&lt;p&gt;Throughout the script there are calls to a logging function which is present at the bottom of the script. Currently all this does is write a line to the windows application event log.&lt;/p&gt;
&lt;blockquote&gt;
&lt;div&gt;sub LogMyEvent(eventType, eventMessage)&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wShell.LogEvent eventType, eventMessage&lt;/p&gt;
&lt;div&gt;end sub&lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can find the event log by right clicking my computer, going to 'Manage' then goto 'Event Viewer' 'Application'. Because the script calls this procedure and not the shell logger directly you can replace this with whatever process you wish! Hooray!&lt;/p&gt;
&lt;p&gt;Remember that VB scripts have different error handling capabilities than regular VB6 or VBA, in other words you can't GOTO anywhere on error, it either breaks or carries on. So you have to manually check for errors at every important point. You can see this pattern throughout the script.&lt;/p&gt;
&lt;div&gt;The File&lt;/div&gt;
&lt;p&gt;I'm storing the file as a .txt file, don't ever trust .vbs files you download from the internet, they can do some nasty things to your computer! While you can trust my script, I'd recommend checking ALL VB scripts out first with notepad++ before using them.&lt;/p&gt;
&lt;div&gt;&lt;a href="http://matthew.rathbone.googlepages.com/SQLServerCompareVBS.txt"&gt;HERE IS THE FILE&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;If you&amp;rsquo;re not familiar with comparison tools check out Windiff (free), Compare It! (not free, but the best) and WinMerge (also free).&lt;/p&gt;
&lt;div&gt;Enjoy!&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/FSlqsdgGWBE" height="1" width="1"/&gt;</description><a10:updated>2008-08-10T09:28:49-04:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20080810/comparing-the-contents-of-two-tables-from-two-different-databases-in-sql-server.aspx</feedburner:origLink></item><item><guid isPermaLink="false">4</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/GqGtlgbmZxo/creating-com-compatible-events-in-c-sharp-for-use-in-vb6-or-vba.aspx</link><title>Creating COM Compatible Events in C Sharp For Use in VB6 or VBA</title><description>&lt;p&gt;Creating C# DLL's for use with COM is not too hard, however event exposure can be a little messy especially when trying to subscribe to events in vb6 or vba.&lt;/p&gt;
&lt;p&gt;Here's an example of an everyday COM exposed class:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ComVisible(true)&lt;br /&gt;
ClassInterface(ClassInterfaceType.AutoDual)&lt;br /&gt;
public class CComInterop&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;br /&gt;
We've integrated automatic interface generation so we don't have to make our own. However, this interface type does not expose events.&lt;/p&gt;
&lt;p&gt;The solution is to create a separate interface to expose the events but no other properties / methods of the class. Using some jiggery pokery it is also possible to integrate the contents of this interface into the class itself so that you don't have to deal with multiple objects on the COM side.&lt;/p&gt;
&lt;p&gt;METHOD:&lt;/p&gt;
&lt;p&gt;this is our event, and the event's delegate:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;public event SomeEventHandler SomeEvent;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
public delegate void SomeEventHandler(string teststring);&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;br /&gt;
To expose this event we create the following interface:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ComVisible(true)&lt;br /&gt;
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)&lt;br /&gt;
public interface IComInteropEvents&lt;br /&gt;
{&lt;br /&gt;
void SomeEvent(string teststring);&lt;br /&gt;
}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;br /&gt;
The important part is that we specify the interface type as&lt;strong&gt; IDispatch&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;But we don't want to have to declare a separate object for events, so we add a 'ComSourceInterfacesAttribute' referencing this interface, like so:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ComVisible(true)&lt;br /&gt;
ComSourceInterfacesAttribute(&amp;quot;Tam.Common.LzLibrary.IComInteropEvents&amp;quot;)&lt;br /&gt;
ClassInterface(ClassInterfaceType.AutoDual)&lt;br /&gt;
public class CComInterop&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;br /&gt;
Now we can use the object's events in vb6 or vba without having to declare separate objects!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Public WithEvents InteropObject As Some_Library.CComInterop&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;br /&gt;
and you can still use the methods and properties of the object normally with all intellisense intact.&lt;/p&gt;
&lt;p&gt;Full sample Class and interface shown below:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ComVisible(true)&lt;br /&gt;
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)&lt;br /&gt;
public interface IComInteropEvents&lt;br /&gt;
{&lt;br /&gt;
void SomeEvent(string teststring);&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
public delegate void SomeEventHandler(string teststring);&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
ComVisible(true)&lt;br /&gt;
ComSourceInterfacesAttribute(&amp;quot;Tam.Common.LzLibrary.IComInteropEvents&amp;quot;)&lt;br /&gt;
ClassInterface(ClassInterfaceType.AutoDual)&lt;br /&gt;
public class CComInterop&lt;br /&gt;
{&lt;br /&gt;
private int m_nSomeProperty = 0;&lt;br /&gt;
public event SomeEventHandler SomeEvent;&lt;/p&gt;
&lt;p&gt;public void SomeMethod(int nValue)&lt;br /&gt;
{&lt;br /&gt;
m_nSomeProperty = nValue;&lt;br /&gt;
// Raises the event&lt;br /&gt;
SomeEvent(&amp;quot;Hello&amp;quot;);&lt;br /&gt;
}&lt;/p&gt;
&lt;p&gt;public int SomeProperty&lt;br /&gt;
{&lt;br /&gt;
get { return m_nSomeProperty; }&lt;br /&gt;
set { m_nSomeProperty = value; }&lt;br /&gt;
}&lt;br /&gt;
}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/GqGtlgbmZxo" height="1" width="1"/&gt;</description><a10:updated>2008-08-06T15:19:51-04:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20080806/creating-com-compatible-events-in-c-sharp-for-use-in-vb6-or-vba.aspx</feedburner:origLink></item><item><guid isPermaLink="false">3</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/7xYnHvpnZag/converting-bloomberg-data-from-an-array-to-a-recordset-using-vba-in-excel.aspx</link><title>Converting Bloomberg data from an array to a recordset using VBA in Excel</title><description>&lt;p&gt;&lt;span style="font-size: medium;"&gt;&lt;font&gt;I have found whilst working in financial institutions that I am continually called upon to integrate Bloomberg market data into spreadsheets using VBA in Excel. While the Bloomberg API returns data in an array, I tend to work with recordsets when dealing with large sets of data. Because of this I have some standard code which I reuse in all my Bloomberg projects to fairly efficiently convert bloomberg results arrays into recordsets.&lt;br /&gt;
&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: medium;"&gt;ADODB.Recordsets have advantages over arrays for storing larger volumes of data, such as in built sorting and searching methods, and while converting an array into a recordset may seem like a waste of time it can make working with large volumes of Bloomberg data a lot easier. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: medium;"&gt;Implementing this function is very simple, you simply loop through the array and write the relevent values to the recordset after jigging about with the format of the original array.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: medium;"&gt;Here is the code complete with an example of retrieving data from the Bloomberg API:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class="vb" name="code"&gt;
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Function: BBArrayToRecordset
' Required Reference to: Microsoft ActiveX DataObjects
' Author: Matthew Rathbone
'
' Description: This function takes a results array as output by the Bloomberg API and converts it
' into a ADODB.recordset
'
' Copyright: Matthew Rathbone: Free for commercial and non-commercial use.
' Links to www.matthewrathbone.com are always appreciated
''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function BBArrayToRecordset(fieldList As Variant, dataArray As Variant) As ADODB.Recordset

    'declare our return object
    Dim returnSet As ADODB.Recordset
   
    ' string to hold our list of fields
    Dim fieldString As String
   
    'string to hold our list of records
    Dim recordString As String
   
    Dim rDataArray As Variant
    ReDim rDataArray(0 To UBound(dataArray, 2))
   
    'convert the fields array to a string
    fieldString = Strings.Join(fieldList, &amp;quot;, &amp;quot;)
   
    'construct our return object
    Set returnSet = New ADODB.Recordset
   
    ' lets make our recordset! Looping and adding fields
    For i = 0 To UBound(fieldList, 1)
        returnSet.Fields.Append fieldList(i), adVarChar, 500
    Next
   
    'open the recordset
    returnSet.Open
        ' lets fill our recordset!
        For i = 0 To UBound(dataArray, 1)
            For ii = 0 To UBound(dataArray, 2)
                rDataArray(ii) = dataArray(i, ii)
            Next
            returnSet.AddNew fieldList, rDataArray
        Next
       
   
    'return the recordset
    Set BBArrayToRecordset = returnSet
   
End Function

'Example of it's use
'THIS EXAMPLE REQUIRES THE BLOOMBERG DATA TYPE LIBRARY REFERENCE
Public Sub exampleExecution()

    Dim oBlp                    As BlpData
    Dim aResult                 As Variant
    Dim aTickerList             As Variant
    Dim aFieldList              As Variant
    Dim exampleRecordset        As ADODB.Recordset
   
    'defining the securities we want data for
    ReDim aTickerList(0 To 1)
    aTickerList(0) = &amp;quot;AMGN EQUITY&amp;quot;
    aTickerList(1) = &amp;quot;GOOG EQUITY&amp;quot;
   
    'defining the fields we want to retrieve
    ReDim aFieldList(0 To 1)
    aFieldList(0) = &amp;quot;NAME&amp;quot;
    aFieldList(1) = &amp;quot;PX_CLOSE&amp;quot;
   
        'initialize our bloomberg data object
        Set oBlp = New BlpData
       
        'we want a single subscription to bloomberg (will not fire events ongoing instead populates our result array)
        With oBlp
            .Timeout = 40000
            .SubscriptionMode = ByRequest
            .Subscribe aTickerList, 3, aFieldList, , , aResult
        End With
   
    Set oBlp = Nothing
    Set exampleRecordset = BBArrayToRecordset(aFieldList, aResult)
       
   
End Sub
&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://matthew.rathbone.googlepages.com/BloombergArrayToRecordset.bas"&gt;&lt;span style="font-size: medium;"&gt;Link to the actual code module&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/7xYnHvpnZag" height="1" width="1"/&gt;</description><a10:updated>2009-01-21T06:33:18-05:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20080805/converting-bloomberg-data-from-an-array-to-a-recordset-using-vba-in-excel.aspx</feedburner:origLink></item><item><guid isPermaLink="false">1</guid><link>http://feedproxy.google.com/~r/matthewrathbone/~3/zLwu9pZUwsg/site-launched.aspx</link><title>Site Launched</title><description>&lt;p&gt;It's sunday the 3rd August. MatthewRathbone.com is now live.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;It looks pretty sparse at the moment, that's because I'm going to add features and content as and when I get time.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The site has been made from scratch (blogging engine included), and has been deliberately overengineered as a way for me to practice my asp.net skills. It will continue to serve this purpose going forwads with new features chosen due to what I can learn through making them.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In terms of this blog, I plan to post useful tips &amp;amp; tricks on linux / VBA / ASP.net / C# etc based on things I found difficult to work out, or which I found little writing on.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I hope whoever reads this enjoys it, there's no commenting enabled for the blog posts yet, so if you need to let me know that I've said something incorrect, or that I'm just plain wrong about something please email me through the contact page.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Thanks all,&lt;/p&gt;
&lt;p&gt;Matthew Rathbone&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/matthewrathbone/~4/zLwu9pZUwsg" height="1" width="1"/&gt;</description><a10:updated>2008-08-03T15:05:36-04:00</a10:updated><feedburner:origLink>http://matthewrathbone.com/Blog/view/post/20080803/site-launched.aspx</feedburner:origLink></item></channel></rss>

