Dynamic Column Index Name Error in Formula - excel

I am trying to calculate the component q'ty from Sheet Plan to Sheet Result by using Vlookup to fill in column,having:
Count_col: is the total column in sheet Plan
Last_col: is the total column in sheet Result (before add column Demand)
Sheet Results
Material
Component
Demand W1
Demand W2
ABCD1000
nc200
#NAME?
#NAME?
Sheet Plan
Material
Demand W1
Demand W2
ABCD1000
1000
200
For i = 1 To count_col
Cells(1, i + last_col).Value = "=Plan!RC[-2]"
Cells(1, i + last_col).Offset(1, 0).Select
ActiveCell.FormulaR1C1 = "=VLOOKUP(RC1,Plan!C1:C15,i+1,0)"
Next i
But the result is name error, I checked the spelling of function is correct and dont know how to fix. Why there is "#" in my formula?
Detail of error
=VLOOKUP($A2,Plan!$A:$O,#i+1,0)

i+1 inside "" behaves like a string rather than a variable. Try this.
ActiveCell.FormulaR1C1 = "=VLOOKUP(RC1,Plan!C1:C15," & i + 1 & ",0)"
Also avoid the use of .Select. Your code can be written as
Cells(1, i + last_col).Offset(1, 0).FormulaR1C1 = _
"=VLOOKUP(RC1,Plan!C1:C15," & i + 1 & ",0)"
Recommended Reading: How to avoid using Select in Excel VBA
Also you are mixing R1C1 and A1 style of referencing. I would recommend using one of them. A simple Google search R1C1 vs A1 style will explain what they are.
In R1C1, Plan!C1:C15 needs to be written as Plan!R1C3:R15C3. So your final code would be
Cells(1, i + last_col).Offset(1, 0).FormulaR1C1 = _
"=VLOOKUP(RC1,Plan!R1C3:R15C3," & i + 1 & ",0)"

Related

Excel VBA Trying to write a "MAX" formula to Cells with different Ranges with For-Loop

I am trying to make VBA write a formula into different cells that will find the maximum value for a Range decided by some variables. My variables I and J are (numbers/Integers).
Here is my code.
Sub AddMAX()
Dim I As Integer
Dim J As Integer
Dim L As Integer
I = InputBox("Number of columns to check max value")
J = InputBox("Number of Rows to add formula inn and find max value of that row")
For L = 5 To 4 + J
Worksheets(1).Cells(L, 4 + I).Formula = "=" & Max(Range(Cells(L, 4), Cells(L, 3 + I)))
Next L
End Sub
Have tried to re-write the second part (part behind the equal sign) several times. Usually I get the message Compile error: Sub or Function not defined and it marks the "Max". I thought Max (also tried with big letters) was an in-built function like SUM and so on.
I'm trying to make it write an Excel formula like this into the cells:
For I=2 and J=3:
Cell F5: =MAX(D5:E5)
Cell F6: =MAX(D6:E6)
Cell F7: =MAX(D7:E7)
i.e. I want a formula in the cells like I had wrote it in the cells manually to calculate max value, so that if the value in Cells D5, to D7 and E5 to E7 change, the new max value will be found without any scripts having to run.
Let me know if something is unclear.
You should not be putting Range and Cells in a formula string, they mean nothing to the Excel formula engine. You need the Address of the cells:
Dim I As Long
Dim J As Long
Dim L As Long
I = InputBox("Number of columns to check max value")
J = InputBox("Number of Rows to add formula inn and find max value of that row")
L = 5
With Worksheets(1)
.Range(.Cells(L, 4 + I), .Cells(4 + J, 4 + I)).Formula = "=MAX(" & .Cells(L, 4).Address(False, False) & ":" & .Cells(L, I + 3).Address(False, False) & ")"
End With
The formula is actually the same for all cells, which is why it is possible to assign it in one assignment for the entire range. It looks different in the A1 reference notation, but if you switch to R1C1 in the Excel settings, you will see they are the same. Which also means it is easier to create that formula using the R1C1 notation in the first place:
Dim I As Long
Dim J As Long
Dim L As Long
I = InputBox("Number of columns to check max value")
J = InputBox("Number of Rows to add formula inn and find max value of that row")
L = 5
With Worksheets(1)
.Range(.Cells(L, 4 + I), .Cells(4 + J, 4 + I)).FormulaR1C1 = "=MAX(RC[-" & I & "]:RC[-1])"
End With
But it would appear to me that you should instead use the Excel interface the intended way. Select the cells in which the MAX formula should be. Keeping the entire range selected, put the MAX formula into any of its cells as if you were creating it for just that cell, but instead of pressing Enter, press Ctrl+Enter.
You have to be careful to distinct between the part that is seen by VBA and the final formula.
If you write
Worksheets(1).Cells(L, 4 + I).Formula = "=" & Max(Range(Cells(L, 4), Cells(L, 3 + I)))
Max (and all the following stuff) is seen by the VBA-interpreter, not Excel. But there is no Max-function, and you get an (compiler)-error.
If you write
Worksheets(1).Cells(L, 4 + I).Formula = "=Max(Range(Cells(L, 4), Cells(L, 3 + I)))"
the VBA-interpreter sees the whole stuff as a string. It cannot take care about variables like L or I because is doesn't see them. So you end up with a formula that is exactly like you write it - and Excel (not VBA) will show you an error because it doesn't understand L or I.
What you need is a statement (in VBA) that creates a string that contains the actual values of your variables, and assign it to the cell.formula. I strongly advice that you first assign this to a string variable - it makes debugging much easier:
Dim formula As String
formula = "=Max(Range(Cells(" & L & ", 4), Cells(" & L & ", 3 + " & I & ")))"
Debug.Print formula
Worksheets(1).Cells(L, 4 + I).Formula = formula
Update: Sorry, I haven't looked to the content of the formula at all, of course the Range and Cells-objects are VBA objects. What you need in your formula is the address of the range, so change the line to
formula = "=MAX(" & Range(Cells(L, 4), Cells(L, 3 + i)).Address & ")"
Now VBA will create a Range and put the address into the formula string.

Inserting Excel formula that refers to alternative columns

I am trying to insert the following formula ='External Costs B0'!F73 in the same row of a sheet in consecutive columns, however with the cell reference "F73" in worksheet "External Costs" referring to alternate columns e.g F73, H73, J73, L73 etc.
Here is a screen shot of the spreadsheet with formula commented
Screen Capture of formula sheet
This is the code I have tried but I am struggling to figure how to get the alternative column reference working.
Dim CostColumns As Long
'Select cell to start inserting the formula from
Range("E26").Select
'Start from column F (6) in the "External Costs B0" sheet and step to every alternate column
For CostColumns = 6 To 600 Step 2
ActiveCell.Formula = "= ""'External Costs B0'!"" & Rows(73)Columns(CostColumns)"
Move to the next cell to insert the formula in and advance the column reference by 2 columns
ActiveCell.Offset(0, 1).Select
Next CostColumns
The net result is the same error I have seen in many posts:
Application-defined or object-defined error.
Here are many other syntax's for the formula insert I have tried with no success. Any help is greatly appreciated. The below refers to row 40 instead of row 73 in the External Costs B0 sheet as per the example above.
Range("E26").Select
For CostColumns = 6 To 66 Step 2
'ActiveCell.FormulaR1C1 = "= worksheets("""External Costs B0""").Cells(40,6).Value"
'ActiveCell.FormulaR1C1 = "='External Costs B0'!R[14]C[CostColumns]"
'Range("E26:AK26").FormulaR1C1 = "='External Costs B0'!R[14]C[CostColumns]"
'ActiveCell.FormulaR1C1 = "= worksheets('External Costs B0')!" & " Rows(40)Columns(CostColumns)"
'Range("E26:AK26").FormulaR1C1 = "='External Costs B0'!R[14]C[+2]"
'Range("E26:AK26").FormulaR1C1 = "=Wksht.Cells(40,CostColumns) &"
'Range("E26:AK26").Formula = "=worksheets('External Costs B0'!)" & ".Cells(40,6)"
'ActiveCell.Formula = "= worksheets('External Costs B0'!).Cells(40,6).Value"
ActiveCell.Offset(0, 1).Select
Next CostColumns
Use this:
ActiveCell.Formula = "='External Costs B0'!" & Cells(73, CostColumns).Address(0, 0)
The problem with that is that Rows(73) and Columns(CostColumns) both return a Range object which you can't concatenate to a string.
Its way easier, if you use FormulaR1C1 and no selects like in the following sub:
(please change R, RowOffset and FormulaUntilColumn to your needs)
Sub Formulas()
Dim I As Integer
Const R As Long = 9 'row
Const RowOffset As Integer = -8
Const ForumulaUntilColumn As Long = 7
For I = 1 To ForumulaUntilColumn
Cells(R, I).FormulaR1C1 = "=R[" & RowOffset & "]C[" & I - 1 & "]"
Next I
End Sub
P.S.: add workbook and table name as in any other formula between '=' and 'R['
This code will place your formula in cells Sheet1!A1:AD1.
The formula in A1 will be ='External Costs B0'!$A$73.
In B1 it will be ='External Costs B0'!$C$73 and so on up to ='External Costs B0'!$BG$73 in cell AD1.
Sub PasteFormula()
Dim CostColumns As Long
Dim y As Long
'Starting column for External Costs reference
CostColumns = 1
With ThisWorkbook.Worksheets("Sheet1")
For y = 1 To 30
.Cells(1, y).FormulaR1C1 = "='External Costs B0'!R73C" & CostColumns
CostColumns = CostColumns + 2
Next y
End With
End Sub
To update the code change Sheet1 to whichever sheet you need to
formula to appear in.
Change CostColumn=1 to the correct column
number you want the formula to refer to.
Change y = 1 To 30 to
the correct columns you want the formula to appear in.
The code uses R1C1 syntax as it's easier to update a formula if you only need to deal with row & column numbers R73C2 is row 73, column 2 for example.

get the differences between 2 Integer columns into third column

I have to calculate the difference between the values of 2 columns(firstCol and lastCol) and set those differences in a different column(NextColumn). The row count keeps changing, so I have to calculate the rowCount before calculating the difference. I'm trying to write a loop using Range so that the difference can be calculated but it doesn't seem to work.
For i = 3 To lastRow
Range(Cells(3, NextColumn), Cells(lastRow, NextColumn)).FormulaR1C1 = "=Range(Cells(i, firstCol),Cells(i,firstCol)).Value - Range(Cells(i, lastCol),Cells(i,lastCol)).Value"
Next i
Any help would be greatly appreciated!
Thank you
Nick
For any input of "i" into the formula, you need to use " & i & " when using using a formula="", such as:
"=A" & i & "+B" & i
When you change to just a formula that doesn't input a formula to the cell (math happens in VBA), you can ignore the Excel formatting and "" blocking, such as:
= Cells(i,"A").Value + Cells(i,"B").Value
Make sure to use your loop variable where appropriate, so that you would have an outcome in a loop like:
Dim i as Long
For i = 1 to 10
Cells(i,"C").Formula = Cells(i,"A").Value + Cells(i,"B").Value
Next i
Why looping ? Unless I misunderstood the question, something like this should do the trick:
Range("X3:X"& lastrow).Formula = "=C3-D3"
The formula will adjust.
vba needs to be outside the quotes and you do not need the loop:
Range(Cells(3, NextColumn), Cells(lastRow, NextColumn)).Formula = "=" & Cells(3, firstCol).Address(0, 0) & "-" & Cells(3, lastCol).Address(0, 0)
No loop needed. Excel will change the relative references as needed.

Dynamic formula autofill

I would like to know how may i convert this code into dynamic range autofill for the column I to enable the freedom of editing the excel sheet at a later time without the need to adjust the vba code.
Sub Rowcount()
'Charles, M
Dim H As Long
Set sh = Worksheets("Report-Charles, M")
H = sh.UsedRange.Rows.Count
Range("I2:I" & H).Formula = "=IF((AND(OR(E2=""Unrated"",E2=""""),OR(G2<>""Unrated"",G2<>""""))),G2,IF(E2>=""4,25"",""High Performance"",IF(E2<""3,35"",""Low Performance"",IF(AND(E2>=""3,35"",E2<""4,25""),""Medium Performance"",""Unrated""))))"
MsgBox (H) & "Rows have been Autofilled with 3 scale Rating Results"
End Sub
Have a look into the AutoFill function:
Range("I2:I" & H).AutoFill Destination:=Range("I2:I2000"), Type:=xlFillDefault
First off, you are only implicitly referencing the Report-Charles, M as the ActiveSheet property to put the .Formula into; not explicitly with direct reference.
Second, To assign the formula, use a direct .Formula write, the Range.AutoFill method or the Range.FillDown method.
Lastly, writing a formula .Formula through VBA should be done with EN-US syntax and regional settings. If you want to use non-EN-US regional settings like 3,35 or 4,25 then use the Range.FormulaLocal property.
Above all else, treat numbers as numbers; not as text-that-look-like-numbers.
with Worksheets("Report-Charles, M")
h = .UsedRange.Rows.Count
.Range("I2:I" & H).FormulaLocal = _
"=IF((AND(OR(E2=""Unrated"", E2=TEXT(,)), OR(G2<>""Unrated"", G2<>TEXT(,)))), G2, IF(E2>=4,25, ""High Performance"", IF(E2<3,35, ""Low Performance"", ""Medium Performance"")))"
.Range("I2:I" & H).Formula = _
"=IF((AND(OR(E2=""Unrated"", E2=TEXT(,)), OR(G2<>""Unrated"", G2<>TEXT(,)))), G2, IF(E2>=4.25, ""High Performance"", IF(E2<3.35, ""Low Performance"", ""Medium Performance"")))"
end with
with Worksheets("Report-Charles, M")
'any of the following will fill column I with formulas to the last row in .UsedRange
'all of the following assumes a valid formula in I2
h = .UsedRange.Rows.Count
.Range("I2:I" & H).Formula = .Range("I2").Formula
.Range("I2:I" & H).FillDown
.Range("I2:I" & H).DataSeries Rowcol:=xlColumns, Type:=xlAutoFill
.Range("I2").AutoFill Destination:=.Range("I2:I" & H), Type:=xlFillDefault
end with
I've shortened one IF condition since the AND was unnecessary and Medium was the default response. Using TEXT(,) is the same as saying "" and does not have to double-up double-quotes.

Create new Excel rows based on column data

Good afternoon all,
I have an issue where I have users who have multiple bank account details. I need to try and create a new row for each employee who has more than one bank account, with the second bank account being allocated a new row.
Employee Number User ID BSB Account number
10000591 WOODSP0 306089,116879 343509,041145273
10000592 THOMSOS0 037125 317166
I need it to look something like this:
Employee Number User ID BSB Account number
10000591 WOODSP0 306089 343509
10000591 WOODSP0 116879 041145273
10000592 THOMSOS0 037125 317166
Any thoughts? Your input is greatly appreciated!
Screenshots are here to demonstrate:
Right click on the tab and choose "View Code"
Paste this code in:
Sub SplitOnAccount()
Dim X As Long, Y As Long, EmpNo As String, UserID As String, BSB As Variant, AccNo As Variant
Range("F1:I1") = Application.Transpose(Application.Transpose(Array(Range("A1:D1"))))
For X = 2 To Range("A" & Rows.Count).End(xlUp).Row
EmpNo = Range("A" & X).Text
UserID = Range("B" & X).Text
BSB = Split(Range("C" & X).Text, ",")
AccNo = Split(Range("D" & X).Text, ",")
For Y = LBound(AccNo) To UBound(AccNo)
Range("F" & Range("F" & Rows.Count).End(xlUp).Row).Offset(1, 0).Formula = EmpNo
Range("G" & Range("G" & Rows.Count).End(xlUp).Row).Offset(1, 0).Formula = UserID
Range("H" & Range("H" & Rows.Count).End(xlUp).Row).Offset(1, 0).Formula = BSB(Y)
Range("I" & Range("I" & Rows.Count).End(xlUp).Row).Offset(1, 0).Formula = AccNo(Y)
Next
Next
End Sub
Close the window to go back to excel
Press ALT-F8
Choose SplitOnAccount and click run.
Note, this is going to populate the split data to rows F to I, make sure there is nothing in there. If there is post back and we can change it.
Also format columns F - I as text before you run it or Excel will strip leading zeros off as it will interpret it as a number.
Here is another sub that appears to perform what you are looking for.
Sub stack_accounts()
Dim rw As Long, b As Long
Dim vVALs As Variant, vBSBs As Variant, vACTs As Variant
With ActiveSheet '<-define this worksheet properly!
For rw = .Cells(Rows.Count, 1).End(xlUp).Row To 2 Step -1
vVALs = .Cells(rw, 1).Resize(1, 4).Value
vBSBs = Split(vVALs(1, 3), Chr(44))
vACTs = Split(vVALs(1, 4), Chr(44))
If UBound(vBSBs) = UBound(vBSBs) Then
For b = UBound(vBSBs) To LBound(vBSBs) Step -1
If b > LBound(vBSBs) Then _
.Rows(rw + 1).Insert
.Cells(rw - (b > LBound(vBSBs)), 1).Resize(1, 4) = vVALs
.Cells(rw - (b > LBound(vBSBs)), 3).Resize(1, 2).NumberFormat = "#"
.Cells(rw - (b > LBound(vBSBs)), 3) = CStr(vBSBs(b))
.Cells(rw - (b > LBound(vBSBs)), 4) = CStr(vACTs(b))
Next b
End If
Next rw
End With
End Sub
I was originally only going to process the rows that had comma delimited values in columns C and D but I thought that processing all of them would allow the macro to set the Text number format and get rid of the Number as text error warnings and keep the leading zero in 041145273.
        
You Can definitely use Power Query to transform the data to generate new rows using split column option.
Check this article it explains the process in detail.
Load Data in Power Query section of excel.
Create an Index (Not required step)
Use Split column function with advance options and split them into new rows.
Save this result into new table for your use.
I did it myself and it worked like a charm.
A formula solution:
Delimiter: Can be a real delimiter or an absolute reference to a cell containing only the delimiter.
HelperCol: I have to use a helper column to make it work. You need to give the column letter.
StartCol: The column letter of the first column containing data.
SplitCol: The column letter of the column to be splitted.
Formula1: Used to generate the formula for the first column not to be splitted. You can fill this formula down and then fill to right.
Formula2: Used to generate the formula for the column to be splitted(only support split one column).
Formula3: Used to generate the formula for the Helper column.
(If the title of the column to be splitted contains the delimiter, you must change the first value of the helper column to 1 manually.)
Formula1:=SUBSTITUTE(SUBSTITUTE("=LOOKUP(ROW(1:1),$J:$J,A:A)&""""","$J:$J","$"&B2&":$"&B2),"A:A",B3&":"&B3)
Formula2:=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE("=MID($M$1&LOOKUP(ROW(A1),$J:$J,F:F)&$M$1,FIND(""艹"",SUBSTITUTE($M$1&LOOKUP(ROW(A1),$J:$J,F:F)&$M$1,$M$1,"&"""艹"",ROW(A2)-LOOKUP(ROW(A1),$J:$J)))+1,FIND(""艹"",SUBSTITUTE($M$1&LOOKUP(ROW(A1),$J:$J,F:F)&$M$1,$M$1,""艹"",ROW(A2)-LOOKUP(ROW(A1),$J:$J)+1))-FIND(""艹"",SUBSTITUTE($M$1&LOOKUP(ROW(A1),$J:$J,F:F)&$M$1,$M$1,""艹"",ROW(A2)-LOOKUP(ROW(A1),$J:$J)))-1)&""""","$M$1",IF(ISERROR(INDIRECT(B1)),""""&B1&"""",B1)),"$J:$J","$"&B2&":$"&B2),"F:F",B4&":"&B4)
Formula3:=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE("=SUM(E1,LEN(B1)-LEN(SUBSTITUTE(B1,$H$1,"""")))+1","B1",B4&1),"$H$1",IF(ISERROR(INDIRECT(B1)),""""&B1&"""",B1)),"E1",B2&1)
Helper must filled one row more than the data.
How to use:
Copy the formula generated by the above three formula.
Use Paste Special only paste the value.
Make the formula into effect.
Fill the formula.
Bug:
Numbers will be converted to Text. Of course you can remove the &"" at the end of the formula, but blank cells will be filled with 0.
ps. This method may by very hard to comprehend. But once you master it, it can be very useful to solve relative problems.

Resources