I'm trying to search for a result based on 2 criteria. "For Each" is much too slow.
This code is much faster. It writes a formula in the cell and then converts it to text. After a few hundred lines, values are still in the cell but they are no longer correct.
I tried manually pasting the =LOOKUP formula. It fetches the correct value, so I assume that it's moving so fast it doesn't have time to find the correct value before it's converted to text.
Sheets("Combined").Select
'put the formula in the first cell
Sheets("Combined").Range(ColumnLetter & "2").Value = "=LOOKUP(2,1/('SheetName'!B:B=Combined!B2)/('SheetName'!A:A=Combined!A2),'SheetName'!C:C)"
'copy the formula all the way down
Sheets("Combined").Range(ColumnLetter & "2").AutoFill Destination:=Range(ColumnLetter & "2:" & ColumnLetter & lastRow)
'convert the result to text
Sheets("Combined").Range(ColumnLetter & "2:" & ColumnLetter & lastRow).Value = Sheets("Combined").Range(ColumnLetter & "2:" & ColumnLetter & lastRow).Value
If you are correct and excel does not have time to complete the search, the following will force a recalculate, and wait until it completes.
Application.Calculate
If Not Application.CalculationState = xlDone Then
DoEvents
End If
You may not need the first line because when you paste it is most likely making excel recalculate anyway.
Jos makes a good point: this will most likely take a long time if you have hundreds of lines.
https://stackoverflow.com/questions/11277034/wait-until-application-calculate-has-finished
I took the suggestions from #BigBen and #Jos Woolley and combined them, this has resolved my issue. The code gets the correct result and still outperforms my 'For Each' code that I was comparing it to. The 'For Each' takes 8.5 minutes to get through the 30k+ lines and this newly modified code gets through the same amount of data in only 2 minutes, albeit without updating a progress bar, but I'll take the shorter time span. Thank you everyone for your help! Here is the updated code:
Sheets("Combined").Select
'put the formula in all cells
Sheets("Combined").Range(ColumnLetter & "$2:" & ColumnLetter & "$" & lastRow).Formula = "=LOOKUP(2,1/('SheetName'!B$2:B$" & lastRow2 & "=Combined!B2)/('SheetName'!A$2:A$" & lastRow2 & "=Combined!A2),'SheetName'!C$2:C$" & lastRow2 & ")"
'convert the result to text
Sheets("Combined").Range(ColumnLetter & "2:" & ColumnLetter & lastRow).Value = Sheets("Combined").Range(ColumnLetter & "2:" & ColumnLetter & lastRow).Value
For comparison, here is the 'For Each' code I was speed testing this code against:
Sheets("Combined").Select
For Each cell In Range(ColumnLetter & "2:" & ColumnLetter & lastRow)
cellNumber = Right(cell.Address, Len(cell.Address) - Len("####"))
MainMenu.numberCompleteLabel.Caption = cellNumber & "/" & lastRow & " complete"
cell.Value = "=LOOKUP(2,1/('SheetName'!B2:B" & lastRow2 & "=Combined!B" & cellNumber & ")/('SheetName'!A2:A" & lastRow2 & "=Combined!A" & cellNumber & "),'SheetName'!C2:C" & lastRow2 & ")"
cell.Value = cell.Value
Next cell
Thank you everyone for your help!
Related
I need to create a formula that is going to concatenate 3 different cells into one date. The formula is going to be a part of a loop function so I need the cell reference to change as the loop function runs.
I am having trouble with the syntax such as the "&" and the """" that are necessary to distinguish parts of the formula from the cell references.
For now I am just trying to get the formula to paste into a single cell without the loop. The 3 cells that I am combining are in columns: N,O & P. I am trying to paste the formula into column M.
I tried creating the formula on a separate "Data" tab and then simply copy and pasting it into each cell using VBA but the row number does not update according to the row that the formula is pasted.
I tried rearranging the & and "" for a while and could not figure out the winning combination.
FormulaRow = Cells(Rows.Count, "M").End(xlUp).Offset(1).Row
M_Formula = "=N" & FormulaRow & "" / "" & "O" & FormulaRow & "" / "" & "P" & FormulaRow
Range("M" & FormulaRow).Value = M_Formula
I am expecting to get the following result: =N5&"/"&O5&"/"&P5 with the row number corresponding to the row that the formula is pasted.
When I tried the copy and paste method I got this message: "Object Doesn't Support this Property or Method"
Any help would be appreciated. Thank you!
Maybe:
Sub sub1()
' If you have 12 in N2 and 34 in O2 and 5678 in P2:
Dim FormulaRow&, M_Formula$
FormulaRow = 2
M_Formula = "=N" & FormulaRow & "&" & """" & "/" & """" & "&" & _
"O" & FormulaRow & "&" & """" & "/" & """" & "&" & _
"P" & FormulaRow
Cells(FormulaRow, ColNum("M")) = M_Formula ' gives the formula you want 12/34/5678
Cells(FormulaRow, 13) = M_Formula ' also gives the formula you want 12/34/5678
End Sub
Function ColNum&(col$)
ColNum = Range(col & 1).Column
End Function
Excel is smart enough to increment the row reference when you do a range in one go:
Range("M5:M" & Range("N" & rows.count).end(xlup).row).formula = "=N5 & ""/"" & O5 & ""/"" & P5"
That will do what you want in 1 line.
Then you can copy the result, paste as values then format to date with something like this:
Sub EnterDate()
Range("M5:M" & Range("N" & Rows.Count).End(xlUp).Row).Formula = "=N5 & ""/"" & O5 & ""/"" & P5"
Range("M5:M" & Range("N" & Rows.Count).End(xlUp).Row).Copy
Range("M5:M" & Range("N" & Rows.Count).End(xlUp).Row).PasteSpecial xlPasteValues
Range("M5:M" & Range("N" & Rows.Count).End(xlUp).Row).NumberFormat = "DD/MM/YYYY"
'Force a reevaluate to make it see actual dates
Range("M5:M" & Range("N" & Rows.Count).End(xlUp).Row).Formula = Range("M5:M" & Range("N" & Rows.Count).End(xlUp).Row).Value
End Sub
Using this method I just tested on over 12,000 rows and it took under a second.
With regards to the comments about using the date function, using the date function is a much better method, I wanted to show you how to do it using your own method but you can get rid of the formatting code if you use Date like so:
Sub EnterDate()
Range("M5:M" & Range("N" & Rows.Count).End(xlUp).Row).Formula = "=DATE(P5,O5,N5)"
Range("M5:M" & Range("N" & Rows.Count).End(xlUp).Row).Copy
Range("M5:M" & Range("N" & Rows.Count).End(xlUp).Row).PasteSpecial xlPasteValues
End Sub
If you want to leave the formulas then simply delete the last 2 lines in there.
I'm trying to do a VBA code to accomplish 2 things as follows:
Count how many characters there is on cell A1, using the formula LEN(A1) and one the last line, I'm trying to have the formula RIGHT(LEFT(A1;Q1-2);6) on cell J1
Please follow down my VBA code so far:
LR = Cells(Rows.Count, "A").End(xlUp).Row
For i = 1 To LR
cel = "A" & i
cel2 = "P" & i
cel3 = "Q" & i
Range("P" & i).Formula = "=LEN(" & cel & ")"
Range("J" & i).Formula = "=RIGHT(LEFT(" & cel & "," & cel3 & "-" & 2 & ")," & 6 & ")"
Next i
It seems something silly what is missing, however, I couldnt manage to solve it so far
Thanks in advance
You’re missing a Right, and some other things
Range("J" & i).Formula = "=RIGHT(LEFT(" & cel & "," & cel3 & "-2), 6)"
I am working on a problem to loop through a certain number of columns and paste in an array formula. For every new column, I have to change the formula to reflect that column address. However, when I try to run it now, I keep getting a 1004 (select method of range class failed) error. Here is what I have written:
Sub Testlee()
Dim i As Integer
Dim LastColumn As Long
Dim rng As Range
Dim colStr As String
LastColumn = 10
For i = 1 To LastColumn
colStr = Replace(Split(Columns(i).Address, ":")(0), "$", "")
ThisWorkbook.Sheets("Data Validation").Range(colStr & "2:" & colStr & "500").Select
Selection.FormulaArray = "=IF(LEN(Agent1!" & colStr & "2:" & colStr & "500) + LEN(Agent2!" & colStr & "2:" & colStr & "500) = 0,"""",(IF(Agent1!" & colStr & "2:" & colStr & "500=Agent2!" & colStr & "2:" & colStr & "500, ""YES"", Agent1!" & colStr & "2:" & colStr & "500&""||""&Agent2!" & colStr & "2:" & colStr & "500)))"
Next i
End Sub
Any help would be appreciated : )
Update: I was able to get it working using a combination of the two approaches. Here is the code that works:
For i = 1 To LastColumn
colStr = Replace(Split(Columns(i).Address, ":")(0), "$", "")
With ThisWorkbook.Sheets("Data Validation").Range("A2:A500")
ThisWorkbook.Sheets("Data Validation").Range(colStr & "2:" & colStr & "500").FormulaArray = "=IF(LEN(Agent1!RC:R[498]C)+LEN(Agent2!RC:R[498]C) = 0,"""",(IF(Agent1!RC:R[498]C=Agent2!RC:R[498]C, ""YES"", Agent1!RC:R[498]C&""||""&Agent2!RC:R[498]C)))"
End With
Next i
Thank to everyone for their help!
Try this instead:
Sub MM()
Const LastCol As Integer = 10 '// Column number to extend to
With Sheets("Data Validation").Range("A2:A500")
.Resize(500, LastCol).FormulaArray = "=IF(LEN(Agent1!RC:R[498]C)+LEN(Agent2!RC:R[498]C) = 0,"""",(IF(Agent1!RC:R[498]C=Agent2!RC:R[498]C, ""YES"", Agent1!RC:R[498]C&""||""&Agent2!RC:R[498]C)))"
End With
End Sub
Use R1C1 Notation to make the formula relevant to each cell without looping.
Also, you can use Resize() method to resize an existing range - again, saves looping. Info on Resize method here
Finally, as already mentioned - 99.99% of the time there is no need to .Select anything in vba - you can access an object's properties and methods directly without making it the Selection
From what I see, you're probably selecting the columns of Sheets 'Data Validation' while the active sheet is another worksheet.
You need to activate Data Validations Sheet first which means you add a line
ThisWorkbook.Sheets("Data Validation").Select
before the line
ThisWorkbook.Sheets("Data Validation").Range(colStr & "2:" & colStr & "500").Select
This is provided you don't need to run anymore code which uses the current activesheet.
I have used the below code to get the answer. I m getting the result at my required location but sum is not displayed.
Cells(lastrow, 2).Offset(3, 1).Value = "=Sumif(L4:L" & lastrow & "," & "NEW ALBERTSONS INC" & ",J4:J" & lastrow - 1 & ")"
Could some one help me how to sort it out.
Try this one:
Cells(lastrow, 2).Offset(3, 1).Formula = "=SUMIF(L4:L" & lastrow & "," & """NEW ALBERTSONS INC""" & ",J4:J" & lastrow & ")"
Some notes:
I'm using """NEW ALBERTSONS INC""" instead "NEW ALBERTSONS INC"
(you should escape your quotes when constucting excel formulas
through vba)
sum_range and criteria_range should have same dimmentsion, that's
why you should use L4:L" & lastrow and J4:J" & lastrow (or &
lastrow-1 for both ranges)
actually, you can slightly simplify your formula by changing "," & """NEW ALBERTSONS INC""" to ", ""NEW ALBERTSONS INC"""
UPDATE:
Got a new issue with a formula, can't quite get it to work because of text in the formula, the formula (as taken from excel) should be,
=IF(D2<=0,"No Sales Price",E2/D2)
I have tried as many combinations as I can think of but the "no sales price" is causing an issue with the quotation marks. My current code is
For i = 2 To LastRowG
Range("Q" & i).Formula = "=IF(D" & i & "<=0," & "(No Sales Price)", & "(E" & i & "/D" & i & "))"
Next i
have had a look around but been unable to see any resolutions to the problem, any enlightenment will be met with the greatest appreciation
EDIT:This was fixed by inserting the following lines;
For i = 2 To LastRowG
Range("Q" & i).Formula = "=IF(D" & i & "<=0," & Chr(34) & "No Sales Price" & Chr(34) & "," & "E" & i & "/" & "D" & i & ")"
Next i
The Chr(34) inserts the ASCII character appertaining to that number which just so happens to be ". The program doesn't read it as having typed in the quote marks and continues to read the line of code correctly but then places the "no sales price" correctly in the formula.
It will output the line as the formula is intended to be and the Chr(34) is like writing ""No Sales Price"" without the inevitable "expected end of statement" error
What I suggested will result in something like this:
LastRow = Cells(Rows.Count, "C").End(xlUp).Row
Cells(LastRow + 1, 3).Formula = "=SUM(C1:C" & LastRow & ")"
Extra 1
Is it possible to use this formula to enter the word Total in the cell to the left?
Range("B" & LastRow + 1) = "Total"
Extra 2
One more just to push my luck, how about copying a formula all the way down a column the the last cell? =G2*57.5 copied until the last row in I
LastRowG = Cells(Rows.Count, "G").End(xlUp).Row
For i = 2 To LastRowG
Range("I" & i).Value = "=G" & i & "*57.5"
Next i