Advertisement
AlanElston

Phil Turd

Feb 3rd, 2019
336
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Option Explicit
  2. 'Private Sub Worksheet_Change(ByVal Target As Range)
  3. '    If Range("A1") < "Filters" Then Exit Sub
  4. '    If Target Is Nothing Then Exit Sub
  5. '    If Target.Cells.Count > 1 Then Exit Sub
  6. '    If Target.Column = 1 Then Filtering Target
  7. 'End Sub
  8. '
  9. 'Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  10. '    If Range("A1") < "Filters" Then Exit Sub
  11. '    If Target Is Nothing Then Exit Sub
  12. '    If Target.Column <> 1 Then Exit Sub
  13. '    If Target.Cells.Count > 1 Then Exit Sub
  14. '    If Target.Value = "" Then Exit Sub
  15. '    Filtering Target
  16. 'End Sub
  17. Sub test()
  18.  Let Application.EnableEvents = True
  19.  Call Worksheet_SelectionChange(Me.Range("A3"))
  20.  Let Application.EnableEvents = True
  21. End Sub
  22. ' =DataSaladinValagationLists!A2:A3
  23.  
  24.  
  25.  
  26. Private Sub Worksheet_SelectionChange(ByVal Target As Range) ' for initial making of list for drop down
  27.    If IsArray(Target.Value) Then Exit Sub
  28. Rem 1 main worksheet data range info
  29. Dim CntItms As Long: Let CntItms = Me.Range("B" & Rows.Count & "").End(xlUp).Row
  30.     If Application.Intersect(Target, Me.Range("A2:A" & CntItms & "")) Is Nothing Then Exit Sub ' only do anything for a selection in the A column range.
  31.    If Worksheets("DataSaladinValagationLists").Range("A" & Target.Row & "").Value <> "" Then Exit Sub ' We already have made a drop down list - only does anything if there is not already a range of ordered values needed to fill the drop down list for the selected row
  32. Dim CntClms As Long: Let CntClms = Me.Cells.Item(1, Columns.Count).End(xlToLeft).Column
  33. Rem 2 make drop down list for this row
  34. ' 2a) get unique list of all values in row
  35. Let Application.EnableEvents = False
  36.  Me.Range("C" & Target.Row & "", Me.Cells.Item(Target.Row, CntClms)).SpecialCells(xlCellTypeConstants).Copy ' The range of data for that row is copied to the clipboard, excluding empty cells
  37. Let Application.EnableEvents = True
  38. Dim Dtaobj As Object '  Late Binding equivalent'   If you declare a variable as Object, you are late binding it.  http://excelmatters.com/2013/09/23/vba-references-and-early-binding-vs-late-binding/
  39. Set Dtaobj = GetObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}") ' http://excelmatters.com/2013/10/04/late-bound-msforms-dataobject/       http://www.eileenslounge.com/viewtopic.php?f=30&t=31547#p244124
  40. Dtaobj.GetFromClipboard: Dim strClip As String: Let strClip = Dtaobj.GetText()
  41.  Let strClip = Left(strClip, Len(strClip) - 2) ' Take off last vbCr & vbLf
  42. Application.CutCopyMode = False ' Clear clipboard, stop screen flicker
  43. Dim strSptInDrpPlop() As String: Let strSptInDrpPlop() = Split(strClip, vbTab, -1, vbBinaryCompare) ' a row in Excel is held as a string with a vbTab as seperator. The array made here may contain duplicated cell values
  44. Dim UnEeks As String ' this string will have unique cell values only
  45. Dim Cnt As Long
  46.     For Cnt = 0 To UBound(strSptInDrpPlop())
  47.      If InStr(1, UnEeks, Trim(strSptInDrpPlop(Cnt)), vbBinaryCompare) = 0 And Not Trim(strSptInDrpPlop(Cnt)) = "" And Not strSptInDrpPlop(Cnt) = vbTab Then ' I am not sure yet if the last check is needed.
  48.      Let UnEeks = UnEeks & Trim(strSptInDrpPlop(Cnt)) & " " ' A similar string to the original retrieved from the clipboard  strClip  is made with the difference that the seperator is a space and we have no duplicated cell values
  49.     Else
  50.      End If
  51.     Next Cnt
  52. 'Let UnEeks = Replace(UnEeks, vbTab, "", 1, -1, vbBinaryCompare) 'remove rogue vbtabs
  53. Let UnEeks = Left(UnEeks, Len(UnEeks) - 1) ' take off last " "                                             ' Left(UnEeks, Len(UnEeks) - 3) ' take off " " & vbCr & vbLf
  54. 'Let UnEeks = "-" & " " & UnEeks & "Blanks"
  55. Let strSptInDrpPlop() = Split(UnEeks, " ", -1, vbBinaryCompare) ' Replace the 1 Dimensional array  values with only unique values
  56. ' 2b) sort list ( Bubble sort )
  57. Dim Eye As Long, Jay As Long
  58.     For Eye = 0 To UBound(strSptInDrpPlop()) - 1 'I want to take the next in the array, starting at the first. The process below should result in the smallest being put at this position, because I go through the rest , the inner Jay loop, and when ever i find something smaller i swap so the smalles comes here
  59.       For Jay = Eye + 1 To UBound(strSptInDrpPlop()) ' I now go through comparing with each of the rest, the Jays
  60.           If IsNumeric(strSptInDrpPlop(Eye)) And IsNumeric(strSptInDrpPlop(Jay)) Then ' This is to overcome an extra problem that I have: I have strings, and VBA thinks that "6" is bigger than "35" but it thinks  6  is  less than   35
  61.                If CLng(strSptInDrpPlop(Eye)) > CLng(strSptInDrpPlop(Jay)) Then ' This means that I am bigger than the next. So I will swap . I keep doing this which will have the effect of putting the smallest in the current Eye. By the next Eye, I miss out the last, and any previous, which means I effectively do the same which puts the next smallest in this next Eye
  62.                Dim Temp As String: Let Temp = strSptInDrpPlop(Jay): Let strSptInDrpPlop(Jay) = strSptInDrpPlop(Eye): Let strSptInDrpPlop(Eye) = Temp
  63.                 Else
  64.                 End If
  65.            Else ' if we have text, then VBA still allows a comparison to sort - like B > A returns True
  66.                If strSptInDrpPlop(Eye) > strSptInDrpPlop(Jay) Then
  67.                  Let Temp = strSptInDrpPlop(Jay): Let strSptInDrpPlop(Jay) = strSptInDrpPlop(Eye): Let strSptInDrpPlop(Eye) = Temp ' The element being compared with all the rest is bigger, so we swap it. The effect of this is that the smallest in the rest of the list being looked at, ( The Jay loop ) , will finally end up in the current Eye position.
  68.                Else
  69.                 End If
  70.            End If
  71.        Next Jay
  72.     Next Eye
  73. ' 2c) paste in values in DataSaladinValagationLists worksheet
  74.    With Worksheets("DataSaladinValagationLists")
  75.      Let .Range("A" & Target.Row & "").Value = "-" '                                                   ' a leading "-" ,
  76.     Let .Cells.Item(Target.Row, 2).Resize(1, UBound(strSptInDrpPlop()) + 1).Value = strSptInDrpPlop() '    unique values
  77.     Let .Cells.Item(Target.Row, UBound(strSptInDrpPlop()) + 3).Value = "Blank" '                      '       and trailing "Blank"
  78.    End With
  79. ' 2d) Make dropdown list
  80. Target.Validation.Delete ' This is only necerssary if a drop down is already there
  81. Target.Validation.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:="=DataSaladinValagationLists!A" & Target.Row & ":" & CLDoWhile(UBound(strSptInDrpPlop()) + 3) & "" & Target.Row & ""
  82. End Sub
  83. Sub testieCLDoWhile()
  84. Dim testieletter As String
  85.  Let testieletter = CLDoWhile(3) ' should return "C"
  86. End Sub
  87. '   CLDoWhile  is a Function to get column letter from column number
  88. Function CLDoWhile(ByVal lclm As Long) As String 'Using chr function and Do while loop      For example http://www.excelforum.com/excel-programming-vba-macros/796472-how-to-go-from-column-number-to-column-letter.html
  89. Dim rest As Long 'Variable for what is "left over" after subtracting as many full 26's as possible
  90.    Do
  91.     '    Let rest = ((lclm - 1) Mod 26) 'Gives 0 to 25 for Column Number "Left over" 1 to 26. Better than ( lclm Mod 26 ) which gives 1 to 25 for clm 1 to 25 then 0 for 26
  92.    '    Let FukOutChrWithDoWhile = Chr(65 + rest) & FukOutChrWithDoWhile 'Convert rest to Chr Number, initially with full number so the "units" (0-25), then number of 26's left over (if the number was so big to give any amount of 26's in it, then number of 26's in the 26's left over (if the number was so big to give any amount of 26 x 26's in it, Enit ?
  93.    '    'OR
  94.    Let CLDoWhile = Chr(65 + (((lclm - 1) Mod 26))) & CLDoWhile
  95.     Let lclm = (lclm - (1)) \ 26 'This gives the number of 26's ( if any ), but just the excact part, in the next number down , - so applying the rest formula to this new number will again leave a difference "left over" rest.
  96.    'lclm = (lclm - (rest + 1)) \ 26 ' As the number is effectively truncated here, any number from 1 to (rest +1)  will do in the formula
  97.    Loop While lclm > 0 'Only loop further if number was big enough to still have 0-25's in it
  98. End Function
  99. '
  100. '
  101. Sub testieWksChange()
  102.  Call Worksheet_Change(Me.Range("A2"))
  103.  Let Application.EnableEvents = True ' Just incase it got turned off
  104. End Sub
  105.  
  106. Private Sub Worksheet_Change(ByVal Target As Range)
  107.     If IsArray(Target.Value) Then Exit Sub
  108. Rem 1 main worksheet data range info
  109. Dim CntItms As Long: Let CntItms = Me.Range("B" & Rows.Count & "").End(xlUp).Row
  110.     If Application.Intersect(Target, Me.Range("A2:A" & CntItms & "")) Is Nothing Then Exit Sub ' only do anything for a selection in the A column range.
  111. Dim CntClms As Long: Let CntClms = Me.Cells.Item(1, Columns.Count).End(xlToLeft).Column
  112.     If Target.Value = "Blank" Then Let Application.EnableEvents = False: Let Target.Value = "": Let Application.EnableEvents = True
  113. Rem 2 test data range reset
  114.     If Target.Value = "-" Then
  115.      Let Application.EnableEvents = False
  116.      Let Me.Range("C1", Me.Cells.Item(CntItms, Worksheets("Sheet1 (2)").Cells.Item(1, Columns.Count).End(xlToLeft).Column)).Value = Worksheets("Sheet1 (2)").Range("C1", Worksheets("Sheet1 (2)").Cells.Item(CntItms, Worksheets("Sheet1 (2)").Cells.Item(1, Columns.Count).End(xlToLeft).Column)).Value
  117.      Let Application.EnableEvents = True
  118. Rem 3 Get indices( column numbers) for required columns, and all row indicies
  119.     '3a) indices( column numbers) for required columns
  120.    Else ' selected value is a unique value or ""  for  "Blank"
  121.    Dim arrLine() As Variant: Let arrLine() = Me.Range(Me.Cells.Item(Target.Row, 1), Me.Cells.Item(Target.Row, CntClms)).Value ' I dont need the first and third column, but it makes it easier to keep track of the correct columns indicie
  122.    Dim Cnt As Long
  123.     Dim strClms As String: Let strClms = "1 2 " ' For our required columns containing in this row the target selected value
  124.        For Cnt = 3 To CntClms ' check columns from 3 for a match to the value in column 1
  125.            If CStr(arrLine(1, Cnt)) = CStr(Target.Value) Then ' This is indication of wanted column as it contains the value
  126.             Let strClms = strClms & Cnt & " "
  127.             Else
  128.             End If
  129.         Next Cnt
  130.      Let strClms = Left(strClms, Len(strClms) - 1) ' Take off last " "
  131.    Dim clmsSpt() As String: Let clmsSpt() = Split(strClms, " ", -1, vbBinaryCompare)
  132.     Dim Clms() As String: ReDim Clms(1 To UBound(clmsSpt()) + 1) ' for        {1,2,7,9} = required columns
  133.        For Cnt = 0 To UBound(clmsSpt())
  134.          Let Clms(Cnt + 1) = clmsSpt(Cnt)
  135.         Next Cnt
  136.     '3b) all data ro indicies
  137.    Dim Rws() As Variant: Let Rws() = Evaluate("=Row(1:" & CntItms & ")") ' = {1;2;3;4;5;6;7;8;9;.......... , CntItms} = required rows ( all rows are required )
  138. Rem 4 Output filtered columns
  139.      Dim arrOut() As Variant: Let arrOut() = Application.Index(Cells, Rws(), Clms())
  140.      Let Application.EnableEvents = False
  141.      Me.Cells.ClearContents
  142.      Let Range("A1").Resize(UBound(arrOut(), 1), UBound(arrOut(), 2)).Value = arrOut()
  143.      Let Application.EnableEvents = True
  144.     End If
  145. End Sub
  146.  
  147.  
  148. Sub testsort()
  149.  
  150. Dim df As String, d As String
  151.  df = "df"
  152. Dim var
  153.   If IsNumeric(df) Then var = CLng(df)
  154. Dim dg As String
  155.  dg = "dg"
  156.  MsgBox (dg > df) & "   " & (dg > d)
  157.  MsgBox "7" < "77"
  158. Dim seven As String, seventyseven As String
  159.  Let seven = "7": Let seventyseven = "77"
  160.  MsgBox seven < seventyseven
  161.  If seven < seventyseven Then MsgBox "True"
  162. Dim arrStr(0 To 1) As String
  163.  Let arrStr(0) = "7": Let arrStr(1) = "77"
  164.  MsgBox arrStr(0) < arrStr(1)
  165.  MsgBox "6" < "34" ' FALSE !!!!!!!!!!******************
  166. End Sub
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement