如果选择了大量单元格,userform(微调器)返回类型不匹配的代码。VBA Excel

如果选择了大量单元格,userform(微调器)返回类型不匹配的代码。VBA Excel,vba,excel,range,spinner,Vba,Excel,Range,Spinner,我知道类型不匹配通常是在错误定义变量时发生的,但我不确定在这种情况下是否有意义。下面发布的我的代码是针对一个带有微调器的用户表单的,当您单击微调器按钮时,您在单击该用户表单之前高亮显示的单元格会增加/减少指定的百分比 这对于数量较少的单元非常有效。例如,我可以选择5个不同范围的4个单元格,每个单元格的行为将与预期的一样。但是,如果我选择的范围超过此范围,则在使用微调器时会出现类型不匹配错误,调试器会高亮显示下面的singlecell.Value=singlecell.Value*pvar代码。这

我知道类型不匹配通常是在错误定义变量时发生的,但我不确定在这种情况下是否有意义。下面发布的我的代码是针对一个带有微调器的用户表单的,当您单击微调器按钮时,您在单击该用户表单之前高亮显示的单元格会增加/减少指定的百分比

这对于数量较少的单元非常有效。例如,我可以选择5个不同范围的4个单元格,每个单元格的行为将与预期的一样。但是,如果我选择的范围超过此范围,则在使用微调器时会出现类型不匹配错误,调试器会高亮显示下面的singlecell.Value=singlecell.Value*pvar代码。这似乎只影响每个选定范围的最后几行

有人知道为什么会这样,或者如何纠正这种情况吗?以我有限的知识,作为一个类型不匹配的错误,它似乎不完全有意义。我唯一的假设是,当定义为范围时,可以存储为范围的数量有一个限制?请参阅下面的代码:

'打开sinner用户窗体的代码

Public SelRange As Range
Public pvar As Double
Public SelVar As Double
Public InitVar As Double
Public GetAllValuesAtOnceAsArray As Variant

Sub Button2_Click()
Spinner.Show
End Sub
'用户表单的代码

Option Explicit

'on opening userform this sets the variables

Private Sub UserForm_Activate()

pvar = 1
Set SelRange = Selection
GetAllValuesAtOnceAsArray = SelRange.Value

End Sub

'button to maintain adjusted values

Private Sub CommandButton1_Click()

UserForm3.Show

End Sub

'Button to return to starting values

Private Sub DefaultButton_Click()

Dim singlecell As Range

'write back the original values
SelRange.Value = GetAllValuesAtOnceAsArray

'Adjust every single Cell within range
pvar = 1

End Sub

'Spin Up button

Private Sub SpinButton1_SpinUp()

Application.ScreenUpdating = False

pvar = pvar + UpBox.Value / 100

'write back the original values
SelRange.Value = GetAllValuesAtOnceAsArray

Dim singlecell As Range

'Adjust every single Cell within range
For Each singlecell In SelRange.Cells
    singlecell.Value = singlecell.Value * pvar
Next singlecell


Application.ScreenUpdating = True
End Sub

' Spin Down button

Private Sub SpinButton1_SpinDown()

pvar = pvar - DownBox.Value / 100

'write back the original values
SelRange.Value = GetAllValuesAtOnceAsArray

Dim singlecell As Range

'Adjust every single Cell within range
For Each singlecell In SelRange.Cells
        singlecell.Value = singlecell.Value * pvar
Next singlecell

End Sub

' Reset values when closing userform unless specified otherwise

Private Sub UserForm_terminate()

'Now write back the original values
SelRange.Value = GetAllValuesAtOnceAsArray

End Sub
您提到您“选择了5个不同的区域,每个区域有4个单元格”,这似乎表明您选择的是非连续区域。如果是这种情况,那么真正的问题可能是您尝试在变量数组中存储并恢复范围内的值的方式。这样不行。考虑下面的子:

Sub test1()
    Dim myRange As Range, myCopy As Variant
    Set myRange = Selection
    myCopy = myRange.Value
    myRange.ClearContents
    'now restore:
    myRange.Value = myCopy 'doesn't always work!
End Sub
用不同的值填充范围A1:B2和D1:E4,然后通过先选择A1:B2,然后选择D1:E4来同时选择它们。调用sub。您应该看到D3:E4范围内的#N/A——这就是导致实际类型不匹配的原因

问题是,非连续范围是区域的集合,并且只有第一个区域被Value属性抓住。如果确实要存储并恢复值,可以执行以下操作:

Sub test2()
    Dim myRange As Range, myArea As Range
    Dim myCopy As Variant
    Dim i As Long, numAreas As Long

    Set myRange = Selection

    numAreas = myRange.Areas.Count
    If numAreas = 1 Then
        myCopy = myRange.Value
    Else
        ReDim myCopy(1 To numAreas)
        For i = 1 To numAreas
            myCopy(i) = myRange.Areas(i).Value
        Next i
    End If

    myRange.ClearContents

    'now restore:

    If numAreas = 1 Then
        myRange.Value = myCopy
    Else
        For i = 1 To numAreas
            myRange.Areas(i).Value = myCopy(i)
        Next i
    End If
End Sub
在您的情况下,您可能需要myCopy和numAreas模块级变量。用于复制值的代码和用于恢复值的代码都可以移动到sub,以及用于将某个范围内的每个单元格乘以一个值的代码(对向上旋转和向下旋转都很有用)。下面3个sub说明了这一点,然后是一个测试sub,以显示sub调用是如何工作的:

Sub CopyVals(R As Range, V As Variant)
    Dim A As Range
    Dim i As Long, n As Long
    n = R.Areas.Count
    If n = 1 Then
        V = R.Value
    Else
        ReDim V(1 To n)
        For i = 1 To n
            V(i) = R.Areas(i).Value
        Next i
    End If
End Sub

Sub RestoreVals(R As Range, V As Variant)
    Dim A As Range
    Dim i As Long, n As Long
    n = R.Areas.Count
    If n = 1 Then
        R.Value = V
    Else
        For i = 1 To n
            R.Areas(i).Value = V(i)
        Next i
    End If
End Sub

Sub Multiply(R As Range, p As Double)
    Dim c As Range
    For Each c In R.Cells
        c.Value = p * c.Value
    Next c
End Sub

Sub test()
    Dim myRange As Range, myCopy As Variant
    Dim pvar As Double

    Set myRange = Selection
    CopyVals myRange, myCopy
    pvar = 0.9
    Multiply myRange, pvar

    pvar = 1.1
    RestoreVals myRange, myCopy
    Multiply myRange, pvar
End Sub
请注意,test()的最后两行不能折叠为

RestoreVals myRange, myCopy * pvar

因为这将涉及数组乘以双类型不匹配

您选择的范围是非连续的吗?还有——什么时候会出现错误?是在加载表单时还是在点击旋转按钮时?如果在
singlecell.Value=singlecell.Value*pvar
处出现错误,那么为什么不插入一个复选框来确认如果是数字(singlecell.Value),您的想法是什么然后在
的其他部分
中,我会放置这样的东西
debug.print singlecell.address&“不是一个数字”
。嗨,John,它们通常是不连续的,当我点击旋转按钮而不是打开用户表单时会出现错误。嗨,拉尔夫,谢谢你的建议,在这种情况下,给出错误的单元格不是数字。为什么在定义相同的情况下,这会发生在一些人身上而不是其他人身上?我现在的问题是,如果我使用以下代码:如果numAreas=1,那么myRange.Value=myCopy*pvar Else For I=1 to numAreasmyRange.Areas(i).Value=myCopy(i)*pvar下一个i结束,如果它本质上是您的代码,但使用myCopy*pvar(表示百分比变量)我得到了另一个类型不匹配。@Sam我想我不明白其动机——如果“旋转”按钮已经修改了这些值,为什么需要重新复制原始值来重新修改它们?可能有一个布尔变量控制终止事件是否恢复。在任何情况下,myCopy或myCopy(i)(视情况而定)都将是数组(除非在特殊情况下,该区域由单个单元格组成),将数组乘以标量值没有任何意义。如果您想走这条路-只需重新复制值,然后稍后在单元格上循环,修改值。@Sam还-复制代码和还原代码(如果您经常使用它们)可以有效地移动到subs(比如CopySelection()和RestoreSelection())中,以使其余代码更具可读性。再次感谢。只是解释一下。电子表格包含大量值(例如资产价格)。然后,在理论上,但不是在功能上,用户可以选择他们想要的任何资产,然后应用微调器,这模拟了这些资产价格的上涨/下跌%,等等,然后他们可以观察这如何影响业务的各个方面。然后,它们有两个按钮,一个可以保留调整后的值,另一个可以重置值。此外,原始值将设置为预期发生的情况,但能够更改这些假设以评估影响的能力是关键。然而,在许多情况下,我们希望看到影响,但不希望在电子表格中保留它。我对VBA不太在行,所以您能否解释一下,或者给出一个示例,说明您建议我如何复制和循环单元格?谢谢