Why is (L \ 12) calculating to 0? - vba

I am trying to do calculations through VBA.
I am doing it through the form itself because when Production creates one of these Job Tickets a number of fields can change on the fly. Which Unit of Measure we are running in, which type of Wood, how we Wrap it, etc.
All of these changes affect the total footage or amount of pieces we have to run, which is why I have If-Then-Else statements for them.
It works until I get to Wrap SQ Footage. I get a zero inserted into my field, but when I do the calculations on my own I never get 0.
I created this expression in the control source of one of the Wrap SQ Footages, and it comes out correctly.
=Abs(Int( (([Wrap_Slit1]/12) * [Quantity_Ordered] ) * ( [RIP_Scrap_Rate] + 1))))
Private Sub FTG_Calculations()
'Declare Variable
Dim L As Double
Dim Length As Double
Dim OrderFTG As Double
Dim UoM As String
Dim W As Double
Dim frm As Access.Form
Set frm = Forms!Frm_JobTicket
'Set L equal to Length from Tbl_JobTicketMould
L = DLookup("Length", "Tbl_JobTicketMould", "Access_ID =" & Forms!Frm_JobTicket!Part_Number)
'Convert Length to Feet
Length = (L \ 12)
'Find Unit of Measure for this part
UoM = DLookup("Unit_of_Measure", "Tbl_JobTicketUoM", "Access_ID =" & Forms!Frm_JobTicket!Part_Number)
'Mupltiply Length times Quantity to get Order Footage
OrderFTG = Int((Length * Me.Txt_Pcs_JobTicket))
'If UoM is PCS then insert that number. Otherwise set equal to Quantity Ordered divided by Length of piece(in FT)
If UoM = "PCS" Then Me.Txt_Pcs_JobTicket = Me.Quantity_Ordered Else: Me.Txt_Pcs_JobTicket = Abs(Int(Me.Quantity_Ordered \ Length))
'Define limits of the loop. Then runs through all Wrap SQ FTG fields and inputs calculation
For W = 1 To 3
'If UoM is PCS then calculate Order Footage to find Wrap Sqaure Footage. Otherwise take slit size in FT and multiply by Order Quantity and Scrap Rate
If UoM = "PCS" Then
frm("Txt_Wrap" & W & "SQFTG_JobTicket") = (((frm("Wrap_Slit" & W) \ 12) * OrderFTG) * (Round((frm("RIP_Scrap_Rate")), 3) + 1))
Else: frm("Txt_Wrap" & W & "SQFTG_JobTicket") = (((frm("Wrap_Slit" & W) \ 12) * frm(Quantity_Ordered)) * (frm(RIP_Scrap_Rate + 1)))
End If
Next W
I figured out the issue is in the (frm("Wrap_Slit" & W) \ 12) area. Wrap_Slit1 shows a value of 2 in the data tips, but when I divide by 12 it comes out to 0.
All of my data points are set to double, and the variables are declared as double. It is rounding down when it should come out to .16667.

Place the following code before the:
If UoM = "PCS" Then
Msgbox code:
MsgBox("Current State:" & vbCrLf & _
"UoM:" & vbTab & UoM & vbCrlf & _
"OrderFTGL" & vbTab & OrderFTG & _
"Wrap_Slit1:" & vbTab & Me.Wrap_Slit1 & _
... continue pattern for other desired values in calculation...
"Continue...", vbOK)

Related

Showing the name of the most expensive product in vb

i'm pretty new to programming and i got stuck trying to write a program where you type in the name and prices of products and you get back the total, the name+ prices and the most expensive product. Everything works fine except showing the name of the most expensive product.
Here's what i've done
""
Public Class Mrj
Shared Sub main()
Dim i, n As Integer
Console.WriteLine("Enter the number of products")
n = Console.ReadLine()
Dim Products_name(n) As String
Dim Products_price(n), HT, TTC, TVA, max As Decimal
For i = 1 To n
Console.WriteLine("Enter the name of the product " & i)
Products_name(i - 1) = Console.ReadLine()
Console.WriteLine("Enter the price of the product " & i)
Products_price(i - 1) = Console.ReadLine()
HT = HT + Products_price(i - 1)
Next
For i = 1 To n
Console.WriteLine(Products_name(i - 1) & " " & Products_price(i - 1))
Next
TVA = 0.2 * HT
TTC = HT + TVA
Console.WriteLine("Total to pay " & TTC)
max = Products_price(0)
For i = 1 To n - 1
If max > Products_price(i) Then
Else
max = Products_price(i)
End If
Next
Console.WriteLine("The product the most expensive is" & max & Products_name(i))
End Sub
End Class
""
I think the problem is that you are using i to get the name of the most expensive product, but that index i is always i = n since you don't save the index of the maximum value.
You should add a new variable where you store the index everytime you get a new maximum value, and use it in the last line.
Your for loop should be something like this:
Dim max_index As Integer
For i = 1 To n - 1
If max > Products_price(i) Then
Else
max = Products_price(i)
max_index = i
End If
Next
Console.WriteLine("The product the most expensive is" & max & Products_name(max_index))
Try this out and check if it works.
Turn on Option Strict now and forever. Project Properties -> Compile tab. Also for future projects Tools -> Options -> Projects and Solutions -> VB Defaults
You cannot assume that a user will actually enter a number. Test with TryParse.
Arrays in vb.net are declared Products_name(upper bound). In this case that would be Products_name(n-1)
Instead of doing i - 1 for the indexes in the For loop, start our with For i = 0 to n-1
I decided to not use the parallel arrays. Instead I made a tiny class and declared a List(Of Product). I filled the list with the user input setting the Properties of the Product.
I used Linq instead of loops for sums and max. Not necessarily faster but can be accomplished in a single line of code.
I use interpolated strings to display results. When your string is preceded by a $, you can insert variables directly in the text surrounded by braces. The colon following Price indicates a formatting character. Here, I used a C for currency.
Public Class Product
Public Property Name As String
Public Property Price As Decimal
End Class
Sub main()
Dim ProductList As New List(Of Product)
Dim n As Integer
Console.WriteLine("Enter the number of products")
Integer.TryParse(Console.ReadLine, n)
For i = 1 To n
Dim p As New Product
Dim pr As Decimal
Console.WriteLine("Enter the name of the product " & i)
p.Name = Console.ReadLine()
Console.WriteLine("Enter the price of the product " & i)
Decimal.TryParse(Console.ReadLine, pr)
p.Price = pr
ProductList.Add(p)
Next
For Each p In ProductList
Console.WriteLine($"{p.Name} {p.Price:C}")
Next
Dim SubTotal As Decimal = ProductList.Sum(Function(item) item.Price)
Dim Tax As Decimal = 0.2D * SubTotal
Dim Total = SubTotal + Tax
Console.WriteLine($"Total to pay {Total:C}")
Dim Prod = ProductList.OrderByDescending(Function(p) p.Price).FirstOrDefault()
Console.WriteLine($"The product the most expensive is {Prod.Name} at {Prod.Price:C}")
Console.ReadKey()
End Sub

Compile Error At IfError in VBA Code of Nested WorksheetFunctions

So, I'm quite new to VBA and I'm trying to learn. I have several tables with fastener data that I'm trying to pull information from based on what's in the main input table. I have a formula that works, but as I add different fastener tables, the nested IF formula is getting unruly. I decided to try to convert the formula to VBA and I'm getting an error: "Compile error: Wrong number of arguments or invalid property assignment." It shows up at the IfError. I may also have called the table columns incorrectly. The formula that I am trying to convert is included below. I haven't yet determined how best to set up the If statement so that if the user selected IFF, it would switch to using the IFF table, but that's another post.
Dim tbl_Solid As ListObject
Dim Rep_Fast_Type
Dim Incoming_Dia
Dim BP_Max_Dia
Dim Test_Dia
Dim Rep_Fast
Dim Test_Value
Dim i
Set tbl_Solid = ThisWorkbook.Sheets("Fastener DB").ListObjects("tbl_Solid")
i = 1
Incoming_Dia = [tbl_Input].Cells(i, 2)
BP_Max_Dia = [tbl_Input].Cells(i, 3)
Rep_Fast_Type = [tbl_Input].Cells(i, 4)
If Incoming_Dia > BP_Max_Dia Then
Test_Dia = Incoming_Dia
Else
Test_Dia = BP_Max_Dia
End If
'Compile error at IfError in third line.
If Rep_Fast_Type = "Solid" Then
Rep_Fast = WorksheetFunction.Index([tbl_Solid].Range("Fastener"), _
WorksheetFunction.Aggregate(15, 6, WorksheetFunction.IfError( _
Rows([tbl_Solid].Range("Fastener")) / ((Test_Dia >= [tbl_Solid].Range("min")) * (Test_Dia <= [tbl_Solid].Range("max"))), _
Rows([tbl_Solid].Range("Fastener")) / (Test_Dia <= [tbl_Solid].Range("min")), 1)))
End If
'To test values
MsgBox "Incoming diameter is " & Incoming_Dia & vbCrLf & "B/P max diameter is " & BP_Max_Dia & vbCrLf & "Test diameter is " & Test_Dia & vbCrLf & "Repair fastener type is " & Rep_Fast_Type & vbCrLf & "Repair Fastener is " & Rep_Fast
Old Excel Formula:
=IF([#[rep type]]="Solid",INDEX(tbl_Solid[[#All],[Fastener]],AGGREGATE(15,6,IFERROR(ROW(tbl_Solid[Fastener])/(([#diameter]>=tbl_Solid[min])*([#diameter]<=tbl_Solid[max])),ROW(tbl_Solid[Fastener])/([#diameter]<=tbl_Solid[min])),1)),IF([#[rep type]]="IFF",INDEX(tbl_IFF[[#All],[Fastener]],AGGREGATE(15,6,IFERROR(ROW(tbl_IFF[Fastener])/(([#diameter]>=tbl_IFF[min])*([#diameter]<=tbl_IFF[max])),ROW(tbl_IFF[Fastener])/([#diameter]<=tbl_IFF[min])),1))))
Screenshot of Data
It was just a parenthesis wrongly placed:
replace this line:
Rows([tbl_Solid].Range("Fastener")) / (Test_Dia <= [tbl_Solid].Range("min")), 1)))
with for this:
Rows([tbl_Solid].Range("Fastener")) / (Test_Dia <= [tbl_Solid].Range("min"))), 1))
Nevertheless, I would suggest to use the With statement to wrap the formula, i.e.:
With WorksheetFunction
Rep_Fast = .Index([tbl_Solid].Range("Fastener"), _
.Aggregate(15, 6, .IfError( _
Rows([tbl_Solid].Range("Fastener")) / _
((Test_Dia >= [tbl_Solid].Range("min")) * (Test_Dia <= [tbl_Solid].Range("max"))), _
Rows([tbl_Solid].Range("Fastener")) / (Test_Dia <= [tbl_Solid].Range("min"))), 1))
End With
Note that this answer refers only to the syntax that gives the compile error, no test have been performed to the formula output.

Division with decimals below zero vb.net

I'm writing a program in vb.net which allows the user to input an amount of money and then outputs the minimum number of coins that are needed to make that amount. For example if the user inputs £3.43 the program would output 1 x £2, 1x £1, 2x £20p, 1x 2p and 1x 1p.
I have the program working for one and two pound coins but as soon as the program checks for smaller coins (E.G. below £1) the program doesn't recognize anything. The program uses division and modulus to do this, for each coin it divides the amount by the value of the coin (ignoring the remainder), sets the value of a variable named "remainder" as the amount modulus by the value of the coin and resets the amount to the value of the remainder
The code is below:
Public Class MinimumCoins
Dim ammount As Decimal
Dim TwoPound As Integer
Dim OnePound As Integer
Dim fifty As Integer
Dim twenty As Integer
Dim ten As Integer
Dim five As Integer
Dim two As Integer
Dim one As Integer
Dim remainder As Decimal
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
ammount = InputBox("Enter Ammount")
TwoPound = ammount \ 2
remainder = ammount Mod 2
ammount = remainder
OnePound = ammount \ 1
remainder = ammount Mod 1
ammount = remainder
remainder = remainder * 100
fifty = ammount \ 50
remainder = ammount Mod 50
ammount = remainder
twenty = ammount \ 20
remainder = ammount Mod 20
ammount = remainder
ten = ammount \ 10
remainder = ammount Mod 10
ammount = remainder
five = ammount \ 5
remainder = ammount Mod 5
ammount = remainder
two = ammount \ 2
remainder = ammount Mod 2
ammount = remainder
one = ammount \ 1
lblOutput.Text = TwoPound & " X" & " £2.00" & vbNewLine & OnePound & " X" & " £1.00" & vbNewLine & fifty & "X" & " 50p" & vbNewLine & twenty & " X" & " 20p" & vbNewLine & ten & " X" & " 10p" & vbNewLine & five & " X" & " 5p" & vbNewLine & two & " X" & " 2p" & vbNewLine & one & " X" & " 1p"
End Sub
End Class
The first two times the program is run (for one pound and two pound coins) it works perfectly fine but then the program displays no coins are needed for any amount smaller than £1.
You set your ammount to the remainder of the Mod 1 (so for an input of 2.53, your ammount is now 0.53)
Then you multiply remainder by 100 and store it back into remainder, so remainder is 53, ammount is still 0.53..
And then you carry on doing maths on the ammount of 0.53, so your program is going to be asking these questions:
"How many times does 50p go into 0.53p?" 0
"How many times does 20p go into 0.53p?" 0
"How many times does 10p go into 0.53p?" 0
And so on..
I haven't given you the exact answer to your problem, but there's enough in here to work it out - it'll be a better learning exercise for you if you think that last part through yourself, rather than me just giving you the answer directly :)
Good luck

VB InputBox Validation Inquiry

I know InputBox isn't the best for validation, but that was one of the specifications on the program I am writing for class. My problem is that despite the if or case statements I make to validate the data entered, it still accepts the data while simultaneously displaying the MsgBox's I have in my code..
Essentially what I would like the case statement to do is to properly filter the data that is entered and not proceed onto the next floor if the data is invalid and request that new data be entered. If the data is valid, proceed onto the next floor.
Const ROOMS As Integer = 30
Const MAX_FLOOR As Integer = 16
Dim floor As Integer
Dim StrOccupancy As String
Dim occupancy As Integer
Dim occupancyRate As Double
Dim occupancySum As Integer
Dim overallRate As Double
lblOccupancyRate.Text = String.Empty
lblRoomsOccupied.Text = String.Empty
output.Items.Clear()
For floor = 1 To MAX_FLOOR
If floor = 13 Then
Continue For
End If
StrOccupancy = Integer.TryParse(InputBox("Enter the number of rooms occupied for floor:" & Space(1) & floor), occupancy)
Select Case occupancy
Case < 1
MsgBox("Please enter a number of 1 or more occupants.")
Case > 30
MsgBox("Amount of occupants must be between 1-30.")
Case >= 1 And occupancy <= 30
occupancyRate = (occupancy / ROOMS)
occupancySum += occupancy
overallRate = occupancySum / (ROOMS * 15)
End Select
output.Items.Add("Floor: " & floor & " Rooms Occupied: " & occupancy _
& " Occupancy Rate: " & occupancyRate.ToString("P2"))
lblRoomsOccupied.Text = occupancySum.ToString
lblOccupancyRate.Text = overallRate.ToString("P2")
Next
output.Items.Add("")
output.Items.Add("Total occupancy is" & Space(1) & occupancySum & Space(1) & "and" & Space(1) & overallRate.ToString("P2") & Space(1) & " of rooms are full.")
End Sub
Had a little time to check your code and actually you need a Boolean that validates if the occupancy requirements are met and loop if not. The code would be something like this:
For floor = 1 To MAX_FLOOR
'Boolean to validate the occupancy meet the requirements
Dim goodOccupancy As Boolean = False
'Do loop enters at least 1 time and runs the code inside it
Do
Integer.TryParse(InputBox("Enter the number of rooms occupied for floor:" & Space(1) & floor), occupancy)
Select Case occupancy
Case < 1
MsgBox("Please enter a number of 1 or more occupants.")
Case > 30
MsgBox("Amount of occupants must be between 1-30.")
Case >= 1 And occupancy <= 30
occupancyRate = (occupancy / ROOMS)
occupancySum += occupancy
overallRate = occupancySum / (ROOMS * 15)
'If the requirements are met we change the Boolean value to continue with the execution
goodOccupancy = True
End Select
'We loop if the requirements are not met
Loop Until goodOccupancy = True
output.Items.Add("Floor: " & floor & " Rooms Occupied: " & occupancy _
& " Occupancy Rate: " & occupancyRate.ToString("P2"))
lblRoomsOccupied.Text = occupancySum.ToString
lblOccupancyRate.Text = overallRate.ToString("P2")
Next
But please next time try to be more explicit with your code. Most of people won't check what is going on. Do not expect people to solve your problems without guidance. Please read the How to ask guide it will give you a light to use the site as it is supposed to be used

VBA ACCESS Comparing String as they are integer

I am trying to prompt the user to input a range and display all the instruments that are within that range in a subform.
Problem: The upper and lower range is a text field (because some of the range cannot be expressed in integer). As seen in the screenshot, the comparison only compare the first character of the field.
User's input: 5 - 3
On the subform: 36 - 4
It compares 5 and 3 instead of 36
I know vba is doing what it has been told but how can I achieve the result I want?
Here is my code for requering the subform:
Dim Up As Integer
Dim Low As Integer
If Me.Text_L = "" Or IsNull(Me.Text_L) Or Me.Text_U = "" Or IsNull(Me.Text_U) Then
MsgBox ("Please choose a valid range!")
Else
Up = Me.Text_U
Low = Me.Text_L
SQL = SQL_Origin & " WHERE [qry_View_Search].[Upper_Range] <= '" & Up & "' " _
& "AND [qry_View_Search].[Lower_Range] >= '" & Low & "';"
subform_View_Search.Form.RecordSource = SQL
subform_View_Search.Form.Requery
End If
so what i did is made a new column in the query for
IIf(IsNumeric([Upper]), Val([Upper]), Null)
to get all the numeric result.
Then in the vba, I re query the subform as below
SQL = SQL_Origin & " WHERE [qry_View_Search].[Upper] <= cint(Forms![frm_View_Search]![Text_U]) " _
& "AND [qry_View_Search].[Lower] >= cint(Forms![frm_View_Search]![Text_L]);"
Thanks #HansUp !
I have successfully for those cases used Val only:
Value: Val([FieldName])
or:
Value: Val(Nz([FieldName]))