【问题标题】:Delete multiple columns from Multiple sheets从多个工作表中删除多个列
【发布时间】:2017-03-18 10:42:15
【问题描述】:

我正在尝试从多个工作表中删除多个列,同时保留在列表中找到的那些。

例如我有sheet1sheet2sheet3、...、sheet7。 从这些表格中,我有一些特定的列要保留。

来自sheet1 我想保留s.nocust.nameproductdate 之类的列,应该从sheet2 中删除相同的列 我想保留prod.disc,addresspin 剩下的所有应该删除,就像我有剩余的工作表一样,我想保留特定的列,所有应该被删除。 我正在尝试使用数组但无法开始如何做。我有基本的语法。

Sub sbVBS_To_Delete_Specific_Multiple_Columns()
Sheets("Sheet1").Range("A:A,C:C,H:H,K:O,Q:U").EntireColumn.Delete
End Sub`[code]

但这对我不起作用,因为将来可能会在其中添加一些列,我希望列应该通过名称识别要保留和丢弃的列。

【问题讨论】:

  • 从删除单个列开始。如果列标题是您指定的名称,请将其删除。在下一步中,创建一个循环,使用另一个标题重复该操作。要查找标题,您需要遍历工作表中的所有标题或使用 Find 功能。
  • 你能提供我基本的语法吗??

标签: arrays vba excel dictionary


【解决方案1】:

好的,这是基本代码。指定要在主过程中删除的工作表和列。设置子过程中查找字幕的行。

Sub DeleteColumns()
    ' 17 Mar 2017

    Dim ClmCaption As Variant
    Dim Ws As Worksheet
    Dim i As Integer

    Set Ws = ActiveSheet
    ' better to specify the sheet by name, like Set Ws = ThisWorkbook.Worksheets("My Excel")

    Application.ScreenUpdating = False      ' freeze screen (speeds up execution)
    ClmCaption = Array("One", "two", "three", "four", "five")
    ' specify all the columns you want to delete by caption , not case sensitive

    For i = 0 To UBound(ClmCaption)         ' loop through all the captions
        DelColumn Ws, CStr(ClmCaption(i))   ' call the sub for each caption
    Next i
    Application.ScreenUpdating = True       ' update screen
End Sub

Private Sub DelColumn(Ws As Worksheet, Cap As String)
    ' 17 Mar 2017

    Dim CapRow As Long
    Dim Fnd As Range

    CapRow = 3                              ' this is the row where the captions are
    Set Fnd = Ws.Rows(CapRow).Find(Cap)     ' find the caption
    If Fnd Is Nothing Then
        MsgBox "The caption """ & Cap & """ doesn't exist." & vbCr & _
               "The column wasn't deleted.", _
               vbInformation, "Invalid parameter"
    Else
        Ws.Columns(Fnd.Column).EntireColumn.Delete Shift:=xlToLeft
    End If
End Sub

您可以按原样运行代码,但您会收到很多错误消息,因为指定的标题不存在。

【讨论】:

  • 嗨,感谢您的及时响应,第一个代码看起来不错,但正如我之前提到的,我想保留 'dict("Sheet1") = Array("s.no", "cust.name" , "product", "date") dict("Sheet2") = Array("prod.disc", "address", "pin") dict("Sheet50") = Array("foo", "bar")'工作表中的列名应完整,其余列应删除
  • @Kittu - 它在哪里提到您正在使用带有数组的字典作为要保留的列,为什么上面的原始问题没有被编辑以包含该显着事实?
  • 您的评论似乎与我发布的代码无关。由于我花时间写它,应您的要求,如果您至少看看它而不是附加您似乎与其他人的通信,那就太好了。
  • @Variatus 感谢您的代码..它确实帮助我重新创建了代码
【解决方案2】:

以下使用 Scripting Dictionary 对象,该对象维护要作为字典 keys 处理的工作表列表,并带有列标题标签数组以保留为关联的 items .

Option Explicit

Sub delColumnsNotInDictionary()
    Dim d As Long, ky As Variant, dict As Object
    Dim c As Long, lc As Long

    Set dict = CreateObject("Scripting.Dictionary")
    dict.comparemode = vbTextCompare

    dict.Item("Sheet1") = Array("s.no", "cust.name", "product", "date")
    dict.Item("Sheet2") = Array("prod.disc", "address", "pin")
    dict.Item("Sheet50") = Array("foo", "bar")

    With ThisWorkbook
        For Each ky In dict.keys
            With Worksheets(ky)
                lc = .Cells.Find(What:="*", After:=.Cells(1, 1), LookIn:=xlFormulas, LookAt:=xlPart, _
                                 SearchOrder:=xlByColumns, SearchDirection:=xlPrevious, _
                                 MatchCase:=False, SearchFormat:=False).Column
                For c = lc To 1 Step -1
                    'filter array method of 'not found in array'
                    'WARNING! CASE SENSITIVE SEARCH  - foo <> FOO
                    If UBound(Filter(dict.Item(ky), .Cells(1, c).Value2)) = -1 Then
                        '.Cells(1, c).EntireColumn.Delete
                    Else
                        Debug.Print .Cells(1, c).Value2 & " at " & _
                          UBound(Filter(dict.Item(ky), .Cells(1, c).Value2))
                    End If
                    'worksheet MATCH method of 'not found in array'
                    'Case insensitive search - foo == FOO
                    If IsError(Application.Match(.Cells(1, c).Value2, dict.Item(ky), 0)) Then
                        .Cells(1, c).EntireColumn.Delete
                    Else
                        Debug.Print .Cells(1, c).Value2 & " at " & _
                          Application.Match(.Cells(1, c).Value2, dict.Item(ky), 0)
                    End If
                Next c
            End With
        Next ky
    End With

    dict.RemoveAll: Set dict = Nothing

End Sub

请注意,我提供了两种方法来确定列标题标签是否在要保留的列数组中。一种区分大小写(数组过滤方法),另一种不区分大小写(工作表函数 MATCH 方法)。不区分大小写的搜索方法当前处于活动状态。

【讨论】:

  • 这段代码对我有用,但是在 sheet1 中的 'dict.Item("Sheet1") = Array("Requested id", "Module", "Product", "Status")' 它正在删除“请求ID”也,不明白为什么?
  • 在工作表标题标签中查找前导或尾随空格、双空格或其他非打印字符。 =LEN(&lt;cell with 'Requested id'&gt;) 应该返回 12。
  • 它返回 12 并尝试使用 "dict.Item("Sheet1") = Array("Requestor", "Module", "Product", "Status") 我尝试用 Requestor 替换并删除“请求者”也是 :-(
  • 嗯...如果不实际处理数据,我真的不能说,这超出了这里的范围。在 .cells(1, c).value2 上使用 Watch 并在即时窗口中尝试 ?.cells(1, c).value2=dict.Item("Sheet1")(0)
  • 当我将此代码应用于我的实时数据时,我在 'lc = .Cells.Find(What:="*", After:=.Cells(1, 1), LookIn:=xlFormulas, LookAt:=xlPart, _ SearchOrder:=xlByColumns, SearchDirection:=xlPrevious, _ MatchCase:=False, SearchFormat:=False).Column'
猜你喜欢
  • 2022-01-04
  • 1970-01-01
  • 2018-10-04
  • 1970-01-01
  • 1970-01-01
  • 2010-10-04
  • 1970-01-01
  • 2021-05-24
  • 1970-01-01
相关资源
最近更新 更多