如何从sheet2运行sheet1中的macros

我无法弄清楚要从另一张纸上运行这个macros是怎样改变的。 任何想法 ?

  • 这个macros被存储在表单“邮件”

  • 我想通过一个button从Sheet2运行macros

是否有可能或者必须从根本上改变macros观?

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 

说明

总是使用工作表(如sht.Range()指定Range()Cells() sht.Range()
当然,必须首先设置你想要的工作表:

 Set sht = ThisWorkbook.Worksheets("Mail") 

另外尝试避免.Select而不是将所需的范围Set SendRng = sht.Range("B2:K26")为一个variablesSet SendRng = sht.Range("B2:K26") ,稍后再使用它。

显然MailEnvelope确实发送活动工作表的选定范围:(所以这次我们有一个真正的用例.Select.Activate我们无法避免它(至less我没有find一个)。

通过这种方式,您的代码可以独立于活动工作表和任何select,因此您可以运行任何表单或单元格。


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

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

 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 

隐式引用ActiveSheet

如果macros是在表单“Mail”的代码隐藏中实现的,那么在查询Worksheets集合以获取该表单的对象引用的任何地方,都可以用引用当前类模块实例Me来替代,是的,工作表模块类模块。 与用户表单一样,VBA为它们声明一个全局作用域的对象 – 通过改变工作表的(Name)属性,可以在属性工具窗口(F4)中确定用于该对象的标识符。 所以你可以命名你的工作表MailSheet 并在代码中使用它

 Debug.Print MailSheet.Name 

现在,无论何时您使用非限定 Range调用(或Rows ,或Cells ,或NamesColumns ),您都隐式引用任何工作表当前处于活动状态 ,这可能是也可能不是您打算使用的工作表。 这经常会导致运行时错误,你会发现几十个问题在这个网站上,这是根本原因 – 总是限定Range调用一个适当的工作表对象,你不会有这个问题。

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


调用程序

如果程序是以标准模块 (.bas)中的Public Sub实现的,而不是工作表的代码隐藏,那么您可以在项目中的任何位置像这样调用它:

 DynamicRange 

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

如果您不想将过程移动到标准过程模块,则可以始终将其保留为工作表模块的公共成员(如果未指定Public则隐含; VBA中的模块成员始终为Public )并像这样调用它:

 MailSheet.DynamicRange 

假设您在属性工具窗口中将“邮件”表格命名为MailSheet ,如上所述。


参数化过程

如果您希望您的过程针对任何指定的工作表 ,则需要对其进行参数化签名变成这样:

 Public Sub DynamicRange(ByVal sht As Worksheet) 

所以当你调用这个过程时,你可以提供一个Worksheet对象:

 DynamicRange MailSheet 

要么

 MailSheet.DynamicRange Sheet2 

为了这个工作,你需要删除你的shtvariables的本地声明和赋值,并使代码在指定的工作表上工作。