如何从sheet2中运行sheet1中的宏

时间:2017-06-08 14:36:42

标签: excel vba excel-vba

我无法弄清楚要从其他工作表运行此宏的更改内容。有什么想法吗?

  • 此宏存储在工作表“Mail”

  • 我想通过按钮

  • 从Sheet2运行宏

是否可以或者我必须从根本上改变宏?

    Sub DynamicRange()
    'Find the last row in the range then make the slection
    '-----------------------------------------------------------------------
    Dim sht As Worksheet
    Dim LastRow As Long
    Dim LastColumn As Long
    Dim StartCell As Range
    Dim Sendrng As Range
    Dim strbody As String

    '----------------------------------------------------------------
    If IsEmpty(Range("B26").Value) = True Then
    ThisWorkbook.Sheets("Mail").Range("B2:K26").Select
    Else        
    '----------------------------------------------------------------

    Set sht = Worksheets("Mail")
    Set StartCell = Range("B2")

    'Refresh UsedRange
    Worksheets("Mail").UsedRange

    'Find Last Row
    LastRow = sht.Cells.Find("*", SearchOrder:=xlByRows, 
    SearchDirection:=xlPrevious).Row

    'Select Range
    sht.Range("B2:K" & LastRow).Select

    End If

    '-----------------------------------------------------
    'Mail codes starts here
    On Error GoTo StopMacro

    With Application
    .ScreenUpdating = False
    .EnableEvents = False
    End With

    'Note: if the selection is one cell it will send the whole worksheet
     Set Sendrng = Selection

    'Create the mail and send it
    With Sendrng

    ActiveWorkbook.EnvelopeVisible = True
    With .Parent.MailEnvelope

        With .Item
            .To = "here@myour.mail"
            .CC = ""
            .BCC = ""
            .Subject = ThisWorkbook.Sheets("Mail").Range("O4").Value
            .Importance = 2
            .ReadReceiptRequested = True
            .Send
        End With

    End With
    End With

    StopMacro:
    With Application
    .ScreenUpdating = True
    .EnableEvents = True
    End With
    ActiveWorkbook.EnvelopeVisible = False

    End Sub

2 个答案:

答案 0 :(得分:4)

对ActiveSheet的隐式引用

如果宏是在“邮件”表的代码隐藏中实现的,那么在您查询Worksheets集合以获取该工作表的对象引用的任何位置,您可以替换为Me,指的是类模块的当前实例 - 是的,工作表模块类模块。与userforms一样,VBA为它们声明了一个全局范围的对象 - 您可以通过更改 Properties 工具窗口(F4)中的(Name)属性来确定要用于该对象的标识符。工作表。因此,您可以将工作表命名为MailSheet ,并在代码中使用

Debug.Print MailSheet.Name

现在,每当您使用不合格的 Range来电(或RowsCellsNamesColumns时}),您隐含地指的是当前处于活动状态的工作表,这可能是也可能不是您打算使用的工作表。这会导致运行时错误,并且您会在此站点上找到数十个问题,这是根本原因 - 始终使用正确的工作表对象限定Range次调用,您将不会遇到此问题。

  

我大量参与了Rubberduck,这是VBE(VBA的IDE /编辑器)的加载项,可以找到活动工作表的隐式引用的所有实例,还有一些其他常见的初学者(和一些不那么初学者的错误。你可能想尝试一下,它是免费的和开源的。

调用程序

如果程序是作为{em>标准模块(。bas)中的Public Sub实现的,而不是工作表的代码隐藏,那么你可以从中调用它,就像在项目:

DynamicRange

请注意,这是一个相当差的程序名称;程序做某事,他们的名字应该以动词开头,名字应该传达它正在做的事情。

如果您不想将过程移动到标准过程模块,那么您始终可以将其保留为工作表模块的公共成员(如果未指定Public则它是隐式的;模块成员在默认情况下,VBA始终为Public并将其称为:

MailSheet.DynamicRange

假设您在属性工具窗口中为“邮件”表单提供了名称MailSheet,如上所述。

参数化程序

如果您希望您的程序对任何指定的工作表起作用,那么您需要参数化它。 签名就像这样:

Public Sub DynamicRange(ByVal sht As Worksheet)

因此,当您调用该过程时,您可以提供Worksheet对象:

DynamicRange MailSheet

MailSheet.DynamicRange Sheet2

为了使其工作,您需要删除sht变量的本地声明和赋值,并使代码适用于指定的工作表。

答案 1 :(得分:3)

解释

始终使用Range()等工作表指定Cells()sht.Range() 当然,sht必须首先设置为您想要的工作表:

Set sht = ThisWorkbook.Worksheets("Mail")

另请尝试避免.Select而是将所需范围设置为变量Set SendRng = sht.Range("B2:K26")并稍后再使用。

  

显然,MailEnvelope确实从活动工作表中发送了所选范围:(所以这次我们有.Select.Activate的真实用例我们无法避免它(至少我没找到一个)。

这样您的代码就可以独立于活动工作表和任何选择,因此您可以在选择任何工作表或单元格的情况下运行它。

我整理了你的代码。将其保存到模块中,它应该从任何工作表运行。

注意:我删除了未使用的变量。

Option Explicit

Sub DynamicRange()
    Dim sht As Worksheet, actSht As Worksheet
    Dim LastRow As Long
    Dim SendRng As Range

    Set sht = ThisWorkbook.Worksheets("Mail")

    'Find the last row in the range then make the slection
    '-----------------------------------------------------------------------
    If IsEmpty(sht.Range("B26").Value) = True Then
        Set SendRng = sht.Range("B2:K26")
    Else        
        'Find Last Row
        LastRow = sht.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row

        'Select Range
        Set SendRng = sht.Range("B2:K" & LastRow)
    End If

    '-----------------------------------------------------
    'Mail codes starts here
    On Error GoTo StopMacro

    With Application
        .ScreenUpdating = False
        .EnableEvents = False
    End With
    Set actSht = ActiveSheet 'remember active sheet

    'Create the mail and send it
    With SendRng 
        .Parent.Activate 'we need to activate the mail sheet
        .Select 'we need to select the range which should be in the email

        ActiveWorkbook.EnvelopeVisible = True
        With .Parent.MailEnvelope.Item
            .To = "here@myour.mail"
            .CC = ""
            .BCC = ""
            .Subject = sht.Range("O4").Value
            .Importance = 2
            .ReadReceiptRequested = True
            .Send
        End With
    End With

StopMacro:
    actSht.Select 'jump back to the sheet we came from
    With Application
        .ScreenUpdating = True
        .EnableEvents = True
    End With
    ActiveWorkbook.EnvelopeVisible = False
End Sub