I have a data like this :
A049
A050
A051
A053
A054
A055
A056
A062
A064
A065
A066
And I want the output like :
As you can see, I want the ranges which are in consecutive order
I am trying some thing like this:
Private Sub CommandButton1_Click()
Set wb = ThisWorkbook
lastRow = wb.Sheets("Sheet1").Range("A" & wb.Sheets("Sheet1").Rows.Count).End(xlUp).Row
For i = 2 To lastRow
r = wb.Sheets("Sheet1").Range("A" & i).Value
If wb.Sheets("Sheet1").Range("A" & i).Value = wb.Sheets("Sheet1").Range("A" & i+1).Value
Next i
End Sub
But not helping me
Am feeling charitable so have tried some code which should work. It assumes your starting values are in A1 down and puts results in C1 down.
Sub x()
Dim v1, v2(), i As Long, j As Long
v1 = Range("A1", Range("A" & Rows.Count).End(xlUp)).Value
ReDim v2(1 To UBound(v1, 1), 1 To 2)
For i = LBound(v1, 1) To UBound(v1, 1)
j = j + 1
v2(j, 1) = v1(i, 1)
If i <> UBound(v1, 1) Then
Do While Val(Right(v1(i + 1, 1), 3)) = Val(Right(v1(i, 1), 3)) + 1
i = i + 1
If i = UBound(v1, 1) Then
v2(j, 2) = v1(i, 1)
Exit Do
End If
Loop
End If
If v1(i, 1) <> v2(j, 1) Then v2(j, 2) = v1(i, 1)
Next i
Range("C1").Resize(j, 2) = v2
End Sub
Try the below code
Private Sub CommandButton1_Click()
Set wb = ThisWorkbook
lastRow = wb.Sheets("Sheet1").Range("A" & wb.Sheets("Sheet1").Rows.Count).End(xlUp).Row
Dim lastNum, Binsert As Integer
Dim firstCell, lastCell, currentCell As String
Binsert = 1
lastNum = getNum(wb.Sheets("Sheet1").Range("A1").Value)
firstCell = wb.Sheets("Sheet1").Range("A1").Value
For i = 2 To lastRow
activeNum = getNum(wb.Sheets("Sheet1").Range("A" & i).Value)
currentCell = wb.Sheets("Sheet1").Range("A" & i).Value
If (activeNum - lastNum) = 1 Then
'nothing
Else
lastCell = wb.Sheets("Sheet1").Range("A" & (i - 1)).Value
wb.Sheets("Sheet1").Range("B" & Binsert).FormulaR1C1() = firstCell
If (firstCell <> lastCell) Then
wb.Sheets("Sheet1").Range("C" & Binsert).FormulaR1C1() = lastCell
End If
Binsert = Binsert + 1
firstCell = wb.Sheets("Sheet1").Range("A" & i).Value
End If
lastNum = activeNum
Next i
'last entry
wb.Sheets("Sheet1").Range("B" & Binsert).FormulaR1C1() = firstCell
If (firstCell <> currentCell) Then
wb.Sheets("Sheet1").Range("C" & Binsert).FormulaR1C1() = currentCell
End If
End Sub
Public Function getNum(ByVal num As String) As Integer
getNum = Val(Mid(num, 2))
End Function
Another solution. It loops backwards from last row to first row.
Option Explicit
Public Sub FindConsecutiveValues()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
Dim lRow As Long 'find last row
lRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
Dim lVal As String 'remember last value (stop value)
lVal = ws.Range("A" & lRow).Value
Const fRow As Long = 2 'define first data row
Dim i As Long
For i = lRow To fRow Step -1 'loop from last row to first row backwards
Dim iVal As Long
iVal = Val(Right(ws.Range("A" & i).Value, Len(ws.Range("A" & i).Value) - 1)) 'get value of row i without A so we can calculate
Dim bVal As Long
bVal = 0 'reset value
If i <> fRow Then 'if we are on the first row there is no value before
bVal = Val(Right(ws.Range("A" & i - 1).Value, Len(ws.Range("A" & i - 1).Value) - 1)) 'get value of row i-1 without A
End If
If iVal - 1 = bVal Then
ws.Rows(i).Delete 'delete current row
Else
If lVal <> ws.Range("A" & i).Value Then 'if start and stop value are not the same …
ws.Range("B" & i).Value = lVal 'write stop value in column B
End If
lVal = ws.Range("A" & i - 1).Value 'remember now stop value
End If
Next i
End Sub
I have two sheets – Latency, TP. I need to copy col M from "Latency" and paste it into col D of "TP" only if "Latency" col E has the string “COMPATIBLE” and col O has the string “Pass”.
I have the below code, but it doesn't give any result.
I'm not sure whats wrong with it:
Sub sbMoveData()
Dim lRow As Integer, i As Integer, j As Integer
'Find last roe in Sheet1
With Worksheets("Latency")
lRow = .Cells.SpecialCells(xlLastCell).Row
j = 1
For i = 1 To lRow
If UCase(.Range("E" & i)) = "COMPATIBLE" And UCase(.Range("O" & i)) = "Pass" Then
.Range("M" & i).Copy Destination:=Worksheets("TP").Range("D" & j)
j = j + 1
End If
Next
End With
End Sub
UCase(.Range("O" & i)) = "Pass"
Will always be false :-)
You are never going to match UCase(Cell) = "Pass", right? You either need to have:
UCase(.Range("O" & i)) = "PASS"
or
.Range("O" & i) = "Pass"
Try this
Sub sbMoveData()
Dim lRow As Integer, i As Integer, j As Integer
Dim ws1, ws2 As Worksheet
Set ws1 = ThisWorkbook.Sheets("Latency")
Set ws2 = ThisWorkbook.Sheets("TP")
'Find last roe in Sheet1
lRow = ws1.Cells.SpecialCells(xlLastCell).Row
j = 1
For i = 1 To lRow
If ws1.Range("A" & i) = "COMPATIBLE" And ws1.Range("B" & i) = "Pass" Then
ws1.Range("M" & i).Copy Destination:=ws2.Range("D" & j)
j = j + 1
End If
Next i
End Sub
I have a VBA code that calculates a formula (I know it's pretty long):
Cells(i, mcol) = "=IF(RC[-1]=""C"",(RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4,4,0)),SUM((RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4,4,0)),(RC[-3]/SUMIFS(C[-3],C66,RC66,C[-1],""GA + C""))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C3,3,0))))"
in the Vlookup it takes a 4th column in the range from C1:C4 and the 3rd column from the range C1:C3.
It was ok till the column number (4 and 3) was fixed.
Now it changes each time running For cycle.
Foe example, the second run column numbers will be 5 and 4, the third run 6 and 5 and so on till 12.
Is there any way to integrate the column number changed dynamically into the formula above?
Thanks a lot!
I put also a whole code as well.
Sub AutoCalcV2()
Dim ws As Worksheet
Dim LastRow As Long
Dim i As Integer, n As Integer, x As Integer, j As Integer, mcol As Integer
Set ws = ActiveWorkbook.Sheets("Sheet1")
ws.Select
LastRow = Sheets("Sheet1").Range("A" & Sheets("Sheet1").Rows.Count).End(xlUp).Row
mcol = 71
For j = 1 To 11
mcol = mcol + 1
For i = 3 To LastRow
On Error Resume Next
Cells(i, mcol) = "=IF(RC[-1]=""C"",(RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4,4,0)),SUM((RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4,4,0)),(RC[-3]/SUMIFS(C[-3],C66,RC66,C[-1],""GA + C""))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C3,3,0))))"
Range("BT4").Select
Next i
Next j
End Sub
Dim iColumn as Integer
mcol = 71
For j = 1 To 11
iColumn = 4
mcol = mcol + 1
For i = 3 To LastRow
On Error Resume Next
Cells(i, mcol) = "=IF(RC[-1]=""C"",(RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4," & str(iColumn) & ",0)),SUM((RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4," & str(iColumn) & ",0)),(RC[-3]/SUMIFS(C[-3],C66,RC66,C[-1],""GA + C""))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C3,3,0))))"
Range("BT4").Select
iColumn = iColumn + 1
Next i
Next j
So based on what I understood, you have 3 vlookups and you want to use 4 (4+1,5+1,6+1) for first Two vlookups and 3 (3+1,4+1,5+1) for third one.
If that so, here how you can increment your 4 and 3.
Sub AutoCalcV2()
Dim ws As Worksheet
Dim LastRow As Long
Dim i, n, x, j, mcol, iCol As Integer '<-- Changed here
Set ws = ActiveWorkbook.Sheets("Sheet1")
ws.Select
LastRow = Sheets("Sheet1").Range("A" & Sheets("Sheet1").Rows.Count).End(xlUp).Row
mcol = 71
iCol = 4 '<-- Newly added
For j = 1 To 11
mcol = mcol + 1
For i = 3 To LastRow
On Error Resume Next
'Changed the formula
Cells(i, mcol) = "=IF(RC[-1]=""C"",(RC[-3]/SUMIFS(C[-3],C66,RC66))" & _
"*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4," & iCol & ",0)),SUM((RC[-3]/SUMIFS(C[-3],C66,RC66))" & _
"*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4," & iCol & ",0)),(RC[-3]/SUMIFS(C[-3],C66,RC66,C[-1],""GA + C""))" & _
"*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C3," & i & ",0))))"
Range("BT4").Select
iCol = iCol + 1
Next i
Next j
End Sub
OK, Take a look. I can give an suggestion for you. Not the whole formula, Just a part of VLOOKUP.
I know that this is your formula for cell in loop:
Cells(i, mcol) = "=IF(RC[-1]=""C"",(RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4,4,0)),SUM((RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4,4,0)),(RC[-3]/SUMIFS(C[-3],C66,RC66,C[-1],""GA + C""))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C3,3,0))))"
Now is you want to change the dynamically the column according to looping. I understand the column pair as follow:
C1:C4 & C1:C3
C1:C5 & C1:C4
C1:C6 & C1:C5
C1:C7 & C1:C6
C1:C8 & C1:C7
C1:C9 & C1:C8
C1:C10 & C1:C9
C1:C11 & C1:C10
C1:C12 & C1:C11
Actually, your looping are not clear, I can't use it. So, I used as follow:
For column = 3 To 11
mcol = mcol + 1
For row = 1 To lastRow
Cells(row , mcol) = "=IF(RC[-1]=""C"",(RC[-3]/SUMIFS(C[-3],C66,RC66))*" & _
"(VLOOKUP('Sheet1'!RC66,GA_C!C1:C" & column + 1 & "," & column + 1 & ",0))" & _
",SUM((RC[-3]/SUMIFS(C[-3],C66,RC66))*" & _
"(VLOOKUP('Sheet1'!RC66,GA_C!C1:C" & column + 1 & "," & column + 1 & ",0))" & _
",(RC[-3]/SUMIFS(C[-3],C66,RC66,C[-1],""GA + C""))*" & _
"(VLOOKUP('Sheet1'!RC66,GA_C!C1:C" & column & "," & column & ",0))))"
Next row
Next column
Try as above, it will be helpful for you.
How do i add dashes(-) til my cell value = 5, If my length character is not equal to five and i have a 4 character, for ex A B... what i want it to do if i have cell value less then 5 then i want it to replace with dashes(-) till my cell length value reach to 5 character. Here is my Code and image... IMAGE will make more sense.. let me know if there is any confusion.
Sub xn()
Dim x As Integer, lastrow As Long, a As Long, i As Long
Dim xcell As String
a = 1
lastrow = Worksheets("Sheet2").UsedRange.Rows.Count + 1
For i = a To lastrow
xcell = Worksheets("Sheet2").Range("A" & i).Value
Do Until Len(xcell) = 5
If Len(xcell) <> 5 Then
Worksheets("Sheet2").Range("C" & i) = Replace(xcell, " ", "_")
Else
Exit Do
End If
Loop
Next i
End Sub
try this
Sub test()
Dim lastrow&, i&, xcell$, z%
lastrow = Sheet2.Cells(Rows.Count, "A").End(xlUp).Row
For i = 1 To lastrow
xcell = Replace(Sheet2.Range("A" & i).Value, " ", "")
If Len(xcell) < 5 And xcell <> "" Then
z = 5 - Len(xcell)
Sheet2.Cells(i, "C").Value = Left(xcell, Len(xcell) - 1) & _
WorksheetFunction.Rept("-", z) & Right(xcell, 1)
Else
Sheet2.Cells(i, "C").Value = xcell
End If
Next i
End Sub
output
This line isn't going to do anything unless there's already spaces padding the end of the string:
Worksheets("Sheet2").Range("C" & i) = Replace(xcell, " ", "_")
You need to check the length, if it's less than five, add 5 - length characters to the end of it:
Sub xn()
Dim lastrow As Long
Dim i As Long
Dim xcell As String
lastrow = Worksheets("Sheet2").UsedRange.Rows.Count + 1
For i = 1 To lastrow
xcell = Worksheets("Sheet2").Range("A" & i).Value
If Len(xcell) < 5 Then
Worksheets("Sheet2").Range("C" & i) = xcell & String$(Len(xcell) - 5, "_")
End If
Next i
End Sub
You can also leave out the variable 'a' - it's basically a constant in the code you posted.
i have in A column some names and in b column some numbers like:
jimmy 4
jimmy 4
carl 8
john 8
I need to sum jimmy's numbers. I mean, if there are some same values in A colum the sum the B numbers of that name. So jimmy = 8.
How can i do it? I'm very new in vba so the easy things for me are not so easy :)
EDIT, the macro:
Sub Sample()
Dim path As String
Dim openWb As Workbook
Dim openWs As Worksheet
Dim DataInizio As String
Dim DataFine As String
path = "C:\Me\Desktop\example.xls"
Set thiswb = ThisWorkbook
Set openWb = Workbooks.Open(path)
Set openWs = openWb.Sheets("details")
Set Logore = thiswb.Sheets("Log")
With openWs
start = CDate(InputBox("start (gg/mm/aaaa)"))
end = CDate(InputBox("end (gg/mm/aaaa)"))
Sheets("details").Select
LR = Cells(Rows.Count, "A").End(xlUp).Row
dRow = 2
For r = 2 To LR
If Cells(r, 1) >= start And Cells(r, 1) <= end Then
' Do un nome alle colonne nel file di log indicandone la posizione
ore = Range("K" & r)
nome = Range("J" & r)
totore = totore + ore
If ore <> 8 Then
Range("A" & r & ",J" & r & ",D" & r & ",K" & r).Copy Logore.Cells(dRow, 1)
rigatot = dRow
dRow = dRow + 1
End If
If nome <> Range("J" & r + 1) Then
If totore <> 40 Then
Logore.Cells(dRow, 5) = totore
End If
totore = 0
End If
End If
Next
thiswb.Sheets("Log").Activate
End With
openWb.Close (False)
End Sub
Well, this macro will sum up the values and reprint them as a new list. You can specify the columns as String parameters in your Main sub.
CollectArray "A", "D" - collects array from column A and removes duplicates from it and then prints it to column D
DoSum "D", "E", "A", "B" - summs up all values for column D and writes them to column E - gets the match from column A & values from column B
before:
Option Explicit
Sub Main()
CollectArray "A", "D"
DoSum "D", "E", "A", "B"
End Sub
' collect array from a specific column and print it to a new one without duplicates
' params:
' fromColumn - this is the column you need to remove duplicates from
' toColumn - this will reprint the array without the duplicates
Sub CollectArray(fromColumn As String, toColumn As String)
ReDim arr(0) As String
Dim i As Long
For i = 1 To Range(fromColumn & Rows.Count).End(xlUp).Row
arr(UBound(arr)) = Range(fromColumn & i)
ReDim Preserve arr(UBound(arr) + 1)
Next i
ReDim Preserve arr(UBound(arr) - 1)
RemoveDuplicate arr
Range(toColumn & "1:" & toColumn & Range(toColumn & Rows.Count).End(xlUp).Row).ClearContents
For i = LBound(arr) To UBound(arr)
Range(toColumn & i + 1) = arr(i)
Next i
End Sub
' sums up values from one column against the other column
' params:
' fromColumn - this is the column with string to match against
' toColumn - this is where the SUM will be printed to
' originalColumn - this is the original column including duplicate
' valueColumn - this is the column with the values to sum
Private Sub DoSum(fromColumn As String, toColumn As String, originalColumn As String, valueColumn As String)
Range(toColumn & "1:" & toColumn & Range(toColumn & Rows.Count).End(xlUp).Row).ClearContents
Dim i As Long
For i = 1 To Range(fromColumn & Rows.Count).End(xlUp).Row
Range(toColumn & i) = WorksheetFunction.SumIf(Range(originalColumn & ":" & originalColumn), Range(fromColumn & i), Range(valueColumn & ":" & valueColumn))
Next i
End Sub
Private Sub RemoveDuplicate(ByRef StringArray() As String)
Dim lowBound$, UpBound&, A&, B&, cur&, tempArray() As String
If (Not StringArray) = True Then Exit Sub
lowBound = LBound(StringArray): UpBound = UBound(StringArray)
ReDim tempArray(lowBound To UpBound)
cur = lowBound: tempArray(cur) = StringArray(lowBound)
For A = lowBound + 1 To UpBound
For B = lowBound To cur
If LenB(tempArray(B)) = LenB(StringArray(A)) Then
If InStrB(1, StringArray(A), tempArray(B), vbBinaryCompare) = 1 Then Exit For
End If
Next B
If B > cur Then cur = B
tempArray(cur) = StringArray(A)
Next A
ReDim Preserve tempArray(lowBound To cur): StringArray = tempArray
End Sub
after: