Adding Items in a listbox visual basic - visual-studio-2010

I'm making a cash register for homework and all the transactions are listed in a listbox (the amount)
Now I know how to add this up using a for loop, but the course has not even gone into loops yet so If i use loops I might lose marks
For example
55.34
43.13
12.43
The only way I can think of adding all these up to get the total is using a for loop, since I do not know how many transactions will be there.
Maybe there is a listbox function that I do not know of?
This is how items are added to the listbox
Private Sub enterTaxable_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles enterTaxable.Click
conversion = textDollars.Text + "." + textCents.Text
taxable = CDbl(conversion)
tax = taxable * 0.07
taxable = tax + taxable
taxable = FormatNumber(taxable, 2)
salesSlip.Items.Add(taxable)
textDollars.Text = ""
textCents.Text = ""
End Sub
salesSlip is my listbox name

There is no function of the the ListBox control to facilitate this for you, and any control that will is going to be very specific and even less common than the knowledge of loops that you report hasn't been taught yet; therefore, you're in he same predicament!
Use a loop.
If your teacher hasn't given the means you need otherwise, then approach them about it and enquire.

Related

Beginners Visual Basic Help: I am to create a simple "game" which prompts a user to enter a number 1-10. That number must be stored

Beginners Visual Basic Help: I am to create a simple "game" which prompts a user to enter a number 1-10. That number must be stored. Then the real game begins, Using a loop have the user try to guess the number stored. Notify if the guess is too high, too low, or correct. Continue loop until correct.
I am very stuck right now; all I have is-
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim mynumber, input As Integer
mynumber = Val(TextBox1.Text)
input = TextBox1.Text
Please Help I Know this is very simple but this class is very complicated for me.
So, to start off I'm going to use your variables and we're going to declare these so the whole of the form can access them.
Dim mynumber As Integer
Dim input As Integer
We're also going to declare a seperate variable which will count the amount of times that the user has tried to guess the number, and also the number that they are going to be guessing which in this case is declared as guessnumber
Dim counter As Integer
Dim guessnumber As Integer
You want to create a button and call it btnNewGame which will start the game playing and this is going to be the code that you'll add to that button:
Dim mynumber As Random
guessnumber = Number.Next(10) + 1
This will create the random number and have it change to a new value when the new game button is clicked, so no game is the same.
We want to initialize the counter now so that whenever a new game is started then the amount of guesses that the user has had is 0 and we also want to initialize the textbox so that it is empty when the new game button is clicked.
counter = 0
txtInput.Text = ""
So now, underneath a separate play button we want to add this code
Dim uni As Integer
uni = CInt(txtInput.Text)
counter = counter + 1
Now lets add in a 'Try' function which will run through until the user has either guessed the number or exceeded the amount of turns which is 3. You can easily alter the amount of turns.
Try
If uni = guessnumber Then
MessageBox.Show("You guessed my Number!")
ElseIf uni < guessnumber Then
MessageBox.Show("Your guess is too low")
ElseIf uni > guessnumber Then
MessageBox.Show("Your guess is too high.")
End If
Catch E1 As InvalidCastException
MessageBox.Show("Please enter a number and try again.")
End Try
Hope this helps you, please let me know how you get on!

VBA loop efficiency

I've used the answers found in the site a TON of times, but this is my first post.
Is it more efficient to perform a for loop inside a function or sub or to just send the incremented value of the loop into the function or sub as an argument?
I am importing some text data files into Excel, parsing out the various fields, and then splitting some of the fields into individual characters. One file I am using is a list of doctors. I have name, address, phone, DEA number, NPI, etc.
When checking the DEA number, I have a sub that receives the line number to be checked that splits the DEA into its individual digits, perform checking on these digits one at a time and then modify another field with the status of that DEA. This status cell will be colored red if it contains anything but the word "GOOD". Also, I am coloring the individual digit that is bad, if applicable.
This one sub is doing a lot and I could probably break it up a little, but there aren't any other places in the doctor file that I am performing this exact step, so I figured I should keep it like it is.
Anyways, the real question is whether I should send the line number into the sub or should I just call the sub and have the sub calculate the number of lines and do the checking. In the first case, I will call the sub a number of times equal to the number of lines in the doctor file. In the second, I will call the sub once and the sub contains the for loop for each line. Which is usually more efficient.
Apologies if I seem redundant. I train some complex software and that sort of thing leaks into other areas of life sometimes.
EDIT: I tried to add this into a comment but have insufficient experience posting here. Apologies if I violate some rule for this...
Here is the code I use currently to call the sub:
'Use the Doctor Last Name as the number of rows count
Dim numRows As Integer
numRows = Application.CountA(Sheets("DoctorDEA").Range("m:m"))
'lineCtr is the Line Counter used to iterate the FOR loops
Dim lineCtr As Integer
lineCtr = 1
'Call DEACHecking and DisplayIssues Subs
For lineCtr = 1 To numRows - 1
DEAChecking (lineCtr)
DisplayIssues (lineCtr)
Next lineCtr
My questions is this: Would it be better to just call DEAChecking with no arguments and just have DEAChecking calculate the line numbers and then use the FOR loop or to leave it as is?
This question is too broad right now to be answered effectively. So am just offering a small insight that might help you structure your program.
Typically the most efficient code is the one where all the variables are as local as possible. If inside a loop you are using globals, or calling other functions it is going to be much worse than performing all the calculation with local variables.
If you want to test each, and time them, you can use a timer. If you have a major gap, you will be able to catch it. If not, you will have your answer with no significant difference as far as processing time.
You can either use this and call your sub from TimerTest, or simply Call TimerStart at the beginning of your code and TimerStop at the end.
Run some code with the timer
Log the result
Repeat and compare
HH:MM:SS:00 format
Timer Code:
Public strStartTime As String
Public strEndTime As String
Public startTime As Date
Public endTime As Date
Sub timeTest()
Call TimerStart
'INSERT CALL TO YOUR SUB HERE
Call TimerStop
End Sub
Sub TimerStart()
startTime = Now
End Sub
Sub TimerStop()
endTime = Now
'Waited until the timer stopped to perform any additional code, such as formatting the time
Dim TotalTime As String
strStartTime = Format(startTime, "hh:mm:ss:" & Right(Format(Timer, "#0.00"), 2))
strEndTime = Format(endTime, "hh:mm:ss:" & Right(Format(Timer, "#0.00"), 2))
TotalTime = Format(endTime - startTime, "hh:mm:ss:" & Right(Format(Timer, "#0.00"), 2))
MsgBox (" Start: " & strStartTime & vbNewLine & _
" End: " & strEndTime & vbNewLine & _
"Total Time : " & TotalTime)
End Sub
Credit: #Nick Dandoulakis for timer formatting in his answer here: Providing this solution to show clock time with accuracy of less than a second.

Make choice from combo box enable different combo box

I am new to this website, so I apologize if this question was asked and I could not find it.
I am trying to create a program using Visual Studio 2010 where if you select a word from either list A or B, (where lists and B are combo boxes), then it gets defined on the bottom of the screen.
The problem I am having is making a selection from a combo box with the choices for lists A and B enable/disable the appropriate list.
To phrase that better, I have a 3 combo box lists, one with choices "English and Hebrew", one titled cboEnglish, and one titled cboHebrew.
How do I make it so that if I select "English", then cboEnglish is enabled, and if I select "Hebrew", then THAT list is enabled?
I threw a bit of coding around, but all it accomplishes is that no matter what choice I pick, then the English gets enabled every time:
Private Sub English()
cboHebrew.Enabled = False
cboEnglish.Enabled = True
End Sub
Private Sub Hebrew()
cboEnglish.Enabled = False
cboHebrew.Enabled = True
End Sub
I had a draft where the choices English and Hebrew were buttons, which would make the coding really easy to do (The above code was copied from that version), but I did not really like how it looked.
I am fairly new to Visual Studio (like 1 1/2 months of use), so I apologize if this is a dumb question...
Figured it out. I ended up turning the main combo box into an integer, and defining each of the sub options to make the other boxes true/false using the same procedure as if I would have just been using 2 buttons to enable/disable them.
Not sure if this procedure is ideal, but hey, it works (for now)
Dim intLanguage As Integer
intLanguage = Me.cboLanguage.SelectedIndex
Select Case intLanguage
Case 0
English()
Case 1
Hebrew()
End Select
End Sub
Private Sub English()
'This attempts to enable English list
cboEnglish.Enabled = True
cboHebrew.Enabled = False
End Sub
Private Sub Hebrew()
'This attempts to enable English list
cboEnglish.Enabled = False
cboHebrew.Enabled = True
End Sub
End Class
I'm not into Visual Basic, but basically you should place your code into handler method. In your case it should SelectedIndexCHanged (see http://www.tutorialspoint.com/vb.net/vb.net_combobox.htm).
A simple if then else statement should work.
If combobox.optionA = selected Then
comboxBox.optionB = false
Else comobox.optionB = selected then
comboxBox.optionA = false
END if

use of goto versus runtime code evaluation

Recently for a programming class, we were given the assignment to write a program in any language that, given n, will produce all the possible derangements for an array p of size n such that p[i] != i for all i: 0 <= i < n. We had to use iterators, e.g. yield.
Example: n=3, [0, 1, 2] is not a derangement, but [2, 0, 1] is as well as [1, 2, 0].
I came up with a pseudocode solution that would work, but the problem was that it required power loops (that is, n nested loops where n is only known at runtime). To do this, I generated n nested loops in Ruby code in a string, then eval-ed the string. My solution worked, however my professor thought that using a few gotos would have been better solution (easier to read, at least) than dynamic code generation.
I was under the impression that goto was always a bad choice. Why might runtime evaluation of dynamically generated code be a worse choice than goto? The generated code is clean and simple, and seems fairly efficient for the given problem. The only user input upon which the code generation depends is n, which is checked to ensure it's an integer value beforehand. It yields only unique derangements, as it should.
I'm not asking for a solution to my programming assignment, I just want to know reasons behind the use of goto over dynamic code evaluation, or vice versa.
Edit: to clarify, the assignment included writing a program using iterators and another using recursion, so the iterative version wasn't necessarily meant to be efficient.
Both GOTO and code generation are inelegant solutions to this problem IMO. There is a recursive algorithm that is probably the right answer here.
That's a really interesting question - I'm not sure that there's a definitive answer.
The problem with goto is its use in an unstructured fashion - a goto is a "massive random leap" so in the general instance, after the jump, you don't know where you came from which causes all kinds of issues both in terms of debugging and maintainability and - in a more formal sense with proving "correctness" of the code. Of course there are languages (I've been around a while) where you don't have an option at which point you impose structure on the code. The bottom line is that its not that GOTO is bad so much as the way that goto is used (and abused) that is bad and that makes its a dangerous construct to have available.
Using code generation and then evaluating the result is clever :) However "clever" is not always a good thing and I suspect that in part the issue with using that as a solution is that its not actually addressing the problem as intended. That may be "cheating" in a sense - at least so far as your professor is concerned - doesn't invalidate your solution but may render it "inelegant". The debugging and maintainance issues also arise in respect of the code.
A recursive solution - especially as I vaguely remember being taught (some 25 years ago) that one can usually unwind recursion into loops - would probably be the most elegant.
Definitely an interesting question!
Without seeing your code, I would tend to side with the prof. If it's a choice between GoTo and dynamic code, I would lean towards the former. GoTo are not always a bad choice.
You can solve almost all problems without the use of GoTos. Specifically with loops you can use the break and continue statements to implitly use gotos while code standard are still maintained.
n nested loops sound like a bad plan, and I suggest that you instead look into a recursive functions. Every single time you need to do a n-loops you should always be thinking recursion.
Dynamic code is not compile time checkable, which means any errors will go undetected until run time. Potentially making them harder to find. For ruby, this would mean that syntax errors would not be found by the IDE or editor, whichever you happen to be using. That is a plus for choosing goto.
I think I would have to see both to make a decision in this case. I haven't seen the code, but I'm willing to bet there is a good solution that doesn't use dynamic code, or goto's. goto is not always bad, but if you are thinking of using it you probably have not made the best design decisions up to this point and probably want to revisit your solution.
In one of my assignement in college, I once had to do something that was relatively similar
My solution was to use a recursive function, passing the array, the size of the array and the nesting level as argument. The function then call itself with nesting level +1, until the nesting level is equal to the size of the array. No Goto, no code evaluation, only clean code!
Example
function computeDerangement(yourArray, loopLevel, arraySize)
{
//We check to see if the loop level is the same as the array size
//if true, then we have executed exactly n loop
if (loopLevel == arraySize) {
display(yourArray); //Display being some kind of function that show the array,
//you get the idea
} else {
while(something) {
//Here you put the logic that you execute at one level of the loop
//Then you call yourself with one more level of nesting
computeDerangement(yourArray, loopLevel + 1, arraySize);
}
}
}
Hope that help!
I have never used goto in my life, so I'm pretty sure there is always a way to avoid them
The main reason people avoid goto statements is that they can make your program more difficult to understand.
Without having seen your code, I'd guess it's more difficult to understand than the equivalent program using goto...
GOTO Solution -- a goto is convenient when simulating a function call. Here's a non-recurisve solution that simply simulates the recursive solution using a stack and a goto label to return to the point where the function call would have occurred.
See the recursive procedure (I have posted this as a separate answer) for comparison.
Option Strict On
Option Explicit On
Module Module1
Dim x As Stack
Private Sub printGeneratedList(ByVal generatedList As List(Of Integer))
For Each el In generatedList
Console.Write(el & " ")
Next
Console.WriteLine()
End Sub
Private Sub generateAux(ByVal i As Integer, ByVal n As Integer, _
ByVal generatedList As List(Of Integer))
Dim stackI As Stack(Of Integer) = New Stack(Of Integer)
Dim stackJ As Stack(Of Integer) = New Stack(Of Integer)
Dim j As Integer
StartLabel:
j = 0
If i >= n Then
printGeneratedList(generatedList)
If stackI.Count = 0 Then
Return
Else
GoTo ReturnLabel
End If
End If
While j < n
If Not j = i Then
If Not generatedList.Contains(j) Then
generatedList.Add(j)
stackI.Push(i)
stackJ.Push(j)
i = i + 1
GoTo StartLabel
ReturnLabel:
i = stackI.Pop()
j = stackJ.Pop()
generatedList.Remove(j)
End If
End If
j = j + 1
End While
If stackI.Count = 0 Then
Return
Else
GoTo ReturnLabel
End If
End Sub
Private Sub generate(ByVal n As Integer)
Console.WriteLine("Generating for n = " & n.ToString())
Dim l As List(Of Integer) = New List(Of Integer)
If n < 0 Then
Throw New Exception("n must be >= 0")
End If
generateAux(0, n, l)
End Sub
Sub Main()
generate(0)
Console.ReadLine()
generate(1)
Console.ReadLine()
generate(2)
Console.ReadLine()
generate(3)
Console.ReadLine()
generate(4)
Console.ReadLine()
End Sub
End Module
goto's are not clean. but if high performance is required, you need to break some of those coding rules sometimes...
if speed is really an important matter, for example if you want to write a library or code you have big exigeance on, you might consider using goto. for sure you have to pay attention that everything goes well.
Comment: At the end, the executing CPU does nothing else than simple jumps. Just only that the programming language / the compiler creates them. use with caution and don't mess with it.
Both the goto solution and dynamic code generation ideas are bad. This is easily solved with a recursive solution as mentioned by others. You simply recursively generate all permutations (standard recursive solution) and when generation is complete (ie at the leaf of the recursion) simply skip returning permutations that are not derangements.
Recursive solution -- here's a solution with early pruning. My only question is regarding enumerations: did he want you to create an enumerator that on each successful call would generate the next item in the list? This would probably be easiest implemented by creating a lambda version of this program - I used to do this in lisp all the time when writing query generators that would generate the next answer to a question when doing prolog-interpreter style queries.
Option Strict On
Option Explicit On
Module Module1
Private Sub printGeneratedList(ByVal generatedList As List(Of Integer))
For Each el In generatedList
Console.Write(el & " ")
Next
Console.WriteLine()
End Sub
Private Sub generateAux(ByVal i As Integer, ByVal n As Integer, _
ByVal generatedList As List(Of Integer))
If i >= n Then
printGeneratedList(generatedList)
Return
End If
For j As Integer = 0 To n - 1
If Not j = i Then
If Not generatedList.Contains(j) Then
generatedList.Add(j)
generateAux(i + 1, n, generatedList)
generatedList.Remove(j)
End If
End If
Next
End Sub
Private Sub generate(ByVal n As Integer)
Console.WriteLine("Generating for n = " & n.ToString())
Dim l As List(Of Integer) = New List(Of Integer)
If n < 0 Then
Throw New Exception("n must be >= 0")
End If
generateAux(0, n, l)
End Sub
Sub Main()
generate(0)
Console.ReadLine()
generate(1)
Console.ReadLine()
generate(2)
Console.ReadLine()
generate(3)
Console.ReadLine()
generate(4)
Console.ReadLine()
End Sub
End Module

Loading data in to a combo box is slow

I have a VB6 application with a search screen. On the search, I have 9 combo boxes. Some of the combo boxes only have a couple items, but some have a couple hundred items. It takes a long time (couple of seconds) to populate the data.
Each combo box is configured the same: Sorted = False, Style = 2 - Dropdown List
3 of the combo boxes have less that 20 items.
1 has 130 items.
4 have approximately 250 items
1 has almost 700 items.
I fill all nine combo boxes with similar code.
While Not RS.EOF
cmbX.List(i) = RS("Description")
cmbX.ItemData(i) = RS("Id")
i = i + 1
RS.MoveNext
Wend
I tried setting Visible = False but it had no effect on performance.
Is there another way to fill the combo box that will perform better than my existing method?
Here is something you can try. According to this post you can shave about 60% off your overhead by using a Windows API function to populate the combo box, instead of the usual AddItem method:
Private Const CB_ERR As Long = -1
Private Const CB_ADDSTRING As Long = &H143
Private Const CB_RESETCONTENT As Long = &H14B
Private Const CB_SETITEMDATA As Long = &H151
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal _
hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Public Sub AddItem(cmb As ComboBox, Text As Variant, Optional ItemData As Long)
Dim l As Long
Dim s As String
If VarType(Text) = vbString Then
s = Text
Else
s = Trim$(Str$(Text))
End If
l = SendMessage(cmb.hwnd, CB_ADDSTRING, 0&, ByVal s)
If l <> CB_ERR Then
SendMessage cmb.hwnd, CB_SETITEMDATA, l, ByVal ItemData
End If
End Sub
Public Sub Clear(cmb As ComboBox)
SendMessage cmb.hwnd, CB_RESETCONTENT, 0, 0&
End Sub
You might be able to shave a little more off by omitting the function call, and just calling the API function directly.
You really need to rethink your design. No user is going to want to choose between 700 items in a combo box. It'll make your app seem cluttered, if you don't correct it.
A picture always comes to my mind when I hear a situation like this:
Some suggestions:
Use With RS.
Use the Recordset object's RecordCount property rather than test for EOF on every iteration (if RecordCount = -1 then you should alter the cursor type, cursor location, etc to ensure RecordCount is supported).
Use a For..Next loop rather than maintain you own iterator variable.
Use the bang operator (!).
For example:
With RS
Debug.Assert .RecordCount >= 0
Dim counter As Long
For counter = 0 To .RecordCount - 1
cmbX.List(counter) = !Description
cmbX.ItemData(counter) = !Id
.MoveNext
Next
End With
Perhaps something else to consider is setting the combo's Sorted property to False and if sorting is required then either use the Recordset's Sort property or do the sorting at source (e.g. using an ORDER BY clause in SQL code).
You can try telling the combobox not to repaint itself while you add the new items. You can do this with WM_SETREDRAW. EDIT - apparently this didn't help, probably because the combo box is being hidden while it's filled, which probably gives you all the same benefits.
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"( _
ByVal hwnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, lParam As Any) As Long
Private Const WM_SETREDRAW = &HB
Call SendMessage(cmbX.hWnd, WM_SETREDRAW, 0, 0&)
'DO STUFF'
Call SendMessage(cmbX.hwnd, WM_SETREDRAW, 1, 0&)
Warning: lots of otherwise excellent VB6 websites tell you to use LockWindowUpdate instead. Do not do this, or you will get bugs. Also the disfavour of Raymond Chen!
Why are you prepopulating the list and then repopulating List(i) and ItemData(i)? Instead you should do the following
While Not RS.EOF
cmbX.AddItem RS("Description")
cmbX.ItemData(cmbX.NewIndex) = RS("Id")
RS.MoveNext
Wend
You will see zero performance difference between Robert Harvey's answer and the code above. For added speed, apply MarkJ's answer.
Another problem could be the cursor you are using to bring the data back from the database. Since you are loading every single item from the recordset, there is very little reason to have a server-side cursor. So you might want to specify Client side cursor when retrieving the recordset.
That does seem like a long time. How are you opening your recordsets? Are you using firehose (readonly, forward-only recordset) cursors? If you aren't, you might get some performance improvement from that. Make sure your SQL statements are ONLY returning the data they need for the combo boxes (i.e. DO NOT use a SELECT *).
If your SQL statements contain WHERE clauses or JOINS, make sure you have indexes on the appropriate fields.
If you are using ACCESS as a backend you will get an immediate speed improvement by upsizing to SQL Server Express.
'' Populate COMBOBOX
I had to wait 20 seconds to my program populate the city combo box with 80,000 records
I tried several methods but all they were worse
this was my original code
Me.txt_City.DataSource = tblCities
Me.txt_City.ValueMember = "city"
Me.txt_City.DisplayMember = "city"
and guess what, I just moved the first line of code to the end
and then the population took only 5 seconds
Me.txt_City.ValueMember = "city"
Me.txt_City.DisplayMember = "city"
Me.txt_City.DataSource = tblCities
try it

Resources