Printing input statements to a specific row(?) - input

Doing a project for a qbasic class, and i need the 1st row to ask for input i.e. " Enter projected depletion rate: ", after doing that it will run a loop under it, wherein i need it to print another input statement on that same 1st row, " Enter another projected depletion rate or 0 to quit :" the issue i'm having is that if i use LOCATE it will print the next results of the loop directly under that statement when id like it to print below the last results in the list, at the lowest unused space, and it doesn't clear the top row of old text. I know part of it is that the LOCATE is getting repeated because of the loop but i'm genuinely stuck. sorry for format i'm new :)
CLS
DIM percent AS DOUBLE
DIM ozLevel AS DOUBLE
DIM counter AS INTEGER
DIM change AS DOUBLE
INPUT "enter a projected depletion rate, or 0 to quit: ", percent
PRINT
PRINT TAB(2); "Loss"; TAB(17); "Final Ozone"
PRINT TAB(2); "Rate"; TAB(10); "Years"; TAB(17); "Concentration"
change = (percent / 100)
DO WHILE percent <> 0
counter = 0
ozLevel = 450
DO UNTIL ozLevel < 200
counter = counter + 1
ozLevel = ozLevel - (ozLevel * change)
LOOP
PRINT USING "##.##%"; TAB(2); percent;
PRINT TAB(10); counter;
PRINT USING "###.##"; TAB(17); ozLevel;
LOCATE 1, 1
INPUT "enter new projection: ", percent
change = (percent / 100)
LOOP
LOCATE 1, 35
PRINT "DONE"
END

QBasic has the CRSLIN function that tells you where the cursor is.
Make sure that printing the 3rd result does a carriage return and linefeed. Just remove the ;
Now store the index to the next available row in a suitable variable like TableRow.
Input as before on the 1st row of the screen.
Position the cursor on the next available row using this variable after each following input.
...
PRINT USING "###.##"; TAB(17); ozLevel
tablerow = CRSLIN
LOCATE 1, 1
INPUT "enter new projection: ", percent
change = (percent / 100)
LOCATE tablerow, 1
LOOP
...

Related

VB.Net Remove Multiple parentheses and text within from strings

So basically what I am trying to do in vb.net is remove multiple nested parentheses and all the text inside those parentheses from a string. It's easy to do if there is just one set of parentheses like in the first example below I just find the index of "(" and ")" and then use the str.remove(firstindex, lastindex) and just keep looping until all parentheses have been removed from the string.
str = "This (3) is(fasdf) an (asdas) Example"
Desired output:
str = "This is an example"
However I still can't figure out how to do it if their are multiple nested parentheses in the string.
str = "This ((dsd)sdasd) is ((sd)) an (((d))) an example"
Desired Outcome:
str = "This is an example"
This isn't really a tutorial site, so I shouldn't be answering this, but I couldn't resist.
As Ahmed said, you could use Regex.Replace, but I find Regexes complex and impenetrable. So it would be difficult for someone else to maintain it.
The following code has three loops. The our loop, a While loop, will run the two inner loops as long as the character index is less than the length of the string.
The first inner loop searches for the first "open bracket" in a group and records the position and adds 1 to the number of "open brackets" (the depth). Any subsequent "open brackets" just adds 1 to the number of brackets. This carries on until the first loop finds a "close bracket"
Then the second loop searches for the same number of "close brackets" from that point where the first "close bracket" is found.
When the loop gets to the last "close bracket" in the group, all the characters from the first "open bracket" to the last "close bracket" in the group are removed. Then the While loop starts again if the current index position is not at the end of the updated inputString.
When the While loop finishes, any double spaces are removed and the updated output string is returned from the function
Private Function RemoveBracketsAntContents(inputString As String) As String
Dim i As Integer
While i < inputString.Length
Dim bracketDepth As Integer = 0
Dim firstBracketIndex As Integer = 0
Do
If inputString(i) = "(" Then
If firstBracketIndex = 0 Then
firstBracketIndex = i
End If
bracketDepth += 1
End If
i += 1
Loop Until i = inputString.Length OrElse inputString(i) = ")"
If i = inputString.Length Then Exit While
Do
If inputString(i) = ")" Then
bracketDepth -= 1
End If
i += 1
Loop Until bracketDepth = 0
inputString = inputString.Remove(firstBracketIndex, i - firstBracketIndex)
i = i - (i - firstBracketIndex)
End While
inputString = inputString.Replace(" ", " ")
Return inputString
End Function

Trying to shorten code in VB.NET

One of my assignments in vb.net is to make a program that takes in 15 inputted "test scores", returns the average, and then returns the corresponding letter grade. I am trying to make this as short as possible, and I remembered a code format that I can use when I am coding in Python (simple example with only three scores):
counter = 0
number = 0
test1,test2,test3 = 0,0,0
for i in [test1,test2,test3]:
print("Enter a test score")
i = int(input())
counter += i
number += 1
average = counter/number
Is there such a code format in VB.NET?
Yes.
Here is a simple sample code which asks user to input number of items and then items one by one. At the end it calculates average of numbers.
Console.WriteLine("Enter number of Items")
Dim numberOfItems As Integer
If Integer.TryParse(Console.ReadLine(), numberOfItems) Then
Dim items As New List(Of Decimal)()
For i As Integer = 1 To numberOfItems
Console.WriteLine("Enter number {0}", i)
Dim num As Decimal
If Decimal.TryParse(Console.ReadLine(), num) Then
items.Add(num)
End If
Next
Console.WriteLine("Average is " + items.Average())
Console.ReadLine()
End If
Please note that I've not included any type of error handling.

How can I calculate the sum of Legacy Form Fields without werid scrolling?

I have a Word document with a table that contains the price of an item, the order amount and the item sum, where amount and item sum are Legacy Form Fields:
There are other items available as options that you can chose via checkbox (also Legacy Form Fields):
Code
Now I've created a function that calculates the item sum
Sub order_amount_Click()
Dim amount As Integer
Dim valueFromCell As String
Dim list
Dim value As Double
amount = ActiveDocument.FormFields("order_amount").Result
If amount > 0 Then
valueFromCell = ThisDocument.Tables(1).Cell(5, 3).Range.Text
list = Split(valueFromCell, " ")
value = list(0)
subsum = value * amount
ActiveDocument.FormFields("order_amount_sum").Result = subsum
Else
ActiveDocument.FormFields("order_amount_sum").Result = 0
End If
CalculateSum
End Sub
and another function that calculates the item sum for additional items (if the checkbox is activated) multiplied by the order amount:
Sub optional_item_Click()
Dim checkbox As Integer
Dim valueFromCell As String
Dim list
Dim value As Double
Dim amount As Integer
Dim subsum As Double
checkbox = ActiveDocument.FormFields("optional_item1").Result
amount = ActiveDocument.FormFields("order_amount").Result
If checkbox = 1 And amount > 0 Then
valueFromCell = ThisDocument.Tables(1).Cell(7, 3).Range.Text
list = Split(valueFromCell, " ")
value = list(0)
subsum = value * amount
ActiveDocument.FormFields("optional_item1_sum").Result = subsum
Else
ActiveDocument.FormFields("optional_item1_sum").Result = 0
End If
CalculateSum
End Sub
(There are as many Click() functions as there are optional_item fields, 17 in sum - I haven't generalized the function yet.)
The last line within both Subs is a function call, that calculates the net sum, the VAT and the final total sum
Function CalculateSum()
Dim net As Double
Dim vat As Double
Dim total_sum As Double
net = CDbl(ActiveDocument.FormFields("order_amount_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item1_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item2_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item3_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item4_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item5_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item6_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item7_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item8_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item9_sum").Result)
' Cannot compile when line too long, so splitting into two statements
net = net + CDbl(ActiveDocument.FormFields("optional_item10_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item11_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item12_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item13_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item14_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item15_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item16_sum").Result) + CDbl(ActiveDocument.FormFields("optional_item17_sum").Result)
'MsgBox "net " & net
ActiveDocument.FormFields("net_sum").Result = net
vat = net * 0.19
'MsgBox "vat " & vat
ActiveDocument.FormFields("vat_sum").Result = vat
total_sum = net + vat
'MsgBox "total " & total_sum
ActiveDocument.FormFields("total_sum").Result = total_sum
End Function
Problem
The code itself works fine, all elements are calculated correctly. But there are two major problems that make the whole document almost unusable (all actions for users are restricted to enter their name on top of the document, chose the amount and de-/activate the checkboxes; sum fields aren't accessible):
When I perform an action (e.g. enter an amount) the CalculateSum() function visibly loops over all sum fields (spanned over three pages) and weirdly scrolls on the document along the sum fields.
When I click on a checkbox on the 2nd or 3rd page, the document scrolls up to the first page to the place where I can enter the amount of pieces I want to order.
Now how can I supress all that looping over the sum fields and weirdly scrolling around? And how can I prevent the document from scrolling up to the 1st page?
Any help appreciated! (I'm also thankful for side comments on my code, as I'm new to VBA.)
Update #1
I've added a screencast showing the error.
Update #2
The basic problem seems to be that the macro is scrolling to the position I am referring to in my script, e.g. if I'm using
ActiveDocument.FormFields("total_sum").Result = total_sum
it's scrolling to the total_sum field.
Too difficult for a comment...
For (b) you have to use VBA - you can't use the trick I suggested elsewhere with the FormFields checkboxes, only with the Content Control ones.
For (c), something like this (not tested)
Make sure the On Exit macro is set for optional_item1 and the Calculate on Exit is also set. I don't think you need an On Entry macro as well.
Sub optional_item1_Click()
Call cb_Click("optional_item1")
End Sub
Sub cb_Click(ffname As String)
ActiveDocument.Variables(ffname) = abs(int(ActiveDocument.FormFields(ffname).Checkbox.Value))
End Sub
In your Summa column, next to the checkbox, something like
{ ={ DOCVARAIABLE optional_item1 }*X2 }
where X2 is the cell that contains the 3,00 Euro value and all the { } are the special field code brace pairs that you can insert using ctrl-F9 on Windows Word.
BUT
Whether Word will correctly interpret your Euro value correctly depends on the regional settings of the user using your form, (decimal separator, group (thousands) separator, currency symbol and location of the currency symbol may all change Word's behaviour. Even within the Eurozone I think some of those things can vary. So if the user does not need to modify the multiplier 3,00 Euros in the cell, it may be better to plug the value directly into the { = } field:
{ ={ DOCVARAIABLE optional_item1 }*3 }
You can also use \# numeric formats to give you the format you want when positive or 0. But again, Word's numeric formatting facility is not locale-independent).
Those locale dependencies are also sometimes a reason for doing more in VBA rather than field codes.
As AdamsTips found out elsewhere, replacing this
ActiveDocument.FormFields("myField").Result
by this
ActiveDocument.Bookmarks("myField").Range.Fields(1).Result
allows accessing the field without focusing it.

Making text go to a new line when in a while loop

I have a richTextbox, and a while loop, x = 0, and every time this loop runs, x += 1 till it reaches a certain value.
Heres what I want to happen:
while x <> 10 then
it will say item 0 +1 on a new line, and then item 1 + 1 on the line under it, etc, so you will see all 10 values after.
What happens is, it will change that line into the new value.
My question is: How do I make it put the words on a new line instead?
Here is my code:
While readListItem <> PaymentList.Items.Count
If readListItem > PaymentList.Items.Count Then
readListItem = 0
Exit While
End If
readListItem += 1
MessageBox.Show(readListItem)
resultBox.Text = vbNewLine + PaymentList.Items.Item(readListItem) + " costs " + enteredCost + "." + vbNewLine
End While
readListItem is "x", and that is being iterated by 1 every time the loop runs
PaymentList is my listbox containing an unknown value (the user sets the number of items in this list)
The If if there because, after x = lets say 10, it would add another to x (so now it = 11) and try to print out the 11th item, as it doesnt exist, it crashes. This is to attempt to prevent that. I didnt want to go with a try catch
Try adding the new value instead of replacing the entire value:
resultBox.Text &= Environment.NewLine() & PaymentList.Items.Item(readListItem) + " costs " + enteredCost + "."
The expression &= is equivalent, in this case, to resultBox.Text = resultBox.Text & "...".
And once advice, you can simplify your loop by using this condition:
While readListItem < PaymentList.Items.Count
'...
End While

Way to Jump to Next i in For..Next Loop?

I'm reverse engineering in QuickBasic and I have code like this:
FOR i = star TO fin
IF a < 1 THEN
CALL clrbot
COLOR 15
PRINT force$(side); " army in "; city$(armyloc(i)); " is CUT OFF !";
TICK turbo!
GOTO alone
END IF
size = size + 1
max = 11: IF LEN(armyname$(i)) < 11 THEN max = LEN(armyname$(i))
mtx$(size) = LEFT$(armyname$(i), max)
array(size) = i
alone:
NEXT i
I'd like to get rid of the line label (alone) and instead do something like:
IF a < 1 THEN
CALL clrbot
COLOR 15
PRINT force$(side); " army in "; city$(armyloc(i)); " is CUT OFF !";
TICK turbo!
NEXT i
END IF
You could replace the GOTO with an Else:
For i = star To Fin
If a < 1 Then
' Do something
Else
' Do Something else
End If
Next
This would follow the same logic - the Else takes the place of the GOTO alone statement.
In the original code (QuickBASIC) if the If block is entered, everything after then GOTO alone statement is ignored.
If the If block is not entered (i.e., a >= 1) then everything after the If block is executed.
The Else statement in the VB.NET code will produce the same behavior. If a < 1, the first block will be executed and the Else block will be ignored, and the loop will advance to the next increment of i.
If a >= 1, then the Else block will be executed and the loop will then advance to the next increment of i.
The above assumes labels in QuickBASIC are like labels in DOS batch files.