代码需要运行多次才能删除所有列

问题描述 投票:0回答:4

此代码删除与数组中的文本相同的列。

我需要运行 2-3 次才能删除所有列。

Sub DeleteSpecifcColumn()
    Dim xFNum, xFFNum, xCount As Integer
    Dim xStr As String
    Dim xArrName As Variant
    Dim MR, xRg As Range
    On Error Resume Next
    Set MR = Range("A1:N1")
    xArrName = Array("textBox25", "textBox4", "textBox6", "textBox8", "textBox19", "textBox9",    "textBox10", "textBox11", "textBox22", "textBox12", "textBox23", "textBox5", "textBox7", "textBox24", "textBox1", "textBox3", "textBox14", "textBox8", "textBox19", "textBox9", "textBox10", "textBox11", "textBox22", "textBox12", "textBox23")
    xCount = MR.Count
    xStr = xArrName(xFNum)
    For xFFNum = xCount To 1 Step -1
        Set xRg = MR(1, xFFNum)
        For xFNum = 0 To UBound(xArrName)
            xStr = xArrName(xFNum)
            If xRg.Value = xStr Then xRg.EntireColumn.Delete
        Next xFNum
    Next
End Sub

以下代码也有同样的问题:

Sub change_header_2()
    Cells(1, "A").Value = "Shift"
    Cells(1, "B").Value = "Clock In Time"
    Cells(1, "C").Value = "First Task"
    Cells(1, "D").Value = "Last Task"
    Cells(1, "E").Value = "Clock Out"
    Cells(1, "F").Value = "User"
    Cells(1, "G").Value = "Name"
End Sub

尝试运行一个循环来解决问题,但我不知道如何将其写入子程序中,也不知道如何将其写入运行前一个子程序循环的新子程序中。

excel vba
4个回答
1
投票

删除匹配列

Sub DeleteMatchingColumns()
    
    Const HEADER_RANGE As String = "A1:N1"
    Dim LookupHeaders(): LookupHeaders = Array( _
        "textBox1", "textBox3", "textBox4", "textBox5", "textBox6", _
        "1textBox7", "textBox8", "textBox9", "textBox10", "textBox11", _
        "textBox12", "textBox14", "textBox19", "textBox22", "textBox23", _
        "textBox24", "textBox25")
    
    Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
    Dim hrg As Range: Set hrg = ws.Range(HEADER_RANGE).Rows(1) ' ensure one row
    Dim hcCount As Long: hcCount = hrg.Columns.Count
    
    ' In this case, 'hcIndexes' will return a 1D one-based array
    ' containing the indexes of matches or error values if not matching.
    Dim hcIndexes()
    
    If hcCount = 1 Then ' one column of headers
        ReDim hcIndexes(1 To 1)
        hcIndexes(1) = Application.Match(CStr(hrg.Value), LookupHeaders, 0)
    Else ' multiple columns of headers
        hcIndexes = Application.Match(hrg, LookupHeaders, 0)
    End If
    
    Dim hurg As Range, hc As Long
    
    For hc = 1 To hcCount
        If IsNumeric(hcIndexes(hc)) Then ' it's a match
            ' Combine the matching cells into a range.
            If hurg Is Nothing Then
                Set hurg = hrg.Cells(hc)
            Else
                Set hurg = Union(hurg, hrg.Cells(hc))
            End If
        'Else ' it's not a match; do nothing
        End If
    Next hc
        
    If hurg Is Nothing Then
        MsgBox "No matches found.", vbExclamation
    Else
        ' Delete all matching columns in one go.
        hurg.EntireColumn.Delete xlShiftToLeft
        MsgBox "Columns deleted.", vbInformation
    End If
        
End Sub

0
投票

以下是第一个子项目的两个解决方法。

#1 - 循环范围和数组

'declare Worksheet variable to hold the exact sheet - ActiveSheet 
is a quite random value
Dim ws As Worksheet

' declare and fill array
Dim xArrName As Variant
xArrName = Array("textBox25", "textBox4", "textBox6", "textBox8", "textBox19", "textBox9", "textBox10", "textBox11", "textBox22", "textBox12", "textBox23", "textBox5", "textBox7", "textBox24", "textBox1", "textBox3", "textBox14", "textBox8", "textBox19", "textBox9", "textBox10", "textBox11", "textBox22", "textBox12", "textBox23")

' declare a range to search values in
Dim workRange As Range

' assign a specific sheet to variable, you may need to change the sheet name
Set ws = ThisWorkbook.Sheets("Sheet1")

' declare iteration variable for columns - it's a good practice to
' grant variables with explanatory names
Dim columnIterator As Integer

'same for array iterator
Dim arrayIterator As Integer

' in case you want to loop through both array and range
' looping through range
For columnIterator = 14 To 1 Step -1
    ' looping through array
    For arrayIterator = LBound(xArrName) To UBound(xArrName)
        If ws.Cells(1, columnIterator).Value = xArrName(arrayIterator) Then
            ws.Cells(1, columnIterator).EntireColumn.Delete
        End If
    Next
Next
' do other stuff

#2 - 使用“.Find()”方法

'declare Worksheet variable to hold the exact sheet - ActiveSheet is a quite random value
Dim ws As Worksheet

' declare and fill array
Dim xArrName As Variant
xArrName = Array("textBox25", "textBox4", "textBox6", "textBox8", "textBox19", "textBox9", "textBox10", "textBox11", "textBox22", "textBox12", "textBox23", "textBox5", "textBox7", "textBox24", "textBox1", "textBox3", "textBox14", "textBox8", "textBox19", "textBox9", "textBox10", "textBox11", "textBox22", "textBox12", "textBox23")

' declare a range to search values in
Dim workRange As Range

' assign a specific sheet to variable, you may need to change the sheet name
Set ws = ThisWorkbook.Sheets("Sheet1")

' assign a range with binding to specific sheet
Set workRange = Range(ws.Cells(1, 1), ws.Cells(1, 14))
' that's just for looping through array
' like Nick.McDermaid suggestet
For arrayIterator = LBound(xArrName) To UBound(xArrName)
' in this case I DO know that if there
' will be no matches on .Find() function
' I will get an
' Run-time error '91': Object variable or With block variable not set
' error and can live with that for now
' so I use On Error Resume Next statement to ignore it
On Error Resume Next
    workRange.Find(xArrName(arrayIterator)).EntireColumn.Delete
Next

' reset error handler after the loop
Err.Clear

' do other stuff

如果“N”列(O、P、Q、R...等)之后没有任何值,这些方法将正常工作,否则,这些值将向左移动并且范围“A1:N1”可能包含已删除的内容再次值。

这是第二个子项目,尝试使用特定的工作表和单元格来设置值

Sub change_header_2()
'declare Worksheet variable to hold the exact sheet - ActiveSheet is a 
quite random value
Dim ws As Worksheet
' assign a specific sheet to variable, you may need to change the sheet name
Set ws = ThisWorkbook.Sheets("Sheet1")

' this construction will add values
' to specific cells on a specific sheet
With ws
    .Cells(1, "A").Value = "Shift"
    .Cells(1, "B").Value = "Clock In Time"
    .Cells(1, "C").Value = "First Task"
    .Cells(1, "D").Value = "Last Task"
    .Cells(1, "E").Value = "Clock Out"
    .Cells(1, "F").Value = "User"
    .Cells(1, "G").Value = "Name"
End With
End Sub

最后你应该注意Pᴇʜ关于变量声明的评论。


0
投票

我不包含任何代码,因为您的代码可以工作,但仅在特殊情况下有效。 这些是。

  • 不带对象限定符的引用是指根据以下内容的工作表

    1. Placed in a sheet's code: Refers to the sheet where it is placed
    2. Placed in ThisWorkbook or Module: Refers to the ActiveSheet.
    
  • With Defined object 限定符指的是定义的对象。

在带有 Me 关键字的代码中,您可以到达运行代码的工作表,但要小心它,因为 Microsoft 没有明确定义它。欲了解更多信息 请参阅 来自 Microsoft

https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/me-keyword

因此,在您的代码中,在此表单的范围和单元格属性之前添加工作表名称

Worksheets("name").

其中名称是窗口底部选项卡上给出的工作表的实际名称。


0
投票

这里似乎发生了一些事情。 我感兴趣的是为什么您需要多次运行代码才能删除所有列。 在我看来,你的

Set MR = Range("A1:N1")
可能与此有关。 该范围包含 14 个成员,但您正在尝试检测要删除的 25 个列标题。

另外,声明多个相同类型的变量时,仍然需要声明它们的类型。 例如,

Dim MR, xRg As Range
不会将这两个声明为
Ranges
,而是将
xRg
声明为
Range
,并将
MR
声明为
Variant
,这是 VBA 在未指定其他数据类型时使用的数据类型。 您想要的是这里
Dim MR As Range, xRg As Range

以下是您想要执行的操作的配对版本,例如:

Private Sub DeleteColumns()

    ' Range of cells to look through
    Dim HeaderRange As Range
    Set HeaderRange = Range("A1:N1")
    
    ' Column names we want to delete
    Dim BadNames As Variant
    BadNames = Array("textBox3", "textBox5")
    
    ' Iterate through our range of cells, looking at column names
    Dim ii As Long, jj As Long
    For ii = HeaderRange.Columns.Count To 1 Step -1
        
        ' For each cell in the range, compare its name to the Bad names
        For jj = LBound(BadNames) To UBound(BadNames)
        
            ' If the name is one of the Bad names, delete the column
            If HeaderRange(ii).Value = BadNames(jj) Then
                HeaderRange.Columns(ii).EntireColumn.Delete
                
                ' We can exit the "jj" loop now, because we've already
                ' deleted the column
                Exit For
                
            End If
            
        Next jj
        
    Next ii

End Sub

这应该足以指导您。 如果这是您希望定期执行的任务,您还可以考虑将其转换为

Sub
,它将标题单元格的范围和坏名称列表作为参数。

© www.soinside.com 2019 - 2024. All rights reserved.