I'd like to concatenate the number of days that add up to 80%. Please see the example below;
I can run a code that concatenates Range A1:A7 and the result is printed in C1;
Sub Concatenator()
Dim lastLng As Long
Dim result As String
Dim delim As String
Dim b As String
delim = "&"
lastLng = Worksheets("Sheet1").Range("A1048576").End(xlUp).Row
For i = 1 To lastLng
b = Cells(i, 1).Value
result = result & b & delim
Next
result = Left(result, Len(result) - Len(delim))
Worksheets("Sheet1").Cells(1, 3).Value = result
End Sub
I'd to add a "Do Until" loop that loops until the value in column is greater than 80%. I've tried to amend the code above with the "Do Until" loop;
Sub Concatenator()
Dim lastLng As Long
Dim result As String
Dim delim As String
Dim b As String
delim = "&"
lastLng = Worksheets("Sheet1").Range("A1048576").End(xlUp).Row
Do Until Cells(i, 2).Value = ">80%"
For i = 1 To lastLng1
b = Cells(i, 1).Value
result = result & b & delim
Next
Loop
result = Left(result, Len(result) - Len(delim))
Worksheets("Sheet1").Cells(1, 3).Value = result
End Sub
As far as I understand this might work for you
To understand how to set up the code, take a look For-Loop and Do-while, then combine the conditions with the loop as the following code
i = 1
Do Until Cells(i, 2).Value = 0.8 'Loop until request condition
If i > lastLng1 Then Exit Do 'Loop until end of the range
b = Cells(i, 1).Value
result = result & b & delim
i = i + 1
Loop
'Or------------------------------
For i = 1 To lastLng1 'Loop until end of the range
If Cells(i, 2).Value = 0.8 Then Exit For 'Loop until request condition
b = Cells(i, 1).Value
result = result & b & delim
Next
This is what worked for me
Sub Concatenator()
Dim lastLng As Long
Dim result As String
Dim delim As String
Dim b As String
delim = "&"
lastLng = Worksheets("Sheet1").Range("A1048576").End(xlUp).Row
For i = 1 To lastLng
If Cells(i, 2).Value > "80" Then Exit For
b = Cells(i, 1).Value
result = result & b & delim
Next
result = Left(result, Len(result) - Len(delim))
Worksheets("Sheet1").Cells(1, 3).Value = result
End Sub
I changed the value in column be from a percentage to a number. I also removed the equal sign
For i = 1 To lastLng
If Cells(i, 2).Value > "80" Then Exit For
b = Cells(i, 1).Value
result = result & b & delim
Next
This will work very well for me for now. Thank you #The GridLock
Related
I am new to VBA and learning myself...
I am facing a similar problem with this post: Excel Vba - Group number sequence inside a string
which the difference is that my item no. is in horizontal like below:
ColA(ID) ColB ColC ColD ColE ColF ColG
A 101 102 103
B 201 202 203 501 502
Sometimes for an ID, there will only have 3 item no., sometimes with 5, they can be upto 30 sometimes...
What I think the function could look like this: Cell G1 = lookupsequence(A1:A30), since that lookup function is no need in this situtation
Then G1 -> 101-103
Then G2 -> 201-203, 501-502
Below is the code I have based on that post, but just generating G1: 101, 102, 103
Lookupsequence(Return_val_col As Range)
Dim i As Long
Dim result As String
Dim initial As String
Dim separator As String
Dim preValue As Integer
Dim value As Integer
preValue = -1
separator = ""
For i = 1 To 30
value = CInt(Return_val_col.Cells(1, i).value)
If value - 1 = preValue Then
result = initial & "-" & value
Else
result = result & separator & value
initial = result
separator = ","
End If
Next
Lookupsequence = Trim(result)
End Function
I tried to add something like but not succeed
Dim lastcol As Long
lastcol = Cells(1, Columns.Count).End(xlToLeft).Column
For i = 1 To lastcol
Thank you
Assuming a max of 30 numbers within the limits of rownumbers of Excel, try:
Function GetSequence(rng1 As Range) As String
Dim rng2 As Range
For Each cl In rng1.SpecialCells(2, 1)
If rng2 Is Nothing Then
Set rng2 = Cells(cl.Value, 1)
Else
Set rng2 = Union(rng2, Cells(cl.Value, 1))
End If
Next
GetSequence = Replace(Replace(rng2.Address(False, False), "A", ""), ":", "-")
End Function
Invoke through: =GetSequence(B1:D1) or whichever range holding the numbers.
If numbers get too large and too many for the above function, try:
Function GetSequence(rng As Range) As String
Dim arr As Variant: arr = rng.Value
With CreateObject("System.Collections.ArrayList")
For Each el In arr
If IsNumeric(el) And el <> "" Then .Add el
Next
.Sort
For i = .Count - 1 To 0 Step -1
If i = .Count - 1 Then
GetSequence = .Item(i) & "|"
Else
If Val(GetSequence) = .Item(i) + 1 Then
If Mid(GetSequence, Len(.Item(i)) + 1, 1) = "-" Then
GetSequence = .Item(i) & Mid(GetSequence, Len(CStr(Val(GetSequence))) + 1)
Else
GetSequence = .Item(i) & "-" & GetSequence
End If
Else
GetSequence = .Item(i) & "," & GetSequence
End If
End If
Next
End With
GetSequence = Replace(GetSequence, "|", "")
End Function
It's abit verbose but this way can even insert empty or unsorted arrays of numbers:
I tested this code and it worked correctly for me. I returned to the page and saw the solution from JvdV; so I thought I'd post my solution too.
Option Explicit
Private Sub Test()
Dim result$
Dim WS As Worksheet
Set WS = ThisWorkbook.Sheets("Sheet3")
result$ = Lookupsequence(WS.Range("B1:AE1"))
result$ = Lookupsequence(WS.Range("B2:AE2"))
result$ = Lookupsequence(WS.Range("B3:AE3"))
End Sub
Private Function Lookupsequence(Return_val_col As Range) As String
Dim preValue%, value%
Dim i&
Dim result$, separator$
preValue = -1
result = ""
separator = ", "
For i = 1 To Return_val_col.count
value = CInt(Return_val_col.Cells(1, i).value)
If value = 0 Then
Exit For
ElseIf result = "" Then
result = value
ElseIf value - 1 <> preValue Then
result = result & "-" & preValue & separator & value
End If
preValue = value
Next
If value = 0 Then
value = preValue
End If
result = result & "-" & value
Lookupsequence = Trim(result)
End Function
My test data in two images from columns A to AE to test the possibility of 30 item numbers
I am attempting to loop through a column. If the the item in the column matches the next item in the column. If they are the same, I will take values associated with the first row item and append it with stuff from the lines below.
I have tried using nested if loops to loop through a column. Ignore some of the functionality my code, but I am not sure why my comparisons are not working.
For bigLoop = 1 To Length + 1
firstString = Workbooks("VBA_Basics.xlsm").Worksheets("TestSheet").Cells(bigLoop, 24).Value
Cells(bigLoop, 28).Value = Cells(bigLoop, 26)
Debug.Print firstString
For smallLoop = 1 To Length + 1
secondString = Workbooks("VBA_Basics.xlsm").Worksheets("TestSheet").Cells(smallLoop + 1, 4).Value
Debug.Print secondString
myComp = StrComp(firstString, secondString, vbBinaryCompare)
If myComp = 0 Then
Cells(bigLoop, 28).Value = Cells(bigLoop, 26).Value & " :) " & Cells(smallLoop + 1, 26).Value
End If
Debug.Print myComp
Next smallLoop
Next bigLoop
Please sort your column! Then try this:
Option Explicit
Option Base 1
Private Const NITEMS As Integer = 11
' Column "A"
Private Const COLUMN As Integer = 1
' Column "B"
Private Const TARGET_COLUMN As Integer = 2
' Please sort your column!
Public Sub X()
Dim I As Integer
Dim J As Integer
Dim V1 As Variant
Dim V2 As Variant
I = 1
While I <= NITEMS
V1 = ActiveSheet.Cells(I, COLUMN).Value
ActiveSheet.Cells(I, TARGET_COLUMN).Value = V1
J = I + 1
V2 = ActiveSheet.Cells(J, COLUMN).Value
While V1 = V2 And J <= NITEMS
ActiveSheet.Cells(I, TARGET_COLUMN).Value = _
ActiveSheet.Cells(I, TARGET_COLUMN).Value & " :) " & V2
J = J + 1
V2 = ActiveSheet.Cells(J, COLUMN).Value
Wend
I = J
Wend
End Sub
My code keeps giving me only results for Sheet1.Cells(3, 1). It outputs to the correct cells using sequential i's but always from the same input in (3,1). How can I get it to loop through the inputs of the first column (3,1), (4,1) (5,1) etc.?
Sub CorrectName()
Dim IndexAnswers() As String
Dim FirstLastName As String
Dim FirstLastNameSplit() As String
i = 3
While Sheet1.Cells(i, 1) <> ""
IndexAnswers() = Split(Sheet1.Cells(i, 1), ";")
For k = 0 To UBound(IndexAnswers)
If IndexAnswers(k) = "" Then IndexAnswers(k) = ","
If k > 107 And k < 132 Then
FirstLastName = FirstLastName & IndexAnswers(k)
End If
Next
FirstLastNameSplit() = Split(FirstLastName, ",")
Sheet1.Cells(i, 4) = FirstLastNameSplit(0)
Sheet1.Cells(i, 3) = FirstLastNameSplit(1) & FirstLastNameSplit(2)
i = i + 1
Wend
End Sub
We have the column "following ID", which contains IDs of predecessors in the format "1; 2; 3; 4". Now I want to find the ID inside a specific cell. My problem is, that if I f.e. searching for "1", it also is true when there is a "11, 21, 13, 14, ..." inside the cell. Is there a way to search for the "ID" in "following ID", without getting true when the ID is part of an other ID?
For i = 2 To 250
Dim tmp As String
tmp = ""
If Cells(i, 1) = "" Then Exit For
For j = 2 To 250
If Cells(j, 1) = "" Then
Exit For
End If
If Cells(j, 11) = Cells(i, 1) Then
If tmp = "" Then
tmp = Cells(j, 1)
Else
tmp = tmp & "; " & Cells(j, 1)
End If
End If
Next j
Cells(i, 10) = tmp
Next i
Picture of Data
What you try to do can be described minimally with the following:
- Try to search for "1" in the string "1;2;3;4;11;12;13", returning only "1" and not "11", "12", "13".
This is a way to do it:
split the string to array by ";"
search in the array
The code would look like this:
Option Explicit
Public Sub TestMe()
Dim inputA As String
Dim cnt As Long
Dim arr As Variant
inputA = "1;2;3;4;11;12;13"
arr = Split(inputA, ";")
For cnt = LBound(arr) To UBound(arr)
If 1 = arr(cnt) Then
Debug.Print "Found in position " & cnt
Exit For
End If
Next cnt
End Sub
You can create a UDF like below:
Public Function FindID(rngToCheck As Range, strVal As String) As Boolean
If InStr(1, ";" & Replace(rngToCheck.Value, " ", "") & ";", ";" & strVal & ";", vbTextCompare) > 0 Then FindID = True
End Function
And then check the cell like below assuming your data is in Cell A2:
=FindID(A2,"1")
I am looking for a formula to list occurrences of values only if they are greater than 2 times; and the result would be shown as in the image.
For example, if a value repeats 2 times, it's shown by "2", and 3 times by "3". so if there are two numbers repeating in the range, then it would be shown by "32" as in the image below. (There is no need for a comma between the numbers). Thanks.
Here is a simple UDF:
Function mycount(rng As Range) As String
Dim str As String
Dim rngcnt As Range
For Each rngcnt In rng
If InStr("," & str & ",", "," & rngcnt.Value & ",") = 0 Then
If Application.WorksheetFunction.CountIf(rng, rngcnt) > 1 Then
mycount = mycount & Application.WorksheetFunction.CountIf(rng, rngcnt)
str = str & "," & rngcnt
End If
End If
Next rngcnt
End Function
So your call on the sheet would be:
=mycount(A2:H2)
Then copy down.
The way I got it is defining a VBA function.This function uses a dictionary, so it is necessary to add th reference to 'Microsoft Scripting Runtime' (look here). Also, I have used a function to sort the characters in string from here
Function Repetitions(rng As Range)
Dim dict As New Scripting.Dictionary
Dim res() As Integer
For aux = 1 To rng.Count
Dim numero As Integer
numero = rng.Cells(1, aux).Value
If Not dict.Exists(numero) Then
dict.Add numero, 1
Else
dict(numero) = dict(numero) + 1
End If
Next aux
Dim result As String
result = ""
For aux = 0 To UBound(dict.Items)
If dict.Items(aux) > 1 Then result = result & dict.Items(aux)
Next aux
While Len(result)
iTemp = 1
Temp = Left(result, 1)
For I = 2 To Len(result)
If StrComp(Mid(result, I, 1), Temp, vbTextCompare) = 0 Then
If StrComp(Mid(result, I, 1), Temp, vbBinaryCompare) = 1 Then
Temp = Mid(result, I, 1)
iTemp = I
End If
End If
If StrComp(Mid(result, I, 1), Temp, vbTextCompare) = 1 Then
Temp = Mid(result, I, 1)
iTemp = I
End If
Next I
Repetitions = Repetitions & Temp
result = Left(result, iTemp - 1) & _
Mid(result, iTemp + 1)
Wend
End Function
After all, you will be able to use the function as formula in Excel, calling it as following for example:
=Repetitions(A2:F2)