VBA: nested With with If statement - vba

Is nested With allowed in VBA? If it is, how to use it with IF statement?
I have the following nested With combined with If statement and compiler gave me an error message saying "End With without With".
With
If
With
End With
Else
End With <- End With without With
End If
I put the first With outside the IF statement because the IF statement can use it. Since the above code didn't work, I tried a different way. Another error message was obtained if I moved the first With inside the IF statement. This time, the error message says "Else without If". That leads me to wonder if nested With is allowed in VBA.
A google search turned up one hit, which is not exactly the same as my problem.

Try like below
With
If <Logical Test> Then
With
'Your action here
End With
Else
'Your other actions here.
End If
End With

The With End With structure applies to the current scope only. The scope of if else is different to else endif. Thus the with should either encompass the whole if statement or appear seperately in each scope.
It's perfectly possible to have a with end with nested inside other With End With structures. In this case you have to remember that the leading . Refers to the current scope.

Related

Trying to stop the save process due to an error being promted

I'm trying to provide on the save button a validation error saying a certain field can't be left blank.
I'm honestly not sure what to try.
If txtGEMFeeWBS.Text = "" Or lblGEMFeeWBS.Text = "" Then
MsgBox("Error Gem Fee WBS Code must be provided before you can save")
End If
Save_Validation()
If blnValidation = True Then
If Me.lblInvoiceShipmentID.Text = "" Then
Save(1)
Else
SaveAllKitUnits()
Save(2)
End If
End If
After where the message box is thrown I want to close out and not hit save data information
I'm not sure about having understood the question but...
It depends on a lot of things. Do you want to completely close the program? Are you inside a method?, etc...
If you want to close the entire program (I don't think so) just try
Application.Exit()
If you are on a method you can just use the instruction return nothing
And in other cases use the GoTo: Anywhere on the code (almost
anywhere) you can put SampleGoToLine: (don't forget the ':')
and then call the instruction GoTo SampleGoToLine anywhere you
want or, in your case, after showing the messagebox.
(The name SampleGoToLine is invented, you can put any not reserved VB keyword)
Finally what I would personally do is to reestructure the code. Maybe split validation and save into two different methods or something similar so you can always control what method do you go to depending on certain conditions. (With a simple if-else structure)

VBA: Run-time error '5825' Object has been deleted

I was putting this code ActiveDocument.Variables("time1").Delete before End Sub and I get that error "Object has been deleted" so that if a variable "time1" exist, it will be deleted at the end of the procedure. I understand why I get that code because "time1" has already deleted on the first run but I want to skip and end the sub if it encounter errors. I tried to do this
On Error Goto here
ActiveDocument.Variables("time1").Delete
here:
End sub
but I still get that Error. Why is it that the error handler did not work?
You should be able to avoid this if you are not interested in whether the Variable existed or not.
ActiveDocument.Variables("time1") = ""
should remove a Variable called "time" if there is one, and execute without errors if there is not.
In a similar way,
ActiveDocument.Variables("time1") = "something"
will create the Variable if it does not exist.
This is one of the things that makes Variables slightly easier to work with than Custom Document Properties, although it does mean that empty variables are not allowed.

What's the difference between GoTo, using a Select, and using separate function?

To start off, I know that using Goto is never a good idea. But I'm having a hard time seeing the difference between the following structures...All of them process conditions sequentially, stop processing when they find a true value, then return control to a specified location in the code (the next line, as that's where this particular 'GoTo' target is). What is the difference between:
Ifs with GoTo:
If ConditionA then 'This is designed to skip the evaluation of condition B if condition A is met.
Do something
Goto Resume
End If
If ConditionB then
Do something
Goto Resume
End If
Resume:
Select Case:
Select ConditionIsTrue 'This will also skip the evaluation of B if A is true.
Case A
Do something
Case B
Do something
End select
Separate sub:
EvaluateConditions(condition)
Sub EvaluateConditions(condition)
If A then
DoSomething
Exit Sub
End If
If B then
DoSomething
Exit Sub
End If
End Sub
In general,
'goto' transfers the control of execution to the label that you are assigning. The control never comes back to where you use 'goto'. As the program flow is altered altogether, it is not advisable to use 'goto'. It becomes hard to debug.
When you write a subroutine and call it from other part of your code, the control is transferred back to the called part of your code once the execution of subroutine is complete. Hence, unlike goto, the program flow will not be affected and is always advisable to use subroutines instead of goto.
In case of select statement, it is not much different from multiple 'if-else' statements. Instead of having too many 'if-else' you can use 'select' to have a more cleaner code.
Being specific to what you have asked, all three does the same and there is no difference as such. What you choose depends on your requirement, number of conditions, re-usability of the piece of code and future enhancements.
If you have a very few conditions ( 2 or 3) and if you are sure that the piece of code doesn't require future enhancements, it is 'ok' to use goto.(still not a great choice)
If the piece of code should be reusable or even otherwise, using subroutine is the best choice. In fact, even if you have a very few conditions, it is better to use 'select' statement within the subroutine so that your code looks clean and is easy to add further conditions in future.

Expected end of Statement Error on Simple Formula Insert

###.value = "=LOOKUP(LEFT(W2),{"C","A","B"},{"Pick Up","Collect","Prepaid"})"
I want VBA to do this simple formula but getting "Expected: end of Statement" error.
It seems that I need to define something as VBA doesn't recognize character "{}" the brackets.
Assuming that ### actually symbolizes a cell object (otherwise you would get a compile error):
###.Value = "=LOOKUP(LEFT(W2),{""C"",""A"",""B""},{""Pick Up"",""Collect"",""Prepaid""})"
Also, I thought that you would have to change .Value to .Formula, but I tested and both ways work.
It might be requiring you to end the script like this
###.value = "=LOOKUP(LEFT(W2),{"C","A","B"},{"Pick Up","Collect","Prepaid"});"
OR
###.value = "=LOOKUP(LEFT(W2),{"C","A","B"},{"Pick Up","Collect","Prepaid"})";
NOTICE: the Semi-colon at the end ';'.
I'm not a VBA user for a long time. but just try. Delete this answer if its not good enough.

How to check if a Paragraph is in a Table or not in MS-Word macro?

The paragraph object in the Word has a property called Range. Within this Range object has a property called Cells.
For paragraph that are not in a table, this property Paragraph.Range.Cells is set to "". This can be seen in the Watches window in debug mode.
For paragraph that are in a table, the property Paragraph.Range.Cells has other properties in it, for example it has a property called Count.
I am using this property of Paragraph.Range.Cells to determine if the paragraph is in a table or not. However, I cant seem to figure out how to test this.
For example, I cannot simply test like this...
If paragraph.Range.Cells <> Null Then.... or even
If IsNull(paragraph.Range.Cells) Then ...
It throws a Run-time error '5907' There is no table at this location
So, how would I test for this? thanks
You can use the Information property:
If Selection.Information(wdWithInTable) Then
'What ever you'd like to do
End If
Hence you don't need any manual error catching mechanisms.
You can't call the Cells method unless the paragraph is in a table. You need to use a different method to determine whether the range is in a table.
You can use either...
paragraph.Range.Tables.Count > 0
...or...
paragraph.Range.Information(wdWithinTable)
Note that the second one looks more obvious, but is actually slower (only a problem if you're doing this inside a loop).
*Edited (if Err=) changed to (If Err<>)
You can simply allow the error to happen and catch it using OnError statement
Dim ParagraphIsTable As Object
OnError Resume Next 'allows errors to happen but execute next instruction
ParagraphIsTable = paragraph.Range.Cells
If Err <> 5907 Then '(this is to check for a specific error that might have happened)
'No Error occured, this means that ParagraphIsTable variable must contain a value
' Do the rest of your code here
Else
' an Error occured, this means that this is not a table
' do whatever
End If
OnError Goto 0 ' This cancels the effect of OnError Resume Next
' Which means if new errors happen, you will be prompt about them