Stack data and add break lines - excel

I want to combine two separate macro's into one macro with one button.
I put some data in A1, then the first code stacks them under each other.
The second code separates them by adding a break line every 5 lines.
First macro:
Dim Rng1 As Range, Rng2 As Range, rng As Range
Dim RowIndex As Integer
Set Rng1 = Application.Selection
Set Rng1 = Application.InputBox("Select Range:", "StackDataToOneColumn",
Rng1.Address, Type:=8)
Set Rng2 = Application.InputBox("Destination
Column:", "StackDataToOneColumn", Type:=8)
RowIndex = 0
Application.ScreenUpdating = False
For Each rng In Rng1.Rows
rng.Copy
Rng2.Offset(RowIndex, 0).PasteSpecial Paste:=xlPasteAll, Transpose:=True
RowIndex = RowIndex + rng.Columns.Count
Next
Application.CutCopyMode = False
Application.ScreenUpdating = True
Second macro:
Dim rng As Range
Dim CountRow As Integer
Dim i As Integer
Set rng = Selection
CountRow = rng.EntireRow.Count
For i = 1 To CountRow / 2
ActiveCell.Offset(4, 0).EntireRow.Insert
ActiveCell.Offset(5, 0).Select
Next i
End Sub
Example of data input and output:

You can do it like this:
Sub test()
'code to specify what range you want to copy
Dim MyRange As Range
Dim rng As Range
Dim i As Long
Dim ZZ As Long
Set MyRange = Range("A3").CurrentRegion 'this will be rng to be transposed
'code to positionate into target cell from sheet2
'
'
'
'in this example, my target cell will be A9, so it will be Range("A9")
i = 9
ZZ = MyRange.Cells(1, 1).Row 'top row of range
For Each rng In MyRange
If rng.Row <> ZZ Then
i = i + 1 'we add extra plus 1 so we skip 1 cell and make breakline
ZZ = rng.Row 'we update zz
End If
rng.Copy
Range("A" & i).PasteSpecial xlPasteAll
i = i + 1
Next rng
Set MyRange = Nothing
End Sub
After executing code I get:
You just need to adapt it to work on different sheets.
The trick here is detecting when you want to leave a blank cell, and it's every time you change row on your original range. So if your original range is a range of 3x5 cells, you will leave 1 blank when switching from row 1 to 2, and another one when switching from row 2 to 3.
Property rng.row will return the absolute row number, referenced to whole worksheet.
Property MyRange.Cells(1,1).Row will return the first row number of your fist top cell on your range, so you can know where it starts. With that, then you can easily track when it has switched rows when looping :)

Related

Copy first Row of Each Data after every empty Row

I have been trying to copy the first highlighted row of each new data after empty row and i have looked around to find a way which could do this but cannot find.
I can do this manually by putting name of rows to copy but code should be dynamic because rows order can be changed but there must be empty rows after new data.
Any help will be appreciated.
after copying and pasting the result would be like this.
My try
Sub copynextfirstrow()
lastRow = Sheets("Sheet1").Cells(.Rows.Count, "A").End(xlUp).Row
Sheets("Sheet1").Range("A1:A" & lastRow).Copy
Sheets("Sheet2").Range("A1").Cells.PasteSpecial
End Sub
Try the next code, please:
Sub copynextfirstrow()
Dim sh1 As Worksheet, sh2 As Worksheet, lastRow As Long, i As Long, rngCopy As Range
Set sh1 = Sheets("Sheet1")
Set sh2 = Sheets("Sheet2")
lastRow = sh1.cells(sh1.rows.count, "A").End(xlUp).row
For i = 1 To lastRow
If WorksheetFunction.CountA(sh1.rows(i)) = 0 And WorksheetFunction.CountA(sh1.rows(i + 1)) > 0 Then
If rngCopy Is Nothing Then
Set rngCopy = sh1.rows(i + 1)
Else
Set rngCopy = Union(rngCopy, sh1.rows(i + 1))
End If
ElseIf i = 1 And WorksheetFunction.CountA(sh1.rows(i)) > 0 Then
Set rngCopy = sh1.rows(i)
End If
If Not rngCopy Is Nothing Then
rngCopy.Copy
sh2.Range("A1").cells.PasteSpecial
End If
End Sub
It should be fast enough, firstly making a Union of the rows to be copied and pasting all the range at once.
I couldn't understand that an empty row is one having only a cell in A:A empty, so I created a piece of code which considers an empty row the one not having any record on all columns...
Quick example: search for blank cells and see if offset values exist:
Sub Blah()
Dim Cell As Range
Dim rng As Range
Set rng = Application.Intersect(Sheets("Sheet1").UsedRange, Sheets("Sheet1").Range("A:A")).SpecialCells(xlCellTypeBlanks)
For Each Cell In rng
If Cell.Offset(1, 0) <> "" Then Debug.Print Cell.Offset(1, 0)
Next Cell
End Sub

For every blank cell in column, run an auto fill macro

To this:
I would like the set of code to be able to pick up every blank in column C and perform a macro in it. It would have been easy if my sheet has a fixed range, however, my list is constantly increasing in rows... Hence, I would need the macro to be able to run macro on blank cells and skip on those filled cells. The macro should also end upon the last filled cell in the column.
Sub Testing()
Dim Rl As Long ' last row
Dim Tmp As Variant
Dim R As Long ' row counter
With ThisWorkbook.ActiveSheet ' modify to suit
Rl = .Cells(.Rows.Count, "C").End(xlUp).Row
' work on column C
For R = 1 To Rl ' start the loop in row 1
Tmp = .Cells(R, "C").Value
If Len(Tmp) Then
Cells(R, "C").Select
Call AutoFill
End If
Next R
End With
Sub AutoFill()
Application.EnableEvents = False
Dim rng As Range
Set rng = Range(Selection, Selection.End(xlDown))
Set rng = rng.Resize(rng.Rows.Count - 1, rng.Columns.Count)
rng.FillDown
End Sub
Your problem is here: If Len(Tmp) Then and that's just checking if Tmp has any length. So this actually ignores your empty cells by skipping them. Instead you are selecting cells with values in them.
Do not loop all cells in a range. Instead just look at those empty cells of interest. For example:
Sub Testing()
Dim LR As Long, LC as Long
Dim rng As Range
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
With ws
LR = .Cells(.Rows.Count, "A").End(xlUp).Row
LC = .Cells(LR, .Columns.Count).End(xlToLeft).Column
Set rng = .Range(.Cells(1, 1), .Cells(LR, LC))
If WorksheetFunction.CountBlank(rng) > 0 Then
For Each area In rng.SpecialCells(xlCellTypeBlanks).Areas
area.Offset(-1).Resize(area.Rows.Count + 1).FillDown
Next
End If
End With
End Sub
As you can see I left out .Select and ActiveSheet as that's poor coding and usually not needed at all.

How to Write Excel Macro to Delete Entire Row if cell Value Equals ""

I would like to have a macro that deletes an entire row of the cell value equals "" for multiple ranges. Ranges are "B16:B115, B131:B230, B250:B349".
Logic:
If cell equals "" then delete the entire row.
I want the row actually deleted and not just the contents of the cells.
Thank you.
This would be worth trying:
On Error Resume Next
Range("B16:B115,B131:B230,B250:B349").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
On Error Goto 0
Depending on whether the "" cells have formulas or are just empty.
Range.SpecialCells: What does xlCellTypeBlanks actually represent?
EDIT: if you have formulas then you have to go the long way round:
Sub DeleteEmpty()
Dim c As Range, rngDel As Range
For Each c In Range("B16:B115,B131:B230,B250:B349").Cells
If Len(c.Value) = 0 Then
If rngDel Is Nothing Then
Set rngDel = c
Else
Set rngDel = Application.Union(rngDel, c)
End If
End If
Next c
If Not rngDel Is Nothing Then rngDel.EntireRow.Delete
End Sub
Following sub will allow you to select range to delete blank rows.
Sub RemoveBlanks()
Dim rng As Range, rws As Long, i As Long
Dim LastRow As Range
Dim myRange As Range
Set myRange = Application.InputBox(prompt:="Select Header Cell To Remove Blanks.", Type:=8)
'LastRow = Cells(Rows.Count, "A").End(xlUp).Row
Set LastRow = Cells(Rows.Count, myRange.Column).End(xlUp)
Set rng = ActiveSheet.Range(myRange.Address & ":" & LastRow.Address)
rws = rng.Rows.Count
For i = rws To 1 Step (-1)
If WorksheetFunction.CountA(rng.Rows(i)) = 0 Then rng.Rows(i).EntireRow.Delete
Next
Set myRange = Nothing
Set LastRow = Nothing
Set rng = Nothing
End Sub

Delete column based on row value

I have a sheet containing data. I want to delete the columns based on row value.
My code doesn't stop and when I hit escape, it has deleted all of the column from my starting columns.
I want to check values in row 2 from column D to the last used column (I have about 100 columns now) that if they contain C15, C17 and so on then don't do anything, else, delete the columns.
I only have 40k rows. My range, column and row will expand every week so I want to use VBA to cut down formatting time.
Sub test()
'start
Dim LR1 As Long
Dim i As Long
Set ws = ThisWorkbook.ActiveSheet
With ws
LR1 = .Cells(2, .Columns.Count).End(xlToLeft).Column
Dim arr As Variant
Dim x
arr = Array("C15", "C17", "C19", "C20", "C21", "C22", "C23", "C24", "C25", "C28", "C29", "C30", "C32")
For x = LBound(arr) To UBound(arr)
For i = LR1 To 4 Step -1
If .Cells(2, i).Value = arr(x) Then
Else
.Columns(i).Delete
End If
Next i
Next x
End With
End Sub
Besides all the points made in the comments, the main issue is that your looping logic is off. Your outer loop should be the columns, and the inner loop should be the array. But with Select Case this can be simplified this to just one loop anyway.
Perhaps something like this:
Option Explicit
Sub Test()
Dim ws As Worksheet
Set ws = ThisWorkbook.ActiveSheet
With ws
Dim lastCol As Long, i As Long
Dim rng As Range
lastCol = .Cells(2, .Columns.Count).End(xlToLeft).Column
For i = lastCol To 4 Step -1
Select Case .Cells(2, i).Value
Case "C15", "C17", "C19", "C20", "C21", "C22", "C23", "C24", "C25", "C28", "C29", "C30", "C32"
' keep
Case Else
If rng Is Nothing Then
Set rng = .Columns(i)
Else
Set rng = Union(rng, .Columns(i))
End If
End Select
Next i
If Not rng Is Nothing Then
rng.Delete
End If
End With
End Sub

Select and copy row directly above matching value

I have a working code that looks for a value and copies the entire row, pasting it to the relevant sheet.
I would like to amend the code, so that it copies the entire row above the found value, rather than the row of the value.
Can anyone suggest a simple amendment to allow me to select the row above?
Sub Prod()
Sheets("BJ").Cells.Clear
Sheets("Master").Range("A1:A2").EntireRow.Copy Destination:= _
Sheets("BJ").Range("A1")
Dim MyRange, MyRange1 As Range
Sheets("Master").Select
LastRow = Sheets("Master").Range("K65536").End(xlUp).Row
Set MyRange = Sheets("Master").Range("M1:Q325" & LastRow)
For Each c In MyRange
If c.Value = "BJ" Then
If MyRange1 Is Nothing Then
Set MyRange1 = c.EntireRow
Else
Set MyRange1 = Union(MyRange1, c.EntireRow)
End If
End If
Next
If Not MyRange1 Is Nothing Then MyRange1.Copy Sheets("BJ").[a3]
End Sub
Here is one way to copy the row directly above the ActiveCell to the next open row of another worksheet:
Sub Dural()
Dim sh2 As Worksheet, N As Long
Set sh2 = Sheets("Destynation")
N = sh2.Cells(Rows.Count, "A").End(xlUp).Row + 1
If ActiveCell.Row = 1 Then
MsgBox "Nothing above"
Exit Sub
End If
ActiveCell.Offset(-1, 0).EntireRow.Copy sh2.Cells(N, 1)
End Sub

Resources