I'm trying to get rid of #NAs in excel, I've tried using the VLOOKUP formula but it doesn't seems to be working in my case. I just have one cell from A1:A18, and two of the cells contains NAs, I was wondering what the VLOOKUP formula would be like to get rid of those cells.
Use the formula =IFNA(A1,"") in an adjacent column and copy downwards. The second argument of this function is the value that you want to replace a cell containing #N/A with. I've chosen a blank string, but you could use 0, &c.
On older versions of Excel (prior to the 2013) release, use =IF(ISNA(A1), "", A1)
Then perform the rest of your analysis on that newly created column.
I dislike removing the #N/A cells as that can destroy the structure of your workbook, and using VBA to remove them is inherently buggy since #N/A propagates through built-in Excel functions.
In general:
Select A1:A18
Run the following:
Sub InsertIFERROR()
Dim R As Range
For Each R In Selection.SpecialCells(xlCellTypeFormulas)
R.Formula = "=IFNA(" & Mid(R.Formula, 2) & ","""")"
Next R
End Sub
It is a bit dangerous, because you will not see #NA errors and you cannot revert the formulas with Ctrl+Z.
Related
The true problem I'm trying to solve:
I've pasted text including formulas from one Excel workbook to another, but I don't want to reference the old workbook in the formulas
The question I'm asking:
How can I find and replace (or similar results) references to an old workbook, where I want formula to instead reference (identically named) internal data table? I want to replace the values within a formula, but my best guess is that Excel is having a problem with some kind of special character
Sample:
The following is formatted as a data table named "Data" in "MyOldWorkbook.xlsx" and "MyCurrentWorkbook.xlsx"
ColRowNum
ColAmt
1
5
2
10
3
5
The original/desired formula: =COUNTIFS(Data[ColAmt],"<=10")
The unwanted formula when pasted: =COUNTIFS('MyOldWorkbook.xlsx'!Data[ColAmt],"<=10")
Notes:
The sample is overly simplistic. The easiest thing to do is manually just deleted out the unwanted text, but I'm looking for the systematic solution.
I feel like I'm missing some "escape" character command/grep thing/something in the find & replace dialogue.
Fails
If I try to put into the Find and Replace dialogue box(es) Find: 'MyOldWorkbook.xlsx'! and replace with "" (actually blank), I get an error.
If I try to shorten it (remove the !) I get an error about how excel has broken formulas (true) and refuses to find/replace for me
Can't break the external links, since that converts my formulas (formula, in this simple example) to numbers
UPDATE I've encountered this issue before and didn't have a solution other than manually fixing the text. When I was replicating the problem to a colleague, the above find-and-replace method actually worked. I don't think this has ever worked for me before. Does anyone have any ideas????
Sort of not-a-terrible-Solution: Use a Formula
As I'm posting this, stackoverflow tried to see if my question was answered before and it got me thinking which got to a solution that isn't horrendous, though I was hoping to use the GUI find/replace feature:
A1 (formula): =COUNTIFS(Data[ColAmt],"<=10")
B1 (text): 'MyOldWorkbook.xlsx'!
Use this formula in C1 =SUBSTITUTE(FORMULATEXT(A1),B1,"")
Copy and paste-vales from C1 into D1
Done
Terrible (but relatively functional) solution: Paste As Text etc.
Format formula cell as TEXT (or paste formula in a cell formatted as text)
Find/Replace "=" with "" to remove Excel thinking it's a formula (or otherwise remove "=")
Find/Replace "'MyOldWorkbook.xlsx'!" with ""
stitch back formula in some way and copy text back to original formula cell
You can programmatically remove references to different workbooks in Excel formulas using either a macro or VBA script.
You can loop through all of the cells in a worksheet and modify the formulas to remove any references to external workbooks. I have created an example below:
Sub remove_external_references()
Dim cell As Range
Dim ws As Worksheet
Set ws = ActiveSheet 'Change to the desired worksheet
For Each cell In ws.UsedRange
If cell.HasFormula Then
cell.Formula = Replace(cell.Formula, "[", "")
cell.Formula = Replace(cell.Formula, "]", "")
End If
Next cell
End Sub
This script uses the Replace function to remove any square bracket characters "[" and "]" from the formula, which are typically used to indicate a reference to an external workbook.
You could of course change it anyway you want to, for example: cell.Formula = Replace(cell.Formula, "'MyOldWorkbook.xlsx'!", "")
Additionally, you can use the Workbook.LinkSources property to get the list of external links for a workbook, and use the Workbook.ChangeLink method to update the references.
I've had a scroll through most of the SUMIFS questions here and they all seem to be variations of double quote problems, as opposed to what I'm getting.
I'm trying to insert sumifs into a table which is triggering runtime error 1004. The sum range, and the three criteria ranges are all in a different table (on a different tab, though that shouldn't make a difference), and the three criteria are all in the table where the formula is being entered. The first critera is the row header, the other two are other cells in the same row. Within the code, the table where the criteria are, and the formula is being entered is in a ListObject variable (summary_table) and the sum and criteria ranges are in a different ListObject variable (data_table)
Code is as follows:
For i = 5 To summary_table.ListColumns.Count - 1
summary_table.ListColumns(i).DataBodyRange.Formula = _
"=SUMIFS(data_table[Amount],data_table[FOCUS GLs],summary_table[[#Headers],[" & _
summary_table.HeaderRowRange(i).Value & "]],data_table[Employee Number]," & _
"[#[Position Number]],data_table[Posting Date],[#[Posting Date]]"
Next i
Basically, just looping through the fifth column through to second last and inserting this sumifs formula in. This is then within a larger loop that goes through 40 or so entities. The summary_table is a listObject variable pass to this particular sub.
If I put a debug.print statement in to look at the actual formula string that is being produced, and copy that into the table, the formula works fine.
If I built a sub-routine that puts the sum range and the three criteria ranges into range variables, and the three criteria into three long variables, then loop through each range in each listColumn.DataBodyRange and enter in the result of calling Application.WorksheetFunction.SumIfs(sum_range, crit_range1, crit1 etc...), that will populate the cells with the correct value.
However, this takes 10-20 second per entity for which this is being done, adding 7-15 minutes to the running time. If the formula in the code block worked, it should only be a few milliseconds. Additionally, if someone updates the data table (which is unlikely, but possible), the lack of a formula means the summary table will no longer hold the correct value.
I cannot for the life of me work out why it is not working and would appreciate any comments, observations, thoughts or general abuse.
I suggest you apply a few basics. That will make your formula easier to read. Once it's easier to read I would attempt to do so. But if it were easier to read you probably wouldn't need my help. So, let's apply basics.
A ListObject as a Range, ListRows and ListColumns. It also has Header and Total rows which are included in the Range.
A ListObject's DataBodyRange excludes the headers and totals. It's nothing but a named range. In fact, the name for it is set up by Excel to be the same as the table's. Since it's a range it has rows and columns which you can address by their range (DataBodyRange) or sheet coordinates.
Therefore one wouldn't use ListRows or ListColumns to address DataBodyRange rows and columns. Your code would become a lot simpler if you were to use With summary_table.DataBodyRange to start the show off.
A SUMIFS function has these arguments:-
= SUMIFS(SumRng, Crit1_Rng, Crit1, Crit2_Rng, Crit2, etc)
Therefore, once you hit a problem - and a problem you did hit - you should resolve all arguments. Then your code would look somewhat like this:-
Dim Formla As String
Dim SumRng As Range
Dim Crit1_Rng As Range
Dim Crit1 As Variant
Dim Crit2_Rng As Range
Dim Crit2 As Variant
Formla = "=SUMIFS(" & SumRng.Address & _
"," & Crit1_Rng.Address & "," & Crit1 & _
"," & Crit2_Rng.Address & "," & Crit2 & ")"
True, your code looks a lot more compact and uses fewer characters but it also brought you to this forum. Set SumRng = data_table[Amount] allows you to check Debug.Print SumRng.Address, a luxury you have denied yourself by design. And please don't believe that your code would run faster because it doesn't need to assign the range to a variable. It will have to do that whether you instruct or not.
Now all that remains is to assign the formula. You suggest summary_table.ListColumns(i).DataBodyRange.Formla. But wouldn't that assign the same formula to every cell in the DataBodyRange? If you want to assign the formula to all cells in one column your syntax should look somewhat like this:-
summary_table.DataBodyRange.Columns(i).Formula = Formla
Of course, this doesn't address the question of absolute and relative referencing. But in the logically structured approach that I have recommended above you would solve that when you assign the ranges, perhaps using Address(0, 0) in place of the naked Address I showed above, setting the formula for a single cell and then copying that cell to the rest of the column. But you can also use structural referencing, perhaps by using string variables in place of the ranges I showed above. Once the toys are all laid out you can start playing with them.
For those of you playing along at home (and I suspect it's only me, but there's a useful lesson in this anyway), I finally found the answer to the problem, and it's as stupid a minor detail as is always the case. I decided that VBA didn't like SUMIFS formulas split across two tables on two different sheets, so decided to change it to cell references. (For the record, VBA is fine with formulae across multiple tables on multiple sheets, but it at least led me down the right path).
Now, the default A1 reference style is a thing of beauty when working directly in the Excel spreadsheet, but it's disgusting to code with (getting the .address variable and splitting on $ is just unnecessary code - great if you're being paid by line of code, but just nasty to work with and worse to maintain). So I used R1C1 reference style. Still wouldn't work in the VBA code, but if I debug.printed the formula out and copied and pasted, it was fine. But, R1C1 formulae tend to be much shorter, so I could compare the debug.print text, copy and paste it just under where I had the formula I'd built in Excel as a comment straight under each other on a single line, and lo and behold:
'=SUMIFS(Data!R2C17:R777C17,Data!R2C1:R777C1,R1C,Data!R2C13:R777C13,RC1,Data!R2C16:R777C16,RC4)' '=SUMIFS(Data!R2C17:R777C17,Data!R2C1:R777C1,R1C,Data!R2C13:R777C13,RC1,Data!R2C16:R777C16,RC4
"Close your (expletive deleted) brackets, Yianni!!!"
And of course, Excel somewhere around the 07 release decided that if a simple, non nested, single bracket formula was missing the last bracket, it would just add it when you hit enter, so pasting the incorrect formula in Excel worked because it corrected it for me...
So, the takeout from this is something I should have known all along - R1C1 reference style is always the answer in VBA if at all possible, it's just this particular case needs table reference formulae instead.
I have a table of results in MS Excel 2010 with formulas in each cell that I need to edit. I have INDIRECT cell references in the formulas that do not update when copied to other cells. So, I believe the easiest way in this case for me to edit all the formulas in the table is with two find-and-replaces (changing the beginning and end of each formula to have what I need). However, when I try to do the find and replace, Excel shoots a "The formula you typed contains an error" pop-up at me and refuses to execute the replace. I know there's an error, I'm not finished with the formula yet! So:
1) How can these errors be disabled?
2) Is there a way to make indirect cell references update the way a normal cell reference would (eg. make INDIRECT("'"&F5&"'!L7") update L7 to L8 in the next row) so that I can copy the new formula throughout the table of results, and avoid the find-and-replace entirely?
Sorry guys, I realize this is a somewhat strange question for stackoverflow.
1) I don't know.
2) I'm not 100% sure from the question, but I can think of two scenarios:-
(a) You have a list of references which your INDIRECT formula uses, and you want it to select each one in turn as you pull the formula down. This is trivial so it's probably not what you meant:-
=INDIRECT(A$1&"!"&A2)
assuming your sheet name is in A1 and the references are in A2,A3 etc.
(b) You have a reference to the beginning of a range of cells in sheet2, and when you pull the INDIRECT formula down, you want it to automatically get the next cell in the range:-
=INDIRECT(SUBSTITUTE(ADDRESS(1,COLUMN(INDIRECT($A$2)),4,1,$A$1),"1","")
&(ROW(INDIRECT($A$2))+ROW()-ROW($C$2)))
where this formula is placed in cell C2 and pulled down.
The idea is that you break the cell reference down into its column name (using the excellent suggestion here ) and its row number, then get the row number to increment using the ROW function.
Sheet 2:-
Sheet 1:-
I'm wondering if anyone knows of a way to get a cell to implement a specific formula based on the contents of another cell.
For example, if one cell contains "general" then a generic sum formula is applied to the cell, though if it contains "conditional" then a countif formula is applied. I can't do this through a general series of chained if statements as there are around 500 formulas that constantly get added and amended and the formula entry area is insufficient to hold them all.
I've figured it out using a UDF and evaluate.
Public Function ev(r As String) As Variant
Application.Volatile (True)
ev = Evaluate(Replace(r, "#", Application.Caller.Row))
End Function
Put a Vlookup inside the ev() call, and have the formulas with # replacing all the row references. Not sure if it is the best way but it got it working.
How does one cell obtain the formula of another cell as text without using VBA? I can see this question has already been asked many times and the answer is always to write a custom function in VBA.
However, I found a post made in 2006 which claimed to have found the non-VBA solution but the link provided in that post is already broken.
=FormulaText(Reference) will do the trick Documentation
There is nice way of doing this without VBA. It uses XL4 macros (these are macros, but it is not VBA, as asked).
With reference to the figure 1, cells A2:A4 contain usual formulas.
Going to Formulas -> Define Name, I defined two named ranges (see fig. 2), with the information shown in cells A6:B8.
Enter in cell B2 =FormulaAsText. This will retrieve the formula in cell A2 as text.
Explanation:
The named range FormulaAsText uses =GET.CELL(info_type,reference). In this case, ìnfo_type = 6 retrieves the formula, and reference = OFFSET(INDIRECT("RC",FALSE),0,-1) uses the cell with 0 rows and -1 columns offset from the one the formula is used in.
Copy B2 and paste into B3:B4. This will show formulas in A3:A4. Cell A4 shows that the worksheet function CELL only retrieves values, not formulas (as opposed to GET.CELL).
Since FormulaAsText gets the formula from a cell at fixed offset (0,-1) from the current, I defined another range FormulaAsText2, which uses an offset (rows,cols) read from the worksheet itself. Cells D2:D4 contain =FormulaAsText2. Thus, cell D2 shows the contents of cell B3 (=OffSET(D2,1,-2)), which is FormulaAsText. cells D3:D4 show the contents of themselves. This adds some flexibility. YMMV.
PS1: The essence was taken from
http://www.mrexcel.com/forum/excel-questions/20611-info-only-get-cell-arguments.html
PS2: Tim Williams mentioned in a comment "the old XLM GET.FORMULA()". This answer is possibly related (not the same, since this one uses GET.CELL()).
PS3: A simple VBA solution is given, e.g., in
http://dmcritchie.mvps.org/excel/formula.htm
EDIT: Complementing this nice answer, the worksheet function FormulaText is available for Excel 2013 and later.
This suggestion may be helpful for those who after retrieving a block of formulas and transporting them to a new spreadsheet want to put them to work again. Excels FORMULATEXT function is great for picking up formulas but it leaves them as unusable text strings. If you want to get them back as fully functioning formulas you have to edit each one individually to remove the string character, but here is a shortcut for larger blocks.
Get to the position where you have the required formulas as text (in other words after using FORMULATEXT - you have done a copy and (value only) paste). The next step involves highlighting all the cells you want to convert and then navigating to the [Text-To-Columns] menu option ({Data} bar on Excel 2016). You can select 'Delimited' but on the next screen just make sure you de-select any marks that do appear in your formulas. Then 'Finish'. Excel should automatically analyse the cells as containing formulas and you should now have them working again.
There is a way to do this. In my example I had a table that showed a date. The date comes from Sheet!G91. In my table I also had a column that showed the sheet name. I added two more columns to my table. The first column had column(Sheet!g91), which returns the number 7, because G is the seventh letter in the alphabet. I then converted the number to a letter (G) using another table in my workbook. In the second column that I added, I made a formula row(Sheet!G91), which returns the number 91. Note: Row and Column may appear as volatile formulas, which recalculate with every calculation of the workbook.
I wanted another column to show the formula contents of the date cell mentioned at the beginning of this post. I included the following string function (you can also use CONCATENATE).
"=" & AJ9 & "!" & AM9 & AN9
The items separated by ampersands get strung together (that is, concatenated). AJ9 in my example contains the sheet name, AM9 contains the column letter, and AN9 contains the row number.
I now have a column that dynamically updates its contents to reflect the sheet name and cell reference. The results in my workbook cell are
=Sheet!G91.
You can't. This is most likely a design choice to eliminate an average Excel user from accidentally getting something they did not want.
What you are reading is correct - writing a UDF is the solution you want.