在工作中,我有一个重复的任务,即遍历帐户活动和更改的列表,在这些更改中,我必须删除执行维护所不需要的空格和行。对于其中的80%,我能够为每个循环工作一个非常细腻但有效的循环。 示例:
import pandas as pd
import numpy as np
import itertools
N_t = 5
N_e = 2
classes = tuple(list(itertools.product([0, 1], repeat=N_e)))
N_c = len(classes)
noise = np.random.randint(0, 10, size=(N_c, N_t))
df = pd.DataFrame(noise, index=classes)
df
0 1 2 3 4
0 0 5 9 4 1 2
1 2 2 7 9 9
1 0 1 7 3 6 9
1 4 9 8 2 9
# should be shown as
0 1 2 3 4
0 0 5 9 4 1 2
0 1 2 2 7 9 9
1 0 1 7 3 6 9
1 1 4 9 8 2 9
子字符串是每种交易类型的描述性标题行。我遇到的一个问题是可变的,而其他的则不是。它可以是9行或6行,也可以是正数或负数,但每种可能性都带有相同的标题行。 根据我能找到的所有答案,我需要使用一个循环,从下到上移动。我无法通过InStr或向左/向右触发它。
这是我现在正在尝试的简化版本:
For Each c In ActiveSheet.UsedRange
If InStr(1, c.Value, SubString7) = 1 Then ' find earn lines and remove
c.EntireRow.Offset(1).Delete
c.EntireRow.Clear
c.EntireRow.Offset(-1).Delete
End If
Next
我最初的第一条If行是:
lr = Range("A" & Rows.Count).End(xlUp).Row
For rowcounter = lr To 0 Step -1
If VBA.Strings.Left(Cells(rowcounter).Value, 11) Like "Earn Manual" Then
If VBA.Strings.Left(Cells(rowcounter + 5).Value, 1) = "-" Then
If VBA.Strings.Left(Cells(rowcounter + 6).Value, 3) = "AVG" Then
Cells(rowcounter).EntireRow.Offset(5).Delete 'this, several more times with different offsets for the required lines
Else
Cells(rowcounter).EntireRow.Offset(5).Delete 'different ones, finalizing removals on the negative value items
End if
Else
If VBA.Strings.Left(Cells(rowcounter + 6).Value, 3) = "AVG" Then
Cells(rowcounter).EntireRow.Offset(5).Delete 'again, but with different offsets
Else 'There is one line for these that I have to split into two lines, not sure if this will even work as I cannot get it to trigger
Cells(rowcounter).EntireRow.Offset(8).Delete
Cells(rowcounter).EntireRow.Offset(7).Delete
Cells(rowcounter + 4).Value = VBA.Strings.Right(Cells(rowcounter + 3).Value, 25)
Cells(rowcounter + 3).Value = VBA.Strings.Left(Cells(rowcounter + 3).Value, 13)
End if
End If
End If
Next Rowcounter
我尝试切换为If InStr(1, Cells(rowcounter).Value, SubString8) = 1 Then
和“赞”,但仍然没有骰子。
试图提供输入/输出示例
A列的目标输出:
再次更新,新的和改进的代码仍然失败:
Left()
答案 0 :(得分:0)
我无法100%正确地得到它,因为它是基于OP的新代码和改进代码的,这在逻辑上存在一些缺陷。我的目标是简化整体语法,以使其更容易理解。
删除带有偏移值的问题是这些值会在您身上移动。我的解决方案是合并要删除的所有行,然后在循环完成后删除它们。这不仅效率更高,而且还允许我们从上到下循环。这使代码更易于遵循。
以联合方式进行范围调整时,必须首先进行测试以查看要删除的目标范围是否为Nothing。如果目标范围是“无”,则将其设置为新范围,否则我们将两个范围合并。我编写了一个子例程UnionRange()
,这样我们就不必在每次需要执行Union时都重复此过程。
With
块Range.Offset()
和Range.Resize()
用于简化语法。我觉得这比在范围内连接地址更干净(例如Range(“ A”&i + 5)和Range(“ A”&i,“ A”&i + 8))。
Sub CleanUp()
With ThisWorkbook.Worksheets("Sheet1")
Dim r As Long
Dim rUnion As Range
For r = 1 To .Cells(.Rows.Count, 1).End(xlUp).Row
With .Cells(r, 1)
If .Value = "" Then
UnionRange rUnion, .Offset(0)
ElseIf .Value Like "Earn Manual*" Then
If .Offset(6).Value Like "Avg*" Then ' shows AVG, negative value
UnionRange rUnion, .Offset(8)
Else ' no AVG, negative value
UnionRange rUnion, .Offset(5)
End If
Else
'This can't be right
If .Offset(6).Value Like "Avg*" Then 'If Like "Avg*" Then Delete These Cells
UnionRange rUnion, .Resize(3)
UnionRange rUnion, .Offset(5)
Else 'Hell If Not Like "Avg*" Then Delete The Same Cells Anyway
UnionRange rUnion, .Resize(3)
UnionRange rUnion, .Offset(5)
End If
End If
End With
Next
End With
If Not rUnion Is Nothing Then
Application.ScreenUpdating = False
rUnion.EntireRow.Delete
End If
End Sub
Sub UnionRange(ByRef rUnion As Range, ByRef Cell As Range)
If rUnion Is Nothing Then
Set rUnion = Cell
Else
Set rUnion = Union(rUnion, Cell)
End If
End Sub