IF statement error despite the check being FALSE and the [value_if_false] being 0 or 1 - vba

For my own amusement I am trying to automate a project from work to learn more about excel vba. For the primary tab of data, I have an import function that drags in the relevant columns from another sheet for columns A through J. After that, there are a bunch of columns already set up to manipulate the the data being imported.
One of the calculation columns is supposed to return a basic 0/1 flag if the related company has been a client for >20 years. However, it ended up being a very slow UDF, so I wrapped it in an If statement to check if any other flags are false first so I can skip the slow calculation if the claim is already being eliminated. It worked fine before I went back to tweaking the import macro. Here is the function:
=IF( Q2*O2*N2 = 0, 0, IF(CompanyYears(J2, End_of_Claim_Period, Analysis_Width) >= Valid_Co_Years, 1, 0))
So now after the data import the only two results the column gives are 0 and #VALUE!. However, the 'evaluate function' step through confused me more. Turns out that for every value error, the 3 flags from columns Q/O/N are 1. So first the evaluate looks up and multiplies those 3 flags, gets 1=0 -> FALSE. The next thing it does is resolve what the named range End_of_Claim_Period points to. While it successfully changes it to a cell address, the outer IF statement's value_if_true changes from 0 to #N/A at the same time. The inner if statement continues just fine to a result of 0 or 1, and finally the statement
=IF(FALSE, #N/A, 1)
or
=IF(FALSE, #N/A, 0)
gets evaluated to #VALUE!.
Also, if I try to filter that column to see only the rows with a #VALUE! response, it correctly reevaluates them to the appropriate 0/1 values. I tried having the vba code filter then unfilter the row automatically but that leaves the errors in place still.
Update: While working on something else I came across a somewhat similar question here:
Excel is not updating cells, options > formula > workbook calculation set to automatic
I added Application.CalculateFull in at the end of the macro, which technically solved my problem, albeit for a notable performance hit.

Related

SUMIFS returns 0 using dynamic criteria, with criteria range and sum range on another sheet

Anyone,
I've chatted with and called excel customer service with no luck. I used the formula builder (please see attached screenshot) to make sure each element of the formula is correct and returns the value for the criteria I'm trying to reference.
Everything is accurate, but it returns a value of 0. When I do the same thing in the actual sheet the data is stored in (and click a criteria cell within the criteria range) it returns the accurate value?! I'm not sure why it won't work on the other sheet. The values I am using to select are dynamic and change with a drop down. I have another, advanced, workbook (I did not create) that does the same thing and completes an even more complicated formula, but actually works so I'm not sure why this is returning a 0 value.
Photos and code/syntax: Dynamic Selection, Example 2 of it working, Example 1 of it working, Formula Builder, CountIFs, Advanced Spreadsheet working, VLOOKUP
=SUMIFS('GFEBS Pull'!Q:Q,'GFEBS Pull'!G:G,FMCOP!$C$20,'GFEBS Pull'!H:H,FMCOP!B23)
or:
=SUMIFS('GFEBS Pull'!Q:Q,'GFEBS Pull'!G:G,'FMCOP'!$C$20,'GFEBS Pull'!H:H,'FMCOP'!B23)
When I type ' around FMCOP sheet name, they disappear? I've also tried to lock the columns on the 'GFEBS Pull' sheet with no luck. Cell B23 is not locked because I'm going to copy the formula down to reference other cells. Any help is appreciated!
In this screenshot you can clearly see that both FMCOP!C20 ansd FMCOP!B23 have prefacing spaces; e.g. " HHC".
Since " HHC" will never match "HHC", fix the data returned from 'the lower table in the same screenshot'.
A Text-to-Columns, Fixed Width, Finish should do this. You could adjust the original formula like,
=SUMIFS('GFEBS Pull'!Q:Q, 'GFEBS Pull'!G:G, TRIM(FMCOP!$C$20), 'GFEBS Pull'!H:H, TRIM(FMCOP!B23))
I would caution against the latter 'bandaid' fix. Fix the original data; do not apply bandaids on-the-fly.

Range("CustomTable").SpecialCells(xlCellTypeVisible).Delete now fails. Run-time error '1004'

was wondering if anyone noticed a change in behaviour of the following or similar code:
.Range("CustomTable").SpecialCells(xlCellTypeVisible).EntireRow.Delete
I use it to delete filtered range on a ListObjects table in excel 2013 and until about last week it was working fine; and now, if there are at least two non-sequential lines needed to be deleted, it is throwing an error: "Run-time error '1004': Delete method of Range class failed. I am sure it is not just the case that nothing is visible in filtered data-set, I ran it in debug and it definitely has multiple lines to delete, and it does give a normal entire row address with multiple lines to delete, but it fails to.
I have solved it by stripping out EntireRow and suppressing excel alerts on confirmation menu if I want to delete entire row. I am just quizzed why it suddenly stopped working?
I've come across this problem as well. What I've found to work is to save the range, remove the filter and then iterate through the areas of the range in reverse order (required as ranges change as you delete).
I've added in the "Application.Union" to take care of hidden columns. I just found a case of hidden columns creating multiple areas for the same row. So the solution to that is to get the SpecialCells range with the EntireRow, which still gives you duplicate areas for full rows. Then using the Application.Union you can compress these into a unique set of areas in a range.
Set delete_range = Application.Union(.Range("CustomTable").SpecialCells(xlCellTypeVisible).EntireRow, .Range("CustomTable").SpecialCells(xlCellTypeVisible).EntireRow)
.AutoFilter
Set delete_range =
For i = delete_range.Areas.Count To 1 Step -1
delete_range.Areas(i).EntireRow.Delete
Next
Hope that works for you. The disabling alerts didn't solve my problems. Everything else I tried had corner cases that didn't work. I assume you've already catered for removing the header (if you have one) from the range of interest.
NOTE: I also had another strange case which was resulting in the range = nothing. Can't remember the reasons for this happening, but I also included a check for nothing of the range before processing. I didn't include that in this answer.
Just to clarify: I have found a work around it, therefore not looking for one, I am just trying to understand why this line worked OK previously and doesn't work now.
In case anyone stumbles into this post whilst searching for the solution the line can be replaced by the following 3 lines, giving same result:
Application.DisplayAlerts = False
.Range("CustomTable").SpecialCells(xlCellTypeVisible).Delete
Application.DisplayAlerts = True
P.S. I am personally not a big fan of suppressing alerts, but feel like this is the most optimal fix...

Return blank if #VALUE is returned

I've setup a formula that combines numbers from multiple worksheets and then compares it against another number from worksheet.
I am using the INDIRECT function to reference the sheets as well as COLUMN and ROW to adjust the numbers to the corresponding coordinates when I drag it across.
However, some of the figures don't always exist in the worksheets so a #VALUE error is returned. How Can I change it so a blank cell is shown if this happens?
My Current formula: =INDIRECT("'"&$C$11&"'!R"&ROW(E29)&"C"&COLUMN(E29),FALSE)-SUM(INDIRECT("'"&$C$11&"'!R"&ROW(C29)&"C"&COLUMN(C29),FALSE),INDIRECT("'"&$C$13&"'!R"&ROW(E29)&"C"&COLUMN(E29),FALSE))
Use =IFERROR(<your original formula>, "") which will replace any error with "" but passes any other result through.
But do bear in mind the degradation in spreadsheet stability: INDIRECT makes spreadsheets brittle enough on its own: your hiding any error output could be dangerous.

#Value! error with =(A1+A2)

I'm trying to add multiple cells with the formula =(A1+A2+A3...etc)
Which works, but if all the cells are empty then I get a #Value!
PLEASE NOTE:
Yes I am aware the proper way to add cell values is with =SUM(A1:A3)
However the cells I'm adding together each have their own functions to get their numbers, and the =SUM function won't add them together.
So! Is there a way I can make =(A1+A2+A3...etc) not give me a #Value! error in the cell that's supposed to total them if ALL the cells (A1,A2,etc) are empty? (as in, the cell with the total will just be blank)
Yes I know this is overly complicated. I'm working with that I've got.
EDIT
I might have figured out my problem. My 'false' statement in the function of the cells that were being added is "" in order to make the cell not have a 0 in it when empty. When it tries to add those cells together, if they all read "" and none are a number that's when I get the #Value! error. Not sure yet what I'm going to do about that...
EDIT 2
Yup. Problem was caused by having a non-numerical value as my false statement. Didn't want a bunch of zeros everywhere, but oh well I guess.
I tried both Excel 2007 and Calc 3.4.1, and neither one of these generated the #Value! that you mention. I am thinking that perhaps your source cells' equations are producing a value that is causing this to error out.
For example, if one of the cells has a String value, then this will be the result. This can be detected with the TYPE() function. for example:
=( IF(TYPE(A1)=1;A1;0) + IF(TYPE(A1)=1;B1;0) + ...)
this will make sure that you are actually adding numbers before the addition takes place.
edit
See: http://www.techonthenet.com/excel/formulas/type.php
for details on TYPE()

For each cell in a range, if a value in a seperate range is found in the next cell do stuff

This Macro I have built works but I am hoping for a faster version or a Formula that will do the same in less time.
What I Have:
For Each cell In Range("Table_Query_1[[#Data],[Reason2]]")
For Each PossibleValue In Range("F2", Range("F2").End(xlDown))
If Len(cell) = 0 Then
If (InStr(UCase(cell.Offset(0, 1)), UCase(PossibleValue)) <> 0) Then
cell.Value = PossibleValue.Value
End If
Else
Exit For
End If
Next
If Len(cell) = 0 Then
cell.Value = cell.Offset(0, -1)
End If
Next
The only other way I could get anything to work way with the following Array Formula
=IF(ISNA(MATCH($F$3:$F$10,[#Extra Info],0)),[#Reason],$F$3:$F$10)
but this doesn't work for Partial matches as in the case of Row 4 and 9. I also have my doubts that this array formula would be that much faster then a vba macro along with the fact it would also require more upkeep with the test values range (F2:f3) in this case as I would have to constantly update that formula OR I wouild have to make the original range like F2:F100 witch would cause it to take that much longer.
So, what i'd like is if ANY value in my range of values (F2:F3 in this case), Is found inside of the Extra Info Column on the current Row , Then Reason2 of that row (Offset(0, -1)) equals the Value that was matched. But if nothing is found then just use the Reason in that row(Offset(0,1)).
And the second Issue is that I need the Macro to Run After the QueryTable refreshes but if I set it as a Cell Change Event on a cell the is in the query that will change, the macro runs and finishes before the Final querytable is imported and sorted.
Solved!
This is post the comment that I posted above which had the initial formula.
=IF(COUNT(FIND($F$2:$F$3,C1)),"What Will Go Here",A1)
The below tells you what has to go in place of "What Will Go Here"
Put this formula in cell B2. Note that this is an Array Formula. You will have to press CTRL + SHIFT + ENTER after you enter the formula.
=IF(COUNT(FIND($F$2:$F$4,C2)),INDEX($F$2:$F$4,MATCH(SUM(IF(ISNUMBER(--FIND($F$2:$F$4,C2,1)),--FIND($F$2:$F$4,C2,1))),FIND($F$2:$F$4,C2,1),0),0),A2)
Screenshot
Explanation:
FIND($F$2:$F$4,C2,1) when used with an array returns an array. To check the values you can highlight it and press F9 and it will tell you the position at which the match is found. See this screenshot
So it tells us that it found the match at the 3rd position in 4532. It yet doesn't tell us with what did it find a match.
Now the next step is to retrieve the position of that number from the array. So in the above example it will be position 2 and to find that position we will use MATCH() and to use MATCH we will need that 3
So to retrieve 3 from the array we use this formula
=SUM(IF(ISNUMBER(--FIND($F$2:$F$4,C2,1)),--FIND($F$2:$F$4,C2,1)))
Now we have that 3 so we will use it in Match to find the position in the Possible Value
=MATCH(SUM(IF(ISNUMBER(--FIND($F$2:$F$4,C2,1)),--FIND($F$2:$F$4,C2,1))),FIND($F$2:$F$4,C2,1),0)
This will give us 2
Now we know the position of the number in the Possible Value. To find that number we will use INDEX
=INDEX($F$2:$F$4,MATCH(SUM(IF(ISNUMBER(--FIND($F$2:$F$4,C2,1)),--FIND($F$2:$F$4,C2,1))),FIND($F$2:$F$4,C2,1),0),0)
SAMPLE Workbook
http://wikisend.com/download/280280/Sample.xlsx
This is a solution I came across that does not have to be Array Entered and seems to run faster then Siddharth Rout's solution. I am using the formula
=IFERROR(LOOKUP(1E+100,SEARCH($F$2:$F$4,C2),$F$2:$F$4),A2)
Where I am looking for any word in C2 that is in the range F2:F4. If none found it will throw an ERROR and in that situation I know nothing was found and simply return the original reason.
Not shown in the picture I also turn F2:F4 into a named range called Reasons and change the formula too:
=IFERROR(LOOKUP(1E+100,SEARCH(Reasons,C2),Reasons),A2)