I have a complex VBA function and a workbook with multiple sheets.
Let's say the code goes through every row of Sheet1 and does something with that data.
I would like to be able to pause on SourceRow = 16, check out results I'm getting on different sheets and then continue on (press ok, or some key stroke)
I've tried
If SourceRow = 16 Then
MsgBox "ReachedRow 16"
End If
But the Message box is modal and I can not switch to a different sheet(s) to see the data.
P.S. 16 is just as an example, hardcoded for now but will not be later on.
You can use the Stop statement and then press F5 to resume the code execution. This is akin to adding a breakpoint.
If SourceRow = 16 Then
Stop
End If
The row will be highlighted yellow while it is paused and you should be able to navigate work sheets.
Example:
In similar fashion you can use Debug.Assert (sourcerow <> 16) which will pause the code when sourcerow<>16 evaluates to false, that is to say when sourcerow equals 16. (Thanks to RBarryYoung for the comment)
If you don't want a permanent stop in your code, consider adding a breakpoint by clicking the gray region to the left of the editing window in the VB editor, which should will look like this:
The code will stop when the line is reached. Again press F5 to resume code execution. Alternatively you can continually press F8 in order to step through the code line by line. This eliminates the need to set many breakpoints.
Simply click the maroon circle to dismiss the breakpoint. Breakpoints are not saved in your code, so this is a temporary method (as opposed to the two methods listed above which would stay in your VBA code if you save the workbook).
The images were taken from this tutorial from Wise Owl regarding breakpoints.
Right-click on SourceRow (anywhere in your code) and click Add Watch....
In the dialog that appears, enter the following in the Expression textbox:
SourceRow = 16
Under Watch Type, select Break when value is True.
Click OK.
This will automatically cause your program to break/pause when the value is reached and there's no need to add any new code just for debugging/pausing purposes.
Related
I'm trying to find a way to pass params to a macro that's assigned to a button in Excel (2010). I've seen a number of proposed solutions in this thread but none of them work for me - maybe due to my setup?
I have a macro defined in an Add-In file (macros.xlam) that takes no parameters. I have added a button in my *.xlsm file and attached the macro to it. When I click the button macro gets called and it works fine. My macro is called Export and it's inside CSV module so in the button's property I'm calling CSV.Export.
I have added an int parameter to the macro so the definition looks like this now:
Sub Export(a As Integer)
....
End Sub
Now I want to make the button pass 1 as the parameter. I set a breakpoint in first line of the Sub and tried various approaches but none worked:
'CSV.Export 1' - when I click on the button nothing happens, breakpoint doesn't catch. Additionally when I edit the macro again it turns out that what I entered was automatically replaced by 'sheet_name.xlsm'!'CSV.Export 1'. If I leave it at that it still does not work.
'CSV.Export(1)' - when I click on the button nothing happens, breakpoint doesn't catch. This one does not get automatically replaced.
'macros.xlam'!'CSV.Export 1 ' - when I click on the button nothing happens, breakpoint doesn't catch. Upon later edit it turns out that it gets replaced by 'sheet_name.xlsm'!'CSV.Export 1'
'macros.xlam'!'CSV.Export(1)' - when I click on the button nothing happens, breakpoint doesn't catch. Upon later edit it turns out that it gets replaced by 'CSV.Export(1)'
CSV.Export 1 - when trying to close button property window displays an error that the formula contains an error and won't allow to leave it like that
CSV.Export(1) - this return an error saying that "Formula is too complex to be assigned to object".
I want my macro to be customizable (users being able to pass parameters to it). At the same time I want to avoid hacky hard-coded solutions like calling the sub with no params and then always assuming that cell A1 has first parameter, A2 has second and so on.
So first, when one clicks on the "View Macro" button, this pops up:
What I want to know is, is there some code that I can run on workbook open (and then "unrun" on workbook close) that grays out that run button (like the others underneath it are) ONLY until the password is entered in the VBA project (using Alt+F11 to open the editor)?
I don't want the users to be able to run any of these subs manually.
If you declare the sub so that it needs input, even optional input it will not show in the list either.
sub Test(optional a as string)
Declare the subs as private and they won't show up in the Alt+F8 dialog box.
Declare them as public (the default) and they will.
You can use vba to edit the vba code of another module.
Is it possible in Excel VBA to change the source code of Module in another Module
You can change one line or search through the lines and comment/uncomment whole blocks of code. Capturing the event when vba is unlocked may be the hard part. You may have to run a sub that does this after unlocking vba.
I think you have the wrong approach to this and it would be better to structure your code more properly.
The first two on that sheet are called from other macros that are run with buttons on my main worksheet.
OK. So attach these to a form control/button, and use Bigtree's suggestion to include an optional argument in these subs. They will not display in the Macros menu. YOU can run them at least three different ways:
either from the VBE by finding the procedure and pressing F5, or
by entering the name of the procedure in the Immediate window in the VBE, or
by pressing the buttons you have provided.
The middle two are called when the sheet opens and closes
Sounds like this should be a private subroutine (or, use the method above from Bigtree) and CALL these from the one or more of the appropriate event handlers (at the worksheet level perhaps: Worksheet_Activate, Worksheet_Deactivate; or at the workbook level SheetActivate and SheetDeactivate depending on your needs)
You can always run the procedure manually from the Immediate window in VBE, or by manually invoking the event procedure, etc.
and the last two I manually call when I want to edit my main sheet
Again, call from the Immediate window or manually from the VBE. You only have 6 subroutines here, it can't be that difficult to locate the ones you frequently need. Put them in a new module and organize your modules so you know where these are.
Alternatively, put some boolean in the subroutine like:
Sub SheetLock()
If Not Environ("username") = "YOUR_USERNAME" Then Exit Sub
'other code to do stuff is below...
End Sub
UPDATE FROM COMMENTS
The Immediate Window is like a console/command line, it is where the result of your Debug.Print statements would appear, etc. It is very handy for debugging and evaluating expressions.
There are several ways you could invoke the subroutine depending on whether it is public/private, including
Application.Run "MacroName" or simply MacroName if public
Application.Run "ModuleName.MacroName" or Call ModuleName.MacroName if private
I did not want to use a private sub,
I used the shape name to determine if from a button
On Error GoTo noshapeselected
shapeis = ActiveSheet.Shapes(Application.Caller).Name
' I manually set the shape name in the page layout tab selection pane
' below I test for the desired button
If shapeis = "your button name" then
goto oktogo
else
goto noshapeselected
endif
noshapeselected:
msgbox ("must run from a button")
goto theendsub
oktogo: 'continue if desired shape was selected
theendsub: 'a button was not pushed
For those macros without buttons, but called by another macro,
set a variable to 'OK' to run a macro, then the called macro tests for 'OK' ('OK' means initiated by another macro 'NOK' means not initiated by another macro)
So I have seen all the ways to hide the screen updating in excel, what I'm looking for is a data problem, so I WANT to see the screen update. Is there a way to code the screen to update during the macro slowly? I tried the following:
'//////adding screen updating to watch what's happening
Application.ScreenUpdating = True
Application.Wait Now + TimeValue("00:00:01")
'/////
and all I got was screen flicker.
Thanks for being excellent unto me.
What you're after is a better method of debugging your errors. ScreenUpdating property of the Application is not what you want :)
Instead, set a breakpoint in your code using F9, at or before where you suspect the error is happening. If necessary, you can put this on your first line of code (if you literally have no idea where the error happens).
Here is a breakpoint, it's the red/maroon highlighted line:
Then, using the F8 key, you can step through the code line by line.
You can add as many breakpoints as you want. Pressing F5 will execute the code only up to the next breakpoint, then you would have to F8 or F5 to resume execution.
Some additional things to help you debug
Use the Locals window.
This shows you the vairables in scope, and you can click on them to view their properties/etc. As you can see, I have a shitload of variables in a fairly complicated application. I've found the immeidates window is very helpful for Object variables and arrays. Here is what it looks like when I expand an array variable, so that I can see all its contents:
Use the Immediate window to query variables or execute statements outside of your code, this is equivalent to Debug.Print statements. For example, let's check to see if the value of some variable is "9", you can:
?someVar = 9 and then press enter. It will show you True or False. You could query the value directly by ?someVar and it would print the value.
In this screenshot, I am checking the value of a boolean, and it shows me that the value is False. I could also verify this in the Locals window.
The screen updating must be set only once, at the start of the code.
But the Wait you will need to put inside your loop, or spread between your code lines.
I have a form that I want refreshed when the submit button is clicked. Preferably those that have default values will be restored and those without will be blank.
The submit button has an attached OnClick Macro that, checks to make sure all fields are filled, if so an action query runs that inserts a new row into a table.
So its after this action query that I want the refresh to occur. I have tried researching and come across suggestions that suggest using VBA code Me.Requery or Me.Refresh. I'm not 100% on how to incorporate this into the macro. The RunCode command doesn't recognize the function I put the code in, and The convert macro to VBA option in the top left is grey'd out.
I'm new to Access and just not seeing where the communications are for code and macros if someone could please elaborate for me I would be greatly appreciated.
Please consider my solution as a brief introduction to VBA. If you care to learn the language, you will find there is very little you cannot do.
Within your submit button properties, there should be an 'Event' tab. In this tab, the On Click should be set to [Event Procedure]. Click the three dot button just to the right of that, and it will launch the VBA editor.
All you need to have here between the Private Sub and End Sub lines are these lines of code:
DoCmd.RunMacro ("Mac_1")
Me.TextBox1.Value = "Null"
Me.CombBox1.Value = "Null"
Me.Refresh
MsgBox "Your Save Was Successful.", vbOKOnly, "Saved"
"Mac_1" is the name of the macro you want to execute. the ME.Refresh executes as soon as mac_1 finishes, and will refresh the page. Be sure to enclose it in a proper quote (") and not a double tick ('').
The Requery command can be used from both within VBA code or a macro. It sounds like you are using the macro designer so you can use the Requery macro action instead of VBA.
Just add this to your macro after you have inserted your new data.
This macro action lets you specify a control to requery. The parameter can be left blank to requery the source of the active object. More information can be found here.
Edit
In response to your comments, I think you should try experimenting with the SetProperty macro action (more details here).
I have attached this macro to a button click event and the value from the TextBox called txtInputValue is cleared. The Value field is left blank as you want to fully remove the value from the text box.
I hope someone have some insight into this.
I have a check box on page 1 and when it's clicked, it will launch a macro & insert a value to a text box on page 10. Simple
The problem is, the script in the macro is looking for the value of another text box on page 5 to do some calculation. Whenever i do
text5value = Val(oFFld("Text5").Result)
or
If (Val(oFFld("Text5").Result) = "") Then
The cursor will suddenly move from page 1 to page 5. Very confusing to user.
This behavior happens whenever I try to get the value of a textbox. Wherever that textbox is in the current document, it will jump to it.
Please help
Try setting Screen Updating to false for the duration of the macro.
Application.ScreenUpdating = False
Not only will this hide the various screen jumps it is doing while the macro runs, the macro will also run faster if it doesn't have to constantly update the screen.