Translate a worksheet formula in VBA - excel

Can somebody help me to write this formula in excel VBA?
=IF(ISERROR(VLOOKUP(A3,Temp!$A$3:$A$595,1,FALSE)),A3,"0")
My code is getting stuck with :"syntax error"
Sub checkDuplitems()
Application.ScreenUpdating = False
Const top As Integer = 3
Dim bottom As Long
bottom = Sheets("Temp").Cells(Rows.Count, top).End(xlUp).row
With ThisWorkbook.Sheets("trash").Range("A" & top & ":A" & bottom)
.Formula = "=IF(ISERROR(VLOOKUP(A" & top & ",Temp!$B$" & top & ":$B$" & bottom & _
",1,FALSE)),A" & top & ", & '" 0" & ," '")"
.Value = .Value
.SortSpecial
End With
'Call something...
End Sub

You have a concatenation problem in the second line of the .Formula line.
To emulate the formula you have at the top of your question (which is wrong incidentally because you should be pointing to $B$3:$B$595 or something like that because your look up cell A3 should not be inside the VLOOKUP range).
Try this new .Formula line:-
.Formula = "=IF(ISERROR(VLOOKUP(A" & top & ",Temp!$B$" & top & ":$B$" & bottom & _
",1,FALSE)),A" & top & ", " & "0)"

Are you sure you want to use top as both the starting row in column A and the column to get the bottom row from the Temp worksheet? The important column on the Temp worksheet is column B (i.e. 2) not C (i.e. 3).
If you are putting formula(s) into Trash!A3:A595 that reference Trash!A3:A595 then these are circular references and cannot be resolved under normal conditions. I'll put the formulas into column Z.
If you are operating with Excel 2007 or newer then I would humbly propose this alternate that uses the worksheet's IFERROR function and does not attempt to make text out of the 0 returned value.
Const top As Integer = 3
Dim bottom As Long
bottom = Sheets("Temp").Cells(Rows.Count, "B").End(xlUp).Row '<~~change here
With ThisWorkbook.Sheets("trash")
With .Range("Z" & top, .Cells(Rows.Count, "A").End(xlUp).Offset(0, 25))
.Formula = "=IFERROR(VLOOKUP(A" & top & ", Temp!$B$" & top & ":$B$" & bottom & _
", 1, FALSE), 0)" '<~~ big change here
.Value = .Value
End With
End With
It is also curious as to why the number of rows of formulas in the Trash worksheet must be governed by the number of rows of data in the Temp worksheet. I would have thought that the number of values in column A of the Trash sheet should govern how many formulas go into the Trash worksheet.

Related

Compute countif in column Range & combine if with count if

I have two formulas that I need to transfer to VBA.
On Excel, my formula would be =countif(A$2:A2,A2) so I transferred that using this formula but everything is returning to 1. The rows didn't become dynamic and I want only the values to be displayed.
For a = 2 To lrow
ws.Range("T" & a).Formula = "=CountIf(A$2&"":""&A2)"",""&A2)"
Next a
Next formula that I use in Excel is
=IF(COUNTIF(A:A,A2)>Q2,"Check","Ok")
I tried this formula in VBA:
For i = 2 to lrow
If Countif(ws.Range("A2:A" & lrow), "A2") > ws.Range("Q2:Q", & lrow) Then
ws.Range("T" & i).Value = "Check"
Else
ws.Range("T" & i).Value = "Ok"
End If
Next i
You could populate column T with your first formula with this line of code:
ws.Range("T2:T" & lrow).FormulaR1C1 = "=COUNTIF(R2C[-19]:RC[-19],RC[-19])"
I can't advise on your second formula unless you clarify where you want to write it...

Adding a new row of data after the last

I have a list of data on my Excel file. I want to add new elements to this list by using a userform.
The code below should add the data on column B, one after the data on the last row.
The problem is each time I add a new data, my code deletes the old data.
So if I have data on column B line 3, it deletes what is in line 3 (the last row) and adds what I've just entered in that line.
Private Sub CommandButton1_Click()
Dim ws_liste As Worksheet
Dim fin_liste As Integer
Set ws_liste = ActiveWorkbook.Worksheets("Liste_Lame_" & Me.ComboBox_Modele.Value)
fin_liste = ws_liste.Range("A" & Rows.Column).End(xlUp).Row
'fin_liste = ws_liste.Range("A65533").End(xlUp).Row
ws_liste.Cells(fin_liste + 1, 2) = Me.ComboBox_Num.Value & "-" & Me.TextBox_Mois.Value & "-" & Me.TextBox_Annee.Value & "-" & Me.ComboBox_Modele.Value & "-" & Me.ComboBox_Const.Value
Unload Me
End Sub
I don't understand why you use this code
fin_liste = ws_liste.Range("A" & Rows.Column).End(xlUp).Row
It always give you value "1" and never change, that's why the new data will delete the old one.
I'll give you two solutions, choose what you want.
First, take one cell to save a value from fin_liste as integer (for example I choose cell "D1"). Then add "i" for a new variable as integer.
Here the code.
Private Sub CommandButton1_Click()
Dim ws_liste As Worksheet
Dim fin_liste, i As Integer
Set ws_liste = ActiveWorkbook.Worksheets("Liste_Lame_" & Me.ComboBox_Modele.Value)
fin_liste = ws_liste.Range("A" & Rows.Column).End(xlUp).Row
i = Range("D1").Value + fin_liste
'fin_liste = ws_liste.Range("A65533").End(xlUp).Row
ws_liste.Cells(i + 1, 2) = Me.ComboBox_Num.Value & "-" & Me.TextBox_Mois.Value & "-" & Me.TextBox_Annee.Value & "-" & Me.ComboBox_Modele.Value & "-" & Me.ComboBox_Const.Value
Range("D1").Value = i
Unload Me
End Sub
But there's a risk, if value in "D1" has changed, it make your data in a mess.
Second option.
Private Sub CommandButton1_Click()
Dim fin_liste As Range
Set fin_liste = ThisWorkbook.Worksheets("Liste_Lame_" & Me.ComboBox_Modele.Value).Cells(Rows.Count, "B").End(xlUp).Offset(1, 0)
'fin_liste = ws_liste.Range("A65533").End(xlUp).Row
fin_liste = Me.ComboBox_Num.Value & "-" & Me.TextBox_Mois.Value & "-" & Me.TextBox_Annee.Value & "-" & Me.ComboBox_Modele.Value & "-" & Me.ComboBox_Const.Value
Unload Me
End Sub
ws_liste.Range("A" & Rows.Column).End(xlUp).Row will evaluate to the first row in the range due to the xlUp parameter.
Since you are adding one to the row index in the following line (ws_liste.Cells(fin_liste + 1, 2)), I am assuming you are trying to refer to the last row of the range. You can achieve this by using xlDown instead of xlUp.
fin_liste = ws_liste.Range("A1").End(xlDown).Row
Edit: As SJR noted, If there is no data in column A, using xlDown on A1 will not find the last row of the data, but instead the next non-blank cell in column A. Instead using xlDown on the column that contains the last row of data would be correct.

Excel VBA For Loop writing Formula in cells depending on the number in the loop

I am trying to write a Forumla in cells (from cell A2 to AI, where I is the number in the For Loop).
The formula to be written must correspond to Cell M2 to MI, also where I is the number in the For Loop.
I am able to write the sheet-reference by itself:
ws.Cells(1 + I, KolonneForX + 1).Formula = " ='" & ws.Name & "'"
which gives me the formula ='Ark1' (by it self) in the cells i want.
And also the right name of cell to read:
ws.Cells(1 + I, KolonneForX + 2).Formula = "=CONCATENATE(""M"",TEXT(" & I & "+1,""0""))"
which gives me the formula MI (by it self, with the corresponing number for I) in the cells i want.
But when I try to put the two of them togheter, I can't get it to run and refer to the right cells.
This is the code I have been trying to run:
Sub OppretteKnutepunkt()
Dim ws As Worksheet
Set ws = Worksheets("Ark1")
Dim KolonneForX As Integer
For I = 1 To 5
ws.Cells(1 + I, KolonneForX + 2).Formula = "='" & ws.Name & "'!CONCATENATE(""M"",TEXT(" & I & "+1,""0""))"
Next I
End Sub
I want the Cell A2 to have the following formula:
='Ark1'!M2
I want the Cell A3 to have the following formula:
='Ark1'!M3
and so on.
Any suggestions?
You can achieve this without looping
Dim I as Long
I = 7
With ws.Range("A2:A" & I)
.Formula = "='" & .Parent.Name & "'!M2"
End With
With is a shorthand way of using the same prefix on a block of code. The VBA compiler prefixes everything that begins with a . with whatever is declared by the With block
The equivalent of the above would be:
ws.Range("A2:A" & I).Formula = "='" & ws.Range("A2:A" & I).Parent.Name & "'!M2"

Worksheet Function Countifs for resizable range

I have a table in which I count the records through Worksheet.Function.Countif.
It is nice because it counts the rows using .Rows.Count and so I am alwasy ensured if my table changes the size.
It looks like that (subset of the code):
endrow = .Cells(.Rows.Count, 20).End(xlUp).Row
ws1.Cells(6, 34).Formula = "=COUNTIF(" & .Range("U6:U" & endrow).Address & ",U6)"
I wish to write the the worksheet.function formula in the same way as above but for 'Countifs'. In excel, I would type it like that:
=COUNTIFS($U$6:$U$144;U6;$T$6:$T$144$;"<>"&T6)
How to write it in vba, using 'endrow' as in the first demonstarted code, i.e. without '144' as the last row but with '& endrow' ?
I was trying multiple times, but I cannot get it to work :/
I will appreciate any help.
Try this:
ws1.Cells(6, 34).Formula = "=COUNTIFS($U$6:$U$" & endrow & ",U6,$T$6:$T$" & endrow & "," & """" & "<>" & """" & "&T6" & ")"
This formula gets the last row of column A:
=IFERROR(LOOKUP(2,1/(NOT(ISBLANK(A:A))),ROW(A:A)),0)

Concatenating SumIfs in VBA

I'm trying to get this segment of code to execute. This is a simplified version of the code. I've included the relevant code. I'm trying to concatenate strings and named ranges into a SumIfs formula, but I get error 1004 "Application-defined or Object-defined error." I have a working line of code above this problem section that is similar with the exception of doing a sum function, instead of sumif. Any idea how to get this code to execute? Thank you.
Dim wb As Workbook
Dim ara As Worksheet
Dim inv As Worksheet
Dim ARBlock As Range
Dim Invoices As Range
Dim AgedDays As Range
Set wb = ThisWorkbook
Set ara = wb.Sheets("AR Aging")
Set inv = wb.Sheets("Invoices")
Set ARBlock = ara.Range("a6")
Set Invoices = inv.Range("a6", inv.Range("a6").End(xlDown))
Set AgedDays = Invoices.Offset(0, 6)
'Populate A/R age buckets
For i = 6 To ARBlock.Rows.Count + 6
With ARBlock(i - 5, 1).Offset(0, 3)
.Value = "=SumIfs(" & Invoices.Offset(0, 4).Address & "," & _
Invoices.Address & "," & ARBlock(i - 5, 1).Value & "," & _
Invoices.Offset(0, 6).Address & ","" <= "" & &O30)"
End With
Next i
End Sub
The line beginning with ".value" is where I'm getting the error message. P.S.: I need the cell to contain the concatenated formula, as opposed to the output value.
UPDATE 1:
As some suggested I updated the .value line to:
.Offset(0, 3).Formula = "=SumIfs(Invoices.Offset(0, 4).Address,Invoices.Address,ARBlock.cells(i - 5, 1).Value)"
I'm still getting the same error. Some auditing I've done:
Removing the "=" before "Sumifs" allows the code to run fine; pasting in the formula into the target cell as text. In this form, my output for i=1 goes to ARBlock.cells(1,1), as it should.
I also used Debug.Print to view all of the components of the formula:
Debug.Print ARBlock.Cells(i - 5, 1).Address
'output $A$6
Debug.Print ARBlock.Cells(i - 5, 1).Value
' output International Business Machines
Debug.Print Invoices.Offset(0, 4).Address
'output $E$6:$E$255
Debug.Print Invoices.Address
'output $A$6:$A$255
I suspected the issue might be that the range dimensions might have been off, but this is not the case. My next suspicion is that the output International Business Machines needs to be in " " for the formula to read it correctly. I hardcoded in
""International Business Machines""
to see if this would fix the formula, but I keep getting the same error once I add the "=" back in. The formula syntax is correct, the dimensions are the same between the sum range and criteria range. Anyone else have any ideas?
.Offset(0, 3).Formula = "=SumIfs(Invoices.Offset(0, 4).Address,Invoices.Address,ARBlock.cells(i - 5, 1).Value)"
Change to:
.Offset(0, 3).Formula = "=SumIfs(" & Invoices.Offset(0, 4).Address & ", " & Invoices.Address & ", " & chr(34) & ARBlock.Cells(i - 5, 1).Value & chr(34) & ")"
EDIT: Added quotes chr(34) around your string!
Your ARBlock(i - 5, 1).Value most likely is an empty cell, which messes the SUMIFS formula as it builds it with to consecutive commas

Resources