Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vba 将工作表作为参数传递给子程序_Vba_Excel - Fatal编程技术网

Vba 将工作表作为参数传递给子程序

Vba 将工作表作为参数传递给子程序,vba,excel,Vba,Excel,我知道在这个话题上有很多问题,但我仍然在努力解决一个超出范围的下标?是的,我正在导入的工作簿确实有一张名为LSL Recon的工作表,我已验证。我已经调试并用导入工作表(1)(如Sheet1)替换了LSL Recon,然后该过程继续进行,但没有将任何内容导入阵列 Option Explicit Public FILENAME, c_DATE, cNAME As String 'Public ws As Worksheet Sub main() Application.DisplayA

我知道在这个话题上有很多问题,但我仍然在努力解决一个超出范围的下标?是的,我正在导入的工作簿确实有一张名为
LSL Recon
的工作表,我已验证。我已经调试并用导入工作表(1)(如
Sheet1
)替换了
LSL Recon
,然后该过程继续进行,但没有将任何内容导入阵列

Option Explicit

Public FILENAME, c_DATE, cNAME As String
'Public ws As Worksheet

Sub main()
    Application.DisplayAlerts = True
    Application.ScreenUpdating = False

    CLEAR
    Import Sheets("LSL Recon")
    Display_Import
End Sub()

Sub Import(ws As Worksheet)  
    Workbooks.Open FILENAME
    Set TempBook = ActiveWorkbook
    ws.Activate

    cNAME = "Entity"
    cA = Sheets(1).Rows.Find(What:=UCase(cNAME), LookAt:=xlWhole, SearchDirection:=xlNext).Column
    cNAME = "Sector"
    cB = Sheets(1).Rows.Find(What:=UCase(cNAME), LookAt:=xlWhole, SearchDirection:=xlNext).Column
    cNAME = "Date"
    cC = Sheets(1).Rows.Find(What:=UCase(cNAME), LookAt:=xlWhole, SearchDirection:=xlNext).Column
    cNAME = "Client"
    cD = Sheets(1).Rows.Find(What:=UCase(cNAME), LookAt:=xlWhole, SearchDirection:=xlNext).Column
    ...
End Sub()
有用的问题:



删除公共作用域变量,声明所有变量,并根据需要传递参数:

Option Explicit

Sub main()

    Dim FILENAME$
    Dim c_DATE$
    Dim cNAME$
    Dim wsName$
    wsName = "LSL Recon"
    Application.DisplayAlerts = True
    Application.ScreenUpdating = False

    CLEAR
    Import (wsName)
    Display_Import
End Sub

Sub Import(wsName$)  
    Dim wb as Workbook
    Dim cNames, itm, found
    ' Use an array of items to search for
    cNames = Split("Entity,Sector,Date,Client",",")

    Set wb = Workbooks.Open(FILENAME)

    Set ws = wb.Sheets(wsName)

    For Each itm in cNames
        found = ws.Rows.Find(What:=UCase(cNAME), LookAt:=xlWhole, SearchDirection:=xlNext).Column
        Debug.Print cName " found in column: " & found
    Next

End Sub
如果需要将
.Find
的结果返回到主过程,则将其更改为函数,并返回一个集合对象,然后像这样调用它:

Set foundItems = Import(wsName)
Dim itm
For each itm in foundItems
    Debug.Print itm
Next
然后函数:

Function Import(wsName$)  
    Dim wb as Workbook
    Dim ret as New Collection
    Dim cNames, itm, found
    ' Use an array of items to search for
    cNames = Split("Entity,Sector,Date,Client",",")

    Set wb = Workbooks.Open(FILENAME)

    Set ws = wb.Sheets(wsName)

    For Each itm in cNames
        ret.Add ws.Rows.Find(What:=UCase(cNAME), LookAt:=xlWhole, SearchDirection:=xlNext).Column
        Debug.Print cName " found in column: " & ret(ret.Count)
    Next
    'return the collection to the calling procedure
    Set Import = ret
End Function

您试图在活动工作簿中引用名为“LSL Recon”的工作表,而不是在即将打开的工作簿中。如果您试图引用将要打开的工作簿中的工作表,则必须将工作表名称作为字符串参数传递。进一步说@Rory所说的,如果您将名称作为字符串传递,则仍必须将工作表设置为子。。。类似于
Set ws=TempBook.Sheets(sName)
假设sName是传递给子对象的字符串,而不是ws-As-worksheet当您声明子导入(wsName)时,为什么传递导入工作表(wsName)?首先,您应该始终定义参数和变量的类型(Dim cNames、itm,例如declare non-typesafe Variant variable)。如果您本应将参数定义为字符串,那么在尝试传递entiere工作表而不是工作表名称时,您将成为运行时错误@cboden我将函数定义更改为require string,传递工作表对象是一个我在OP的代码中没有注意到的错误(公平地说,源代码中有很多错误),我也修改了这个错误。其他变量是类型variant,不需要显式的
As variant
声明,
Dim cNames,itm,found
就足够了。不声明vars的类型(而且函数的返回值类型仍然缺失)仍然是一种不好的风格。这些变量变量会在编译器中造成大量开销,因为每次访问此类变量时都必须进行隐式类型转换。所以这是在浪费资源。此外,键入save vars有助于输入正确的值,正如您在工作表示例中看到的那样,您需要一个字符串。如果您不编写类型安全程序,则很难找到此类错误。@cboden如果您认为我的答案可以改进,欢迎您对其进行编辑