I have an Excel document containing 2 sheets, 1 import sheet and a data sheet. The dynamic dropdown in Column B of the Import sheet should be dependant on the value chosen in Column A of the import sheet.
However to find the corresponding "Series" I need to match the ID's from the data sheet. (Eicher ID should match the Series Parent ID; Column B and D)
Screenshots down below should explain it better;
I selected Eicher in User Sheet.A3, now I want to retrieve the ID from DataSheet Column B (mmcMake-24046283). With this I need to find all corresponding Series with the same Series Parent ID. So in this case my dropdown should have shown; Series Eicher, Series 2000, Series 3000, Series 300 and Series 400.
Ok, here is a code to insert the validation. Check the "setting variables" part to make sure every variable is properly set. Sorry for the quite complex variables names, but empty stomach makes hard to synthesize. :D
Sub SubDynamicDropdownGenerator()
'Declarations.
Dim StrDataSheetName As String
Dim StrImportSheetName As String
Dim StrImportColumnMake As String
Dim StrDataColumns As String
Dim StrDataColumnSeries As String
Dim StrDataColumnSeriesParentIDEntire As String
Dim BytDataColumnMakesIDInternalColumn As Byte
Dim RngCellWithDropDown As Range
'Setting variables.
StrDataSheetName = "Data" 'Insert here the name of the sheet with data
StrImportSheetName = "Import" 'Insert here the name of the sheet with the import (where the range with the dynamic drowpdown is)
StrImportColumnMake = "A" 'Insert here the letter of the column where labeled Make (according to your first picture it is A)
StrDataColumns = "A:E" 'Insert here the letters of the columns where the data are located in the data sheet (i guess they are A:E)
StrDataColumnSeries = "C" 'Insert here the letter of the column where the Series are located in the data sheet (i guess is the C column)
StrDataColumnSeriesParentIDEntire = "E:E" 'Insert here the address of the column where the Series Parent ID are located in the data sheet (i guess is the E column)
BytDataColumnMakesIDInternalColumn = 2 'Insert here the internal reference of the MakesID in the data sheet for the VLOOKUP functions (since it's in the second column, i set it to 2)
Set RngCellWithDropDown = Sheets(StrImportSheetName).Range("B3") 'Insert here the cell on witch you are going to apply the validation dropdown.
'Setting validation.
With RngCellWithDropDown.Validation
.Delete
.Add Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:="=INDIRECT(""" & StrDataSheetName & "!" & StrDataColumnSeries & """&MATCH(VLOOKUP(" & StrImportColumnMake & RngCellWithDropDown.Row & "," & StrDataSheetName & "!" & StrDataColumns & "," & BytDataColumnMakesIDInternalColumn & ",FALSE)," & StrDataSheetName & "!" & StrDataColumnSeriesParentIDEntire & ",0)&"":" & StrDataColumnSeries & """&COUNTIF(" & StrDataSheetName & "!" & StrDataColumnSeriesParentIDEntire & ",VLOOKUP(" & StrImportColumnMake & RngCellWithDropDown.Row & "," & StrDataSheetName & "!" & StrDataColumns & "," & BytDataColumnMakesIDInternalColumn & ",FALSE))+MATCH(VLOOKUP(" & StrImportColumnMake & RngCellWithDropDown.Row & "," & StrDataSheetName & "!" & StrDataColumns & "," & BytDataColumnMakesIDInternalColumn & ",FALSE)," & StrDataSheetName & "!" & StrDataColumnSeriesParentIDEntire & ",0)-1)"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End Sub
Like i've said, it should work as long as the data stay sorted by Series Parent ID. Tell me if you need to appy it on multiple cells. I can edit the code accordingly. Also if you need any explanation on the really messy formula, just say please.
Related
Got a code from a member here (thanks a lot), but got an error with Pop-out error code 1004 on
With wsTarget
.Range("A6").FormulaR1C1 = strFormulaCOA
.Range("D6").FormulaR1C1 = strFormulaStatus
End With
Any idea to fix the problem?
I try to give "" between the strFormulaCOA resulting the code to just insert strFormulaCOA word on the destinated range. Another thing, I also try to change the FormulaR1C1 to value and formula but still no good.
here's the code I use
Option Explicit
Sub insertCOAandStatusFormulas()
'Pattern of each formula part - $1 as placeholder for sheetname
Dim strPartCOA As String, strPartStatus As String
strPartCOA = "IFERROR(INDEX('$1'!R6C:R2000C,MATCH(RC3,'$1'!R6C3:R2000C3,0)),INDEX('$1'!R6C:R2000C,MATCH(RC3,'$1'!R6C5:R2000C5,0)) "
strPartStatus = "IFERROR(VLOOKUP(RC3,'$1'!R6C3:R2000C12,4,0),VLOOKUP(RC3,'$1'!R6C5:R2000C12,2,0) "
Dim wsTarget As Worksheet
Dim wsTarget2 As Worksheet
Set wsTarget = ThisWorkbook.Worksheets("Rekap Capex") '--> adjust this to your needs
Set wsTarget2 = ThisWorkbook.Worksheets("Depreciation")
'build sheet-specific part per formula
Dim strFormulaCOA As String, strFormulaStatus As String
Dim cntSheets As Long, i As Long
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
If Not ws.Name = wsTarget.Name And Not ws.Name = "Depreciation" Then
strPartCOA = strFormulaCOA & Replace(strPartCOA, "$1", ws.Name) & vbCrLf
strPartStatus = strFormulaStatus & Replace(strPartStatus, "$1", ws.Name) & vbCrLf
cntSheets = cntSheets + 1
End If
Next
'add equal-sign, remove last comma and add closing brackets
strFormulaCOA = "=" & strPartCOA & String(cntSheets, ")")
strFormulaStatus = "=" & strPartStatus & String(cntSheets, ")")
With wsTarget
.Range("A6").FormulaR1C1 = strFormulaCOA
.Range("D6").FormulaR1C1 = strFormulaStatus
End With
End Sub
Edit:
Below is the target of the formula (the blank cells) in which I want to add index match and vlookup formula
the problem is that the sheet of the data is not always the same, as we know that vlookup and index match formula need to state the sheet name(the first and second sheet always the same).
this is what my vlookup formula looks like
this is what my index match formula looks like
First of all I highly recommended to use formulas A1 instead R1C1 because it's easyly to understand. To insert in this formula a listname follow the example:
fformula = "=FormulaExample(" & Chr(39) & lst1 & Chr(39) & "!$B$3:$B$" & (n + 3) & "," & Chr(39) & lst1 & Chr(39) & "!L3:L" & (n + 3) & ",$C$2,$D$2,$E$2,$F$2,$B$7," & Chr(39) & lst1 & Chr(39) & "!$AA$3:$AA$" & (n + 3) & ")"
where lst1 = "listexample"
chr(int) returns an ASCII symbol
chr(39) returns dot
Remember that formula inserts with "," instead of ";" (A1,B1 not A1;B1)
That code will be like this:
=FormulaExample('listexample'!$B$3:$B$88000;'listexample'!L3:L88000;$C$2;$D$2;$E$2;$F$2;$B$7;'listexample'!$AA$3:$AA$88000;J2)
And to insert:
with wsTarget:
.Range("A1").Formula = fformula
Please edit your code with A1 code style or give me a picture of sheet/file and I will help you to code
Dim tableref As String
'get cluster number from cel 0,-2
cluster_num = ActiveCell.Offset(0, -2)
'path to named range in wb elementenbundel
tableref = "elementenbundel.xlsm!" & "table_" & cluster_num
'add colum tag to path
tablecol = "=" & tableref & "[Code]"
Set wb_1 = ThisWorkbook
'open wb elementenbundel
Set wb_2 = Workbooks.Open(wb_1.Path + "/elementenbundel.xlsm")
wb_1.Activate
'create defined name for the range
RangeName = "code_" & cluster_num
'MsgBox (RangeName)
'MsgBox (tablecol)
'if name not present, add named range referring to column of table in elementenbundel
If RangeExists(RangeName) Then
MsgBox (RangeName & " exists")
Else
MsgBox (RangeName & " does not exists")
ThisWorkbook.Names.Add Name:=RangeName, RefersTo:=tablecol
End If
'delete previous validation
ActiveCell.Validation.Delete
'insert validation depending on value in A15, B15 will hold "code_" & A15.value
'B15 will be used in the formula to populate the dropdown with the first column of the table in elementenbundel
ActiveCell.Validation.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
Formula1:="=INDIRECT(B15)"
'look for data in elementenbundel to display in current table
Dim formula As String
formula = "=VLOOKUP(" & ActiveCell.Address & "," & tableref & ", 2)"
ActiveCell.Offset(0, 1).formula = formula
the above code works
I would like to change the VLOOKUP formula in such a way that users don't have to run the macro.
at the moment the macro grabs the value to put in tableref, but I prefer the formula takes over the value, so I am looking for something like this
formula = "=VLOOKUP(" & ActiveCell.Address & ",elementenbundel.xlsm!table_"& CONTENT OF CELL A15 & ", 2)"
the result will be that if A15 holds 1:
the dropdown will be populated with table_1 of elementenbundel
the VLOOKUP should be looking for the value in table_1, column 2 that
matches the selected value of the dropdown? thus adding A15.value to the formula
But I don't have a clue how to add this "cell.value" in this formula
Any help would be great!
Thanks in advance
formula = "=VLOOKUP(" & ActiveCell.Address & ",INDIRECT(""elementenbundel.xlsm!table_"" & A15), 2)
I'm new to VBA and I'm trying to create a macro that will filter a column on one sheet (Rules) based on the cell value in another which contains the unique values on that column. The unique values are separated by " & ":
Example, a cell may contain the following value: 19.1 & 19.2 & 19.2c & 14.3a & 14.3b & 14.3b(1) & 14.3b(2) & 14.3b(3) & 14.3c & 14.3c(1) & 14.3c(2) & 14.7a
Each of these values has a unique row in column C of the Rules sheet and I want to filter the sheet on that column for all these values.
I have tried the following but it doesn't work:
Sub ArrayFilter()
Dim Rules As String
Dim ArrayFilter As String
Dim arr As Variant
'This is the cell with the values
' e.g 19.1 & 19.2 & 19.2c & 14.3a & 14.3b & 14.3b(1) & 14.3b(2) & 14.3b(3) & 14.3c & 14.3c(1) & 14.3c(2) & 14.7a
Rules = ActiveCell.Offset(0, 38).Range("A1").Value
' I'm trying to convert this to a string for the filter crieria
ArrayFilter = Chr(34) & Replace(Rules, " & ", Chr(34) & ", " & Chr(34)) & Chr(34)
'Now I make this an Array
arr = Array(ArrayFilter)
Sheets("2019 Rules Breakdown").Select
Application.Run "RemoveAndReApplyFilters"
Range("C1").Select
ActiveSheet.ListObjects("Table10").Range.AutoFilter Field:=3, Criteria1:=arr, _
Operator:=xlFilterValues
'This fails, when I look at the filter deployed it is using Equals and just has the arr output.
End Sub
Any help would be gratefully welcomed.
Thanks
The way you try obtaining the array is not appropriate. You can check it in this way:
Dim rules As String, ArrayFilter As String, arr
rules = "19.1 & 19.2 & 19.2c & 14.3a & 14.3b & 14.3b(1)"
ArrayFilter = Chr(34) & Replace(rules, " & ", Chr(34) & ", " & Chr(34)) & Chr(34)
arr = Array(ArrayFilter)
Debug.Print Join(arr, "|"), UBound(arr) 'it will return "19.1", "19.2", "19.2c", "14.3a", "14.3b", "14.3b(1)" 0 .
'meaning an array with a single element, the long string...
End Sub
Now, using the next way, for the same string, the array will look like it should:
Sub testArrayFromString()
Dim rules As String, arr1
rules = "19.1 & 19.2 & 19.2c & 14.3a & 14.3b & 14.3b(1)"
arr1 = Split(rules, " & ")
Debug.Print Join(arr1, "|"), Ubound(arr1) '19.1|19.2|19.2c|14.3a|14.3b|14.3b(1) 5
'proving that it is an array with 6 elements (0 based)
'Being in VBE, press `Ctrl + G` to see the result in `Immediate Window`.
End Sub
I am trying to apply Vlookup on a filtered range with Variable Lookup Value(Changing according to the row number) and Variable Lookup Range(From a user browsed workbook). But, the formula bar after running the code shows the formula as :-
=IFERROR(VLOOKUP(#Sri Lanka15-#a_One-#Time Base Rent,'[C_Rent Report_25082020.xlsx]Sheet 1'!$J$1:$N$968,4,0)," ")
I am not sure where these "#" signs are coming from. The lookup value for this particular row is :-Sri Lanka15-a_One-Time Base Rent.
Below is the code:-
Dim LR As Long ' Defined as Last row in source file
Dim nlr As Long 'Defined as Last row in Macro Workbook where vlookup is applied
Dim Filename As String
Filename = Application.GetOpenFilename(FileFilter:="All Files(*.xls; *.xlsx; *.csv),*xls,*.xlsx, *csv", Title:="Select File To Be Opened")
Workbooks.Open Filename:=Filename
sourcefile = Dir(Filename)
With ActiveSheet
Range("A1:AQ" & nlr).AutoFilter Field:=25, Criteria1:="One-Time Base Rent"
For Each cell In Range("AA2:AA" & nlr).SpecialCells(xlCellTypeVisible)
lookupvalue = Cells(cell.Row, "Z").Value
cell.Formula = "=IFERROR(VLOOKUP(" & lookupvalue & ",'[" & sourcefile & "]Sheet 1'!$J$1:$N$" & LR & ",4,0),"" "")" ' The problem seems to be here in lookup value as rest are appearing as fine in formula
Next
End With
Since i need to apply subsequent filters after this. i would like to keep the lookup value as variable.
I have tried WorksheetFunction.Vlookup too, but i am not sure how to define the range from a file chosen by user in worksheetfunction
Any help is highly appreciated !!
Thanks
Please, try replacing of
cell.Formula = "=IFERROR(VLOOKUP(" & lookupvalue & ",'[" & sourcefile & "]Sheet 1'!$J$1:$N$" & LR & ",4,0),"" "")"
with
cell.Formula = "=IFERROR(VLOOKUP(" & cells(cell.Row, "Z").Address & ",'[" & sourceFile & "]Sheet 1'!$J$1:$N$" & lr & ",4,0),"" "")"
I am getting a formula error message: Run-time error 1004, for the second recurrence of a formula in the code; the code section in question as follows, for quick reference I pasted the two formulas just below, the first one runs OK, the second one gives the error that I cannot figure out.
ActiveWorkbook.Names.Add Name:="pivotsourceFGPO", RefersToR1C1:=swaFormula (no errors when running the macro)
ActiveWorkbook.Names.Add Name:="pivotsourceorderbase", RefersToR1C1:=swaFormula (FORMULA giving error)
Code: (partial)
swaFormula = "=OFFSET(" & _
ActiveWorkbook.Worksheets(ActiveSheet.Index).Name & "!R" & ActiveCell.Row & "C" & ActiveCell.Column & ",0,0,COUNTA(" & _
ActiveWorkbook.Worksheets(ActiveSheet.Index).Name & "!C" & ActiveCell.Column & ") -" & swarow & ",COUNTA(" & _
ActiveWorkbook.Worksheets(ActiveSheet.Index).Name & "!R" & ActiveCell.Row & ")-" & swacol & ")"
ActiveWorkbook.Names.Add Name:="pivotsourceFGPO", RefersToR1C1:=swaFormula
Dim PTCache As PivotCache
Dim pt As PivotTable
Dim WS As Worksheet
Dim pvtfld As PivotField
' define the range which serves as the data range
Set WS = Sheets.Add ' add new sheet to hold the pivot table
Set PTCache = ActiveWorkbook.PivotCaches.Add(SourceType:=xlDatabase, SourceData:="=pivotsourceFGPO")
' Create the pivot table
Set pt = PTCache.CreatePivotTable(TableDestination:=WS.Range("A1"), TableName:="FGPOPivot")
ActiveWorkbook.ShowPivotTableFieldList = True
pt.PivotFields("Key").Orientation = xlRowField
pt.PivotFields("Key").Position = 1
pt.PivotFields("MTL").Orientation = xlRowField
pt.PivotFields("MTL").Position = 2
pt.PivotFields("Size Code").Orientation = xlRowField
pt.PivotFields("Size Code").Position = 3
pt.PivotFields("Week").Orientation = xlColumnField
pt.PivotFields("Week").Position = 1
pt.AddDataField pt.PivotFields("Wip Qty"), "Sum of Wip Qty", xlSum
'Order base 1 pivot
Sheets("Order base (1)").Select
Range("A1").Select
swarow = ActiveCell.Row - 1
swacol = ActiveCell.Column - 1
' make it comma and not colon
swaFormula = "=OFFSET(" & _
ActiveWorkbook.Worksheets(ActiveSheet.Index).Name & "!R" & ActiveCell.Row & "C" & ActiveCell.Column & ",0,0,COUNTA(" & _
ActiveWorkbook.Worksheets(ActiveSheet.Index).Name & "!C" & ActiveCell.Column & ") -" & swarow & ",COUNTA(" & _
ActiveWorkbook.Worksheets(ActiveSheet.Index).Name & "!R" & ActiveCell.Row & ")-" & swacol & ")"
ActiveWorkbook.Names.Add Name:="pivotsourceorderbase", RefersToR1C1:=swaFormula (FORMULA giving error)
You are relying on the ActiveCell property. There are better ways¹ to reference cells than that but if those 'best practises can be disregarded for a minute, the ActiveCell knows what its .Parent worksheet and workbook are.
Additionally, with no actual worksheet names provided, there is no guarantee that the ActiveSheet's .Name property does not contain a space and may require ticks (e.g. ') to wrap it. Either those should be added as a matter of course or the Range.Address property should be used to generate the strings for the cell range(s).
The non-volatile INDEX function could concevably replace the volatile² OFFSET function but I don't know enough about the layout of your data to suggest an infallible substitute formula.
Dim swaFormula As String, rngName As String
Dim swaRow As Long, swaCol As Long
rngName = "pivotSourceOrderBase"
swaRow = 0: swaCol = 0
With ActiveCell
swaFormula = "=OFFSET(" & _
.Cells(1).Address(external:=True, ReferenceStyle:=xlR1C1) & _
", 0, 0, COUNTA(" & _
.Cells(1).EntireColumn.Address(external:=True, ReferenceStyle:=xlR1C1) & _
")-" & swaRow & ", COUNTA(" & _
.Cells(1).EntireRow.Address(external:=True, ReferenceStyle:=xlR1C1) & _
")-" & swaCol & ")"
Debug.Print swaFormula '<~~ check the formula in the Immediate window
On Error Resume Next 'may be needed for the next line
.Parent.Parent.Names(rngName).Delete
On Error GoTo 0
.Parent.Names.Add Name:=rngName, RefersToR1C1:=swaFormula
End With
Walk through this and check the formula in the VBE's Immediate window before attempting to apply it to the named range creation.
¹ See How to avoid using Select in Excel VBA macros for more methods on getting away from relying on select and activate to accomplish your goals.
² Volatile functions recalculate whenever anything in the entire workbook changes, not just when something that affects their outcome changes. Examples of volatile functions are INDIRECT, OFFSET, TODAY, NOW, RAND and RANDBETWEEN. Some sub-functions of the CELL and INFO worksheet functions will make them volatile as well.