I have an array that plots data to a messagebox, how can I also have that same data on a different sheet?
The data I am working with is a linear cable cut list. It looks at the total cable length and the individual lengths and checks to see how many reels of cable I need for all the separate individual lengths.
Ideally Reel 1 lengths would go in column A and the next reel would be column B, so on and so forth with a blank column in between the different cable types.
'Message Box Output
For k = LBound(DetStk, 2) To UBound(DetStk, 2)
sMsg = sMsg & DetStk(1, k) & vbTab & vbTab _
& DetStk(0, k) & vbCrLf
Next k
THIS IS WHAT I GOT WORKING WITH HELP FROM "Splintered-Origins-Dev"
'Sheet Output
n = 3
q = rC + p - 6
For k = LBound(DetStk, 2) To UBound(DetStk, 2)
If k - 1 >= LBound(DetStk, 2) Then
If DetStk(0, k - 1) <> DetStk(0, k) Then
'Data line reset
n = 3
p = p + 1
q = rC + p - 6
wsVG.Cells(1, q).Value2 = cblType
wsVG.Cells(2, q).Value2 = DetStk(0, k) & " Reels"
End If
Else
wsVG.Cells(1, q).Value2 = cblType
wsVG.Cells(2, q).Value2 = DetStk(0, k) & " Reels"
End If
wsVG.Cells(n, q).Value2 = DetStk(1, k)
n = n + 1
Next k
It's not pretty or elegant, but the following code will allow you to output the data going to your message box to a new sheet "Reel Data". Just replace "loopvar" with whatever variable you're using to iterate through each loop. Additionally the "- 1" in the q variable for columns may or may not be needed depending on how your loop variable is set up. I also recommend adding someplace at the beginning of the sub Worksheets("Reel Data").Cells.Clear to wipe out any old data left behind by previous runs and p = 0 to reset the column counter.
n = 3 'Row
q = *loopvar* + p - 1 'Column
For k = LBound(DetStk, 2) To UBound(DetStk, 2)
If k - 1 >= LBound(DetStk, 2) Then 'If reel count changes, move over a column
If DetStk(0, k - 1) <> DetStk(0, k) Then
n = 3 'Row reset
p = p + 1 'Increment Column
q = *loopvar* + p - 1
Worksheets("Reel Data").Cells(2, q).Value2 = DetStk(0, k)
End If
Else
Worksheets("Reel Data").Cells(2, q).Value2 = DetStk(0, k) 'First Reel
End If
Worksheets("Reel Data").Cells(n, q).Value2 = DetStk(1, k)
n = n + 1 ' Increment Row
Next k
p = p + 1 'This will add an extra column before the next iteration
DetStk Array's 2 rows an k colunms . so You should switch the matrix to make it easier to see.
From
'Message Box Output
For k = LBound(DetStk, 2) To UBound(DetStk, 2)
sMsg = sMsg & DetStk(1, k) & vbTab & vbTab _
& DetStk(0, k) & vbCrLf
Next k
to
'Sheet Output
Sheets.Add
Range("a1").Resize(UBound(DetStk, 2) + 1, UBound(DetStk, 1) + 1) = WorksheetFunction.Transpose(DetStk)
Related
need to create a list in excel for all possible combinations (unique): Let say there are 5 buttons (e.g A B C D E) and 3 are selected. For any single combination, any selected button can't be repeated in that combination.
I should get 60 unique combinations ( 5 1 ) * ( 4 1 ) * ( 3 1 ) = 60. I need to create this list in excel.
e.g have A B C D E buttons. 3 buttons combinations: A B C; C B A; D A C; C D A; A D C; etc.
By "unique" I assume that you want to exclude things like AAD or ABB.
Consider:
Option Explicit
Sub Kombos()
Dim arr(1 To 5) As String
Dim brr(1 To 5) As String
Dim i As Long, j As Long, k As Long
Dim N As Long, V As String
arr(1) = "A"
arr(2) = "B"
arr(3) = "C"
arr(4) = "D"
arr(5) = "E"
N = 1
For i = 1 To 3
For j = i + 1 To 4
For k = j + 1 To 5
Cells(1, N) = arr(i) & arr(j) & arr(k)
N = N + 1
Next k
Next j
Next i
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
For i = 1 To 10
V = Cells(1, i).Value
brr(1) = Left(V, 1)
brr(2) = Mid(V, 2, 1)
brr(3) = Right(V, 1)
Cells(2, i) = brr(1) & brr(3) & brr(2)
Cells(3, i) = brr(2) & brr(1) & brr(3)
Cells(4, i) = brr(2) & brr(3) & brr(1)
Cells(5, i) = brr(3) & brr(1) & brr(2)
Cells(6, i) = brr(3) & brr(2) & brr(1)
Next i
End Sub
Each column is a different combination of 5 elements taken 3 at a time. (10 columns)
The rows below the first row list the various permutations of the column header.
I'm creating a program to randomly assign volunteers to different positions. There are 8 different spots on each date that need to be assigned to different volunteers. I have the code working except I can't seem to figure out how to get rid of duplicates. I added some code that prevents two spots in a row from being duplicates but that's as far as I got.
This is what the sheet looks like: (Notice that on the first date Connor Reilley is listed for two spots of the same position and Pierce Lewin is signed up for two different positions. That has to be changed).
Here is my code:
For j = 2 To jRows
Assign:
If wksCal.Range("C" & j) = "1st Reader" Or wksCal.Range("C" & j) = "2nd Reader" Then
Lector:
iRand = Int((iRows - 2) * Rnd())
If strLec(iRand) = "" Then
GoTo Assign
End If
wksCal.Range("D" & j) = strLec(iRand)
If wksCal.Range("D" & j) = wksCal.Range("D" & j - 1) Then
GoTo Lector
End If
ElseIf wksCal.Range("C" & j) = "EM" Then
EM:
iRand = Int((iRows - 2) * Rnd())
If strEM(iRand) = "" Then
GoTo Assign
End If
wksCal.Range("D" & j) = strEM(iRand)
If wksCal.Range("D" & j) = wksCal.Range("D" & j - 1) Then
GoTo EM
End If
ElseIf wksCal.Range("C" & j) = "Altar Server" Then
Server:
iRand = Int((iRows - 2) * Rnd())
If strAS(iRand) = "" Then
GoTo Assign
End If
wksCal.Range("D" & j) = strAS(iRand)
If wksCal.Range("D" & j) = wksCal.Range("D" & j - 1) Then
GoTo Server
End If
End If
Next j
a suggestion about how to manage the list of volunteers
With wkscal
Dim a()
ReDim a(irows) ' volunteers index list
For s = 1 To 3 ' 3 dates to fill
With .Cells((s - 1) * 8 + 1, 1)
' fill volunteers index list
For i = 1 To irows
a(i) = i
Next
'
For i = 1 To 8 '8 positions to fill per date
'choose an index in the list of remaining valid index
q = Application.RandBetween(1, irows - i + 1)
.Range("D" & i) = strlec(a(q))
' remove the last chosen index from the list
a(q) = a(irows - i + 1)
Next i
End With
Next s
End With
Could someone explain what is happening here? Preferably line for line. I am having a hard time wrapping my head around what is happening with this bit.
a = Application.Transpose(a)
For i = 1 To UBound(a, 2)
If UCase(a(1, i)) Like "*" & temp & "*" Or _
UCase(a(2, i)) Like "*" & temp & "*" Then
n = n + 1
For ii = 1 To UBound(a, 1)
a(ii, n) = a(ii, i)
Next
End If
Next
I am also experiencing a "type mismatch" error for the above. See full Sub below.
Private Sub TextBox_Search_Change()
Select Case True
Case OptionButton_User_Name.Value
Dim a, i As Long, ii As Long, n As Long, temp As String
If Len(Me.TextBox_Search.Value) Then
temp = UCase(Me.TextBox_Search.Value)
With Sheets("ToolData")
a = Union(.Range("B:B"), .Range("F:F"), .Range("G:G")).Value
End With
a = Application.Transpose(a)
For i = 1 To UBound(a, 2)
If UCase(a(1, i)) Like "*" & temp & "*" Or _
UCase(a(2, i)) Like "*" & temp & "*" Then
n = n + 1
For ii = 1 To UBound(a, 1)
a(ii, n) = a(ii, i)
Next
End If
Next
If n > 0 Then
ReDim Preserve a(1 To UBound(a, 1), 1 To n)
Me.ListBox_History.Column = a
End If
Else
With Sheets("ToolData")
Me.ListBox_History.List = Union(.Range("B:B"), .Range("F:F"), .Range("G:G")).Value
End With
End If
Case Else
End Select
You cannot use .Value on a multi-area range: you will only get values from the first column (B).
I would refactor the True portion of your If statement as
temp = UCase(Me.TextBox_Search.Value)
Dim rngValues As Variant
With Sheets("ToolData")
rngValues = .Range("B2", .Range("B" & .Rows.Count).End(xlUp)).Resize(, 6).Value
End With
For i = 1 To UBound(rngValues, 1)
'Check columns B & F for matching values
If UCase(rngValues(i, 1)) Like "*" & temp & "*" Or _
UCase(rngValues(i, 5)) Like "*" & temp & "*" Then
'Store columns B, F & G for displaying in the ListBox
n = n + 1
ReDim Preserve a(1 To 3, 1 To n)
a(1, n) = rngValues(i, 1)
a(2, n) = rngValues(i, 5)
a(3, n) = rngValues(i, 6)
End If
Next
'If anything found, replace the ListBox contents. Otherwise leave it as it was.
If n > 0 Then
Me.ListBox_History.Column = a
End If
thus getting rid of the code which is reading into memory all 1048576 rows of your sheet, and the need of the Transpose (which won't work on large volumes of data).
You will also need to change the False leg of your If, perhaps in a similar fashion.
I have the following VBA which is working fine
Worksheets(d).Cells(x, 5).Value = Application.WorksheetFunction.Max(Range("Data!E3:E7"))
This method should be nested in a FOR function such as
For i = 3 To j
Worksheets(d).Cells(x, 5).Value = Application.WorksheetFunction.Max(Range("Data!E3:E5"))
x = x + 1
Next
How can I parse the E3 and E7to be parameter based according to i meaning
E3 = "E" + i
E5 = "E" + i + 2
full example of what I'm trying:
For i = 3 To j
Worksheets(d).Cells(x, 5).Value = Application.WorksheetFunction.Max(Range("Data!E" + i + ":E" + i+2 +"))
x = x + 1
Next
Try
Sheets("Data").Range("E" & i & ":E" & (i + 2))
& is better than + in combining data of various types into a string. Also -- Range is a child of WorkSheet -- so you need to go through the appropriate Sheet object
Note that you can do this directly without a loop
As formula
Worksheets(d).Cells(x, 5).Resize(J - 3 + 1, 1).FormulaR1C1 = "=MAX(Data!R[1]C5:R[" & J - 3 + 1 & "]C5)"
As values
Worksheets(d).Cells(x, 5).Resize(J - 3 + 1, 1).Value = "=MAX(Data!R[1]C5:R[" & J - 3 + 1 & "]C5)"
I need to track a person in a data sheet to determine from which location to which location the person moved.
If a person appears more then one time in Column J that means the person has changed the location and the location value is in Column L. For this I have the following code:
=IF(J18=J19;IF(COUNTIF(J:J;J18)>1; "From "&L18 &" to "& IF(J18=J19;L19;"");"");"")
The problem is if the person changes the location more than two times. In Column O to Column AA I have the months of the year which determines the location of the person.
How can I modify this code to do the above:
=IF(J18=J19;IF(COUNTIF(J:J;J18)>1; "From "&L18 &" to "& IF(J18=J19;L19;"");"");"")
Here is a User Defined Function (aka UDF) to accomplish the task.
Function my_Travels(nm As Range, loc As Range, cal As Range)
Dim n As Long, cnt As Long, v As Long, vLOCs As Variant, vTMPs As Variant
Dim iLOC As Long, sTMP As String
my_Travels = vbNullString '"no travels"
cnt = Application.CountIf(nm.EntireColumn, nm(1))
If Application.CountIf(nm, nm(1)) = cnt And cnt > 1 Then
Set loc = loc.Rows(1).Resize(nm.Rows.Count, loc.Columns.Count)
Set cal = cal.Rows(1).Resize(nm.Rows.Count, cal.Columns.Count)
'seed the array
ReDim vLOCs(1 To cnt, 1 To cnt)
For v = LBound(vLOCs, 1) To UBound(vLOCs, 1)
vLOCs(v, 1) = cal.Columns.Count + 1
vLOCs(v, 2) = cal.Columns.Count + 1
Next v
'collect the values into the array
For n = 1 To nm.Rows.Count
If nm.Cells(n, 1).Value2 = nm.Cells(1, 1).Value2 Then
iLOC = Application.Match(1, Application.Index(cal, n, 0), 0)
For v = LBound(vLOCs, 1) To UBound(vLOCs, 1)
If vLOCs(v, 1) = cal.Columns.Count + 1 Then
vLOCs(v, 1) = iLOC
vLOCs(v, 2) = n
Exit For
End If
Next v
End If
Next n
'sort the values in the array
For v = LBound(vLOCs, 1) To (UBound(vLOCs, 1) - 1)
For n = (v + 1) To UBound(vLOCs, 1)
If vLOCs(v, 1) > vLOCs(n, 1) Then
vTMPs = Array(vLOCs(v, 1), vLOCs(v, 2))
vLOCs(v, 1) = vLOCs(n, 1)
vLOCs(v, 2) = vLOCs(n, 2)
vLOCs(n, 1) = vTMPs(0)
vLOCs(n, 2) = vTMPs(1)
Exit For
End If
Next n
Next v
'concatenate the locations from the array
For v = LBound(vLOCs) To (UBound(vLOCs) - 1)
sTMP = sTMP & "From " & loc.Cells(vLOCs(v, 2), 1) & " to " & loc.Cells(vLOCs(v + 1, 2), 1) & "; "
Next v
'truncate the string and return it
sTMP = Left(sTMP, Len(sTMP) - 2)
my_Travels = sTMP
End If
End Function
The Locations and the Calendar cells only need to be defined by the first row. Each has its height (i.e. rows) redefined to maintain consistency with the list of names.
In AB2 (as above) the formula is,
=my_Travels(J2:J$8, L2, O2:AA2)
Fill down as necessary.