Recursive code to generate a parametric sweep of input valuesCleaning up and reformatting imported data in an Excel sheetCode optimization of recursive functionFilling a row with valuesFunctional FrameworkMaking a report from payroll detailsVBA Macro to generate a report of mean values for each dateK-combination recursive algorithm implementationVBA - recursive combination listing based on Excel columnsCheck employee input from shift workGenerate parentheses solution

What should be done when the theory behind a PhD thesis turns out to be wrong?

Can any number of squares sum to a square?

Is there any difference between 旅行者 and 旅人?

Is it harder to enter an atmosphere perpendicular or at an angle

What is written in this excerpt from a Manifest of Alien Passengers for the US arriving at Providence?

What is the difference between Cisco's QoS models and strategies?

What is the typical CPU utilization of idle iMac?

Why is the processor instruction called "move", not "copy"?

What is the difference between scissors and shears?

How does a virus know what component of it to mutate?

Load extra fonts with lualatex

Is concept of entropy really indispensable? Especially when the concept of potential energy can serve the purpose?

Possibly unsurprising riddle

Is there a material or method to allow "swimmable" coins?

Why choose the name "Morpheus" when it is the name of the Greek god of dreams

Reconstructed PIE grammar? Could we be able to speak in Proto-European?

Round up my number

Has there been clarification of the Random Weight Table in the Player's Handbook?

If a picture of a screen is a screenshot, what is a video of a screen?

Why doesn't the road lose its thickness to the tyre?

Who's next to me in the queue?

Probability of pushing buttons in elevator

Is harmony based on intervals rather than chords?

Are generation ships inherently implausible?



Recursive code to generate a parametric sweep of input values


Cleaning up and reformatting imported data in an Excel sheetCode optimization of recursive functionFilling a row with valuesFunctional FrameworkMaking a report from payroll detailsVBA Macro to generate a report of mean values for each dateK-combination recursive algorithm implementationVBA - recursive combination listing based on Excel columnsCheck employee input from shift workGenerate parentheses solution






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;









11















$begingroup$


I generate a set of data based off every combination of inputs. The source range that's inputs requires headers to identify the parameters. In its present state I'm not content as it's not as straightforward as I'd like it to be. Specifically the module variables can be cleaned up but I'm not seeing how.



A simple example with 2 columns



---------------------
| Column1 | Column2 |
|---------|---------|
| A | 1 |
| B | 2 |
| C | 3 |
---------------------


generates



---------------------
| Column1 | Column2 |
|---------|---------|
| A | 1 |
| A | 2 |
| A | 3 |
| B | 1 |
| B | 2 |
| B | 3 |
| C | 1 |
| C | 2 |
| C | 3 |
---------------------


Adding a 3 column input table



-------------------------------
| Column1 | Column2 | Column3 |
|---------|---------|---------|
| A | 1 | F1 |
| B | 2 | F2 |
| C | 3 | F3 |
| | | F4 |
-------------------------------


generates



-------------------------------
| Column1 | Column2 | Column3 |
|---------|---------|---------|
| A | 1 | F1 |
| A | 1 | F2 |
| A | 1 | F3 |
| A | 1 | F4 |
| A | 2 | F1 |
. . . . . . . . . . . . . . .
| C | 2 | F4 |
| C | 3 | F1 |
| C | 3 | F2 |
| C | 3 | F3 |
| C | 3 | F4 |
-------------------------------


and so on.



The class module InputColumn is used to help compartmentalize the logic for each column and its corresponding max depth being equivalent to CountOfValues.



'@PredeclaredId
'@Folder("ParametricSweep.Model")
Option Explicit

Private Type THelper
ColumnIndex As Long
Values As Variant
Identifier As String
End Type

Private this As THelper

Public Property Let Values(ByVal Value As Variant)
this.Values = Value
End Property
Public Property Get Values() As Variant
Values = this.Values
End Property

Public Property Get CountOfValues() As Long
CountOfValues = UBound(Values) - LBound(Values) + 1
End Property

Public Property Let Identifier(ByVal Value As String)
this.Identifier = Value
End Property
Public Property Get Identifier() As String
Identifier = this.Identifier
End Property

Public Function Self() As InputColumn
Set Self = Me
End Function

Public Function Create(ByVal ColumnIndex As Long, ByVal sourceArea As Range) As InputColumn
Dim populatedCells As Range
Set populatedCells = sourceArea.SpecialCells(XlCellType.xlCellTypeConstants)

With New InputColumn
.Identifier = populatedCells(1, 1).Value2
.Values = Application.WorksheetFunction.Transpose(populatedCells.Offset(1).Resize(populatedCells.Rows.Count - 1).Value2)

Set Create = .Self
End With
End Function


The sweep of values is generated by populating the inputColumns() array then stepping into PopulateArray 1 for the first (topmost) level. After the call to PopulateArray it recursively descends one level deeper until it's populating the last column. As each loop returns it increments the array recursionInputColumnPopulationIndex() that identifies which element should populated for the corresponding recursion depth.



Option Explicit

Private parentArray() As Variant
Private inputColumns() As InputColumn
Private maxRecursionDepth As Long
Private recursionInputColumnPopulationIndex() As Long
Private populationRow As Long

Public Sub TestRecursive()
Dim foo As Variant
foo = RecursiveParametricSweep(Sheet1.Range("C5").CurrentRegion, True)

Dim bar As Variant
bar = RecursiveParametricSweep(Sheet1.Range("C16").CurrentRegion, False)
End Sub

Public Function RecursiveParametricSweep(ByVal inputSourceArea As Range, ByVal includeHeader As Boolean) As Variant
maxRecursionDepth = inputSourceArea.Columns.Count

ReDim inputColumns(1 To maxRecursionDepth)
ReDim recursionInputColumnPopulationIndex(1 To maxRecursionDepth)

PopulateInputColumns inputSourceArea

Dim rowCount As Long
rowCount = GetRowCount(inputColumns)
If includeHeader Then
ReDim parentArray(0 To rowCount, 1 To maxRecursionDepth)

Dim headerRow As Long
headerRow = LBound(parentArray)
Dim headerColumn As Long
For headerColumn = LBound(inputColumns) To UBound(inputColumns)
parentArray(headerRow, headerColumn) = inputColumns(headerColumn).Identifier
Next

populationRow = LBound(parentArray) + 1
Else
ReDim parentArray(1 To rowCount, 1 To maxRecursionDepth)
populationRow = LBound(parentArray)
End If

PopulateArray 1, includeHeader
RecursiveParametricSweep = parentArray
End Function

Private Sub PopulateArray(ByVal recursionDepth As Long, ByVal includeHeader As Boolean)
Dim populateElementCount As Long
For populateElementCount = 1 To inputColumns(recursionDepth).CountOfValues
If recursionDepth < maxRecursionDepth Then
PopulateArray recursionDepth + 1, includeHeader

recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
Else
Dim columnPopulationIndex As Long
For columnPopulationIndex = recursionDepth To 1 Step -1
parentArray(populationRow, columnPopulationIndex) = inputColumns(columnPopulationIndex).Values(recursionInputColumnPopulationIndex(columnPopulationIndex) + 1)
Next

recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
populationRow = populationRow + 1
End If
Next
recursionInputColumnPopulationIndex(recursionDepth) = 0
End Sub

Private Function GetRowCount(ByRef inputColumns() As InputColumn) As Long
GetRowCount = 1
Dim depthCounter As Long
For depthCounter = LBound(inputColumns) To UBound(inputColumns)
GetRowCount = GetRowCount * inputColumns(depthCounter).CountOfValues
Next
End Function

Private Sub PopulateInputColumns(ByVal inputSourceArea As Range)
Dim populateInputColumnsCounter As Long
For populateInputColumnsCounter = LBound(inputColumns) To UBound(inputColumns)
Set inputColumns(populateInputColumnsCounter) = InputColumn.Create(populateInputColumnsCounter, inputSourceArea.Columns(populateInputColumnsCounter))
Next
End Sub
```









share|improve this question











$endgroup$





















    11















    $begingroup$


    I generate a set of data based off every combination of inputs. The source range that's inputs requires headers to identify the parameters. In its present state I'm not content as it's not as straightforward as I'd like it to be. Specifically the module variables can be cleaned up but I'm not seeing how.



    A simple example with 2 columns



    ---------------------
    | Column1 | Column2 |
    |---------|---------|
    | A | 1 |
    | B | 2 |
    | C | 3 |
    ---------------------


    generates



    ---------------------
    | Column1 | Column2 |
    |---------|---------|
    | A | 1 |
    | A | 2 |
    | A | 3 |
    | B | 1 |
    | B | 2 |
    | B | 3 |
    | C | 1 |
    | C | 2 |
    | C | 3 |
    ---------------------


    Adding a 3 column input table



    -------------------------------
    | Column1 | Column2 | Column3 |
    |---------|---------|---------|
    | A | 1 | F1 |
    | B | 2 | F2 |
    | C | 3 | F3 |
    | | | F4 |
    -------------------------------


    generates



    -------------------------------
    | Column1 | Column2 | Column3 |
    |---------|---------|---------|
    | A | 1 | F1 |
    | A | 1 | F2 |
    | A | 1 | F3 |
    | A | 1 | F4 |
    | A | 2 | F1 |
    . . . . . . . . . . . . . . .
    | C | 2 | F4 |
    | C | 3 | F1 |
    | C | 3 | F2 |
    | C | 3 | F3 |
    | C | 3 | F4 |
    -------------------------------


    and so on.



    The class module InputColumn is used to help compartmentalize the logic for each column and its corresponding max depth being equivalent to CountOfValues.



    '@PredeclaredId
    '@Folder("ParametricSweep.Model")
    Option Explicit

    Private Type THelper
    ColumnIndex As Long
    Values As Variant
    Identifier As String
    End Type

    Private this As THelper

    Public Property Let Values(ByVal Value As Variant)
    this.Values = Value
    End Property
    Public Property Get Values() As Variant
    Values = this.Values
    End Property

    Public Property Get CountOfValues() As Long
    CountOfValues = UBound(Values) - LBound(Values) + 1
    End Property

    Public Property Let Identifier(ByVal Value As String)
    this.Identifier = Value
    End Property
    Public Property Get Identifier() As String
    Identifier = this.Identifier
    End Property

    Public Function Self() As InputColumn
    Set Self = Me
    End Function

    Public Function Create(ByVal ColumnIndex As Long, ByVal sourceArea As Range) As InputColumn
    Dim populatedCells As Range
    Set populatedCells = sourceArea.SpecialCells(XlCellType.xlCellTypeConstants)

    With New InputColumn
    .Identifier = populatedCells(1, 1).Value2
    .Values = Application.WorksheetFunction.Transpose(populatedCells.Offset(1).Resize(populatedCells.Rows.Count - 1).Value2)

    Set Create = .Self
    End With
    End Function


    The sweep of values is generated by populating the inputColumns() array then stepping into PopulateArray 1 for the first (topmost) level. After the call to PopulateArray it recursively descends one level deeper until it's populating the last column. As each loop returns it increments the array recursionInputColumnPopulationIndex() that identifies which element should populated for the corresponding recursion depth.



    Option Explicit

    Private parentArray() As Variant
    Private inputColumns() As InputColumn
    Private maxRecursionDepth As Long
    Private recursionInputColumnPopulationIndex() As Long
    Private populationRow As Long

    Public Sub TestRecursive()
    Dim foo As Variant
    foo = RecursiveParametricSweep(Sheet1.Range("C5").CurrentRegion, True)

    Dim bar As Variant
    bar = RecursiveParametricSweep(Sheet1.Range("C16").CurrentRegion, False)
    End Sub

    Public Function RecursiveParametricSweep(ByVal inputSourceArea As Range, ByVal includeHeader As Boolean) As Variant
    maxRecursionDepth = inputSourceArea.Columns.Count

    ReDim inputColumns(1 To maxRecursionDepth)
    ReDim recursionInputColumnPopulationIndex(1 To maxRecursionDepth)

    PopulateInputColumns inputSourceArea

    Dim rowCount As Long
    rowCount = GetRowCount(inputColumns)
    If includeHeader Then
    ReDim parentArray(0 To rowCount, 1 To maxRecursionDepth)

    Dim headerRow As Long
    headerRow = LBound(parentArray)
    Dim headerColumn As Long
    For headerColumn = LBound(inputColumns) To UBound(inputColumns)
    parentArray(headerRow, headerColumn) = inputColumns(headerColumn).Identifier
    Next

    populationRow = LBound(parentArray) + 1
    Else
    ReDim parentArray(1 To rowCount, 1 To maxRecursionDepth)
    populationRow = LBound(parentArray)
    End If

    PopulateArray 1, includeHeader
    RecursiveParametricSweep = parentArray
    End Function

    Private Sub PopulateArray(ByVal recursionDepth As Long, ByVal includeHeader As Boolean)
    Dim populateElementCount As Long
    For populateElementCount = 1 To inputColumns(recursionDepth).CountOfValues
    If recursionDepth < maxRecursionDepth Then
    PopulateArray recursionDepth + 1, includeHeader

    recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
    Else
    Dim columnPopulationIndex As Long
    For columnPopulationIndex = recursionDepth To 1 Step -1
    parentArray(populationRow, columnPopulationIndex) = inputColumns(columnPopulationIndex).Values(recursionInputColumnPopulationIndex(columnPopulationIndex) + 1)
    Next

    recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
    populationRow = populationRow + 1
    End If
    Next
    recursionInputColumnPopulationIndex(recursionDepth) = 0
    End Sub

    Private Function GetRowCount(ByRef inputColumns() As InputColumn) As Long
    GetRowCount = 1
    Dim depthCounter As Long
    For depthCounter = LBound(inputColumns) To UBound(inputColumns)
    GetRowCount = GetRowCount * inputColumns(depthCounter).CountOfValues
    Next
    End Function

    Private Sub PopulateInputColumns(ByVal inputSourceArea As Range)
    Dim populateInputColumnsCounter As Long
    For populateInputColumnsCounter = LBound(inputColumns) To UBound(inputColumns)
    Set inputColumns(populateInputColumnsCounter) = InputColumn.Create(populateInputColumnsCounter, inputSourceArea.Columns(populateInputColumnsCounter))
    Next
    End Sub
    ```









    share|improve this question











    $endgroup$

















      11













      11









      11





      $begingroup$


      I generate a set of data based off every combination of inputs. The source range that's inputs requires headers to identify the parameters. In its present state I'm not content as it's not as straightforward as I'd like it to be. Specifically the module variables can be cleaned up but I'm not seeing how.



      A simple example with 2 columns



      ---------------------
      | Column1 | Column2 |
      |---------|---------|
      | A | 1 |
      | B | 2 |
      | C | 3 |
      ---------------------


      generates



      ---------------------
      | Column1 | Column2 |
      |---------|---------|
      | A | 1 |
      | A | 2 |
      | A | 3 |
      | B | 1 |
      | B | 2 |
      | B | 3 |
      | C | 1 |
      | C | 2 |
      | C | 3 |
      ---------------------


      Adding a 3 column input table



      -------------------------------
      | Column1 | Column2 | Column3 |
      |---------|---------|---------|
      | A | 1 | F1 |
      | B | 2 | F2 |
      | C | 3 | F3 |
      | | | F4 |
      -------------------------------


      generates



      -------------------------------
      | Column1 | Column2 | Column3 |
      |---------|---------|---------|
      | A | 1 | F1 |
      | A | 1 | F2 |
      | A | 1 | F3 |
      | A | 1 | F4 |
      | A | 2 | F1 |
      . . . . . . . . . . . . . . .
      | C | 2 | F4 |
      | C | 3 | F1 |
      | C | 3 | F2 |
      | C | 3 | F3 |
      | C | 3 | F4 |
      -------------------------------


      and so on.



      The class module InputColumn is used to help compartmentalize the logic for each column and its corresponding max depth being equivalent to CountOfValues.



      '@PredeclaredId
      '@Folder("ParametricSweep.Model")
      Option Explicit

      Private Type THelper
      ColumnIndex As Long
      Values As Variant
      Identifier As String
      End Type

      Private this As THelper

      Public Property Let Values(ByVal Value As Variant)
      this.Values = Value
      End Property
      Public Property Get Values() As Variant
      Values = this.Values
      End Property

      Public Property Get CountOfValues() As Long
      CountOfValues = UBound(Values) - LBound(Values) + 1
      End Property

      Public Property Let Identifier(ByVal Value As String)
      this.Identifier = Value
      End Property
      Public Property Get Identifier() As String
      Identifier = this.Identifier
      End Property

      Public Function Self() As InputColumn
      Set Self = Me
      End Function

      Public Function Create(ByVal ColumnIndex As Long, ByVal sourceArea As Range) As InputColumn
      Dim populatedCells As Range
      Set populatedCells = sourceArea.SpecialCells(XlCellType.xlCellTypeConstants)

      With New InputColumn
      .Identifier = populatedCells(1, 1).Value2
      .Values = Application.WorksheetFunction.Transpose(populatedCells.Offset(1).Resize(populatedCells.Rows.Count - 1).Value2)

      Set Create = .Self
      End With
      End Function


      The sweep of values is generated by populating the inputColumns() array then stepping into PopulateArray 1 for the first (topmost) level. After the call to PopulateArray it recursively descends one level deeper until it's populating the last column. As each loop returns it increments the array recursionInputColumnPopulationIndex() that identifies which element should populated for the corresponding recursion depth.



      Option Explicit

      Private parentArray() As Variant
      Private inputColumns() As InputColumn
      Private maxRecursionDepth As Long
      Private recursionInputColumnPopulationIndex() As Long
      Private populationRow As Long

      Public Sub TestRecursive()
      Dim foo As Variant
      foo = RecursiveParametricSweep(Sheet1.Range("C5").CurrentRegion, True)

      Dim bar As Variant
      bar = RecursiveParametricSweep(Sheet1.Range("C16").CurrentRegion, False)
      End Sub

      Public Function RecursiveParametricSweep(ByVal inputSourceArea As Range, ByVal includeHeader As Boolean) As Variant
      maxRecursionDepth = inputSourceArea.Columns.Count

      ReDim inputColumns(1 To maxRecursionDepth)
      ReDim recursionInputColumnPopulationIndex(1 To maxRecursionDepth)

      PopulateInputColumns inputSourceArea

      Dim rowCount As Long
      rowCount = GetRowCount(inputColumns)
      If includeHeader Then
      ReDim parentArray(0 To rowCount, 1 To maxRecursionDepth)

      Dim headerRow As Long
      headerRow = LBound(parentArray)
      Dim headerColumn As Long
      For headerColumn = LBound(inputColumns) To UBound(inputColumns)
      parentArray(headerRow, headerColumn) = inputColumns(headerColumn).Identifier
      Next

      populationRow = LBound(parentArray) + 1
      Else
      ReDim parentArray(1 To rowCount, 1 To maxRecursionDepth)
      populationRow = LBound(parentArray)
      End If

      PopulateArray 1, includeHeader
      RecursiveParametricSweep = parentArray
      End Function

      Private Sub PopulateArray(ByVal recursionDepth As Long, ByVal includeHeader As Boolean)
      Dim populateElementCount As Long
      For populateElementCount = 1 To inputColumns(recursionDepth).CountOfValues
      If recursionDepth < maxRecursionDepth Then
      PopulateArray recursionDepth + 1, includeHeader

      recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
      Else
      Dim columnPopulationIndex As Long
      For columnPopulationIndex = recursionDepth To 1 Step -1
      parentArray(populationRow, columnPopulationIndex) = inputColumns(columnPopulationIndex).Values(recursionInputColumnPopulationIndex(columnPopulationIndex) + 1)
      Next

      recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
      populationRow = populationRow + 1
      End If
      Next
      recursionInputColumnPopulationIndex(recursionDepth) = 0
      End Sub

      Private Function GetRowCount(ByRef inputColumns() As InputColumn) As Long
      GetRowCount = 1
      Dim depthCounter As Long
      For depthCounter = LBound(inputColumns) To UBound(inputColumns)
      GetRowCount = GetRowCount * inputColumns(depthCounter).CountOfValues
      Next
      End Function

      Private Sub PopulateInputColumns(ByVal inputSourceArea As Range)
      Dim populateInputColumnsCounter As Long
      For populateInputColumnsCounter = LBound(inputColumns) To UBound(inputColumns)
      Set inputColumns(populateInputColumnsCounter) = InputColumn.Create(populateInputColumnsCounter, inputSourceArea.Columns(populateInputColumnsCounter))
      Next
      End Sub
      ```









      share|improve this question











      $endgroup$




      I generate a set of data based off every combination of inputs. The source range that's inputs requires headers to identify the parameters. In its present state I'm not content as it's not as straightforward as I'd like it to be. Specifically the module variables can be cleaned up but I'm not seeing how.



      A simple example with 2 columns



      ---------------------
      | Column1 | Column2 |
      |---------|---------|
      | A | 1 |
      | B | 2 |
      | C | 3 |
      ---------------------


      generates



      ---------------------
      | Column1 | Column2 |
      |---------|---------|
      | A | 1 |
      | A | 2 |
      | A | 3 |
      | B | 1 |
      | B | 2 |
      | B | 3 |
      | C | 1 |
      | C | 2 |
      | C | 3 |
      ---------------------


      Adding a 3 column input table



      -------------------------------
      | Column1 | Column2 | Column3 |
      |---------|---------|---------|
      | A | 1 | F1 |
      | B | 2 | F2 |
      | C | 3 | F3 |
      | | | F4 |
      -------------------------------


      generates



      -------------------------------
      | Column1 | Column2 | Column3 |
      |---------|---------|---------|
      | A | 1 | F1 |
      | A | 1 | F2 |
      | A | 1 | F3 |
      | A | 1 | F4 |
      | A | 2 | F1 |
      . . . . . . . . . . . . . . .
      | C | 2 | F4 |
      | C | 3 | F1 |
      | C | 3 | F2 |
      | C | 3 | F3 |
      | C | 3 | F4 |
      -------------------------------


      and so on.



      The class module InputColumn is used to help compartmentalize the logic for each column and its corresponding max depth being equivalent to CountOfValues.



      '@PredeclaredId
      '@Folder("ParametricSweep.Model")
      Option Explicit

      Private Type THelper
      ColumnIndex As Long
      Values As Variant
      Identifier As String
      End Type

      Private this As THelper

      Public Property Let Values(ByVal Value As Variant)
      this.Values = Value
      End Property
      Public Property Get Values() As Variant
      Values = this.Values
      End Property

      Public Property Get CountOfValues() As Long
      CountOfValues = UBound(Values) - LBound(Values) + 1
      End Property

      Public Property Let Identifier(ByVal Value As String)
      this.Identifier = Value
      End Property
      Public Property Get Identifier() As String
      Identifier = this.Identifier
      End Property

      Public Function Self() As InputColumn
      Set Self = Me
      End Function

      Public Function Create(ByVal ColumnIndex As Long, ByVal sourceArea As Range) As InputColumn
      Dim populatedCells As Range
      Set populatedCells = sourceArea.SpecialCells(XlCellType.xlCellTypeConstants)

      With New InputColumn
      .Identifier = populatedCells(1, 1).Value2
      .Values = Application.WorksheetFunction.Transpose(populatedCells.Offset(1).Resize(populatedCells.Rows.Count - 1).Value2)

      Set Create = .Self
      End With
      End Function


      The sweep of values is generated by populating the inputColumns() array then stepping into PopulateArray 1 for the first (topmost) level. After the call to PopulateArray it recursively descends one level deeper until it's populating the last column. As each loop returns it increments the array recursionInputColumnPopulationIndex() that identifies which element should populated for the corresponding recursion depth.



      Option Explicit

      Private parentArray() As Variant
      Private inputColumns() As InputColumn
      Private maxRecursionDepth As Long
      Private recursionInputColumnPopulationIndex() As Long
      Private populationRow As Long

      Public Sub TestRecursive()
      Dim foo As Variant
      foo = RecursiveParametricSweep(Sheet1.Range("C5").CurrentRegion, True)

      Dim bar As Variant
      bar = RecursiveParametricSweep(Sheet1.Range("C16").CurrentRegion, False)
      End Sub

      Public Function RecursiveParametricSweep(ByVal inputSourceArea As Range, ByVal includeHeader As Boolean) As Variant
      maxRecursionDepth = inputSourceArea.Columns.Count

      ReDim inputColumns(1 To maxRecursionDepth)
      ReDim recursionInputColumnPopulationIndex(1 To maxRecursionDepth)

      PopulateInputColumns inputSourceArea

      Dim rowCount As Long
      rowCount = GetRowCount(inputColumns)
      If includeHeader Then
      ReDim parentArray(0 To rowCount, 1 To maxRecursionDepth)

      Dim headerRow As Long
      headerRow = LBound(parentArray)
      Dim headerColumn As Long
      For headerColumn = LBound(inputColumns) To UBound(inputColumns)
      parentArray(headerRow, headerColumn) = inputColumns(headerColumn).Identifier
      Next

      populationRow = LBound(parentArray) + 1
      Else
      ReDim parentArray(1 To rowCount, 1 To maxRecursionDepth)
      populationRow = LBound(parentArray)
      End If

      PopulateArray 1, includeHeader
      RecursiveParametricSweep = parentArray
      End Function

      Private Sub PopulateArray(ByVal recursionDepth As Long, ByVal includeHeader As Boolean)
      Dim populateElementCount As Long
      For populateElementCount = 1 To inputColumns(recursionDepth).CountOfValues
      If recursionDepth < maxRecursionDepth Then
      PopulateArray recursionDepth + 1, includeHeader

      recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
      Else
      Dim columnPopulationIndex As Long
      For columnPopulationIndex = recursionDepth To 1 Step -1
      parentArray(populationRow, columnPopulationIndex) = inputColumns(columnPopulationIndex).Values(recursionInputColumnPopulationIndex(columnPopulationIndex) + 1)
      Next

      recursionInputColumnPopulationIndex(recursionDepth) = recursionInputColumnPopulationIndex(recursionDepth) + 1
      populationRow = populationRow + 1
      End If
      Next
      recursionInputColumnPopulationIndex(recursionDepth) = 0
      End Sub

      Private Function GetRowCount(ByRef inputColumns() As InputColumn) As Long
      GetRowCount = 1
      Dim depthCounter As Long
      For depthCounter = LBound(inputColumns) To UBound(inputColumns)
      GetRowCount = GetRowCount * inputColumns(depthCounter).CountOfValues
      Next
      End Function

      Private Sub PopulateInputColumns(ByVal inputSourceArea As Range)
      Dim populateInputColumnsCounter As Long
      For populateInputColumnsCounter = LBound(inputColumns) To UBound(inputColumns)
      Set inputColumns(populateInputColumnsCounter) = InputColumn.Create(populateInputColumnsCounter, inputSourceArea.Columns(populateInputColumnsCounter))
      Next
      End Sub
      ```






      vba excel recursion combinatorics






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Sep 28 at 14:39









      Mathieu Guindon

      71.8k16 gold badges166 silver badges431 bronze badges




      71.8k16 gold badges166 silver badges431 bronze badges










      asked Sep 28 at 5:48









      IvenBachIvenBach

      1,9447 silver badges17 bronze badges




      1,9447 silver badges17 bronze badges























          1 Answer
          1






          active

          oldest

          votes


















          6

















          $begingroup$

          This looks like a decent recursive implementation. So, this is mainly about style and readability.



          First, I would like to talk about two things which are really hard and could use some improvement here, naming and consistency of semantic levels. Then I have some more miscellaneous comments.



          Naming



          Generally, the naming is not too bad, but some of the names are a bit misleading, e.g. the function name GetRowCount suggests that it returns the number of rows of whatever I give it. However, what it returns is the number of rows of the later output. So, one could simply call it OutputRowCount, which also follows the general guideline to use nouns that describe the return value for functions.



          Another things with the naming is that it sticks a bit much to the role of things in the implementation and not to what they are. Naming things after what they are can make understanding the code much faster. E.g. using inputColumnIndex instead of recursionDepth would immediately tell the reader that you are dealing with this specific input column right now. Then the technical maxRecursionDepth could also be lastColumnIndex or countOfColumns. Similarly, the rather ominous recursionInputColumnPopulationIndex(recursionDepth) could be currentInputIndex(inputColumnIndex). So generally, my advice would be to name things after what they are and not their implementation purpose.



          Consistency of Semantic Levels



          Programmers, me included, are notoriously bad a keeping semantic levels consistent in procedures. To explain what I mean take a look at RecursiveParametricSweep. It does some high level orchestration like calling the procedure to populate the input columns, calling a function to get the number of output rows, calling the procedure to populate the output array and assigning the return value. However, in between it goes into the detail of how to handle headers. This is a break in semantic level of the procedure that throws one off a bit when first reading the procdure. This could be avoided by extracting either an InitializeOutputArray or a WriteHeaders procedure.



          Miscellaneous



          • The global variable maxRecursionDepth is a bit superfluous since it is just UBound(inputColumns), which is a bit clearer semantically, I think.

          • Instead of incrementing recursionInputColumnPopulationIndex(recursionDepth), you could just always set it to populateElementCount at the start of the loop, which might be called currentInputIndex instead.

          • Istead of keeping track of the indeces for the columns in an array, you might just as well keep track of the values in an array instead. That would put the choice of value closer to the action for the specific column.

          • It looks a bit strange to have the populationRow counter as a module level variable. You could avoid this by passing it ByRef into the recursive procedure.

          • It might make sense to extract a PopulateRow procedure to keep semantic levels consitsent.





          share|improve this answer










          $endgroup$















            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );














            draft saved

            draft discarded
















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f229781%2frecursive-code-to-generate-a-parametric-sweep-of-input-values%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown


























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            6

















            $begingroup$

            This looks like a decent recursive implementation. So, this is mainly about style and readability.



            First, I would like to talk about two things which are really hard and could use some improvement here, naming and consistency of semantic levels. Then I have some more miscellaneous comments.



            Naming



            Generally, the naming is not too bad, but some of the names are a bit misleading, e.g. the function name GetRowCount suggests that it returns the number of rows of whatever I give it. However, what it returns is the number of rows of the later output. So, one could simply call it OutputRowCount, which also follows the general guideline to use nouns that describe the return value for functions.



            Another things with the naming is that it sticks a bit much to the role of things in the implementation and not to what they are. Naming things after what they are can make understanding the code much faster. E.g. using inputColumnIndex instead of recursionDepth would immediately tell the reader that you are dealing with this specific input column right now. Then the technical maxRecursionDepth could also be lastColumnIndex or countOfColumns. Similarly, the rather ominous recursionInputColumnPopulationIndex(recursionDepth) could be currentInputIndex(inputColumnIndex). So generally, my advice would be to name things after what they are and not their implementation purpose.



            Consistency of Semantic Levels



            Programmers, me included, are notoriously bad a keeping semantic levels consistent in procedures. To explain what I mean take a look at RecursiveParametricSweep. It does some high level orchestration like calling the procedure to populate the input columns, calling a function to get the number of output rows, calling the procedure to populate the output array and assigning the return value. However, in between it goes into the detail of how to handle headers. This is a break in semantic level of the procedure that throws one off a bit when first reading the procdure. This could be avoided by extracting either an InitializeOutputArray or a WriteHeaders procedure.



            Miscellaneous



            • The global variable maxRecursionDepth is a bit superfluous since it is just UBound(inputColumns), which is a bit clearer semantically, I think.

            • Instead of incrementing recursionInputColumnPopulationIndex(recursionDepth), you could just always set it to populateElementCount at the start of the loop, which might be called currentInputIndex instead.

            • Istead of keeping track of the indeces for the columns in an array, you might just as well keep track of the values in an array instead. That would put the choice of value closer to the action for the specific column.

            • It looks a bit strange to have the populationRow counter as a module level variable. You could avoid this by passing it ByRef into the recursive procedure.

            • It might make sense to extract a PopulateRow procedure to keep semantic levels consitsent.





            share|improve this answer










            $endgroup$


















              6

















              $begingroup$

              This looks like a decent recursive implementation. So, this is mainly about style and readability.



              First, I would like to talk about two things which are really hard and could use some improvement here, naming and consistency of semantic levels. Then I have some more miscellaneous comments.



              Naming



              Generally, the naming is not too bad, but some of the names are a bit misleading, e.g. the function name GetRowCount suggests that it returns the number of rows of whatever I give it. However, what it returns is the number of rows of the later output. So, one could simply call it OutputRowCount, which also follows the general guideline to use nouns that describe the return value for functions.



              Another things with the naming is that it sticks a bit much to the role of things in the implementation and not to what they are. Naming things after what they are can make understanding the code much faster. E.g. using inputColumnIndex instead of recursionDepth would immediately tell the reader that you are dealing with this specific input column right now. Then the technical maxRecursionDepth could also be lastColumnIndex or countOfColumns. Similarly, the rather ominous recursionInputColumnPopulationIndex(recursionDepth) could be currentInputIndex(inputColumnIndex). So generally, my advice would be to name things after what they are and not their implementation purpose.



              Consistency of Semantic Levels



              Programmers, me included, are notoriously bad a keeping semantic levels consistent in procedures. To explain what I mean take a look at RecursiveParametricSweep. It does some high level orchestration like calling the procedure to populate the input columns, calling a function to get the number of output rows, calling the procedure to populate the output array and assigning the return value. However, in between it goes into the detail of how to handle headers. This is a break in semantic level of the procedure that throws one off a bit when first reading the procdure. This could be avoided by extracting either an InitializeOutputArray or a WriteHeaders procedure.



              Miscellaneous



              • The global variable maxRecursionDepth is a bit superfluous since it is just UBound(inputColumns), which is a bit clearer semantically, I think.

              • Instead of incrementing recursionInputColumnPopulationIndex(recursionDepth), you could just always set it to populateElementCount at the start of the loop, which might be called currentInputIndex instead.

              • Istead of keeping track of the indeces for the columns in an array, you might just as well keep track of the values in an array instead. That would put the choice of value closer to the action for the specific column.

              • It looks a bit strange to have the populationRow counter as a module level variable. You could avoid this by passing it ByRef into the recursive procedure.

              • It might make sense to extract a PopulateRow procedure to keep semantic levels consitsent.





              share|improve this answer










              $endgroup$
















                6















                6











                6







                $begingroup$

                This looks like a decent recursive implementation. So, this is mainly about style and readability.



                First, I would like to talk about two things which are really hard and could use some improvement here, naming and consistency of semantic levels. Then I have some more miscellaneous comments.



                Naming



                Generally, the naming is not too bad, but some of the names are a bit misleading, e.g. the function name GetRowCount suggests that it returns the number of rows of whatever I give it. However, what it returns is the number of rows of the later output. So, one could simply call it OutputRowCount, which also follows the general guideline to use nouns that describe the return value for functions.



                Another things with the naming is that it sticks a bit much to the role of things in the implementation and not to what they are. Naming things after what they are can make understanding the code much faster. E.g. using inputColumnIndex instead of recursionDepth would immediately tell the reader that you are dealing with this specific input column right now. Then the technical maxRecursionDepth could also be lastColumnIndex or countOfColumns. Similarly, the rather ominous recursionInputColumnPopulationIndex(recursionDepth) could be currentInputIndex(inputColumnIndex). So generally, my advice would be to name things after what they are and not their implementation purpose.



                Consistency of Semantic Levels



                Programmers, me included, are notoriously bad a keeping semantic levels consistent in procedures. To explain what I mean take a look at RecursiveParametricSweep. It does some high level orchestration like calling the procedure to populate the input columns, calling a function to get the number of output rows, calling the procedure to populate the output array and assigning the return value. However, in between it goes into the detail of how to handle headers. This is a break in semantic level of the procedure that throws one off a bit when first reading the procdure. This could be avoided by extracting either an InitializeOutputArray or a WriteHeaders procedure.



                Miscellaneous



                • The global variable maxRecursionDepth is a bit superfluous since it is just UBound(inputColumns), which is a bit clearer semantically, I think.

                • Instead of incrementing recursionInputColumnPopulationIndex(recursionDepth), you could just always set it to populateElementCount at the start of the loop, which might be called currentInputIndex instead.

                • Istead of keeping track of the indeces for the columns in an array, you might just as well keep track of the values in an array instead. That would put the choice of value closer to the action for the specific column.

                • It looks a bit strange to have the populationRow counter as a module level variable. You could avoid this by passing it ByRef into the recursive procedure.

                • It might make sense to extract a PopulateRow procedure to keep semantic levels consitsent.





                share|improve this answer










                $endgroup$



                This looks like a decent recursive implementation. So, this is mainly about style and readability.



                First, I would like to talk about two things which are really hard and could use some improvement here, naming and consistency of semantic levels. Then I have some more miscellaneous comments.



                Naming



                Generally, the naming is not too bad, but some of the names are a bit misleading, e.g. the function name GetRowCount suggests that it returns the number of rows of whatever I give it. However, what it returns is the number of rows of the later output. So, one could simply call it OutputRowCount, which also follows the general guideline to use nouns that describe the return value for functions.



                Another things with the naming is that it sticks a bit much to the role of things in the implementation and not to what they are. Naming things after what they are can make understanding the code much faster. E.g. using inputColumnIndex instead of recursionDepth would immediately tell the reader that you are dealing with this specific input column right now. Then the technical maxRecursionDepth could also be lastColumnIndex or countOfColumns. Similarly, the rather ominous recursionInputColumnPopulationIndex(recursionDepth) could be currentInputIndex(inputColumnIndex). So generally, my advice would be to name things after what they are and not their implementation purpose.



                Consistency of Semantic Levels



                Programmers, me included, are notoriously bad a keeping semantic levels consistent in procedures. To explain what I mean take a look at RecursiveParametricSweep. It does some high level orchestration like calling the procedure to populate the input columns, calling a function to get the number of output rows, calling the procedure to populate the output array and assigning the return value. However, in between it goes into the detail of how to handle headers. This is a break in semantic level of the procedure that throws one off a bit when first reading the procdure. This could be avoided by extracting either an InitializeOutputArray or a WriteHeaders procedure.



                Miscellaneous



                • The global variable maxRecursionDepth is a bit superfluous since it is just UBound(inputColumns), which is a bit clearer semantically, I think.

                • Instead of incrementing recursionInputColumnPopulationIndex(recursionDepth), you could just always set it to populateElementCount at the start of the loop, which might be called currentInputIndex instead.

                • Istead of keeping track of the indeces for the columns in an array, you might just as well keep track of the values in an array instead. That would put the choice of value closer to the action for the specific column.

                • It looks a bit strange to have the populationRow counter as a module level variable. You could avoid this by passing it ByRef into the recursive procedure.

                • It might make sense to extract a PopulateRow procedure to keep semantic levels consitsent.






                share|improve this answer













                share|improve this answer




                share|improve this answer










                answered Sep 28 at 8:55









                M.DoernerM.Doerner

                1,1614 silver badges9 bronze badges




                1,1614 silver badges9 bronze badges































                    draft saved

                    draft discarded















































                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f229781%2frecursive-code-to-generate-a-parametric-sweep-of-input-values%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown









                    Popular posts from this blog

                    Tamil (spriik) Luke uk diar | Nawigatjuun

                    Align equal signs while including text over equalitiesAMS align: left aligned text/math plus multicolumn alignmentMultiple alignmentsAligning equations in multiple placesNumbering and aligning an equation with multiple columnsHow to align one equation with another multline equationUsing \ in environments inside the begintabularxNumber equations and preserving alignment of equal signsHow can I align equations to the left and to the right?Double equation alignment problem within align enviromentAligned within align: Why are they right-aligned?

                    Where does the image of a data connector as a sharp metal spike originate from?Where does the concept of infected people turning into zombies only after death originate from?Where does the motif of a reanimated human head originate?Where did the notion that Dragons could speak originate?Where does the archetypal image of the 'Grey' alien come from?Where did the suffix '-Man' originate?Where does the notion of being injured or killed by an illusion originate?Where did the term “sophont” originate?Where does the trope of magic spells being driven by advanced technology originate from?Where did the term “the living impaired” originate?