#excel #vba #user-defined-functions
#excel #vba #определяемые пользователем функции
Вопрос:
У меня есть таблица, состоящая из 3 разных категорий: материк, остров, город; каждая из них имеет 2 разных возможных значения, где им присваивается одно в зависимости от «веса». Если ‘Weight’ <= 2 кг, то наш результат ‘Cost’ равен, например, 1.2 (для материка или 1.3 для острова и т.д.). Если ‘weight’ > 2 кг, нам нужно округлить его до ближайшего целого числа, затем вычислить 0,3 (для материка или 0,9 для острова и т.д.), умноженное на дополнительные целые числа свыше 2 кг. Тогда стоимость будет исходным значением для первых 2 кг, а затем сложите десятичное значение каждой области, умноженное на дополнительные целые числа. Я попытался создать свою собственную функцию для выбора 3 ячеек и выполнения вычисления, поскольку она казалась слишком сложной для линейных функций, заданных из excell.
Но я всегда получаю сообщение об ошибке…
Обратите внимание, что все значения переменных взяты из выбранных пользователем ячеек, а значение Location просто проверяет, какой текст находится внутри ячейки, чтобы присвоить правильные числа для вычисления.
Это то, что у меня есть на данный момент… Есть какие-нибудь советы?
Function TotalCost(ByVal tmx As Integer, ByVal weight As Double, _
ByVal Location As Text)
Dim b As Integer
Dim c As Integer
Dim d As Integer
d = 0
c = 0
f = 0
If Location Like "Mainland" And weight <= 2 Then
TotalCost = 1.2
ElseIf Location Like "Mainland" And weight > 2 Then
weight = Round(weight, 0)
c = weight - 2
Do While c > 0
c = c - 1
d = d 1
Loop
TotalCost = tmx * ((d * 9.55) 1.2)
ElseIf Location Like "City" And weight <= 2 Then
TotalCost = 1.1
ElseIf Location Like "City" And weight > 2 Then
weight = Round(weight, 0)
c = weight - 2
Do While c > 0
c = c - 1
d = d 1
Loop
TotalCost= tmx * ((d * 0.55) 1.1)
ElseIf Location Like "Island" And weight <= 2 Then
TotalCost = 1.3
ElseIf Location Like "Island" And weight > 2 Then
weight = Round(weight, 0)
c = weight - 2
Do While c > 0
c = c - 1
d = d 1
Loop
TotalCost= tmx * ((d * 0.7) 1.3)
End If
End Function
Комментарии:
1. Это не может работать, поскольку
Text
это недопустимый тип переменной. Вам нужноString
. Попробуйте также объявить возвращаемый типDouble
.Function TotalCost(...) as double
. Я думаю, что есть более простой способ сделать это, хотя и не уверен на 100%, что вы на самом деле делаете.2. Пожалуйста, старайтесь правильно расставлять отступы при публикации, иначе ваш код будет трудно просмотреть.
3. Обратите внимание, что в одном из ваших случаев
TotalCostSkyWalk
нетTotalCost
Также вашиInteger
типы, вероятно, должны бытьDouble
s
Ответ №1:
Что-то более похожее на это могло бы быть лучше:
Function TotalCost(ByVal tmx As Integer, ByVal weight As Double, _
ByVal Location As String)
Dim base As Double, mult As Double, tot As Double, wtExtra As Double
Select Case Location
Case "Mainland"
base = 1.2
mult = 9.55
Case "City"
base = 1.1
mult = 0.55
Case "Island"
base = 1.3
mult = 0.7
Case Else
TotalCost = "?Location?"
Exit Function
End Select
If weight > 2 Then
'round up to nearest kg and subtract 2
wtExtra = Application.Ceiling(weight, 1) - 2
TotalCost = tmx * ((wtExtra * mult) base)
Else
TotalCost = base
End If
End Function
Комментарии:
1. Это решение отлично справилось с задачей. Большое вам спасибо за вашу помощь и приношу извинения за мои ошибки новичка, я все еще новичок в VBA и здесь, поэтому я все еще учусь.
Ответ №2:
Вы можете выполнить свои вычисления с помощью относительно простой формулы, но для этого требуется небольшая подготовка, часть которой такая же, какая понадобится и для UDF. Вот формула. Я подробно объясню это ниже.
=VALUE(INDEX(Rates,1,MATCH($F$2,$B$1:$D$1)) (INDEX(Rates,2,MATCH($F$2,$B$1:$D$1))*(-INT($G$2/-2)-1)))*INT(MAX($H$2,1))
Сначала настройка.
- Я поместил таблицу, которую вы опубликовали в своем вопросе, в диапазон A1: D3.
- Я создал именованный диапазон для чисел, B1: D3, и назвал его Rates
- Затем я создал раскрывающийся список проверки в F2, который ссылается на диапазон B1: D1 («Город», «Материк», «Острова»)
- Я отметил ячейку G2 для ввода веса
- И H2 для ввода количества посылок.
Далее подготовка.
- [G6] =MATCH(F2,B1: D1) возвращает 1, 2 или 3 в зависимости от того, что выбрано в F2
- [G7] =(-INT(G2 /-2) -1) возвращает количество доплат за дополнительный вес, например 0 для чего-либо до 2 (кг), 1 для 2.1 -4.0, 2 для 2.1 -6.0 и т.д.
- [G5] =INT(MAX(H2,1)) Все эти формулы должны быть протестированы по отдельности путем проверки их результатов при изменении F2: H2. (Я это сделал.) Это приводит к базовой формуле.
=INDEX(Rates,1,G6) (INDEX(Rates,2,G6)*G7)
и, поскольку это строка,
=VALUE(INDEX(Rates,1,G6) (INDEX(Rates,2,G6)*G7))
и, чтобы умножить на количество участков,
=VALUE(INDEX(Rates,1,G6) (INDEX(Rates,2,G6)*G7))*G5
Теперь все, что осталось сделать, это заменить G5, G6 и G7 в приведенном выше примере формулами в G5, G6 и G7. Затем добавьте знаки $, чтобы включить копирование формулы, и вы получите результат, предложенный первым выше.
Комментарии:
1. Я хочу, чтобы это была функция в виде надстройки, чтобы я мог использовать ее более гибким способом. Спасибо вам за ваше время, несмотря ни на что!