Reading Excel (.xls) Files with ADO.NET

Since Excel has an OleDB provider, we can use the OleDb function in ADO.NET to connect to Excel. However, this requires some preparation on the part of Excel. You might think that since Excel has rows and columns, we can use them and reference A1, B3, etc. We cannot (as far as I know). We have to resort to a different method. Excel has a so called “named range” that we can use. This named range becomes the equivalent of the table name when it is a real database. We also need to use the first Excel row as the column header. In my example loadable table, the first row contains Name | Name | Address | City | Status. Additional lines contain actual data.

To create a named range, select (highlight) the cells that you want to have in your “table”. Then select Insert | in the “Name” menu | Define. In the upper left corner of the dialog that appears, enter the name of your space. This will be the “table name” that you will use in your SQL SELECT statement. The name (full path) of the table is the data source in the connection string, as you will see in the following code. When you upload the files and open the worksheet we included, then select all the date cells. You will see “Addresses” on the left side of the formula bar in Excel. Addresses is the name I gave to my named area.

For this method to work, you need to follow the above two steps (named range and first row of column names). The rest is easy. Let’s look at the code. Aspx page (ExcelSelect.aspx) first. This is nothing special. Just two label checks and two DataGrids. Two labels are for displaying SQL SELECT statements for each DataGrid. I used two SELECT statements and two grids to show that we can work with a (properly configured) spreadsheet in the same way as with a database table.

 

<%@ Page Language="vb" AutoEventWireup="False" Src="ExcelSelect.aspx.vb" Inherits="ExcelSelect"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>ExcelSelect</title>
<meta name="GENERATOR" content="Microsoft Visual Studio.NET 7.0">
<meta name="CODE_LANGUAGE" content="Visual Basic 7.0">
<meta name=vs_defaultClientScript content="JavaScript">
<meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
</head>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<asp:Label ID="lblSql1" Runat="server" />
<asp:DataGrid ID="dtgAddresses1" Runat="server"
              HeaderStyle-BackColor="IndianRed"
              HeaderStyle-ForeColor="White"
              HeaderStyle-Font-Name="Verdana"
              HeaderStyle-Font-Size="10"
              ItemStyle-BackColor="Gainsboro"
              ItemStyle-Font-Name="Verdana"
              ItemStyle-Font-Size="10"
              CellPadding="4"
              GridLines="Both" />
<p></p>
<asp:Label ID="lblSql2" Runat="server" />
<asp:DataGrid ID="dtgAddresses2" Runat="server"
              HeaderStyle-BackColor="IndianRed"
              HeaderStyle-ForeColor="White"
              HeaderStyle-Font-Name="Verdana"
              HeaderStyle-Font-Size="10"
              ItemStyle-BackColor="Gainsboro"
              ItemStyle-Font-Name="Verdana"
              ItemStyle-Font-Size="10"
              CellPadding="4"
              GridLines="Both" />
</form>
</body>
</html>

Now let’s move on to the ExcelSelect.aspx.vb code-behind page. As you can see, we are using the OleDb Jet provider. It is important to note that the last parameter of the connection string is “Extended Properties = Excel 8.0; “is. You MUST enable this option. Actually the connection string is the only” tricky “part of this program. Once this is set up correctly, the rest of the path is to start the player and link the grid in the usual way. I defined the header text in the code. just so as not to print. You would not want this in a real application. The rest of the code speaks for itself.

 

Imports System
Imports System.Data
Imports System.Data.OleDb

Public Class ExcelSelect
Inherits System.Web.UI.Page

Protected dtgAddresses1 As System.Web.UI.WebControls.DataGrid
Protected dtgAddresses2 As System.Web.UI.WebControls.DataGrid
Protected lblSql1 As System.Web.UI.WebControls.Label
Protected lblSql2 As System.Web.UI.WebControls.Label

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim strConn As String = “Provider=Microsoft.Jet.OleDb.4.0;” _
& “data source=f:\inetpub\wwwroot\dotnetjohn\NameAndAddress.xls;” _
& “Extended Properties=Excel 8.0;”
‘First DataGrid
Dim objConn As New OleDbConnection(strConn)
Dim strSql As String = “Select LastName, FirstName, Address, City, State From Addresses”
lblSql1.Text = strSql
Dim objCmd As New OleDbCommand(strSql, objConn)
Try
objConn.Open()
dtgAddresses1.DataSource = objCmd.ExecuteReader()
dtgAddresses1.DataBind()
Catch exc As Exception
Response.Write(exc.ToString())
Finally
objConn.Dispose()
End Try
‘Second DataGrid
objConn = New OleDbConnection(strConn)
strSql = “Select * From Addresses Where State=’CA'”
lblSql2.Text = strSql
objCmd = New OleDbCommand(strSql, objConn)
Try
objConn.Open()
dtgAddresses2.DataSource = objCmd.ExecuteReader()
dtgAddresses2.DataBind()
Catch exc As Exception
Response.Write(exc.ToString())
Finally
objConn.Dispose()
End Try
End Sub

End Class

Okay, now you have it. You can read from Excel to .Net. There are obviously practical problems. Specifying named ranges is just as problematic as the first row of column headings. You will also receive an error if the user opened the workbook in write mode. But if you’re desperate and really need to read Excel spreadsheets, this is one way to do it and make them look professional.

You can download the code here. Remember that you will need to change the path in the connection string to where you will place the NameAndAddress.xls on your computer.