如何在PowerShell中读取Excel?解决旧格式报错并实现只读单元格读取
解决PowerShell读取Excel报错并实现只读读取单元格(保留行结构)
这个报错我之前也碰到过,大概率是旧版.xls文件和当前Office组件的兼容性问题,或者是32/64位PowerShell与Office不匹配导致的。下面给你几个实用的解决方案,都能帮你只读读取单元格内容并保留原始行结构:
方案1:使用ImportExcel模块(推荐,简单高效)
这个PowerShell模块专门处理Excel文件,无需依赖Excel COM对象,操作更简洁,还不会锁定文件。
- 先安装模块(首次使用时):
Install-Module -Name ImportExcel -Scope CurrentUser
- 读取文件并保留行结构:
# 如果文件有表头,直接用下面的命令,会自动把表头作为属性名 $excelData = Import-Excel -Path "c:\users\administrator\my_test.xls" # 如果不需要识别表头,想完全保留原始行的索引结构,加上`-NoHeader`参数 $excelData = Import-Excel -Path "c:\users\administrator\my_test.xls" -NoHeader
读取后$excelData是一个对象数组,每一个元素对应Excel的一行,直接遍历就能获取每行的单元格内容。
方案2:调整COM对象参数解决兼容性问题
如果必须用Excel COM对象,你可以修改打开参数,添加只读设置并兼容旧版格式:
# 创建Excel应用对象,后台运行不显示窗口 $excel = New-Object -ComObject Excel.Application $excel.Visible = $false $excel.DisplayAlerts = $false # 关闭兼容性警告 # 打开文件时指定只读、忽略只读推荐,同时启用旧版格式兼容 $wb = $excel.Workbooks.Open( "c:\users\administrator\my_test.xls", $null, # UpdateLinks $true, # ReadOnly(关键:只读模式打开) $null, # Format $null, # Password $null, # WriteResPassword $true, # IgnoreReadOnlyRecommended $null, # Origin $null, # Delimiter $false, # Editable $false, # Notify $null, # Converter $true # AddToMru(启用旧格式兼容) ) # 获取第一个工作表 $ws = $wb.Worksheets.Item(1) $rowCount = $ws.UsedRange.Rows.Count $colCount = $ws.UsedRange.Columns.Count # 循环读取每一行,保存为二维数组保留行结构 $excelData = @() for ($i=1; $i -le $rowCount; $i++) { $currentRow = @() for ($j=1; $j -le $colCount; $j++) { $currentRow += $ws.Cells.Item($i, $j).Value2 # Value2比Value更高效 } $excelData += ,$currentRow # 逗号确保行数组作为单个元素存入 } # 务必释放COM对象,避免Excel进程残留 $wb.Close($false) $excel.Quit() [System.Runtime.Interopservices.Marshal]::ReleaseComObject($ws) | Out-Null [System.Runtime.Interopservices.Marshal]::ReleaseComObject($wb) | Out-Null [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel) | Out-Null [System.GC]::Collect() [System.GC]::WaitForPendingFinalizers()
方案3:使用OLEDB读取(无需安装Excel)
如果你的环境没有安装Office,可以用ACE驱动通过OLEDB读取,同样支持只读操作:
- 先确保安装了Microsoft Access Database Engine 2010 Redistributable(支持读取旧版
.xls文件) - 执行读取代码:
# 构建连接字符串,指定只读和旧版Excel格式 $connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\users\administrator\my_test.xls;Extended Properties='Excel 8.0;HDR=No;ReadOnly=Yes'" $conn = New-Object System.Data.OleDb.OleDbConnection($connectionString) $conn.Open() # 查询第一个工作表(Sheet1改成你实际的工作表名,后面要加$) $cmd = $conn.CreateCommand() $cmd.CommandText = "SELECT * FROM [Sheet1$]" $adapter = New-Object System.Data.OleDb.OleDbDataAdapter($cmd) $dt = New-Object System.Data.DataTable $adapter.Fill($dt) $conn.Close() # 把DataTable转换成数组,保留行结构 $excelData = $dt | ForEach-Object { $_.ItemArray }
内容的提问来源于stack exchange,提问作者MUY Belgium




