Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I think the problem is that data validation dialog only accepts the following "lists":</p> <ul> <li><p>an actual list of things entered directly into the Source field</p></li> <li><p>a literal range reference (like $Q$42:$Q$50)</p></li> <li><p>a named formula that itself resolves to a range reference</p></li> </ul> <p>That last one is key - there is no way to have a VBA function just return an array that can be used for validation, even if you call it from a named formula.</p> <p>You <em>can</em> write a VBA function that returns a range reference, though, and call <em>that</em> from a named formula. This can be useful as part of the following technique that approximates the ability to do what you actually want.</p> <p>First, have an actual range somewhere that calls your arbitrary-array-returning VBA UDF. Say you had this function:</p> <pre><code>Public Function validationList(someArg, someOtherArg) 'Pretend this got calculated somehow based on the above args... validationList = Array("a", "b", "c") End Function </code></pre> <p>And you called it from $Q$42:$Q$50 as an array formula. You'd get three cells with "a", "b", and "c" in them, and the rest of the cells would have #N/A errors because the returned array was smaller than the range that called the UDF. So far so good.</p> <p>Now, have another VBA UDF that returns just the "occupied" part of a range, ignoring the #N/A error cells:</p> <pre><code>Public Function extractSeq(rng As Range) 'On Error GoTo EH stuff omitted... 'Also omitting validation - is range only one row or column, etc. Dim posLast As Long For posLast = rng.Count To 1 Step -1 If Not IsError(rng(posLast)) Then Exit For End If If rng(posLast) &lt;&gt; CVErr(xlErrNA) Then Exit For End If Next posLast If posLast &lt; 1 Then extractSeq = CVErr(xlErrRef) Else Set extractSeq = Range(rng(1), rng(posLast)) End If End Function </code></pre> <p>You can then call this from a named formula like so:</p> <pre><code>=extractSeq($Q$42:$Q$50) </code></pre> <p>and the named formula will return a range reference that Excel will accept an allowable validation list. Clunky, but side-effect free!</p> <p>Note the use of the keyword 'Set' in the above code. It's not clear from your question, but this might be the only part of this whole answer that matters to you. If you don't use 'Set' when trying to return a range reference, VBA will instead return the <em>value</em> of the range, which can't be used as a validation list.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload