【问题标题】:Blank cell contains a value when code is executed执行代码时空白单元格包含一个值
【发布时间】:2016-01-01 22:26:25
【问题描述】:

我正在使用带有 12 个列表框(编号为 2-13)的用户表单。每个列表框可以包含用户从主列表框 1 分配的 0-8 个项目。当按下按钮时,我运行以下代码将每个列表框(12 个框)的内容输出到工作表“托盘”。

然后将每个列表框从列 B-M 输出到每个托盘的相应列中。 Listbox2 填充每个托盘的第 1 列,依此类推。最多可装 4 个托盘。该代码检查每个托盘的第一个孔,如果它包含一个值,则假定托盘已满并开始填充下一个托盘。

问题:如果第一个托盘包含一个空白列(列表框)并且第二个托盘包含相同列表框中的值,则代码将使用应该在第二个托盘中的值填充第一个托盘的空白列。请看下面的图片和下面的更新代码:

托盘 1 的列表框 2,3 和 4(注意列表框 3 为空)

托盘 2 的列表框 2,3 和 4(注意 listbox3 有数据)

代码运行了两次:来自托盘 2 的 Listbox3 出现在托盘 1 中(错误!!!)

预期输出:

Sub Worklist()
'
Dim Var, VarName As Variant
Dim i, DblDashPos, FirstPeriodPos, lngColNum, lngRowNum As Long
Dim item As ListBox

Const cstrNames As String = "Listbox2,Listbox3,Listbox4,Listbox5,Listbox6,Listbox7,Listbox8,Listbox9,Listbox10,Listbox11,Listbox12,Listbox13"

Application.ScreenUpdating = False

lngColNum = 2

For Each VarName In Split(cstrNames, ",")


    If UserForm2.Controls(VarName).ListIndex <> -1 Then 'if listbox is not blank

        If Sheets("Tray").Cells(4, lngColNum).Value = 0 Then
        'checks if value in row 3 column "lngColNum" is empty
            lngRowNum = 4
            ThisWorkbook.Sheets("Tray").Range("C2").Value = UserForm2.TextBox1.Value

        ElseIf Sheets("Tray").Cells(15, lngColNum).Value = 0 Then 'checks if value in row 14 column "lngColNum" is empty

            lngRowNum = 15

            ThisWorkbook.Sheets("Tray").Range("C13").Value = UserForm2.TextBox1.Value

        ElseIf Sheets("Tray").Cells(26, lngColNum).Value = 0 Then 'checks if value in row 14 column "lngColNum" is empty

            lngRowNum = 26

            ThisWorkbook.Sheets("Tray").Range("C24").Value = UserForm2.TextBox1.Value

        Else 'otherwise assumes tray starts in row 5, column "lngColNum"

            lngRowNum = 37
            ThisWorkbook.Sheets("Tray").Range("C35").Value = UserForm2.TextBox1.Value

        End If


        For i = 0 To UserForm2.Controls(VarName).ListCount - 1
            Var = UserForm2.Controls(VarName).List(i)

            DblDashPos = InStr(1, Var, "--")
            FirstPeriodPos = InStr(1, Var, ".")
            Sheets("Tray").Select
            ActiveSheet.Cells(lngRowNum, lngColNum) = Left(Var, DblDashPos - 1) & Right(Var, Len(Var) - FirstPeriodPos + 1)

            lngRowNum = lngRowNum + 1
        Next i

    End If


    lngColNum = lngColNum + 1

Next

Application.ScreenUpdating = True

End Sub

非常感谢!

【问题讨论】:

  • 尝试将这一行:If Len(Cells(3, lngColNum).Value) = 0 Then 改为 If Cells(3, lngColNum).Value = "" Then
  • 它仍然认为 B3 和 B14 中有一些东西(尽管它们显然是空白的)并在 Tray3 中输出(该托盘的第一行是 25)这很奇怪,因为它 debug.prints 的值B14 甚至不在任何列表框中。
  • 尝试使用您的工作表名称,例如sheets("thesheetname").Cells(3, lngColNum).Value
  • 您的建议有所帮助,但我仍然遇到问题。谢谢

标签: excel vba


【解决方案1】:

问题是您只测试与 ListBox 对应的列以查看单元格是否为空。如果您想测试“托盘”中的所有列是否为空,则需要对整个工作表进行一次测试。像这样的东西(未经测试,因为我懒得重建你的表格):

Private Function FindFirstUnusedRow(sheet As Worksheet) As Long
    Dim testColumn As Long, testRow As Long
    Dim used As Boolean

    For testRow = 4 To 37 Step 11
        used = False
        For testColumn = 2 To 13
            If IsEmpty(sheet.Cells(testRow, testColumn)) = False Then
                used = True
                Exit For
            End If
        Next testColumn
        If used = False Then
            FindFirstUnusedRow = testRow
            Exit For
        End If
    Next testRow
End Function

然后在你的代码中,在你的循环之前调用它:

Sub Worklist()
    Dim var As Variant
    Dim i As Long, dashPos As Long, periodPos As Long, colNum As Long
    Dim rowNum As Long, Dim sheet As Worksheet

    Application.ScreenUpdating = False
    Set sheet = ThisWorkbook.Sheets("Tray")
    rowNum = FindFirstUnusedRow(sheet)

    If rowNum = 0 Then
        Debug.Print "All trays full."
        Exit Sub
    End If

    Dim current As ListBox
    For colNum = 2 To 13
        Set current = UserForm2.Controls("Listbox" & colNum)
        If current.ListIndex <> -1 Then 'if listbox is not blank
            sheet.Cells(rowNum - 2, colNum).Value = UserForm2.TextBox1.Value
            For i = 0 To current.ListCount - 1
                var = current.List(i)
                dashPos = InStr(1, var, "--")
                periodPos = InStr(1, var, ".")
                sheet.Cells(rowNum + i, colNum) = Left$(var, dashPos - 1) & _
                                    Right$(var, Len(var) - periodPos + 1)
            Next i
        End If
    Next colNum
    Application.ScreenUpdating = True
End Sub

还有一些注意事项:您可以完全放弃 Sheets("Tray").Select 行 - 您从不使用选择对象。对ActiveSheetThisWorkbook.Sheets("Tray") 的混合引用也是如此。获取参考并使用它。

此外,这些行并不像您认为的那样:

Dim Var, VarName As Variant
Dim i, DblDashPos, FirstPeriodPos, lngColNum, lngRowNum As Long

在您声明的所有变量中,一切都是VariantlngRowNum 除外。如果你想像这样在一行上合并声明,你仍然需要为每个变量指定一个类型,否则它们将默认为Variant。请参阅上面的示例代码。

【讨论】:

  • 我在这里遇到类型不匹配 Set current = UserForm2.Controls("Listbox" &amp; colNum) 谢谢
  • @user3781528 - 我无法复制错误 - 它与迭代拆分常量的作用相同,但只是动态构建控件名称。您使用的控件是 ListBox 吗?
  • 是的,Const cstrNames As String = "Listbox2,Listbox3,Listbox4,Listbox5,Listbox6,Listbox7,Listbox8,Listbox9,Listbox10,Listbox11,Listbox12,Listbox13"
  • @user3781528 - ListBoxes 表单上的实际控件吗?试试Dim current As Object
  • 谢谢,就是这样!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-05
  • 2016-02-23
  • 1970-01-01
相关资源
最近更新 更多