I found this code:
Add missing dates VBA
Sub InsertMissingDates()
Dim i As Long
Dim RowCount As Long
i = 4
Do
If Cells(i, 1) + 1 < Cells(i + 1, 1) Then
Rows(i + 1).Insert
Cells(i + 1, 1) = Cells(i, 1) + 1
End If
If (Cells(i + 1, 1) = "") Then
Cells(i + 1, 1) = Cells(i, 1) + 1
End If
i = i + 1
Loop Until Cells(i, 1).Value >= DateSerial(2016, 1, 30)
End Sub
How do I point to column E rather than it column A?
you need to change the parameter on Cells function
https://learn.microsoft.com/en-us/office/vba/api/excel.worksheet.cells
On Cells function the second parameter:
1- A
2- B
3- C
4- D
5- E
So if you change your Code and use 5 instead of 1 it will work on cell E
Sub InsertMissingDates()
Dim i As Long
Dim RowCount As Long
i = 4
Do
If Cells(i, 5) + 1 < Cells(i + 1, 5) Then
Rows(i + 1).Insert
Cells(i + 1, 5) = Cells(i, 5) + 1
End If
If (Cells(i + 1, 5) = "") Then
Cells(i + 1, 5) = Cells(i, 5) + 1
End If
i = i + 1
Loop Until Cells(i, 5).Value >= DateSerial(2016, 1, 30)
End Sub
Use a parameter to determine the column:
Sub InsertMissingDates()
Dim i As Long
Dim RowCount As Long
Dim WhichCol As String
i = 4
WhichCol = "D"
Do
If Cells(i, WhichCol) + 1 < Cells(i + 1, WhichCol) Then
Rows(i + 1).Insert
Cells(i + 1, WhichCol) = Cells(i, WhichCol) + 1
End If
If (Cells(i + 1, WhichCol) = "") Then
Cells(i + 1, WhichCol) = Cells(i, WhichCol) + 1
End If
i = i + 1
Loop Until Cells(i, WhichCol).Value >= DateSerial(2016, 1, 30)
End Sub
Related
New to stack here.
I'm on VBA and am creating a quoting tool where outputs are generated if certain cells are populated from row 57 onwards. I.e. "For a = 57 to 1000".
For each of row "a" that has values, I'm trying to have Cells(a + 1, 6) output the sum of the previous a columns.
It took some time to find how to reference a range using cells, but I've been stuck from there. To reference the range I've found something along the lines of below
With Sheet1
.Range(.Cells(a, 6), .Cells(a + 1, 6)).Value2 = "b"
End With
The .Range(.Cells(a, 7), .Cells(a + 1, 7)) are the cells that I want to create a sum for but I'm not sure how to do this (and whether the With Sheet1 and End With sections are needed.
Full VBA code here:
Sub OnEntry()
On Error Resume Next
For a = 14 To 1000
If IsEmpty(Cells(a, 3)) = False And IsEmpty(Cells(a, 4)) = True Then
If IsEmpty(Cells(a + 2, 4)) = True And IsEmpty(Cells(a + 3, 4)) = True And IsEmpty(Cells(a + 2, 3)) = True Then
GoTo GoHere
End If
If IsEmpty(Cells(a, 4)) = True And IsEmpty(Cells(a + 1, 4)) = False Then
GoTo GoHere
End If
Find = Range("'Sheet1'!$B$6:$B$5000").Find(Cells(a, 3).Value).Address
Row# = Range(Find).Row
Cells(a, 4) = Sheets("Sheet1").Cells(Row#, 3)
Cells(a, 5).Value = "=VLOOKUP(C" & a & ", 'Sheet1'!$B$6:$F$5000, 4, 0)"
Cells(a, 7).Value = "=B" & a & "*E" & a
If Cells(a - 1, 1) = "Line" Then
Cells(a, 1).Value = 1
Else
Cells(a, 1).Value = Cells(a - 1, 1) + 1
End If
Cells(a + 1, 1).EntireRow.Insert
**Stuck here**
With Sheet2
.Range(.Cells(a + 1, 7), .Cells(a + 2, 7)).Value2 = "b"
End With
End If
Next a
GoHere:
WaitTime = Now() + TimeValue("00:00:02")
While Now() < WaitTime
DoEvents
Wend
End Sub
I would like to ask how to shorten the code below? Have any other ways to achieve the same result?
Option Explicit
Sub test()
Dim i As Integer
Dim nRow As Integer: nRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To nRow
If Cells(i, 1) <> "" And Cells(i, 1) = Cells(i + 1, 1) And Cells(i + 1, 1) = Cells(i + 2, 1) And Cells(i + 2, 1) = Cells(i + 3, 1) And Cells(i + 3, 1) = Cells(i + 4, 1) Then
Cells(i, 2) = Cells(i, 2) & "/" & Cells(i + 1, 2) & "/" & Cells(i + 2, 2) & "/" & Cells(i + 3, 2) & "/" & Cells(i + 4, 2)
Rows(i + 1 & ":" & i + 4).Delete Shift:=xlShiftUp
ElseIf Cells(i, 1) <> "" And Cells(i, 1) = Cells(i + 1, 1) And Cells(i + 1, 1) = Cells(i + 2, 1) And Cells(i + 2, 1) = Cells(i + 3, 1) Then
Cells(i, 2) = Cells(i, 2) & "/" & Cells(i + 1, 2) & "/" & Cells(i + 2, 2) & "/" & Cells(i + 3, 2)
Rows(i + 1 & ":" & i + 3).Delete Shift:=xlShiftUp
ElseIf Cells(i, 1) <> "" And Cells(i, 1) = Cells(i + 1, 1) And Cells(i + 1, 1) = Cells(i + 2, 1) Then
Cells(i, 2) = Cells(i, 2) & "/" & Cells(i + 1, 2) & "/" & Cells(i + 2, 2)
Rows(i + 1 & ":" & i + 2).Delete Shift:=xlShiftUp
ElseIf Cells(i, 1) <> "" And Cells(i, 1) = Cells(i + 1, 1) Then
Cells(i, 2) = Cells(i, 2) & "/" & Cells(i + 1, 2)
Rows(i + 1 & ":" & i + 1).Delete Shift:=xlShiftUp
ElseIf Cells(i, 1) = "" Then
Exit For
End If
Next i
End Sub
Thank you!
Here's Dictionary based approach which should work for you.
Public Sub RearrangeData()
Dim objDic As Object
Dim varRng
Dim i As Long
Set objDic = CreateObject("Scripting.Dictionary")
objDic.CompareMode = vbTextCompare '\\ change this if you need it case sensitive
varRng = Range("A2:B" & Range("A" & Rows.Count).End(xlUp).Row).Value
For i = LBound(varRng) To UBound(varRng)
If objDic.Exists(varRng(i, 1)) Then
objDic.Item(varRng(i, 1)) = objDic.Item(varRng(i, 1)) & "/" & varRng(i, 2)
Else
objDic.Add varRng(i, 1), varRng(i, 2)
End If
Next i
Range("A2:B" & Range("A" & Rows.Count).End(xlUp).Row).ClearContents
Range("A2").Resize(objDic.Count, 1).Value = Application.Transpose(objDic.Keys)
Range("B2").Resize(objDic.Count, 1).Value = Application.Transpose(objDic.Items)
Set objDic = Nothing
End Sub
here's another dictionary approach (no reference adding required)
Sub strings()
Dim data As Variant, key As Variant
Dim i As Long
data = Range("B2", Cells(Rows.Count, 1).End(xlUp)).Value
With CreateObject("Scripting.Dictionary")
For i = 1 To UBound(data)
.Item(data(i, 1)) = .Item(data(i, 1)) & "/" & data(i, 2)
Next
Range("A1").CurrentRegion.Resize(Range("A1").CurrentRegion.Rows.Count - 1).Offset(1).ClearContents
i = 1
For Each key In .Keys
i = i + 1
Cells(i, 1) = key
Cells(i, 2) = Mid(.Item(key), 2)
Next
End With
End Sub
BTW, should you ever need to combine strings from more columns, you could use
Option Explicit
Sub strings()
Dim data As Variant, key As Variant
Dim i As Long, iCol As Long
With Range("A1").CurrentRegion
With .Resize(.Rows.Count - 1).Offset(1)
data = .Value
.ClearContents
End With
End With
With CreateObject("Scripting.Dictionary")
For iCol = 2 To UBound(data, 2)
For i = 1 To UBound(data)
.Item(data(i, 1)) = Trim(.Item(data(i, 1)) & " " & data(i, iCol))
Next
Range("A2").Resize(.Count) = Application.Transpose(.Keys)
Range("A2").Resize(.Count).Offset(, iCol - 1) = Application.Transpose(.Items)
.RemoveAll
Next
End With
Range("a1").CurrentRegion.Replace what:=" ", replacement:="/", lookat:=xlPart
End Sub
what would be the best way to merge similar rows (only order number letter different a4;a6;a8 and produced quantity) and sum (produced quantity e4;e6;e8) cells? This is how excel table looks
Clarification:
Here is the output I'm looking for
Rows 4;6;8 are the same except Order column (one letter added on 6 and 8) and Produced Column (different produced quantity). Rows 4,6,8 are merged and produced quantity is summed. Rows 6,8 is hidden or deleted.
Here is an example that could solve your problem:
Sub test()
i = 1
produced = 0
While Cells(i, 1) <> "" Or Cells(i + 1, 1) <> ""
If Cells(i, 1) <> "" Then
produced = Cells(i, 5)
j = 1
'second loop to add up every line with the same order, then suppress the lines
While Cells(j, 1) <> "" Or Cells(j + 1, 1) <> ""
If Left(Cells(j, 1), 7) = Left(Cells(i, 1), 7) And i <> j Then
produced = produced + Cells(j, 5)
Cells(j, 5).EntireRow.Select
Selection.Delete Shift:=xlUp
j = j - 1
End If
j = j + 1
Wend
End If
i = i + 1
Wend
Ok, here is the modified #Bitoubi code which helped me:
Sub RemoveSplitOrders()
i = 1
produced = 0
While Cells(i, 1) <> "" Or Cells(i + 1, 1) <> ""
If Cells(i, 1) <> "" Then
produced = Cells(i, 20)
j = 1
'second loop to add up every line with the same order, then suppress the lines
While Cells(j, 1) <> "" Or Cells(j + 1, 1) <> ""
If Left(Cells(j, 1), 8) = Left(Cells(i, 1), 8) Or Left(Cells(j, 1), 9) = Left(Cells(i, 1), 9) Then
If Cells(j, 2) = Cells(i, 2) And i <> j Then
produced = produced + Cells(j, 20)
Cells(i, 20).Value = produced
Range(Cells(j, 20), Cells(j + 1, 20)).EntireRow.Delete Shift:=xlUp
j = j - 1
End If
End If
j = j + 1
Wend
End If
i = i + 1
Wend
End Sub
I wrote a very quick script for VBA that takes a spread sheet and organizes it appropriately. For some reason I have just tried using it and I get a user defined error at this loop:
Dim qu As Long
For j = i To 10 Step -1
If Cells(j, 10) = "" Then
qu = j - 1
Do While Cells(qu, 10) = Cells(qu - 1, 10)
Cells(qu, 11) = 10
Cells(qu - 1, 11) = 10
qu = qu - 1
Loop
Cells(j - 1, 11) = 10
End If
Next j
The whole code looks like this:
Sub PopulateNF()
i = 10
Do While Cells(i, 2) <> ""
i = i + 1
Loop
For k = 10 To i Step 1
If Cells(k, 1) <> "" Then
Cells(k, 10) = ""
Else
If InStr(1, Cells(k, 2), "Received") Then
Cells(k, 10) = -1
ElseIf InStr(1, Cells(k, 2), "Workflow") Then
Cells(k, 10) = 0
ElseIf InStr(1, Cells(k, 2), "Forwarded") Then
Cells(k, 10) = 1
ElseIf InStr(1, Cells(k, 2), "Review Response") Then
Cells(k, 10) = 2
ElseIf InStr(1, Cells(k, 2), "Responded and Closed") Then
Cells(k, 10) = 4
ElseIf InStr(1, Cells(k, 2), "Sent") Then
Cells(k, 10) = 3
ElseIf InStr(1, Cells(k, 2), "Sent and Closed") Then
Cells(k, 10) = 3
End If
End If
Next k
Dim qu As Long
For j = i To 10 Step -1
If Cells(j, 10) = "" Then
qu = j - 1
Do While Cells(qu, 10) = Cells(qu - 1, 10)
Cells(qu, 11) = 10
Cells(qu - 1, 11) = 10
qu = qu - 1
Loop
Cells(j - 1, 11) = 10
End If
Next j
For a = i To 10 Step -1
If Cells(a, 1) <> "" Then
Cells(a, 11) = 10
End If
Next a
Const colA As Long = 11
Dim lngRow As Long
Dim lngLastRow As Long
lngLastRow = Cells.SpecialCells(xlCellTypeLastCell).Row
lngRow = 10
Do While lngRow <= lngLastRow
If Cells(lngRow, colA) = "" Then
Cells(lngRow, 1).EntireRow.Delete
lngLastRow = lngLastRow - 1
Else: lngRow = lngRow + 1
End If
Loop
d = 10
Do While Cells(d, 2) <> ""
d = d + 1
Loop
For k = 6 To d Step 1
If Cells(k, 1) = "" Then
Cells(k, 1) = Cells(k, 6)
Cells(k, 6) = ""
Cells(k, 2) = Cells(k, 7)
Cells(k, 7) = ""
Cells(k, 3) = Cells(k - 1, 3)
Cells(k, 4) = Cells(k - 1, 4)
Cells(k, 5) = Cells(k - 1, 5)
Cells(k, 6) = Cells(k - 1, 6)
Cells(k, 7) = Cells(k - 1, 7)
Cells(k, 8) = Cells(k - 1, 8)
Cells(k, 9) = Cells(k - 1, 9)
End If
Next k
Const colAN As Long = 1
Dim lngRowN As Long
Dim lngLastRowN As Long
lngLastRowN = Cells.SpecialCells(xlCellTypeLastCell).Row
lngRowN = 9
Do While lngRowN <= lngLastRowN
If Cells(lngRowN, colAN) = "" Then
Cells(lngRowN, 1).EntireRow.Delete
lngLastRowN = lngLastRowN - 1
ElseIf InStr(1, Cells(lngRowN, colAN), "_") Then
Cells(lngRowN, 1).EntireRow.Delete
lngLastRowN = lngLastRowN - 1
Else: lngRowN = lngRowN + 1
End If
Loop
Range("a9").CurrentRegion.Sort key1:=Range("a9"), order1:=xlAscending, Header:=xlGuess
Range("D:D").NumberFormat = "mm/dd/yyyy"
Range("F:I").NumberFormat = "mm/dd/yyyy"
Range("C:I").HorizontalAlignment = xlCenter
Range("a:a").VerticalAlignment = xlTop
Range("J:K").EntireColumn.Delete
Range("A:J").Font.Color = vbBlack
MsgBox ("Reformatting Complete")
End Sub
Any help would be greatly appreciated!
Stepping through the code looks like your loop doesn't know where to end.
Basically the line:
Do While Cells(qu, 10) = Cells(qu - 1, 10)
is never false and "qu-1" eventually becomes negative.
I'm not sure if this works with the greater bulk of your code, but you could try:
Do While qu <> 1
That should close your loop while still allowing you to modify cell values within the loop.
I have an excel sheet with more than 2000 rows.
I use the below macro to add a blank rows with a change in value of cloumn A1.
Sub AddBlankRows()
'
Dim iRow As Integer
Range("a1").Select
'
iRow = 1
'
Do
'![enter image description here][1]
If Cells(iRow + 1, 1) <> Cells(iRow, 1) Then
Cells(iRow + 1, 1).EntireRow.Insert shift:=xlDown
iRow = iRow + 2
Else
iRow = iRow + 1
End If
'
Loop While Not Cells(iRow, 1).Text = ""
'
End Sub
Is there a way insert the row (same with the above macro) with a fourmula and a predefined formatting?
Below is the sample code.
Sub AddBlankRows()
Dim lastRow As Long
Dim iRow As Long
Dim cursor As Long
cursor = 2
With ThisWorkbook.Sheets("sheet1")
lastRow = .Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To lastRow
If (LCase(Trim(.Cells(i, 1))) <> LCase(Trim(.Cells(i + 1, 1)))) Then
.Cells(i + 1, 1).EntireRow.Insert shift:=xlDown
.Cells(i + 1, 1).EntireRow.Interior.Color = vbYellow
lastRow = lastRow + 1
.Cells(i + 1, 2) = WorksheetFunction.Count(.Range(.Cells(cursor, 2), .Cells(i, 2)))
.Cells(i + 1, 2).NumberFormat = "0"
.Cells(i + 1, 3) = WorksheetFunction.Sum(.Range(.Cells(cursor, 3), .Cells(i, 3)))
.Cells(i + 1, 3).NumberFormat = "0.00"
i = i + 2
cursor = i
End If
Next
.Cells(lastRow + 1, 1).EntireRow.Insert shift:=xlDown
.Cells(lastRow + 1, 1).EntireRow.Interior.Color = vbYellow
.Cells(lastRow + 1, 2) = WorksheetFunction.Count(.Range(.Cells(cursor, 2), .Cells(lastRow, 2)))
.Cells(lastRow + 1, 2).NumberFormat = "0"
.Cells(lastRow + 1, 3) = WorksheetFunction.Sum(.Range(.Cells(cursor, 3), .Cells(lastRow, 3)))
.Cells(lastRow + 1, 3).NumberFormat = "0.00"
End With
End Sub