<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Excel</title>
        <link>http://www.nimblecoder.com/blog/category/4.aspx</link>
        <description>Excel</description>
        <language>en-US</language>
        <copyright>Ryan Van Slooten</copyright>
        <generator>Subtext Version 2.1.1.1</generator>
        <item>
            <title>Macro Guidelines for Excel VBA Beginners</title>
            <link>http://nimblecoder.com/blog/archive/2008/05/27/macro-guidelines-for-excel-vba-beginners.aspx</link>
            <description>  &lt;p&gt;     I'm in the process of updating an Excel spreadsheet that is failing when it is running     inside of Internet Explorer. The issue is related to the ActiveSheet and other global     properties having a value of Nothing when the code is assuming they have valid references.     As I am going through this spreadsheet, I am noting a wide variety of programming     deficiencies and inefficiencies. Here is a list of some of the issues encountered:&lt;/p&gt;   &lt;blockquote&gt;     If you run spreadsheets under Internet Explorer, use     &lt;span style="font-weight:bold;"&gt;Application.ThisWorkbook&lt;/span&gt; and to ensure the browser     evaluates the reference correctly.&lt;/blockquote&gt;   &lt;blockquote&gt;     NOTE: This is not an exhaustive list, nor do I claim that the "Better" examples     are the best code example, but rather they are (hopefully) significant improvements     over the "Bad" examples. In many cases, I have kept the design of the bad example     so that you can see the differences however you should strive to completely refactor     the code if possible.&lt;/blockquote&gt;   &lt;ol&gt;     &lt;li&gt;       &lt;h3&gt;         Do not abuse the "With" statement in VBA.&lt;/h3&gt;       Some people like "With" and some people don't and I don't particularly care for       it. In particular, do not use nested "With" statements.       &lt;h4&gt;         Example of Bad Code&lt;/h4&gt;       &lt;pre class="vb" style="background-color: #ffdab9" name="code"&gt;' ... BAD EXAMPLE: DO NOT USE ...
With ActiveSheet
  With TestForm
    ' ...
  End With ' TestForm
End With ' ActiveSheet
' ... BAD EXAMPLE: DO NOT USE ...

&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;h3&gt;
        Avoid using the "Goto" statement in VBA.&lt;/h3&gt;
      "Goto" is almost always a bad idea and a sign of spaghetti code. There are very few cases were it is appropriate to use it -- very few cases!
      &lt;h4&gt;
        Example of Bad Code&lt;/h4&gt;
      &lt;pre class="vb" style="background-color: #ffdab9" name="code"&gt;' ... BAD EXAMPLE: DO NOT USE ...
For i = iHere To lRealLastRow Step 2
  BuildStr = "A" &amp;amp; i + 1
  Range(BuildStr).Select
  If Range(BuildStr).Value = "---" Then GoTo DoneWithNames
  SelectItemDlg.Items_List.AddItem Range(BuildStr).Text
Next

DoneWithNames:
' ... BAD EXAMPLE: DO NOT USE ...
&lt;/pre&gt;
      &lt;h4&gt;
        Example of Better Code (I still would have designed it differently)&lt;/h4&gt;
      &lt;pre class="vb" name="code"&gt;' ...
Dim MyCell As Range
For i = iHere To lRealLastRow Step 2
  Set MyCell = Cells(i + 1, 1)
  If MyCell.Value = "---" Then
    Exit For
  End If
  SelectItemDlg.Items_List.AddItem MyCell.Text
Next
' ...
&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;h3&gt;
        Avoid using the name of a Form inside the Form code&lt;/h3&gt;
      The current form is implied in the code. It is not necessary to use the form name to reference controls on the form. If you want to differeniate form controls, you can use the 'Me' keyword such as: Me.Hide
      &lt;h4&gt;
        Example of Bad Code&lt;/h4&gt;
      &lt;pre class="vb" style="background-color: #ffdab9" name="code"&gt;' ... BAD EXAMPLE: DO NOT USE ...
' This example is doubly bad because it uses the form name (ChartConfig)
' both explicitly and in a With statement
If ChartConfig.Variable1.Text = ChartConfig.Variable2.Text Then
    MsgBox "Variable1 cannot be same as Variable2. Please choose another variable type.", vbOKCancel

    'Turn off the Change effect on Variable2.
    changeCasevar = False
    With ChartConfig
        .Variable2.Text = ""
        .Variable2Desc.Text = ""
        .Variable2Uom.Text = ""
    End With
    'Turn back on the Change effect on Variable2.
    changeCasevar = True
    Exit Sub
    '
End If

' ... BAD EXAMPLE: DO NOT USE ...
&lt;/pre&gt;
      &lt;h4&gt;
        Example of Better Code (I still would have designed it differently)&lt;/h4&gt;
      &lt;pre class="vb" name="code"&gt;' ...
If Variable1.Text = Variable2.Text Then
    MsgBox "Variable1 cannot be same as Variable2. Please choose another variable type.", vbOKCancel

    'Turn off the Change effect on Variable2.
    changeCasevar = False

    Variable2.Text = ""
    Variable2Desc.Text = ""
    Variable2Uom.Text = ""

    'Turn back on the Change effect on Variable2.
    changeCasevar = True
    Exit Sub
End If

&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;h3&gt;
        Use Error Handling and Resume to restore Application.ScreenUpdating&lt;/h3&gt;
      &lt;h4&gt;
        Example of Bad Code&lt;/h4&gt;
      &lt;pre class="vb" style="background-color: #ffdab9" name="code"&gt;' ... BAD EXAMPLE: DO NOT USE ...
' There are quite a few global variables and a pass-by-reference
' boolean that should just be the function return value.
Application.ScreenUpdating = False

iOption = "Single"
x = ChartPicker.Input_Val_Text
Call CheckUserRangeInputsAndOutputs(iOption, OkToChart)
iOption = ""

If OkToChart = True Then
    With ChartConfig
        CreateChartingArrays
    End With
End If

Application.ScreenUpdating = True
' ... BAD EXAMPLE: DO NOT USE ...
  &lt;/pre&gt;
      &lt;h4&gt;
        Example of Better Code (I still would have designed it differently)&lt;/h4&gt;
      &lt;pre class="vb" name="code"&gt;' ...
  On Error GoTo ErrorHandler

  Application.ScreenUpdating = False

  If CheckUserRangeInputsAndOutputs("Single") Then
    ChartConfig.CreateChartingArrays
  End If

Exit_Handler:
  Application.ScreenUpdating = True
  Exit Sub

ErrorHandler:
  MsgBox "Error " &amp;amp; Err.Number &amp;amp; ": " &amp;amp; Err.Description
  Resume Exit_Handler

  &lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;h3&gt;
        Use If, Else If, and Else correctly.&lt;/h3&gt;
      &lt;h4&gt;
        Example of Bad Code&lt;/h4&gt;
      &lt;pre class="vb" style="background-color: #ffdab9" name="code"&gt;' ... BAD EXAMPLE: DO NOT USE ...
If TextBoxMinimum.Text = "" Then
  MsgBox "Must enter Minimum Value before proceeding", vbOK
  Result = False
  Exit Function
End If

If TextBoxMaximum.Text = "" Then
  MsgBox "Must enter Maximum Value before proceeding", vbOK
  Result = False
  Exit Function
End If
' ... BAD EXAMPLE: DO NOT USE ...
&lt;/pre&gt;
      &lt;h4&gt;
        Example of Better Code&lt;/h4&gt;
      &lt;pre class="vb" name="code"&gt;' ...
' For a explicit method, you can directly refer to the controls
Result = False
If Not IsNumeric(TextBoxMinimum.Text) Then
  MsgBox "Must enter Minimum Value before proceeding", vbOK
  TextBoxMinimum.SetFocus
ElseIf Not IsNumeric(TextBoxMaximum.Text) Then
  MsgBox "Must enter Maximum Value before proceeding", vbOK
  TextBoxMaximum.SetFocus
Else
  Result = True
End If

' If you can use a generic method, you can iterate through all of the controls
' There are obviously better ways of doing this, especially with .NET
Dim ValidateControl
Dim ControlList = Array(TextBox1, TextBox2, TextBox3)
For Each ValidateControl In ControlList
  If Input_Val_Text = Null Or Input_Val_Text = "" Then
    MsgBox "Must enter Value in " &amp;amp; ValidateControl.Name &amp;amp; " before proceeding", vbOK
    Result = False
    Exit Function
  End If
Next
&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;h3&gt;
        Avoid using the ActiveSheet, Range, Cells, and other global variables.&lt;/h3&gt;
      Rather than assuming a position, it is much better to set a variable to the desired
      Workbook, Worksheet, or Range.
      &lt;blockquote&gt;In particular, if there is any chance the spreadsheet might run under a browser,
      use &lt;span style="font-weight:bold;"&gt;Application.ThisWorkbook&lt;/span&gt; to ensure the browser
      evaluates the macro correctly.
      &lt;/blockquote&gt;
      &lt;h4&gt;
        Example of Bad Code&lt;/h4&gt;
      &lt;pre class="vb" style="background-color: #ffdab9" name="code"&gt;' ... BAD EXAMPLE: DO NOT USE ...
'NOTE: Arrays start with 1st position as "0", not "1"
'Thus ColLtrs(0) is not used but placed there as a spacer for letter to column alignment:
ColLtrs = Array("", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z")

With ActiveSheet
  Range(ColLtrs(iOutCol) &amp;amp; iOutRow).Select
    
  If UnitSystem = "Metric" Then
    iRow = ActiveCell.Row
    For i = iRow To iLastRow - 1
      currCell = ColLtrs(ActiveCell.Column) &amp;amp; i + 1

      If Range(currCell).Value &amp;lt;&amp;gt; "" Then
        'capture the value from original calculatated data
        Range(currCell).Select

        strOrigValueCell = ColLtrs(iResultsCol) &amp;amp; ActiveCell.Row
        Result = ConvertUom(Range(strOrigValueCell))
      End If
    Next i
  End If
End With
' ... BAD EXAMPLE: DO NOT USE ...
&lt;/pre&gt;
      &lt;h4&gt;
        Example of Better Code&lt;/h4&gt;
      &lt;pre class="vb" name="code"&gt;' ...
Dim mySheet As Worksheet
Dim Value As Variant

Set mySheet = ActiveSheet

For i = iRow To iLastRow - 1
  Value = mySheet.Cells(i, iOutCol).Value
  If Value &amp;lt;&amp;gt; "" Then
    Result = ConvertUom(UnitSystem, Value)
  End If
Next i

' To get a column letter/code, do not reinvent the wheel!
' Various functions from:
' http://www.dicks-blog.com/archives/2004/05/21/column-numbers-to-letters/

Function ColLetter(ColNumber As Long) As String
    On Error Resume Next
    ColLetter = Application.Substitute(Application.ConvertFormula("R1C" &amp;amp; ColNumber, xlR1C1, xlA1, 4), "1", "")
End Function

Function ColumnLetter(ByVal c As Long) As String
  Dim p As Long
  While c
    p = 1 + (c - 1) Mod 26
    c = (c - p) \ 26
    ColumnLetter = Chr$(64 + p) &amp;amp; ColumnLetter
  Wend
End Function
&lt;/pre&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;h3&gt;
        Avoid using .Select and moving selection in macros unless absolutely.&lt;/h3&gt;
      Do not change the current sheet or selection unless that is the intention of the macro.
      In general, don't mess with the user, flip sheets, or other heinous acts and 
      try to leave things the way you found them.
      &lt;h4&gt;
        Example of Bad Code&lt;/h4&gt;
      &lt;pre class="vb" style="background-color: #ffdab9" name="code"&gt;' ... BAD EXAMPLE: DO NOT USE ...
For i = 1 To 10
  Range("A" &amp;amp; i).Select
  ActiveCell.Value = "Row " &amp;amp; i
Next i
' ... BAD EXAMPLE: DO NOT USE ...
&lt;/pre&gt;
      &lt;h4&gt;
        Example of Better Code&lt;/h4&gt;
      &lt;pre class="vb" name="code"&gt;Dim iColumn As Long
Dim mySheet As Worksheet
Dim myRange As Range

iColumn = 1
Set mySheet = ActiveSheet

For iRow = 1 To 10
  Set rng = mySheet.Cells(iRow, iColumn)
  rng.Value = "Row " &amp;amp; iRow
Next iRow
&lt;/pre&gt;
    &lt;/li&gt;
  &lt;/ol&gt;&lt;img src="http://nimblecoder.com/blog/aggbug/68.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Van Slooten</dc:creator>
            <guid>http://nimblecoder.com/blog/archive/2008/05/27/macro-guidelines-for-excel-vba-beginners.aspx</guid>
            <pubDate>Tue, 27 May 2008 23:28:20 GMT</pubDate>
            <wfw:comment>http://nimblecoder.com/blog/comments/68.aspx</wfw:comment>
            <comments>http://nimblecoder.com/blog/archive/2008/05/27/macro-guidelines-for-excel-vba-beginners.aspx#feedback</comments>
            <wfw:commentRss>http://nimblecoder.com/blog/comments/commentRss/68.aspx</wfw:commentRss>
            <trackback:ping>http://nimblecoder.com/blog/services/trackbacks/68.aspx</trackback:ping>
        </item>
        <item>
            <title>Formatting XML in Excel/VB</title>
            <link>http://nimblecoder.com/blog/archive/2007/05/23/Formatting-XML-in-ExcelVB.aspx</link>
            <description>&lt;p&gt;I was working on a spreadsheet that submitted XML data to a web service and the XML that was being generated by the XmlDocument object was not very tidy. Normally with C# I use Tidy.NET to clean up the HTML or XML, but since this was being used in Excel I didn't want to have any external dependencies. I found the following code online and it seems to work pretty well:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Option&lt;/span&gt; Explicit

&lt;span class="rem"&gt;' http://www.vb-helper.com/howto_formatted_xml_document.html&lt;/span&gt;
&lt;span class="rem"&gt;' Add formatting to the document.&lt;/span&gt;
&lt;span class="kwrd"&gt;Public&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; FormatXmlDocument(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; xml_doc &lt;span class="kwrd"&gt;As&lt;/span&gt; DOMDocument)
    FormatXmlNode xml_doc.documentElement, 0
&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

&lt;span class="rem"&gt;' Add formatting to this element. Indent it and add a&lt;/span&gt;
&lt;span class="rem"&gt;' carriage return before its children. Then recursively&lt;/span&gt;
&lt;span class="rem"&gt;' format the children with increased indentation.&lt;/span&gt;
&lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; FormatXmlNode(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; node &lt;span class="kwrd"&gt;As&lt;/span&gt; IXMLDOMNode, _
                          &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; indent &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;)
&lt;span class="kwrd"&gt;Dim&lt;/span&gt; child &lt;span class="kwrd"&gt;As&lt;/span&gt; IXMLDOMNode
&lt;span class="kwrd"&gt;Dim&lt;/span&gt; text_only &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Boolean&lt;/span&gt;

    &lt;span class="rem"&gt;' Do nothing if this is a text node.&lt;/span&gt;
    &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;TypeOf&lt;/span&gt; node &lt;span class="kwrd"&gt;Is&lt;/span&gt; IXMLDOMText &lt;span class="kwrd"&gt;Then&lt;/span&gt; &lt;span class="kwrd"&gt;Exit&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="rem"&gt;' See if this node contains only text.&lt;/span&gt;
    text_only = &lt;span class="kwrd"&gt;True&lt;/span&gt;
    &lt;span class="kwrd"&gt;If&lt;/span&gt; node.hasChildNodes &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; child &lt;span class="kwrd"&gt;In&lt;/span&gt; node.childNodes
            &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Not&lt;/span&gt; (&lt;span class="kwrd"&gt;TypeOf&lt;/span&gt; child &lt;span class="kwrd"&gt;Is&lt;/span&gt; IXMLDOMText) &lt;span class="kwrd"&gt;Then&lt;/span&gt;
                text_only = &lt;span class="kwrd"&gt;False&lt;/span&gt;
                &lt;span class="kwrd"&gt;Exit&lt;/span&gt; &lt;span class="kwrd"&gt;For&lt;/span&gt;
            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
        &lt;span class="kwrd"&gt;Next&lt;/span&gt; child
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

    &lt;span class="rem"&gt;' Process child nodes.&lt;/span&gt;
    &lt;span class="kwrd"&gt;If&lt;/span&gt; node.hasChildNodes &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="rem"&gt;' Add a carriage return before the children.&lt;/span&gt;
        &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Not&lt;/span&gt; text_only &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            node.insertBefore _
                node.ownerDocument.createTextNode(vbCrLf), _
                node.FirstChild
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

        &lt;span class="rem"&gt;' Format the children.&lt;/span&gt;
        &lt;span class="kwrd"&gt;For&lt;/span&gt; &lt;span class="kwrd"&gt;Each&lt;/span&gt; child &lt;span class="kwrd"&gt;In&lt;/span&gt; node.childNodes
            FormatXmlNode child, indent + 2
        &lt;span class="kwrd"&gt;Next&lt;/span&gt; child
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

    &lt;span class="rem"&gt;' Format this element.&lt;/span&gt;
    &lt;span class="kwrd"&gt;If&lt;/span&gt; indent &amp;gt; 0 &lt;span class="kwrd"&gt;Then&lt;/span&gt;
        &lt;span class="rem"&gt;' Indent before this element.&lt;/span&gt;
        node.parentNode.insertBefore _
            node.ownerDocument.createTextNode(Space$(indent)), _
            node

        &lt;span class="rem"&gt;' Indent after the last child node.&lt;/span&gt;
        &lt;span class="kwrd"&gt;If&lt;/span&gt; &lt;span class="kwrd"&gt;Not&lt;/span&gt; text_only &lt;span class="kwrd"&gt;Then&lt;/span&gt; _
            node.appendChild _
                node.ownerDocument.createTextNode(Space$(indent))

        &lt;span class="rem"&gt;' Add a carriage return after this node.&lt;/span&gt;
        &lt;span class="kwrd"&gt;If&lt;/span&gt; node.nextSibling &lt;span class="kwrd"&gt;Is&lt;/span&gt; &lt;span class="kwrd"&gt;Nothing&lt;/span&gt; &lt;span class="kwrd"&gt;Then&lt;/span&gt;
            node.parentNode.appendChild _
                node.ownerDocument.createTextNode(vbCrLf)
        &lt;span class="kwrd"&gt;Else&lt;/span&gt;
            node.parentNode.insertBefore _
                node.ownerDocument.createTextNode(vbCrLf), _
                node.nextSibling
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;
&lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;&lt;img src="http://nimblecoder.com/blog/aggbug/25.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Van Slooten</dc:creator>
            <guid>http://nimblecoder.com/blog/archive/2007/05/23/Formatting-XML-in-ExcelVB.aspx</guid>
            <pubDate>Wed, 23 May 2007 15:23:57 GMT</pubDate>
            <wfw:comment>http://nimblecoder.com/blog/comments/25.aspx</wfw:comment>
            <comments>http://nimblecoder.com/blog/archive/2007/05/23/Formatting-XML-in-ExcelVB.aspx#feedback</comments>
            <wfw:commentRss>http://nimblecoder.com/blog/comments/commentRss/25.aspx</wfw:commentRss>
            <trackback:ping>http://nimblecoder.com/blog/services/trackbacks/25.aspx</trackback:ping>
        </item>
        <item>
            <title>C# Utility to export Excel Worksheet As ADO Recordset XML</title>
            <link>http://nimblecoder.com/blog/archive/2007/01/19/C-Utility-to-export-Excel-Worksheet-As-ADO-Recordset-XML.aspx</link>
            <description>I wrote a little VBA the other day to save an Excel Worksheet as an ADODB.Recordset XML file. I decided to see how hard it would be to do the exact same thing in C#. The idea is that I might start using &lt;a href="http://www.csscript.net/" title="C# Script"&gt;C# Script&lt;/a&gt; instead of JavaScript for little utilities in the future.

&lt;textarea name="code" class="c#" cols="60" rows="20"&gt;using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Runtime.InteropServices;

using ADODB;
using Excel;


namespace ExcelUtility
{
	class ExcelExport
	{
		public const string EXCEL_PROG_ID = "Excel.Application";

		public static Excel.Application ExcelApplication
		{
			get
			{
				Excel.Application app = null;

				try
				{
					// http://msmvps.com/blogs/pauldomag/archive/2006/03/15/86417.aspx
					app = Marshal.GetActiveObject(EXCEL_PROG_ID) as Excel.Application;
				}
				catch (Exception ex)
				{
					System.Diagnostics.Trace.WriteLine(ex.ToString());
				}

				if (app == null)
				{
					try
					{
						app = new Excel.ApplicationClass();
					}
					catch (Exception ex)
					{
						System.Diagnostics.Trace.WriteLine(ex.ToString());
					}
				}

				return app;
			}
		}

		public static System.Data.DataTable SaveWorksheetAsDataTable()
		{
			Excel.Application app = ExcelApplication;
			Excel.Workbook book = app.ActiveWorkbook as Excel.Workbook;
			Excel.Worksheet sheet = app.ActiveSheet as Excel.Worksheet;
			int col, colcount;
			int row, rowcount;

			if (sheet == null)
				return null;

			// Get the current sheet range
			Excel.Range range = sheet.Cells;
			colcount = sheet.UsedRange.Columns.Count;
			rowcount = sheet.UsedRange.Rows.Count;

			// Get the header row
			row = 1;
			System.Data.DataTable dt = new System.Data.DataTable(sheet.Name);
			for (col = 1; col &amp;lt;= colcount; ++col)
			{
				string text = (string)(range[row, col] as Excel.Range).Text;
				dt.Columns.Add(text, typeof(string));
			}

			// Get all of the data
			for (row = 2; row &amp;lt;= rowcount; ++row)
			{
				DataRow dr = dt.NewRow();
				for (col = 0; col &amp;lt; colcount; ++col)
				{
					string text = (string)(range[row, col + 1] as Excel.Range).Text;
					if (text.Length &amp;gt; 0)
						dr[col] = text;
				}
				dt.Rows.Add(dr);
			}

			// Save the data
			dt.WriteXml(book.Path + "\\" + sheet.Name + ".xml");

			// Clean up
			app = null;
			return dt;
		}

		public static ADODB.Recordset SaveWorksheetAsRecordset()
		{
			Excel.Application app = ExcelApplication;
			Excel.Worksheet sheet = app.ActiveSheet as Excel.Worksheet;
			int col, colcount;
			int row, rowcount;

			if (sheet == null)
				return null;

			// Get the current sheet range
			Excel.Range range = sheet.Cells;
			colcount = sheet.UsedRange.Columns.Count;
			rowcount = sheet.UsedRange.Rows.Count;

			// Get the header row
			row = 1;
			ADODB.Recordset rst = new ADODB.RecordsetClass();
			for (col = 1; col &amp;lt;= colcount; ++col)
			{
				string text = (string)(range[row, col] as Excel.Range).Text;
				rst.Fields.Append(text, ADODB.DataTypeEnum.adVarChar, 255, ADODB.FieldAttributeEnum.adFldMayBeNull, null);
			}
			rst.Open(null, null, CursorTypeEnum.adOpenUnspecified, LockTypeEnum.adLockUnspecified, -1);

			ADODB.Field[] fields = new ADODB.Field[colcount];
			for (col = 0; col &amp;lt; colcount; ++col)
				fields[col] = rst.Fields[col];

			// Get all of the data
			for (row = 2; row &amp;lt;= rowcount; ++row)
			{
				rst.AddNew(null, null);
				for (col = 0; col &amp;lt; colcount; ++col)
				{
					string text = (string)(range[row, col + 1] as Excel.Range).Text;
					if (text.Length &amp;gt; 0)
						fields[col].Value = text;
				}
				rst.Update(null, null);
			}

			// Save the data
			string filename = book.Path + "\\" + sheet.Name + ".xml";
			rst.Save(filename, PersistFormatEnum.adPersistXML);

			// Clean up
			app = null;
			return dt;
		}
	}
}
&lt;/textarea&gt;&lt;img src="http://nimblecoder.com/blog/aggbug/3.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Van Slooten</dc:creator>
            <guid>http://nimblecoder.com/blog/archive/2007/01/19/C-Utility-to-export-Excel-Worksheet-As-ADO-Recordset-XML.aspx</guid>
            <pubDate>Fri, 19 Jan 2007 13:52:36 GMT</pubDate>
            <wfw:comment>http://nimblecoder.com/blog/comments/3.aspx</wfw:comment>
            <comments>http://nimblecoder.com/blog/archive/2007/01/19/C-Utility-to-export-Excel-Worksheet-As-ADO-Recordset-XML.aspx#feedback</comments>
            <wfw:commentRss>http://nimblecoder.com/blog/comments/commentRss/3.aspx</wfw:commentRss>
            <trackback:ping>http://nimblecoder.com/blog/services/trackbacks/3.aspx</trackback:ping>
        </item>
        <item>
            <title>Export Excel Worksheet to ADO Recordset</title>
            <link>http://nimblecoder.com/blog/archive/2007/01/15/2.aspx</link>
            <description>This weekend I was working on a spreadsheet and I needed to save the data as a recordset. Unfortunately there didn't seem to be a way to do it easily without VBA macros. So I wrote this macro to save the current worksheet as an ADODB.Recordset XML file. Remember to add a reference to &lt;span style="font-family: Courier New;"&gt;Microsoft.ActiveX Data Object 2.8 Library&lt;/span&gt; in the Excel Visual Basic Editor.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea name="code" class="vb" cols="60" rows="10"&gt;  
Public Sub CreateAdoRecordsetXml()
    Dim rst As New ADODB.Recordset
    Dim sheet As Worksheet
    Dim col As Long, colcount As Long
    Dim row As Long, rowcount As Long
    Dim Filename As String

    Filename = ActiveWorkbook.Path + "\" + ActiveSheet.Name + ".xml"
    Set sheet = ActiveSheet
    colcount = sheet.UsedRange.Columns.count
    rowcount = sheet.UsedRange.Rows.count

    col = 1
    row = 1
    Do While col &amp;lt;= colcount
        Call rst.Fields.Append(sheet.Cells(row, col).Text, adVarChar, 255, adFldMayBeNull)
        col = col + 1
    Loop
    rst.Open

    row = 2
    Do While row &amp;lt;= rowcount
        col = 1
        Call rst.AddNew
        With rst.Fields
            Do While col &amp;lt;= colcount
                If sheet.Cells(row, col).Text &amp;lt;&amp;gt; "" Then
                    .Item(col - 1).Value = sheet.Cells(row, col).Text
                End If
                col = col + 1
            Loop
        End With
        Call rst.Update
        row = row + 1
    Loop

    Call rst.Save(Filename, adPersistXML)
End Sub
&lt;/textarea&gt;&lt;img src="http://nimblecoder.com/blog/aggbug/2.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Ryan Van Slooten</dc:creator>
            <guid>http://nimblecoder.com/blog/archive/2007/01/15/2.aspx</guid>
            <pubDate>Mon, 15 Jan 2007 18:22:28 GMT</pubDate>
            <wfw:comment>http://nimblecoder.com/blog/comments/2.aspx</wfw:comment>
            <comments>http://nimblecoder.com/blog/archive/2007/01/15/2.aspx#feedback</comments>
            <wfw:commentRss>http://nimblecoder.com/blog/comments/commentRss/2.aspx</wfw:commentRss>
            <trackback:ping>http://nimblecoder.com/blog/services/trackbacks/2.aspx</trackback:ping>
        </item>
    </channel>
</rss>