Subroutine not fully executing when called indirectly - excel

I have a spreadsheet, with the following two subroutines in it (there's a lot more to them, but I've stripped out all the code not directly relevant to the question):
Sub HF_Reset()
Feats_Reset
End Sub
Sub Feats_Reset()
Range("TblAllFeatsSelected").Value = CVErr(xlErrNA)
Range("Test").Value = "Success"
Range("Test2").Value = 1
End Sub
Test is a single cell, Test2 is a two-cell range, TblAllFeatsSelected is a large range.
If I call Feats_Reset, it executes absolutely fine, does what it's intended to do. If I call HF_Reset, then Testgets "Success" put into it, and Test2 is filled with 1s, but TblAllFeatsSelected doesn't change. I have absolutely no clue what's going on - any ideas?
For debugging purposes, I've also tried setting Range("TblAllFeatsSelected").Value = 1 and Range("TblAllFeatsSelected").Value = 0, and again it works fine when calling Feats_Reset but not when calling HF_Reset.
EDIT: I've played some more, and traced the problem to another subroutine called in Feats_Reset. I suspect I'm not going to be able to provide enough information here to get a useful answer - it's a complicated sheet, and there's a lot of interactions that could be the problem. Bother.
EDIT2: Found the problem. The subroutine was setting TblAllFeatsSelected to the value of another range, which when calling from HF_Reset needed to have an Application.Calculate or it would justset it back to what it used to be.
Is there any way I can delete this question as not useful? It's such a specific thing, I doubt it could help anyone else.

Problem Exists Between Keyboard and Chair. I was missing an Application.Calculate in a completely different part of the code.

Related

Why doesn't my excel vba if/or statement work correctly?

I'm comparing values of numbers from 2 data sheets, and I've dropped the relevant data from both into their own arrays. I need to find matching values to run other steps of analysis.
For i = Lbound(Array1) to UBound(Array1)
For j = LBound(Array2) to UBound(Array2)
If (criteria for Array2) then
variable = 11111
Else
variable = 22222
End if
If variable = Array1(i,1) Or variable = Array1(i,2) or variable = Array1(i,3) then
more steps
Else
more steps
End if
next j
next i
The first if statement sets the variable correctly, but the variable doesn't match any of the criteria. It doesn't go to the else like it should. Now I only know this because I walked through the code step by step. If I just F5 and run the thing, "Excel is not responding". I don't know what the hang up it. All of my variables are declared and assigned a type, I'm not missing any closing statements. And I have no idea what I'm doing wrong.
What do I need to check for in my code?
EDIT
Sorry, but in this instance I'm not allowed to upload any code here. It's work related, NDA kind of stuff. Hence the pseudo code. What I need to show wouldn't be a big deal(at least I don't think it would), but I'm not risking it.
My apologies.
The solution, as it turns out, has to do with a poorly named array(not me) and a simple typo(definitely me). I'm certain that would have been an easy solve for the good citizens of Stack Overflow if I would have been allowed to post actual code.
For what's it worth, I think it's dumb that I couldn't in this case. Thanks #ScottCraner and #SuperSymmertry for trying to be helpful even without much to go on.
Super, I'm still curious about Val. If you've got a minute, I would appreciate more knowledge on that. Anything from an actual person is better than Microsoft documentation.

Finding out which function called other funciton in VBA excel

Problem
I have an excel file with a quite complicated VBA code behind and I am having some problems to track back and debug the errors.
Sometimes a function B gets a value that it should not get and crashes, but at this point it is not possible for me to know which other funciton called that function B, and the anylys process to finding it out is very much time consuming.
My solution
The solution could be transform all the functions I have in the following way:
Sub foo1(variable1 as string)
'do whatever
End Sub
into
Sub foo1(variable1 as string, inforvariable as string)
'do whatever
End Sub
Infovariable being the name of the function calling.
This is obviously very time consuming (refactoring everything). Besides I dont know neither how to access the name of the "sub" of funcion of the code calling, something like:
infovariable = self.name
call foo1(variable1, inforvariable)
Does not seems to exists in VBA
Some ideas?
I have a look here, here, and here
Debug your macro, put a breakpoint on the line with the problem (in case the line gets called too often, add a condition only to break upon that condition), and view the call stack (keyboard shortcut Ctrl+L).

Excel VBA hard crash on ModifyAppliesToRange with no error message

I'm getting a strange problem in Excel and VBA.
I'm calling ModifyAppliesToRange on various FormatCondition, along with quite a lot of other FormatCondition related stuff.
It works fine for a while (about 2-300 calls) and then for no reason I can see my Excel (and the VBA development environment) will shut down with no error from either my error handler or excel, no notification, nothing except a 'pause' where nothing happens until it crashes. This happens whether I'm running it normally or with a breakpoint and Step.
Depending on the exact contents of the WorkSheet's FormatConditions the exact number of times it works seems to vary. But if the starting condition is the same then the point of failure is the same (i.e. it fails on the same FormatCondition). Code failing is:
myCF.ModifyAppliesToRange Union(range1, range2)
where myCF As FormatCondition
I tried
Dim rng As Range
Set rng = Union(range1, range2)
myCF.ModifyAppliesToRange rng
I checked: myCF, range1, range2 and rng are all valid as far as I can tell, and show valid .Address strings (for the ranges). For example, it will fail on range1.Address="$DO$9:$GN$39,$BD$8:$BD$39", range2.Address="$CI$9:$DN$39", and the resulting rng.Address="$BD$8:$BD$39,$CI$9:$GN$39"
So I tried
Set rng = Union(Range(CFFrom.AppliesTo.Address), Range(CFTo.AppliesTo.Address))
Same problem.
On occasion (under different start conditions) it will get past the above ModifyAppliesToRange but the moment I look at myCF.AppliesTo.Address the same crash happens - whether hovering a mouse over it, or showing it in Watches, or displaying it in Immediate. Yet rng.Address gives no such problem.
Yet it also seems to work just fine for 2-300 times.
I suspect a memory problem (but Excel is not using much memory or CPU, there's plenty of empty memory on the computer, I've used Option Explicit, and so on) or a hard limit or bug in Excel
Any ideas as to why this might be happening?
Any ideas as to how I can find out what is shutting down Excel?
NOTE: To give the exact way to reproduce it I'd have to post my entire spreadsheet and code, which I'm reluctant to do. Still I might be able to send one-on-one if need be.
I've encountered this problem as well. It does seem to be an Excel bug to be honest.
However, according to this Technet forum post, it seems that Excel changes the format conditions collection on the fly when updating conditions. Seeing as that might lead to nasty bugs when processing all conditions in a loop (like I did), I first rewrote my code so that it first collects all conditions to process in a Collection, and then loops over those. That still gave me Excel crashes; possibly the condition objects themselves also get updated (created/destroyed) behind the scenes mid-way, causing stale pointers to deleted VBA objects?
Not trusting Excel to keep the order identical either, I then rewrote my code to keep looping over all conditions, finding the first to update and just restarting the loop, until not a single condition was left unprocessed. So basically like:
Dim stillBusy As Boolean
Do
stillBusy = False
Dim nextCondition As FormatCondition
For Each nextCondition In myRange.FormatConditions
Dim newAreas As Range
Set newAreas = ResizeAreas(nextCondition.AppliesTo, myRange.Rows.Count)
If Not AreasEqual(nextCondition.AppliesTo, newAreas) Then
Call nextCondition.ModifyAppliesToRange(newAreas)
stillBusy = True
Exit For
End If
Next
Loop While stillBusy
And while this is super inefficient, it... miraculously works?! (for now). Hopefully it also works for anyone else?
Btw: ResizeAreas and AreasEqual are some of my own helper functions; ResizeAreas transforms e.g. [A1:A3,C1:D3] to [A1:A6,C1:D6], and AreasEqual looks if the given two ranges are composed of the exact same cells ([A1:A2,B1:B2] and [A1:B2] = True)

Workbook_BeforePrint event not working

I want to dynamically set some data to the header (and/or footer) of a sheet.
From several forums I found numerous examples showing how to do that, and they all seem pretty easy to understand without any difficulty.
So I applied what I read to a simple try like this:
Private Sub Workbook_BeforePrint(Cancel As Boolean)
ActiveSheet.PageSetup.CenterFooter = Range("A1")
End Sub
But it merely don't work: nothing appears in my sheet preview.
BTW the only ambiguous point in documentations was about the expression of the data to use, so I also tried replacing Range("A1") by Range("A1").Text, then by Range("A1").Value, also without success.
I suppose I'm missing some simple point...
Your code worked for me. Also tested your code with some extra lines for debugging:
Private Sub Workbook_BeforePrint(Cancel As Boolean)
Debug.Print "Running Workbook_BeforePrint"
ActiveSheet.PageSetup.CenterFooter = Range("A1")
Cancel = True
End Sub
Before printing, the footer was empty; after printing, the footer in Preview matched A1 and "Running Workbook_BeforePrint" was in the Immediate window.
It's not the beforeprint that isn't working, it's the .centerfooter. Try instead:
ActiveSheet.PageSetup.CenterFooter = CStr(Cells(1, 1))
Documentation explicitly calls for a string, but I'm not sure why it explicitly needs it as a string even if it already is a string in the cell.
As other answers already suggested, the code was fine and the problem wasn't there: in fact, the issue came from the fact that it was not invoked.
And this in turn came from a silly situation: the Design Mode was enabled!
With Design Mode disabled, all works fine...
Check yourApplication.EnableEvents is true before print sheet

Cannot remove code modules from a destination workbook through VBA

I am running an Excel 2010 macro that opens another workbook and removes a few code modules (a form and a BAS module). After that it re-imports them as an updated version. This is the code:
For Each x In destination_wb.VBProject.VBComponents
If LCase(x.Name) Like LCase("frmCCLogin*") Or _
LCase(x.Name) Like LCase("modCQ_test*") Then
destination_wb.VBProject.VBComponents.Remove (x)
Next
I have no problem with the import but the remove process doesn't always work as expected. For some reason the BAS (modCQ_test.bas) module is not always removed. As a result, when I re-import, a new duplicated module is created ending with a "1" (i.e. modCQ_test1.bas).
I could see that many people experienced the same problem however, none of the proposed solutions worked for me. Not sure why this is happening?
Please advise.
If you can use the exact name of the module, you can write something like:
Public Sub RemoveComponent(ByVal Book As Workbook, ByVal Name As String)
On Error Resume Next
With Book.VBProject.VBComponents
Call .Remove(.Item(Name))
End With
End Sub
If you're stuck with wildcard matching (i.e. SomeName*) you could iterate the VBComponents collection and cache the names into a collection or array or whatever and call the function above for each name matched.
Additionally, if you wish to enumerate the VBComponents collection and remove like your code sample, I recommend that you go in the reverse order.
So something like:
Public Sub RemoveComponent1(ByVal Book As Workbook, ByVal NameSearch As String)
Dim oCompS As VBComponents
Dim oComp As VBComponent
Dim i As Integer
Set oCompS = Book.VBProject.VBComponents
For i = oCompS.Count To 1 Step -1
Set oComp = oCompS(i)
If oComp.Name Like NameSearch Then Call oCompS.Remove(oComp)
Next
End Sub
Problem is resolved. This simple line of code that hides the destination workbook, fixed the duplication issue in my case:
destination_wb.Windows(1).Visible = False
After this you can remove, then add the components. No duplication will occur.
I have experienced exactly the same phenomenon and it drove me mad for weeks already.
I do check whether the Code Module had definitely been removed directly after the removal and although it had vanished from the VBE's Project View, it still exists and consequently the subsequent import creates a Code Module named xxx1.
Any of the hints given proved not to be reliable on the long run and thus are nothing but guesses. Since the phenomenon is unpredictable as mentioned you never can really tell what did the trick.
As time (some years) has passed I do now have an answer for the phenomenon and a solid and stable solution.
In order not to "cut off the branch you sit on" one will have to envoke another Workbook/VB-Project for deleting and re-importing a Component.
Even another VB-Project performing the task will have to consider that the Component is definitely removed when the code which removed it has "finished".
Conclusion: Rename, Remove, Import, all performed by a VB-Project invoked via "Run ...." will do the trick.

Resources