【问题标题】:Excel VBA - run a macro residing in workbook A to affect workbook B. B's name is a wildcardExcel VBA - 运行驻留在工作簿 A 中的宏以影响工作簿 B。B 的名称是通配符
【发布时间】:2018-09-24 15:24:46
【问题描述】:

希望在工作簿 B 中使用过滤器,其中包含工作簿 A 中的剪贴板内容。工作簿 B 名称是通配符,需要从工作簿 A 运行宏。到目前为止,我有:

Sub SwitchAndFilter()
'

Dim wb As Workbook

For Each wb In Application.Workbooks
   If wb.Name Like "*ABC_*" Then wb.Activate:
   With ActiveWorkbook
'code here just getting run onto workbook A, plus don't know how to pass clipboard contents to a filter
ActiveSheet.Range("$A$1:$W$501").AutoFilter Field:=3, Criteria1:="12345" ' this should be clipboard contents from Workbook A
   End With
    Exit Sub
Next wb

'if code gets here, it isn't already open...
End Sub

更新 1 在线获取“运行时错误 '9':下标超出范围”:

.Sheets("Sheet1").Range("AA1").Paste

根据下面的建议“应该从范围中获取过滤条件,而不是剪贴板”,我尝试首先将剪贴板粘贴到 wbB 上的范围中,然后参考该范围进行过滤。我现在拥有的完整代码是:

Sub SwitchAndFilter3()
    Dim wbA As ThisWorkbook
    Dim wbB As Workbook

    Set wbA = ThisWorkbook

    For Each wbB In Application.Workbooks
        If wbB.Name Like "*ABC_*" And wbA.Name <> wbB.Name Then

            'Your with should reference the context of your for, i.e. wbB, not ActiveWorkbook.
            With wbB

                'You should really try to avoid Activesheet
                'Also, you should get the filter criteria from the range, not the clipboard.
                '
                .Sheets("Sheet1").Range("AA1").Paste
                .ScrollColumn = 2
                '
                .Sheets("Sheet1").Range("$A$1:$W$501").AutoFilter Field:=3, Criteria1:=wbB.Sheets("Sheet1").Range("AA1").Value

                'If you need wbB to be active:
                .Activate

            End With

            Exit Sub
        End If
    Next wbB

COPY SUB FOR @ValonMiller 18 年 9 月 26 日响应以下评论中的请求

Sub CopyFirstOne()
Dim position As Integer
Dim substring As String
position = InStr(ActiveCell, " ")
If (position > 0) Then
    substring = Left(ActiveCell, position - 1)

    Dim MyText As DataObject
    Set MyText = New DataObject

    On Error Resume Next
    MyText.setText substring
    MyText.PutInClipboard

End If
'below macro works on it's own, but Calling from here crashes XL for a bit and gives error on PasteSpecial
'Call SwitchAndFilterWorks
End Sub

10.8.18 更新

Sub ListFiles_A3_Works()
Dim objFSO As Object
Dim objFolder As Object
Dim objFile As Object
Dim i As Integer

    Application.Goto Reference:="Body"
    Selection.ClearContents

    Range("B6").Select

objFolderName = Range("A3").Value

'Create an instance of the FileSystemObject
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Get the folder object
Set objFolder = objFSO.GetFolder(objFolderName)
'Set objFolder = objFSO.GetFolder(Range("A3").Value)
i = 5
'loops through each file in the directory and prints their names and path
For Each objFile In objFolder.Files
'print file name
Cells(i + 1, 1) = objFile.Name
'print file path
'Cells(i + 1, 2) = objFile.Path
i = i + 1
Next objFile
    Range("B6").Select
    Range("A6").Select
        ActiveWindow.ScrollRow = Selection.Row
Call CopyFirstOne
End Sub

【问题讨论】:

  • 工作簿是ThisWorkbook吗?
  • 另外,过滤条件是否从范围(即单元格)中复制?哪个单元格在哪个工作表上?
  • 为什么要激活工作表,并在 For each wb 循环中使用 ActiveWorkbook?只需使用If wb.Name like "whatever" Then // wb.Sheets("whateverSheet").Range([whatever])...?另外,请正确格式化代码,If 语句末尾的: 不正确,将不起作用。 End If 在哪里?你知道你在第一个 Wb 之后退出 sub 对吗?
  • @Alex 标准应该是Criteria1:=.Sheets("Sheet1").Range("AA1").Value。排除 wbB,因为它已经是 With 中的上下文。关于错误,请确保您实际上有一个工作表名称“Sheet1”,如果这实际上不是工作表的名称,那么您需要在代码中更新它。另一个潜在的问题是复制源,复制的是什么以及从哪里复制?如果它是从 Excel 外部复制的,那么如果它支持 Excel 粘贴,那么你所拥有的可能会起作用。如果您尝试从 wbA 复制某些内容,那么我看不到复制发生在这里。
  • @ValonMiller - 当我运行这个 Sub 时,已经从 wbA 进行了复制。根据您上面的注释:我已排除 wbB 并将 wbB 中的所有“Sheet1”引用重命名为实际工作表名称,但在同一行上不断收到“运行时错误'9':下标超出范围”......

标签: excel vba


【解决方案1】:

[根据上述讨论于 9 月 26 日更新]

确保使用正确的工作表名称更新With wbB.Sheets("Sheet1") 行。

Sub CopyFirstOne()
    Dim position As Integer
    Dim substring As String

    position = InStr(ActiveCell, " ")

    If (position > 0) Then
        substring = Left(ActiveCell, position - 1)
    Else
        substring = ActiveCell.Value
    End If

    'Pass the filter string directly
    Call SwitchAndFilter(substring)
End Sub

Sub SwitchAndFilter(fitlerValue As String)
    Dim wb As Workbook

    For Each wb In Application.Workbooks
        If wb.Name Like "*ABC_*" And ThisWorkbook.Name <> wb.Name Then

            'Changed with to target Sheet, instead of Workbook
            With wb.Sheets("Sheet1")

                .Range("$A$1:$W$501").AutoFilter Field:=3, Criteria1:=fitlerValue

                'Optional
                .Activate

            End With

            Exit Sub
        End If
    Next wb

    'if code gets here, it isn't already open...

End Sub

【讨论】:

  • “运行时错误'438':对象不支持此属性或方法”在线If wbB.Name Like "*ABC_*" And wbA &lt;&gt; wbB Then
  • @Alex 这是因为您无法明确比较 workbook 对象。相反,将其更改为 And wbA.FullName &lt;&gt; wbB.FullName Then
  • @Valon - 我也许可以让 wbA 始终保持相同的名称,但 wbB 总是会有所不同 - 这就是为什么我在我的问题中说“工作簿 B 名称是通配符”......跨度>
  • @Alex wbA 没有改变,它总是指的是ThisWorkbook。 wbB 是 for 循环上下文中的当前工作簿。正在评估名称的比较,以便 IF 块作用于除自身之外的所有工作簿。
  • @ValonMiller - 你能看看我的 UPDATE 1 在这个线程顶部的原始问题 - 我已经发布了我现在正在运行的完整代码,解释和行给出错误的代码......(也在我之前的评论中,就在我回复你的上方,没有注意到我回复的评论来自 Marcucciboy2 而不是你)
【解决方案2】:

我认为这不是最好的解决方案,但要解决我认为是您的复制/粘贴问题的根本原因,请尝试以下操作:

Sub CopyFirstOne()
    Dim position As Integer
    Dim substring As String
    Dim MyText As DataObject

    Set MyText = New DataObject

    position = InStr(ActiveCell, " ")

    If (position > 0) Then
        substring = Left(ActiveCell, position - 1)
    Else
        substring = ActiveCell.Value
    End If

    On Error Resume Next
    MyText.setText substring
    MyText.PutInClipboard

    Call SwitchAndFilterWorks
End Sub

【讨论】:

  • 我使用的文件名总是至少有一个空格。尝试此版本的 CopyFirstOne() 性能甚至最差时,它甚至没有列出目录中的文件,并且在冻结后会在行 Set objFolder = objFSO.GetFolder(objFolderName ) 在 Sub ListFiles_A3_Works() 中,我将在我的原始帖子中粘贴带有 10.8.18 更新的 Sub
猜你喜欢
  • 1970-01-01
  • 2015-01-18
  • 1970-01-01
  • 2017-10-18
  • 1970-01-01
  • 2014-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多