【问题标题】:Use VBA loops to search for a changing list of values and delete them?使用 VBA 循环来搜索不断变化的值列表并删除它们?
【发布时间】:2013-07-26 13:56:52
【问题描述】:

我一直在处理 Excel 工作表,我在其中使用宏基本上运行“查找功能”以在单独的工作表上查找单词/短语,然后删除该单词/短语所在的整个列. 目前,感谢我的上一篇文章 (Is there a way to use the find function with changing, user inputted values in an excel macro?) 我有这个:

Dim strFind As String
Dim rngFind As Range
Dim i As Integer


strFind = Sheets("Instructions").Range("E56").Value
Set rngFind = Sheets("Forecast").Cells.Find(What:=strFind, LookAt:=xlPart)
check if value is found
Do While Not rngFind Is Nothing
If Not rngFind Is Nothing Then
   i = 0
        Do While rngFind.Offset(0, i + 1) = ""
            i = i + 1
        Loop
    rngFind.Resize(1, i + 1).EntireColumn.Delete Shift:=xlShiftToLeft
Loop
End If

这可以完美地引用单元格 C53(这是用户输入单词/短语的位置),然后转到“预测”表并删除单词/短语所在的列以及后续列直到下一个填充的列。但是,我需要它再做两件事。

  • 目前它只找到一次单词,即使它可能多次存在于工作表中,我需要它来删除所有这些 - 基本上它是“查找下一个”而不是“查找所有”。我正在考虑创建一个循环,以便一旦找到一个并删除该列,它会再次找到相同的单词并删除该列(以及它旁边的后续空行),直到该单词不再出现在工作表上。
  • 其次,我需要它来查找多个单词/短语。现在它引用单元格'C53',但我需要它然后继续到'C54'并做同样的事情,然后是'C55',然后是'C56'等等。直到它到达一个只有一个'的单元格0' 在里面。问题是,C 列中的列表大小总是不同的(但总是从 C53 开始)。一旦它到达“0”(不是空白单元格),我需要它停止。

对于这个“循环初始”问题的任何帮助将不胜感激!我对 VBA 很陌生,我刚刚被赋予了这样做的任务。非常感谢!

【问题讨论】:

    标签: vba loops excel


    【解决方案1】:

    我一直在使用一个宏来处理一个 Excel 工作表 基本上运行“查找功能”以在单独的 表,然后删除该单词/短语所在的整个列 位于。

    如果我理解正确 - 在我看来,你的潜艇过于复杂:

    Sub DeleteColumnsWithString()
    
    Dim strFind As String
    Dim rngFind As Range
    
    strFind = Sheets("Instructions").Range("C53").Value
    
    Do
        Set rngFind = Sheets("Forecast").Cells.Find(What:=strFind, LookAt:=xlPart)
        If Not rngFind Is Nothing Then
            rngFind.EntireColumn.Delete
        End If
    Loop Until rngFind Is Nothing
    
    End Sub
    

    如果你想做多个字符串,你可以这样做:

    Sub DeleteColumnsWithAnyOfTheseStrings()
    
    Dim strFind As String
    Dim rngFind As Range
    Dim SearchTerms As Range
    
    Set SearchTerms = Sheets("Instructions").Range("C53:C55")
    
    For Each Cell In SearchTerms.Cells
        strFind = Cell.Value
    
        Do
            Set rngFind = Sheets("Forecast").Cells.Find(What:=strFind, LookAt:=xlPart)
            If Not rngFind Is Nothing Then
                rngFind.EntireColumn.Delete
            End If
        Loop Until rngFind Is Nothing
    Next Cell
    
    End Sub
    

    根据您的评论更新:

    Sub DeleteColumnsWithTheseStringsAndToTheRightBlanksColumns()
    
    Dim strFind As String
    Dim rngFind As Range
    Dim strFindAddress As String
    Dim SearchTerms As Range
    Dim Counter As Long
    
    Set SearchTerms = Sheets("Instructions").Range("C53:C55")
    
    For Each Cell In SearchTerms.Cells
        Counter = 0
        strFind = Cell.Value
    
        Do
            Set rngFind = Sheets("Forecast").Cells.Find(What:=strFind, LookAt:=xlPart)
            If Not rngFind Is Nothing Then
                strFindAddress = rngFind.Address
                Do
                    Range(strFindAddress).EntireColumn.Delete
                    Counter = Counter + 1
                Loop Until Range(strFindAddress).Value <> "" Or Counter >= 100
            End If
        Loop Until rngFind Is Nothing
    Next Cell
    
    End Sub
    

    【讨论】:

    • 感谢您的回答,我认为我的问题没有按照我应该的方式表达,哈哈。我的代码如此复杂的原因是它会找到单词所在的列并将其删除,但也会删除该列右侧的列(在第 1 行中),直到下一个填充的单元格。解释起来有点混乱。对于第二部分,我喜欢范围的想法,但我正在处理的范围总是在变化(有时会是 100 行,有时只有 70 行,等等)有什么想法吗?
    【解决方案2】:

    我认为你在这里有很好的基础。

    对于这个“循环初始”问题的任何帮助将不胜感激!

    我认为这样的事情应该有助于您的第一点(未经测试,但这是使用另一个 Do 循环的想法,直到 rngFind Is Nothing):

    Set rngFind = Sheets("Forecast").Cells.Find(What:=strFind, LookAt:=xlPart)
    Do While Not rngFind Is Nothing '## Makes sure the value is found before operating the rest of the loop
        i = 0
            Do While rngFind.Offset(0, i + 1) = ""
                i = i + 1
            Loop
        rngFind.Resize(1, i + 1).EntireColumn.Delete Shift:=xlShiftToLeft
        '## Find the NEXT instanct of strFind within rngFind
        Set rngFind = Sheets("Forecast").Cells.FindNext(What:=strFind, LookAt:=xlPart)
    Loop 
    

    对于第二点,将要搜索的值列表存储在数组中。您可以对逗号分隔的字符串使用 Split 函数来创建数组。对于较小的列表很有用。否则您可能需要使用不同的方法来创建数组。

    根据评论更新:

    Dim valsToSearch() As Variant
    Dim val As Variant
    Dim numberOfValues as Long
    
    numberOfValues = CInt(Application.InputBox("How Many Search Terms?"))
    valsToSearch = Range("C53").Resize(numberOfValues,1)
    

    然后,将上面包含在For/Next 循环中以迭代数组中的值:

    For each val in valsToSearch
        strFind = val
        Set rngFind = Sheets("Forecast").Cells.Find(What:=strFind, LookAt:=xlPart)
        Do While Not rngFind Is Nothing '## Makes sure the value is found before operating the rest of the loop
            i = 0
                Do While rngFind.Offset(0, i + 1) = ""
                    i = i + 1
                Loop
            rngFind.Resize(1, i + 1).EntireColumn.Delete Shift:=xlShiftToLeft
            '## Find the NEXT instanct of strFind within rngFind
            Set rngFind = Sheets("Forecast").Cells.FindNext(What:=strFind, LookAt:=xlPart)
        Loop 
    Next
    

    【讨论】:

    • 太好了,我的第一部分开始工作了!但是对于第二部分,正在搜索的文本的“值”总是在变化。此外,有时我会搜索 100 个值(因此从 C53:C153 开始),但有时我只有 25 个值,等等。但是,“值”正在搜索。有什么想法可以循环到 0 吗?
    • 是的,我们可以将这些值直接存储在数组中,而不是在分隔字符串上使用 Split 函数。我会及时更新我的​​答案。
    • 嗯,这是一种不同的方式。问题是这将被用作一种用户输入表。他们从下拉列表中进行选择,该列表会自动填充我正在使用宏搜索的列 (C) 中的值。所以我真的不想让每个人计算行数并将其放入输入框中。这更有意义吗?抱歉,这真的很令人困惑,试图解释这一切哈哈
    • @JoeGay 有几种方法可以实现。这个论坛上有成千上万个关于“如何在列/工作表/等中找到最后一行”的主题。请查看其中的一些内容。
    • 是的,我刚刚意识到解决这个问题的第一部分让整个事情变得容易多了。感谢大家的帮助!
    猜你喜欢
    • 1970-01-01
    • 2017-01-05
    • 1970-01-01
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多