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
用excel处理变量_Excel_Vba_Loops - Fatal编程技术网

用excel处理变量

用excel处理变量,excel,vba,loops,Excel,Vba,Loops,语言:Excel 您好,谢谢您阅读我的帖子 我正在尝试创建一个公式来。。。根据变量乘以单元格(或在本例中为字母)。变量是它是否可以被(1000+250x)整除,根据答案,乘以相应的字母百分比 视觉表现: A B C 1% 2% 3% 250 500 1000 1 1,000 2 1,250 3 1,500 4 1,750 5 2,000 例如,因为#1可以被1000整除,所以我会将它乘以3% 第二个例子,因为#

语言:Excel

您好,谢谢您阅读我的帖子

我正在尝试创建一个公式来。。。根据变量乘以单元格(或在本例中为字母)。变量是它是否可以被(1000+250x)整除,根据答案,乘以相应的字母百分比

视觉表现:

   A     B     C   
   1%    2%    3%  
   250   500   1000  


1  1,000
2  1,250
3  1,500
4  1,750
5  2,000 
例如,因为#1可以被1000整除,所以我会将它乘以3% 第二个例子,因为#2可以被250和1000整除,所以我将250乘以1%,1000乘以3%,然后将它们相加

我目前的尝试:

=IF(MOD(A2,F14)<=1,A2*F15,"")

=IF(MOD(A2,F14)对于Excel公式,我想不出任何好的解决方案,因为你想要的结果太复杂了:就像你标记了你的问题一样,你需要一个循环,不管怎样,恐怕哪些公式不能为你做。
但是,当您将
VBA
添加为标记之一时,我假设
VBA
解决方案适合您,因此我编写了一个脚本:
Option Explicit'必须声明变量,否则会出错。非常方便的规则
Option Explicit 'variables MUST BE declared, otherwise error. very handy rule
Option Base 0 'won't be needed this time, but in general, this rule is also a great ally
'(it says: arrays' 1st item will always be the "0th" one)
Dim divLARGE, divMED, divSMALL 'you can use variable types in Excel Dim percLARGE, percMED, percSMALL 'but sadly, not in VBScript which I have ATM

'test input values and their results, won't be needed in your Excel Dim testA, testB, testC, testD, testE, testF 'so add types if you like Dim resA, resB, resC, resD, resE, resF '(should make execution a little faster)

'Init our variables declared above. in VBScript you can't do this at declaration,
'i.e. can't say "Dim whatever As Boolean = true" which would be the right way to do this Call Initialize()

'Call the "main routine" to execute code
Call Main()

'you can add access modifiers here. "private" would be the best
'i.e. "private Sub Main()" Sub Main() resA = CalcMaster(testA, divLARGE) resB = CalcMaster(testB, divLARGE) resC = CalcMaster(testC, divLARGE) resD = CalcMaster(testD, divLARGE) resE = CalcMaster(testE, divLARGE) resF = CalcMaster(testF, divLARGE) MsgBox (CStr(testA) + " --> " + CStr(resA) + vbCrLf + _ CStr(testB) + " --> " + CStr(resB) + vbCrLf + _ CStr(testC) + " --> " + CStr(resC) + vbCrLf + _ CStr(testD) + " --> " + CStr(resD) + vbCrLf + _ CStr(testE) + " --> " + CStr(resE) + vbCrLf + _ CStr(testF) + " --> " + CStr(resF) + vbCrLf) End Sub
Sub Initialize() divLARGE = 1000 'the large number for which we look after remnants divMED = 500 'medium/middle sized number to divide by divSMALL = 250 'the small value percLARGE = 3 'percentage we want if no remnants on LARGE number percMED = 2 'same but for medium/mid size numbers percSMALL = 1 'and the percentage we want for the small remnants
testA=1000 'result should be exactly 30.0 testB=1250 'res == 32.5 testC=1500 'res == 40.0 testD=1750 'res == 42.5 testE=2000 'res == 60.0 testF=-198 'res == #ERROR/INVALID VALUE End Sub
Function CalcMaster(inVar, byDiv) 'A silly function name popped in my mind, sorry :) Dim remnant, percDiv
'sometimes happens, looks cheaper calc.wise to handle like this; if initial input
'can be 0 and that's a problem/error case, handle this scenario some other way If (inVar = 0) Then Exit Function remnant = inVar Mod byDiv 'if you'll implement more options, do a Select...Case instead (faster) If (byDiv = divLARGE) Then percDiv = percLARGE ElseIf (byDiv = divMED) Then percDiv = percMED Else percDiv = percSMALL End If

If (remnant = 0) Then CalcMaster = inVar * (percDiv / 100) Exit Function End If 'had remnant; for more than 3 options I would use an array of options 'and call back self with the next array ID If (byDiv = divLARGE) Then CalcMaster = CalcMaster(inVar - remnant, divLARGE) + CalcMaster(remnant, divMED) ElseIf (byDiv = divMED) Then CalcMaster = CalcMaster(inVar - remnant, divMED) + CalcMaster(remnant, divSMALL) Else 'or return 0, or raise error and handle somewhere else, etc 'MsgBox ("wrong input number: " + CStr(inVar)) CalcMaster = -1 End If End Function
这次不需要选项库0,但一般来说,此规则也是一个很好的盟友(它说:数组的第一项将始终是“第0项”)
Dim divLARGE、divMED、divSMALL“您可以在Excel中使用变量类型 Dim percLARGE,percMED,percSMALL'但遗憾的是,不是在VBScript中,我有ATM

'测试输入值及其结果,在Excel中不需要 Dim testA、testB、testC、testD、testE、testF’因此,如果您愿意,可以添加类型 Dim resA,resB,resC,resD,resE,resF'(应该使执行速度加快一点)

'Init我们上面声明的变量。在VBScript中,您不能在声明时执行此操作,
'即不能说“Dim whates As Boolean=true”,这是正确的方法 调用Initialize()

调用“主例程”执行代码
调用main()

您可以在此处添加访问修饰符。“private”将是最好的
,即“private Sub-main()” 副标题() resA=CalcMaster(testA,divLARGE) resB=CalcMaster(testB,divLARGE) resC=CalcMaster(testC,divLARGE) resD=CalcMaster(testD,divLARGE) resE=CalcMaster(测试,大) resF=CalcMaster(testF,divLARGE) MsgBox(CStr(测试)+“-->”+CStr(resA)+vbCrLf+_ CStr(测试B)+“-->”+CStr(resB)+vbCrLf+_ CStr(testC)+“-->”+CStr(resC)+vbCrLf+_ CStr(testD)+“-->”+CStr(resD)+vbCrLf+_ CStr(测试)+“-->”+CStr(研究)+vbCrLf+_ CStr(testF)+“-->”+CStr(resF)+vbCrLf) 末端接头
子初始化() divLARGE=1000'我们关注的大数字 divMED=500'中/中型数字除以 divSMALL=250'小值 percLARGE=3'如果大数字上没有残余,则我们需要的百分比 percMED=2'相同,但适用于中型/中型号码 percSMALL=1'和我们希望的小残余物百分比
testA=1000'结果应正好为30.0 testB=1250'分辨率==32.5 testC=1500'分辨率==40.0 testD=1750'分辨率==42.5 测试仪=2000'分辨率=60.0 testF=-198'res=#错误/无效值 末端接头
函数CalcMaster(因瓦,byDiv)'一个愚蠢的函数名突然出现在我的脑海中,对不起:) 暗淡的残余物,percDiv
“有时会发生,这样处理看起来更便宜;如果初始输入
'可以为0,并且这是一个问题/错误案例,请以其他方式处理此场景 如果(因瓦=0),则退出函数 残数=因瓦模数byDiv '如果要实现更多选项,请改为使用Select…案例(更快) 如果(byDiv=divLARGE),则 percDiv=perclave ElseIf(byDiv=divMED)然后 percDiv=percMED 其他的 percDiv=percsall 如果

如果(剩余=0),则 CalcMaster=因瓦*(percDiv/100) 退出功能 如果结束 "有残余,;对于3个以上的选项,我将使用一系列选项 '并使用下一个数组ID回调self 如果(byDiv=divLARGE),则 CalcMaster=CalcMaster(因瓦-残余,divLARGE)+CalcMaster(残余,divMED) ElseIf(byDiv=divMED)然后 CalcMaster=CalcMaster(因瓦-残余,divMED)+CalcMaster(残余,divSMALL) 或返回0,或引发错误并在其他地方处理,等等 'MsgBox(“输入错误:+CStr(因瓦)) CalcMaster=-1 如果结束 结束功能



这并不完美,我想可能会有更好的解决方案,但我认为这已经足够好了。我希望你同意:)
干杯

在Sparrow解释之后,我得到了“最佳可能解决方案”是将所有可能的整数除数(即250、500、1000)乘以相应的“奖金”(1%、2%、3%)得到的“总奖金”最大化的方案

这是一个必然的解决方案

Option Explicit

Sub main()
Dim dataRng As Range, cell As Range, percRng As Range, divRng As Range
Dim i As Long, value As Long, nDivisors As Long
Dim prize As Double, totalPrize As Double

Set dataRng = ActiveSheet.Range("B1:B10") '<== here set the range cointaining the numbers to be processed
Set percRng = ActiveSheet.Range("F15:H15") '<== here set the range of % "prizes": they MUST be in ascending order (from lowest to highest)
Set divRng = ActiveSheet.Range("F14:H14") '<== here set the range of the possible divisors. this range MUST be of the same size as thre "prizes" range

For Each cell In dataRng.SpecialCells(xlCellTypeConstants, xlNumbers)

    value = cell.value
    nDivisors = 0
    prize = 0
    totalPrize = 0
    Do
        i = FindMaxDivisor(value, percRng, divRng)
        If i > 0 Then
            value = value - divRng(i) ' update value to the remainder
            prize = percRng(i) * divRng(i) ' get current "prize"
            totalPrize = totalPrize + prize 'update totalprize
            nDivisors = nDivisors + 1 'update divisors number
            cell.Offset(, nDivisors) = divRng(i)  'write divisor in next blank adjacent cell in the number row
        End If
    Loop While value > 0 And i >= 0

    If i >= 0 Then ' the number has been correctly divided by given divisors
        With cell.Offset(, nDivisors + 1)
            .value = totalPrize
            .Font.Color = vbRed
        End With
    Else
        MsgBox "Not possible to break " & cell.value & " into given divisors"
    End If

Next cell

End Sub


Function FindMaxDivisor(value As Long, percRng As Range, divRng As Range) As Long
Dim i As Long

FindMaxDivisor = -1 'default value should not be found any whole divisor

i = divRng.Columns.Count
Do While value Mod divRng(i) <> 0 And i > 1
    i = i - 1
Loop

If value Mod divRng(i) = 0 Then FindMaxDivisor = i

End Function
选项显式
副标题()
Dim dataRng As Range、cell As Range、percRng As Range、divRng As Range
Dim i为长,值为长,NDIVISOR为长
暗奖为双倍,总奖为双倍

设置dataRng=ActiveSheet.Range(“B1:B10”)“Sparrow先生,请编辑“最佳可能解决方案”是什么意思?我所说的最佳可能解决方案@user3598756是什么意思。。。例如,以数字3为例。把500(1500)除以2,然后再乘以1%,或者换句话说,取((250*1%)*2)+(1000*3%),这样做会更理想。。。((500*2%)+(1000*3%))我已经将VBA标记为可能的解决方案,尽管我在这方面缺乏经验。我相信,由于您的注释和我以前的编码经验,我将能够相当快地拿起它。既然你花了时间为我写了一段代码,我将花时间剖析它并学习它来报答你的好意。非常感谢你,马克@斯派洛,不客气!如果你有任何问题,不要犹豫