I have code that will insert the number of rows based on data missing between 2 numbers but I am unable to figure out the code to get it to copy and paste the years I am missing.
Thanks in advance for any help, I am pretty good at manipulating existing code but I can't find any code to add to this to make it work
Here is the code I have to insert the right number of blank rows
Public Sub Insert()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual 'pre XL97 xlManual
lastRow = ActiveSheet.UsedRange.Rows.Count
ActiveSheet.Cells(lastRow, 1).Select
Set CurrentCell = ActiveSheet.Cells(lastRow, 1)
For n = lastRow To 0 Step -1
If n = lastRow Then GoTo CheckLastRow
If n = 1 Then GoTo CheckfirstRow
ActiveCell.Offset(-2, 0).Select
CheckLastRow:
Set NextCell = CurrentCell.Offset(-1, 0)
ActiveCell.Offset(1, 0).Select
For i = 1 To CurrentCell
ActiveCell.EntireRow.Insert
Next i
Set CurrentCell = NextCell
Next n
'To be performed on the firstrow in the column
CheckfirstRow:
ActiveCell.Offset(-1, 0).Select
For i = 1 To CurrentCell
ActiveCell.EntireRow.Insert
Next i
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
My data looks like this
Column A is number of Rows I need Column B&C has years
B = 2009
C = 2013
It would need the output to copy the line and look like
2009 2010
2010 2011
2011 2012
2012 2013
I added this to the code and I still only have blank lines
Public Sub InsertTest()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual 'pre XL97 xlManual
lastRow = ActiveSheet.UsedRange.Rows.Count
ActiveSheet.Cells(lastRow, 1).Select
Set CurrentCell = ActiveSheet.Cells(lastRow, 1)
For n = lastRow To 0 Step -1
If n = lastRow Then GoTo CheckLastRow
If n = 1 Then GoTo CheckfirstRow
ActiveCell.Offset(-2, 0).Select
CheckLastRow:
Set NextCell = CurrentCell.Offset(-1, 0)
ActiveCell.Offset(1, 0).Select
For i = 1 To CurrentCell
ActiveCell.EntireRow.Insert
Next i
With Worksheets("Sheet1")
newYear = .Cells(n, 2).Value
YearDifference = .Cells(n, 3).Value - newYear
For j = 0 To YearDifference - 1
.Cells(n + j, 2).Value = newYear
newYear = newYear + 1
.Cells(n + j, 3).Value = newYear
Next j
End With
Set CurrentCell = NextCell
Next n
'To be performed on the firstrow in the column
CheckfirstRow:
ActiveCell.Offset(-1, 0).Select
For i = 1 To CurrentCell
ActiveCell.EntireRow.Insert
Next i
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
TESTED
First off, you should always avoid using Select and ActiveCell as described here.
Try adding the following loop before your Set CurrentCell = NextCell line:
With Worksheets("Sheet1")
newYear = .Cells(n, 2).Value
YearDifference = .Cells(n, 3).Value - newYear
For j = 0 To YearDifference - 1
.Cells(n + j, 1).Value = .Cells(n, 1).Value
.Cells(n + j, 2).Value = newYear
newYear = newYear + 1
.Cells(n + j, 3).Value = newYear
Next j
End With
You'll need to change the sheet reference as necessary and you should dimension the variables at the beginning of your code.
EDIT
Replace your code with this and it should work:
Sub InsertTest()
Dim LastRow As Long
Dim newYear As Long
Dim YearDifference As Long
Dim n As Long, j As Long
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
With Worksheets("Sheet1")
LastRow = .Cells(Rows.Count, 2).End(xlUp).Row
For n = LastRow To 1 Step -1
If n Mod 10 = 0 Then DoEvents
If .Cells(n, 1).Value <> "" Then
newYear = .Cells(n, 2).Value
YearDifference = .Cells(n, 3).Value - newYear
If YearDifference > 1 Then
Application.StatusBar = "Updating Row #" & n
.Range(.Cells(n + 1, 1), .Cells(n + YearDifference - 1, 15)).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
For j = 0 To YearDifference - 1
.Rows(n + j).Value = .Rows(n).Value
.Cells(n + j, 2).Value = newYear
newYear = newYear + 1
.Cells(n + j, 3).Value = newYear
Next j
End If
End If
Next n
End With
Application.StatusBar = False
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
EDIT 2 - The code now includes a DoEvents line that runs every 10 iterations. This frees up some resources so that the code will run in the background. For a sheet with 27,000 rows like yours, it may take a couple hours to run the code, but you should be able to do other things in the meantime. I've also added a line to update the status bar so you can see which row the code is on.
Related
I have up to 6 cells with potential data coming from 6 different places. I am trying to get only the first three cells with data transferred to another sheet WITH THE ORIGINAL FORMAT Sub Transfer_Data()
Sub Transfer_Data()
Dim i As Long, j As Long
j = 1
For i = 1 To 6
If Sheets("Sheet1").Cells(i, 1).Value <> "" Then
Sheets("Sheet2").Cells(j, 1).Value = Sheets("Sheet1").Cells(i, 1).Value
j = j + 1
End If
If j > 3 Then Exit For
Next i
End Sub
what happens is it displays the sheet2 format and color when im trying to keep sheet1
Try it like this...
Sub Transfer_Data()
Dim i As Long, j As Long
j = 1
For i = 1 To 6
If Sheets("Sheet1").Cells(i, 1).Value <> "" Then
Sheets("Sheet1").Cells(i, 1).Copy
Sheets("Sheet2").Cells(j, 1).PasteSpecial xlPasteFormats
Sheets("Sheet2").Cells(j, 1).PasteSpecial xlPasteValues
j = j + 1
End If
If j > 3 Then Exit For
Next i
Application.CutCopyMode = False
End Sub
Edited code as per the new requirement:
Sub Transfer_Data()
Dim i As Long, j As Long
j = 1
For i = 1 To 6
If Sheets("Sheet1").Cells(i, 1).Value <> "" Then
Sheets("Sheet2").Cells(j, 1).Value = Sheets("Sheet1").Cells(i, 1).Value
Sheets("Sheet2").Cells(j, 1).Interior.Color = Sheets("Sheet1").Cells(i, 1).Interior.Color
j = j + 1
End If
If j > 3 Then Exit For
Next i
End Sub
I'm trying to copy a range from one sheet to another, but ignoring blank rows, and making sure there aren't blank rows in the destination.
After looking on this site, I've successfully used the code below.
However, I want to expand this to a large data range and it seems to take an absolute age. Any ideas on a more efficient code? Slight newbie here!
Thanks!
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.EnableEvents = False
ActiveSheet.DisplayPageBreaks = False
Dim Source As Worksheet
Dim Destination As Worksheet
Dim i As Integer
Dim j As Integer
Set Source = Sheet1
Set Destination = Sheet4
j = 2
For i = 9 To 10000
If Source.Cells(i, 2).Value <> "" Then
Destination.Cells(j, 1).Value = Source.Cells(i, 1).Value
Destination.Cells(j, 2).Value = Source.Cells(i, 2).Value
Destination.Cells(j, 3).Value = Source.Cells(i, 3).Value
Destination.Cells(j, 4).Value = Source.Cells(i, 4).Value
Destination.Cells(j, 5).Value = Source.Cells(i, 5).Value
Destination.Cells(j, 6).Value = Source.Cells(i, 6).Value
Destination.Cells(j, 7).Value = Source.Cells(i, 7).Value
Destination.Cells(j, 8).Value = Source.Cells(i, 8).Value
Destination.Cells(j, 9).Value = Source.Cells(i, 9).Value
j = j + 1
End If
Next i
Application.ScreenUpdating = True
Application.EnableEvents = True
ActiveSheet.DisplayPageBreaks = True
Application.Calculation = xlCalculationAutomatic
End Sub
[Edited to add a bit of clarity]
Replace your for loop with codes below.
Method 1: union all the range you would like to copy, and paste them at once.
Dim copyRange As Range
For i = 9 To 10000
If Source.Cells(i, 2).Value <> "" Then
If copyRange Is Nothing Then
Set copyRange = Source.Range(Source.Cells(i, 1), Source.Cells(i, 9))
Else
Set copyRange = Union(copyRange, Source.Range(Source.Cells(i, 1), Source.Cells(i, 9)))
End If
End If
Next i
copyRange.Copy Destination.Cells(2, 1)
Method 2(recommended): Use an autofilter for filtering the data.
Dim sourceRng As Range
Set sourceRng = Source.Range(Source.Cells(9, 1), Source.Cells(10000, 9))
sourceRng.AutoFilter Field:=2, Criteria1:="<>"
sourceRng.Copy Destination.Cells(2, 1)
Source.AutoFilterMode = False
Looping through worksheet rows is almost the slowest way to process data blocks. The only thing slower is looping through both rows and columns.
I'm not sure how many records you have but this processed 1500 rows of dummy data in ~0.14 seconds.
Option Explicit
Sub Macro4()
Dim wsSource As Worksheet, wsDestination As Worksheet
Dim i As Long, j As Long, k As Long, arr As Variant
On Error GoTo safe_exit
appTGGL bTGGL:=False
Set wsSource = Sheet1
Set wsDestination = Sheet4
'collect values from Sheet1 into array
With wsSource
arr = .Range(.Cells(9, "A"), .Cells(.Rows.Count, "B").End(xlUp).Offset(0, 7)).Value
End With
'find first blank in column B
For j = LBound(arr, 1) To UBound(arr, 1)
If arr(j, 2) = vbNullString Then Exit For
Next j
'collect A:I where B not blank
For i = j To UBound(arr, 1)
If arr(i, 2) <> vbNullString Then
For k = 1 To 9: arr(j, k) = arr(i, k): Next k
j = j + 1
End If
Next i
'clear remaining rows
For i = j To UBound(arr, 1)
For k = 1 To 9: arr(i, k) = vbNullString: Next k
Next i
'put values sans blanks into Sheet4
With wsDestination
.Cells(2, "A").Resize(UBound(arr, 1), UBound(arr, 2)) = arr
End With
safe_exit:
appTGGL
End Sub
Sub appTGGL(Optional bTGGL As Boolean = True)
With Application
.EnableEvents = bTGGL
.ScreenUpdating = bTGGL
.DisplayAlerts = bTGGL
.Calculation = IIf(bTGGL, xlCalculationAutomatic, xlCalculationManual)
End With
Debug.Print IIf(bTGGL, "end: ", "start: ") & Timer
End Sub
Recently, I have been trying to code a VBA to assist me in summing a column and divide by counter to get average. However, I have a new requirement that is it is only going to sum up those that are visible. Any idea on how should I proceed? Below is my code,
Sub test3()
Dim FinalRow As Long
Dim Row As Long
Dim counter As Integer
Dim total As Double
counter = 3
total = 0
Dim i As Double
FinalRow = Range("C65536").End(xlUp).Row
For Row = 3 To FinalRow
If Not IsEmpty(ActiveSheet.Cells(counter, "C")) And Not IsEmpty(ActiveSheet.Cells(Row + 1, "C")) Then
If ActiveSheet.Cells(counter, "B").Value = True Then
ActiveSheet.Cells(Row, "M").Value = 100
For i = counter To Row
If IsEmpty(ActiveSheet.Cells(i, "F")) Then
With ActiveSheet.Cells(i, "F")
.Value = Now
.NumberFormat = "dd/mm/yy"
If (.Value - .Offset(0, 2).Value) >= 0 Then
.Font.color = vbRed
Else
.Font.color = vbBlack
End If
End With
End If
Next i
End If
If (ActiveSheet.Cells(Row, "L").Value = 100) Then
For i = counter To Row
If IsEmpty(ActiveSheet.Cells(i, "F")) Then
With ActiveSheet.Cells(i, "F")
.Value = Now
.NumberFormat = "dd/mm/yy"
If (.Value - .Offset(0, 2).Value) >= 0 Then
.Font.color = vbRed
Else
.Font.color = vbBlack
End If
End With
End If
Next i
End If
If Not (ActiveSheet.Cells(counter, "B").Value) = True Then
ActiveSheet.Cells(counter, "M").Value = (Application.Sum(Range(ActiveSheet.Cells(counter, "L"), ActiveSheet.Cells(Row, "L")))) / (Row + 1 - counter)
End If
counter = Row + 1
End If
Next
End Sub
This testcode works for me, just change it as you need it:
Sub TestSumme()
Dim Summe As Long
Summe = Application.WorksheetFunction.Sum(ThisWorkbook.Sheets(1).Range("A1:A6").SpecialCells(xlCellTypeVisible))
MsgBox (Summe)
End Sub
I have an excel sheet but all the data came in on Row 1. I need to move every 16th Column to the next row. So my data is supposed to be in Columns 1 thru Column 15. I'm not very Excel savvy so please bear with me.
Sub dividde_16()
No_of_columns = Cells(1, Columns.Count).End(xlToLeft).Column
No_of_rows = Int(No_of_columns / 15) + 1
For i = 1 To No_of_rows
For j = 1 To 15
Cells(i + 1, j) = Cells(i * 15 + j)
Next
Next
Range(Cells(1, 16), Cells(1, No_of_columns)) = ""
End Sub
You might be able to try something like this:
Sub Move_to_Columns()
Dim lR As Long, R As Range
lR = Range("A" & Rows.Count).End(xlUp).Row
Set R = Range("A1", "A" & lR)
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
For Each C In R
If C.Row Mod 16 = 0 Then
C.Offset(-1, 1).Value = C.Value
C.ClearContents
End If
Next C
Application.Calculation = xlCalculationAutomatic
End Sub
But with columns instead of rows.
My objective is to copy values from cells in sheet 1 "B5" onwards and paste it to sheet 2 "C11" onwards below is the code not working properly
Sub SCMPROCUREMENT()
' SUPPLY CHAIN MANAGEMENT PROCUREMENT
Worksheets("Sheet1").Select
Range("B5:B100000").Select
finalrow = Cells(Rows.Count, 2).End(xlUp).Row
For x = 5 To finalrow
If Worksheets("sheet1").Cells(x, 2).Font.Bold = False Then
Worksheets("sheet1").Select
Cells(x, 2).Select
Selection.Copy
ThisWorkbook.Worksheets("Sheet2").Range("C11").Select
ActiveSheet.Paste
End If
Next x
End Sub
a) your ThisWorkbook.Worksheets("Sheet2").Range("C11") doesn't work like that
b) you need a counter for the second list, otherwise you keep overwriting C11
Sub SCMPROCUREMENT()
' SUPPLY CHAIN MANAGEMENT PROCUREMENT
Dim count As Integer
For x = 5 To Worksheets("Sheet1").Cells(Rows.count, 2).End(xlUp).Row
If Worksheets("Sheet1").Cells(x, 2).Font.Bold = False Then
Worksheets("Sheet1").Cells(x, 2).Copy
Worksheets("Sheet2").Cells(11 + count, 3).Select
ActiveSheet.Paste
count = count + 1
End If
Next x
End Sub
Sub SCMPROCUREMENT()
' SUPPLY CHAIN MANAGEMENT PROCUREMENT
Application.ScreenUpdating = False
Dim count As Integer
With Worksheets("Sheet1")
For x = 5 To .Cells(Rows.count, 2).End(xlUp).Row
If .Cells(x, 2).Font.Bold = False Then
.Cells(x, 2).Copy Worksheets("Sheet2").Cells(11 + count, 3)
count = count + 1
End If
Next x
End With
Application.ScreenUpdating = True
End Sub