Hi I have tired creating a loop which copies the entire row and pastes it in another worksheet, dependent upon two things.
Firstly, there is a level of completion column, if the values are not equal to 100% then they should be copied, also I only want rows copied that are not blank.
Having copied the rows into the next sheet, I want to run through column B and each time the value changes there should be inserted a new blank row.
I am not sure whether you can use this kind of loop this way, any input would be greatly appreciated.
Sheets("Tracker").Activate
For Each c In Range("H:B")
If c.Value <> "100%" _
And c.Offset(0, -6) <> "" Then
EntireRow.Select
Application.CutCopyMode = xlCopy
Selection.Copy
End If
Next
Sheets("Project Overview").Activate
Range("A24").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("Project Overview").Activate
For Each b In Range("B24:B")
If b.Value <> "" Then
Selection.Insert Shift:=xlDown
End If
Next
End Sub
First, the line For Each c In Range("H:B") will loop through every cell in columns B-H. Is this really what you want? I don't think so. It will take your code forever to loop through that! It will also check your conditions for each and every cell!
Try the code I have pasted below. It uses AutoFilter which is much faster and more reliable, along with the SpecialCells, method to copy and paste the data.
When you insert the rows, you need to step backward from the last row to the beginning. This is because when Excel insert rows it will through your original counter off.
Sub FilterCopy()
Dim wT As Worksheet, wPO As Worksheet
Set wT = Sheets("Tracker")
Set wPO = Sheets("Project Overview")
With wT
Dim lRow As Long
lRow = .Range("B" & .Rows.Count).End(xlUp).Row
With .Range("B1:H" & lRow)
.AutoFilter 7, "<>100%" '7th column not 100% (column H)
.AutoFilter 1, "<>" '1st column not blank (column B)
End With
Intersect(.UsedRange,.UsedRange.Offset(1), .Range("B1").EntireColumn).SpecialCells(xlCellTypeVisible).EntireRow.Copy
End With
With wPO
.Range("A24").PasteSpecial xlPasteValues
lRow = .Range(.Range("B24"), .Range("B" & .Rows.Count).End(xlUp)).Rows
Dim i As Integer
For i = lRow To 24 Step -1
If .Range("B" & i) <> "" Then .Range("B" & i).Insert Shift:=xlDown
Next
End With
End Sub
Related
So I am trying to create a macro that will autofilter a range of data (in Column E) for predefined headers that start at Column N. So the autofilter runs filtering the data in column e for the title in column n, it then copies and pastes that data into column n, then loops and does the same for column o and so on. The issue I am having, is if the filter runs, and there are no matches for the autofilter it creates an error. Strangely, I used if error go to, and for one blank column it works perfectly, however if there are two blank columns as such, then it fails the second time around. I have posted the code below. Does anyone have any suggestions?
Sub Siglum_Sorter()
Sheets("Operator Database").Select
Dim rRng1 As Range
Dim rRng2 As Range
Dim fCol As Long
fCol = 13
Set rRng1 = Range("E:E")
Set rRng2 = Range("G2:G100")
Do
On Error GoTo SkipToHere
fCol = fCol + 1
rCrit = Cells(1, fCol)
MsgBox "cells " & fCol & " " & rCrit
With rRng1
.AutoFilter field:=1, Criteria1:=rCrit, Operator:=xlOr
rRng2.SpecialCells(xlCellTypeVisible).Copy 'or do something else
End With
Cells(2, fCol).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
SkipToHere:
Loop Until IsEmpty(Cells(1, fCol))
End Sub
Dim rngF As Range
With rRng1.AutoFilter field:=1, Criteria1:=rCrit, Operator:=xlOr
Set rngF = Nothing
On Error Resume Next 'ignore any error if no visible cells
Set rngF = rRng2.SpecialCells(xlCellTypeVisible)
On Error Goto 0
If Not rngF Is Nothing Then
'do something with rngF
Else
'no visible cells...
End If
I would just add a a check after the filter to see if the last visible row is the data headers. If so, don't copy the data
Dim lrow_data as long
lrow_data = ThisWorkbook.Sheets("Sheet1").Cells(Cells.Rows.Count,1).End(xlUp) 'or change it to your needed sheet
If lrow_data = 1 Then
'Do Nothing, last row is the headers
Else
rRng2.SpecialCells(xlCellTypeVisible).Copy
End If
I have an Excel Sheet wherein column "A" contains Serial numbers. One serial number may repeat to several rows. The cells in column "A" are merged [if more than one rows are appearing for One serial number]. I have made following macro to UN-merge these cells and repeat the serial number in subsequent blank rows until next serial number appears. The problem I am facing is that this macro is running very slow e.g. for a sheet containing 30,000 rows it may take a very long time. Is there a neat and less slower way to do it?
Here is the code I am using. Please guide.
Sub Unmerge_Cell()
Dim NumRows As Integer
Range("B2").Select
NumRows = Range("B2", Range("B2").End(xlDown)).Rows.Count
Columns("A:A").Select
Selection.UnMerge
Range("A2").Select
Range("A2").Activate
For i = 1 To NumRows - 1
If IsEmpty(ActiveCell.Offset(1, 0).Value) = True Then
ActiveCell.Select
Selection.Copy
ActiveCell.Offset(1, 0).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Else
ActiveCell.Offset(1, 0).Select
ActiveCell.Offset(0, 0).Activate
End If
Next
Range("A1").Select
End Sub
Regards
This should be the fastest solution, no loop, simple.
Sub unMerge()
Dim lastRow As Long
lastRow = Range("B2").End(xlDown).Row
Range("A:A").unMerge
Range("A2:A" & lastRow).SpecialCells(xlCellTypeBlanks).FormulaR1C1 = "=r[-1]c"
With Range("A2:A" & lastRow)
.Value = .Value 'convert formula to constant
End With
End Sub
I tried to simplyfy your code. I haven't tested it in Excel ;-/
Sub Unmerge_Cell()
Dim NumRows As Integer
Dim i as Long
NumRows = Range("B2", Range("B2").End(xlDown)).Rows.Count
For i = 1 To NumRows - 1
If IsEmpty(Range("A2").Offset(i,0).Value) Then
Range("A2").Offset(i,0).Value = Range("A2").Offset(i-1,0).Value
End If
Next
End Sub
You can also turn off and turn on the screen updating when you macro is running
At the beginning on your code insert
application.screenupdating = false
And turn it on at the end
application.screenupdating = true
I have a spreadsheet with a column of values that I would like to divide by a fixed cell (say C3), and have the results in an adjacent column.
I would like this code to run to the last available row (with values) as well.
Would greatly appreciate any help! Thanks!
If your source values were in, for instance, A1:A7 and you want to copy them to B1:B7 and divide by C3 at the same time, you could:
With ActiveSheet
'Determine last row
Dim lastRow As Long
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
'Copy the original values from column A to column B
.Range("B1:B" & lastRow).Value = .Range("A1:A" & lastRow).Value
'Copy / Pastespecial Divide using cell C3
.Range("C3").Copy
.Range("B1:B" & lastRow).PasteSpecial Paste:=xlPasteValues, _
Operation:=xlDivide, _
SkipBlanks:=False, _
Transpose:=False
Application.CutCopyMode = False
End With
You can use Do While
Do While Cells(iCol, 3).Value <> ""
'Do some thing
iCol = iCol + 1
Loop
On the same worksheet, I'm trying to compact all my cell data, i.e. move all the cells with value to be next to each other instead of spread apart. The original sheet looks like this:
The desired output would be something like this:
I have tried below code to solve this problem, and sorry I'm new here so don't know how to ask the question
Sub SelectRangea()
Sheets("Sheet1").Select
Range("a1:cf1").Select
Application.CutCopyMode = False
Selection.Copy
With Sheets("Sheet1")
lst = .Range("A" & Rows.Count).End(xlUp).Row + 1
.Range("A" & lst).PasteSpecial xlPasteColumnWidths
.Range("A" & lst).PasteSpecial xlPasteValues
End With
End Sub
This code solves the problem as per your sample data.
Dim c As Long
c = 1
With Worksheets("sheet6")
c = .Cells(1, c).End(xlToRight).End(xlToRight).Column
Do While c < .Columns.Count
With .Range(.Cells(1, c), .Cells(1, c).End(xlToRight))
.Parent.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Resize(1, .Columns.Count) = .Cells.Value
.Clear
End With
c = .Cells(1, c).End(xlToRight).Column
Loop
End With
If one of the 'islands' of data in the first row is a single cell then you will have to accommodate that special condition.
I'm taking data that is listed across multiple columns and putting it into a single column (A). If there is data in column B, it grabs that data, sticks it at the end of the data in column A, then goes back and deletes the now empty column B, which moves all the other columns over one so now there is data in column B again, up until the point there are no more columns of data except for column A. The way I'm doing this currently is by listing multiple blocks of the same code below which is not efficient obviously and sooner or later the code will break. Any advice is appreciated!!
Range("B1").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Cut
Range("A1").Select
Selection.End(xlDown).Select
ActiveCell.Offset(1, 0).Range("A1").Select
ActiveSheet.Paste
Selection.End(xlUp).Select
ActiveCell.Offset(0, 1).Columns("A:A").EntireColumn.Select
Selection.Delete Shift:=xlToLeft
ActiveCell.Offset(0, -1).Range("A1").Select
I like Christmas007's answer. I wanted to share this solution too:
Sub MoveIt()
Dim mysht As Worksheet
Set mysht = ActiveSheet
Set myrng = mysht.UsedRange
nextrow = mysht.Cells(mysht.Rows.Count, 1).End(xlUp).Row
For i = 2 To myrng.Columns.Count
lastColrow = myrng.Cells(mysht.Rows.Count, i).End(xlUp).Row
If lastColrow <> 1 Or myrng.Cells(1, i) <> "" Then
For j = 1 To lastColrow
nextrow = nextrow + 1
mysht.Cells(nextrow, 1) = myrng.Cells(j, i)
Next j
End If
Next i
Range(myrng.Columns(2), myrng.Columns(myrng.Columns.Count)).Clear
End Sub
I like it because it doesn't use the copy, paste, and delete functions. In my experience these functions start to cause the macro to drag if you are dealing with big workbooks and they also require that the sheet is activated.
There is a pretty simple way to do this:
Sub MoveIt()
Dim LastRow As Long
Dim ws1 as Worksheet
Set ws1 = Sheets("Name of Sheet")
Do While (ws1.Range("B1").Value <> "")
LastRow = ws1.Range("A" & ws1.Rows.Count).End(xlUp).Row + 1
ws1.Range("B1:B" & ws1.Range("B" & ws1.Rows.Count).End(xlUp).Row).Copy
ws1.Range("A" & LastRow).PasteSpecial
ws1.Range("B1").EntireColumn.Delete xlToLeft
Loop
End Sub