【问题标题】:Pass Variable After Calling Sub调用 Sub 后传递变量
【发布时间】:2017-05-18 18:46:09
【问题描述】:

我有两个问题。

  1. 因为 Var3 有时可能为空白,这取决于 Sub,我收到 424 错误,并且“未定义”一词被复制到网站上的文本框中 - 但是我需要将其留空并且不要在其中粘贴任何内容案子。

  2. 我在 Excel 中有一个下拉框来选择要调用的 Sub。我想将其合并到如下所示的 IF 语句中,但是当我尝试代码时,没有任何反应。

这是我的尝试:

Public Sub Populate()

Dim Var1 As String
Dim Var2 As String
Dim Var3 As String    

Dim User_Name As String
Dim StrFile1 As String
Dim StrFile2 As String
Dim Filename As String
Dim strFilename As String

Dim IE As Object

If ComboBox1.Value = "Data1" Then
    Call Data1 (Filename, Var1, Var2, Var3)
End If

If ComboBox1.Value = "Data2" Then
    Call Data2 (Filename, Var1, Var2, Var3)
End If

'If ComboBox1.Value = Data3, Data4, etc...

    User_Name = Environ("UserName")
    StrFile1 = "C:\Users\"
    StrFile2 = "\Desktop\"

    strFilename = StrFile1 & User_Name & StrFile2 & Filename

    With ActiveSheet.QueryTables.Add(Connection:= _
        "TEXT;" & strFilename, Destination _
        :=Range("$A$22"))
        .Name = Filename
        .FieldNames = True
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .RefreshStyle = xlOverwriteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = False
        .RefreshPeriod = 0
        .TextFilePromptOnRefresh = False
        .TextFilePlatform = 437
        .TextFileStartRow = 1
        .TextFileParseType = xlDelimited
        .TextFileTextQualifier = xlTextQualifierDoubleQuote
        .TextFileConsecutiveDelimiter = False
        .TextFileTabDelimiter = False
        .TextFileSemicolonDelimiter = False
        .TextFileCommaDelimiter = True
        .TextFileSpaceDelimiter = False
        .TextFileColumnDataTypes = Array(1, 1)
        .TextFileTrailingMinusNumbers = True
        .Refresh BackgroundQuery:=False
    End With

    ActiveWindow.SmallScroll Down:=-27

    DoEvents

    'FillInternetForm
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual

    Set IE = CreateObject("InternetExplorer.Application")
    IE.Navigate "https://website.com"
    IE.Visible = True
    While IE.busy
        DoEvents  'wait until IE is done loading page.
    Wend

    IE.Document.All(Var1).Value = ThisWorkbook.Sheets("Sheet1").Range("B5")
    IE.Document.All(Var2).Value = ThisWorkbook.Sheets("Sheet1").Range("B6")
    IE.Document.All(Var3).Value = ThisWorkbook.Sheets("Sheet1").Range("B7")

    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic

End Sub


Public Sub Data1 (ByRef Filename As String, ByRef Var1 As String, ByRef Var2 As String, ByRef Var3 As String)

    Filename = "FILE1.CSV"
    Var1 = "Response123"
    Var2 = "Response456"
    Var3 = "Response789"

End Sub

Public Sub Data2 (ByRef Filename As String, ByRef Var1 As String, ByRef Var2 As String, ByRef Var3 As String)

    Filename = "FILE2.CSV"
    Var1 = "Response987"
    Var2 = "Response654"
    Var3 = "Response321"

End Sub

'Public Sub Data3, Data4, etc...

【问题讨论】:

  • Var 是一个局部变量,只能从 Populate 子中访问。 Variable1 sub 无权访问Var。如果您使用Option Explicit 语句,则您的代码不应编译(即使在开始时更正Dim 错字。我建议您始终使用Option Explicit,并使用Function 来返回值而不是Sub 和共享变量。
  • " & Var & " 是一个字符串常量,而不是进行任何连接的代码。你想用什么连接Var?请参阅msdn.microsoft.com/en-us/library/office/gg264104.aspx 了解如何使用& 运算符进行连接。
  • 感谢 Vincent G 50,我正在尝试用 IE.Document.All(" ... ").Value 之后的变量替换引号“...”内的文本框 ID ,但发现使用 &..& 不起作用。还纠正了错字-在我的实际代码中没有这样拼写:)
  • 如果我想在 Variable1() 中包含基于 Excel 工作表值的计算...您是否仍建议将其设为函数而不是子函数?我想用它来返回值,但也可以进行计算和做其他事情。
  • 见@Comintern 的回答。恕我直言,函数是返回单个值的最佳等待。当需要返回多个值时,可以平等地使用带有 ByRef 参数的 Function 或 Sub。我想不出在 sub 中完成的任何事情不能在函数中完成。

标签: vba excel


【解决方案1】:

如果您在子例程/函数中声明 (DIM) 变量,则它仅在该子例程/函数中可用。

您需要公开声明变量,以便其他子例程可以使用它们。

或者,您可以重写代码,如下所示:

Private Sub Populate()

Dim strVar As String 
Dim IE As Object

DoEvents
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Set IE = CreateObject("InternetExplorer.Application")
With IE
    .Navigate "https://website.com"
    .Visible = True
    While .busy
        DoEvents  
    Wend
End With
strVar=Variable1()

IE.Document.All(" & strVar & ").Value = ThisWorkbook.Sheets("Sheet1").Range("B5")

End Sub

Private Function Variable1() AS String
    Var = "R_575031"
End Sub

通过将例程转换为函数,您可以返回一个值。私有函数只存在于模块中(例如在一个表单中)。 Public Functions 和 subs 属于全局模块容器,而不是 Form / Sheet 容器。

【讨论】:

  • 谢谢,我想我会尝试将这些 subs 公开,只是因为我想在 Variable1() 中包含其他命令,例如计算 Excel 工作表中特定单元格的平均值。计算的单元格数也会因每个子项而异(例如变量 1()、变量 2() 等)
  • 是否多次进行相同的计算?我将不再只是给函数名称通用名称 - 给它一个你会理解的名称。
【解决方案2】:

这不是变量的工作方式,也不是参数的工作方式。正如 cmets 中所指出的,在过程中声明的变量仅在这些过程中具有作用域。如果您想从不同的程序更改您所在程序之外的值,您有 2 个选项 - 将它们传递给 ByRef

Sub Variable1(ByRef Var As String)
    Var = "R_575031"
End Sub

'In the calling code...
Variable1 Var

...或将它们分配给函数的返回值:

Function Variable1() As String
    Variable1 = "R_575031"
End Function

'In the calling code...
Var = Variable1

在您的情况下,第二个使代码更清晰、更易于阅读。

至于使用吧,这一行是错误的:

E.Document.All(" & strVar & ").Value = ThisWorkbook.Sheets("Sheet1").Range("B5")

您不会将变量连接到命令中。如果需要传参数,就传一个参数:

E.Document.All(strVar).Value = ThisWorkbook.Sheets("Sheet1").Range("B5")
              '^^^^^^ this is a parameter of .All()

【讨论】:

  • 谢谢共产国际,这很有帮助。当我创建一个作为字符串的函数时,这是否将函数的使用限制为字符串?基本上我想向这个函数添加更多内容,例如进行计算、传递多个变量等,而不仅仅是将其用于将字符串传递给变量。如果是这种情况,您会建议使用 ByRef 的第一个选项吗?
  • @RS - 我不确定您所说的“进行计算而不仅仅是将其用于传递字符串”是什么意思。但是,是的,如果它返回 String,那就是它返回的内容。好的设计实践只会让每个 SubFunction 负责做一件事。
  • 我的计划是拥有多个功能/子,当一个被调用时让它执行一系列单独的任务。一项任务将涉及在 Excel 工作表上选择单元格并进行平均值、最小值和最大值等计算。对于每个函数/子项,在进行这些计算时,单元格范围会有所不同。变量 Var 只是一个结果。每个结果将有多个变量,例如 Var1、Var2 等,所有变量都将进入 IE。抱歉,我应该在我的原始帖子中更清楚地说明这一点。以后我肯定会发布更详细的代码。我希望这很清楚。
  • @RS - 您当然可以为函数或子 (see this page on Documentation) 使用超过 1 个“ByRef”参数,但通常这表明设计不佳。如果要全局使用变量,请将它们声明为全局变量。
  • 我在这里编辑了我的原始帖子,并更新了显示新代码的更新,以便更准确地了解我想要完成的工作。然而,出现了一些我似乎无法解决的新问题..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-12
  • 2017-01-25
  • 1970-01-01
  • 2013-08-09
  • 1970-01-01
相关资源
最近更新 更多