Showing the updates being performed by macro - vba

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.

Related

How to pass params to Excel button macro

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.

Excel VBA - Pause code execution

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.

Update and use a Variable in an expression in SSIS

I am trying to use a variable that I am updating in a loop inside an expression in SSIS. I am going to trying to be as clear as possible. Before to arrive to the last Data Flow Task (where I have a ODBC source), I am getting some values inside the variable (Return) that I am going to use in the [ODBC Source].[SqlCommand], with the second Script Task I could checked that the variable is been updating in the way I need. The problem is that in the Data Flow the expression is taking into account this variable but with the Default value that I have choosen ('').
In the first Script task I am updating the variable:
Dts.Variables["Return"].Value = Dts.Variables["Return"].Value + identif;
So, I do not know if I missed a previous indication or what could be happening with the execution of this control flow
The Variables window will not show you the value of the variable at the end of package execution. You need to set breakpoints and use the local window to "catch" the value of the variable before and after it changes.
Breakpoints Example
I have a package with a single script task.
The code inside is this...
new string strReturn = "NewValue";
public void Main()
{
// TODO: Add your code here
Dts.Variables["Return"].Value = strReturn;
Dts.TaskResult = (int)ScriptResults.Success;
}
The code sets the my SSIS variable equal to NewValue. To catch this variable changing values I will set breakpoints. To set breakpoints, right-click the Script Task and select Edit Breakpoints.
Set a Pre and PostExecute breakpoint. Save and then execute the package. When it reaches the breakpoint, it will pause. The first pause is PreExecute event, just before the script is about to execute. During this pause, you can enter the name of your variable into the locals window.
You will see that the value has not changed yet. Press the continue button to move to the next breakpoint, PostExecute. Now, the Script Task has been executed. Check the local window and you should see that the value has changed!
Notice that throughout each of these the top left Variables window never shows an updated value. It always shows '' . You must use breakpoints to see a variable value changing. Hope this helps you to debug your package!

How to test that agent is running In Debug?

Is there a way to know that an agent in running in debug mode (Tools/Debug LotusScript has been activated) ?
I found nothing in NotesAgent class, something like RunOnServer but RunInDebugger.
I need this to avoid using the progress bar function located in NNOTESWS.DLL, which pops over the debugger and prohib any click (step into, or watching variables). BTW if it occurs to someone you still can press F8 / F5, this help at least not to kill Notes.
There Is a very good example for doing this in OpenNTF. You can find it here.
And in fact it IS for the progress bar, so you can use tho whole class from there.
The trick is: you add a function with a stop statement. You measure the time before the stop statement and after. If the time passed is bigger than 100ms, than a user had to click on "continue", what he never manages to do in such a small amount of time. If debugger is not enabled, the stop is ignored - no delay...
Here is the function used in the linked openntf article:
Public Function IsDebugMode() As Boolean
Dim start As Variant
start = Getthreadinfo(6) ' LSI_THREAD_TICKS
Stop
If Getthreadinfo(6) - start > 100 Then IsDebugMode = True
' If you debug the application you will not be able to press the CONTINUE-Buton
' within less then 100 milliseconds, otherwise the STOP-statement is not in function
' and you will always be quicker then 100 milliseconds
End Function
Although the comment is in fact wrong (100 tics are not 100ms, you would have to devide by ticks per second to get that value), the code still works and does exactly what you want.

Display time left when running

I have a form with a few buttons which execute code when pressed like running validations on the database.
Some code can run for a few minutes so is there any way to show the time remaining or a message to display the % of process completed?
Or pop out a message when code evaluation starts and the message should disappear once code running is completed?
What you are probably looking for is a "Progress Bar".
I've used the Microsoft ProgressBar control (you can find it under Insert->ActiveX Control), and it's not that hard to use. Just set the value of it to a percentage (as an integer, not a decimal).
'foo, being the ProgressBar
me.foo = 70 '70%
There is some good info here on another method: http://www.granite.ab.ca/access/progressbar.htm
In order to do this the "normal" way, you'd need to run your validation in another thread and have it report its progress back to the UI thread. However, I don't believe VBA supports any kind of multithreading.
If your validation routines involve a loop, or even just many separate discrete operations, you can try inserting a DoEvents statement in between loop iterations (or operations), and then have your progress display updated periodically (say, in an Application_OnTime event handler).
I usually have a form I name frmProgress or whatever, with a cancel button and a label for displaying a status message. Then embedded in the form code I have a boolean called bCancel, and when you hit the cancel button it simply sets bCancel as true.
Also in this code I have a routine called ShowPercDone( Idx , NumIdc ) where Idx is the step the code is on, and NumIdc is the number of steps the code will take (assuming each step takes the same amount of time). This works well when I'm running through a for loop, but basically any time I want to display a status update I just call the routine in the form with my message, which I should add runs the doevents command for me.
So that's how the status form works. In the macro I run, I start out by just calling frmProgress.show (0) so that it lets you click the cancel button. Then in my loop when I update the status message I then check frmProgress.bCancel and if it's true I exit out of the macro.
Hope that helps.
Finally to be simple i decided to use the method given here
http://oreilly.com/pub/h/3330#code