VBA using forms and textboxes - vba

I am a bit confused as to how to implement code for Text boxes. I am trying to set up a form which displays a text box, for which the user has the option to enter in the values (parameters) , which then are entered into another subprogram and runs that subprogram. For example, in the following code:
Option Explicit
Sub FillSampleTable()
'This will fill an x by y grid of numbers incrementing to use for testing purposes
Dim x As Double
Dim y As Double
Dim z As Double
Dim OffsetColumn As Integer
Dim offsetrows As Integer
Dim a As Long
Application.ScreenUpdating = False
a = 10
OffsetColumn = 1
offsetrows = 1
z = 0
For x = 1 To a
For y = 1 To a
z = z + 1
Cells(x + offsetrows, y + OffsetColumn).Select
Cells(x + offsetrows, y + OffsetColumn).Value = z
Next y
Next x
Application.ScreenUpdating = True
End Sub
I would want to have a text box to prompt the user for the value of 'a', and once that value is loaded, then this subprogram is run. If no value is entered, then it would shoot an error msgbox and return to the entry screen.
When I click the box I get:
Private Sub GridSize_Change()
'I renamed text box GridSize
End Sub
but don't know what to do with this. MS Excel v 2016.

What you need is an inputbox.
You could do a simple :
a = InputBox("Enter number a")
Since you need a to be a positive integer, you should at least specify the datatype accepted by the inputbox to 1 (number). But you probably also need to make sure it is a positive integer.

Related

Short any value in VB.Net

I'm quite a beginner in programming, and I want to make it shorter: code:
For y as integer = 1 to 5
'Code'
Next
Using sw As New StreamWriter(filepath)
sw.WriteLine("[TxtStringNumP1]")
sw.WriteLine(TxtStringNumP1.Text)
sw.WriteLine("[TxtStringNumP2]")
sw.WriteLine(TxtStringNumP2.Text)
sw.WriteLine("[TxtStringNumP3]")
sw.WriteLine(TxtStringNumP3.Text)
sw.WriteLine("[TxtStringNumP4]")
sw.WriteLine(TxtStringNumP4.Text)
sw.WriteLine("[TxtStringNumP5]")
sw.WriteLine(TxtStringNumP5.Text)
End Using
MsgBox("Ok", vbInformation)
You can make this bit shorter:
For y as integer = 1 to 5
For y = 1 to 5
And you can then rely on the fact that your control have names that differ only by a number, and there is some collection of them that knows them by name:
For y = 1 To 5
Dim n = "TxtStringNumP" & y 'formulate the name
Dim c = Me.Controls.Find(n, True) 'find all controls with a matcing name, returns a collection of controls
sw.WriteLine($"[{n}]") 'write the name we formulated
sw.WriteLine(c(0).Text) 'write the text of the first control. All controls have a Text property, we don't need to convert it to textbox
Next

How can i loop the above code?

Sub CalculateWFR()
'select 1st sheet
Worksheets(1).Activate
'select range A:W
Worksheets(1).Cells.Select
Columns("A:W").Select
'copy paste sheet programare in results
Sheets("Programare").Range("A:W").Copy Destination:=Sheets("Result").Range("A:W")
'compare values from column U with column V and put +/-/= if value from U2 is higher,smaller or equals value from column V2
Dim X As Integer Dim y As Integer
X = Worksheets("Result").Range("U2").Value
y = Worksheets("Result").Range("V2").Value
If X > y Then
Worksheets("Result").Range("X2") = "+"
ElseIf X < y Then
Worksheets("Result").Range("X2") = "-"
ElseIf X = y Then
Worksheets("Result").Range("X2") = "="
End If
End Sub
I am trying to loop the above code on column X, which has over 1000 Rows. Also there are no blank spaces. How can I do this?
As #Zerk suggested try to figure out how this works.
Looping and Selecting is not required at all.
Try to think this as you were to put formula in column X and then google how to put that formula through VBA.
Sub test()
Sheets("Programare").Range("A:W").Copy Destination:=Sheets("Result").Range("A:W")
Sheets("Result").Range("X2:X1000").Formula = "=IF(U2>V2,""+"",IF(V2>U2,""-"",IF(U2=V2,""="","""")))"
End Sub

Integer subtraction and looping based on integer values

I'm having two problems here. First off all I want to x to change values to x - y and if the new X is higher then 0 i want the process to repeat itself. I've worked out the code below but i'm not certiant on two things.
Am I even allowed to make the equation x = x - y or does this mess up everything? I mean in mathematical terms it would not be possible but if we take X as Hp and Y as damage I want the damage to add up. I don't want it to create an "damage HP" integer for every subtraction as I even don't know how many "Z = x - y" style equations I would have to create if I set Y to be random.
My guess is that I could create a Z integral that would copy X a moment before the subtraction would go off and then have the subtraction be X = Z - Y but I'm not sure how I would go about coding this.
I want it to go ahead and loop itself if X is higher then 0 and I'm not sure if I coded that correctly.
Here is my code:
Module Module1
Dim A As Integer
Dim B As Integer
Dim x As Integer
Dim y As Integer
Sub Main()
End Sub
Sub Maths()
A = 5
B = 4
x = 3
y = 1
Subtraction()
Console.WriteLine("You deal {0} damage to your enemy reducing it to {1} hp.", y, x)
Do Until x <= 0
Loop
End Sub
Private Sub Subtraction()
If A > B Then x = x -y
Return
End Sub
End Module
I liked this question. Here's my thoughts:
Yes, x = x - y is perfectly valid code. It's no different than if I had a string variable named myRunOnSentence and I wanted to concatenate the string that was already in the variable and another string and then store the results back in the string variable. Like this: myRunOnSentence = myRunOnSentence + "another string" Same concept, just change the datatype to an Integer. x = x + y. That programatically says: "take the value in x and the value in y, add them together, and store the result of that expression in x."
You did indeed make a mistake with the loop. You don't have any code inside the body of the loop itself.
You have nothing happening in the Main() sub of your module so this module when run will do nothing. You should just take the code from the Maths() method and put it in the Main() sub.
In your Subtraction() method, A > B will always evaluate to True because A and B are initialized with values and then never changed.
Your code should look something like this:
Module Module1
Dim A As Integer = 5
Dim B As Integer = 4
Dim x As Integer = 3
Dim y As Integer = 1
Sub Main()
Do Until x <= 0
Subtraction()
Console.WriteLine("You deal {0} damage to your enemy reducing it to {1} hp.", y, x)
Loop
End Sub
Private Sub Subtraction()
If A > B Then x = x - y 'Return statement wasn't needed.
End Sub
End Module
If this answered your question, please don't forget to mark it as the answer.

Excel range subtraction, overlooking errors in some cells possible?

I am having trouble figuring out how to subtract two ranges from each other, some cells in range H:H have "#N/A" while in range D:D there are no errors. I know in Excel it's a simple "=H2-D2" and drag that down but I'm in the process of recording a Macro and wanted to automate the subtraction as well. So far this is what I have:
Dim quantity1, quantity2, rIntersect, Qdiff, x As Range
Set quantity1 = Range("D:D")
Set quantity2 = Range("H:H")
Set rIntersect = Intersect(quantity1, quantity2)
For Each x In quantity1
If Intersect(rIntersect, x) Is Nothing Then
If Qdiff Is Nothing Then
Set Qdiff = x
Else
Set Qdiff = Application.Union(Qdiff, x)
End If
End If
Next x
Range("J2").Select
Dim lastRowJ As Long
lastRowJ = Range("A" & Rows.Count).End(xlUp).Row
Range("J2").AutoFill Destination:=Range("J2:J" & lastRowJ)
Place this procedure in a standard code module:
Public Sub Subtract()
[j2:j99] = [h2:h99-d2:d99]
End Sub
If you like how that works, I'm happy to embellish it so that it is not hard-coded for 98 rows only. Let me know.
UPDATE
Here is a version that will deal with any number of rows. It keys off of column D. So if there are 567 numbers in column D, then you will get 567 corresponding (subtracted) results in column J.
This assumes that the data start in row 2, and that there are no blank cells until the numbers in column D end.
If you are going to call this from the Macro Dialog then you should keep it Public. If on the other hand you are going to call it from another procedure in the same module, then you can make it Private.
Here is the enhanced solution:
Public Sub Subtract()
Dim k&
Const F = "iferror(h2:h[]-d2:d[],0)"
k = [count(d:d)]
[j2].Resize(k) = Evaluate(Replace(F, "[]", k + 1))
End Sub
Note that the routine now handles the errors and places a ZERO value in column J when the corresponding value in column H is an error. If you would prefer to have something other than a ZERO (like a blank for instance) when there are errors in column H, just let me know and I'll update to whatever you want.
UPDATE 2
Here is how to handle displaying blanks instead of zeroes:
Public Sub Subtract()
Dim k&
Const F = "iferror(if(h2:h[]-d2:d[]=0,"""",h2:h[]-d2:d[]),0)"
k = [count(d:d)]
[k2].Resize(k) = Evaluate(Replace(F, "[]", k + 1))
End Sub

using an input box to set up how many times a loop will run

I have a code that puts spaces in a column of numbers, so that each group of 6 numbers have 2 spaces between them, starting from the top of the sheet. After the groups of 6 there can be groups of 5, these need to have 3 spaces between them.
The groups of 6 always appear above the groups of 5.
I would like to have a code that asks how many groups of 6, then asks for how many groups of 5, then puts in the relevant spacing.
Sub MacroMan()
Dim x As Integer
x = 8
For i = 1 To CInt(InputBox("Run this many times:"))
'Range("H2").Paste
Application.CutCopyMode = False
Range("H&x:H&x+1").Insert Shift:=xlDown
'Range("H2:H110").Copy
x = x + 8
Next
End Sub
I've got the code to run now, but I get the following error.
Run-time error '1004'
Method 'Range of object'_'Global'failed
You can ask the user for their input and store the answer in a string. Then convert the string to an integer and use it to determine the number of loops.
sub AskUser
dim Answer as string
dim i as integer
dim Number as integer
Answer = Inputbox("Your text here")
Number = CInt(Answer) 'Note this will throw an error if you enter something that's not a numbeer
for i = 1 to Number
'code
next i
End sub
This should do the same thing, for the amount of times that you specify.
Important: Always run untested code on a copy of your data as executed code cannot be undone!
Sub SO()
Dim x As Integer, i As Integer
x = 8
Application.CutCopyMode = False
For i = 1 To CInt(InputBox("Run this many times:"))
Range("H" & x & ":H" & x + 1).Insert Shift:=xlDown
x = x + 8
Next
End Sub