VBA Excel奇怪的行为

时间:2018-02-24 22:59:45

标签: excel vba

我一直试图编写一个可以导入任何电子表格的模块,并且适用于管理存储在工作簿中任何工作表中的用户帐户信息。

到目前为止,我已经写了以下模块:

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' modUserSession
'
' The purpose of this module is to provide a layer that manages
' user accounts. 
'
' There is a standard format that must be adheired to, this is
' done by populating the global SessionParams type with the
' relevant information describing the particular sheet where
' the user account information is stored.     
'


Type SessionParameters
    sheetName As String         ' Name of the sheet that contains user accounts
    sheetUnlock As String       ' String to lock/unlock the users sheet

    startRow As Integer         ' Row on which user accounts begin

    nameColumn As Integer       ' Column on which user names are stored
    passColumn As Integer       ' Column on which user passwords are stored
    forenameColumn As Integer   ' Column where user forename is stored
    surnameColumn As Integer    ' Column where user surname is stored
    telephoneColumn As Integer  ' Column where user telephone number is stored
    emailColumn As String       ' Column where user email address is stored
End Type


Type UserAccount
    userName As String
    userPass As String

    foreName As String
    surName As String
    telNum As String
    emailAddr As String
End Type


Private SessionParams As SessionParameters


'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' setSessionParams() 
'
' Populates the global SessionParams that is used to reference the
' relevant sheet where user accounts are stored.
'
Public Function setSessionParams( _
    ByRef sParams As SessionParameters _
)

    SessionParams.sheetName = sParams.sheetName
    SessionParams.sheetUnlock = sParams.sheetUnlock

    SessionParams.startRow = sParams.startRow
    SessionParams.nameColumn = sParams.nameColumn
    SessionParams.passColumn = sParams.passColumn

    SessionParams.forenameColumn = sParams.forenameColumn
    SessionParams.surnameColumn = sParams.surnameColumn
    SessionParams.telephoneColumn = sParams.telephoneColumn
    SessionParams.emailColumn = sParams.emailColumn

End Function


'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' nextEmptyUserRow()    
'
' Will return the next empty row on the sheet referenced by
' the global SessionParams type.
'
Public Function nextEmptyUserRow()

    Dim intRow As Integer

    Dim sheetName As String
    Dim nameColumn As Integer

    sheetName = SessionParams.sheetName
    nameColumn = SessionParams.nameColumn

    intRow = SessionParams.startRow

    While (True)
        If (ActiveWorkbook.Sheets(sheetName).Cells(intRow, nameColumn) = "") Then
            nextEmptyUserRow = intRow
            Exit Function
        End If

        intRow = (intRow + 1)
    Wend

End Function


'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' findUserAccount()
'
' Finds the row on which a particular user account is stored and
' returns the row number. 
'
' If the specified user account isn't found then 0 is returned.
'
Public Function findUserAccount( _
    ByVal userName As String _
) As Integer

    Dim intRow As Integer

    Dim sheetName As String
    Dim nameColumn As Integer

    sheetName = SessionParams.sheetName
    nameColumn = SessionParams.nameColumn

    intRow = SessionParams.startRow

    While (True)
        If (ActiveWorkbook.Sheets(sheetName).Cells(intRow, nameColumn) = "") Then
            findUserAccount = 0
            Exit Function
        End If

        If (ActiveWorkbook.Sheets(sheetName).Cells(intRow, nameColumn) = userName) Then
            findUserAccount = intRow
            Exit Function
        End If

        intRow = (intRow + 1)
    Wend

End Function


'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' loadUserAccountByRow()
'
' Loads a user account from the specified row - even if the row is
' empty and contains no data, the cells are loaded and returned
' in a SessionParameters type and will be empty. 
'
Public Function loadUserAccountByRow( _
    ByVal intRow As Integer _
) As UserAccount

    Dim sheetName As String

    sheetName = SessionParams.sheetName

    loadUserAccountByRow.userName = ActiveWorkbook.Sheets(sheetName).Cells(intRow, SessionParams.nameColumn)
    loadUserAccountByRow.userPass = ActiveWorkbook.Sheets(sheetName).Cells(intRow, SessionParams.passColumn)
    loadUserAccountByRow.foreName = ActiveWorkbook.Sheets(sheetName).Cells(intRow, SessionParams.forenameColumn)
    loadUserAccountByRow.surName = ActiveWorkbook.Sheets(sheetName).Cells(intRow, SessionParams.surnameColumn)
    loadUserAccountByRow.telNum = ActiveWorkbook.Sheets(sheetName).Cells(intRow, SessionParams.telephoneColumn)
    loadUserAccountByRow.emailAddr = ActiveWorkbook.Sheets(sheetName).Cells(intRow, SessionParams.emailColumn)

End Function


'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' loadUserAccountByName()
'
' Loads the specified user account and returns a SessionParameters
' type with the loaded info.
'
' If the specified account doesn't exist then all of the fiels in
' the SessionParameters type will be empty. 
'
' This function works by calling findUserAccount(), passing the
' specified userName as a parameter.
'
' If the account doesn't exist then findUserAccount() will return
' 0, in which case an empty row is loaded.
'
' If the account does exist it is loaded via a call to the
' loadUserAccountByRow() function.
'
Public Function loadUserAccountByName( _
    ByVal userName As String _
) As UserAccount

    Dim intRow As Integer

    ' Get the row on which the user account is stored - the
    ' findUserAccount function will return 0 if the specified
    ' user account does not exist.
    '
    intRow = findUserAccount(userName)

    If (intRow = 0) Then
        ' Return an empty SessionParameters structure.
        '
        loadUserAccountByName = loadUserAccountByRow(nextEmptyUserRow)
    Else
        loadUserAccountByName = loadUserAccountByRow(intRow)
    End If

End Function

现在的想法是,您使用与存储数据的特定工作表相关的信息填充模块中定义的全局SessionParameters变量(SessionParams)。我基本上需要填写SessionParams以指示工作表名称和存储数据的起始行/列。

我有以下表格:

enter image description here 所以,我现在正在做的是测试loadUserAccountByName()函数(来自上面的模块)。

首先,我必须使用指向工作表的相关信息初始化全局SessionParams,并定义工作表上的所有内容。

因此,当我的工作簿首次打开时,我执行了以下代码:

Private Function populateSessionParams()

    Dim sParams As SessionParameters
    Dim userRow As Integer


    sParams.sheetName = "Users"
    sParams.sheetUnlock = "UnlockSheet"

    sParams.startRow = 5

    sParams.nameColumn = 4
    sParams.passColumn = 6

    sParams.forenameColumn = 8
    sParams.surnameColumn = 10
    sParams.telephoneColumn = 12
    sParams.emailColumn = 14

    setSessionParams sParams

End Function


Private Sub Workbook_Open()

    Dim uParams As UserAccount

    populateSessionParams

    uParams = loadUserAccountByName("Admin")

    MsgBox _
        "Username: " & uParams.userName & vbCrLf & _
        "Password: " & uParams.userPass & vbCrLf & _
        "Forename: " & uParams.foreName & vbCrLf & _
        "Surname: " & uParams.surName & vbCrLf & _
        "Tel: " & uParams.telNum & vbCrLf & _
        "Email: " & uParams.emailAddr

End Sub

Workbook_Open()函数中,我首先调用populateSessionParams()函数 - 这会初始化模块中定义的全局SessionParams并使用适当的值。

除了一件事之外,一切都很有效 - loadUserAccountByName()函数调用loadUserAccountByRow()函数,如果找到特定的用户帐户,则使用相关信息填充UserAccount类型。它正在查找管理员帐户并加载除拒绝填充的emailAddr成员之外的所有相关数据。

错误可以追溯到loadUserAccountByRow()函数的以下行:

    loadUserAccountByRow.emailAddr = ActiveWorkbook.Sheets(sheetName).Cells(intRow, SessionParams.emailColumn)

我可以从调试器中看到SessionParams.emailColumn肯定包含值14,即电子邮件地址存储在“用户”表中的列。我还可以在调试器中看到sheetName的值确实是"用户"

它使用几乎相同的代码填充UserAccount类型的所有其他值:

' Each of the following lines work.
loadUserAccountByRow.userName = ActiveWorkbook.Sheets(sheetName).Cells(intRow, SessionParams.nameColumn)
loadUserAccountByRow.userPass = ActiveWorkbook.Sheets(sheetName).Cells(intRow, SessionParams.passColumn)
loadUserAccountByRow.foreName = ActiveWorkbook.Sheets(sheetName).Cells(intRow, SessionParams.forenameColumn)
loadUserAccountByRow.surName = ActiveWorkbook.Sheets(sheetName).Cells(intRow, SessionParams.surnameColumn)
loadUserAccountByRow.telNum = ActiveWorkbook.Sheets(sheetName).Cells(intRow, SessionParams.telephoneColumn)

' This particular line will not work and I get an application or
' object defined error. If I comment this line out, everything works
' great and there are no errors.
'
loadUserAccountByRow.emailAddr = ActiveWorkbook.Sheets(sheetName).Cells(intRow, SessionParams.emailColumn)

我现在已经在这一点上打了我的额头,似乎无法理解我的头脑。我知道它有点啰嗦,但你真的需要所有的代码和对我尝试做的事情的合理解释,希望它有意义。

任何帮助表示感谢。

0 个答案:

没有答案