<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Gobán Saor &#187; SQLite</title>
	<atom:link href="http://blog.gobansaor.com/category/sqlite/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.gobansaor.com</link>
	<description>A country datasmith.</description>
	<lastBuildDate>Fri, 27 Jan 2012 10:22:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='blog.gobansaor.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://0.gravatar.com/blavatar/67e164f5d51c2b3115a7819b84505c13?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>Gobán Saor &#187; SQLite</title>
		<link>http://blog.gobansaor.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://blog.gobansaor.com/osd.xml" title="Gobán Saor" />
	<atom:link rel='hub' href='http://blog.gobansaor.com/?pushpress=hub'/>
		<item>
		<title>VBA Multithreading, .NET integration via HAMMER</title>
		<link>http://blog.gobansaor.com/2011/07/18/vba-multithreading-net-integration-via-hammer/</link>
		<comments>http://blog.gobansaor.com/2011/07/18/vba-multithreading-net-integration-via-hammer/#comments</comments>
		<pubDate>Mon, 18 Jul 2011 17:00:22 +0000</pubDate>
		<dc:creator>gobansaor</dc:creator>
				<category><![CDATA[excel]]></category>
		<category><![CDATA[HAMMER]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[VBA]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Threads]]></category>
		<category><![CDATA[VBA .NET integration]]></category>
		<category><![CDATA[VBA Multithreaded]]></category>

		<guid isPermaLink="false">http://blog.gobansaor.com/?p=1978</guid>
		<description><![CDATA[In a previous post I urged all potential datasmiths to learn a scripting language (I suggested Python). But what of VBA, the granddaddy of the scripting world? Well yes, if you have a need to automate Excel then you must learn &#8230; <a href="http://blog.gobansaor.com/2011/07/18/vba-multithreading-net-integration-via-hammer/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1978&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.gobansaor.com/2011/07/18/vba-multithreading-net-integration-via-hammer/vbaxl/" rel="attachment wp-att-1979"><img class="alignleft size-full wp-image-1979" title="vbaXL" src="http://gobansaor.files.wordpress.com/2011/07/vbaxl.png?w=500" alt=""   /></a>In a<a href="http://blog.gobansaor.com/2011/06/29/those-with-a-datasmiths-hammer-see-every-problem-as-a-table/"> previous post</a> I urged all potential datasmiths to learn a scripting language (I suggested Python). But what of VBA, the granddaddy of the scripting world? Well yes, if you have a need to automate Excel then you must learn VBA. VBA is to Excel as JavaScript is to the modern browser, its tight integration with Excel&#8217;s Object Model and its superb debugging facilities makes it the optimal choice for automating Excel.</p>
<p>VBA is now a one trick pony (Office automation), but Python opens all sorts of API scripting and product automation doors. My use of <a class="zem_slink" title="IronPython" href="http://ironpython.net/" rel="homepage">IronPython</a> as HAMMER&#8217;s scripting language is one such door, a door to the otherwise mainly-closed-to-VBA world of multi-threading and easy .NET library integration.</p>
<p>The HAMMER function can be called from VBA using the Application.Run command like so&#8230;</p>
<p><em>retArray = Application.Run(&#8220;DATASMITH.HAMMER&#8221;,inArray,&#8221;Select dept,count(*) from table1&#8243;,&#8221;SQL&#8221;)</em></p>
<p>&#8230; the 1st parameter is the function name, parameter two is the 1st argument to the function, parameter three is the 2nd and so on.</p>
<p>By utilising HAMMER&#8217;s IronPython functionality (requires NET 4.0 runtime), VBA routines can access the full power of the <a class="zem_slink" title=".NET Framework" href="http://msdn.microsoft.com/netframework" rel="homepage">.NET platform</a> with data passed back and forth using tables. Admittedly for many complex .NET utilities utilising VB.NET or C# may be a better approach (due to better IDE and debugging features of such languages) but for standard library calls, IronPython is an ideal option. It also has the benefit that the &#8220;code&#8221; can be stored within the workbook.</p>
<p>HAMMER also offers the power of multi-threading to VBA via its<a href="http://blog.gobansaor.com/2011/06/17/hammer-and-threads/"> internal threading functionality</a> (requires Excel &gt;= 2007 and Net4.0 runtime). The multi-threading example in the hammerThreads.xlsx workbook could easily be wrapped in VBA code, perhaps to allow it to be controlled by a user-form.</p>
<p>I&#8217;ve added two new commands specially designed for use within VBA scripted HAMMER scenarios:</p>
<ul>
<li>APPDB &#8211; Opens an application-wide shared in-memory database. This will allow tables (and Python objects) created in one function call to be accessible in an other function call (assuming both issue the APPDB command as their 1st command). This replicates the functionality of microETL which by default exposes a application-wide SQLite in-memory instance and a common Python workspace.</li>
<li>CLOSEAPPDB &#8211; This will close and clear the shared c#-SQLite and IronPython instances. Equivalent of microETL&#8217;s xLiteReset() function.</li>
</ul>
<p>Be careful not to&#8230;</p>
<ul>
<li>use the APPDB instance from in-cell UDF calls to HAMMER that are likely to be scheduled as multi-threaded (the helper functions HammerToSheet &amp; HammerToFit are safe, as they are always single-threaded),</li>
<li>or use within &#8220;internal threaded&#8221; HAMMER commands</li>
</ul>
<p><span class="Apple-style-span" style="color:#444444;font-family:Georgia, 'Bitstream Charter', serif;font-size:14px;line-height:23px;">&#8230;as although c#-SQLite is thread safe, the implementation logic is not.</span></p>
<p><a href="http://www.gobansaor.com/hammer">Here’s a list of the HAMMER commands implemented so far …</a></p>
<p><a href="http://bit.ly/datasmith">You can download the latest version of HAMMER here …</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gobansaor.wordpress.com/1978/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gobansaor.wordpress.com/1978/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/gobansaor.wordpress.com/1978/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/gobansaor.wordpress.com/1978/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/gobansaor.wordpress.com/1978/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/gobansaor.wordpress.com/1978/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/gobansaor.wordpress.com/1978/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/gobansaor.wordpress.com/1978/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/gobansaor.wordpress.com/1978/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/gobansaor.wordpress.com/1978/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/gobansaor.wordpress.com/1978/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/gobansaor.wordpress.com/1978/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/gobansaor.wordpress.com/1978/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/gobansaor.wordpress.com/1978/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1978&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.gobansaor.com/2011/07/18/vba-multithreading-net-integration-via-hammer/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<georss:point>53.204039 -6.574340</georss:point>
		<geo:lat>53.204039</geo:lat>
		<geo:long>-6.574340</geo:long>
		<media:content url="http://1.gravatar.com/avatar/b714f82b5e24beb3b74779615b6ad969?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">gobansaor</media:title>
		</media:content>

		<media:content url="http://gobansaor.files.wordpress.com/2011/07/vbaxl.png" medium="image">
			<media:title type="html">vbaXL</media:title>
		</media:content>
	</item>
		<item>
		<title>Those with  a datasmith&#8217;s hammer, see every problem as a table.</title>
		<link>http://blog.gobansaor.com/2011/06/29/those-with-a-datasmiths-hammer-see-every-problem-as-a-table/</link>
		<comments>http://blog.gobansaor.com/2011/06/29/those-with-a-datasmiths-hammer-see-every-problem-as-a-table/#comments</comments>
		<pubDate>Wed, 29 Jun 2011 15:50:54 +0000</pubDate>
		<dc:creator>gobansaor</dc:creator>
				<category><![CDATA[ETL]]></category>
		<category><![CDATA[excel]]></category>
		<category><![CDATA[HAMMER]]></category>
		<category><![CDATA[microETL]]></category>
		<category><![CDATA[PowerPivot]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[Extract transform load]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[sql engine in excel]]></category>

		<guid isPermaLink="false">http://blog.gobansaor.com/?p=1916</guid>
		<description><![CDATA[I picked the name HAMMER for my new micro ETL tool to capture the spirit of how it&#8217;s intended to be used. It&#8217;s an everyday tool, sufficient for many of the tasks a datasmith faces and when not, will help &#8230; <a href="http://blog.gobansaor.com/2011/06/29/those-with-a-datasmiths-hammer-see-every-problem-as-a-table/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1916&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.gobansaor.com/2011/06/29/those-with-a-datasmiths-hammer-see-every-problem-as-a-table/hamme_and_nail_clear/" rel="attachment wp-att-1922"><img class="alignleft size-full wp-image-1922" title="hammer and nail" src="http://gobansaor.files.wordpress.com/2011/06/hamme_and_nail_clear.png?w=500" alt=""   /></a>I picked the name HAMMER for my new micro ETL tool to capture the spirit of how it&#8217;s intended to be used. It&#8217;s an everyday tool, sufficient for many of the tasks a datasmith faces and when not, will help (or at least not get in the way of) with the marshalling of data that needs to be processed by more powerful tools.</p>
<p>The saying &#8220;If you only have a <em>hammer</em>, you tend to see <em>every problem</em> as a nail<em>&#8220; </em>could be rephrased as &#8221;If you only have a datasmith&#8217;s <em>HAMMER</em>, you tend to see <em>every problem</em> as a table<em>&#8220;!. </em>But that&#8217;s OK, as nearly every commercial IT problem can be expressed as a set of tables, and in any case, HAMMER is not intended to be a datasmith&#8217;s only tool. Its close integration with Excel, recognises the prime importance of spreadsheets to most data wranglers and its use of CSV &amp; the SQLite database format as its persistence &amp; transport mechanism, (<em>à la</em> <a href="http://blog.gobansaor.com/2009/03/14/sqlite-as-the-mp3-of-data/">&#8220;SQLite as the MP3 of data</a>&#8220;) recognises that datasets will often need to be shared with other tools.</p>
<p>Finding the perfect tool for the job it an IT obsession that most of our customer&#8217;s care little for; it&#8217;s only when our choice of tool affects their bottom-line (i.e excessive cost or wasted time) that end users take much notice of the backroom technology. The most important skill for a datasmith, is the ability to understand the structures and forms that data can take and to be able to derive and build business value from that data. The technology is an aid, nothing more, technology (and indeed  applications) will come and go, data lives on.</p>
<p>HAMMER encapsulates the  minimum set of technical skills an aspiring datasmith should learn:</p>
<ul>
<li>Spreadsheets, in particular Excel. No need to know every nook and cranny, nor expect it to handle every task. But do learn about pivot tables and array formulas; if you have Excel &gt;= 2007, learn about <a href="http://msdn.microsoft.com/en-us/library/bb693324(v=office.11).aspx">Excel  tables (aka Lists)</a>. If you have Excel 2010, make sure to download <a class="zem_slink" title="PowerPivot" href="http://www.powerpivot.com/" rel="homepage">PowerPivot</a>. Become comfortable with &#8220;formula programming&#8221;, don&#8217;t expect  a ribbon command to solve every problem.</li>
<li><a href="http://blog.gobansaor.com/2008/12/18/sql-does-exactly-what-it-says-on-the-tin/">SQL</a> &#8211; learn the basics of selecting, joining and group-by; again no need to become a master; SQLite is not only an excellent way to learn SQL, it&#8217;s also a powerful tool to have once you&#8217;ve picked up the basics.</li>
<li>Learn a scripting language &#8211;  Python is one of the best and is relatively easy to learn. Again, mastery is nice, but not essential, learn the basics of IF-THEN-ELSE logic, loops and iterations, array and list handling and string manipulation.  Your efforts at coding do not have to be pretty or elegant, just functional. Python skills will also transfer across platforms, <a class="zem_slink" title="CPython" href="http://www.python.org/" rel="homepage">CPython</a> (the original and the best), <a class="zem_slink" title="IronPython" href="http://ironpython.net/" rel="homepage">IronPython</a> (.NET and HAMMER) and Jython (JVM, <a href="http://sikuli.org/">here&#8217;s an cool example of Python as a scripting language to automate GUIs</a>).</li>
</ul>
<p>All this talk of picking the right tools brings to mind the old golf pro-am story where the amateur was constantly pointing out to the pro (Jack Nicklaus I think) what club to play. At a particularly tricky shot to the green, the pro had enough when his choice of club was again “criticised”. So, he proceeded to take out every club including woods &amp; putters, placed a ball for each one and hit every ball on to the green.</p>
<p>We&#8217;re not all as talented as Jack Nicklaus, so having at least an <em>good enough</em> tool for the job at hand  is important. But it does show, that focusing on the end-game is what matters, not becoming fixated with a  particular way of doing things.</p>
<p>Enough of the moralising, and talking of being fixated on a particular tool  ;) here&#8217;s this week&#8217;s list of new features to be found in HAMMER:</p>
<h5>New commands:</h5>
<p>TXT &#8211; will load a text file such that each line is a new row in a single columned (column named &#8220;text&#8221;) table.</p>
<p>LOADDB &#8211; like OPENDB, opens the named database but only if the database file exists (OPENDB will create a new empty database if file not found). Intended primarily as end-point to request-process-response loop, see DELEGATE/SUBMIT  below.</p>
<p>SAVEDB &#8211; saves the current &#8220;main&#8221; database using the previous argument as it&#8217;s name. (shorthand for &#8230; &#8220;main&#8221;,&#8221;filename.db&#8221;,&#8221;SAVENAMEDDB&#8221;).</p>
<p>SUBMIT &#8211; same as SAVEDB, but the value of the prior argument has a &#8220;.request&#8221; appended to make a file name in the format &#8220;databasename.request&#8221; for saving to. Also, if the previous argument = &#8220;&#8221; or &#8220;{GUID}&#8221; will generated a globally unique name using  a GUID. The main use-case for this command is to send the saved database for processing by an external program, maybe a Talend or Keetle ETL job , or a HAMMER.EXE job.</p>
<p>DELEGATE &#8211; same a SUBMIT, but doesn&#8217;t do any processing (i.e. all commands other than DELEGATE, which is expected to be the last command, are ignored), instead it&#8217;ll package the request in the saved database with the expectation that an external HAMMER.EXE, or another Excel-based HAMMER call, with do the processing.</p>
<h5>Changes and helper functions to support DELEGATE/SUBMIT processing:</h5>
<p>The DELEGATE and SUBMIT commands are how HAMMER implements its version of <a href="http://blog.gobansaor.com/2011/03/16/steam-powered-powerpivot/">steam-powered servers</a>.</p>
<p>The intention is that databases named with extensions of &#8220;.request&#8221; are picked up and processed by &#8220;servers&#8221; waiting for such files. (The transport of such files between server and the served is a separate issue, might be simply a matter of placing files on a shared drives, or <a href="http://www.dropbox.com/">DropBox</a>!) Theses servers may then populate that database with new data ( or not, e.g. might generate a CSV). When finished, a text file of the same name but with the &#8220;.request&#8221; replaced by a &#8220;.response&#8221; is written to indicate that processing is complete.</p>
<p>Both the Excel udf HAMMER and HAMMER.EXE (non-excel command line version of UDF function), have been changed such that when a single argument is passed, that argument is expected to be a DELEGATE generated &#8220;.request&#8221; database. The database&#8217;s &#8220;pickled&#8221; arguments and data will then unpacked and the &#8220;delegated request&#8221; processed.</p>
<p>HAMMER.exe, if started with no arguments, implements a simple DELEGATE &#8220;server&#8221;, i.e. will wait for &#8220;.requests&#8221; files in its default folder and process each file as above.</p>
<h5>Three<a href="http://support.microsoft.com/kb/289150"> RTD helper functions</a> have been added to HAMMER udf:</h5>
<p><em>waitOnHammerResponse(database (without the .response),[folder name])</em> &#8211; will return &#8220;Waiting&#8221; until it finds a database.response file, will then return the original .request filename (i.e. not the response file as it&#8217;s simply a marker, the database.request will  contain original data and any new data generated).</p>
<p><em>waitOnHammerRequest(database (without the .request),[folder name])</em> &#8211; will return &#8220;Waiting&#8221; until it finds a database.request file, will then then return the request filename.</p>
<p><em>waitOnFile(filenaname,[folder name])</em> &#8211; like the functions above but without the response/request expectations.</p>
<p><a href="http://www.gobansaor.com/hammer">Here&#8217;s a list of the HAMMER commands implemented so far &#8230;</a></p>
<p><a href="http://bit.ly/datasmith">Get the latest version of HAMMER here &#8230;</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gobansaor.wordpress.com/1916/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gobansaor.wordpress.com/1916/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/gobansaor.wordpress.com/1916/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/gobansaor.wordpress.com/1916/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/gobansaor.wordpress.com/1916/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/gobansaor.wordpress.com/1916/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/gobansaor.wordpress.com/1916/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/gobansaor.wordpress.com/1916/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/gobansaor.wordpress.com/1916/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/gobansaor.wordpress.com/1916/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/gobansaor.wordpress.com/1916/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/gobansaor.wordpress.com/1916/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/gobansaor.wordpress.com/1916/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/gobansaor.wordpress.com/1916/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1916&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.gobansaor.com/2011/06/29/those-with-a-datasmiths-hammer-see-every-problem-as-a-table/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<georss:point>53.204039 -6.574340</georss:point>
		<geo:lat>53.204039</geo:lat>
		<geo:long>-6.574340</geo:long>
		<media:content url="http://1.gravatar.com/avatar/b714f82b5e24beb3b74779615b6ad969?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">gobansaor</media:title>
		</media:content>

		<media:content url="http://gobansaor.files.wordpress.com/2011/06/hamme_and_nail_clear.png" medium="image">
			<media:title type="html">hammer and nail</media:title>
		</media:content>
	</item>
		<item>
		<title>Using PowerPivot to Hammer home some facts</title>
		<link>http://blog.gobansaor.com/2011/06/24/using-powerpivot-to-hammer-home-some-facts/</link>
		<comments>http://blog.gobansaor.com/2011/06/24/using-powerpivot-to-hammer-home-some-facts/#comments</comments>
		<pubDate>Fri, 24 Jun 2011 17:47:41 +0000</pubDate>
		<dc:creator>gobansaor</dc:creator>
				<category><![CDATA[ETL]]></category>
		<category><![CDATA[excel]]></category>
		<category><![CDATA[HAMMER]]></category>
		<category><![CDATA[microETL]]></category>
		<category><![CDATA[PowerPivot]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[SQLite]]></category>

		<guid isPermaLink="false">http://blog.gobansaor.com/?p=1893</guid>
		<description><![CDATA[From my previous post&#8217;s example of a Hammer use-case, it&#8217;s obvious I primarily see Hammer (and indeed microETL) as a tool for shaping dimensional type data; i.e. relatively low volume, often very &#8216;dirty&#8217;, but very high (business) value. Fact (aka &#8230; <a href="http://blog.gobansaor.com/2011/06/24/using-powerpivot-to-hammer-home-some-facts/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1893&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.gobansaor.com/2011/06/24/using-powerpivot-to-hammer-home-some-facts/hammer-and-chisel-c/" rel="attachment wp-att-1905"><img class="alignleft size-full wp-image-1905" title="hammer-and-chisel-c" src="http://gobansaor.files.wordpress.com/2011/06/hammer-and-chisel-c.png?w=500" alt=""   /></a>From <a href="http://blog.gobansaor.com/2011/06/21/hammer-a-new-excel-etl-tool-for-the-powerpivot-age/">my previous post&#8217;s example of a Hammer use-case</a>, it&#8217;s obvious I primarily see Hammer (and indeed microETL) as a tool for shaping dimensional type data; i.e. relatively low volume, often very &#8216;dirty&#8217;, but very high (business) value.</p>
<p>Fact (aka transactional data) can of course be handled, particularly when already reduced or when by-nature low volume, such facts will in many cases fit easily in-memory.</p>
<p>But when facts start to run into the millions of records, traditional in-memory manipulation becomes a problem. Obviously such large volumes datasets should in the first instance be handled IT-side utilising tools that are designed to handle such volumes, i.e. enterprise-class databases. But sometimes data, even large transactional databases, are &#8220;thrown-over-the-wall&#8221; with limited support offered (or accepted). But again, there&#8217;s plenty of cut-down versions of enterprise RDBMS available (SQL Express, Oracle Express etc.) plus the FOSS offerings such as MySQL or PostgresSQL, that can be configured user-side to help tame these beasts.</p>
<p>If you&#8217;re using PowerPivot, you have another option, PowerPivot itself. With its ability to quickly load and compress large volumes of data and its ability to perform many data cleansing tasks by means of row-context DAX formulas, often that&#8217;s all that will be required.</p>
<p>The typical problems that a transactional dataset can throw up, such as data split over two tables (header and detail) or needing to replace a surrogate date key with an actual date (to <a href="http://mdxdax.blogspot.com/2011/01/dax-time-intelligence-functions.html">enable certain DAX date functionality to work</a>) can easily be fixed within PowerPivot.</p>
<p>One thing to note about fact data presented as a Header-Detail set, is that traditional star-schema design requires that such data be flattened to the lower &#8220;grain&#8221; of the detail line, but PowerPivot doesn&#8217;t actually require you to do that. Some dimensions can link to the header (example Customer on Invoice Header) and others to the line (example Product on Invoice Line). The detail line table is still the &#8220;hub&#8221; of the &#8220;star&#8221; but one of its dimensions (the header table) is its route to a multiple other dimensions. Not classic star schema design, but it&#8217;ll work , and good for quick and dirty analysis (might be situations though where things might not pan-out as expected <a href="http://mdxdax.blogspot.com/2011/03/logic-behind-magic-of-dax-cross-table.html">see this</a>, perhaps best stick with pure star-schemas for complex work).</p>
<p>There&#8217;ll come a time however, when you&#8217;ll be faced with the problem of manipulating large datasets outside of traditional  RDBMS servers and outside of PowerPivot. Combining sets of data from multiple sources, as in my previous post, would be a prime example. Such projects often operate on a &#8220;need-to-know-basis&#8221; often with those supplying the data &#8216;outside the loop&#8217;. Today&#8217;s additions to HAMMER should help.</p>
<p>Three new commands, ATTACHDB, ATTACHDBINMEMORY and SAVENAMEDB, will allow external disk-based databases to be attached to the default HAMMER database.</p>
<p>ATTACHDB requires a filename  followed by an alias name for the attached db. Having an attached external database would allow, for example, a large fact table in CSV format to be loaded (and indexed) without touching memory. This could also be done using the previously introduced OPENDB command, but the benefit of ATTACHDB is that other non-memory-threatening processing can continue to take place in-memory.</p>
<p>The ATTACHDBINMEMORY also attaches an external database, but this time loads it into memory, so any changes made will not be automatically persisted back to disk. To do that, use the SAVENAMEDDB command.</p>
<p>This requires an attached database alias, followed by the file name to save the database to. SAVEASNAMEDB has other uses such as making backups or making copies of data for use in an external debugging platform (it can be much easier to debug Python using a proper IDE).</p>
<p>Along side the facility to load data via CSV/TSV, I&#8217;ve also added an ADO command. This requires a valid ADO connection string, followed by either a table/view name or a SQL Select statement. <del>It uses ADODB 2.7, to enable handling of modern Access file formats, I&#8217;ll eventually make an ADO.NET version to remove this dependency.</del></p>
<p>Finally, I&#8217;ve managed to get a DBAPI compliant SQLite provider working in the PYTHON step. The provider is called XLite (it&#8217;s a modified version of J<a href="https://bitbucket.org/jdhardy/ironpython.sqlite/wiki/Home">eff Hardy&#8217;s SQLite3 library</a>) and exposes most of the same functionality as<a href="http://docs.python.org/library/sqlite3.html"> CPython&#8217;s SQlite3 provider</a>.</p>
<p>The library can open external SQLite databases, so offering another means of accessing non in-memory data and accesses the HAMMER default databases via the pre-connected pyDB variable. Having the ability to lazy-load rows via a cursor loop is also very useful in reducing memory foot-print when dealing with large tables. (see the IrelandFOIExample_hammer_test2.xlsx for an example of using XLite).</p>
<p>Update:</p>
<p>I&#8217;ve removed the dependency on a specific ADODB library (figured out how do equivalent of CreateObject in .NET for COM libraries). Also included is a first pass at a command line version (hammer.exe). Example:</p>
<p>hammer.exe mydata.csv CSV myotherdata.csv CSV JOIN &gt; new.csv</p>
<p>hammer.exe inv.csv &#8220;CSV&#8221; &#8220;sum(qty)&#8221; REDUCE sum.csv TOCSV</p>
<p><a href="http://www.gobansaor.com/hammer">Here’s a list of the HAMMER commands implemented so far …</a></p>
<p><a href="http://bit.ly/datasmith">Download  the latest version of HAMMER from here &#8230;</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gobansaor.wordpress.com/1893/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gobansaor.wordpress.com/1893/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/gobansaor.wordpress.com/1893/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/gobansaor.wordpress.com/1893/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/gobansaor.wordpress.com/1893/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/gobansaor.wordpress.com/1893/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/gobansaor.wordpress.com/1893/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/gobansaor.wordpress.com/1893/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/gobansaor.wordpress.com/1893/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/gobansaor.wordpress.com/1893/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/gobansaor.wordpress.com/1893/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/gobansaor.wordpress.com/1893/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/gobansaor.wordpress.com/1893/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/gobansaor.wordpress.com/1893/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1893&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.gobansaor.com/2011/06/24/using-powerpivot-to-hammer-home-some-facts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<georss:point>53.204039 -6.574340</georss:point>
		<geo:lat>53.204039</geo:lat>
		<geo:long>-6.574340</geo:long>
		<media:content url="http://1.gravatar.com/avatar/b714f82b5e24beb3b74779615b6ad969?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">gobansaor</media:title>
		</media:content>

		<media:content url="http://gobansaor.files.wordpress.com/2011/06/hammer-and-chisel-c.png" medium="image">
			<media:title type="html">hammer-and-chisel-c</media:title>
		</media:content>
	</item>
		<item>
		<title>HAMMER a new Excel ETL tool for the PowerPivot age &#8230;</title>
		<link>http://blog.gobansaor.com/2011/06/21/hammer-a-new-excel-etl-tool-for-the-powerpivot-age/</link>
		<comments>http://blog.gobansaor.com/2011/06/21/hammer-a-new-excel-etl-tool-for-the-powerpivot-age/#comments</comments>
		<pubDate>Tue, 21 Jun 2011 16:38:18 +0000</pubDate>
		<dc:creator>gobansaor</dc:creator>
				<category><![CDATA[BI]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[ETL]]></category>
		<category><![CDATA[HAMMER]]></category>
		<category><![CDATA[microETL]]></category>
		<category><![CDATA[PowerPivot]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[c#-SQLite]]></category>
		<category><![CDATA[Data Quality]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Master Data]]></category>
		<category><![CDATA[MDM]]></category>

		<guid isPermaLink="false">http://blog.gobansaor.com/?p=1860</guid>
		<description><![CDATA[So, why am I developing this new datasmithing tool when I already have microETL to do the same task? To be honest, when I started, my aim was to simply port  a lot of my useful framework code to .NET &#8230; <a href="http://blog.gobansaor.com/2011/06/21/hammer-a-new-excel-etl-tool-for-the-powerpivot-age/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1860&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.gobansaor.com/2011/06/21/hammer-a-new-excel-etl-tool-for-the-powerpivot-age/age_of_aquarius/" rel="attachment wp-att-1864"><img class="alignleft size-medium wp-image-1864" title="age_of_aquarius" src="http://gobansaor.files.wordpress.com/2011/06/age_of_aquarius.jpg?w=239&#038;h=300" alt="" width="239" height="300" /></a>So, why am I developing this new datasmithing tool when I already have<a href="http://www.gobansaor.com/microetl"> microETL</a> to do the same task?</p>
<p>To be honest, when I started, my aim was to simply port  a lot of my useful framework code to .NET as I&#8217;m doing more and more work in pure .NET these days.</p>
<p>It&#8217;s a lot easier to do so with a project driving the work rather than the drudgery of line by line conversions simply for the sake of conversion.</p>
<p>But over the last few months of investigating the process of moving some of more useful code over to .NET; discovering<a href="http://code.google.com/p/csharp-sqlite/"> C#-SQLite</a> as a near drop-in replacement for SQLite; realising that IronPython 2.7 marks the coming-of-age of Python under .NET; discovering the ease of multi-threading programming under Net 4.o; I began to see the potential of building a tool more suited to this new emerging world of technological plenty; of 64bit, multi-core high-RAM machines playing host to ground-breaking tools such as PowerPivot, than the 32bit, single-threaded  world that microETL was born into.</p>
<p>I wanted to bring microETL back to its roots as an in-cell function. To make it sit more easily with the spreadsheet functional style of programming, a style of programming that has been more successful at attracting &#8220;civilians&#8221; to programming that any other method. To make the tool more in tune with the Excel-way of doing things.</p>
<p>At the same time, I also wanted the tool to be &#8220;detachable&#8221; from Excel, so that it could perform ETL functions server-side without the need for Excel. Ideally capable of being run from the command-line from a single no-install-required executable.</p>
<p>And so, <a href="http://blog.gobansaor.com/2011/06/10/the-datasmiths-hammer/">the Datasmith&#8217;s HAMMER was born</a>.</p>
<p>So where does this fit in with PowerPivot? When I design something like HAMMER I normally craft it around a serious of <a href="http://en.wikipedia.org/wiki/Use_case">&#8220;use cases&#8221;</a>. Below would be a one of my PowerPivot &amp; HAMMER  use cases:</p>
<h4>The Data Quality Team</h4>
<p>The sales &amp; marketing department of a wholesaling company have discovered PowerPivot and are excited about using it to help manage an upcoming merger with a recently purchased competitor, also in the wholesaling business. There&#8217;s a large overlap between customers and products supplied, and the sales structures, pricing and KPIs used by both companies are very different. The transition phase from two separate companies to a single operating unit will need detailed  planning and constant monitoring.  Oh, and there&#8217;s also the problem of the brand new ERP system that&#8217;ll replace the existing systems currently in use.</p>
<p>The group can see how PowerPivot models will help with this task but are worried about the sourcing and managing the data. They decide to appoint a small data quality team, with a mixture of IT and business experience; which will be responsible for mapping old  to old,old to new, managing the data deltas (business will still goes on, new customers, new products etc.).</p>
<p>Most of this work revolves around &#8220;master data&#8221;. Transactional data may be much larger in volume, but get the master data right then transactional data will be easy to handle as long as the processing capacity to handle the volumes is available (which thanks to PowerPivot and really fast high-RAM PCs it is).</p>
<p>In golf, there&#8217;s a saying &#8220;You drive for show, but you putt for dough&#8221;. Likewise in data: a lot of emphasis is put on the big-data transactional datastores, but real analytical benefit comes from the less sexier master-data, aka the dimensions. As a result the most important output from the data quality team will be a set of <a href="http://smdbi.blogspot.com/2009/05/what-is-conformed-dimension.html">conformed dimensions</a>.</p>
<p>Each week (and at month-end) the team will get extracts of the master and transactional data in various formats from both legacy systems and will also get the WIP master datasets from the team working on the new ERP system. From these they&#8217;ll construct point-in-time conformed-dimensions combined old with old and old with new; and will rebuild transactional feeds with new conformed keys alongside existing keys. These datatsets are then sent to the various analysis teams to enable them build Excel and PowerPivot models that will hopefully all &#8220;sing from the same hymn sheet&#8221;.</p>
<p>And how will this be accomplished? With the datasmith&#8217;s HAMMER of course (well it is my <del>day-dream</del> use-case!).  Both in-Excel and command-line HAMMER &#8220;scripts&#8221; will be used to wrangle the datasets and the complete sets packaged as SQLite database files.</p>
<p>When the analysis groups receive these files, they too will use HAMMER to extract the datasets they require (either straight to CSV for loading into PowerPivot) or into Excel for some further transformation work prior to modelling. To handle <a href="http://blog.gobansaor.com/2011/01/08/slowly-changing-dimensions-time-to-stop-worrying/">slowing-changing dimension scenarios</a>, many of the teams will squirrel away each week&#8217;s data in other to be able to model yet-unknown-but-very-likely changes of organisational structures.</p>
<p>Although this is a use-case, it&#8217;s based on reality, a reality that would have been so much easier to manage if I, and the teams I worked with, had access to technology such as HAMMER and PowerPivot.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gobansaor.wordpress.com/1860/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gobansaor.wordpress.com/1860/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/gobansaor.wordpress.com/1860/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/gobansaor.wordpress.com/1860/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/gobansaor.wordpress.com/1860/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/gobansaor.wordpress.com/1860/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/gobansaor.wordpress.com/1860/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/gobansaor.wordpress.com/1860/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/gobansaor.wordpress.com/1860/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/gobansaor.wordpress.com/1860/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/gobansaor.wordpress.com/1860/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/gobansaor.wordpress.com/1860/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/gobansaor.wordpress.com/1860/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/gobansaor.wordpress.com/1860/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1860&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.gobansaor.com/2011/06/21/hammer-a-new-excel-etl-tool-for-the-powerpivot-age/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<georss:point>53.204039 -6.574340</georss:point>
		<geo:lat>53.204039</geo:lat>
		<geo:long>-6.574340</geo:long>
		<media:content url="http://1.gravatar.com/avatar/b714f82b5e24beb3b74779615b6ad969?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">gobansaor</media:title>
		</media:content>

		<media:content url="http://gobansaor.files.wordpress.com/2011/06/age_of_aquarius.jpg?w=239" medium="image">
			<media:title type="html">age_of_aquarius</media:title>
		</media:content>
	</item>
		<item>
		<title>SQL noSQL no Python no VBA.</title>
		<link>http://blog.gobansaor.com/2011/06/20/sql-nosql-no-python-no-vba/</link>
		<comments>http://blog.gobansaor.com/2011/06/20/sql-nosql-no-python-no-vba/#comments</comments>
		<pubDate>Mon, 20 Jun 2011 19:13:23 +0000</pubDate>
		<dc:creator>gobansaor</dc:creator>
				<category><![CDATA[ETL]]></category>
		<category><![CDATA[HAMMER]]></category>
		<category><![CDATA[microETL]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[VBA]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[noVBA]]></category>
		<category><![CDATA[SQLite Excel]]></category>

		<guid isPermaLink="false">http://blog.gobansaor.com/?p=1848</guid>
		<description><![CDATA[I&#8217;ve uploaded another version of HAMMER; this adds some new features and also takes some away. The removed features are Python and multi-threading support from the 2003 version of the add-in. Calling it the 2003 version isn&#8217;t entirely accurate (it&#8217;s actually called &#8230; <a href="http://blog.gobansaor.com/2011/06/20/sql-nosql-no-python-no-vba/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1848&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.gobansaor.com/2011/06/20/sql-nosql-no-python-no-vba/thor-clear/" rel="attachment wp-att-1850"><img class="alignleft size-full wp-image-1850" title="Thor-clear" src="http://gobansaor.files.wordpress.com/2011/06/thor-clear.png?w=500" alt=""   /></a>I&#8217;ve uploaded another version of HAMMER; this adds some new features and also takes some away. The removed features are Python and multi-threading support from the 2003 version of the add-in. Calling it the 2003 version isn&#8217;t entirely accurate (it&#8217;s actually called datasmith-noPython.xll) as this version will also work for Excel 2007/2010 32bit and for older versions (maybe even &#8217;97!). It should really be called the .NET 2.0 version as the features removed from this version depend on the NET 4.0 runtime (IronPython 2.7 and multi-threading). I&#8217;ll eventually build a .NET4 version for Excel 97-2003 with Python included, but this will still be missing the multi-threading features.</p>
<p>So, the version that the setup.xls will install if it detects a sub-2007 version of Excel, will offer<strong> SQL</strong> and <strong>noSQL</strong> (JOIN,UNION etc.) but <strong>no Python</strong> or <strong>multi-threading</strong>.</p>
<p>So what about new features? <a href="http://blog.gobansaor.com/2010/03/02/excel-as-a-document-oriented-nosql-database/">Excel being the original noSQL  database</a>, I continue to add more noSQL commands for those who wish to avoid SQL or find its syntax somewhat long-winded. The JOIN  &amp; LOJOIN (outer join) commands are good examples, simply load two tables with the column names that you wish to join on, sharing the same names, simple.  Another example is the REDUCE (aka GROUPBY aka DISTINCT) command I&#8217;ve added this version. It essentially performs a SELECT &#8230; FROM &#8230; GROUP BY; again load or generate a table, then follow with a list of the columns you wish to &#8216;reduce&#8217; the table by, plus any aggregates you wish to perform. Examples:</p>
<ul>
<li>=HAMMER(myHugeList,&#8221;dept,sum(overtime)&#8221;,&#8221;REDUCE&#8221;)</li>
<li>=HAMMER(AccessLogs!A1:C9999,&#8221;areaAccessed,byWhom&#8221;,&#8221;REDUCE&#8221;)</li>
<li>=HAMMER(invHead,invLine,&#8221;JOIN&#8221;,&#8221;count(invID),sum(netAmt)&#8221;,&#8221;REDUCE&#8221;)</li>
</ul>
<p><span class="Apple-style-span" style="font-size:14px;line-height:23px;">If noSQL is not your cup of tea and you wish to utilise the full power of a SQL database; a new command &#8220;OPENDB&#8221; will allow you to open an existing (or create a new) SQLite database file. This will allow SQLite data sources to be accessed and written to via standard in-cell formula, no VBA required! The command expects the previous argument to be the database name. If no such argument exists it will create a temporary on-disk database. This command usually only makes sense as the 1st command as it&#8217;ll close and wipe any previously opened databases. If no &#8220;OPENDB&#8221; command is issued (i.e. the default) an in-memory database (aka :memory:)  is used . Examples:</span></p>
<ul>
<li>=HAMMER(&#8220;C:\data\myDB.db&#8221;,&#8221;OPENDB&#8221;,A10:C:9910) will copy the data for range A10:C9910 and save in a table called table3 in the myDB.db SSQLite database.</li>
<li>=HAMMER(&#8220;C:\data\myDB.db&#8221;,&#8221;OPENDB&#8221;,&#8221;SELECT * from table3&#8243;) will fetch the same data back into Excel.</li>
</ul>
<p><span class="Apple-style-span" style="font-size:14px;line-height:23px;">Wow steady on, what if there&#8217;s a need to store or fetch data from disk without using SQLite? No problem, use the &#8220;TOCSV&#8221; command, outputs the last table loaded or generated in CSV format to the file name specified. (There&#8217;s also a &#8220;SQLTOCVS&#8221; command which expects a SQL statement to specify the data to extract followed by the file name to extract to).</span></p>
<p><span class="Apple-style-span" style="font-size:14px;line-height:23px;">Two other commands &#8220;CSV&#8221; and &#8220;TSV&#8221; will load comma and tab separated data into HAMMER.  Although the CSV functionality is useful within Excel, the main driver for these command is to enable HAMMER to work outside Excel as a command-line data processor; you heard it here first folks! </span></p>
<p><span class="Apple-style-span" style="font-size:14px;line-height:23px;">I&#8217;ve also added the 1st set of my helper functions, these two functions are only available in the 2007/2010 versions as they use multi-threading. The two functions are:</span></p>
<ul>
<li>hammerToFit &#8211; wraps HAMMER, but will auto-resize the array area (or create a brand new array-selection if none) to fit the returned table. Note: to achieve this, the HAMMER function will be called twice if the existing array area needs adjusting.</li>
<li>hammerToSheet &#8211; again wraps HAMMER, but will paste the resulting table to a new sheet.</li>
</ul>
<p><span class="Apple-style-span" style="font-size:14px;line-height:23px;">Although both helper functions utilise threads to achieve these little tricks (hence they&#8217;re not available sub-2007) when HAMMER functionality is called via these wrappers the function operates as a single threaded function &#8211; there&#8217;s a good reason for this which I&#8217;ll explain some other time.<a href="http://blog.gobansaor.com/2011/06/17/hammer-and-threads/"> Internal HAMMER threading</a> does however still work.</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><a href="http://www.gobansaor.com/hammer">Here’s a list of the HAMMER commands implemented so far …</a></p>
<p><a href="http://bit.ly/datasmith">Download the latest version of HAMMER here &#8230;</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gobansaor.wordpress.com/1848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gobansaor.wordpress.com/1848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/gobansaor.wordpress.com/1848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/gobansaor.wordpress.com/1848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/gobansaor.wordpress.com/1848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/gobansaor.wordpress.com/1848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/gobansaor.wordpress.com/1848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/gobansaor.wordpress.com/1848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/gobansaor.wordpress.com/1848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/gobansaor.wordpress.com/1848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/gobansaor.wordpress.com/1848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/gobansaor.wordpress.com/1848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/gobansaor.wordpress.com/1848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/gobansaor.wordpress.com/1848/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1848&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.gobansaor.com/2011/06/20/sql-nosql-no-python-no-vba/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<georss:point>53.204039 -6.574340</georss:point>
		<geo:lat>53.204039</geo:lat>
		<geo:long>-6.574340</geo:long>
		<media:content url="http://1.gravatar.com/avatar/b714f82b5e24beb3b74779615b6ad969?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">gobansaor</media:title>
		</media:content>

		<media:content url="http://gobansaor.files.wordpress.com/2011/06/thor-clear.png" medium="image">
			<media:title type="html">Thor-clear</media:title>
		</media:content>
	</item>
		<item>
		<title>The Datasmith&#8217;s Hammer</title>
		<link>http://blog.gobansaor.com/2011/06/10/the-datasmiths-hammer/</link>
		<comments>http://blog.gobansaor.com/2011/06/10/the-datasmiths-hammer/#comments</comments>
		<pubDate>Fri, 10 Jun 2011 17:47:38 +0000</pubDate>
		<dc:creator>gobansaor</dc:creator>
				<category><![CDATA[ETL]]></category>
		<category><![CDATA[excel]]></category>
		<category><![CDATA[HAMMER]]></category>
		<category><![CDATA[microETL]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[VBA]]></category>
		<category><![CDATA[Excel MapReduce]]></category>
		<category><![CDATA[IronPython Excel]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.gobansaor.com/?p=1782</guid>
		<description><![CDATA[Although my microETL add-in is very powerful, it can be a bit intimidating for those without a programming background. It was after all, designed for my needs primarily and being a professional programmer I tend to see the world from that perspective. &#8230; <a href="http://blog.gobansaor.com/2011/06/10/the-datasmiths-hammer/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1782&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.gobansaor.com/2011/06/10/the-datasmiths-hammer/datasmithhammer/" rel="attachment wp-att-1788"><img class="alignleft size-full wp-image-1788" title="datasmithhammer" src="http://gobansaor.files.wordpress.com/2011/06/datasmithhammer.png?w=500" alt=""   /></a>Although my <a href="http://www.gobansaor.com/microetl">microETL</a> add-in is very powerful, it can be a bit intimidating for those without a programming background. It was after all, designed for my needs primarily and being a professional programmer I tend to see the world from that perspective. Hence microETL&#8217;s ability to forge vast and complex datasets in parallel to those of Excel; to share those datasets not just with Excel and VBA but also with the powerful tool that is <a class="zem_slink" title="CPython" href="http://en.wikipedia.org/wiki/CPython" rel="wikipedia">CPython</a>. But microETLs genesis was not as an all-powerful ETL tool but as means to quickly and accurately handle tabular data in Excel. The original xLite (which begat microETL) started out with just two functions, Join two tables or Left Outer Join two tables. That was it, but it was still useful.</p>
<p>I&#8217;ve been intending for some time to build an offshoot of microETL that would be less powerful but perhaps more approachable and have fewer moving parts. This week I finished it, still needs some more testing, but the basic product is in place. It&#8217;s a single file add-in (a .xll) , called DATASMITH. At its heart is a single function called HAMMER, there will be other helper functions that in the main will wrap the HAMMER function, but in essence it is the datasmith&#8217;s HAMMER.</p>
<p>If microETL is a datasmith&#8217;s forge or indeed a mirco-foundry,HAMMER is a datasmith&#8217;s everyday portable tool (with perhaps Excel as the anvil, and your CPUs as the fire?). Talking of CPUs; multi-core CPUs are now the norm and since version 2007, Excel can utilise such multi-cores. MicroETL being VBA-based cannot however take advantage of this, to do so requires an .xll add-in; another reason to build the HAMMER.</p>
<p>So what will this new functionality look like:</p>
<h4>Examples:</h4>
<p>=<strong>HAMMER(Invoices[#All],InvoiceLine[#All],&#8221;JOIN&#8221;)</strong></p>
<p>&#8230;will take the two ranges (you need the [#All] to pick-up the header and data sections of a 2007/2010 Excel Table) and join them using the columns with the same name as the join fields. The JOIN command expects the last two preceding arguments to be tables (aka arrays with a header line).</p>
<p>=<strong>HAMMER(&#8220;SALES&#8221;,DeptSales!A1:F2101,&#8221;SELECT * from table2 where dept=&#8217;:1&#8242;&#8221;,&#8221;SQL&#8221;)</strong></p>
<p>&#8230; the 1st argument is loaded as Arg(1) (:1 in SQL), the 2nd argument is loaded (being an array) into a table named<em> table2</em>; if they were the other way round, it would be<em> table1</em> and Arg(2). The 3rd argument is loaded as Arg(3) and the 4th is a command: SQL. SQL looks back at the preceding argument (Arg(3) in this case) and executes its contents as SQLite SQL. If the preceding argument was a table, it would expect to find a list of SQL statements for execution in the first column. The output of the last issued SELECT statement is then returned to Excel as an array.</p>
<p>=<strong>HAMMER(DeptTargets!A1:D20,DeptSales!A1:F2101,SalesTagetScript,&#8221;PYTHON&#8221;)</strong></p>
<p>&#8230;this is similar to the previous SQL example but this time the command is PYTHON which will execute the Python Script passed in via the command&#8217;s preceding argument. The script will most likely return a table to Excel, but it could also, if not the last argument, create a table associated with its position, in this case <em>table4</em>, which could then be accessed by subsequent PYTHON or SQL scripts.</p>
<p>Up to 25 arguments can be passed, the last table produced is returned to Excel (either via a load, which wouldn&#8217;t be terribly useful, or more likely as a result of a command such as JOIN, SQL or PYTHON). HAMMER functions can of course be nested and can also issue <a href="http://blog.gobansaor.com/2011/06/17/hammer-and-threads/">&#8220;internal&#8221; HAMMER requests</a>. The &#8220;flow&#8221; of commands is from left to right, with the preceding args usually setting the stage for subsequent commands. Alongside the all-powerful SQL and PYTHON commands, I&#8217;ll most likely add a set of &#8220;noSQL&#8221; offerings such as JOIN, LOJOIN (left-outer), DISTINCT, REDUCE (a SELECT .. GROUP BY&#8230; with PYTHON as the MAP?), UNION, INTERSECT. These will likely also be available through helper functions such as =JOIN(ThisTable,ThatTable).</p>
<p>Unlike microETL, there&#8217;s no persistence across function calls i.e. HAMMER will play by Excel&#8217;s Functions <strong><em>no-side-effects</em></strong> rule. Each call to a function will build up and tear down its in-memory SQLite environment (including calls to HAMMER from within PYTHON).(UPDATE: Specify the 1st COMMAND as &#8220;APPDB&#8221; to simulate microETL&#8217;s persistence across function calls) <del> Likewise each call to PYTHON will be a separate engine instance</del>. Likewise each call to a HAMMER function will create its own PYTHON engine. Tables  and Python artefacts created by prior &#8220;steps&#8221; in a single HAMMER call are available to subsequent steps.</p>
<p>HAMMER embeds Python under the guise of <a class="zem_slink" title="IronPython" href="http://ironpython.net/" rel="homepage">IronPython</a>, so a lot of the power and speed of CPython will not be available, but on the other hand, the full power of the .NET CLR will be, not a bad swap.</p>
<p>And a huge advantage, HAMMER will be an asynchronous function (i.e. will run in its own thread). This will allow multiple long running transforms to be handled within the same Excel instance, a major shortcoming of microETL. This requires Excel 2007 or 2010, but will still work synchronously for Excel 97-2003. Having said that, there&#8217;s a requirement for Net4.o for IronPython so this add-in is more suited for modern versions of Excel and for OS &gt;= XP SP3.</p>
<p>HAMMER is <a href="http://office.microsoft.com/en-us/excel-help/introducing-array-formulas-in-excel-HA001087290.aspx">an array function</a>, yeah I know, normal folk tend to steer clear of Excel arrays. Which is to be expected, they&#8217;re not the most intuitive end-user-facing construct that the industry has ever come up with. But, they are the &#8220;Excel way&#8221; for passing tables in and out of formulas and, once mastered, open up a new world of power to Excel users. I will be adding helper functions to make using arrays a bit easier (an autoSize wrapper function, that&#8217;ll resize the selection area if it&#8217;s too small or too big, at the cost of a 2nd pass at the enclosed functions, might also port microETL&#8217;s SQL &#8220;paste&#8221; functionality).</p>
<p><del>I had intended to have an example to download with this post, but have discovered a last-minute bug that needs fixing. So it&#8217;ll be most likely next week before I&#8217;ve a version to show.</del></p>
<p>UPDATE:</p>
<p>I&#8217;ve managed to sort out the bug, so here&#8217;s an example&#8230;</p>
<p><a href="http://bit.ly/datasmith">http://bit.ly/datasmith</a></p>
<p><a href="http://www.gobansaor.com/hammer">Here’s a list of the HAMMER commands implemented so far …</a></p>
<p>Use setup.xls to install (or simply open in Excel), see IrelandFOIexample_hammer (2007/2010) for examples (there&#8217;s also a copy of the same functionality via microETL in IrelandFOIexample_microETL.xls &#8211; note the speed difference).  There&#8217;s Excel 2007/2010 32bit and  Excel 2010 64bit versions included and there&#8217;s also an un-tested 2003 version.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gobansaor.wordpress.com/1782/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gobansaor.wordpress.com/1782/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/gobansaor.wordpress.com/1782/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/gobansaor.wordpress.com/1782/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/gobansaor.wordpress.com/1782/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/gobansaor.wordpress.com/1782/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/gobansaor.wordpress.com/1782/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/gobansaor.wordpress.com/1782/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/gobansaor.wordpress.com/1782/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/gobansaor.wordpress.com/1782/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/gobansaor.wordpress.com/1782/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/gobansaor.wordpress.com/1782/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/gobansaor.wordpress.com/1782/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/gobansaor.wordpress.com/1782/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1782&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.gobansaor.com/2011/06/10/the-datasmiths-hammer/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<georss:point>53.204039 -6.574340</georss:point>
		<geo:lat>53.204039</geo:lat>
		<geo:long>-6.574340</geo:long>
		<media:content url="http://1.gravatar.com/avatar/b714f82b5e24beb3b74779615b6ad969?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">gobansaor</media:title>
		</media:content>

		<media:content url="http://gobansaor.files.wordpress.com/2011/06/datasmithhammer.png" medium="image">
			<media:title type="html">datasmithhammer</media:title>
		</media:content>
	</item>
		<item>
		<title>Attach a SQLite database into Excel&#8217;s memory via microETL</title>
		<link>http://blog.gobansaor.com/2011/05/20/attach-a-sqlite-database-into-excels-memory-via-microetl/</link>
		<comments>http://blog.gobansaor.com/2011/05/20/attach-a-sqlite-database-into-excels-memory-via-microetl/#comments</comments>
		<pubDate>Fri, 20 May 2011 11:05:17 +0000</pubDate>
		<dc:creator>gobansaor</dc:creator>
				<category><![CDATA[excel]]></category>
		<category><![CDATA[microETL]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[VBA]]></category>
		<category><![CDATA[SQLite Attach]]></category>

		<guid isPermaLink="false">http://blog.gobansaor.com/?p=1690</guid>
		<description><![CDATA[In my previous post I described the various methods of accessing SQLite databases from within Excel using microETL. Via comments on the post, Michael Römer suggested a change to how microETL loads into memory an external SQLite database (not only &#8230; <a href="http://blog.gobansaor.com/2011/05/20/attach-a-sqlite-database-into-excels-memory-via-microetl/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1690&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.gobansaor.com/2011/05/20/attach-a-sqlite-database-into-excels-memory-via-microetl/datatool-clear-2/" rel="attachment wp-att-1692"><img class="alignleft size-medium wp-image-1692" title="datatool-clear" src="http://gobansaor.files.wordpress.com/2011/05/datatool-clear.png?w=210&#038;h=122" alt="" width="210" height="122" /></a>In <a href="http://blog.gobansaor.com/2011/05/11/accessing-sqlite-databases-from-excel-via-microetl/">my previous post</a> I described the various methods of accessing SQLite databases from within Excel using <a href="http://www.gobansaor.com/microetl">microETL</a>. Via comments on the post, Michael Römer suggested a change to how microETL loads into memory an external SQLite database (not only suggested, but also provided the C code changes to enable the change; thanks Michael).</p>
<p>The existing <em><strong>xLiteLoadUnLoad(filename[,unload]) </strong></em>function loads a SQLite file into &#8220;main&#8221; i.e. the primary database (which is usually a :memory: db) overwriting any existing data. Michael&#8217;s suggestion was to allow loading into another in-memory database with a different alias; thus keeping the main database intact but allowing the benefits of in-memory access to the externally attached database. This feature has now been added.</p>
<p>I&#8217;ve kept the existing<strong> xLiteLoadUnLoad</strong> as is, but added a new optional argument to the xLiteAttachDB function so.</p>
<ul>
<li><strong> <em><strong>xliteAttachDB(databaseName,alias)  </strong></em></strong><em>becomes</em><strong><em><strong> <em><strong>xliteAttachDB(databaseName,alias,[loadInMemory=False])</strong></em></strong></em></strong><em><em>. </em></em>The optional loadInMemory argument defaults to FALSE, so acts like the old version (i.e. issues a standard SQLite Attach statement). But if set to TRUE; the function will first Attach a &#8220;:memory: database&#8221; named as the<strong> alias</strong>, then will load the external database file into that in-memory database. Once this happens the on-disk database is not referenced, so any changes will not be reflected back to disk. To enable changes to be persisted to disk, I&#8217;ve added another new function&#8230;</li>
<li><strong>xLiteDBSaveAs(alias,outDatabaseFile)</strong> will save a copy of the database named <strong>alias</strong> (with could be &#8220;main&#8221; if you wished to backup the default in-memory database) to the file<strong> outDatabaseFile</strong>. I&#8217;ve also added a &#8230;</li>
<li><strong>xLiteDetachDB(alias) </strong>to issue a SQLite DETACH statement. You might ask why not simply use the SQL() function to issue DETACH (or indeed ATTACH) statements? Statements such as ATTACH/DETACH cannot be issued by the SQL() functions as its pre-processor (for table() functionality) wraps SQL statements in a SAVEPOINT (nested SQL transaction). You can however use the fastSQL() or xliteRawSQL() functions to issue such commands.</li>
</ul>
<p><span class="Apple-style-span" style="font-size:14px;line-height:23px;">There&#8217;s another (this time breaking) change to the SQLScript TIMER  (<a href="http://blog.gobansaor.com/2011/03/27/expand-excels-horizons-look-to-the-cloud/">see here &#8230;</a>) command. The existing function used an ActiveX control (the Internet Explorer control as a provider for JavaScript timer functionality); ActiveX controls do not work under 64bit Excel, so I&#8217;ve reverted back to using Application.OnTime as my timer mechanism. The breaking change is the 3rd argument, which previously expected a value indicating the number of thousands-of-a-second to wait, now it represents whole seconds.</span></p>
<p>To download the latest version see the <a href="http://www.gobansaor.com/microetl">http://www.gobansaor.com/microetl</a> page.</p>
<p><strong>Update:</strong></p>
<p>For another method of loading SQLite databases within Excel/VBA see my new .NET-centric micro ETL tool  <a href="http://blog.gobansaor.com/category/hammer/">http://blog.gobansaor.com/category/hammer/</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gobansaor.wordpress.com/1690/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gobansaor.wordpress.com/1690/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/gobansaor.wordpress.com/1690/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/gobansaor.wordpress.com/1690/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/gobansaor.wordpress.com/1690/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/gobansaor.wordpress.com/1690/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/gobansaor.wordpress.com/1690/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/gobansaor.wordpress.com/1690/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/gobansaor.wordpress.com/1690/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/gobansaor.wordpress.com/1690/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/gobansaor.wordpress.com/1690/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/gobansaor.wordpress.com/1690/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/gobansaor.wordpress.com/1690/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/gobansaor.wordpress.com/1690/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1690&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.gobansaor.com/2011/05/20/attach-a-sqlite-database-into-excels-memory-via-microetl/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<georss:point>53.204039 -6.574340</georss:point>
		<geo:lat>53.204039</geo:lat>
		<geo:long>-6.574340</geo:long>
		<media:content url="http://1.gravatar.com/avatar/b714f82b5e24beb3b74779615b6ad969?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">gobansaor</media:title>
		</media:content>

		<media:content url="http://gobansaor.files.wordpress.com/2011/05/datatool-clear.png?w=300" medium="image">
			<media:title type="html">datatool-clear</media:title>
		</media:content>
	</item>
		<item>
		<title>Accessing SQLite databases from Excel via microETL</title>
		<link>http://blog.gobansaor.com/2011/05/11/accessing-sqlite-databases-from-excel-via-microetl/</link>
		<comments>http://blog.gobansaor.com/2011/05/11/accessing-sqlite-databases-from-excel-via-microetl/#comments</comments>
		<pubDate>Wed, 11 May 2011 18:44:19 +0000</pubDate>
		<dc:creator>gobansaor</dc:creator>
				<category><![CDATA[excel]]></category>
		<category><![CDATA[microETL]]></category>
		<category><![CDATA[SQLite]]></category>

		<guid isPermaLink="false">http://blog.gobansaor.com/?p=1635</guid>
		<description><![CDATA[MicroETL makes two SQLite instances available to Excel. The main database is the App database, by default an in-memory instance; the second is a Helper instance, again by default in-memory, which is used to hold logs and to enable SQLite &#8230; <a href="http://blog.gobansaor.com/2011/05/11/accessing-sqlite-databases-from-excel-via-microetl/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1635&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.gobansaor.com/2011/05/11/accessing-sqlite-databases-from-excel-via-microetl/sqlite-clear/" rel="attachment wp-att-1662"><img class="alignleft size-full wp-image-1662" title="SQLite-clear" src="http://gobansaor.files.wordpress.com/2011/05/sqlite-clear.png?w=500" alt=""   /></a><a href="http://www.gobansaor.com/microetl/">MicroETL</a> makes two SQLite instances available to Excel. The main database is the<strong><em> App</em></strong> database, by default an in-memory instance; the second is a <em><strong>Helper</strong></em> instance, again by default in-memory, which is used to hold logs and to enable SQLite to perform certain activities that would not be possible without two separate database instances. The main commands such as<a href="http://blog.gobansaor.com/2011/03/09/microetls-sql-function/"> SQL()</a> deal exclusively with the <strong><em>App</em></strong> instance, and for the most part that&#8217;s the only database that a microETL user needs to be aware of.</p>
<p>Within the microETL project, VBA routines can gain access to the <em>App</em> instance via the gAppDB global variable (gHelperDB for the <em>Helper</em> instance) while Python routines use the global dictionary element connDict(&#8220;App&#8221;) or connDict(&#8220;xlite&#8221;) for the <em>App</em> database (and connDict(&#8220;Helper&#8221;) for the <em>Helper</em>).</p>
<p><a href="http://blog.gobansaor.com/2011/03/04/sqlscript-microetls-sql-sequencer-utility/">SQLScript</a> (and in-cell formulas) can gain access to the Helper instance via the <strong>xLiteSQL(inSQL,outRange,NoHeader,PasteOver,useHelperDB)</strong> command, by setting useHelperDB to True. (The SQL() function is a thin-wrapper on this function to handle positional substitution tokens (:1, :2 &#8230;), the main functionality,such as the table() preprocessor commands and output to a range, are provided by xLiteSQL.)</p>
<p>These default in-memory databases are blank databases that are  instantiated in memory at workbook start-up and any tables or data created during the workbook session are discarded at shutdown. The standard use-case assumes that any data to be saved or fetched will come from Excel or perhaps via external CSVs or corporate database connections as would be the case with a normal Excel workbook, i.e. the main use for SQLite is assumed to be a provider of a SQL layer on top of Excel not a primary data-store.</p>
<p>However, <a href="http://blog.gobansaor.com/2009/03/14/sqlite-as-the-mp3-of-data/">SQLite is a superb data-store</a>, one which is used by 1000s of applications (quite likely many of apps on your smart-phone or iPad use SQLite as their database). Its <a href="http://www.sqlite.org/transactional.html">ACID nature</a> and small foot-print makes it an ideal means of storing client-side information that would otherwise need to be communicated to a &#8220;proper&#8221; server-side database such as MySQL or SQL Server.</p>
<p>MicroETL supports the use of disk-based databases for both the main App and companion Helper instances via:</p>
<ul>
<li><em><strong>xliteAttachDB(databaseName,alias)</strong></em>; this command will attach a database to the App database and assign it an alias. This is a wrapper on the SQLite Attach command  <a href="http://www.sqlite.org/lang_attach.html" rel="nofollow">http://www.sqlite.org/lang_attach.html</a>. Note: the SQL Attach command can not be used via the<a href="http://blog.gobansaor.com/2011/03/09/microetls-sql-function/"> SQL()</a> command, but can be used by the &#8220;raw&#8221; fastSQL() function.</li>
<li><em><strong>xLiteLoadUnLoad(filename[,unload])</strong></em>; this function is both useful &amp; dangerous, it will replace the main (<em>App</em>) database&#8217;s contents with the contents of the SQLite file provided by the first parameter. Typically the target database is the default empty in-memory (:memory:) database so no harm done; but if the default database was a file-based database, whose contents you wished to preserve, this might not be what you wanted. The second parameter if set to TRUE (FALSE being the default) works in the opposite direction i.e. replaces the specified database&#8217;s contents with those of the main (App) database.</li>
<li>Setting a <a href="http://www.ehow.com/how_2124432_create-excel-2007-custom-properties.html" rel="nofollow">custom property</a> of xLiteDB to a SQLite filename in a <em>driver</em> workbook, this database will then be used as the default App database. As well as file based databases, the xLiteDB property can be set to &#8221;:temp:&#8221; or &#8220;:memory:&#8221;, :temp: is like :memory: but will use RAM &amp; a temporary file while :memory: only uses RAM. The <em>driver</em> workbook is the first workbook to initiate microETL, so be careful of  multiple workbooks with different App &#8220;expectations&#8221; being accessed in the same Excel instance.</li>
<li>The similar custom property of xLiteHelperDB controls what Helper (i.e. Logging) database to use.</li>
<li>Another option is to use the custom properties xLiteAttachDB &amp; xLiteAttachDBAlias to auto-attach a database at startup</li>
<li>Yet another method is provided by the custom properties xLiteDBSeed and xLiteHelperDBSeed. Does the the equivalent of xLiteLoadUnLoad(databaseName,FALSE) at startup. <span class="Apple-style-span" style="font-size:13px;line-height:22px;">There&#8217;s an xLiteClose() function which release&#8217;s resources held by the App &amp; Helper databases and if they were seeded via xLiteDBSeed or XLiteHelperDBSeed, will save back any changes to the seed databases.</span></li>
</ul>
<div>
<p><strong>UPDATE:</strong></p>
<p><strong>As per Michael&#8217;s suggestions below, I&#8217;ve add the ability to attach an external database into an &#8220;aliased&#8221; :memory: database, see <a href="http://blog.gobansaor.com/2011/05/20/attach-a-sqlite-database-into-excels-memory-via-microetl/">http://blog.gobansaor.com/2011/05/20/attach-a-sqlite-database-into-excels-memory-via-microetl/</a></strong></p>
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gobansaor.wordpress.com/1635/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gobansaor.wordpress.com/1635/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/gobansaor.wordpress.com/1635/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/gobansaor.wordpress.com/1635/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/gobansaor.wordpress.com/1635/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/gobansaor.wordpress.com/1635/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/gobansaor.wordpress.com/1635/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/gobansaor.wordpress.com/1635/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/gobansaor.wordpress.com/1635/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/gobansaor.wordpress.com/1635/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/gobansaor.wordpress.com/1635/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/gobansaor.wordpress.com/1635/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/gobansaor.wordpress.com/1635/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/gobansaor.wordpress.com/1635/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1635&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.gobansaor.com/2011/05/11/accessing-sqlite-databases-from-excel-via-microetl/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<georss:point>53.204039 -6.574340</georss:point>
		<geo:lat>53.204039</geo:lat>
		<geo:long>-6.574340</geo:long>
		<media:content url="http://1.gravatar.com/avatar/b714f82b5e24beb3b74779615b6ad969?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">gobansaor</media:title>
		</media:content>

		<media:content url="http://gobansaor.files.wordpress.com/2011/05/sqlite-clear.png" medium="image">
			<media:title type="html">SQLite-clear</media:title>
		</media:content>
	</item>
		<item>
		<title>microETL &#8211; the ultimate datasmithing tool?</title>
		<link>http://blog.gobansaor.com/2011/04/29/microetl-the-ultimate-datasmithing-tool/</link>
		<comments>http://blog.gobansaor.com/2011/04/29/microetl-the-ultimate-datasmithing-tool/#comments</comments>
		<pubDate>Fri, 29 Apr 2011 15:08:06 +0000</pubDate>
		<dc:creator>gobansaor</dc:creator>
				<category><![CDATA[ETL]]></category>
		<category><![CDATA[excel]]></category>
		<category><![CDATA[microETL]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[VBA]]></category>

		<guid isPermaLink="false">http://blog.gobansaor.com/?p=1574</guid>
		<description><![CDATA[Over the years I&#8217;ve accumulated and written thousands of lines of VBA code, I&#8217;ve also integrated Excel with countless other technologies. Most of this work was associated with the movement and managing of datasets; data for reporting on, for analysing &#8230; <a href="http://blog.gobansaor.com/2011/04/29/microetl-the-ultimate-datasmithing-tool/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1574&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.gobansaor.com/2011/04/29/microetl-the-ultimate-datasmithing-tool/transform-clear/" rel="attachment wp-att-1656"><img class="alignleft size-medium wp-image-1656" title="transform etl" src="http://gobansaor.files.wordpress.com/2011/04/transform-clear.png?w=300&#038;h=95" alt="" width="300" height="95" /></a>Over the years I&#8217;ve accumulated and written thousands of lines of VBA code, I&#8217;ve also integrated Excel with countless other technologies. Most of this work was associated with the movement and managing of datasets; data for reporting on, for analysing and for collection. MicroETL is, in effect, a collection of the best (or at least the most useful) of these activities, packaged primarily so that I don&#8217;t have to continuously re-invent the wheel, so that when I&#8217;m working on a client&#8217;s problem, I can concentrate on the problem and not the technology. So although I share the code with all and sundry with the hope that others may find it useful (little choice as it&#8217;s VBA <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ), its primary purpose is to the serve my needs, and indirectly, those of my clients.</p>
<p>VBA is of course at the heart of microETL. I&#8217;m often asked why not port the code to one of Microsoft&#8217;s more &#8220;modern&#8221; languages? There are three  main reasons for not doing so now (and one major one for not doing so in the past).</p>
<p>First the past. When MS introduced .NET the needs of those who program mainly around the Office platform were ignored, .NET add-ins for Excel were a pain to write, even more painful to deploy and even then, were slow compared to VBA add-ins. Things have improved, it&#8217;s now much easier to target Office from within Visual Studio (although still just as expensive). But even now, the best method of using .NET with Excel is a  superb 3rd-party open source tool, <a href="http://exceldna.codeplex.com/" target="_blank">ExcelDNA</a>. This is the tool I&#8217;ve used (and will continue to use) whenever I needed to merge Excel with the .NET platform.</p>
<p>I&#8217;m currently developing a .NET offshoot of microETL called HAMMER; using ExcelDNA, C#-SQLite and IronPython; not so much a replacement for microETL but a new type of tool to take advantage of the new capabilities offered by Excel 2007/2010 (multi-threading and 64bit memory addressing mainly) and .NET4 (IronPython and ease of multi-threading programming). It&#8217;s also, thanks to ExceDNAPack, a single file deployment. To keep an eye on its development follow <a href="http://blog.gobansaor.com/category/powerpivot/hammer/" target="">the HAMMER tag on my blog</a>.</p>
<p>So if ExcelDNA provides a pain-free (and cost-free) method of using C# or VB.NET with Excel, why stick with VBA? As I said, three reasons:</p>
<ul>
<li>VBA is to Excel what JavaScript is to the web browser. It&#8217;s only remaining purpose as a language (with the death of VB6) is as an Office automation language and ,in effect, when you&#8217;re programming in Excel you&#8217;re largely working with the Excel Object model (in much the same way and the DOM is the focus of attention on JavaScript progamming). VBA is perfectly suited to this task and although it has its problems as a language (again like JavaScript) once you know them they&#8217;re not a problem. VBA is here for the long haul, Office 2010&#8242;s addition of the 64bit support to the language (Vb7 !) confirmed that. As the code is already in VBA, works very well as VBA and has a long future ahead of it, why change?</li>
<li>VBA is easy for a large subset of end-users to learn due to Excel&#8217;s macro-recording facility. The resulting code may not be pretty but it works both as a automation tool and as a learning tool. Millions of <a href="http://blog.gobansaor.com/2010/05/12/time-assets/" target="_blank">citizen programmers</a> owe their skills to the VBA macro recorder. One of microETL&#8217;s goal is to make adding functionality as easy as possible and one such method of doing that is via simple VBA functions that can be called from <a href="http://blog.gobansaor.com/2011/03/04/sqlscript-microetls-sql-sequencer-utility/" target="_blank">SQLScript (microETL&#8217;s tabular scripting extension)</a>. C# or VB.NET are professional languages designed for professionals to use, VBA comes from a long line of &#8220;pro-am&#8221; scripting languages which open the world of programming to a much larger population.</li>
<li>Multiple deployment options. MicroETL can be installed like a normal add-in and consists of three files, the VBA add-in, the SQLite3 dll and the xLiteSQLite dll to wrap SQLite to make it VBA accessible. Python functionality and other options will add further files. But by embedding a small call-on-open macro in a workbook the add-in can be called without installation. This is how I use it for once-off tasks, as I can package the code and the associated data and workbooks in a single zip file for archiving purposes or for deployment (often running off a USB stick).  Because I can deploy my code as <em>code-at-a-moment-in-time</em> I can modify the codebase to suit the current requirements without affecting other microETL projects that are using, or might in the future use, a different version fo the code. In fact, microETL has a <em>noSQL </em>compile option that removes SQLIte and other DLL dependencies (with a reduction in power obviously) enabling the code to be embedded in a workbook allowing for a single-file deployment (which often, is the only option). This could not be done with a .NET add-in.</li>
</ul>
<p><a href="http://blog.gobansaor.com/2011/04/29/microetl-the-ultimate-datasmithing-tool/datatool-clear/" rel="attachment wp-att-1659"><img class="alignleft size-medium wp-image-1659" title="datatool etl" src="http://gobansaor.files.wordpress.com/2011/04/datatool-clear.png?w=180&#038;h=105" alt="" width="180" height="105" /></a>Okay, so VBA is useful, but why embed SQLite and Python? As I&#8217;ve said above, microETL exists to make my life easier. I&#8217;m a database programmer, I&#8217;ve been using SQL (or its predecessors ) for  three decades. I like set-based logic (such as SQL  or PowerPivot&#8217;s DAX) because:</p>
<ul>
<li>I&#8217;m good at it (practice does make perfect) enabling me to solve many data related problems efficiently and more accurately (fast is no good if the result is wrong) that would be the case with functional (Excel fromulas) or procedural (code) approaches.</li>
<li>I believe anybody who spends a significant proportion of their working lives managing datasets should learn basic SQL. If they don&#8217;t it&#8217;s like driving a car but never getting beyond 2nd gear.</li>
</ul>
<p>SQLite allows me to bring the beautiful world of set logic to user-centric<a href="http://blog.gobansaor.com/2009/10/25/excel-as-the-ipod-of-downloaded-data/" target="_blank"> Excel world of functional programming</a> (yes, all you Excel jocks, you&#8217;re functional programmers). It also brings some nice side-effects:</p>
<ul>
<li>It is, like Excel itself, a<a href="http://blog.gobansaor.com/2009/03/14/sqlite-as-the-mp3-of-data/" target="_blank">n outstanding single-file document-oriented datastore</a>.</li>
<li>By default, microETL uses SQLite in-memory database functionality (you can also attach disk-based ones) so it offers a means of exploiting the vast amount of cheap RAM that modern PCs now offer. Excel has always stored its working datasets in-memory and it too now offers much greater capacity (1,000,000 rows per sheet in Excel 2007/2010). SQLite has no practical limit other than the available memory and the addressable-limit of the OS (2GB for 32bit Windows). With 64bit Windows (microETL is Excel 64bit enabled) that addressable limit is now effectively gone. This makes microETL a s<a href="http://www.gobansaor.com/microETL-fix-my-list" target="_blank">uperb platform for all sorts of ETL tasks</a>.</li>
<li>As SQLite offers Excel a secondary in-memory datastore it can be used to share models across programming platform boundaries. This allows me to embed Python in Excel and use the in-memory SQLite database as a shared data conduit. I&#8217;ve done the same with <a href="http://blog.gobansaor.com/2010/06/04/javascript-as-an-excel-scripting-language-via-jsdb/" target="_blank">JavaScript</a> (but only on 32bit) and with .NET. The result is the non-native languages can be used as if they were not operating with Excel, no need to mangle in Excel interface code, simple!</li>
</ul>
<p>Which brings me to Python. Why embed a Python interpreter into microETL? Can I not just use VBA as I quite obviously know it inside out? Well of course for all things Excel-focused that is what I do, and for most other transformation or calculations that require some programming I would also opt for VBA. No reason not to, it works and works quickly. However, Python (and in particular C-Python) offers access to world of superb code. If something can be automated, or interfaced to, or turned into a computing algorithm, somebody (usually very bright) will have done it in Python. Python also works well with C, and again if a C library is useful somebody will have wrapped it in Python. Python means that if I&#8217;m asked &#8220;Can you integrate Excel with &#8230;&#8230;?&#8221;, I can say, &#8220;Yeah, no problem&#8221;.</p>
<p>Python as a language has the other advantage of being a superb tool to work through a problem with; it doesn&#8217;t get in the way; very little of my mind has to be diverted to the language itself, the problem at hand gets the attention (C would be an example of a language on the other extreme, you better have the solution to your domain problem figured out before you start to program in C as the programming task itself will command most of your attention).</p>
<p>Python is an ideal language for business logic. It is easy to learn, eminently readable and generally immune to programming gotchas. Because of this, it&#8217;s very popular as a <em>citizen programmers&#8217;</em> language, especially amongst engineers, scientists and quants, so it blends in naturally with microETL the <em>ultimate datasmithing tool!</em></p>
<p>So if microETL is built on a foundation of &#8220;civilian friendly&#8221; technologies such as Excel formulas, VBA, SQL and Python is it a tool that anybody could use? In theory yes, in practice it depends.</p>
<p>Only a small proportion of the population has the ability to master procedural programming and an even smaller precentage has the interest in so doing. (A much large proportion of the population shows the ability and the interest to tackle Excel&#8217;s native programming method: functional no-side-effects programming using Excel formulas, which accounts for the appeal of spreadsheets to the general populace!).</p>
<p>So although I&#8217;ve abstracted away a large level of the complexity of automating Excel by means of the <a href="http://blog.gobansaor.com/2011/03/04/sqlscript-microetls-sql-sequencer-utility/" target="_blank">SQLScript</a> and <a href="http://blog.gobansaor.com/2011/03/09/microetls-sql-function/" target="_blank">SQL</a> functions, it&#8217;s still programming.  But even if the full power of the tool is beyond most, the tabular sequential nature of  SQLScript and the relative approachability of SQL should mean that many can at least follow the logic and data flows and might even be able to modify existing scripts. Those users with a good knowledge of VBA and or SQL should find the tool enables them to be more productive and cost effective. While those with Excel formula skills can usually work in tandem with a framework of microETL functionality with relative ease.</p>
<p>For the latest versions and articles on using microETL follow the<a href="http://blog.gobansaor.com/category/microETL/"> microETL tag </a>on this blog &#8230;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gobansaor.wordpress.com/1574/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gobansaor.wordpress.com/1574/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/gobansaor.wordpress.com/1574/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/gobansaor.wordpress.com/1574/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/gobansaor.wordpress.com/1574/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/gobansaor.wordpress.com/1574/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/gobansaor.wordpress.com/1574/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/gobansaor.wordpress.com/1574/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/gobansaor.wordpress.com/1574/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/gobansaor.wordpress.com/1574/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/gobansaor.wordpress.com/1574/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/gobansaor.wordpress.com/1574/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/gobansaor.wordpress.com/1574/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/gobansaor.wordpress.com/1574/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1574&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.gobansaor.com/2011/04/29/microetl-the-ultimate-datasmithing-tool/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<georss:point>53.204039 -6.574340</georss:point>
		<geo:lat>53.204039</geo:lat>
		<geo:long>-6.574340</geo:long>
		<media:content url="http://1.gravatar.com/avatar/b714f82b5e24beb3b74779615b6ad969?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">gobansaor</media:title>
		</media:content>

		<media:content url="http://gobansaor.files.wordpress.com/2011/04/transform-clear.png?w=300" medium="image">
			<media:title type="html">transform etl</media:title>
		</media:content>

		<media:content url="http://gobansaor.files.wordpress.com/2011/04/datatool-clear.png?w=300" medium="image">
			<media:title type="html">datatool etl</media:title>
		</media:content>
	</item>
		<item>
		<title>microETL&#8217;s SQL function</title>
		<link>http://blog.gobansaor.com/2011/03/09/microetls-sql-function/</link>
		<comments>http://blog.gobansaor.com/2011/03/09/microetls-sql-function/#comments</comments>
		<pubDate>Wed, 09 Mar 2011 14:03:09 +0000</pubDate>
		<dc:creator>gobansaor</dc:creator>
				<category><![CDATA[ETL]]></category>
		<category><![CDATA[microETL]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[VBA]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://blog.gobansaor.com/?p=1395</guid>
		<description><![CDATA[At the heart of microETL is the SQL() command (or more correctly microETL.SQL()). The primary purpose of microETL is to allow the power of SQL to be used within Excel and SQL() is how that is delivered. The command can &#8230; <a href="http://blog.gobansaor.com/2011/03/09/microetls-sql-function/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1395&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>At the heart of microETL is the SQL() command (or more correctly microETL.SQL()). The primary purpose of microETL is to allow the power of SQL to be used within Excel and SQL() is how that is delivered. The command can either be issued from a cell, like a standard excel formula, or by using the microETL SQL Menu option or as a command in a <a href="http://blog.gobansaor.com/2011/03/04/sqlscript-microetls-sql-sequencer-utility/">SQLScript</a>. It can be called from a VBA macro (using Application.Run(&#8220;microETL.SQL&#8221; &#8230; ) but not if that macro is to be used as a User Defined Function (aka user defined formula). It can also be called from within another SQL statement using the equivalent SQLite user defined function also called SQL().</p>
<p>Example: click for a larger image (animated GIF)</p>
<div id="attachment_1410" class="wp-caption aligncenter" style="width: 1034px"><a href="http://gobansaor.files.wordpress.com/2011/03/ex2_a.gif"><img class="size-large wp-image-1410" title="=SQL() function " src="http://gobansaor.files.wordpress.com/2011/03/ex2_a.gif?w=1024&#038;h=413" alt="" width="1024" height="413" /></a><p class="wp-caption-text">=SQL() in action</p></div>
<p><strong>SQL(sqlStatement,selectDestination(OR arg1), arg2 &#8230;. argn)</strong></p>
<p>The 1st argument is the SQL statement(s) to execute. These can be any valid SQLite statements (see <a href="http://www.sqlite.org/lang.html">SQL as understood by SQLite</a>); exceptions are the ATTACH statement and in some circumstances the DROP TABLE statement. The statement will be issued against the default microETL <a href="http://www.sqlite.org/inmemorydb.html">in-memory database</a> i.e. an empty database that is instantiated in memory at workbook start-up and any tables or data created during the workbook session are discarded at shutdown.</p>
<p>So, if the database is ephemeral where will my data be stored? In the spreadsheet most likely. The other alternatives  are to use the SQLite UDFs load_CSV() and write_CSV() to load/save CSV files, or see <a href="http://blog.gobansaor.com/2011/05/11/accessing-sqlite-databases-from-excel-via-microetl/">http://blog.gobansaor.com/2011/05/11/accessing-sqlite-databases-from-excel-via-microetl/</a> for other options.</p>
<p>In order to make transferring data between Excel and the SQL environment easier and simpler a pre-processor has been added to the function. There are three types of pre-processor commands:</p>
<ul>
<li>The TABLE(…) command tells SQL() to go fetch the relevant Excel range, loads the “table” into SQLite; when the SQL command finishes it writes back the data (if changed) to the originating Excel address, and cleans up the temporary SQLite-side table. Nearly all SQL commands can be issued against the resulting tables, including UPDATE, DELETE, DROP and CREATE TRIGGERS etc.</li>
<li>Two other pre-processor commands are CELL(…) and CELLS(…). Similar to TABLE(…), data is loaded from the Excel addresses specified and placed in the SQL  statement. CELL takes a single cell reference while CELLS will iterate through a multi-cell range and insert a comma-separated list into the SQL statement (in a format suitable for IN (…) expressions).</li>
<li>Positional substitution tokens in the form :1 to :n</li>
</ul>
<p>Note these are pre-processor commands not SQLite commands and can only be accessed using the SQL() function. The pre-processor &#8220;functions&#8221; may appear to work like a normal SQLite function call but are less flexible in some ways e.g. no spaces allowed, parser expects &#8220;TABLE(&#8221; not &#8220;TABLE  ( &#8221; but more flexible in others so a function requiring a table name can use the pre-processor to provide it e.g. =SQL(&#8220;Select load_CSV(&#8216;TABLE(Sheet!A1)&#8217;,'c:\data\test.csv&#8217;);)&#8221;).</p>
<p>The sequence of events when a TABLE() pre-processor command is detected in a SQL statement is as follows:</p>
<ul>
<li>SQLite <a href="http://www.sqlite.org/lang_savepoint.html">SAVEPOINT</a> is set if the SQL()  statement is not already running in the context of a previous SQL() function call. This wrapping in a transaction is the reason for ATTACH commands not been allowed. The purpose of the transaction is two-fold; 1st it will clean up any temporary tables and other updates in the case of a function failure, 2nd, SQLite inserts/updates are much faster when executed within a transaction, especially if writing to a disk-based database.</li>
<li>If the text between &#8220;TABLE(&#8221; and the next &#8220;)&#8221; is a valid range representation (or a named range pointing at such) a check is carried out to see whether that same range has been referenced before in this context (same context being within the same set of SQL statements or those of a prior &#8220;wrapping&#8221; SQL() function call). If already &#8220;handled&#8221; replace the TABLE(&#8230;) with the name of the temporary table associated with this range. If not, load the table data (as long as the range is an Excel table, or points to the top left-hand corner of a potential table) into a new temporary SQLite table and replace the TABLE(&#8230;) with its name.</li>
<li>When the last SQL statement within the current context is executed and if the temporary table has been modified (INSERT&#8217;ed, UPDATEd,DELETEd or DROPped ) the table is written back to the source range (or range cleared if a DROP statement).</li>
<li>The SAVEPOINT is released.</li>
</ul>
<p>The remaining arguments to the SQL() function are also processed by the pre-processor, the arguments passed replace positional substitution tokens in the form :1 to :n where :1 is replaced by 2nd argument and :n is replaced by the n+1th argument.</p>
<p>The 2nd argument (that is the arg corresponding to the :1 token) is special. If no &#8220;:1&#8243; token is found within the SQL Statement, the argument is assumed to be a destination for a SQL SELECT statement (think of it as a SELECT INTO). It can be either a string representation of a workbook range or a named range pointing at one. The range can be either a full range, top left-hand corner range or an Excel Table. (If none of the above, the SELECT will populate an <a href="http://www.4guysfromrolla.com/webtech/080101-1.shtml">ADO detached RecordSet</a> and use the argument as the name of that recordset).</p>
<p>A number of helper functions have been added to SQLite within microETL. Note: these are not preprocessor commands and so can be used by any SQL issued within microETL. (There are a number of SQL issuing functions other than SQL() and there&#8217;s also the SQL calls issued within Python functions.)</p>
<div id="attachment_1416" class="wp-caption aligncenter" style="width: 510px"><a href="http://gobansaor.files.wordpress.com/2011/03/sql_from_menu.png"><img class="size-full wp-image-1416" title="SQL_from_Menu" src="http://gobansaor.files.wordpress.com/2011/03/sql_from_menu.png?w=500&#038;h=285" alt="" width="500" height="285" /></a><p class="wp-caption-text">Using the Menu option SQL</p></div>
<h3><strong>The main SQL helper functions are &#8230;</strong></h3>
<p><strong>x(formula,p1,p2,p3&#8230;)</strong></p>
<p>Where formula is a spreadsheet formula or built-in function, followed by a variable list of parameters. The formula can take advantage of microETL &#8220;placeholders&#8221; e.g. x(&#8220;20+ :1 + :2&#8243;,20,40) will return 80, x(&#8220;upper(:1:)&#8221;,&#8221;abc&#8221;) returns ABC.</p>
<p>The formula&#8217;s text, with any placeholders replaced, is passed to Excel&#8217;s Application object&#8217;s Evaluate method, so not withstanding some of the limitations associated with this function (see <a href="http://www.decisionmodels.com/calcsecretsh.htm">here</a>) it&#8217;s possible to use most Excel formulas within a SQL statement.</p>
<p>Only built-in functions (i.e not User Defined Functions) can be called in this manner.  To call a UDF use the udf() (or u() /mdf())  function.</p>
<p>When specifying the formula do not include the leading &#8220;=&#8221;, this will ensure formula is evaluated inline along with the rest of the SQL statement. If preceded by &#8220;=&#8221;, the formula is passed back as text. This can sometimes be useful either for testing purposes or to get around Application.Evaluate limitations.</p>
<p>Example: click for larger view:</p>
<p><a href="http://gobansaor.files.wordpress.com/2011/03/x_example.png"><img class="aligncenter size-large wp-image-1413" title="x()_Example" src="http://gobansaor.files.wordpress.com/2011/03/x_example.png?w=1024&#038;h=263" alt="" width="1024" height="263" /></a></p>
<p><strong>udf(functionName,p1,p2,p3&#8230;)</strong></p>
<p>This allows any VBA public function (i.e. a UDF) in the active workbook  to be called from within a SQLite SQL statement. The u() and mdf() functions are similar but the mdf() function will only run functions in the microETL project while u() will default to the microETL project but will also take references to UDFs in other workbooks.</p>
<p><strong>Py(address,<strong>p1,p2,p3&#8230;</strong>)</strong></p>
<p>The address can be either a string representation of an Excel range e.g. &#8220;Sheet2!A3:Sheet2!D6&#8243; or a named range. If the range is a single cell the function will expect to find the full Python script within, if a multi-cell range then the script will utilise cells as Python indents.</p>
<p>The scripts are in fact anonymous parameter-less Python functions. Parameters are passed via xLite &#8220;placeholders&#8221; which are replaced before the script is passed to the Python interpreter e.g.</p>
<p><a href="http://gobansaor.files.wordpress.com/2011/03/simple_python.png"><img class="aligncenter size-full wp-image-1409" title="simple_python" src="http://gobansaor.files.wordpress.com/2011/03/simple_python.png?w=500" alt=""   /></a></p>
<p>If in  this case 2nd parameter is less than 40, return 1st parameter increased by 10% otherwise return unchanged.</p>
<p><strong>SQLScript(address,<strong>p1,p2,p3&#8230;</strong>)</strong></p>
<p>See previous post <a href="http://blog.gobansaor.com/2011/03/04/sqlscript-microetls-sql-sequencer-utility/">http://blog.gobansaor.com/2011/03/04/sqlscript-microetls-sql-sequencer-utility/</a></p>
<p><strong>SQL(sqlStatement,p1,p2,p3&#8230;)</strong></p>
<p>This allows the microETL.SQL() function (along with its pre-processor goodness) to be called from an environment where the pre-processor is not supported e.g. within Python. It&#8217;s also useful to process a series of SQL statements held in a table.</p>
<p><strong>Various Hierarchy functions</strong></p>
<p>See this <a href="http://blog.gobansaor.com/2011/02/18/handling-flat-parent-child-and-nested-set-hierarchies/">Handling Flat, Parent-Child and Nested Set Hierarchies</a> and <a href="http://blog.gobansaor.com/2011/03/03/powerpivot-powered-budgets-targets/">this</a>.</p>
<p><strong>write_CSV(table,filename)</strong></p>
<p>This will write out the contents of the table in classic CSV format (UTF-8 encoded). Useful for external SQLite tables that may be too big to fit in memory but need transformation before loading as a CSV into the likes of PowerPivot.</p>
<p><strong>load_CSV(table,filename)</strong></p>
<p>Will load UFT-8 encoded CSV files into a table. Again, if a CSV source is too big to load into memory (thinking fact tables here) but needs some SQL love&#8217;n'care can be loaded into an external table (i.e. in a disk-based database) bypassing the need to fit in Excel&#8217;s working memory.</p>
<p><strong>sqliteDate(dateTimeString)</strong></p>
<p>Will attempt to convert a string to an ISO DateTime string ( the format used internally by SQLite i.e. &#8220;YYYY-MM-DD hh:mm:ss&#8221;). Usually microETL will handle date conversions between Excel and SQlite and back again (but when a date is pasted back it&#8217;ll be in Excel numeric representation, the column may need to be formatted to the required date/time representation). Sometimes however the date format of imported &#8220;string dates&#8221; may not be recognised (for example, Excel loaded CSVs often fail to recognise dates correctly). This function will usually solve the problem.</p>
<p><strong>ISODate(Year,Month,Day)</strong></p>
<p>Will take a date passed as 3 numbers (e.g. ISODate(2010,12,31)) and convert to SQLite date format.</p>
<p><strong>REGEXP</strong></p>
<p>I&#8217;ve also added REGEXP (<a href="http://blog.gobansaor.com/2008/07/01/regular-expressions-as-an-end-user-programming-tool/">regular expression</a>) support so you can do stuff like so&#8230;</p>
<p>SELECT * FROM Foo WHERE account_id REGEXP &#8216;[0][0-9]*[x]&#8216;</p>
<p>or</p>
<p>=SQL(&#8220;SELECT regexp(&#8216;[0][0-9]*[x]&#8216;,&#8217;0987f85x&#8217;);&#8221;) -&gt; returns 0 for false (should be all digits between leading zero and final &#8216;x&#8217;).</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/gobansaor.wordpress.com/1395/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/gobansaor.wordpress.com/1395/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/gobansaor.wordpress.com/1395/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/gobansaor.wordpress.com/1395/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/gobansaor.wordpress.com/1395/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/gobansaor.wordpress.com/1395/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/gobansaor.wordpress.com/1395/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/gobansaor.wordpress.com/1395/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/gobansaor.wordpress.com/1395/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/gobansaor.wordpress.com/1395/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/gobansaor.wordpress.com/1395/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/gobansaor.wordpress.com/1395/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/gobansaor.wordpress.com/1395/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/gobansaor.wordpress.com/1395/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.gobansaor.com&amp;blog=110633&amp;post=1395&amp;subd=gobansaor&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.gobansaor.com/2011/03/09/microetls-sql-function/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<georss:point>53.204039 -6.574340</georss:point>
		<geo:lat>53.204039</geo:lat>
		<geo:long>-6.574340</geo:long>
		<media:content url="http://1.gravatar.com/avatar/b714f82b5e24beb3b74779615b6ad969?s=96&#38;d=monsterid&#38;r=G" medium="image">
			<media:title type="html">gobansaor</media:title>
		</media:content>

		<media:content url="http://gobansaor.files.wordpress.com/2011/03/ex2_a.gif?w=1024" medium="image">
			<media:title type="html">=SQL() function </media:title>
		</media:content>

		<media:content url="http://gobansaor.files.wordpress.com/2011/03/sql_from_menu.png" medium="image">
			<media:title type="html">SQL_from_Menu</media:title>
		</media:content>

		<media:content url="http://gobansaor.files.wordpress.com/2011/03/x_example.png?w=1024" medium="image">
			<media:title type="html">x()_Example</media:title>
		</media:content>

		<media:content url="http://gobansaor.files.wordpress.com/2011/03/simple_python.png" medium="image">
			<media:title type="html">simple_python</media:title>
		</media:content>
	</item>
	</channel>
</rss>
