How to fix #NAME? error with formula or vba - vba

i am using an excel formula to reference, and adjust when necessary, a very long list of scraped values. my problem is that occasionally the values start with "=+" causing them to be seen as a formula, and thus producing a #NAME? error. whenever my formula references these cells, it too produces said error.
is there anyway to account for #NAME errors within my formula? something like ISNA but for #NAME errors?
if that is not possible, could i use VBA to delete "=+" from any cells that contain it?
any help would be greatly appreciated, ive been looking for an answer to this for hours.

The easiest way is to add a ' in front of each cell's formula.
Imagining you have your scraped values in the range C1:C10, you can fix it like this:
For j = 1 To 10
Range("C" & j).Value = "'" & Range("C" & j).Formula
Next j
By doing so, you preserve the original value of your scraped object.
Of course you can fix the issue at the source, i.e. imagining you print your values like this:
rng.Value = myScrapedValue
... you can replace it like this:
rng.Value = quoteFirst(myScrapedValue)
... where
Private Function quoteFirst(ByVal strng As String) As String
quoteFirst = "'" & strng
End Function

I think you could use an =IFERROR() in your formulas directly, that would save time of developping a VBA code dedicated to this specific error.

Can you not use something like...
=ERROR.TYPE(A1) =5
This should produce a TRUE-FALSE in the formula....

If you want to delete the "=+" you can use something like this :
Dim index As Integer
For index = 1 To 10
If (Mid(Cells(index, 1), 1, 2) = "=+") Then
Cells(index, 1) = Mid(Cells(index, 1), 3)
End If
Next
It will replace the content of the cells beginning by "+=" by the same content without "+=".

Related

Writing a formula with concatenated parts into a cell

Scenario: I have a code that should write a formula to a worksheet cells. This formula is for an API to retrieve some value. My formula is inside a loop (this is done for multiple columns) and references the first row for an identifier.
The original formula:
=FS(B1;"FI(DATE,,DATE)")
The modified formula with the floating reference (inside the loop):
For i = 1 To lColumn
If wb.Worksheets("Dates").Cells(i, 1).Value <> "" Then
wb.Worksheets("Dates").Cells(i,2).value = "=FS(" & i & "1;"FI(DATE,,DATE)")"
End If
Next i
Where lColumn is some pre-defined number.
Issue: I keep getting the "Unexpected end of statement" error in the formula part of the loop.
What I already tried: I tried different variations, repositioning the "s and 's, for example:
wb.Worksheets("Dates").Cells(i,2).value = "'"=FS(" & i & "1;"FI(DATE,,DATE)")""
or
wb.Worksheets("Dates").Cells(i,2).value = "'=FS(" & i & "1;"FI(DATE,,DATE)")"
or
wb.Worksheets("Dates").Cells(i,2).value = "'""=FS(" & i & "1;"FI(DATE,,DATE)")"
and so on. But the error still persists.
Question: What is the proper way to do this operation?
Working with formulas in VBA is a little bit tricky:
To write a formula, use the range.formula property, not the .value.
You have to write the formula as if you are using an english Excel. Parameter-separator is comma (not semicolon).
If a formula needs a quote, double it so that the VBA compiler understands that you want a quote within a string.
I find it helpfull to write a formula into a variable before assigning it - you can check in the debugger if it is exactly how it should before assigning it.
To check how the formula should look like, write it into a cell, change to the VBA-editor, open the immediate window and write ? activecell.formula
Try (untested as the formula you need is not valid to us):
with wb.Worksheets("Dates")
dim f as string, adr as string
adr = cells(i, 1).address(false, false) ' get rid of Dollar signs
f = "=FS(" & adr & ",""FI(DATE,,DATE)"")"
.Cells(i, 2).formula = f
end with
wb.Worksheets("Dates").Cells(i,2).formula = "=FS(" & Cells(1, i).Address(0,0) & ";""FI(DATE,,DATE)"")"
There may be a better way to convert the column number to a letter (which is the problem you are having, along with the double quotes)!

adding a for loop or if statement to excel for averaging numbers

So I have a template that I am inputting data from a csv into an excel file. The data doesn't always "file the template" so to speak or there are some fields that have '0' in them. What I am trying to do is add a for loop or something of the sort to basically 'throw out' the 0's but still average the cells say BX2-BX50. I would like excel to ignore the 0's when averaging the numbers within those fields.
Any help would be greatly appreciated!
No need to over-think this. The AVERAGEIFS function should be more than sufficient.
=averageifs(BX:BX, BX:BX, "<>0")
all,
so you mean the line with "0" is not the data, is only the error line when you convert it from CSV to Excel? If so, it is better to delete those lines as you know if the 0 shows as the correct data, it should reduce the overall average. you can eliminate the error data but you cannot ignore the real to lead to wrong result.
and for delete error zero line, you can use loop:
Sub removeZero()
Dim a As Integer
a = ActiveSheet.UsedRange.Rows.Count
For i = 1 To a
If Range("B" & i) = 0 Then
Range("B" & i) = ""
End If
Next i
Columns("B:B").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub

Defining a group of cell names using vba

I have a question, I am trying to define a cell name in excel using vba. Now to select one cell only i have been using the following code which proves to work fine:
Range("A1").Name = "zm_1"
However I need to name a number of cells in a column i.e:
Range("A1").Name = "zm_1"
Range("A2").Name = "zm_2"
Range("A3").Name = "zm_3"
Range("A4").Name = "zm_4"
Since this is quite tedious for 100 cells, i have been trying to use an array:
For i=1 to 100
Range("A(i)").Name = "zm_(i)"
next
^ this however gives an error which i have been unable to track. Any ideas/suggestions on how can it be done? Thanks!
The problem is with Range("A(i)").Name = "zm_(i)" The " indicate that something is text, so you should place your (i) out of the ".
For the first part it is quiet easy, as you can also use the row and column way of describing the cell. Therefore that becomes
Range(Cells(i,1)).Name
For the second part you need to concatenate the text and the numbers. That becomes: "zm_" & i
You don't need an array, just your loop:
For i = 1 to 100
Range("A" & i).Name = "zm_" & i
next
Try the below code and hope it helps you:
For i = 1 To 100
ThisWorkbook.Sheets(1).Range("A" & i).Name = "zm_" & i
Next
Where Sheet(1) refers to Sheet1 of the current workbook.

Convert Excel array formula VBA

I'm trying to do "vlookup" with 2 different criteria(Column A and G values) using "Index" and "Match" functions.
and here is the line i used for the Excel command.
=INDEX(Database!A:KG,MATCH(1,(Database!A:A='TempSheet'!A2)*(Database!G:G='TempSheet'!G2),0),10)
How would I do it with VBA? It's keep giving me the error message "Compile error: Expected end of statement".
Selection= _
"=Index(DB.Range("A:KG"), Match(1, (DB.Range("A" = Temp.Range("A" & i).Value)) * (DB.Range("G" = Temp.Range("G" & i).Value)), 0), 10)"
Thanks
Every time you use a spreadsheet formula inside a VBA code, you need to precede it with <Excel.WorksheetFunction.> or <Application.WorksheetFunction.>.
For example:
Application.WorksheetFunction.Match
instead of Match only.
I have had little luck getting array formulas to work correctly via VBA, and use the 'IFERROR' as a workaround like so:
=IFERROR(VLOOKUP(A1, Database!A:Z,1,FALSE),VLOOKUP(B1, Database!A:Z,1,FALSE))
This function will attempt to match A1, and in case of a #VALUE error, it will match B1.
To get this kind of formula populated on a sheet in VBA, you can loop down your sheet using the '.formula' approach.
' get length of source data
Dim RowCount As Long
RowCount = ThisWorkbook.Sheets("Database").Cells(Rows.Count, 1).End(xlUp).Row
' now starting from row 2 to preserve headings
For i = 2 To RowCount
ThisWorkbook.Sheets("Summary").Cells(i, 1).Formula = "=IF(ISERROR(SEARCH(""ISO"",V" & i & ")),""Order type not supported"",""Transit"")"
ThisWorkbook.Sheets("Summary").Cells(i, 6).Formula = "=IFERROR(TEXT(VLOOKUP(B" & i & ",Database!A:N,7,FALSE),""dd-mmm-yyyy HH:MM AM/PM""),"""")"
Next
Not exactly what you were after, but hope it helps!

UsedRange.Count counting wrong

Summary: I'm taking a row of data from one sheet and pasting it into another, however the sheet would be a daily use kind of thing where new data is just entered below old data.
Problem: On each new run, 7 is consistently added to the UsedRange.Count. For example: on one run the UsedRange.Count will be 7; the next time I run through the function the count will be 14.
What I'm Looking For: Why is this the case and is there a way to help UsedRange be more accurate
-I've included the entire Function for references' sake.
Function eftGrabber()
Dim usedRows As Integer
Dim i As Integer
ChDir "\\..."
Workbooks.Open Filename:= _
"\\...\eftGrabber.xlsm"
usedRows = Sheets("EFT").UsedRange.Count
Windows("Data").Activate
Sheets("DataSheet").Range("A11").EntireRow.Copy
Windows("eftGrabber").Activate
Sheets("EFT").Range("A" & usedRows + 1).Select
ActiveSheet.Paste
i = usedRows
Do 'THIS LOOP DELETES BLANKS AFTER POSTING NEW LINES
Range("A" & i).Select
If Range("A" & i) = "" Then
ActiveCell.EntireRow.Delete
End If
i = i - 1
Loop Until i = 1
Windows("eftGrabber").Activate
ActiveWorkbook.Save
Windows("eftGrabber").Close
End Function
Let me know if I've left out any important details. Thanks in advance!
Change: usedRows = Sheets("EFT").UsedRange.Count
To: usedRows = Sheets("EFT").Range("A" & Sheets("EFT").Rows.Count).End(xlUp).Row
Where "A" can be changed to whichever row you wish to count the total number of columns.
There is a danger in using UsedRange because it factors in such things and formatted cells with no data and other things that can give you unexpected results, like if you are expecting your data to start in Range("A1"), but it really starts in another range!
I will say, however, that If you really wish to use UsedRange, your code above is still wrong to get the rows. Use this instead UsedRange.Rows.Count or to get the last absolute cell of the UsedRange, use UsedRange.SpecialCells(xlCellTypeLastCell).Row
This two line do the magic
usedCol = ThisWorkbook.ActiveSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Column
usedRow = ThisWorkbook.ActiveSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row
For more info visit Microsoft's site
http://msdn.microsoft.com/en-us/library/office/ff196157.aspx
Thanks for the discussion...
.UsedRange.Rows.Count and .UsedRange.Columns.Count work fine provided there is something in cell A1. Otherwise need to use the SpecialCells solution.
Hope this is helpful.
“UsedRange” works if you use it like this >>
x := Sheet.UsedRange.Row + Sheet.UsedRange.Rows.Count - 1;
y := Sheet.UsedRange.Column + Sheet.UsedRange.Columns.Count - 1;
Problem with SpecialCells is that you can't use it on a Protected Sheet.
Assuming you have contiguous sheet (i.e. no blank cells), and you sheet starts in A1, then I have found that
Range("A1").CurrentRegion.Rows.Count
gives the most reliable results.