VBA SUM Variable Range - excel

I want a code to sum the Variable rows up if certain condition is met.
e.g. If A12 is numeric and B12 is empty then insert a fomula in cell C12 to sum C3:C11.
Then perform the same action at C22 and C30.
The problem I have is don't know how to define the starting row.
Sub Test()
Dim y As Variant
Dim r As Variant
Dim StartRow As Variant
LastRow = Range("C" & Rows.Count).End(xlUp).Row
For y = 3 To 500
For r = 1 To LastRow
If InStr(1, Cells(r, 1), "Amount") Then
StartRow = r
If IsNumeric(Cells(y, 1)) And IsEmpty(Cells(y, 2)) Then
Cells(y, 3).Formula = "=SUM(C" & StartRow + 1 & ":C" & y - 1 & ")"
End If
End If
Next r
Next y
End Sub

Sub Test()
Dim y As Variant
Dim firstRow As Variant
Dim lastRow As Variant
lastRow = Range("C" & Rows.Count).End(xlUp).Row
firstRow = Cells(lastRow, 3).End(xlUp).Row
If IsNumeric(Cells(lastRow + 1, 1)) And IsEmpty(Cells(lastRow + 1, 2)) Then
Cells(lastRow + 1, 3).Formula = "=SUM(C" & firstRow & ":C" & lastRow & ")"
End If
For y = firstRow To 3 Step -1
lastRow = Cells(y, 3).End(xlUp).Row
firstRow = Cells(lastRow, 3).End(xlUp).Row
If firstRow < 3 Then firstRow = 3
If IsNumeric(Cells(lastRow + 1, 1)) And IsEmpty(Cells(lastRow + 1, 2)) Then
Cells(lastRow + 1, 3).Formula = "=SUM(C" & firstRow & ":C" & lastRow & ")"
End If
y = firstRow
If firstRow = 3 Then Exit Sub
Next y
End Sub

Related

vba program to detect cell value in column and copy corresponding cell value in previous column

im trying to make a vba code that will detect when Active balancing is on ( A value in cell ) and then copy the previous tension value, and simillarly do the same at the end of Active balancing to copy the next tension value. (see picture for more explanation).
im planing to show those values in another sheet
thanks to the help of Mr.PeterT i modified his code to do it but i couldn't succeed. thanks for you help and mentoring guys!
image of values i want to extract
Option Explicit
Sub find_balanced_cells_and_tensions()
FindWith "A"
End Sub
Sub FindWith(checkValue As Variant)
Dim destinationSheet As Worksheet
Set destinationSheet = ThisWorkbook.Sheets.Add
destinationSheet.Name = "Equilibrage.actif.info"
Dim destRow As Long
destRow = 1
Dim sourceSheet As Worksheet
Set sourceSheet = ThisWorkbook.Sheets("Equilibrage.passif")
Dim lastRow As Long
Dim lastColumn As Long
lastRow = sourceSheet.Cells(sourceSheet.Rows.Count, 1).End(xlUp).Row
lastColumn = sourceSheet.Cells(1, sourceSheet.Columns.Count).End(xlToLeft).Column
Dim i As Long
Dim j As Long
For j = 1 To lastColumn
For i = 2 To lastRow
If sourceSheet.Cells(i, j).Value = checkValue _
& sourceSheet.Cells(i + 1, j).Value = checkValue Then
sourceSheet.Cells(i - 1, j - 1).Copy _
Destination:=destinationSheet.Range("A" & destRow)
destRow = destRow + 1
ElseIf sourceSheet.Cells(i, j).Value = checkValue _
& sourceSheet.Cells(i + 1, j).Value <> checkValue Then
sourceSheet.Cells(i + 1, j - 1).Copy _
Destination:=destinationSheet.Range("B" & destRow)
destRow = destRow + 1
Exit For 'immediately skip to the next row
End If
Next i
Next j
End Sub
Untested but should be close.
I will test if you can share a sample dataset.
Sub find_balanced_cells_and_tensions()
FindWith "A"
End Sub
Sub FindWith(checkValue As Variant)
Dim sourceSheet As Worksheet
Dim destinationSheet As Worksheet
Dim destRow As Long, lastRow As Long, lastColumn As Long, valCount As Long
Dim i As Long, j As Long, preVal, postval, cellLabel, dt, tm
Set sourceSheet = ThisWorkbook.Sheets("Equilibrage.passif")
Set destinationSheet = ThisWorkbook.Sheets.Add()
destinationSheet.Name = "Equilibrage.actif.info"
destRow = 1
lastRow = sourceSheet.Cells(sourceSheet.Rows.Count, 1).End(xlUp).Row
lastColumn = sourceSheet.Cells(1, sourceSheet.Columns.Count).End(xlToLeft).Column
For j = 4 To lastColumn Step 2 'only process relevant columns
i = 3
Do 'from 3 to lastrow-1 to allow for -1 at top and +1 at bottom
If sourceSheet.Cells(i, j).Value = checkValue Then
dt = sourceSheet.Cells(i - 1, 1).Value 'collect start info
tm = sourceSheet.Cells(i - 1, 2).Value
cellLabel = sourceSheet.Cells(1, j).Value
preVal = sourceSheet.Cells(i - 1, j - 1).Value
valCount = 1 'how many values in this run?
Do While sourceSheet.Cells(i, j).Offset(valCount).Value = checkValue
valCount = valCount + 1
Loop
postval = sourceSheet.Cells(i + valCount, j - 1).Value
destinationSheet.Cells(destRow, 1).Resize(1, 5).Value = _
Array(dt, tm, cellLabel, preVal, postval)
destRow = destRow + 1
i = i + valCount
End If
i = i + 1
Loop While i < lastRow
Next j
End Sub
So after countless hit and miss and the help of Tim Williams and Funthomas, i arrived to this code that does the job plus some things.
the worksheet to get the values from is this one :
Value source
And the result of the code is like this :
Results
the final code is like this :
Option Explicit
Sub find_balanced_cells_and_tensions_A()
FindWith "A" ' we can replace A by any value we want to look for here
End Sub
Sub FindWith(checkValue As Variant)
Dim destinationSheet As Worksheet
Set destinationSheet = ThisWorkbook.Sheets.Add
destinationSheet.Name = "Equilibrage.actif.info"
'___ variables to track cells where will put our extacted values _______
Dim destRow As Long
destRow = 1
Dim destRow2 As Long
destRow2 = 1
'______ source sheet where we take our values from ___________
Dim sourceSheet As Worksheet
Set sourceSheet = ThisWorkbook.Sheets("Equilibrage.passif")
'_____ defining the end of columns and rows to end scaning for values _____________
Dim lastRow As Long
Dim lastColumn As Long
lastRow = sourceSheet.Cells(sourceSheet.Rows.Count, 1).End(xlUp).Row
lastColumn = sourceSheet.Cells(1, sourceSheet.Columns.Count).End(xlToLeft).Column
Dim i As Long
Dim j As Long
For j = 1 To lastColumn
For i = 2 To lastRow
'_____this part is to detect the start of balancing and taking the tension value of the previous row______________________
If sourceSheet.Cells(i, j).Value = checkValue _
And sourceSheet.Cells(i - 1, j).Value = 0 Then
sourceSheet.Cells(i - 1, j - 1).Copy _
Destination:=destinationSheet.Range("E" & destRow)
Range("A" & destRow).Value = sourceSheet.Cells(1, j)
Range("B" & destRow).Value = "was actively balanced at"
Range("C" & destRow).Value = sourceSheet.Cells(i, 2)
Range("D" & destRow).Value = "from"
Range("F" & destRow).Value = "to"
destRow = destRow + 1
'______ this condition is for when the balancing starts at the first row of the table so we take the present tension instead of the previous ___________
ElseIf sourceSheet.Cells(i, j).Value = checkValue _
And sourceSheet.Cells(i - 1, j).Value <> checkValue _
And sourceSheet.Cells(i - 1, j).Value <> 0 Then
sourceSheet.Cells(i, j - 1).Copy _
Destination:=destinationSheet.Range("E" & destRow)
Range("A" & destRow).Value = sourceSheet.Cells(1, j)
Range("B" & destRow).Value = "was actively balanced at"
Range("C" & destRow).Value = sourceSheet.Cells(i, 2)
Range("D" & destRow).Value = "from"
Range("F" & destRow).Value = "to"
destRow = destRow + 1
End If
'_____to find the next tension value after the end of balancing _____________
If sourceSheet.Cells(i, j).Value = checkValue _
And sourceSheet.Cells(i + 1, j).Value <> checkValue _
And IsEmpty(sourceSheet.Cells(i + 1, j).Value) = False Then
sourceSheet.Cells(i + 1, j - 1).Copy _
Destination:=destinationSheet.Range("G" & destRow2)
Range("H" & destRow2).Value = "at"
Range("I" & destRow2).Value = sourceSheet.Cells(i + 1, 2)
destRow2 = destRow2 + 1
'_____in case the balancing ends at the last row we take the present tension as the next one doesnt exist _____________
ElseIf sourceSheet.Cells(i, j).Value = checkValue _
And IsEmpty(sourceSheet.Cells(i + 1, j).Value) = True Then
sourceSheet.Cells(i, j - 1).Copy _
Destination:=destinationSheet.Range("G" & destRow2)
Range("H" & destRow2).Value = "at"
Range("I" & destRow2).Value = sourceSheet.Cells(i, 2)
destRow2 = destRow2 + 1
End If
Next i
Next j
'_____ Cells modification and formating _________________
Range("C:C").NumberFormat = "hh:mm:ss"
Range("I:I").NumberFormat = "hh:mm:ss"
Range("E:E").Style = "Normal"
Range("G:G").Style = "Normal"
Range("A:K").Font.Size = 14
Range("E:E").Font.Bold = True
Range("G:G").Font.Bold = True
Worksheets("Equilibrage.actif.info").Columns.AutoFit
End Sub

Convert date list into date ranges [duplicate]

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

Cut content to next row maintaining other content in range

I want to cut the cells present from the cells in E1:G1 and add it to D2 and copy the cells in range present in A1:C1 to the next row,
and do that to next rows and so on in which they have content from the columns E to G.
I've already tried to use the "Data - Text to Columns" in Excel but I can't use that in order to copy to rows...
What I'm trying to obtain is in this format, but I'm having a hard time finding VBA code in order to do this.
You could try:
Option Explicit
Sub test()
Dim LastRow As Long, LastColumn As Long, i As Long, y As Long
Dim Avalue As String, BValue As String, Cvalue As String
With ThisWorkbook.Worksheets("Sheet1")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = LastRow To 1 Step -1
Avalue = .Range("A" & i).Value
BValue = .Range("B" & i).Value
Cvalue = .Range("C" & i).Value
LastColumn = .Cells(i, .Columns.Count).End(xlToLeft).Column
If LastColumn > 4 Then
For y = LastColumn To 5 Step -1
.Rows(i + 1).EntireRow.Insert
.Cells(i + 1, 1).Value = Avalue
.Cells(i + 1, 2).Value = BValue
.Cells(i + 1, 3).Value = Cvalue
.Cells(i, y).Cut .Cells(i + 1, 4)
Next y
End If
Next i
End With
End Sub
Array Version
Option Explicit
Sub test()
Dim LastRow As Long, LastColumn As Long, i As Long, y As Long
Dim Avalue As String, BValue As String, Cvalue As String
Dim ABCvalues As Variant
With ThisWorkbook.Worksheets("Sheet1")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = LastRow To 1 Step -1
ABCvalues = .Range("A" & i & ":C" & i).Value
LastColumn = .Cells(i, .Columns.Count).End(xlToLeft).Column
If LastColumn > 4 Then
For y = LastColumn To 5 Step -1
.Rows(i + 1).EntireRow.Insert
.Range("A" & i + 1 & ":C" & i + 1).Value = ABCvalues
.Cells(i, y).Cut .Cells(i + 1, 4)
Next y
End If
Next i
End With
End Sub

Creating new rows in excel with From and To values

I currently have a sheet with two columns - 'From' and 'To'. I am trying to create a spreadsheet where each line is an individual value that falls within the ranges currently in each row.
An example (sorry I cannot embed images yet)--
What I have:
What I want:
Try this VBA code,
Sub splitToCodes()
Dim i As Long, j As Long, k As Long
j = 2
For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
If IsNumeric(Cells(i, 1)) Then
For k = Cells(i, 1) To Cells(i, 2)
Cells(j, 4) = k
j = j + 1
Next k
Else
For k = Right(Cells(i, 1), Len(Cells(i, 1)) - 1) To Right(Cells(i, 2), Len(Cells(i, 2)) - 1)
Cells(j, 4) = k
Cells(j, 4) = Left(Cells(i, 1), Len(Cells(i, 1)) - Len(Cells(j, 4))) & k
j = j + 1
Next k
End If
Next i
End Sub
This code loops through the columns A and B and prints the output in column D. Modify as per your needs.
Note:- This code will work only for similar data as in the image as you have not mentioned any other format.
Copy & paste FROM and TO columns under each other and apply remove duplicates function at data block of menu bar.
Here is my super tedious solution:
Option Explicit
Sub Test()
Dim i As Integer, j As Integer, k As Long, sht As Worksheet, lastrow As Long, missingzeroes As Integer, zeroesholder As String, myzeroes As String
Set sht = ThisWorkbook.Worksheets("Sheet1")
lastrow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
For i = 2 To lastrow
If IsNumeric(Range("B" & i).Value) = True And IsNumeric(Range("A" & i).Value) = True Then
j = Range("B" & i).Value - Range("A" & i).Value
lastrow = sht.Cells(sht.Rows.Count, "D").End(xlUp).Row
For k = 0 To j
Range("D" & lastrow + 1 + k).Value = Range("A" & i).Value + k
Next k
Else
j = Right(Range("B" & i).Value, 4) - Right(Range("A" & i).Value, 4)
lastrow = sht.Cells(sht.Rows.Count, "D").End(xlUp).Row
For k = 0 To j
Range("D" & lastrow + 1 + k).Value = Left(Range("B" & i).Value, 1) & Right(Range("A" & i).Value, 4) + k
If Len(Range("B" & i).Value) <> Len(Range("D" & lastrow + 1 + k).Value) Then
missingzeroes = Len(Range("B" & i).Value) - Len(Range("D" & lastrow + 1 + k).Value)
zeroesholder = "000000000000000000000000000000000000000000000000000000000000000000"
myzeroes = Left(zeroesholder, missingzeroes)
Range("D" & lastrow + 1 + k).Value = Left(Range("A" & i).Value, 1) & myzeroes & Right(Range("A" & i).Value, Len(Range("D" & lastrow + 1 + k).Value) - 1) + k
End If
Next k
End If
Next i
End Sub

Create ranges out of rows VBA

I have multiple rows which are sometimes in order and sometimes not.
Out of rows which are in order, I would need to create a range, which are not in order just to copy the number.
The thing is, the most rows in order can be even 20.
For example cells:
1
3
5
6
7
8
9
10
13
14
15
There would be:
1
3
5-10
13-15
Is it possible to code it?
Thanks
Assuming your data starts with A1.... and
required results will be printed at C column.
Try with below code
Sub test()
Dim i As Long, lastrow As Long, incre As Long
Dim startno As Variant
Dim endno As Variant
incre = 1
lastrow = Range("A" & Rows.Count).End(xlUp).Row
For i = 1 To lastrow
If Cells(i, 1) = (Cells(i + 1, 1) - 1) Then
startno = Cells(i, 1)
Do While Cells(i, 1) = (Cells(i + 1, 1) - 1)
endno = Cells(i + 1, 1)
i = i + 1
Loop
Cells(incre, 3) = "'" & startno & "-" & endno
incre = incre + 1
Else
Cells(incre, 3) = Cells(i, 1)
incre = incre + 1
End If
Next i
End Sub
if you want the address of all consecutive ranges you could use:
Option Explicit
Sub main()
Dim rangeStrng As String
With Worksheets("MyRowsSheet") '<--| change "MyRowsSheet" with your actual sheet name
rangeStrng = .Range("A1", .Cells(.Rows.Count, "A").End(xlUp)).SpecialCells(xlCellTypeConstants).Areas.Parent.Address(False, False)
End With
End Sub
if you want only the rows range then you could use:
Option Explicit
Sub main2()
Dim rng As Range
Dim rowsRangeStrng As String
With Worksheets("MyRowsSheet") '<--| change "MyRowsSheet" with your actual sheet name
For Each rng In .Range("A1", .Cells(.Rows.Count, "A").End(xlUp)).SpecialCells(xlCellTypeConstants).Areas
If rng.Rows.Count = 1 Then
rowsRangeStrng = rowsRangeStrng & rng.Rows(1).Row & ","
Else
rowsRangeStrng = rowsRangeStrng & rng.Rows(1).Row & "-" & rng.Rows(rng.Rows.Count).Row & ","
End If
Next rng
End With
If rowsRangeStrng <> "" Then rowsRangeStrng = Left(rowsRangeStrng, Len(rowsRangeStrng) - 1)
End Sub
If I understood your question correctly, you are not looking to address a range, but rather want an output table. This code below should provide you with just that. My input numbers are in column A, and the output is in column B.
Sub sequentials()
Dim tws As Worksheet
Dim tmpRowA, tmpRowB As Integer
Dim seq() As Long
Dim frA, frB, lrA As Integer 'firstrow col A, col B, lastrow of data
Set tws = ThisWorkbook.Worksheets("Sheet1")
frA = 2
frB = 2
lrA = tws.Range("A1000000").End(xlUp).Row
'Input in column A, Output in column B
'Headers in Row 1
ReDim seq(0 To lrA - 1)
seq(0) = -2
seq(1) = tws.Range("A" & frA).Value
tmpRowA = frA
tmpRowB = frB
tws.Range("B" & frB & ":B" & lrA).NumberFormat = "#"
For r = frA + 1 To lrA
If r = 23 Then
r = 23
End If
With tws
seq(r - 1) = .Range("A" & r).Value
If seq(r - 1) = seq(r - 2) + 1 Then
If r = lrA Then
.Range("B" & tmpRowB).Value = .Range("A" & tmpRowA - 1).Value & "-" & seq(r - 1)
End If
Else
If seq(r - 2) = seq(r - 3) + 1 Then
.Range("B" & tmpRowB).Value = .Range("A" & tmpRowA - 1).Value & "-" & seq(r - 2)
Else
.Range("B" & tmpRowB).Value = seq(r - 2)
End If
tmpRowB = tmpRowB + 1
tmpRowA = r + 1
If r = lrA Then
.Range("B" & tmpRowB).Value = seq(r - 1)
End If
End If
End With
Next r
End Sub
Proof of concept:

Resources