-1
Option Explicit

Sub LoopThroughValidationList()
    Dim lst As Variant
    Dim rCl As Range
    Dim str As String
    Dim iX As Integer

    str = Range("B1").Validation.Formula1
    On Error GoTo exit_proc:
    If Left(str, 1) = "=" Then
        str = Right(str, Len(str) - 1)
        For Each rCl In Worksheets(Range(str).Parent.Name).Range(str).Cells
            Range("B1").Value = rCl.Value
        Next rCl
    Else
        lst = Split(str, ",")
        For iX = 0 To UBound(lst)
            Range("B1").Value = lst(iX)
        Next iX
    End If
    Exit Sub
exit_proc:
    MsgBox "No validation list ", vbCritical, "Error"
End Sub

I am tring to iterate through two data validation lists and copy a range in sheet1 to sheet2 for every iteration. This code iterates through one data validation drop down and doesn't copy the range I want in sheet1.

  1. Change data validation list1 to first item in list
  2. Change data validation list2 to first item in list
  3. Copy range from sheet1 to sheet2, first item in list + first item in list + copied range
  4. Repeat

UPDATE 2018-07-27:

Here are the formulas for my data validation list ='A. Dashboard2'!$B$1:$V$1, ='A. Dashboard'!$B$1:$V$1. And also =OFFSET('A. Dashboard'!$A$1;1;MATCH($F$4;'A. Dashboard'!$A$1:$V$1;0)-1;COUNTA(OFFSET('A. Dashboard'!$A$1;1;MATCH($F$4;'A. Dashboard'!$A$1:$V$1;0)-1;55;1));1)

Waimea
  • 71
  • 7
  • 13

1 Answers1

0

Untested, written on mobile. See if it works and whether it does what you want.

Code expects that validation list 1 will always begin with an = sign and will be a reference to a range -- and that validation list 2 is a ; delimited list.

Code expects sheets called Dashboard and Result to already exist.

Code will attempt to copy the various ranges (from Dashboard sheet) to a new row on the Result sheet for each item in the validation lists.

Option Explicit

Sub LoopThroughValidationLists()

With thisworkbook

Dim resultsRange as range 'First cell to output to'
Set resultsRange = . worksheets("Result").range("A1")

with .worksheets("Dashboard")
dim list1range as range
set list1range = .range("G3")

dim list2range as range
set list2range = .range("W3")

dim rangeToCopy1 as range
set rangeToCopy1 = .range("K9:K40")

dim rangeToCopy2 as range
set rangeToCopy2 = .range("Z9:Z40")
end with

end with

dim list1formula as string
on error resume next
list1formula = list1range.Validation.Formula1
on error goto 0

dim list2formula as string
on error resume next
list2formula =  list2range.Validation.Formula1
on error goto 0

if Len(list1formula) = 0 then
MsgBox("Validation list1 not detected.")
exit sub
elseif ASC(list1formula) <> 61 then
MsgBox("Expected list1 to begin with '='")
exit sub
elseif instrrev(list1formula,"!",-1,vbbinarycompare) > 0 then
List1formula = mid$(list1formula,instrrev(list1formula,"!",-1,vbbinarycompare)+1)
List1formula = replace(list1formula,"$",vbnullstring,1,vbbinarycompare)
End if

if Len(list2formula) = 0 then
MsgBox("Validation list2 not detected.")
exit sub
end if

dim list1items as range
on error resume next
set list1items = thisworkbook.worksheets("A. Dashboard").range(mid$(list1formula,2))
on error goto 0

if list1items is nothing then
MsgBox("Expected validation list1 to refer to a range:" & VBnewline & vbnewline & list1formula)
exit sub
end if

dim list2items() as string
list2items() = split(list2formula, ";")

if list1items.cells.count <> (ubound(list2items) +1) then
MsgBox ("Count of items in list1 is not the same as count of items in list2:" & vbnewline & vbnewline & "List1 = " & list1items.cells.count & " cells " & vbnewline & "List2 = " & (ubound(list2items) +1) & " items")
Exit sub
end if

dim cell as range
dim listIndex as long

application.calculation = xlCalculationManual
application.screenupdating = false

with resultsRange 

for each cell in list1range
list1range.value2 = cell.value2
list2range.value2 = list2items(listindex)

list1range.parent.calculate ' Sheet needs to re-calculate '

' Column 1 = list1'
' Column 2 = list2'
' Columns 3 to 34 = K9:K40'
' Columns 35 to 66 = Z9:Z40'

.offset(listindex, 0) = cell.value2 ' Value from list1'
.offset(listindex, 1) = list2items(listindex) ' Value from list2'

rangeToCopy1.copy
'below needs to appear on a new line'
.offset(listIndex, 2).pastespecial paste:=xlPasteValuesAndNumberFormats, 
transpose:=True

rangeToCopy2.copy
'below needs to appear on a new line'
.offset(listIndex, 34).pastespecial  paste:=xlPasteValuesAndNumberFormats, 
transpose:=True

listindex = listindex +1

next cell

application.calculation = xlautomatic
application.screenupdating = true

end with

End Sub
chillin
  • 4,391
  • 1
  • 8
  • 8
  • Thank you for your reply. I am overwriting the data validation lists with the value of every item in the list. This changes 100+ vlookups, sumifs och countifs based on the value of the dropdown list. After each update I would like to copy a range in sheet1 to sheet2 for every iteration of the loop. – Waimea Jul 25 '18 at 08:17
  • I can, but my code doesn't do what you've put in your edit, so no point. Where are validation lists list1 and list2 kept? In cell B1 of Sheet1 and Sheet2 respectively? – chillin Jul 25 '18 at 17:37
  • Thank you for your reply! The validation list1 and validation list2 are kept in a worksheet named Dashboard. The cell address for validation list1 is G3 and the cell address for validation list2 is W3. I would like to copy the result from Dashboard to Result worksheet. – Waimea Jul 25 '18 at 18:13
  • #1. Change value of cell D3 on Dashboard sheet to first item in cell D3's validation list, #2. Change value of cell W3 on Dashboard sheet to first item in cell W3's validation list, #3. At this point, the 100+ VLOOKUPS, SUMIFS, etc. should update/re-calculate, #4 Copy cells B1, G3, W3 from Dashboard sheet to somewhere on Result sheet. #5 Repeat for remaining values in validation list. ## Is that right? Where on the Result sheet should the copied cells go? Do you want static values only on the Result sheet? Do list1 and list2 have an equal number of items? – chillin Jul 25 '18 at 21:28
  • Thank you for your reply! That is right. I want to start from cell A1 in result sheets and copy from D3 and W3 in the Dashboards sheet and also a range from K9 to K40 and a range from Z9 to Z40 in the Dashboards. What do you mean by static or dynamic values? I am not sure how to best store the results? – Waimea Jul 26 '18 at 14:51
  • See if it's any closer to doing what you want it to do, and whether you can finish/tweak the rest as per your needs. – chillin Jul 26 '18 at 22:28
  • Thank you for your reply! I get a Compile error: Sub or Function not defined at list2range.Value2 = list2(listIndex). So I am unable to see if the code works like I wish it will. – Waimea Jul 27 '18 at 07:55
  • Sorry, that should have been `list2items`, not `list2`. Have amended the code, see how far you get now. – chillin Jul 27 '18 at 17:13
  • Thank you for the code update! I get a 424 error at rangeToCopy1.Copy.Offset(listIndex, 2).PasteSpecial XlPasteType:=xlPasteValuesAndNumberFormats, Transpose:=True – Waimea Jul 27 '18 at 17:26
  • I'm not sure how they appear on your screen but I've written them as two separate lines on mine. I've inserted a comment in between the two lines of code to make it clear. I recommend deleting all the code you have, and copy-paste the code I have provided in full. – chillin Jul 27 '18 at 17:32
  • I have deleted all the code I had and copy-paste the code you have provided. Should this line be .Offset(listIndex, 1) = list2items(listIndex) ' Value from list2' instead of .Offset(listIndex, 1) = list2(listIndex) ' Value from list2'. Also I get a compile error (Named argument not found) at XlPasteType:=xlPasteValuesAndNumberFormats, Transpose:=True. – Waimea Jul 27 '18 at 18:10
  • Yes, it should be `list2items`. I've just looked at the documentation. The argument should be `Paste`, not `xlpastetype`. Have edited code, if you want to try again. – chillin Jul 27 '18 at 18:26
  • Thank you for your time and your code. I think the code works now but I gives me an error with data validation lists. One is a normal data validation list and the other list uses OFFSET function. How is the validation range supposed to work? – Waimea Jul 27 '18 at 18:41
  • Please add both validation list formulas to your question, I'll have a look. Also, when you say 'error', could you tell me the exact messaging that you see? Thanks – chillin Jul 27 '18 at 18:49
  • I have added the formulas for my data validation lists to my question. I get an error that shows the formula. The error is from this messagebox: MsgBox("Expected validation list1 to refer to a range:" & VBnewline & vbnewline & list1formula) The list1formula shows both data validations formulas in my question. – Waimea Jul 27 '18 at 19:01
  • I have edited the code for it to handle a sheet name in the reference but I can't tell which formula is for validation list1 in your question. Is list1 meant to contain cells `$B$1:$V$1` on the `Dashboard` sheet? – chillin Jul 27 '18 at 19:51
  • Thank you for your reply! List1 contains cells $B$1:$V$1 on "A. Dashboard Sheet" Not on Dashboard sheet! It looks like cell W3 gets overwritten by the formula for the second data validation list and that the lists get different lenghts after the first loop. I get 1 line of output in Result sheet. – Waimea Jul 27 '18 at 19:59
  • If cell W3 gets overwritten by the entire formula, that would indicate that an incorrect delimiter is being given to the split function. I notice from your formulas that you use `;` instead of `,`. Does list2 also use `;` between each element? – chillin Jul 27 '18 at 20:20
  • All of my formulas uses ; instead of ,. List2 uses ; between each element. Is this what is causing the error? – Waimea Jul 27 '18 at 20:24
  • I have changed some things in the code, if you want to try again. Now the code will exit/end early if list1 and list2 do not contain the same number of items (before it would let you continue because I forgot to add something). – chillin Jul 27 '18 at 20:28
  • I have just tried the code and it says "Expected validation list1 to refer to a range: "$B$1:$V$1" which is the address of the first data validation list. Does it have to be a range? – Waimea Jul 28 '18 at 08:49
  • At the bottom of this thread there is a piece of code that works with the data validation lists that I am using, maybe you could have a look at it? https://stackoverflow.com/questions/51170356/for-each-loop-with-data-validation-lists – Waimea Jul 28 '18 at 09:10
  • Either the `$` characters aren't allowed in a `range` argument (can't remember/test right now) or `A. Dashboard` sheet doesn't exist. Have edited the code if you want to try again. – chillin Jul 28 '18 at 09:35
  • I have tried without the $ characters and there is no difference. I still get MsgBox ("Expected validation list1 to refer to a range:" & vbNewLine & vbNewLine & list1formula) with the list1formula as the first data validation drop down cell address. Thank you for continuing with the code! – Waimea Jul 28 '18 at 10:01
  • I am still interested in a solution for this problem! – Waimea Jul 31 '18 at 19:04
  • Not much more I can do. I don't have a non-work PC, so can't test it. There is also not enough information and clarity in your question for anyone to write the code in full for you -- in my opinion. – chillin Jul 31 '18 at 19:22