Ive been working on a checkbook application for my visual basic class and I'm a little stumped..

To preface, the values I need to mess with include:

transaction type (checking or deposit)
DTP
check number ("dep" if deposit)
payee (who check is for)
purpose of check/deposit
amount of check/deposit
user defined beginning account balance

Below is the Change I need to make to my program...

"You will create a set of either collections or arrays (your choice but use just one or the other--don't mix them) scoped at the form/module level. These structures will store all of the input data needed for your checkbook transactions except for the running balance which will continue to be stored in a single module-scoped variable. That is, every input that users made in Assignment 3 will be stored in one of these arrays but you will not store any calculated values. You will not store the transaction type but will store "Dep" or a number in the check number array which will also indicate the transaction type. The Record button will add the current sale's data to these structures using either ReDim for the arrays or an appropriate technique for the collections. (You must ReDim your arrays so that the have just enough space for the data that is in them. Declaring the arrays with a large size with no facility to resize them is not allowed. Don't forget to use the ReDim Preserve syntax to retain the existing array contents when you resize them.)"

I don't know if I make a single array for all the values or if I create a separate one for each. If its a separate one for each I don't understand why an array is needed.

Thank you in advance!!!!

I think you will need to make more than one, based on these:

You will create a set of either collections or arrays (your choice but use just one or the other--don't mix them) scoped at the form/module level. These structures...

As for your second question, an array isn't really needed, you can use a collection instead. If you are more comfortable with arrays than collections, you would probably want to use arrays.
So i read that statement as "create a set of collections or create a set of arrays."

I think you will need to make more than one, based on these:

As for your second question, an array isn't really needed, you can use a collection instead. If you are more comfortable with arrays than collections, you would probably want to use arrays.
So i read that statement as "create a set of collections or create a set of arrays."

Alright.. i figured out mostly everything but my math is still screwing me up. I need to accumulate running totals for number of checks and number of deposits ;and total value of checks and total value of deposits. Im supposed to do this by looping through my arrays and this is what I have so far:

Private Sub LoadArrayElements()

strTransDate(UBound(strTransDate)) = dtpTransDate.ToString
objCheckNum(UBound(objCheckNum)) = txtCheck.Text
strPayee(UBound(strPayee)) = txtPayee.Text
strPurpose(UBound(strPurpose)) = txtPurpose.Text
End Sub


Call LoadArrayElements()
'*Redim arrays to add new element
ReDim Preserve strTransDate(UBound(strTransDate) + 1)
ReDim Preserve objCheckNum(UBound(objCheckNum) + 1)
ReDim Preserve strPayee(UBound(strPayee) + 1)
ReDim Preserve strPurpose(UBound(strPurpose) + 1)
ReDim Preserve intAmount(UBound(intAmount) + 1)

sglAmount = Convert.ToSingle(txtAmount.Text)

'* Accumulate transaction count
ReDim Preserve intItemCount(UBound(intItemCount) + 1)
intItemCount(UBound(intItemCount)) = 1

'* Perform calculations
If radDeposit.Checked = True Then '* Transaction is a deposit
'* Accumulate totals
sglBalance += txtAmount.Text

Dim x As Integer = 0, i As Integer = 0
For i = 0 To intDepositAmount.GetUpperBound(0)
sglDepositAmount += intDepositAmount(i)
Next


Else '* Transaction is a check
'* Accumulate totals
sglBalance -= txtAmount.Text

Dim x As Integer = 0, i As Integer = 0
For i = 0 To intDepositAmount.GetUpperBound(0)
sglCheckAmount += intCheckAmount(i)
Next

End If '* End of transaction type test
'*
'* Display accumulated totals
'*
'* Overall totals
lblBalance.Text = FormatNumber(sglBalance, 2)
lblNumOfItems.Text = intItemCount.Length
'* Check totals
lblValueOfChecks.Text = FormatNumber(sglCheckAmount, 2)
lblNumOfChecks.Text = intCheckAmount.Length
'* Deposit totals
lblValueOfDeposits.Text = FormatNumber(sglDepositAmount, 2)
lblNumOfDeposits.Text = intDepositAmount.Length
'* Transfer input values to display labels
If radDeposit.Checked = True Then
lblType.Text = "Deposit"
Else
lblType.Text = "Check"
End If
lblTransDate.Text = dtpTransDate.Text
lblCheckNum.Text = txtCheck.Text
lblPayee.Text = txtPayee.Text
lblPurpose.Text = txtPurpose.Text
lblAmount.Text = FormatNumber(sglAmount, 2)
'* Reset input controls
'* Leaves transaction date at last value
radCheck.Checked = False
radDeposit.Checked = False
txtCheck.Text = ""
txtPayee.Text = ""
txtPurpose.Text = ""
txtAmount.Text = ""
'* Notify user of success
lblHelp.Text = "Transaction processed successfully"
End If '* End of processing for valid entries


My balance always comes out right and so does total number of items.. but my running totals for the checks and deposits come out to zero.. Please someone help! =) Thank you!

"You will create a set of either collections or arrays"
"Set" means a collection in terms of English, not as a program object type.
You can choose collection"s" or array"s". This could be set up as Dim values(6,10) as string and redim the second value, but this violates your teacher's obvious request to separate them into collections or arrays that match the specific type of data. It looks like he is requesting you have 7 separate variables, so programming is specific to each variable's purpose.

f radDeposit.Checked = True Then ...Else...
This seems like a single transaction desision, but you are applying all the values that were entered into either a deposit account or a check account running total which violates your instructions. Your deposit and checking arrays NEVER are updated
Put the updates into LoadArrayElements method and USE your arrays to store the value.

If you aren't storing the type of deposit or check why use intAmount which is never set?
Why don't you add an Ischecking(0) as boolian, set it based on radDeposit, have dim temp as single in LoadArrayElements, set it to your txtAmount, and then intAmount() to temp*100.

WHY do you have your count in an ARRAY, your ubound always has the total count.

Initalize!!!! your statistics before the loop. IE TotalDeposits=o TotalChecks=0 etc.
ONLY!!!! loop when requested IE

do i=0 to ...
if Ischecking(i) then
TotalChecks+=1
TotalCheckAmount+=intAmount(i)
else
etc.
...
next i

TotalCheckAmount/=100
etc.

Ever heard of debugging and STEPPING through your code?
You can actually WATCH your code getting changed.

PS You are BEGGING for an overindex error:
For i = 0 To intDepositAmount.GetUpperBound(0)
sglCheckAmount += intCheckAmount(i)

Do i have to:

'*Redim arrays to add new element
ReDim Preserve strTransDate(UBound(strTransDate) + 1)
ReDim Preserve objCheckNum(UBound(objCheckNum) + 1)
ReDim Preserve strPayee(UBound(strPayee) + 1)
ReDim Preserve strPurpose(UBound(strPurpose) + 1)
ReDim Preserve intAmount(UBound(intAmount) + 1)

??

I could be totally wrong but my idea of arrays is that if i want to add a new element I have to resize it first.. so i tried to make it so that when the record button is pressed, it loads the arrays and then adds 1 new empty element, partially because i wanted to count from it, but then as you pointed out I created arrays for the running totals I was supposed to acquire by looping through the arrays.

But what does this mean exactly? -> set it to your txtAmount, and then intAmount() to temp*100.

and this ->

do i=0 to ...
if Ischecking(i) then
TotalChecks+=1
TotalCheckAmount+=intAmount(i)
else
etc.
...
next i

TotalCheckAmount/=100
etc.


I basically get the idea of what your saying for accumulating totals.. but how do I : "The Record button will add the current sale's data to these structures using either ReDim for the arrays or an appropriate technique for the collections. (You must ReDim your arrays so that the have just enough space for the data that is in them. Declaring the arrays with a large size with no facility to resize them is not allowed. Don't forget to use the ReDim Preserve syntax to retain the existing array contents when you resize them.) "

Edited 7 Years Ago by bcohenllc: n/a

Or even.. how would i do this qith collections?? Im not so familiar with the code for collections but Ive been told its somewhat easier...

Your existing ReDim process is fine. Your existing process of loading the data into arrays isn't fine, because the amount entered on your page isn't loaded into any array.
That needs to be corrected.

I had a suggestion for how to make that correction. Having two arrays, one for deposits and one for checks is OK but it has pitfalls associated with it. Having those two arrays AND an integer array saving the same data is redundant. I suggested having a boolian array added to the list and removing the two individual arrays. The advantage of this is that you can exactly mimic the chronological order of when checks and deposits were posted, it forces you to count checks and deposits separately, it integrates nicely with the database you are going to have to put up when you get to your ADO.NET training when you load a datatable into a dataset.

You don't have to have a Boolean array. When a check is drawn, make sure your IntAmmount is negative and a deposit is positive. (It would be a little hard to tell if the intent was a check or deposit if the amount is 0. Do you add an entry, if the user puts in 0?)

You are making a basic beginner’s mistake not initializing your sums before the do loop. You start out at 0, you put in a deposit of 1000, your deposit sum is 1000, and your checking sum is 0. You add a check for 100, your deposit sum is 2000, your check sum is 100, and your total is 1900 all because you didn't reset your deposit total before looping.

You are always looping to get the running totals once a new entry is made. I get the intent of the instructor is to loop through the numbers when a running total is requested, not every time you process. It's extremely inefficient not to keep running totals and loop each time if that was the instructor's intent.

Getting back to ReDim. I believe that when you execute it, the array location put into a new address, and the "preserve" copies the array values from the old location before it is put into the garbage collector. A Collection's address doesn't change, but the internal structure of the data retained in it will change. A Collection exposes properties that allow you to manipulate the internal data in a controlled manner.

I put in the temp variable because I wasn't sure of how the string casting would happen if you muliplied a string by 100. I did know implicit casting occurs if you put it into a single value. Inserting a string into an integer would drop the decimal value and it would be totally lost. If you can set "i(loc) = txb.Text * 100"

PS, Enter "$1,234.56" in your text. Is your int value 123456? You might also want to look up "currency, localizing" if your instructor wants to allow international updates.

...

But what does this mean exactly? -> set it to your txtAmount, and then intAmount() to temp*100.

and this ->

do i=0 to ...
if Ischecking(i) then
TotalChecks+=1
TotalCheckAmount+=intAmount(i)
else
etc.
...
next i

TotalCheckAmount/=100
etc.

... "

1. I meant "temp = txtAmount.Text"
that implicitly converts a string into a single value. Then
"intAmount(intAmount.ubound) = temp * 100"
That converts the decimal portion of the single value implicitly into an integer value without loosing the decimal value of the change entered. If you had "intAmount(intAmount.ubound) = txtAmount.Text" and you had entered "45.46", the integer conversion would be 45. If you set it to temp and then multiplied by 100 the integer conversion would be 4546 even if you had entered "45.46135" which a conversion to single would retain. A single value would never exactly match "45.46" and retaining single values in an array would introduce rounding errors in the total sum.

For this:
do i=0 to ...
if Ischecking(i) then
TotalChecks+=1
TotalCheckAmount+=intAmount(i)
else
etc.
...
next i

"..." and "etc." means I used short-hand. I didn't even include the initialization of the variables. I meant TotalChecks would count the total number of checks entered. I could do this because Ischecking(i) was previously set to true when the user said they were entering a check and this was concurrently updated with intAmount and "ReDim"ed at the same times so the index and the upper bounds for both is exactly the same. I thought you could figure out you needed to add the deposit value settings in the else phase and the final "..." was for any additional processing that didn't pertain to the check and deposit balances. If there isn't any, don't put it in.

I also assumed you knew the integer sum is 100 times too high so after the loop, divide both check and deposit sums by 100. (A "single" variable should be able to add the integer values accurately assuming the total significant digits aren't too high. Dividing by 100 after the loop removes rounding errors introduced by adding the real number during the loop.) The final tally is just the deposit minus the check sums while you add the counts for the total transactions.

Thinking about it, a single would be precise up to around $10,000, an int32 would be precise to about $20,000,000. Maybe you should sum using int64? Put the calculations in a double and after dividing by 100 it would remain accurate for around $10 billion. Or keep the int64 and be accurate to around $40 million billion. Make the suggested temp field double.

This article has been dead for over six months. Start a new discussion instead.