Cell shows #NAME? after VBA inputs formula - vba

Cells(intRow, 2 + j).Formula = "=SUM(C" & intRow & ":" & colName & intRow & ")"
This is the code I am using to put a basic SUM-functionality into the cells at the end of certain rows. Upon entering this formula in the cell, the cell shows "#NAME?". If i click into the formula and then press "Enter", the formula works as intended (the formula input is also correct).
Is there a way to make VBA update these cells automatically, so the formula works as soon as it's entered into the cell by VBA?
Edit: Example values for the variables are:
intRow = 5
j = 7 (Column G)
colName = H (refers to j + 1)
So the finished formula in cell K5 would be:
=SUM(C5:J5)

Solved: Using
.FormulaR1C1
does not cause the same error.
Cells(intRow, 2 + j).FormulaR1C1 = "=SUM(RC[" & -(j - 1) & "]:RC[" &
(-1) & "])"

I just had the same problem, for a different reason, but I think it may help someone else :
It was due to a problem of localization (language)
I'm a French user and I was trying the following code :
For Each cel In selectedRange.Cells
cel.FormulaR1C1 = "=SI(R[0]C[-1]=1,1,0)"
Next cel
Where SI corresponds to the formula IF in English.
The problem is that FormulaR1C1 accept only English Formula: so to fix it I had to use :
For Each cel In selectedRange.Cells
cel.FormulaR1C1 = "=IF(R[0]C[-1]=1,1,0)"
Next cel
Otherwise I can also use my French formula thanks to FormulaR1C1Local such as :
For Each cel In selectedRange.Cells
cel.FormulaR1C1Local = "=SI(L(0)C(1)=1;1;0)"
Next cel
(note that L/C are for french words : Ligne/Colonne, that I needed to use the separator ; , that brackets are replaced by parenthesis in the Excel's French world ..)

Related

How can I insert a dynamic last row into a formula?

I'm working with a clean sheet where I paste one column of dates with a varying number of rows. My goal is to show how many times each date shows up. However, every time I get to the last line I keep getting Run-time error '1004' Application-defined or object-defined error.
Here is my code:
Dim lastrow As Long
Set ws = ActiveSheet
Set startcell = Range("A1")
lastrow = ws.Cells(Rows.Count, "A").End(xlUp).Row
Range("B2").Formula = "=countif(A1:" & lastrow & ")"
Thanks in advance!!
COUNTIF function takes 2 arguments (https://support.microsoft.com/en-us/office/countif-function-e0de10c6-f885-4e71-abb4-1f464816df34), not one as in your code. Also missed column letter in range. If you want to process N dates, you have to make N formulas COUNTIF.
Try this code (dates in column A from A1, formulas in column B):
Sub times()
With ActiveSheet
Intersect(.Columns(1), .UsedRange).Offset(0, 1).FormulaR1C1 = "=COUNTIF(C[-1],RC[-1])"
End With
End Sub
Result:
SOLVED! 4 WAYS
High-level
Countif formula is incorrect (missing: col label A + condition)
Outlook: quick to fix, but requires loop for all dates
Current method may be CPU/time-intensive for large lists
Solutions A-D:
See Below (Links section), for google sheets (with full macro code, descriptions) for 4 solutions (3 macro based + 1 macro-free albeit dynamic soln). Briefly:
A: output with correction to your code
B: as for A, with for loop deployed
C: VB code for much quicker implementation of for loop/.Function code
D: macro-free variant (proposed/preferred)
Screenshots
Comparison table
Links:
Google Sheet
VBA count and sumifs - Automate Excel
VB code (A-C)
For completeness (same can be found in linked Google Sheet, typed - so macro-free / safe workbook):
Sub Macro_A():
lastrow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row
cell = Range("a4").Address
Range("B4").Value = "=countif(A1:" & "A" & lastrow & "," & cell & ")"
' For i = 1 To lastrow - Range(cell).Row + 1
' Range("B4").Offset(i - 1).Formula = "=countif(A1:" & "A" & lastrow & "," & Range(cell).Offset(i - 1).Address & ")"
' Next
End Sub
Sub Macro_B():
Application.Calculation = xlCalculationManual
start_time = Timer
lastrow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row
cell = Range("a4").Address
' Range("B4").Value = "=countif(A1:" & "A" & lastrow & "," & cell & ")"
For i = 1 To lastrow - Range(cell).Row + 1
Range("c4").Offset(i - 1).Formula = "=countif(A1:" & "A" & lastrow & "," & Range(cell).Offset(i - 1).Address & ")"
Next
Application.Calculation = xlCalculationAutomatic
Range("c3").End(xlDown).Offset(2).Value = Round(Timer - start_time, 2)
End Sub
Sub Macro_C():
start_time = Timer
Set Rng = Range("A4", Range("A4").End(xlDown))
For Each cell In Rng
cell.Offset(0, 3) = WorksheetFunction.CountIf(Rng, cell.Value)
Next
Range("d3").End(xlDown).Offset(2).Value = Round(Timer - start_time, 2)
End Sub
Macro-free soln (D)
Go to Formulas (ribbon), Name Manager:
In Name Manager window that apperas, click 'New...'
Populate dialogue box as req. (modifying Sheet name and $A$4 starting cell as req.)
Test your new dynamic range by clicking on upward arrow in bottom right hand corner (which should select dates in column A as depicted below)
Enter single formula in first cell of output range (here, cell D4)*:
Formulae (for convenience):
range_countif:
=Sheet1!$A$4:OFFSET(Sheet1!$A$4,COUNTA(Sheet1!$A:$A)-2,0,1,1)
Entry in cell D4
=COUNTIF(range_countif,range_countif)
*Notes: requires Office 360 for 'spill effect' (input as array formula with 'ctrl' + 'shift' + 'enter' otherwise).
Let me know if you have any further Qs. Best of luck with your excel Spreadsheet!
So many ways to achieve. I use this formula to get the number of rows
=ArrayFormula(MAX(IF(L2s!A2:A1009<>"",ROW(2:1011))))
Then I build a string from it
="L2s!A2:E"&D3
I love named ranges so I named the cell with the string built DynamicRangeL2s
Here is how I used the dynamic range in my formula (denormalize() is a custom function I wrote but could be any function) using the INDIRECT() function
=denormalize(INDIRECT(DynamicRangeL2s),INDIRECT(DynamicRangeSchedule),2,2,"right")
Here is a great article on Dynamic Ranges
https://www.benlcollins.com/formula-examples/dynamic-named-ranges/

Excel VBA - if/then statement - Identifying cells with a dash

I am trying to write a VBA line where if cell A1 contains a dash anywhere in the cell, then B1 will say "Blue". If there is no dash, then B1 would say "Red".
I have the following code written, but it's not working and I'm not sure if I'm doing the "like" part correctly:
ActiveCell.FormulaR1C1 = _
"=IF(RC[-1]=" - ",""Blue"",""Red"")"
Thank you for any help you can provide! I've done so much searching, but have been unable to find any examples that didn't include specific numbers or text.
You can also use
ActiveCell.FormulaR1C1 = "=IF(ISNUMBER(FIND(""-"",RC[-1])),""Blue"",""Red"")"
Or a one-liner:
ActiveCell.FormulaR1C1 = "=IF(ISERROR(FIND(""-"",RC[-1])),""Red"",""Blue"")"
You could do it with a simple VBA script like this:
Sub Test()
Dim sh1 As Worksheet
Set sh1 = Sheets("Sheet1")
Application.ScreenUpdating = False
For x = 1 To sh1.Cells(rows.Count, "A").End(xlUp).Row
If InStr(1, sh1.Range("A" & x).Value, UCase("-"), 1) > 0 Then sh1.Range("B" & x).Value= "Red"
If InStr(1, sh1.Range("A" & x).Value, UCase("-"), 1) < 0 Then sh1.Range("B" & x).Value = "Blue"
Next x
Application.ScreenUpdating = True
End Sub
I don't believe that put a formula in every "B" column cells it's a good pratice, Excel can take a long time to calculate.
Try this:
Sub Example()
mySheet.Cells(1, "B").Value = IIf(Not InStr(1, mySheet.Cells(1, "A"), Chr(45), vbTextCompare) = 0, "Blue", "Red")
End Sub
You can loop through every cell you want to put that condition using this code.
Functions:
IIf is equals to Excel Worksheet Function "IF".
InStr search a string in another string, you can pass a unique char as criterea. I used chr(45) because it returns a char according to the passed code, 45 references to Dash code.
The error, corrected (but not pointed out) in several of the other answers lies in changing your formula from
" - "
to
"" - ""
i.e. going from single double-quotes around your - to double double-quotes. The single quote is ending your string - you can even see that the - shows up in black text in your question instead of red text, therefore, it's not part of the string being inserted into ActiveCell.FormulaR1C1.

VBA Excel Format Range when value is found

I'm trying to implement a macro that looks for the words "TRUE" and "FALSE" in a huge array of data - and then, when found, changes the color of the cells above it.
Specifically, I would like it to color not the TRUE/FALSE-cell, but the 30 cells directly above it. This is where things get tricky... I hope someone can help.
I've tried adapting the below code, but mostly I'm adding it as inspiration at this point.
Sub ChangeColor()
lRow = Range("C" & Rows.Count).End(xlUp).Row
Set MR = Range("C2:C" & lRow)
For Each cell In MR
Select Case cell.Value
Case "Yes"
cell_colour = 4
Case "y"
cell_colour = 4
Case Else
cell_colour = 3
End Select
cell.Interior.ColorIndex = cell_colour
Next
End Sub
Using a datafield array
Looping through a range is always time consuming; this should speed it up.
Caveat: Formatting single cells can maximize file size, so at least I reformat the whole column C to xlColorIndexNone.
Option Explicit
Public Sub Mark30CellsAbove()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("MySheet")
Dim v As Variant
Dim i As Long, j As Long, n As Long, m As Long, r As Long
Dim Rng As Range
Dim t As Double
' stop watch
t = Timer
' get last row in column C
n = ws.Range("C" & ws.Rows.Count).End(xlUp).Row
' get values to one based 2dim array
v = ws.Range("C1:C" & n).Value
' clear existing colors over the WHOLE column to minimize file size
ws.Range("C:C").Interior.ColorIndex = xlColorIndexNone
' loop through C2:Cn and mark 30 rows before found condition
For i = 2 To n
' check condition, find string "true" or "false"
If InStr(".true.false.", "." & LCase(v(i, 1)) & ".") > 0 Then
' set range block - fixed rows count 30 above found cell
If i < 32 Then ' only in case of less than 30 rows
Set rng = ws.Range("C2:C" & (i - 1))
Else
Set rng = ws.Range("C" & (i - 30) & ":C" & (i - 1))
End If
rng.Interior.ColorIndex = 4
End If
Next i
MsgBox "Time needed: " & Format(Timer - t, "0.00") & " seconds."
End Sub
Of course you could also loop within If - EndIf, just to see this slower method:
If InStr(".true.false.", "." & LCase(v(i, 1)) & ".") > 0 Then
' Always avoid to loop through a range
' For j = i - 1 To i - 30 Step -1
' If j < 2 Then Exit For ' optional escape if one line under title row
' ws.Cells(j, 3).Interior.ColorIndex = 4
' Next
End If
The code that I posted should only highlight cells in column B whose value is different from the corresponding cell in column A. I tested it and it worked OK.
If you want to try conditional formatting:
Select column B, or the part of column B that you want to colour conditionally.
In the following, I will assume that B1 is the active cell within the selection.
On the Home tab of the ribbon, click Conditional Formatting > New Rule...
Select "Use a formula to determine which cells to format".
Enter the formula =B1<>A1
If the active cell is not in row 1, adjust the formula accordingly. For example, if the active cell within the selection is B3, use =B3<>A3
Click Format...
Activate the Fill tab.
Select the desired fill colour.
Click OK until all dialogs have closed.
Change some values in column A and/or B to see the result.
Refer - https://social.technet.microsoft.com/Forums/ie/en-US/2fffa4d8-bbba-473b-9346-5fce8f0728a8/using-vba-to-change-a-cell-colour-based-on-the-information-in-a-different-cell-excel-2010?forum=excel
First you need to check whether the row of the cell is higher than 30 and then it you can offset to change the color:
Thus instead of this line: cell.Interior.ColorIndex = cell_colour
write this:
If cell.Row > 30 Then cell.Offset(-30, 0).Interior.ColorIndex = cell_colour
This may be done without VBA. You should set up two conditional formatting with formulas. First:
=COUNTIF(OFFSET(INDIRECT(ADDRESS(ROW(), COLUMN())),1,0,29,1), "TRUE")>0
and the same for false. To highlight the cell you just need to use Highlight Cell Rules (the top option for CF).
I would do this with conditional formatting
Mark all your data and press "Conditional Formatting". Enter 2 rules with Use a formula...
First rule is for TRUE. Assuming that you start with Col A:
=COUNTIF(A2:A31;TRUE)
The second rule is similar, just exchange TRUE by FALSE. Below the formula, press the "Format" button to set the color.
Explanation:
I reverted the logic: Instead of searching for TRUE/FALSE and then format the cells above, I look for every cell if it has at least one entry TRUE resp. FALSE in the next 30 cells. However, I have to admit I don't know how fast Excel can handle such a large amount of data.

Formatting a Formula in a String VBA

I have a script that needs to place a formula into a cell but I'm getting a 1004 error from the first part I am sure I formatted something wrong. I had difficulty with the " marks in the string but got those worked out so I'm figuring I'm missing something else. The cells are also unprotected.
Worksheets(CurSheet + 1).Range("D" & Y).Value = "=IF(D52=1,0,IF(C52=" & """Saturday""" & ",0,'" & CurSheet & "!C" & Y & "))"
This is the section that gives the error. If it is removed code works.
"=IF(D52=1,0,IF(C52="
I am not sure what I am doing wrong with this part.
It looks like you're using CurSheet as a sheet index number and as a sheet name.
The index number just returns the relative position of the sheet in the workbook while the name is what you see on the sheet tab (there's also the CodeName but I won't go into that here).
Although I don't fully understand what you're after this code will place a formula on the sheet identified with the sheet index number, so if CurSheet= 1(+1) it will place the formula on the second sheet.
The formula itself will reference the name of the sheet that is before the sheet that the formula appears on (so if the formula is on the second sheet, the formula will reference the first sheet).
Sub Test()
Dim Y As Long
Dim CurSheet As Long
Y = 1
CurSheet = 1
Worksheets(CurSheet + 1).Range("D" & Y).Formula = _
"=IF(D52=1,0,IF(C52=" & """Saturday""" & ",0,'" & Worksheets(CurSheet).Name & "'!C" & Y & "))"
End Sub
Hope I made that clear enough. :)
You need to declare that you are inputting a formula, not a value:
Change:
Worksheets(CurSheet + 1).Range("D" & Y).Value
To:
Worksheets(CurSheet + 1).Range("D" & Y).Formula

Excel VBA range select

I have a macro in which I need to select the range R2:last row in sheet. However the last row in my sheet might be blank in column R. At the moment I am using this
Dim t As Range
Set t = Range("R2", Range("R1000").End(xlUp))
For Each Cell In t
If IsEmpty(Cell) Then
Cell.Activate
ActiveCell.Value = "To Be Picked Up"
End If
Next
However if the last row has a blank in column R then it gets ignored. I am hoping to pull the range using column A, as the last row of data always has column A. So something like,
Dim t As Range
Set t = Range("R2", Range("A1000").End(xlUp).ActiveCell.Offset(0, 17))
For Each Cell In t
If IsEmpty(Cell) Then
Cell.Activate
ActiveCell.Value = "To Be Picked Up"
End If
Next
It seems so simple but I'm sure im missing something stupid. Any help or alternative methods would be helpful thank you.
This should do the trick in one line:
Sub SO()
Range("R2:R" & Range("A" & Rows.Count).End(xlUp).Row).SpecialCells(xlCellTypeBlanks).Value = "To Be Picked Up"
End Sub
But in answer to your question specifically
Set t = Range("R2:R" & Range("A" & Rows.Count).End(xlUp).Row)
The Range() method will accept a string as an argument to obtain a range.So we can build this string any way we want:
"A1000" '// A1000
"A" & 1000 '// A1000
"A" & "10" & "00" '// A1000
"A" & CStr(1001 - 1) '// A1000
"A" & Rows.Count will return A65536 or A1048576 depending on the type of worksheet.
Range("A1048576").End(xlUp) as you know, will retrieve the last cell in that area, or the first cell in the next area on the direction specified.
Range("A1048576").End(xlUp).Row will return the row number of that cell (let's say it's A1000 for argument's sake) so the return value is 1000.
"R2:R" & Range("A" & Rows.Count).End(xlUp).Row therefore makes the string R2:R1000.
So finally, Range("R2:R" & Range("A" & Rows.Count).End(xlUp).Row) is the same as Range("R2:R1000")