I couldn't observe the number of rows completed during run time. Hence I was thinking why not just come out few line of codes to display the number of rows completed in run time.
Follow are my implementation:
Dim ownCntrl As Control
Set ownCntrl = UserForm1.Controls.Add("Forms.TextBox.1")
With ownCntrl
.Name = "RowNoTextBox"
.Value = "test"
.Width = 150
.Height = 25
.Top = 10
.Left = 10
.ZOrder (0)
End With
UserForm1.Show
Following are my queries:
1)Beside TextBox Object, is there any other Object like label in Java to display information in VBA?
2)Without Created a UserForm called "UserForm1" initially, can I create the TextBox Object or other suitable Object Directly during run time? Cause, without called the UserForm1.Show function, the TextBox Object won't display
3)How can I remain the UserForm or TextBox to display during run time without users' interaction to close it to proceed?
I'm just start to learn VBA. Appreciate you guys' suggestions. Thanks a lot.
According to some additional information placed in comments the simplest idea to keep information about progress of your subroutine is to use Excel status bar. Therefore we put within our subroutine something like this:
Application.StatusBar = "Current progress- Row No.: " & rowNum
where rowNum is a variable (loop variable) representing current row.
Which is important- you need to return standard status bar behaviour calling this line before end of your procedure:
Application.StatusBar = False
Related
I've got some code where the user has to multi-select items from a 2-column listbox. These items are variables which will later be plotted, and each have their own units (i.e. °C, °F, etc.). If the user selects items which have different units, an error message appears telling them to reselect.
The problem I'm having is that after the user reselects, it seems the initial selections are still there, because when the plot is generated I can see those variables being plotted. Here's what I've tried without any success:
If InStr(header, yUnit) = 0 Then 'this is the check to see if the selections use different units
MsgBox "Error! y variable selections contain different units. Please choose again"
Application.DisplayAlerts = False
ActiveChart.Delete 'Delete the chart which is currently being constructed
Application.DisplayAlerts = True
'Method 1:
Unload FormatChart
FormatChart.UserForm_Initialize 'FormatChart is the form in which the listbox is contained.
'UserForm_Initialize is the subroutine which constructs the listbox
FormatChart.Show
'Method 2:
With FormatChart.ListBox1
For x = 0 To .ListCount - 1
If .Selected(x) Then
.Selected(x) = False
End If
Next x
End With
FormatChart.Show
End If
'''
Solved it! I just have to use the following:
FormatChart.Show
Exit Sub
I believe what was happening was that the subroutine would continue to run, even though after I showed the form again I had an "Enter" button which would call the subroutine again, possibly resulting in it grabbing variables from the previous, still active, instance of it, or that multiple instances of that subroutine were running, not sure... anyway I'm just happy to end this headache :)
This feels like a stupid question but I can't figure it out, so here goes...
I have a workbook which, based on what's input into a userform, creates a new worksheet each time a command button on the userform is clicked, and deletes the old one.
That means that, although the new worksheet is always given the same name ("Results"), the sheet number increments each time; it's currently calling itself Sheet48 and next time I run it it will be Sheet49.
What I'd like to do is add a command button to that "Results" sheet, which users can click to take them to a different worksheet. I've got as far as adding some code into the userform which creates the command button itself on the "Results" worksheet. I haven't yet written the sub which would tell it to take the user to a different worksheet, but I'm confident that I could do this without much trouble.
My question is how I can assign the sub to the button, considering that the worksheet it's located on is not permanent? I thought the sub should go into a standard module, but all the examples I see for this kind of thing begin with "CommandButton1_Click", or "CommandButton2_Click", and are stored within the sheet object itself. It seems like these numbers 1 and 2 refer to the command button's order on a given worksheet, but presumably a sub on a standard module won't know which worksheet to look at.
I hope that makes sense - any helpful explanations will be much appreciated! Thanks.
EDIT:
This is the code I'm using to create the command button and to (attempt to) assign the sub to it:
'Add a command button, which will allow users to jump to the full report
ActiveSheet.OLEObjects.Add(ClassType:="Forms.CommandButton.1", Link:=False _
, DisplayAsIcon:=False, Left:=1025, Top:=130.5, Width:=160, Height:= _
400).Select
ActiveSheet.CommandButton1.Caption = "Click here to see the original report"
ActiveSheet.CommandButton1.WordWrap = True
ActiveSheet.CommandButton1.OnAction = "Module1.ButtonForOriginal" 'the sub works in isolation, but this line isn't assigning it.
Can anyone see any issues there? The ButtonForOriginal sub procedure works in isolation, so it looks like I'm just not calling it properly?
EDIT 2 - I have now achieved the right effect with a different method - see my answer posted below if you're interested. Thanks to those who helped and set me on the right path!
As i understand you are trying to add new sheet with new button, i would recommend using non-dependent buttons with hyperlinks to run your module.
Click insert shape - rectangle or so - and use Selection.OnAction = "YourWorkBook'!YOURSUB"
"CommandButton1_Click" should be an Event Procedure. They go into the module page connected with the sheet that the object sits on. So when you click on it, it knows which procedure to run, it's the one connected to the sheet the button is on.
OK, I sort of figured it out. I had for some reason decided to use an ActiveX command button, instead of a plain old Form one. This seems to have made things more difficult. I don't understand the detail, but I have achieved the effect I was after by doing this instead:
ActiveSheet.Buttons.Add(1025, 130.5, 160, 400).Select
Selection.Characters.Text = "Click here to see the original report"
With Selection.Characters(Start:=1, Length:=200).Font
.Name = "Verdana"
.FontStyle = "Regular"
.Size = 10
.Strikethrough = False
.Superscript = False
.Subscript = False
.OutlineFont = False
.Shadow = False
.Underline = xlUnderlineStyleNone
.ColorIndex = 1
End With
Selection.OnAction = "ButtonForOriginal"
I have a userform which looks like this
All the textboxes are filled with default values once a user opens this form.
The user then changes the values manually and presses OK which will close the form and will affect the charts linked to the form.
If the user opens the form again, the values in the textboxes revert back to default ones and the charts linked will assume their default positions too.
Is there any way where once the user presses OK, the values in the userform gets saved so when the user opens the form the next time, they are presented with the changed values instead of the default ones??
Thanks!
Have you tried using the Sheet as a place to save the data?
Dim i As Integer
Private Sub UserForm_Initialize()
For i = 1 To 49 'Number of TextBoxes (I counted 49)
Controls("TextBox" & i).Text = Cells(i, 1)
Next i
End Sub
Private Sub CommandButton1_Click() 'Save button
For i = 1 To 49
Cells(i, 1) = Controls("TextBox" & i).Text
Next i
End Sub
This will save the values in the first 49 rows of the first coloumn. If you want to save it to an other Sheet, create a new one and add Worksheets("SheetName").Cells....
Another solution if you don´t have similiar names (but Hungarian Notion like cbTest for a combo box) for the control elements, so you cannot iterate through them with a command like Controls("TextBox" & i)....
If you have a userform (e. g. called ufTest), then you can iterate through all control elements like this:
Dim controlElement as Control
For Each controlElement In ufTest.Controls
MsgBox controlElement.Name
' Check for type of control
If Left(controlElement.Name, 2) = "cb" Then
MsgBox = controlElement.Text
ElseIf Left(controlElement.Name, 3) = "txt" Then
MsgBox = controlElement.Value
End If
Next controlElement
This gets you the name of every control element in your userform, no matter how you´ve called your controls.
P. S.: I´m sure there is a way to get the type of the control without using the Hungarian Notion, but I did not find it in time.
I am trying to make a maths practice powerpoint where students are presented with random addition problems using numbers 1 – 20. I have been working through tutorials by David Marcovtiz (and others) and was using his code as a starting point. As my audience is young students, I would like the maths problems to not be in a message box but in something like text boxes or shapes that I can customise and make large and visually appealing for young students.
So, what I'm wanting to do...
In a powerpoint show
Student can click a ‘get started’ button that takes them to next slide
Next slide automatically generates 2 random numbers that student must add together.
Student enters the answer
If answer is correct – I would like something to signify the answer was correct but not something they have to click on to close. Ideally, a little star flashes in the corner then disappears
If the answer is incorrect, a message or picture flashes then disappears.
A new addition problem is automatically/randomly generated
I would like to set the number of addition problems to e.g. 20, then have the slide move to a scoring slide that shows their score in pictures e.g. a star for every correct answer.
Update:
Using Activex text Boxes:
I have had success with activex text boxes in being able to randomly show two numbers and have them multiply and show the answer in a third activex text box, which I hid off the slide. I used a fourth as an input box for students to type in their answer. If this is the same as the answer in the third box, I can show a star and clear the boxes then move to the next slide. If it's not the same, I can go show another picture then move to the next slide. (I originally wanted the slide to update and use one slide to ask 20 questions but was finding this difficult.)
At present, this requires clicking three command buttons.
What I have managed so far (I know it will seem quite sad to you and possibly unstable, but a major achievement for me and the 'bits' are working) I can manage it for multiplication but when I + the values e.g. 9 + 3, I get 93
Private Sub CommandButton1_Click()
TextBox1.Value = Int(10 * Rnd)
TextBox2.Value = Int(10 * Rnd)
TextBox3.Value = TextBox1.Value * TextBox2.Value
End Sub
Private Sub CommandButton2_Click()
If TextBox4.Value = TextBox3.Value Then
ActivePresentation.Slides("problem").Shapes("badge5").Visible = True
ActivePresentation.Slides("score").Shapes("badge5").Visible = True
Else
ActivePresentation.Slides("problem" _).Shapes("incorrect").Visible = True
TextBox1.Value = ""
TextBox2.Value = ""
TextBox3.Value = ""
TextBox4.Value = ""
End If
End Sub
Private Sub CommandButton3_Click()
SlideShowWindows(1).View.Next
End Sub
What I need
I would like the random numbers in command button 1 to activate automatically.
I would like to combine command button 2 and 3 and include a wait time after the star or incorrect shapes appear before moving to the next slide but the code I have found applies the wait time to the whole sequence as I'm not sure how to include it.
Private Sub Time_Click()
iTime = 2#
Start = Timer
While Timer < Start + iTime
Wend
With SlideShowWindows(1).View.Next
End With
End Sub
Using Shapes:
I would prefer to work with ordinary text boxes or shapes but...
I have managed to produce random numbers in shapes but haven't been able to multiply them and have students type into an activex text box that determines whether it is correct or incorrect yet. I think the problem is in trying to use both shapes and an activex textbox.
I would like to use shapes because I would like to create master slide layouts that can be selected using the following code - though this isn't a deal breaker.
Sub background()
ActivePresentation.Slides.Range(Array(2, 3, 4, 5)).CustomLayout_
= ActivePresentation.Designs(1).SlideMaster.CustomLayouts(6)
End Sub
I feel this is something that other educators could use and am happy to post my finished show if someone is willing and able to assist with the coding. I really appreciate the tolerance and patience of contributors shown to people like myself who have jumped in head first, excited and giving it a go but struggling.
So, to break down the pieces you requested in the "What I Need" section, I will split my answer into two sections:
"I would like the random numbers in command button 1 to activate automatically."
I assume what you mean by "automatically" is that you would like the "next" slide to automatically be populated with values after the user answers the question on the previous slide. To accomplish this functionality, I would call the method that the CommandButton1 currently calls after all the logic in the CommandButton2 has been run.
"I would like to combine command button 2 and 3 and include a wait time after the star or incorrect shapes appear before moving to the next slide..."
I would simply combine the code of the two functions with a wait function in between the two bits of code. I'm not sure where you found the code you posted for the "Timer_Click" function, I don't think that would work as currently posted. I would typically use the method of "wait" mentioned in this answer.
The result, after changing the code for the two new requirements would be something like this:
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Public Sub CommandButton2_Click()
'Command Button 2(code)
If TextBox4.value = TextBox3.value Then
ActivePresentation.slides("problem").Shapes("badge5").visible = True
ActivePresentation.slides("score").Shapes("badge5").visible = True
Else
ActivePresentation.slides("problem").Shapes("incorrect").visible = True
TextBox1.value = ""
TextBox2.value = ""
TextBox3.value = ""
TextBox4.value = ""
End If
'Wait code here(1000ms)
Sleep 1000
'Command Button 3(code)
SlideShowWindows(1).View.Next
'Call the command for CommandButton1,
'this will "automatically" populate the slide with new values
CommandButton1_Click
End Sub
I want a module in my workbook to write about a thousand combinations of the below
Sub trade0001open()
Sheets("TRADEDIARY").Range("AO2").Value = 1
Sheets("TRADEDIARY").Range("AD3").Value = _
Sheets("TRADEDIARY").Range("AJ2").Value
Sheets("TRADEDIARY").Range("AD4").Value = _
Sheets("Sheet8").Range("HA1").Value + 1
Sheets("TRADEDIARY").Range("AO3").Value = 0
End Sub
Sub trade0001close()
Application.ScreenUpdating = False
Sheets("TRADEDIARY").Range("AI3").Value = Sheets("TRADEDIARY").Range("AI3").Value + 1
Sheets("TRADEDIARY").Range("AO3").Value = 1
Application.Wait (Now + 0.000001)
Sheets("TRADEDIARY").Range("AO3").Value = 0
Sheets("TRADEDIARY").Range("AO2").Value = 0
Sheets("TRADEDIARY").Range("AI2").Value = Sheets("TRADEDIARY").Range("AI2").Value + 1
Application.ScreenUpdating = True
End Sub
Changing changing the cell references by a cumulator of four rows down each time. So every AO2 would become AO6 in the next every AD3 becomes AD7. Everything apart from HA1 would change so that includes AO2,AD3,AJ2,AD4,AO3 for the first sub and then that includes AI3, AO3, AO2, AI2 for the second sub.
So since my code above contains the two subs I'd like copied a thousand times - each copy will add 4 rows to each cel reference in each sub.
I am quite new to vba so I guess I am after a similar autofill function like in excel except for my code to do this quickly instead of typing thousands of times unless of course I guess somebody could suggest how to do this differently. hint hint. bare in mind I obviously want all the values pasted without a clipboard so that when those values from where they are copied change, the destination doesn't change. Which is what my above code achieves.
Then I'd like to asign each individual sub within each of the two separately to a developer button control in the spread sheet ( again asigned to change four rows down each time)
#matteo to clarify ''well I envisioned the only way was to have 1000 trade0001open() and 1000 trade001close() possibly defined as trade0001open() , trade0002open() etc ditto close etc etc in order to right click for each one on a vba developer for control button alligned to each cell AK4 for open button and AM4 for close button so AK8 and AM8 etc etc which is long winded again and Im refraining from assuming a developer button could be alligned to each of those cells frm within vba and assigned to each of the sub at the moment. I guess one workaround might be to configure the j somehow into the sub name .''
matteo's reply: ''What you ask is complex to answer here, i will give you a tip to get started: use always the same macro but intercept the reference of the cell from which the call starts in order to add dinamically the 4 rows as I showed you above. You don't need 2000 macros, only 2 that are readapting themselves depending on the caller parent''
me : ''so I guess this is more complicated than it seems if I could somehow make form button's alligned to cells to reference the j value within the 2 macros without need for making thousands of sub macros. As far as I know form buttons in excel can only reference sub functions without reference and not UDFs or anything else or even cell references although I probably am wrong about this. ''
a form button to call the sub based on a cell's reference that is what I need right?
http://www.mrexcel.com/forum/excel-questions/843078-loop-visual-basic-applications-sub-call-form-button-each-nth-row-based-cell-value-row-reference.html#post4105072
I don't know for the life of me where to begin Trying to call a Sub with a String - VBA
You just need to make every string dinamically redefined and loop 1000 times the same macro. This is an example to get started:
For j = 1 To 1000 '<-- do this 1000 times
'...
Sheets("TRADEDIARY").Range("AO" & 2 + (j-1)*4).Value = 1 '<-- if j=1 then row = 2, if j=2 then row = 2+4 = 6 etc.
'...
Next j