<?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/"
	>

<channel>
	<title>Zach Hunter&#039;s Busy Life</title>
	<atom:link href="http://www.zachhunter.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.zachhunter.com</link>
	<description>Random Brain Drool</description>
	<lastBuildDate>Tue, 03 Aug 2010 17:25:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>WordPress 3.0 &#8211; A CMS Solution?</title>
		<link>http://www.zachhunter.com/2010/07/wordpress-3-0-a-cms-solution/</link>
		<comments>http://www.zachhunter.com/2010/07/wordpress-3-0-a-cms-solution/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 22:01:08 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=338</guid>
		<description><![CDATA[I started working on a project site that is going to use WordPress as the CMS engine. I wasn&#8217;t sure if this was going to work, but after a little time I found this was pretty easy to do. You start by deleting all the default content and disabling the default plug-ins and management screen [...]]]></description>
			<content:encoded><![CDATA[<p>I started working on a project site that is going to use WordPress as the CMS engine.  I wasn&#8217;t sure if this was going to work, but after a little time I found this was pretty easy to do.  You start by deleting all the default content and disabling the default plug-ins and management screen options.  Once everything is removed/disabled, you start by creating pages (e.g. Home, About, News, etc&#8230;) that will display all the content you need on the website.  One you have your main page setup (e.g. Home), you need to change the default home page from a dynamic page of blog posts to a static page.  You change the default home page under Settings &#8211;> Reading &#8211;> Front Page Display &#8211;> A Static Page &#8211;> Choose an option from the Front Page drop down list.  That&#8217;s it, you now have WordPress running as a basic CMS soltuion.</p>
<p>I wish I could say that&#8217;s it, but most likely you&#8217;ll need to download and install some additional plug-ins.  I found many plug-ins still do not support WordPress 3.0, so you&#8217;ll need to be careful!  If you happen to install a bad plug-in, there is an easy fix to get you site back online&#8230;  Delete the plug-in folder (via FTP or Hosting Control Panel) and WordPress will automatically disable the plug-in.</p>
<p>Here is the list of plug-ins I added for my project:</p>
<ol>
<li>Contact Form 7<br/>This is a great plug-in, it provides a easy way to create forms that get emailed to you.  You create the forms using HTML online and a shortcode style syntax for the input fields.  The shortcode inputs are then accessible in your email, that you also create using HTML.</li>
<li>WP Google Maps<br />This is a very basic Google Maps plug-in, the is about 10 options and the only think extra you need is a GoogleMaps API key.</li>
<li>WordPress.com Stats<br />I&#8217;ve been using this on my blog and love the UI.  I wish this was all being done client-side, but for some reason it was created as service.  By default it injects a smiley face into your page, so make sure you disable this in your themes style sheet.</li>
</ol>
<p>The only other thing I added was a SSL plug-in that I created based on 3 other plug-ins.  I created my own, so I could force WP to load specific pages as HTTPS and then default back to HTTP if it was not explicitly set to support SSL.  I found most of the default plug-ins will leave the user browsing in SSL after they visit a SSL page, I didn&#8217;t want this and my plug-ins solves this problem.</p>
<pre class="brush: php;">
&lt;?php
/*
This plug-in is based on WPSSL, forcessl and various other posts/comments I found while searching for a soltuion.  The plug-in is used by adding the meta tag &quot;force_ssl&quot; with any value to any pages where you want SSL (&quot;HTTPS&quot;) enabled.  If the page does NOT have this set and your not looking at an admin page (you can enable SSL for admin/login page in wpconfig.php), then display as HTTP.  This prevent links on the SSL page from displaying as SSL for non-secure pages.  This plug-in was tested on WordPress 3.0
*/

function wpssl_forcessl()
{
	global $post;

    $post_id = $post;

    if (is_object($post_id))
    {
		$post_id = $post_id-&gt;ID;
	}

    $force_ssl  = get_post_meta($post_id, 'force_ssl');

    if(!empty($force_ssl))
    {
    	if(!stristr($_SERVER['REQUEST_URI'], 'wp-admin')) {
			if($_SERVER[&quot;HTTPS&quot;] != &quot;on&quot;) {
				$newurl = &quot;https://&quot; . $_SERVER[&quot;SERVER_NAME&quot;] . $_SERVER[&quot;REQUEST_URI&quot;];
            	header(&quot;Location: $newurl&quot;);
            	exit();
        	}
     	}
    } else {
		if(!stristr($_SERVER['REQUEST_URI'], 'wp-admin')) {
			if($_SERVER[&quot;HTTPS&quot;] == &quot;on&quot;) {
				$newurl = &quot;http://&quot; . $_SERVER[&quot;SERVER_NAME&quot;] . $_SERVER[&quot;REQUEST_URI&quot;];
				header(&quot;Location: $newurl&quot;);
				exit();
			}
	}	}
}

add_action('wp', 'wpssl_forcessl');
?&gt;
</pre>
<p>To use the plug-in, you&#8217;ll need to add a custom field called &#8220;force_ssl&#8221; as in the example below.</p>
<p><img src="http://www.zachhunter.com/wp-content/uploads/force_ssl.png" alt="" title="WordPress Custom Force SSL Plug-in" class="alignnone wp-image-343" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/07/wordpress-3-0-a-cms-solution/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Improved NPOI ExportDataTableToExcel Function</title>
		<link>http://www.zachhunter.com/2010/06/improved-npoi-exportdatatabletoexcel-function/</link>
		<comments>http://www.zachhunter.com/2010/06/improved-npoi-exportdatatabletoexcel-function/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 19:43:41 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=330</guid>
		<description><![CDATA[I was looking over my &#8220;generic&#8221; export a DataTable to Excel function the other day and noticed an issue. My default method was throwing everything into a string format, which was preventing users from highlighting columns for subtotals. To fix the problem they could use &#8220;Text to Columns&#8221;, but this was really a work-around to [...]]]></description>
			<content:encoded><![CDATA[<p>I was looking over my &#8220;generic&#8221; export a DataTable to Excel function the other day and noticed an issue.  My default method was throwing everything into a string format, which was preventing users from highlighting columns for subtotals.  To fix the problem they could use &#8220;Text to Columns&#8221;, but this was really a work-around to my lack of creativeness.  I came up with an improved &#8220;ExportDataTableToExcel&#8221; function that will now default the data types Int/Double/Decimal into the NPOI Double type.</p>
<pre class="brush: csharp;">
    /// &lt;summary&gt;
    /// Render DataTable to Excel File
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;sourceTable&quot;&gt;Source DataTable&lt;/param&gt;
    /// &lt;param name=&quot;fileName&quot;&gt;Destination File name&lt;/param&gt;
    public static void ExportDataTableToExcel(DataTable sourceTable, string fileName)
    {
        HSSFWorkbook workbook = new HSSFWorkbook();
        MemoryStream memoryStream = new MemoryStream();
        HSSFSheet sheet = workbook.CreateSheet(&quot;Sheet1&quot;);
        HSSFRow headerRow = sheet.CreateRow(0);

        // Build Header
        foreach (DataColumn column in sourceTable.Columns)
        {
            // Create New Cell
            HSSFCell headerCell = headerRow.CreateCell(column.Ordinal);

            // Set Cell Value
            headerCell.SetCellValue(column.ColumnName);

            // Create Style
            HSSFCellStyle headerCellStyle = workbook.CreateCellStyle();
            headerCellStyle.FillForegroundColor = HSSFColor.GREY_25_PERCENT.index;
            headerCellStyle.FillPattern = CellFillPattern.SOLID_FOREGROUND;

            // Add Style to Cell
            headerCell.CellStyle = headerCellStyle;
        }

        // Build Details (rows)
        int rowIndex = 1;
        int sheetIndex = 1;
        const int maxRows = 65536;

        foreach (DataRow row in sourceTable.Rows)
        {
            // Start new sheet max rows reached
            if (rowIndex % maxRows == 0)
            {
                // Auto size columns on current sheet
                for (int h = 0; h &lt; headerRow.LastCellNum; h++)
                {
                    sheet.AutoSizeColumn(h);
                }

                sheetIndex++;
                sheet = workbook.CreateSheet(&quot;Sheet&quot; + sheetIndex);
                HSSFRow additionalHeaderRow = sheet.CreateRow(0);

                for (int h = 0; h &lt; headerRow.LastCellNum; h++)
                {
                    HSSFCell additionalHeaderColumn = additionalHeaderRow.CreateCell(h);
                    additionalHeaderColumn.CellStyle = headerRow.GetCell(h).CellStyle;
                    additionalHeaderColumn.SetCellValue(headerRow.GetCell(h).RichStringCellValue);
                }

                rowIndex = 1;
            }

            // Create new row in sheet
            HSSFRow dataRow = sheet.CreateRow(rowIndex);

            foreach (DataColumn column in sourceTable.Columns)
            {
                switch (column.DataType.FullName)
                {
                    case &quot;System.String&quot;:
                        dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
                        break;
                    case &quot;System.Int&quot;:
                    case &quot;System.Int32&quot;:
                    case &quot;System.Int64&quot;:
                    case &quot;System.Double&quot;:
                    case &quot;System.Decimal&quot;:
                        dataRow.CreateCell(column.Ordinal).SetCellValue(Double.Parse(row[column].ToString()));
                        break;
                    default:
                        dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
                        break;
                }
            }

            rowIndex++;
        }

        for (int h = 0; h &lt; headerRow.LastCellNum; h++)
        {
            sheet.AutoSizeColumn(h);
        }

        workbook.Write(memoryStream);
        memoryStream.Flush();

        HttpResponse response = HttpContext.Current.Response;
        response.ContentType = &quot;application/vnd.ms-excel&quot;;
        response.AddHeader(&quot;Content-Disposition&quot;, string.Format(&quot;attachment;filename={0}&quot;, fileName));
        response.Clear();

        response.BinaryWrite(memoryStream.GetBuffer());
        response.End();
    }
</pre>
<p>The key part to look at above is the &#8220;switch (column.DataType.FullName)&#8221; block.  This grabs the data type of the source column to use in the SetCellValue() call.  The result is an Excel file with numeric data types formatted as numbers!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/06/improved-npoi-exportdatatabletoexcel-function/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery Validation with ASP.NET</title>
		<link>http://www.zachhunter.com/2010/06/jquery-validation-with-asp-net/</link>
		<comments>http://www.zachhunter.com/2010/06/jquery-validation-with-asp-net/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 04:20:48 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=314</guid>
		<description><![CDATA[Over the past few weeks I&#8217;ve been working to migrate away from the Ajax Control Toolkit &#38; various other ASP.NET built-in controls. My goal has been to get every page of our intranet portal down around 100K, with a maximum load time of &#60; 1 second. I&#8217;ve made a lot of progress, but after being [...]]]></description>
			<content:encoded><![CDATA[<p>Over the past few weeks I&#8217;ve been working to migrate away from the Ajax Control Toolkit &amp; various other ASP.NET built-in controls.  My goal has been to get every page of our intranet portal down around 100K, with a maximum load time of &lt; 1 second.  I&#8217;ve made a lot of progress, but after being cleaning up all the basic stuff (excess view state, duplicate references, compressed JS/CSS, sprites, etc&#8230;), I had to start looking for additional items&#8230;</p>
<p>After using <a href="http://www.fiddler2.com/fiddler2/">Fiddler</a>and <a href="http://getfirebug.com/">FireBug</a> to analyze the page contents, I found that the ASP.NET validation controls were generating ~10K in increase download size.  Since my portal consists of injecting multiple user controls into a page, this number would vary by the number of modules using the validation controls.  To stay consist with my client side library, I decided to implement <a href="http://bassistance.de/jquery-plugins/jquery-plugin-validation/">jQuery Validation Plugin</a> as a replacement to the ASP.NET validation controls.</p>
<p>The idea was simple enough, but since I&#8217;m living in the ASP.NET Web Form this were a bit more difficult to implement.</p>
<h2>Issue #1 &#8211; jQuery Validation by FIELDSET</h2>
<p>I&#8217;ve been using jQuery Validation for about a year, so I was already aware that it was built around using a single FORM versus multiple FIELDSETs.  I put together a solution based on multiple articles I read about to come up with a &#8220;SaveAndSubmit&#8221; function.  This function allows me to re-scope (ex. FIELDSET vs FORM) the group of controls you want to validate.</p>
<p>Here is my custom validation function that validates a group of controls within a FIELDSET with the class &#8220;validationGroup&#8221;.</p>
<pre class="brush: jscript;">
    function ValidateAndSubmit(evt) {
       // Find the parent control that contains the class validationGroup
        var $group = $(evt.currentTarget).parents('.validationGroup');

        var isValid = true;

       // Look at all the input controls and run them against the rules
        $group.find(':input').each(function(i, item) {
            if (!$(item).valid())
                isValid = false;
        });

        // If any control is the group fails, prevent default actions (aka: Submit)
        if (!isValid)
            evt.preventDefault();
    }
</pre>
<p>To use a custom validation function, you need disable the automatic binding of all buttons to the default validation function.  This allows you to bind to your new custom event and to control which controls should trigger the validation.</p>
<pre class="brush: jscript;">
        // Disable default/auto binding of all buttons
        $(&quot;#aspnetForm&quot;).validate({
                onsubmit: false
        });

        // Bind the ASP.NET button with the ID &quot;Search&quot; to the &quot;ValidateAndSubmit&quot; custom validation function.
        $('#&lt;%= Search.ClientID %&gt;').click(ValidateAndSubmit);
</pre>
<p>That&#8217;s it, with those three little little steps (Custom Validate Method, Disable Default/Auto Bind, Manual bind button to custom event), you now have a working validate by FIELDSET (or any other grouping control) solution.</p>
<h2>Issue #2 &#8211; How to validate a group of ASP.NET Check Boxes</h2>
<p>By default, ASP.NET will render a CheckBox or a CheckBoxList with an auto generated unique name attribute.  This becomes a problem when you want to validate the group, since you can&#8217;t set a common name attribute for all the elements.</p>
<p>Here is an example of the HTML that would be rendered by a CheckBoxList with a layout of &#8220;Flow&#8221;.</p>
<pre class="brush: xml;">
&lt;span id=&quot;CheckBoxGroup&quot;&gt;
  &lt;input id=&quot;cbk1&quot; name=&quot;cbk1&quot; type=&quot;checkbox&quot;&gt;Check Box 1&lt;/input&gt;
  &lt;input id=&quot;cbk2&quot; name=&quot;cbk2&quot; type=&quot;checkbox&quot;&gt;Check Box 2&lt;/input&gt;
  &lt;input id=&quot;cbk3&quot; name=&quot;cbk3&quot; type=&quot;checkbox&quot;&gt;Check Box 3&lt;/input&gt;
&lt;/span&gt;
&lt;span class=&quot;jQueryValError&quot;&gt;&lt;/span&gt;
</pre>
<p>My solution to the problem required a custom validator and a custom errorPlacement function, for the jQuery validaiton plug-in.</p>
<p>First, I added a custom validator that looked at a group of check boxes that are inside a wrapping &#8220;Parent()&#8221; element.  I then count the number of checked check boxes to make sure the limit required (e.g. Must check at least 3 check boxes) is greater than the minimum we set.</p>
<pre class="brush: jscript;">
    jQuery.validator.addMethod(&quot;minChecked&quot;,
     function(value, element, param) {
        var $p = $(element).parent();
        var selected = $p.children('input[type=checkbox]:checked').length;

        if (selected &gt;= param) {
            $p.children().removeClass('error');
            $p.siblings('.error').remove();
            return true;
            }

        $p.children('input[type=checkbox]').addClass('error');
</pre>
<p>In order to hookup this custom event to all the controls inside of a wrapping &#8220;Parent()&#8221; control, we use jQuery&#8217;s $().each function to call the validator&#8217;s rules() function.</p>
<pre class="brush: jscript;">
$(&quot;.checkBoxGroup&quot;).children('input[type=checkbox]').each(function(){ $(this).rules(&quot;add&quot;, { minChecked: 3}); });
</pre>
<p>Second, our plug-in will by default put an error message next to the control(s) that triggered the error.  I over ride the default behavior, we setup a &#8220;errorPlacement&#8221; function to put one error beside the wrapping &#8220;Parent()&#8221; control. </p>
<pre class="brush: jscript;">
            $(&quot;#&lt;%= form1.ClientID %&gt;&quot;).validate({
                errorPlacement: function(error, element){
                    if(element.rules().minChecked &gt; 0) {
                        var $p = $(element).parent();
                        if($p.siblings().hasClass(&quot;error&quot;) == false) {
                            error.insertAfter($p);
                        }
                    }
                    else {
                        error.insertAfter(element);
                    }
                }
            });
</pre>
<p>Here is what the form looks like when you have a error with your check boxes.</p>
<p><a href="http://www.zachhunter.com/wp-content/uploads/jQueryValidation_ASPNET_CheckBoxes.jpg"><img src="http://www.zachhunter.com/wp-content/uploads/jQueryValidation_ASPNET_CheckBoxes-300x97.jpg" alt="jQuery Validation of ASP.NET CheckBoxes" title="jQuery Validation of ASP.NET CheckBoxes" width="300" height="97" class="alignnone size-medium wp-image-332" /></a></p>
<p>Here is source code used to create the example above.</p>
<pre class="brush: jscript;">
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head runat=&quot;server&quot;&gt;
    &lt;title&gt;Contact Form Demo&lt;/title&gt;

    &lt;script src=&quot;styles/jQuery.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;

    &lt;script src=&quot;styles/jQuery.Validate.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;

    &lt;script src=&quot;styles/jQuery.Validate.AddOns.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;

    &lt;script type=&quot;text/javascript&quot;&gt;

    jQuery.validator.addMethod(&quot;minChecked&quot;,
     function(value, element, param) {
        var $p = $(element).parent();
        var selected = $p.children('input[type=checkbox]:checked').length;

        if (selected &gt;= param) {
            $p.children().removeClass('error');
            $p.siblings('.error').remove();
            return true;
            }

        $p.children('input[type=checkbox]').addClass('error');

        return false;}, jQuery.validator.format(&quot;Please check at least {0} items.&quot;)); 

        $(document).ready(function(){
            $(&quot;#&lt;%= form1.ClientID %&gt;&quot;).validate({
                rules: {
                    &lt;%= FirstName.UniqueID %&gt;: { required: true },
                    &lt;%= LastName.UniqueID %&gt;: { required: true },
                    &lt;%= Email.UniqueID %&gt;: { required: true, email: true },
                    &lt;%= Phone.UniqueID %&gt;: { required: true, phoneUS: true }
                },
                errorPlacement: function(error, element){
                    if(element.rules().minChecked &gt; 0) {
                        var $p = $(element).parent();
                        if($p.siblings().hasClass(&quot;error&quot;) == false) {
                            error.insertAfter($p);
                        }
                    }
                    else {
                        error.insertAfter(element);
                    }
                }
            });

            $(&quot;.checkBoxGroup&quot;).children('input[type=checkbox]').each(function(){ $(this).rules(&quot;add&quot;, { minChecked: 3}); });

            $(&quot;.myGroupRandom&quot;).children('input[type=checkbox]').each(function(){ $(this).rules(&quot;add&quot;, { minChecked: 1}); });
        });
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;
    &lt;div&gt;
        &lt;fieldset&gt;
            &lt;ol&gt;
                &lt;li&gt;
                    &lt;label class=&quot;left&quot;&gt;
                        First Name
                    &lt;/label&gt;
                    &lt;input type=&quot;text&quot; id=&quot;FirstName&quot; runat=&quot;server&quot; /&gt;&lt;/li&gt;
                &lt;li&gt;
                    &lt;label class=&quot;left&quot;&gt;
                        Last Name
                    &lt;/label&gt;
                    &lt;input type=&quot;text&quot; id=&quot;LastName&quot; runat=&quot;server&quot; /&gt;&lt;/li&gt;
                &lt;li&gt;
                    &lt;label class=&quot;left&quot;&gt;
                        Email
                    &lt;/label&gt;
                    &lt;input type=&quot;text&quot; id=&quot;Email&quot; runat=&quot;server&quot; /&gt;&lt;/li&gt;
                &lt;li&gt;
                    &lt;label class=&quot;left&quot;&gt;
                        Phone
                    &lt;/label&gt;
                    &lt;input type=&quot;text&quot; id=&quot;Phone&quot; runat=&quot;server&quot; /&gt;&lt;/li&gt;
                &lt;li&gt;
                    &lt;label class=&quot;left&quot;&gt;
                        Contact Method
                    &lt;/label&gt;
                    &lt;span class=&quot;checkBoxGroup&quot;&gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;ReqEmail&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;Email&lt;/label&gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;ReqMail&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;Mail&lt;/label&gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;ReqPhone&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;Phone&lt;/label&gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;ReqNoContact&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;No Contact&lt;/label&gt;
                    &lt;/span&gt;&lt;/li&gt;
                &lt;li&gt;
                    &lt;label class=&quot;left&quot;&gt;
                        New Letter Type
                    &lt;/label&gt;
                    &lt;span class=&quot;myGroupRandom&quot; &gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;Checkbox1&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;Company News&lt;/label&gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;Checkbox2&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;Press Releases&lt;/label&gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;Checkbox3&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;Deals&lt;/label&gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;Checkbox4&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;Employement&lt;/label&gt;
                    &lt;/span&gt;&lt;/li&gt;
                &lt;li&gt;
                    &lt;input type=&quot;submit&quot; id=&quot;Submit&quot; value=&quot;Submit&quot; /&gt;&lt;/li&gt;
            &lt;/ol&gt;
        &lt;/fieldset&gt;
    &lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/06/jquery-validation-with-asp-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NPOI &#8211; Set Cell Helper</title>
		<link>http://www.zachhunter.com/2010/05/npoi-set-cell-helper/</link>
		<comments>http://www.zachhunter.com/2010/05/npoi-set-cell-helper/#comments</comments>
		<pubDate>Fri, 21 May 2010 19:57:18 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=282</guid>
		<description><![CDATA[How to create a helper function to quickly set Excel worksheet cell values using NPOI.]]></description>
			<content:encoded><![CDATA[<p>I saw a discussion posting on the NPOI discussion forum on CodePlex today, asking if there was a function like SetCell(X,Y,Value) in NPOI.  Unfortunately there isn&#8217;t&#8230;  At least I was never able to find one, so I created my own.  Since I only needed to set values I added three basic ones into my helper class to make available to everybody using NPOI in my project.  I was really tempted to add these to the HSSFWorksheet, but to keep my code save I figured a helper class for all my extras would be enough.  Here is my version of a SetCellValue() helper set of functions.</p>
<pre class="brush: csharp;">
        private static void SetCellValue(HSSFSheet worksheet, int columnPosition, int rowPosition, DateTime value)
        {
            // Get row
            using (HSSFRow row = worksheet.GetRow(rowPosition))
            {
                // Get or Create Cell
                using (HSSFCell cell = row.GetCell(columnPosition) ?? row.CreateCell(columnPosition))
                {
                    cell.SetCellValue(value);
                    cell.CellStyle.DataFormat = 14;
                }
            }
        }

        private static void SetCellValue(HSSFSheet worksheet, int columnPosition, int rowPosition, double value)
        {
            // Get row
            using (HSSFRow row = worksheet.GetRow(rowPosition))
            {
                // Get or Create Cell
                using (HSSFCell cell = row.GetCell(columnPosition) ?? row.CreateCell(columnPosition))
                {
                    cell.SetCellValue(value);
                }
            }
        }

        private static void SetCellValue(HSSFSheet worksheet, int columnPosition, int rowPosition, string value)
        {
            // Get row
            using (HSSFRow row = worksheet.GetRow(rowPosition))
            {
                // Get or Create Cell
                using (HSSFCell cell = row.GetCell(columnPosition) ?? row.CreateCell(columnPosition))
                {
                    cell.SetCellValue(value);
                }
            }
        }

        // Set Date
        SetCellValue(sheet, 9, 3, DateTime.Now);
        // Set Number
        SetCellValue(sheet, 9, 4, 100.01);
        // Set Text
        SetCellValue(sheet, 9, 5, &quot;Zach Roxs!&quot;);
</pre>
<p>As you can see it&#8217;s pretty easy to create a SetCellValue() helper.  I plan to create another version of these that uses Excel coordinates (e.g. A5, Z10, etc&#8230;), so my die hard Excel teammates can use their native Excel mapping syntax!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/05/npoi-set-cell-helper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NPOI &#8211; Copy Row Helper</title>
		<link>http://www.zachhunter.com/2010/05/npoi-copy-row-helper/</link>
		<comments>http://www.zachhunter.com/2010/05/npoi-copy-row-helper/#comments</comments>
		<pubDate>Fri, 21 May 2010 00:06:55 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=272</guid>
		<description><![CDATA[How to create a helper function to copy rows on a worksheet with NPOI.]]></description>
			<content:encoded><![CDATA[<p>Another day and another little tidbit on using NPOI.  I was doing tool mock-up at work today when I ran across a need for a copy row function.  After searching high and low, I realized NPOI does not currently offer this capability.  After looking around (Google, NPOI and POI threads) I decided to create my own helper function.  I&#8217;m sure there might be a few things I missed in my routine since the library is a bit new to me, but after testing this against a bunch of different scenarios I&#8217;m pretty confident this will work for 99% of my needs and maybe a high percent of yours as well.</p>
<p>Here is the function in all it&#8217;s glory, I thought about modify the NPOI source but since I&#8217;m not sure where it&#8217;s going I figured I&#8217;d just add this in my own little NPOI.CustomHelpers class that I can use with my NPOI project.</p>
<pre class="brush: csharp;">
        /// &lt;summary&gt;
        /// HSSFRow Copy Command
        ///
        /// Description:  Inserts a existing row into a new row, will automatically push down
        ///               any existing rows.  Copy is done cell by cell and supports, and the
        ///               command tries to copy all properties available (style, merged cells, values, etc...)
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;workbook&quot;&gt;Workbook containing the worksheet that will be changed&lt;/param&gt;
        /// &lt;param name=&quot;worksheet&quot;&gt;WorkSheet containing rows to be copied&lt;/param&gt;
        /// &lt;param name=&quot;sourceRowNum&quot;&gt;Source Row Number&lt;/param&gt;
        /// &lt;param name=&quot;destinationRowNum&quot;&gt;Destination Row Number&lt;/param&gt;
        private void CopyRow(HSSFWorkbook workbook, HSSFSheet worksheet, int sourceRowNum, int destinationRowNum)
        {
            // Get the source / new row
            HSSFRow newRow = worksheet.GetRow(destinationRowNum);
            HSSFRow sourceRow = worksheet.GetRow(sourceRowNum);

            // If the row exist in destination, push down all rows by 1 else create a new row
            if (newRow != null)
            {
                worksheet.ShiftRows(destinationRowNum, worksheet.LastRowNum, 1);
            }
            else
            {
                newRow = worksheet.CreateRow(destinationRowNum);
            }

            // Loop through source columns to add to new row
            for (int i = 0; i &lt; sourceRow.LastCellNum; i++)
            {
                // Grab a copy of the old/new cell
                HSSFCell oldCell = sourceRow.GetCell(i);
                HSSFCell newCell = newRow.CreateCell(i);

                // If the old cell is null jump to next cell
                if (oldCell == null)
                {
                    newCell = null;
                    continue;
                }

                // Copy style from old cell and apply to new cell
                HSSFCellStyle newCellStyle = workbook.CreateCellStyle();
                newCellStyle.CloneStyleFrom(oldCell.CellStyle); ;
                newCell.CellStyle = newCellStyle;

                // If there is a cell comment, copy
                if (newCell.CellComment != null) newCell.CellComment = oldCell.CellComment;

                // If there is a cell hyperlink, copy
                if (oldCell.Hyperlink != null) newCell.Hyperlink = oldCell.Hyperlink;

                // Set the cell data type
                newCell.SetCellType(oldCell.CellType);

                // Set the cell data value
                switch (oldCell.CellType)
                {
                    case HSSFCellType.BLANK:
                        newCell.SetCellValue(oldCell.StringCellValue);
                        break;
                    case HSSFCellType.BOOLEAN:
                        newCell.SetCellValue(oldCell.BooleanCellValue);
                        break;
                    case HSSFCellType.ERROR:
                        newCell.SetCellErrorValue(oldCell.ErrorCellValue);
                        break;
                    case HSSFCellType.FORMULA:
                        newCell.SetCellFormula(oldCell.CellFormula);
                        break;
                    case HSSFCellType.NUMERIC:
                        newCell.SetCellValue(oldCell.NumericCellValue);
                        break;
                    case HSSFCellType.STRING:
                        newCell.SetCellValue(oldCell.RichStringCellValue);
                        break;
                    case HSSFCellType.Unknown:
                        newCell.SetCellValue(oldCell.StringCellValue);
                        break;
                }
            }

            // If there are are any merged regions in the source row, copy to new row
            for (int i = 0; i &lt; worksheet.NumMergedRegions; i++)
            {
                CellRangeAddress cellRangeAddress = worksheet.GetMergedRegion(i);
                if (cellRangeAddress.FirstRow == sourceRow.RowNum)
                {
                    CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.RowNum,
                                                                                (newRow.RowNum +
                                                                                 (cellRangeAddress.FirstRow -
                                                                                  cellRangeAddress.LastRow)),
                                                                                cellRangeAddress.FirstColumn,
                                                                                cellRangeAddress.LastColumn);
                    worksheet.AddMergedRegion(newCellRangeAddress);
                }
            }

        }
</pre>
<p>The code comments above should give you a good idea of what I&#8217;m doing, if something doesn&#8217;t make sense just ask.  The key things I wanted to make sure got copied were; Cell Style, Cell Value, Cell Type, Merged Cell Settings.  In the end I noticed a few other things that I thought I might use in the future, so I included them as well.  Here is an example of how to call to CopyRow along with a snapshot of the end result.</p>
<pre class="brush: csharp;">
            // Grab my NPOI workbook memorystream
            HSSFWorkbook workbook = new HSSFWorkbook(memoryStream);

            // Grab my test worksheet
            HSSFSheet sheet = workbook.GetSheet(&quot;Sheet1&quot;);

            // Copy Excel Row 1 to Excel Row 3
            CopyRow(workbook, sheet, 0, 2);

            // Copy Excel Row 2 to Excel Row 4
            CopyRow(workbook, sheet, 1, 3);
</pre>
<div id="attachment_273" class="wp-caption alignnone" style="width: 310px"><a href="http://www.zachhunter.com/wp-content/uploads/NPOI_CopyRowFunctionResults.gif"><img src="http://www.zachhunter.com/wp-content/uploads/NPOI_CopyRowFunctionResults-300x160.gif" alt="" title="NPOI - Copy Row Helper Function Test Results" width="300" height="160" class="size-medium wp-image-273" /></a><p class="wp-caption-text">NPOI - Copy Row Helper Function Test Results</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/05/npoi-copy-row-helper/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using jQuery to prevent &#8220;Delete&#8221; mistakes</title>
		<link>http://www.zachhunter.com/2010/05/using-jquery-to-prevent-delete-mistakes/</link>
		<comments>http://www.zachhunter.com/2010/05/using-jquery-to-prevent-delete-mistakes/#comments</comments>
		<pubDate>Thu, 20 May 2010 06:06:22 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=268</guid>
		<description><![CDATA[Using the Poka-Yoke principal to prevent accidental "Deletes" using jQuery]]></description>
			<content:encoded><![CDATA[<p>A few days ago I was reading a web design article that talked about the &#8220;<a href="http://en.wikipedia.org/wiki/Poka-yoke">Poka-Yoke</a>&#8221; principle.  It was such a funny phrase that I had to go to Wikipedia to figure out the definition.  In a nutshell, the principle refers to the process of &#8220;idiot-proofing&#8221; human interaction with a process.  This term is based on the Japanese words &#8220;yokeru&#8221; avoid and &#8220;poka&#8221; mistake, this is rather funny for me since I work for a Japanese company that has clearly never heard of this principle!</p>
<p>This term came to mind today while helping another programmer develop a system to prevent accidental in their UI.  After discussing what needed to be done, it was clear that we needed to implement some client side logic to &#8220;prevent&#8230; guide&#8230;&#8221; the user into making the correct choices.</p>
<p>The UI was pretty straight forward, there will be a few buttons to do various actions on rows in a table.  The users will select one or more rows for the table and then click the button of the action they want to perform.  Sounds simple, right&#8230; We&#8217;ll it is and it&#8217;s also really easy to select the wrong row and/or the wrong button.  Training is a big help in any process, but one you leave the users alone the system will be the only thing enforcing the rules.</p>
<p>Here is an example of a table where rows will be selected for deletion.  I used a &#8220;asp:Table&#8221; to simulate the markup for a table that will be generated with a &#8220;asp:GridView&#8221;.  In my past 5 years of working with ASP.NET, this was the first time I ever used or seen this control used.</p>
<pre class="brush: xml;">
    &lt;div class=&quot;mediumTable&quot;&gt;
        &lt;asp:Button ID=&quot;DeleteButton&quot; runat=&quot;server&quot; Text=&quot;Delete&quot; /&gt;
        &lt;asp:Table ID=&quot;Table1&quot; runat=&quot;server&quot;&gt;
            &lt;asp:TableHeaderRow&gt;
                &lt;asp:TableHeaderCell&gt;Chk&lt;/asp:TableHeaderCell&gt;
                &lt;asp:TableHeaderCell&gt;Product&lt;/asp:TableHeaderCell&gt;
                &lt;asp:TableHeaderCell&gt;Stock&lt;/asp:TableHeaderCell&gt;
            &lt;/asp:TableHeaderRow&gt;
            &lt;asp:TableRow&gt;
                &lt;asp:TableCell&gt;
                    &lt;asp:CheckBox ID=&quot;CheckBox1&quot; runat=&quot;server&quot; /&gt;&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;Apples&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;0&lt;/asp:TableCell&gt;
            &lt;/asp:TableRow&gt;
            &lt;asp:TableRow&gt;
                &lt;asp:TableCell&gt;
                    &lt;asp:CheckBox ID=&quot;CheckBox2&quot; runat=&quot;server&quot; /&gt;&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;Oranges&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;100&lt;/asp:TableCell&gt;
            &lt;/asp:TableRow&gt;
            &lt;asp:TableRow&gt;
                &lt;asp:TableCell&gt;
                    &lt;asp:CheckBox ID=&quot;CheckBox3&quot; runat=&quot;server&quot; /&gt;&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;Pears&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;150&lt;/asp:TableCell&gt;
            &lt;/asp:TableRow&gt;
            &lt;asp:TableRow&gt;
                &lt;asp:TableCell&gt;
                    &lt;asp:CheckBox ID=&quot;CheckBox4&quot; runat=&quot;server&quot; /&gt;&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;Watermelon&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;2&lt;/asp:TableCell&gt;
            &lt;/asp:TableRow&gt;
        &lt;/asp:Table&gt;
    &lt;/div&gt;
    &lt;/form&gt;
</pre>
<p>Here is the delete &#8220;prevention&#8221; system we came up.  We had a few other ideas like, but after doing a few demos of each solution we decided on the following code that will be discussed below.</p>
<pre class="brush: jscript;">
        $(document).ready(function() {
            $('#&lt;%= DeleteButton.ClientID %&gt;').click(function() {
                // Find all selected items
                var CheckedCheckBoxes = $('#&lt;%= Table1.ClientID %&gt;').find(&quot;input[type='checkbox']:checked&quot;);
                // If there are no selected items, exit
                if (CheckedCheckBoxes.length == 0) {
                    alert(&quot;You must make a selection before you can delete an item.&quot;);
                    return false;
                }
                // If there are selected items, loop
                CheckedCheckBoxes.each(function() {
                    var isProcessed = $(this).parent().parent().find('td:last').text();
                    // If current item is already processed, set flat to true
                    if (jQuery.trim(isProcessed) &gt; 0) {
                        deletedProcessed = true;
                    }
                });
                // Check flag, if true stop ALL deletes and notify user
                if (deletedProcessed) {
                    alert(&quot;You can't delete a product with stock!&quot;);
                    return false;
                }
                else {
                    // Do a final confirmation the user wants to delete the selection
                    var answer = confirm('Are you sure you want to delete your selection?');
                    return answer
                }
            });
        });
</pre>
<p>Since selection box was used for a few different functions (process orders, hold orders and edit orders) we needed a way to add a little extra checking to only the delete button.  Our goals with the logic above was the following.</p>
<ol style="margin-left:40px;">
<li>Disables &#8220;Delete&#8221; if nothing has been selected.</li>
<li>Disables &#8220;Delete&#8221; if the user selected a item should not be deleted (e.g. Has Inventory).</li>
<li>Prompts the user to confirm the really want to delete the item.</li>
</ol>
<p>In addition to these ideas, we also had the following ideas&#8230;</p>
<ol style="margin-left:40px;">
<li>Alert row # of items that don&#8217;t meet the business rule</li>
<li>Highlight the row in &#8220;red&#8221; that don&#8217;t meet the business rule</li>
<li>Physically &#8220;Disable&#8221; the delete button if they select an item that don&#8217;t meet the business rules</li>
</ol>
<p>Mistakes are human nature and by double and triple checking what they are doing we can save the users and ourselves from many emails/phone calls/visits about how the system &#8220;deleted the data all by itself&#8221;.</p>
<p>Mistake proofing is such an easy idea to grasp and agree with, that it&#8217;s surprising that we don&#8217;t see more of it in the systems we using everyday.  I&#8217;m sure I&#8217;ve developed a few bad ones, hopefully the audience using it was small and it didn&#8217;t mitigate itself into other things.  Working for a Japanese company who has developed some of the worst internal tools I&#8217;ve ever seen (0 UI design effort), I&#8217;m sure to bring up the new Japanese &#8220;Poka-Yoke&#8221; principle that next time I talk to one of the developers in Japan.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/05/using-jquery-to-prevent-delete-mistakes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to read in XLSX data for editing with NPOI</title>
		<link>http://www.zachhunter.com/2010/05/read-xlsx-data-for-npoi/</link>
		<comments>http://www.zachhunter.com/2010/05/read-xlsx-data-for-npoi/#comments</comments>
		<pubDate>Mon, 10 May 2010 19:17:04 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=263</guid>
		<description><![CDATA[A helper function to read in XLSX data into a DataTable to be converted into a XLS object for editing with NPOI.]]></description>
			<content:encoded><![CDATA[<p>NPOI is a great solution for working with XLS documents, but what happens when you need to read in XLSX documents as part of your solution?  The easiest solution I could think of was to use OLEDB to extract out all the data (<em>the data, the whole data and nothing but the data</em>) from a worksheet into a new NPOI document.</p>
<p>If you need more support than just reading in data from Excel 2007+ (XLSX), you should look at using the <a href="http://excelpackage.codeplex.com/">ExcelPackage </a>project that is hosted at <a href="http://www.codeplex.com">CodePlex</a>.</p>
<p>The benefit to my approach, is that your able to use your existing NPOI solutions when data is provided in XLSX format.  This is far from full Excel 2007+ support, but if your applicaitons only requirement is &#8220;reading in data&#8221; then your problem is solved.   NPOI v1.6 is supposed to fully support the XLSX format, until then this function will provide basic XLSX support.</p>
<h5>Functions used to convert XLSX document to a NPOI document</h5>
<pre class="brush: csharp;">
    /// &lt;summary&gt;
    /// Render a Excel 2007 (xlsx) Worksheet to NPOI Excel 2003 Worksheet, all excel formatting
    /// from XLSX will be lost when converted.  NPOI roadmap shows v1.6 will support Excel 2007 (xlsx).
    /// NPOI Roadmap  : http://npoi.codeplex.com/wikipage?title=NPOI%20Road%20Map&amp;referringTitle=Documentation
    /// NPOI Homepage : http://npoi.codeplex.com/
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;excelFileStream&quot;&gt;XLSX FileStream&lt;/param&gt;
    /// &lt;param name=&quot;sheetName&quot;&gt;Excel worksheet to convert&lt;/param&gt;
    /// &lt;returns&gt;MemoryStream containing NPOI Excel workbook&lt;/returns&gt;
    public static Stream ConvertXLSXWorksheetToXLSWorksheet(Stream excelFileStream, string sheetName)
    {
        // Temp file name
        string tempFile = HttpContext.Current.Server.MapPath(&quot;~/uploads/&quot; + HttpContext.Current.Session.LCID + &quot;.tmp&quot;);

        // Temp data container (using DataTable to leverage existing RenderDataTableToExcel function)
        DataTable dt = new DataTable();

        try
        {
            // Create temp XLSX file
            FileStream fileStream = new FileStream(tempFile, FileMode.Create, FileAccess.Write);

            const int length = 256;
            Byte[] buffer = new Byte[length];
            int bytesRead = excelFileStream.Read(buffer, 0, length);

            while (bytesRead &gt; 0)
            {
                fileStream.Write(buffer, 0, bytesRead);
                bytesRead = excelFileStream.Read(buffer, 0, length);
            }

            excelFileStream.Close();
            fileStream.Close();

            // Read temp XLSX file using OLEDB
            // Tested on Vista &amp; Windows 2008 R2
            using (OleDbConnection con = new OleDbConnection(@&quot;Provider=Microsoft.ACE.OLEDB.12.0; Extended Properties=Excel 12.0;Data Source=&quot; + tempFile + @&quot;;Extended Properties=Excel 12.0;&quot;))
            {
                con.Open();
                string sql = String.Format(&quot;SELECT * FROM [{0}$]&quot;, sheetName);
                OleDbDataAdapter da = new OleDbDataAdapter(sql, con);

                da.Fill(dt);
            }
        }
        finally
        {
            // Make sure temp file is deleted
            File.Delete(tempFile);
        }

        // Return a new POI Excel 2003 Workbook
        return RenderDataTableToExcel(dt);
    }

    /// &lt;summary&gt;
    /// Render DataTable to NPOI Excel 2003 MemoryStream
    /// NOTE:  Limitation of 65,536 rows suppored by XLS
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;sourceTable&quot;&gt;Source DataTable&lt;/param&gt;
    /// &lt;returns&gt;MemoryStream containing NPOI Excel workbook&lt;/returns&gt;
    public static Stream RenderDataTableToExcel(DataTable sourceTable)
    {
        HSSFWorkbook workbook = new HSSFWorkbook();
        MemoryStream memoryStream = new MemoryStream();
        // By default NPOI creates &quot;Sheet0&quot; which is inconsistent with Excel using &quot;Sheet1&quot;
        HSSFSheet sheet = workbook.CreateSheet(&quot;Sheet1&quot;);
        HSSFRow headerRow = sheet.CreateRow(0);

        // Header Row
        foreach (DataColumn column in sourceTable.Columns)
            headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);

        // Detail Rows
        int rowIndex = 1;

        foreach (DataRow row in sourceTable.Rows)
        {
            HSSFRow dataRow = sheet.CreateRow(rowIndex);

            foreach (DataColumn column in sourceTable.Columns)
            {
                dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
            }

            rowIndex++;
        }

        workbook.Write(memoryStream);
        memoryStream.Flush();
        memoryStream.Position = 0;

        return memoryStream;
    }
</pre>
<p>NOTE:  You could convert an entire workbook (multiple work sheets) into a new NPOI workbook if you looped over each work sheet in the XLSX document.  Since all my tools are based on using a single work sheet, I&#8217;ll leave the workbook conversion up to you.</p>
<h5>Example using XLSX function</h5>
<pre class="brush: csharp;">
            if (FileUpload.PostedFile.ContentLength &gt; 0)
            {
                Stream uploadFileStream = FileUpload.PostedFile.InputStream;

                // If the file uploaded is &quot;XLSX&quot;, convert it's Sheet1 to a NPOI document
                if (FileUpload.PostedFile.FileName.EndsWith(&quot;xlsx&quot;))
                {
                    uploadFileStream = ExcelHelper.ConvertXLSXWorksheetToXLSWorksheet(uploadFileStream, &quot;Sheet1&quot;);
                }
            }
</pre>
<p>** All your NPOI logic that adds columns, changes cell/row formatting, etc&#8230; will now work with the data extracted from the XLSX document.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/05/read-xlsx-data-for-npoi/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Use NPOI to populate an Excel template</title>
		<link>http://www.zachhunter.com/2010/05/npoi-excel-template/</link>
		<comments>http://www.zachhunter.com/2010/05/npoi-excel-template/#comments</comments>
		<pubDate>Fri, 07 May 2010 23:12:18 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=252</guid>
		<description><![CDATA[Create beautiful looking spreadsheets by creating templates to be populated with NPOI using C# and/or ASP.NET]]></description>
			<content:encoded><![CDATA[<p>So I&#8217;ve been using NPOI all week and decide to do a quick &#8220;demo&#8221; for my team today.  My demo was to show how to use NPOI to populate (update) an Excel template you&#8217;ve created.  Microsoft has a bunch of free &#8220;pretty&#8221; templates on their website, so I went and choose one with nice colors, formulas and a few charts.  It took me about an hour to build the complete demo.  It&#8217;s actually a very simple process and only took a few lines of code to update your template.</p>
<h4>Development Summary ( Step-by-Step )</h4>
<ol style="margin-left: 25px;">
<li>Get a template, I grabbed mine from here ( <a title="Office Templates - Event budget" href="http://office.microsoft.com/en-us/templates/TC103362741033.aspx?pid=CT101172321033" target="_blank">office.microsoft.com</a> ).<br />
** I only used the first sheet and deleted all the sample data</li>
<li>Create a new ASP.NET 3.5 Web Application projecct</li>
<li>Download <a title="NPOI 1.2.2 source and binary" href="http://npoi.codeplex.com/releases/view/19351" target="_blank">NPOI</a> binaries and include in your project</li>
<li>Build a UI that will be used to populate your template.<br />
** This could also be populated by a data sources (db, XML, etc..)<br />
** NOTE:  I used Excel to create the form using Excel formulas</li>
<li>Add some c# code &#8220;magic&#8221; to load data into the template using NPOI</li>
</ol>
<p>Sounds simple because it is&#8230; Here is the code to add the form contents into the Excel template.</p>
<pre class="brush: csharp;">
            // Open Template
            FileStream fs = new FileStream(Server.MapPath(@&quot;\template\Template_EventBudget.xls&quot;), FileMode.Open, FileAccess.Read);

            // Load the template into a NPOI workbook
            HSSFWorkbook templateWorkbook = new HSSFWorkbook(fs, true);

            // Load the sheet you are going to use as a template into NPOI
            HSSFSheet sheet = templateWorkbook.GetSheet(&quot;Event Budget&quot;);

            // Insert data into template
            sheet.GetRow(1).GetCell(1).SetCellValue(EventName.Value);  // Inserting a string value into Excel
            sheet.GetRow(1).GetCell(5).SetCellValue(DateTime.Parse(EventDate.Value));  // Inserting a date value into Excel

            sheet.GetRow(5).GetCell(2).SetCellValue(Double.Parse(Roomandhallfees.Value));  // Inserting a number value into Excel
            sheet.GetRow(6).GetCell(2).SetCellValue(Double.Parse(Sitestaff.Value));
            sheet.GetRow(7).GetCell(2).SetCellValue(Double.Parse(Equipment.Value));
            sheet.GetRow(8).GetCell(2).SetCellValue(Double.Parse(Tablesandchairs.Value));
            sheet.GetRow(12).GetCell(2).SetCellValue(Double.Parse(Flowers.Value));
            sheet.GetRow(13).GetCell(2).SetCellValue(Double.Parse(Candles.Value));
            sheet.GetRow(14).GetCell(2).SetCellValue(Double.Parse(Lighting.Value));
            sheet.GetRow(15).GetCell(2).SetCellValue(Double.Parse(Balloons.Value));
            sheet.GetRow(16).GetCell(2).SetCellValue(Double.Parse(Papersupplies.Value));
            sheet.GetRow(20).GetCell(2).SetCellValue(Double.Parse(Graphicswork.Value));
            sheet.GetRow(21).GetCell(2).SetCellValue(Double.Parse(Photocopying_Printing.Value));
            sheet.GetRow(22).GetCell(2).SetCellValue(Double.Parse(Postage.Value));
            sheet.GetRow(26).GetCell(2).SetCellValue(Double.Parse(Telephone.Value));
            sheet.GetRow(27).GetCell(2).SetCellValue(Double.Parse(Transportation.Value));
            sheet.GetRow(28).GetCell(2).SetCellValue(Double.Parse(Stationerysupplies.Value));
            sheet.GetRow(29).GetCell(2).SetCellValue(Double.Parse(Faxservices.Value));
            sheet.GetRow(33).GetCell(2).SetCellValue(Double.Parse(Food.Value));
            sheet.GetRow(34).GetCell(2).SetCellValue(Double.Parse(Drinks.Value));
            sheet.GetRow(35).GetCell(2).SetCellValue(Double.Parse(Linens.Value));
            sheet.GetRow(36).GetCell(2).SetCellValue(Double.Parse(Staffandgratuities.Value));
            sheet.GetRow(40).GetCell(2).SetCellValue(Double.Parse(Performers.Value));
            sheet.GetRow(41).GetCell(2).SetCellValue(Double.Parse(Speakers.Value));
            sheet.GetRow(42).GetCell(2).SetCellValue(Double.Parse(Travel.Value));
            sheet.GetRow(43).GetCell(2).SetCellValue(Double.Parse(Hotel.Value));
            sheet.GetRow(44).GetCell(2).SetCellValue(Double.Parse(Other.Value));
            sheet.GetRow(48).GetCell(2).SetCellValue(Double.Parse(Ribbons_Plaques_Trophies.Value));
            sheet.GetRow(49).GetCell(2).SetCellValue(Double.Parse(Gifts.Value));

            // Force formulas to update with new data we added
            sheet.ForceFormulaRecalculation = true;

            // Save the NPOI workbook into a memory stream to be sent to the browser, could have saved to disk.
            MemoryStream ms = new MemoryStream();
            templateWorkbook.Write(ms);

            // Send the memory stream to the browser
            ExportDataTableToExcel(ms, &quot;EventExpenseReport.xls&quot;);
</pre>
<p>Here are the screen shots of the form and completed template&#8230;</p>
<h6>Here is demo UI.</h6>
<p><a href="http://www.zachhunter.com/wp-content/uploads/NPOI_TemplateForm.gif"><img class="alignnone size-medium wp-image-248" title="NPOI - ASP.NET Form used to populate a Excel Template" src="http://www.zachhunter.com/wp-content/uploads/NPOI_TemplateForm-300x207.gif" alt="NPOI - ASP.NET Form used to populate a Excel Template" width="300" height="207" /></a></p>
<h6>Here is a populated template.</h6>
<p><a href="http://www.zachhunter.com/wp-content/uploads/NPOI_TemplateForm_Filled.gif"><img class="alignnone size-medium wp-image-249" title="NPOI - ASP.NET Form merged with Excel template" src="http://www.zachhunter.com/wp-content/uploads/NPOI_TemplateForm_Filled-208x300.gif" alt="NPOI - ASP.NET Form merged with Excel template" width="208" height="300" /></a></p>
<p>Here is a copy of the XLS file created in the program:  <a href="http://www.zachhunter.com/wp-content/uploads/NPOI_TemplateForm_Filled.xls">NPOI &#8211; ASP.NET Form merged with Excel template</a></p>
<p>Here is a copy of the source code for the demo:  <a href="http://www.zachhunter.com/wp-content/uploads/NPOI_TemplateDemo_VS2008.zip">NPOI &#8211; Visual Studio 2008 (ASP.NET 3.5) Template Merge Demo</a></p>
<p>Like all things, there is one catch.  During the demo I found a bug with NPOI opening my XLS file and I had to download the source code and make two changes to get NPOI to open my XLS template (bug states this issue is caused when you save a XLSX file as XLS in Excel 2007). Read <a href="http://npoi.codeplex.com/WorkItem/View.aspx?WorkItemId=5139">this post</a> to see the fix or use the DLLs for NPOI included in my demo project.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/05/npoi-excel-template/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>NPOI and the Excel 2003 row limit</title>
		<link>http://www.zachhunter.com/2010/05/npoi-excel-2003-row-limit/</link>
		<comments>http://www.zachhunter.com/2010/05/npoi-excel-2003-row-limit/#comments</comments>
		<pubDate>Thu, 06 May 2010 00:28:39 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=234</guid>
		<description><![CDATA[I ran into a problem today, testing my new NPOI DataTable web export function&#8230; While running some large queries that resulted in 65K+ rows of data, my function blew up. As you know, Excel 2003 and the BIFF format only support 65,536 rows! To make sure this never happens again, I&#8217;ve added a little block [...]]]></description>
			<content:encoded><![CDATA[<p>I ran into a problem today, testing my new NPOI DataTable web export function&#8230;  While running  some large queries that resulted in 65K+ rows of data, my function blew up.  As you know, Excel 2003 and the BIFF format only support 65,536 rows!  To make sure this never happens again, I&#8217;ve added a little block of code around my details loop to create an additional sheet every time you reach row 65,536.</p>
<h5>code excerpt based on using a DataTable as your data source</h5>
<pre class="brush: csharp;">
int rowIndex = 1;               // Starting Row (0 = Header)
int sheetIndex = 1;             // Starting sheet is always set to &quot;Sheet1&quot;
const int maxRows = 65536;      // Max rows p/sheet in Excel 2003

// Start loop of details to write to sheet
foreach (DataRow row in DataTableToExport.Rows)
{
	// Check if max rows hit, if so start new sheet and copy headers from current sheet.
	if(rowIndex % maxRows == 0)
	{
		// Auto size columns on current sheet
		for (int h = 0; h &lt; headerRow.LastCellNum; h++)
		{
			sheet.AutoSizeColumn(h);
		}

		// Increment sheet counter
		sheetIndex++;

		// Create new sheet
		sheet = workbook.CreateSheet(&quot;Sheet&quot; + sheetIndex);

		// Create header on new sheet
		HSSFRow additionalHeaderRow = sheet.CreateRow(0);

		// Copy headers from first sheet
		for (int h = 0; h &lt; headerRow.LastCellNum; h++)
		{
			HSSFCell additionalHeaderColumn = additionalHeaderRow.CreateCell(h);
			additionalHeaderColumn.CellStyle = headerRow.GetCell(h).CellStyle;
			additionalHeaderColumn.SetCellValue(headerRow.GetCell(h).RichStringCellValue);
		}

		rowIndex = 1;
	}

	// Create new detail row in sheet
	HSSFRow dataRow = sheet.CreateRow(rowIndex);
	// Loop the columns from the DataRow and add using dataRow.CreateCell(#)....
}
</pre>
<p>In a nutshell, I create some counters before going into the detail row loop to track the Row and Sheet number.  When I hit the max Row number number on a sheet, I create a new Sheet.  To keep everything pretty, I copy the header row from the first sheet to the first row of the new sheet.  The only output limitation now is the max sheets of 255.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/05/npoi-excel-2003-row-limit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Build beautiful XLS documents in .NET with NPOI</title>
		<link>http://www.zachhunter.com/2010/05/getting-started-with-npoi/</link>
		<comments>http://www.zachhunter.com/2010/05/getting-started-with-npoi/#comments</comments>
		<pubDate>Wed, 05 May 2010 00:50:59 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=222</guid>
		<description><![CDATA[I&#8217;ve seen Excel used for a ton of different solutions; Flow Charts, Business Forms, EDI, Photo Album, etc&#8230; Regardless of how Excel is being used, it&#8217;s one of the most common business document formats I know.  We commonly refer to Excel as duct tape, in the office.  I&#8217;ve traditionally limited my web &#38; Excel integration [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve seen Excel used for a ton of different solutions; Flow Charts, Business Forms, EDI, Photo Album, etc&#8230;  Regardless of how Excel is being used, it&#8217;s one of the most common business document formats I know.  We commonly refer to Excel as duct tape, in the office.   I&#8217;ve traditionally limited my web &amp; Excel integration to the capabilities of the  System.Data.OleDb namespace.  This has been a great solution, and when you can&#8217;t buy 3rd party controls or run code in full trust, it&#8217;s a proven solution.  This has solved 99% of my problems, but there&#8217;s always been a need to do a bit more than use Excel as a basic data source.  Fortunate for me, I found a trail of posts in StackOverflow that lead me to NPOI.  It is a .NET implementation of the <a title="Apache's POI Project Home Page" href="http://poi.apache.org/index.html" target="_blank">Apache POI Project</a>.   NPOI is a bit behind POI, but this amazing library gives you the ability to develop rich Excel with a easy to use API.</p>
<p>I&#8217;ve run into a few bugs since starting, but I found lots of posts on CodePlex where the project is hosted.  I&#8217;ve found that running 1.2.2 (alpha) solves a bunch of bugs I immediately found when running 1.2.1.  I downloaded the latest build from CodePlex, but it was still on a 1.2.1 branch and was missing some of the 1.2.2 fixes.</p>
<p>Now that we know what NPOI is going to provide us, lets go grab the files we&#8217;ll need to get started.</p>
<ol style="margin-left: 30px;">
<li>NPOI.Util Basic assistant class library</li>
<li>NPOI.POIFS OLE2 format read/write library</li>
<li>NPOI.DDF Drawing format read/write library</li>
<li>NPOI.SS Formula evaluation library</li>
<li>NPOI.HPSF Summary Information and Document Summary Information read/write library</li>
<li>NPOI.HSSF Excel BIFF format read/write library</li>
</ol>
<p>To keep the demo easy to follow and provide some good ways to refactor NPOI into your existing project, I&#8217;ve taken a old function that would output a DataTable to a HTML formatted document with an Excel (xls) extension.  This solution has worked for years, but every time you open one of these XLS files you get the following message  (&#8220;<em>The file you are trying to open &#8220;&#8221;, is in a different format than specified by the file extension.  Verify that the file is not corrupted and is from a trusted source before opening the file.  Do you want to open the file now?</em>&#8220;).   It&#8217;s a bit annoying and scary to the user, but this approach was used to solve the problem of Excel truncating leading zero&#8217;s in numeric data (e.g. 00002345).</p>
<h5>Before NPOI Function (DataTable to HTML document saved with a XLS extension)</h5>
<pre class="brush: csharp;">
    /// &lt;summary&gt;
    /// Exports a DataTable as a HTML formatted table and forces the results to be downloaded in a .HTM file.
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;dataTable&quot;&gt;DataTable&lt;/param&gt;
    /// &lt;param name=&quot;fileName&quot;&gt;Output File Name&lt;/param&gt;
    static public void DataTableToHtmlXLS(DataTable dataTable, string fileName)
    {
        //Add _response header
        HttpResponse response = HttpContext.Current.Response;
        response.Clear();
        response.ClearHeaders();
        response.AddHeader(&quot;content-disposition&quot;, string.Format(&quot;attachment;filename={0}.xls&quot;, fileName));
        response.ContentEncoding = Encoding.Default;
        response.Charset = String.Empty;
        response.ContentType = &quot;text/HTML&quot;;

        DataGrid dataGrid = new DataGrid();
        dataGrid.EnableViewState = false;
        dataGrid.DataSource = dataTable;
        dataGrid.DataBind();

        StringWriter sw = new StringWriter();
        HtmlTextWriter hw = new HtmlTextWriter(sw);

        dataGrid.RenderControl(hw);
        response.Write(sw.ToString());

        response.End();
    }
</pre>
<p><a href="http://www.zachhunter.com/wp-content/uploads/ErrorOpeningExcel_Non_POI.jpg"><img class="alignnone size-medium wp-image-224" title="Error opening HTML file saved as XLS" src="http://www.zachhunter.com/wp-content/uploads/ErrorOpeningExcel_Non_POI-300x116.jpg" alt="Error opening HTML file saved as XLS" width="300" height="116" /></a></p>
<p>** If you were to look at the the XLS file in notepad, you&#8217;d see the contents are HTML.</p>
<h5>NPOI Function (DataTable to Excel)</h5>
<pre class="brush: csharp;">
    /// &lt;summary&gt;
    /// Render DataTable to Excel File
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;sourceTable&quot;&gt;Source DataTable&lt;/param&gt;
    /// &lt;param name=&quot;fileName&quot;&gt;Destination File name&lt;/param&gt;
    public static void ExportDataTableToExcel(DataTable sourceTable, string fileName)
    {
        HSSFWorkbook workbook = new HSSFWorkbook();
        MemoryStream memoryStream = new MemoryStream();
        HSSFSheet sheet = workbook.CreateSheet(&quot;Sheet1&quot;);
        HSSFRow headerRow = sheet.CreateRow(0);

        // handling header.
        foreach (DataColumn column in sourceTable.Columns)
            headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);

        // handling value.
        int rowIndex = 1;

        foreach (DataRow row in sourceTable.Rows)
        {
            HSSFRow dataRow = sheet.CreateRow(rowIndex);

            foreach (DataColumn column in sourceTable.Columns)
            {
                dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
            }

            rowIndex++;
        }

        workbook.Write(memoryStream);
        memoryStream.Flush();

        HttpResponse response = HttpContext.Current.Response;
        response.ContentType = &quot;application/vnd.ms-excel&quot;;
        response.AddHeader(&quot;Content-Disposition&quot;, string.Format(&quot;attachment;filename={0}&quot;, fileName));
        response.Clear();

        response.BinaryWrite(memoryStream.GetBuffer());
        response.End();
    }
</pre>
<p>** Pretty simple right?  In my production code this is actually split into multiple functions so I can reuse the DataTable to Excel code.  The output of this function is a Excel 2003 (XLS) BIFF.</p>
<p>Now that we are using NPOI to create &#8220;real&#8221; XLS documents, we can do something cool like add formatting to our header row.</p>
<pre class="brush: csharp;">
        // handling header.
        foreach (DataColumn column in sourceTable.Columns)
        {
            // Create New Cell
            HSSFCell headerCell = headerRow.CreateCell(column.Ordinal);

            // Set Cell Value
            headerCell.SetCellValue(column.ColumnName);

            // Create Style
            HSSFCellStyle headerCellStyle = workbook.CreateCellStyle();
            headerCellStyle.FillForegroundColor = HSSFColor.AQUA.index;
            headerCellStyle.FillPattern = CellFillPattern.SOLID_FOREGROUND;

            // Add Style to Cell
            headerCell.CellStyle = headerCellStyle;
        }
</pre>
<p><a href="http://www.zachhunter.com/wp-content/uploads/AddingColorHeader_POI.jpg"><img class="alignnone size-medium wp-image-226" title="Adding Color Headers to POI Excel File" src="http://www.zachhunter.com/wp-content/uploads/AddingColorHeader_POI-300x137.jpg" alt="Adding Color Headers to POI Excel File" width="300" height="137" /></a></p>
<p>There is a million more formatting options possible and by the time you read this you should find a few more example on my site.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/05/getting-started-with-npoi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
