使用OleDB / Powershell从Excel电子表格的任何位置获取DataTable值

时间:2012-05-14 20:34:00

标签: excel powershell oledb

我有一个简单的业务要求来设计一个“名册”电子表格,可以通过powershell脚本读取,以提取下游流程的数据。电子表格包含一些标题,例如FirstName,LastName,Company,StartDate。这些标题从A1开始并继续到J1。电子表格是2007(xlsm)并包含1个带有格式化表格的工作表(DataTable?)。 DataTable的右侧是一些字段,如NumberOfRecords和ContactInfo。

只要DataTable是第一列/行,PowerShell脚本到目前为止工作正常。如果我要切换NumberOfRecords& ContactInfo字段位于上方或左侧,然后它会抛出整个记录读取顺序。

以下是当前脚本

function getData {
$excelPath = "c:\temp\Roster.xlsm"
$global:roster = @()

$conn = new-object System.Data.OleDb.OleDbConnection
$conn.ConnectionString = 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source='+$excelPath+';Extended Properties="Excel 12.0 Xml;HDR=YES";'

$cmd = new-object System.Data.OleDb.OleDbCommand("SELECT * FROM [Roster$] WHERE [Valid] = true",$conn)
$conn.open()

$reader = $cmd.ExecuteReader()
while ($reader.Read())
{
    $user = new-object object
    $user | add-member -MemberType NoteProperty -Name "FirstName" -Value $reader.item(1).ToString()
    $user | add-member -MemberType NoteProperty -Name "MName" -Value $reader.item(2).ToString()
    $user | add-member -MemberType NoteProperty -Name "LastName" -Value $reader.item(3).ToString()
    $user | add-member -MemberType NoteProperty -Name "Company" -Value $reader.item(6).ToString()
    $user | add-member -MemberType NoteProperty -Name $reader.GetName(8) -Value $reader.item(8).ToString()
    $global:roster += $user
}

$conn.close()

$global:roster | out-gridview
#
}

有什么办法可以直接引用这个DataTable吗?我知道在Excel 2010中将数据格式化为表格时,您可以为其命名(默认为Table1)。我能做一些像"SELECT Table1.* FROM [Roster$] WHERE [VALUE] = true" ??

这样的事情

我的目标是提供格式良好的电子表格,通过Powershell从格式化表格中提取数据。

1 个答案:

答案 0 :(得分:0)

我找到了解决方案,但它需要使用COM而不是OLEDB或ADO。我无法通过OLE在线找到任何解决方案来调用命名对象。这个解决方案有点好,因为我可以在工作表中的任何地方安排我的DataTable,但是我不太喜欢它,因为它需要安装Office,但基本上我可以通过创建Excel对象来调用对Named Table的引用然后在ActiveSheet上调用它的ListObjects。这将返回DataTable及其所有列/行/范围。我需要做的就是循环遍历每一行和每列以获取数据。

$excel = new-object -ComObject Excel.Application
$tmp = $excel.Workbooks.Open('c:\temp\Roster.xlsm')
$table = $excel.ActiveSheet.ListObjects | where-object { $_.DisplayName -eq "MyNamedRange" }    
$rows = $table.ListRows