用excel处理变量
语言:Excel 您好,谢谢您阅读我的帖子 我正在尝试创建一个公式来。。。根据变量乘以单元格(或在本例中为字母)。变量是它是否可以被(1000+250x)整除,根据答案,乘以相应的字母百分比 视觉表现:用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% 第二个例子,因为#
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标记为可能的解决方案,尽管我在这方面缺乏经验。我相信,由于您的注释和我以前的编码经验,我将能够相当快地拿起它。既然你花了时间为我写了一段代码,我将花时间剖析它并学习它来报答你的好意。非常感谢你,马克@斯派洛,不客气!如果你有任何问题,不要犹豫