{"id":55093,"date":"2008-09-12T02:23:00","date_gmt":"2008-09-12T02:23:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2008\/09\/12\/hey-scripting-guy-how-can-i-read-from-excel-without-using-excel\/"},"modified":"2008-09-12T02:23:00","modified_gmt":"2008-09-12T02:23:00","slug":"hey-scripting-guy-how-can-i-read-from-excel-without-using-excel","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-read-from-excel-without-using-excel\/","title":{"rendered":"Hey, Scripting Guy! How Can I Read from Excel Without Using Excel?"},"content":{"rendered":"<p><span class=\"Apple-style-span\"><\/p>\n<h2><font class=\"Apple-style-span\" face=\"Verdana\" size=\"3\"><span class=\"Apple-style-span\"><font class=\"Apple-style-span\" face=\"Arial\" size=\"6\"><span class=\"Apple-style-span\"><\/span><\/font><\/span><\/font><\/h2>\n<div><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\" \/> <\/p>\n<p>Hey, Scripting Guy! I have an Microsoft Office Excel spreadsheet with server names in it, and I would like to be able to use this in a Windows PowerShell script. The thing is, I do not have Microsoft Office or Excel installed on the server. How can I use this spread sheet without installing Office on my server (which I understand is unsupported anyway)?<\/p>\n<p>&#8211; FE<\/p>\n<p><img decoding=\"async\" height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\" \/><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\" \/> <\/p>\n<p>Hi FE,<\/p>\n<p>So you want to be able to use Excel, but you do not want to install Excel? Sounds like one of those riddles I heard when I was a kid. You know those things like, &#8220;If you take a red crayon and color all the pages in the book so that no one can see any of the writing, is it a red book?&#8221; (Or is it a read book? Homophones can be so confusing. Especially triple homophones such as: so, sew, sow. This is cool: I just figured out that Microsoft Word seems to hate homophones, it is underlining all kinds of stuff with squiggly lines write now.&nbsp;<a href=\"http:\/\/www.bifroest.demon.co.uk\/misc\/homophones-list.html\" target=\"_blank\">One guy on the Web<\/a>&nbsp;has collected 441 of the things; one nicety about such a collection is that it does not occupy as much space as a book collection or a car collection.)<\/p>\n<p>Often when working with Excel from within a scripting language, we tend to use the&nbsp;<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb149081.aspx\" target=\"_blank\">Excel Automation Model<\/a>. Using the Excel Automation Model generally involves creating an instance of the&nbsp;<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb149137.aspx\" target=\"_blank\">Excel.Application<\/a>&nbsp;object. This would look something like the script seen&nbsp;here: <\/p>\n<pre class=\"codeSample\">$strPath=\"c:\\data\\ScriptingGuys\\Servers.xls\"\n$objExcel=New-Object -ComObject Excel.Application\n$objExcel.Visible=$false\n$WorkBook=$objExcel.Workbooks.Open($strPath)\n$worksheet = $workbook.sheets.item(\"ServerList\")\n$intRowMax =  ($worksheet.UsedRange.Rows).count\n$Columnnumber = 1\n\nfor($intRow = 2 ; $intRow -le $intRowMax ; $intRow++)\n{\n $name = $worksheet.cells.item($intRow,$ColumnNumber).value2\n \"Querying $name ...\"\n  Get-WmiObject -Class win32_bios -computername $name\n   }\n$objexcel.quit()\n<\/pre>\n<p>But, FE, you specifically stated you did not want to use the Excel object model to query the spread sheet. You are then left with using Active X Data Objects (ADO). There are two flavors of ADO: the classic COM ADO you may have used in VBScript, and ADO.NET. In general, the ADO.NET flavor is faster and provides more options. With both the COM version of ADO and ADO.NET you will need to specify a provider. In some cases, these provider names will be the same. In other cases, you will find providers for a specific flavor of ADO.<\/p>\n<p>In the script we create two objects. The first is the&nbsp;<b>System.Data.OleDb.OleDbConnection<\/b>&nbsp;object and the second is the<b>System.Data.OleDb.OleDbCommand<\/b>&nbsp;object. You will note that both of the objects are in the&nbsp;<b>System.Data.OleDb<\/b>&nbsp;namespace. Only the last portion of each name actually changes. These correspond to the connection and the command object we used in classic COM ADO. After the two objects are created, we associate the connection with the command object, open the connection, and use the<b>ExecuteReader<\/b>&nbsp;method from the command object. We then use the data reader to work our way through the data that is returned. We select the&nbsp;<b>name<\/b>&nbsp;column, pass it to WMI, and close both data reader and connection. The script is shown&nbsp;here: <\/p>\n<pre class=\"codeSample\">$strFileName = \"C:\\Data\\scriptingGuys\\Servers.xls\"\n$strSheetName = 'ServerList$'\n$strProvider = \"Provider=Microsoft.Jet.OLEDB.4.0\"\n$strDataSource = \"Data Source = $strFileName\"\n$strExtend = \"Extended Properties=Excel 8.0\"\n$strQuery = \"Select * from [$strSheetName]\"\n\n$objConn = New-Object System.Data.OleDb.OleDbConnection(\"$strProvider;$strDataSource;$strExtend\")\n$sqlCommand = New-Object System.Data.OleDb.OleDbCommand($strQuery)\n$sqlCommand.Connection = $objConn\n$objConn.open()\n$DataReader = $sqlCommand.ExecuteReader()\n\nWhile($DataReader.read())\n{\n $ComputerName = $DataReader[0].Tostring() \n \"Querying $computerName ...\"\n Get-WmiObject -Class Win32_Bios -computername $ComputerName\n}  \n$dataReader.close()\n$objConn.close()\n<\/pre>\n<p>Let&#8217;s look at the script in a bit more detail. We begin the script by initializing a bunch of variables. The first is the path to the Excel spread sheet. (Note: We do not test to ensure this path actually exists. We left it out to reduce the complexity of the script. In a real script you would certainly want to verify the presence of the file before attempting to read the file. To do this in PowerShell you would use the&nbsp;<a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/bb978701.aspx\" target=\"_blank\">Test-Path<\/a>&nbsp;cmdlet.) We then specify the sheet name. As seen in this figure, I always like to rename the Excel spreadsheets (I also delete the two extra sheets that I never seem to use as well):<\/p>\n<p><img decoding=\"async\" height=\"375\" alt=\"Excel spreadsheet graphic\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/hey0911\/excelservers.jpg\" width=\"500\" border=\"0\" \/> <\/p>\n<p>&nbsp;<\/p>\n<p>Next we need to specify the provider name, data source, and extended parameters for our connection. These are exactly the same as you would have used in classic COM ADO. Last, we need to specify our query. This takes the form of&nbsp;<b>&#8220;Select * from [sheetname]&#8221;<\/b>. Note that the spreadsheet name must go inside square brackets (square brackets, not square pants). This section of the script is shown&nbsp;here: <\/p>\n<pre class=\"codeSample\">$strFileName = \"C:\\Data\\scriptingGuys\\Servers.xls\"\n$strSheetName = 'ServerList$'\n$strProvider = \"Provider=Microsoft.Jet.OLEDB.4.0\"\n$strDataSource = \"Data Source = $strFileName\"\n$strExtend = \"Extended Properties=Excel 8.0\"\n$strQuery = \"Select * from [$strSheetName]\"\n<\/pre>\n<p>The next thing we need to do is to create the two objects we will be using. When we create the&nbsp;<b>OleDbConnection<\/b>&nbsp;object we specify the provider, data source, and the extended parameters to the&nbsp;<b>New-Object<\/b>&nbsp;command. These values are called the constructor as it is used in constructing the&nbsp;<b>connection<\/b>&nbsp;object. Next we need to create the&nbsp;<b>command<\/b>&nbsp;object. The&nbsp;<b>OleDbCommand<\/b>&nbsp;object accepts the query for its constructor. After we have these two objects created, we need to wire up the connection and the command, open the connection, and use the&nbsp;<b>ExecuteReader<\/b>&nbsp;method from the&nbsp;<b>OleDbCommand<\/b>&nbsp;object to return our information. This section of the code is shown&nbsp;here: <\/p>\n<pre class=\"codeSample\">$objConn = New-Object System.Data.OleDb.OleDbConnection ` (\"$strProvider;$strDataSource;$strExtend\")\n$sqlCommand = New-Object System.Data.OleDb.OleDbCommand($strQuery)\n$sqlCommand.Connection = $objConn\n$objConn.open()\n$DataReader = $sqlCommand.ExecuteReader()\n<\/pre>\n<p>The object that comes back from the&nbsp;<b>ExecuteReader<\/b>&nbsp;method is called a DataReader. To work with a DataReader, we need to use the<b>Read<\/b>&nbsp;method. We use the&nbsp;<b>While<\/b>&nbsp;statement that says as long as the DataReader is returning data, we will keep on reading. This line of code is shown here:<\/p>\n<pre class=\"codeSample\">While($DataReader.read())<\/pre>\n<p>Well, what are we going to do while we have data coming from the DataReader? We are going to take the first piece of data and turn it into a string. This will be our computer name from the spreadsheet. We then use it in a basic WMI query. To do the WMI query, we use the&nbsp;<b>Get-WmiObject<\/b>&nbsp;cmdlet and give it the WMI class to&nbsp;<b>query (Win32_Bios)<\/b>&nbsp;and the name of the computer to query (the one from the spreadsheet). This is seen&nbsp;here: <\/p>\n<pre class=\"codeSample\">$ComputerName = $DataReader[0].Tostring() \n \"Querying $computerName ...\"\n Get-WmiObject -Class Win32_Bios -computername $ComputerName\n<\/pre>\n<p>To be polite, we close out the DataReader, and we close our connection to the Excel spreadsheet. This is easy to do; we use the&nbsp;<b>close<\/b>method as shown&nbsp;here: <\/p>\n<pre class=\"codeSample\">$dataReader.close()\n$objConn.close()\n<\/pre>\n<p>The results from this script are impressive because of the minimalistic approach to data return. With our background, we are trying to exhaust the blues whilst understating the induction of white (for all you art majors). This can clearly be seen in this figure:<\/p>\n<p><img decoding=\"async\" height=\"375\" alt=\"Query Excel results graphic\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/hey0911\/queryexcelresults.jpg\" width=\"500\" border=\"0\" \/> <\/p>\n<p>&nbsp;<\/p>\n<p>See, FE, that was not too bad was it? This is just half of the equation. If we happen to have an Excel spreadsheet handy, we can use this method to query it. However, if you do not have one handy, we will need to write to the spreadsheet and populate it with data. We will do that next week. Until then, TTFN.<\/p>\n<p><font class=\"Apple-style-span\" face=\"Verdana\" size=\"3\"><span class=\"Apple-style-span\"><b><b>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/b><\/b><\/span><\/font><\/p>\n<p><font class=\"Apple-style-span\" face=\"Verdana\" size=\"3\"><b><\/b><\/font><\/div>\n<p><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I have an Microsoft Office Excel spreadsheet with server names in it, and I would like to be able to use this in a Windows PowerShell script. The thing is, I do not have Microsoft Office or Excel installed on the server. How can I use this spread sheet without installing Office [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[19,727,146,48,49,3,45],"class_list":["post-55093","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-activex-data-objects-ado","tag-ado-net","tag-databases","tag-microsoft-excel","tag-office","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I have an Microsoft Office Excel spreadsheet with server names in it, and I would like to be able to use this in a Windows PowerShell script. The thing is, I do not have Microsoft Office or Excel installed on the server. How can I use this spread sheet without installing Office [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/55093","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=55093"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/55093\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=55093"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=55093"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=55093"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}