Argument not optional, how can I change it? - vba

I'm getting a message Argument not optional running the code below:
Private Sub CommandButton1_Click()
Dim linia As AcadLine
Dim Pt1(0 To 2) As Double
Dim stopien(0 To 3) As Double
Dim segment As Variant
Dim n As Double
Dim h As Double
n = CDbl(TextBox1)
h = CDbl(TextBox2)
Pt1(0) = 10# '
Pt1(1) = 10# '
Pt1(2) = 0# '
segment = Pt1
For Licznik = 0 To n - 1
stopien(0) = segment(0)
stopien(1) = segment(1)
stopien(2) = segment(0) + h
stopien(3) = segment(1)
Set linia = ThisDrawing.ModelSpace.AddLine(stopien)
segment(0) = stopien(2)
segment(1) = stopien(3)
Next
End Sub
I can debug it , but if I write something in the TextBox1 or TextBox2 I get this message.
I don't know how I can fix it

The error message is telling you exactly what the issue is... namely, that you are not supplying a needed argument. In this case, the offending line is below:
Set linia = ThisDrawing.ModelSpace.AddLine(stopien)
The AddLine method takes both a StartPoint and an EndPoint, and you are only supplying one of them.

CDbl to the textbox.. hmm.. Shouldn't that be Textbox1.value ? I think you need more uh error handling on the input for Textbox1 and Textbox2.
For example do something like this before you start converting - so put a breakpoint on your first value set of n = CDbl(Textbox1). Then make sure you can see the debug / immediate views in VBA editor. Then write something like this or add Textbox1 to a watch, and expand it's properties to make sure you are using the object's values correctly.
Debug.print(Textbox1)
Debug.print(Textbox1.value)
To handle problems in conversion or w/e, you want to add error handles to the value checks before you set the values to variables.
MrExcel classic discussion on userform handling input errors

Related

CATIA VBA Measure a user selected line(s)/spline

I am trying to get the length of user selected lines/splines
This is the code I'm using to have users select their lines:
Dim USel As Selection
Dim USelLB
Dim InputObject(0)
InputObject(0) = "AnyObject"
Set USel = CATIA.ActiveDocument.Selection
Set USelLB = USel
USel.Clear
USelLB.Clear
Linestomeasure = USelLB.SelectElement3(InputObject, "Select objects to list names", True, CATMultiSelTriggWhenUserValidatesSelection, False)
Linestomeasure is a public variable, in the mainsub i've been trying to measure Linestomeasure using the following code:
Dim pd1 As PartDocument
Dim a As Object
Dim c As Reference
a = TrimLines.Item(1)
c = pd1.Part.CreateReferenceFromObject(a)
Dim Mea1 As Measurable
Dim TheSPAWorkbench As SPAWorkbench
Set TheSPAWorkbench = pd1.GetWorkbench("SPAWorkbench")
Set Mea1 = TheSPAWorkbench.GetMeasurable(c)
But when I run the code a = trimLines.Item(1) gets highlighted in the debugger with the error message "Object Required".
Does anyone have an idea on how I can change my code so that I can get the length of the line as a variable that I can work with ? Or just a different way to go about what I'm trying to do?
Edited answer to reflect comment bellow
Looks like you are assigning the wrong type of variable to the USelLB.SelectElement3 and also missunderstanding how it actually works.
The Selection.SelectElement3 returns a String that reflects whether the selection was sucessfull or not.
The Object retrieved from the Selection is inside the Selection.Item(Index)
Your code should be something like this:
Dim PD1 as PartDocument
Dim Sel 'as Selection 'Sometimes it is needed to comment the selection to use the .SelectElement3 method
Dim InputObjType(0)
Dim SelectionResult as string
Dim LineToMeasure as AnyObject
Dim I as Integer
Dim SpaWorkbench as SPAWorkbench
Dim Measurable as Measurable
InputObjType(0) = "AnyObject"
'set PD1 = Catia.ActiveDocument
set Sel = PD1.Selection
Set TheSPAWorkbench = pd1.GetWorkbench("SPAWorkbench")
Sel.Clear
SelectionResult= Sel.SelectElement3(InputObject, "Select objects to list names", True, CATMultiSelTriggWhenUserValidatesSelection, False)
If SelectionResult = "Ok" or SelectionResult = "Normal" then 'Check if user did not cancel the Selection
For i = 1 to Selection.Count
Set LineToMeasure = Sel.Item(i).Value
set Measurable = SpaWorkbench.GetMeasurable(LineToMeasure)
'Measure whatever you need here.
Next
End If
Keep in mind that using the AnyObject type filter may cause the user to select unwanted objects. You shoudl use a more specific filter.

How many .ToString("N0") can I have?

I am getting a warning:
Severity Code Description Project File Line Suppression State
Warning BC42322 Runtime errors might occur when converting 'String' to 'IFormatProvider'.
I have 2 .ToString("N0") in my code in the same Sub. Can I not have 2 in the same sub? They go to different labels but, I am new to VB as well so please do not judge. Thanks!
If Integer.TryParse(input, infantry) Then
Dim hpai = Integer.Parse(frmMainGame.lblHPAI.Text, Globalization.NumberStyles.AllowThousands, Globalization.CultureInfo.InvariantCulture)
frmMainGame.lblHPAI.Text = (hpai - infantry * 2).ToString("N0")
frmMainGame.lblInfantryNumberPlayer.Text -= input.ToString("N0") '<---- One that gets the warning
Else
' handle not an int inputted case
End If
Let's look at this line:
frmMainGame.lblInfantryNumberPlayer.Text -= input.ToString("N0")
You're applying the -= operator to STRINGS. This operator has no meaning for strings. Are you trying to apply some kind of reverse-concatenation? Removing any occurrence of input from within the label text? That code just doesn't make sense at all.
If you're actually trying to do a numeric operation, you need to actually work with numbers... convert the label string to an integer, not the integer to a string.
If Integer.TryParse(input, infantry) Then
Dim hpai = Integer.Parse(frmMainGame.lblHPAI.Text, Globalization.NumberStyles.AllowThousands, Globalization.CultureInfo.InvariantCulture)
frmMainGame.lblHPAI.Text = (hpai - infantry * 2).ToString("N0")
Dim numPlayer = Integer.Parse(frmMainGame.lblInfantryNumberPlayer.Text)
frmMainGame.lblInfantryNumberPlayer.Text = (numplayer - input).ToString("N0") '<---- One that gets the warning
Else
' handle not an int inputted case
End If

Why is assigning the Value property of cell causing code to end aburptly?

Private Sub FillRow(programCell As Range, storedProgramCell As Range)
Dim counter As Integer
For counter = 3 To 9
Dim cellOffset As Integer
cellOffset = counter - 3
Dim currentStoredCell As Range
Set currentStoredCell = storedProgramCell.Offset(0, cellOffset)
Dim value As String
value = currentStoredCell.value
Dim currentTargetCell As Range
Set currentTargetCell = programCell.Offset(0, cellOffset)
MsgBox currentStoredCell.value 'Works correctly, prints correct value
currentTargetCell.value = value
Next counter
End Sub
The line:
currentTargetCell.value = value
causes the code to stop executing, with no error.
I added the expression to my watch list, then stepped through the routine. The expression was seen as a Boolean:
This makes me think the expression is being viewed as a comparison, and the program abruptly ends since the returned Boolean is not being stored or used anywhere. I wouldn't doubt if I were wrong though.
I'm new to VBA, struggling to debug my program, so please forgive me if this is a petty mistake. I couldn't find any sources online that explains this problem.
Replace your subroutine with following code:
Private Sub FillRow(Dst As Range, Src As Range)
Dim x As Integer
Dim v As Variant
Dim Srcx As Range
Dim Dstx As Range
Debug.Print "FillRow"
Debug.Print Src.Address
Debug.Print Dst.Address
Debug.Print "Loop"
For x = 0 To 6
Debug.Print x
Set Srcx = Src.Offset(0, x)
Debug.Print Srcx.Address
v = Srcx.Value
Debug.Print TypeName(v)
Set Dstx = Dst.Offset(0, x)
Debug.Print Dstx.Address
Dstx.Value = v
Next
Debug.Print "Completed"
End Sub
Run and post in your question Immediate window output.
Value is a reserved word, even if vba does not raise an error on this name, you should not use it. Name it something else. Also, try setting it as a variant.

Is possible to ignore the TextBox?

I'm creating a program to calculate the average. There are 12 TextBox and I want to create the possibility to leave some fields blank. Now there are only errors and the crash of the program. Is possible to create that?
This is part of code:
ItalianoScritto = (TextBox1.Text)
MatematicaScritto = (TextBox2.Text)
IngleseScritto = (TextBox3.Text)
InformaticaScritto = (TextBox4.Text)
ScienzeScritto = (TextBox5.Text)
FisicaScritto = (TextBox6.Text)
MediaScritto = (ItalianoScritto + MatematicaScritto + IngleseScritto + InformaticaScritto + ScienzeScritto + FisicaScritto) / 6
Label10.Text = Str(MediaScritto)
If i leave blank the textbox1 when I click on the button to calculate the average Vb says Cast not valid from the string "" to type 'Single' and the bar of te textbox1 become yellow
I would do the following:
Iterate over the textboxes and check if you can parse the value into an iteger. If yes, add it to a value list.
Then add all values from that list and divide it by the number of cases.
It is faster than big if-statements and resilient against error
dim TBList as new list(of Textbox)
'add your textboxes to the list here
TbList.add(Textbox1)
...
dim ValList as new List(Of Integer)
for each elem in Tblist
dim value as integer
If integer.tryparse(elem.text,value)=True
ValList.add(Value)
else
'report error or do nothing
end if
next
dim Result as Integer
Dim MaxVal as Integer =0
for each elem in ValList
Maxval +=elem
next
Result = MaxVal / ValList.count
If you need support for point values, just choose double or single instead of Integer.
Also: regardless what you do -CHECK if the values in the textboxes are numbers or not. If you omit the tryparse, somebody will enter "A" and your app will crash and burn
Also: You OPTION STRICT ON!
You just have to check if the TextBox is blank on each one before using the value:
If TextBox7.TextLength <> 0 Then
'Use the value inside
End If
The way to do it depends a lot of your code. You should consider editing your question giving more information (and code) in order to us to help you better.

integer to string problems

I'm trying to make a slot machine program. This procedure that I'm trying to do will assign a name to 3 randomly generated numbers. For some reason I'm getting a conversion error saying that it cant convert the integer to a string. I tried cstr() as well but the problem persisted
Sub GenerateNumbers()
Dim numbers(2) As Integer
Dim names(5) As String
Dim x As Integer
names(0) = "Cherries"
names(1) = "Oranges"
names(2) = "Plums"
names(3) = "Bells"
names(4) = "Melons"
names(5) = "Bar"
For x = 0 To 2
numbers(x) = names(CInt(Int((6 * Rnd()) + 1)))
Next x
End Sub
gives me error: conversion from string "Oranges" to type 'Integer' is not valid
The problem is that you are getting a random string from the names array and trying to assign it to numbers, which is declared as an array of integers. Of course this is not gonna work.
Apart from that, there is also the issue with out of bounds index as Eric pointed out.
Edit in response to comments:
To get the text values of those randomly generated slot machine results you just need to declare the array to store results as strings, same way as names is declared.
To be able to get the results from a separate procedure, you need to change it from Sub to Function, which is a procedure that can return a value, an array of strings in this case. Then you can call this function from your Main or any other procedure and store the returned value in a variable.
I also corrected the part with random result generation.
Module SlotMachine
Sub Main()
Dim slotResults As String()
'Get the results
slotResults = GenerateResults()
'Some further processing of results here, e.g. print results to console
For Each item In slotResults
Console.WriteLine(item)
Next
'Wait for keypress before closing the console window
Console.ReadLine()
End Sub
'Generates random results
Function GenerateResults() As String()
Dim results(2) As String
Dim names(5) As String
Dim x As Integer
names(0) = "Cherries"
names(1) = "Oranges"
names(2) = "Plums"
names(3) = "Bells"
names(4) = "Melons"
names(5) = "Bar"
Randomize()
For x = 0 To 2
results(x) = names(Int(6 * Rnd()))
Next x
Return results
End Function
End Module
Int(6 * Rnd()) will get you 0-5, if you +1, then overflow