我试图清理我的数据。我已经看到了关于这个主题的一些内容。我已经关注并应用了这些示例,但我的脚本似乎出现了问题。
我想要做的是删除整行。 column为null。当我运行我的脚本时,只有一半的行没有空。列已删除。在完全删除所有空行之前,我必须多次运行我的脚本。删除PowerShell中的行是否有限制,或者我遗漏了什么?这是我的剧本:
#cleanup
$max = $sheet.UsedRange.Rows.Count
for ($i = 6; $i -le $max; $i++) {
if ($sheet.Cells.Item($i, 1).Text -eq "") {
$Range = $sheet.Cells.Item($i, 1).EntireRow
$Range.Delete()
}
}
更新 为了解决删除问题,我添加了$ i = $ i - 1 ..现在我必须找到一种方法来停止循环
for ($i = 6; $i -le $row; $i++) {
If ($Sheet.Cells.Item($i, 1).text -eq "") {
$Range = $Sheet.Cells.Item($i, 1).EntireRow
[void]$Range.Delete()
$i = $i - 1
}
}
答案 0 :(得分:1)
如果您要删除"转发"每次删除行时,for
循环都会跳过一行。如果删除行n,则前一行n + 1现在变为行n。但是,由于索引会自动递增,因此您将在下一次迭代中转到新行n + 1(前一行n + 2),从而跳过前一行n + 1(新行n)。
示例:强>
考虑使用这样的表(第一列是行号):
┌────────── 1 │ A ├────────── 2 │ B ├────────── 3 │ C ├──────────
和for
这样的循环:
for ($i=1; $i -le 2; $i++) {
$sheet.Rows.Item($i).Delete()
}
在第一次迭代中,$i
的值为1,因此它指向第1行:
┏━━━━━━━━━━ 1 ┃ A ┡━━━━━━━━━━ 2 │ B ├────────── 3 │ C ├──────────
通过删除该行,后续行向上移动,因此表格变为如此(在第一次迭代结束时):
┌────────── 1 │ B ├────────── 2 │ C ├──────────
第二行现在已成为第一行。但是,当进入下一次迭代时,变量$i
会增加到2,所以它现在指向第2行(前第三行):
┌────────── 1 │ B ← skipped this row ┢━━━━━━━━━━ 2 ┃ C ┡━━━━━━━━━━
你可以从底行开始回到前面来避免这种影响:
$max = $sheet.UsedRange.Rows.Count
for ($i = $max; $i -ge 6; $i--) {
if ($sheet.Cells.Item($i, 1).Text -eq '') {
$Range = $sheet.Rows.Item($i).Delete()
}
}
请注意.UsedRange.Rows.Count
不一定会为您提供最后一行的编号。如果在第一个使用的行之前有空行,则需要将它们的数字作为偏移量添加到使用范围中的行数:
$max = $sheet.UsedRange.Rows.Count + $sheet.UsedRange.Row - 1
答案 1 :(得分:0)
为了解决上面的问题,我使用了一个向后的for循环而不是一个forward for循环。感谢@RonRosenfeld的想法.. @AngarWiechers给出了一个非常有见地的解释为什么使用正向循环是不合适的。他的回答只需要一点调整。设置$ i -ge 6仍然不是后向循环的保证终点。为了停止循环,我添加了一个else语句,当$ Sheet.Cells.Item($ i,1).text不再等于“null”时,它将设置$ i = 0.这将结束向后循环。
#cleanup
$max = $sheet.UsedRange.Rows.Count
for ($i = $max; $i -ge 0; $i--) {
If ($Sheet.Cells.Item($i, 1).text -eq "") {
$Range = $Sheet.Cells.Item($i, 1).EntireRow
[void]$Range.Delete()
echo $i
}
Else {$i = 0}
}