PowerShell中对比两个工作表数据:如何定位特定值单元格后的数据?
手动操作Excel对象实现跨工作表数据库大小对比方案
核心思路
通过PowerShell调用Excel COM对象,遍历工作表行识别服务器分组,提取每组下的数据库大小数据,再跨工作表做存在性校验与百分比差异计算。
1. 初始化Excel对象并加载目标工作簿
先创建Excel后台实例,打开报表文件并指定要对比的两张工作表:
# 启动Excel后台进程(不显示界面) $excel = New-Object -ComObject Excel.Application $excel.Visible = $false # 打开目标报表文件(替换为你的文件路径) $workbook = $excel.Workbooks.Open("C:\Reports\Daily_Server_Stats.xlsx") # 获取两张对比工作表 $sheetLatest = $workbook.Worksheets.Item("2020-08-10") $sheetEarliest = $workbook.Worksheets.Item("2020-08-08")
2. 编写数据提取函数(适配分组布局)
由于服务器分组位置不固定,通过遍历行识别服务器标识,再收集后续的数据库数据(需根据你的报表格式调整判断规则):
function Get-DatabaseData { param([__ComObject]$Worksheet) $dbData = @{} $currentServer = $null $usedRows = $Worksheet.UsedRange.Rows.Count for ($row = 1; $row -le $usedRows; $row++) { $cellText = $Worksheet.Cells.Item($row, 1).Text.Trim() # 识别服务器行(示例规则:单元格内容以"Server:"开头,自行修改匹配逻辑) if ($cellText -match "^Server: (.+)$") { $currentServer = $matches[1] $dbData[$currentServer] = @{} continue } # 收集当前服务器下的数据库数据(示例:第1列是"Database",第2列是库名,第3列是百分比) if ($currentServer -and $cellText -eq "Database") { $dbName = $Worksheet.Cells.Item($row, 2).Text.Trim() # 去除%符号并转为数值类型 $dbSizePct = [double]$Worksheet.Cells.Item($row, 3).Text.Trim().Replace("%", "") $dbData[$currentServer][$dbName] = $dbSizePct } } return $dbData }
注意:如果报表里有合并单元格,读取内容时要改用$Worksheet.Cells.Item($row,1).MergeArea.Cells.Item(1,1).Text
3. 提取数据并执行对比校验
调用函数获取两张表的数据,遍历服务器和数据库,完成存在性校验与差异计算:
# 提取两张表的数据库统计数据 $latestData = Get-DatabaseData -Worksheet $sheetLatest $earliestData = Get-DatabaseData -Worksheet $sheetEarliest # 输出对比结果 Write-Host "=== 数据库大小百分比差异对比结果 ===" foreach ($server in $latestData.Keys) { Write-Host "`n【服务器】$server" # 检查最新表的数据库在最早表中是否存在 foreach ($dbName in $latestData[$server].Keys) { if (-not $earliestData.ContainsKey($server) -or -not $earliestData[$server].ContainsKey($dbName)) { Write-Host " ⚠️ 数据库 $dbName 在2020-08-08报表中不存在" continue } $latestPct = $latestData[$server][$dbName] $earliestPct = $earliestData[$server][$dbName] $diff = [math]::Round($latestPct - $earliestPct, 2) Write-Host " 数据库: $dbName | 08-08: $earliestPct% | 08-10: $latestPct% | 差异: $diff%" } # 检查最早表的数据库在最新表中是否存在 if ($earliestData.ContainsKey($server)) { foreach ($dbName in $earliestData[$server].Keys) { if (-not $latestData[$server].ContainsKey($dbName)) { Write-Host " ⚠️ 数据库 $dbName 在2020-08-10报表中不存在" } } } }
4. 清理Excel进程(避免残留)
操作完成后务必释放COM对象,防止后台Excel进程残留:
# 关闭工作簿(不保存更改) $workbook.Close($false) $excel.Quit() # 释放COM资源 [System.Runtime.Interopservices.Marshal]::ReleaseComObject($sheetLatest) | Out-Null [System.Runtime.Interopservices.Marshal]::ReleaseComObject($sheetEarliest) | Out-Null [System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook) | Out-Null [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel) | Out-Null [System.GC]::Collect() [System.GC]::WaitForPendingFinalizers()
内容的提问来源于stack exchange,提问作者Jurm
相关产品推荐
相关产品推荐

