Transpose VBA Excel Macro based on condition - excel

I am trying to copy & transpose values from one Sheet to another Sheet based on a condition, only transpose the first 4 lines looping in large range.
From this:
To this :
I've found a transpose macro and adapt it but I couldn't apply the condition.
Sub Test()
Set rng = Range("B5", Range("B5").End(xlDown))
Sheets("Example #2").Range(rng).Value = WorksheetFunction.Transpose()
EndSub
Anyone can guide me? Any help would be greatly appreciated!

Please, test the next code. It uses arrays, works in memory and will be much faster than copying. This can be easier observed on a large range:
Sub CopyTranspose4rows()
Dim sh1 As Worksheet, sh2 As Worksheet, lastR As Long, arr, arrSl, i As Long
Set sh1 = ActiveSheet 'use here the sheet you need to copy from
Set sh2 = sh1.Next 'use here what sheet you need to paste
lastR = sh1.Range("B" & sh1.rows.count).End(xlUp).row 'last row sh1
arr = sh1.Range("B5:B" & lastR).Value 'put the range in an array for fast iteration
For i = 1 To UBound(arr) Step 4 'iterate from four to four
With Application
'create a slice array
arrSl = .Transpose(.Index(arr, Evaluate("row(" & i & ":" & i + 4 & ")"), 1))
End With
'drop the slice array content in the second sheet
sh2.Range("A" & sh2.rows.count).End(xlUp).Offset(1).Resize(1, 4).Value = arrSl
Next i
sh2.Activate 'activate the sheet where pasted
End Sub

#FaneDuru's array solution is more elegant, but here's another alternative. You would need to replace the sheet names and the starting cell numbers.
Sub TestTranspose()
Dim sht1 As Worksheet
Dim sht2 As Worksheet
Dim LR1 As Long
Dim x As Long
Set sht1 = ThisWorkbook.Worksheets("Sheet1")
Set sht2 = ThisWorkbook.Worksheets("Sheet2")
LR1 = sht1.Cells(Rows.Count, 2).End(xlUp).Row
y = 1
For x = 1 To LR Step 4
sht1.Range(sht1.Cells(x, 2), sht1.Cells(x + 3, 2)).Copy
sht2.Cells(y, 1).PasteSpecial Paste:=xlPasteAll, Transpose:=True
y = y + 1
Next x
End Sub

With this code you can have different number of answers per question.
Sub Tranpose_Questions()
Dim fnd As String, FirstFound As String
Dim FoundCell As Range, rng As Range
Dim myRange As Range, LastCell As Range
Dim transRng As Range ' range to transpose
Dim dstRng As Range: Set dstRng = ActiveSheet.Range("C1") ' destination cell
' Value find
fnd = "Question"
Set myRange = ActiveSheet.Range("A1", Range("A1").End(xlDown))
Set LastCell = myRange.Cells(myRange.Cells.Count)
Set FoundCell = myRange.Find(what:=fnd, after:=LastCell)
' Test to see if anything was found
If Not FoundCell Is Nothing Then
FirstFound = FoundCell.Address
Else
GoTo errHandler
End If
Set rng = FoundCell
' Loop
Do Until FoundCell Is Nothing
' Find next cell
Set FoundCell = myRange.FindNext(after:=FoundCell)
Debug.Print rng.Address, FoundCell.Address
' Test to see if cycled through to first found cell
If FoundCell.Address = FirstFound Then
Set transRng = Range(rng, rng.End(xlDown))
If rng.Offset(1, 0) <> "" Then
transRng.Select: transRng.Copy
dstRng.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=True
Application.CutCopyMode = False
End If
Exit Do
End If
' Transpose
Set transRng = rng.Resize(FoundCell.Row - rng.Row, 1)
transRng.Copy
dstRng.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=True
Application.CutCopyMode = False
' update rng position
Set rng = FoundCell
' update destination range
Set dstRng = dstRng.Offset(1, 0)
Loop
Exit Sub
' Error Handler
errHandler:
MsgBox "No 'Question' found!"
End Sub

Related

Copy paste date value to last row in nested loop

Got a bunch of worksheets in the same workbook that have a specific range of interest that starts with finding string 'Green'. Let's call this Range (A) that I'm interested in copying and pasting into a master sheet to form a database in same workbook. I found some useful code and got this part to work gr8!
There is a date value in each worksheet in cell(3,3). What's missing is adding this date value from each worksheet and past it to column B in the master sheet 'Main' such that the date value extends to match the length of the pasted Range (A).
all help is appreciated
Sub FindRangeHistory()
'// in MainDB workbook for each trade sheet, copy and paste specific range into 'Main' sheet
Dim fnd As String, faddr As String
Dim rng As Range, foundCell As Range
Dim ws As Worksheet
Dim ws_count As Integer, i As Integer
ws_count = ThisWorkbook.Worksheets.Count
For i = 1 To ws_count
With ThisWorkbook
'initialize main sheet and keyword search
Set ws = .Worksheets("Main")
fnd = "New Life"
'Search for keyword in sheet
With .Worksheets(i)
Set foundCell = .Cells.Find(What:=fnd, after:=.Cells.SpecialCells(xlCellTypeLastCell), _
LookIn:=xlFormulas, LookAt:=xlWhole, _
SearchOrder:=xlByRows, SearchDirection:=xlNext)
'Test to see if anything was found
If Not foundCell Is Nothing Then
faddr = foundCell.Address
Set rng = .Range(foundCell, foundCell.End(xlDown))
Do
Set rng = Union(rng, .Range(foundCell, foundCell.End(xlDown)).Resize(, 7))
Set foundCell = .Cells.FindNext(after:=foundCell)
Loop Until foundCell.Address = faddr
Set rng = rng.Offset(1, 0)
rng.Copy
ws.Cells(Rows.Count, "C").End(xlUp).PasteSpecial Paste:=xlPasteValues
Worksheets(i).Cells(3, 3).Copy
ws.Cells(Rows.Count, "B").End(xlUp).PasteSpecial Paste:=xlPasteValuesAndNumberFormats
End If
End With
End With
Next i
End Sub
You could do it like this:
'...
'...
Dim nextRowC As Long, lastRowC As Long
nextRowC = ws.Cells(Rows.Count, "C").End(xlUp).Row + 1 'first empty row in ColC before paste
rng.Copy
ws.Cells(nextRowC, "C").PasteSpecial Paste:=xlPasteValues
lastRowC = ws.Cells(Rows.Count, "C").End(xlUp).Row 'last used row in ColC after paste
.Worksheets(i).Cells(3, 3).Copy
ws.Range(ws.Cells(nextRowC, "B"), ws.Cells(lastRowC, "B")). _
PasteSpecial Paste:=xlPasteValuesAndNumberFormats
'...
'...

Excel VBA - Find and copy non-matching rows to another worksheet

I would like to compare 2 columns in the same worksheet, search for non-matching values in column A when compared to column D and copy the entire rows of these non-matching values in column A to another worksheet.
Here is a sample of the worksheet:
Therefore, I would like to compare column A with column D, find the values which do not match and copy the entire corresponding rows from Columns A and B to a new worksheet.
*Edit, I forgot to include my code
Dim CopyToRow As Integer
Dim rng1 As Range
Dim rng2 As Range
Dim cell As Range
Dim found As Range
'Start copying data to row 2 in Sheet2 (row counter variable)
CopyToRow = 2
Set rng1 = Range(ActiveSheet.Cells(2, 1), ActiveSheet.Cells(2, 1).End(xlDown))
Set rng2 = Range(ActiveSheet.Cells(4, 2), ActiveSheet.Cells(4, 2).End(xlDown))
For Each cell In rng1
Set found = rng2.Find(what:=cell, LookIn:=xlValues, lookat:=xlWhole, MatchCase:=False)
If Not found Is Nothing Then
cell.EntireRow.Copy Destination:=Sheets("Sheet2").Range("A" & CopyToRow)
CopyToRow = CopyToRow + 1
End If
Next cell
Many thanks and much appreciated!
I agree with Ron Rosenfeld that you should have demonstrated your own attempt. That being said, perhaps this will be of some help to you. Not the most elegant but should work provided you update references to your own sheet names.
Sub SOPractice()
Dim SearchCell As Range 'each value being checked
Dim SearchRng As Range 'column A
Dim LastRow As Long
Dim MatchFound As Range
Dim i As Long: i = 1
LastRow = YourSheet.Range("A" & Rows.Count).End(xlUp).Row
With YourSheet
Set SearchRng = .Range(.Cells(2, 1), .Cells(LastRow, 1))
Application.ScreenUpdating = False
For Each SearchCell In SearchRng
Set MatchFound = .Range("D:D").Find _
(What:=SearchCell.Value, LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False)
If MatchFound Is Nothing Then 'No match hence copy to other sheet
.Range(SearchCell.Address, SearchCell.Offset(, 1)).Copy
YourCopyToSheet.Cells(i, 1).PasteSpecial xlPasteAll
i = i + 1
End If
Next SearchCell
End With
Application.ScreenUpdating = True
Application.CutCopyMode = False
End Sub
I have also found a solution, using a Dictionary object:
Dim Cl As Range, Rng As Range, Dic As Object
Set Dic = CreateObject("scripting.dictionary")
With Dic
For Each Cl In MyWorksheet1Name.Range("D2", MyWorksheet1Name.Range("D" & Rows.Count).End(xlUp))
.Item(Cl.Value) = Empty
Next Cl
For Each Cl In MyWorksheet1Name.Range("A2", MyWorksheet1Name.Range("A" & Rows.Count).End(xlUp))
If Not .Exists(Cl.Value) Then
If Rng Is Nothing Then Set Rng = Cl Else Set Rng = Union(Rng, Cl)
End If
Next Cl
End With
If Not Rng Is Nothing Then
Rng.EntireRow.Copy MyWorksheet2Name.Range("A" & Rows.Count).End(xlUp)
End If
Cheers!

Looping in text filter

I have this code which cuts and pastes an entire row to another sheet. When i set values as = it works, but when i set to like or contains, the loop doesnt happen. The value of the filter i'm looking for would keep changing including with a unique phrase. Eg: 1. Overlap error: 1234, 1. Overlap error:1235 etc.
Sub loopMe()
Dim sh As Worksheet, ws As Worksheet
Dim LstR As Long, rng As Range, c As Range
Set sh = Sheets("Sheet1") 'set the sheet to loop
Set ws = Sheets("Sheet2") 'set the sheet to paste
With sh 'do something with the sheet
LstR = .Cells(.Rows.Count, "BE").End(xlUp).Row 'find last row
Set rng = .Range("BE5:BE" & LstR) 'set range to loop
End With
'start the loop
For Each c In rng.Cells
'If c = "1. Overlap error:" Then
If c.Value Like "*1. Overlap error:*" Then
'If Left(c.Value, 17) = "1. Overlap error:" Then
'If InStr(1, c, "1. Overlap error:") > 0 Then
c.EntireRow.Copy ws.Cells(ws.Rows.Count, "A").End(xlUp).Offset(1) 'copy row to first empty row in sheet2
c.EntireRow.Delete Shift:=xlUp
End If
Next c
End Sub
You can use a filter to find the data, move it and delete the rows.
Sub ed()
Dim sh As Worksheet, ws As Worksheet
Dim rng As Range
Set sh = Sheets("Sheet1")
Set ws = Sheets("Sheet2")
With sh
.Range("BE4").AutoFilter Field:=1, Criteria1:= _
"=*1. Overlap error:*", Operator:=xlAnd
Set rng = .Range("BE5:BE" & .Cells(.Rows.Count, "BE").End(xlUp).Row)
With ws
rng.SpecialCells(xlCellTypeVisible).EntireRow.Copy ws.Cells(ws.Rows.Count, "A").End(xlUp).Offset(1)
End With
rng.EntireRow.Delete
.AutoFilterMode = False
End With
End Sub
So if you prefer your original approach,
Sub loopMe()
Dim sh As Worksheet, ws As Worksheet
Dim LstR As Long, c As Range
Set sh = Sheets("Sheet1")
Set ws = Sheets("Sheet2")
'find last row
LstR = sh.Range("BE65000").End(xlUp).Row
Dim irow
For irow = LstR To 5 Step -1
Set c = sh.Range("BE" & irow)
If c.Value Like "*1. Overlap error:*" Then
'copy row to first empty row in sheet2
c.EntireRow.Copy ws.Cells(65000, 1).End(xlUp).Offset(1, 0)
c.EntireRow.Delete Shift:=xlUp
End If
Next irow
End Sub

How to avoid pasting duplicate Range from one worksheet to another

I want to copy data from a worksheet named "copySheet" to the first blank row in a sheet named "pasteSheet".
If the data in cell A2 of copySheet is in first column of pasteSheet then provide an error message "data is already existed and avoid pasting" otherwise paste the copy range from copySheet to pasteSheet.
I have written code as below however, IF loop is not working correctly. The value in A2 cell found in first column of pasteSheet but code is ignoring the loop and pastes the range again.
Sub Macro1()
'
' Macro1 Macro
'
Dim copySheet As Worksheet
Dim pasteSheet As Worksheet
Set copySheet = Worksheets("Sheet1")
Set pasteSheet = Worksheets("Sheet2")
copySheet.Columns("A:D").Select
Selection.ClearContents
ActiveSheet.Paste Destination:=copySheet.Range("A1")
Dim FoundRange As Range
Dim Search As String
Search = copySheet.Cells(2, 1).Select
Set FoundRange = pasteSheet.Columns(0, 1).Find(Search, LookIn:=xlValues, LookAt:=xlWhole)
If Foundcell Is Nothing Then
Dim N As Long
N = copySheet.Cells(1, 1).End(xlDown).Row
Range("A2:E" & N).Select
Selection.Copy
pasteSheet.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
Else
MsgBox "Data Exists" & " data found at cell address " & Foundcell.Address
End If
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
Try this. A few problems with your code:
as noted above, your Columns syntax was off
you defined FoundRange but then referred to FoundCell - use Option Explicit to flag up these errors
avoid Select wherever possible
Option Explicit
Sub Macro1()
Dim copySheet As Worksheet
Dim pasteSheet As Worksheet
Set copySheet = Worksheets("Sheet1")
Set pasteSheet = Worksheets("Sheet2")
With copySheet
.Columns("A:D").ClearContents
Dim FoundRange As Range
Dim Search As String
Search = .Cells(2, 1)
Set FoundRange = pasteSheet.Columns(1).Find(Search, LookIn:=xlValues, LookAt:=xlWhole)
If FoundRange Is Nothing Then
Dim N As Long
N = .Cells(Rows.Count, 1).End(xlUp).Row + 1
.Range("A2:E" & N).Copy
pasteSheet.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
Else
MsgBox "Data Exists" & " data found at cell address " & FoundRange.Address
End If
End With
End Sub

Trying to copy/paste and transpose multiple ranges between a start points and end points

I am trying to loop through cells in ColumnA to find a start point and end point, then copy all rows between these anchors, transpose the data set, and then continue looping through the rest of the cells and do the same.
I came up with this, but I know it's not even close to working.
Sub TryThis()
Dim LastRow As Integer
Dim startcell As Range
Dim endcell As Range
Sheets("Sheet1").Select
LastRow = ActiveSheet.Range("A1000000").End(xlUp).Row
Set startrng = Range("A1:A" & LastRow)
With Worksheets(1).Range(startrng.Address & ":" & Cells(LastRow, startrng.Column).Address) '<== set the start search range here
Set startcell = .Find(What:="class: pipestandardize.Standardize")
End With
With Worksheets(1).Range(startcell.Address & ":" & Cells(LastRow, startcell.Column).Address) '<== set the end search range here
Set endcell = .Find(What:="id: standardize")
End With
' Range("A10:A100,A150:A330,A380:A420").Select
Selection.Copy
Sheets("Sheet2").Select
Range("A1").End(xlUp).Select
lMaxRows = Cells(Rows.Count, "A").End(xlUp).Row
Range("A" & lMaxRows + 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=True
Sheets("Sheet1").Select
End Sub
Basically, I want to select all rows from the starting point of class: pipestandardize.Standardize to the ending point of id: standardize, copy this range, and transpose it and paste it.
Then, from the cell after id: standardize, start looping through cells again, to find the next starting point that contains class: pipestandardize.Standardize and go down to the ending point that contains id: standardize, select this range, copy and transpose/paste under the previous one.
I suggest using Find in a loop, and exit the loop either if it finds no start/end anymore or if finished.
Option Explicit
Public Sub TransposeData()
Dim wsSrc As Worksheet
Set wsSrc = ThisWorkbook.Worksheets("Sheet1")
Dim wsDest As Worksheet
Set wsDest = ThisWorkbook.Worksheets("Sheet2")
Dim SearchRange As Range 'define search range
Set SearchRange = wsSrc.Range("A1", wsSrc.Cells(wsSrc.Rows.Count, "A").End(xlUp))
Dim LastRowDest As Long
LastRowDest = wsDest.Cells(wsSrc.Rows.Count, "A").End(xlUp).Row
Dim StartRange As Range, EndRange As Range
Set EndRange = SearchRange(1, 1) 'initialize
Application.ScreenUpdating = False
Do
Set StartRange = Nothing
On Error Resume Next
Set StartRange = SearchRange.Find(What:="class: pipestandardize.Standardize", After:=EndRange, LookAt:=xlWhole)
On Error GoTo 0
If StartRange Is Nothing Then Exit Do 'stop if start not found
If StartRange.Row < EndRange.Row Then Exit Do 'stop if find started again from beginning
Set EndRange = Nothing
On Error Resume Next
Set EndRange = SearchRange.Find(What:="id: standardize", After:=StartRange, LookAt:=xlWhole)
On Error GoTo 0
If EndRange Is Nothing Then Exit Do
LastRowDest = LastRowDest + 1
wsSrc.Range(StartRange, EndRange).Copy
wsDest.Cells(LastRowDest, "A").PasteSpecial Paste:=xlPasteValues, Operation:=xlPasteSpecialOperationNone, SkipBlanks:=False, Transpose:=True
DoEvents 'keep Excel responsive
Loop
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
Note that Find will throw an error if it finds nothing. So we need to catch that error:
Set StartRange = Nothing 'reset StartRange
On Error Resume Next 'hide all error messages
Set StartRange = SearchRange.Find(What:="class: pipestandardize.Standardize", After:=EndRange, LookAt:=xlWhole)
'if find throws an error it is hidden now
On Error GoTo 0 're-enable error reporting!!!
'if find didn't didn't find anything then StartRange is still Nothing
If StartRange Is Nothing Then Exit Do 'stop if start not found

Resources