How to go to next line(results sheet) in this code ? vertical to horizontal transpose - excel

Sub Test2()
Dim i&, j&, vIn, vOut
With ThisWorkbook
vIn = .Worksheets(1).Range("a1").CurrentRegion.Value2
ReDim vOut(1 To UBound(vIn, 2), 1 To UBound(vIn, 1))
For i = 1 To UBound(vIn, 1)
For j = 1 To UBound(vIn, 2)
vOut(j, i) = vIn(i, j)
Next
Next
.Worksheets(2).Range("a1").Resize(UBound(vOut, 1), UBound(vOut, 2)) = vOut
End With
End Sub
Problem - Not able to go to next line if i run the program for the next set of data to be transposed.

The issue is that you always write into Range("a1") when using this line
.Worksheets(2).Range("a1").Resize(UBound(vOut, 1), UBound(vOut, 2)) = vOut
Instead first find the next free row
Dim NextFreeRow As Long
NextFreeRow = .Worksheets(2).Cells(.Worksheets(2).Rows.Count, "A").End(xlUp).Row + 1
and then use this row as starting point
.Worksheets(2).Cells(NextFreeRow, "A").Resize(UBound(vOut, 1), UBound(vOut, 2)) = vOut
Actually you might want to have a look at the WorksheetFunction.Transpose method. This would be much easier to transpose the data.

If it is only Range(B2:B5") or similar everytime then you you do not need to use an array for this. It is an overkill for this situation. You can use Copy | PasteSpecial - Transpose to achieve what you want. Also avoid using Worksheets(1), Worksheets(2). Use their code names or the sheet names. Using Index number can give you undesired results if the position of the sheet moves.
Is this what you are trying? (Untested)
Option Explicit
Sub Sample()
Dim wsIn As Worksheet, wsOut As Worksheet
Dim lRow As Long
'~~> Change the sheet names as applicable
Set wsIn = ThisWorkbook.Sheets("Sheet1")
Set wsOut = ThisWorkbook.Sheets("Sheet2")
With wsOut
'~~> Find next available row
lRow = .Range("A" & .Rows.Count).End(xlUp).Row + 1
'~~> Copy relevant range
wsIn.Range("B2:B5").Copy
'~~> Write to relevant area
.Range("A" & lRow).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=True
End With
Application.CutCopyMode = False
End Sub

Related

Alternatives to ActiveSheet.Paste to reduce memory

I am trying to utilise the VBA/macro function at work. However, I came across a problem which says something like 'error; insufficient memory' and after some browsing on the internet I realise that copy and pasting generally takes up a lot of spaces in the Excel and my Excel in workplace is only 32 bits. Therefore, does anyone know any good alternatives to ActiveSheet.Paste?
My codes are currently as following:
ActiveSheet.Range ("$A$!:$Y$1000").AutoFilter Field:=7, Criterial:=_banker
Range("A1").Select
Range(Selection, Selection.End(x1Down)).Select
Range(Selection, Selection.End(X1ToRight)).Select
Selection.Copy
Sheets.Add After:=ActiveSheet
ActiveSheet.Paste
ActiveSheet.Name= banker
i=i+1
Loop
End Sub
You should copy your code as it is and no writing it. In this way you will avoid spelling mistakes (Range ("$A$!:$Y$1000") instead of "A1:..., X1ToRight instead of XlToRight, "_banker" instead of "banker"). Putting Option Explicit on top of your module, as recommended above will help.
A way to filter and copy the filter range, not involving the clipboard should be the next code. Please, test it and send some feedback:
Sub testFilterCopyRange()
Dim sh As Worksheet, shNew As Worksheet, lastR As Long
Dim banker As String, rng As Range, rngF As Range, arr, i As Long
Dim maxIt As Long 'number of iterations
Set sh = ActiveSheet
lastR = sh.Range("A" & sh.rows.count).End(xlUp).row 'last row
maxIt = 1 'set here the maximum number of necessary iterations
sh.AutoFilterMode = False 'eliminate the previous filter
Set rng = sh.Range("A1:H" & lastR) 'set the range to be processed
For i = 1 To maxIt
banker = "7" '"your dinamic criteria"
rng.AutoFilter field:=7, Criteria1:=banker 'filter the range according to above defined criteria
Set rngF = rng.SpecialCells(xlCellTypeVisible) 'set a range to keep the filtered cells in the range
arr = arrayFromDiscRange(rngF, False) 'header inclusive
Set shNew = Sheets.Add(After:=sh): shNew.Name = banker 'add a new sheet and name it
shNew.Range("A1").Resize(UBound(arr), UBound(arr, 2)).value = arr 'drop the array content at once
Next i
End Sub
'function able to transform a filtered (discontinue) range in an array:
Private Function arrayFromDiscRange(rngF As Range, Optional NoHeader As Boolean = False) As Variant
Dim arr, i As Long, j As Long, k As Long, A As Range, R As Range, iRows As Long
'count range rows
For Each A In rngF.Areas
iRows = iRows + A.rows.count
Next A
'Redim the array to keep the range
ReDim arr(1 To iRows - IIf(NoHeader, 1, 0), 1 To rngF.Columns.count): k = 1
For Each A In rngF.Areas 'iterate between the range areas:
For Each R In A.rows 'iterate between the area rows:
If NoHeader And k = 1 Then GoTo Later 'skip the first row, if no header wanted
For j = 1 To R.Columns.count 'iterate between the area row columns:
arr(k, j) = R.cells(1, j).value 'place each row cells value in the array row
Next j
k = k + 1 'intrement the array row to receive values
Later:
Next
Next A
arrayFromDiscRange = arr 'returning the created array
End Function
If something unclear, even if I tried commenting all the code line which could be problematic in understanding, please do not hesitate to ask for clarifications.

How to copy and paste only filtered cells in excel using vba

I've been trying to copy and paste a range of filtered cells in a specific space in my excel sheet (take a look in the images) using vba , but when I try to do that, the
error 1004
occurs. I've searched in a lot of forums and try to solve my problem in different ways but it isn't working and the error 1004 still occurs.
Sub arrumando_dados_pro_xml()
Dim n As Integer
Dim i As Integer
Dim m As Integer
Dim j As Integer
n = Cells(1000, 1).End(xlUp).Row
j = Cells(n - 1, 1).End(xlUp).Row
m = Cells(1, 50).End(xlLeft).Row
Range(Worksheets("Planilha1").Cells(2, 1), Worksheets("Planilha1").Cells(j, m)).SpecialCells(xlCellTypeVisible).Copy
'''Range("A2:P37").SpecialCells(xlCellTypeVisible).Select
''''Selection.SpecialCells(xlCellTypeVisible).Select
'''Selection.SpecialCells(xlCellTypeVisible).Copy
''''Call Plan1.AutoFilter.Range.Copy
Range(Worksheets("Planilha2").Cells(1, 1), Worksheets("Planilha2").Cells(1, m)).Paste
Range(Worksheets("Planilha2").Cells(1, 1), Worksheets("Planilha2").Cells(1, m)).Copy
Range(Worksheets("Planilha1").Cells(n, 1), Worksheets("Planilha2").Cells(n, m)).Copy
''' Range(Cells(n, 1), Cells(n, m)).Select
''' ActiveSheet.Paste
End Sub
Since your code was a little confusing, I simplified it. Here is a basic code example, with comments, to copy visible cells in a range and paste. It can be modified as needed.
'Declare your variables
Dim ws1 As Worksheet, ws2 As Worksheet, As Range, lRow As Long, lCol As Long
'Assign your variables, you should always identify the workbook and worksheet
'ThisWorkbook refers to the workbook where your code resides
Set ws1 = ThisWorkbook.Sheets("Planilha1")
Set ws2 = ThisWorkbook.Sheets("Planilha2")
'Using your worksheet variable find the last used row and last used column
lRow = ws1.Cells(ws1.Rows.Count, 1).End(xlUp).Row
lCol = ws1.Cells(1, ws1.Columns.Count).End(xlToLeft).Column
'Define your range by resizing using lRow and lCol.
Set rng = ws1.Cells(2, 1).Resize(lRow - 1, lCol)
'Copy the visible cells in the range(normally used after filtering or with hidden rows/columns)
rng.SpecialCells(xlCellTypeVisible).Copy
'paste the copied range starting on row 1, after the last column with data, by using .Offset(, 1)
ws2.Cells(1, 1).PasteSpecial xlPasteValues
If you have any questions, please ask and I will help.
Edited I modified your code, had to make changes, see comments
'Added worksheet variables
Dim ws1 As Worksheet, ws2 As Worksheet, n As Long, m As Long 'removed j As Long
Set ws1 = ThisWorkbook.Sheets("Planilha1")
Set ws2 = ThisWorkbook.Sheets("Planilha2")
n = ws1.Cells(1000, 1).End(xlUp).Row
'Removed [j = ws1.Cells(n - 1, 1).End(xlUp).Row] if there are no blank cells after "n" the new last used row then j = 1
m = ws1.Cells(1, 50).End(xlToLeft).Column 'you can't use .End(xlLeft).Row to get the last column
'changed j to n, if j = 1 then only the top two rows will be copied
ws1.Range(ws1.Cells(2, 1), ws1.Cells(n, m)).SpecialCells(xlCellTypeVisible).Copy
'when pasting, just use one cell
ws2.Cells(1, 1).PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False 'Exits the CutCopyMode, removes "Marching Ants"

How do I Cut a range from one worksheet to Paste to a second and make sure future lines go to the next blank row?

Two questions:
1) I have a spreadsheet (TC) that has data on one page that will be updated daily. There are 28 columns. Essentially I am looking to have the line (row) data cut and paste into a second spreadsheet (Archive) when Col. 28 has a value entered in it. I have the base coding but for some reason it causes Excel to be non-responsive.
I think it might be because the coding goes cell by cell rather than row by row. Can anyone point me in the right direction? (Again, keep in mind, this is a snippet of the coding - I have each Cut and Paste up to Column 28.)
2) The second part of my question is: Will what I have written make sure that when the Command Button is pressed next time, the data will cut and paste to the next blank line. Thank you!
Private Sub CommandButton1_Click()
a = Worksheets("TC").Cells(Rows.Count, 2).End(xlUp).Row
'Dim rng As Range
'Set rng = Worksheets("Archived").Range("A1")
b = 1
For i = 2 To a
If Worksheets(“TC”).Cells(i, 28).Value <> "" Then
'Change # to be the number column of Pt Name
Worksheets(“TC”).Cells(i, 1).Cut
'Change ,# to be the number column of where you want it pasted.
Worksheets(“TC”).Paste Destination:=Worksheets(“Archive”).Cells(b + 1, 1)
'Change ,# to be the number column of SOC
Worksheets(“TC”).Cells(i, 2).Cut
'Change ,# to be the number column of where you want it pasted.
Worksheets(“TC”).Paste Destination:=Worksheets(“Archive”).Cells(b + 1, 2)
b = b + 1
End If
Next
Application.CutCopyMode = False
ThisWorkbook.Worksheets(“TC”).Cells(1, 1).Select
End Sub
You can do something like this:
Private Sub CommandButton1_Click()
Dim i as long, b As Long, shtTC as worksheet, shtArch as worksheet
Set shtTC = Worksheets("TC")
Set shtArch = Worksheets("Archive")
'find the first empty row
b = shtArch.Cells(Rows.Count, 2).End(xlUp).Row + 1 'pick a column which will always be populated
For i = 2 To shtTC.Cells(Rows.Count, 2).End(xlUp).Row
If shtTC.Cells(i, 28).Value <> "" Then
'cut the row
shtTc.Cells(i, 1).Resize(1, 28).Cut shtArch.Cells(b, 1)
b = b + 1
End If
Next
Application.CutCopyMode = False
shtTC.Cells(1, 1).Select
End Sub
Here's an example of how to create the kind of copy results you're looking for. Notice that, unless you specifically want to copy/paste all of the formatting with the data, you don't need to use copy/paste. You can perform the copy by assigning the values of the ranges.
Option Explicit
Private Sub CommandButton1_Click()
CopyData ThisWorkbook.Sheets("TC"), ThisWorkbook.Sheets("Archived")
End Sub
Public Sub CopyData(ByRef source As Worksheet, _
ByRef dest As Worksheet, _
Optional ByVal deleteSource As Boolean = False)
'--- calculate and create the source data range
Const TOTAL_COLUMNS As Long = 1
Dim srcRange As Range
Dim lastRow As Long
With source
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
Set srcRange = .Range("A1").Resize(lastRow, TOTAL_COLUMNS)
End With
'--- determine where the data should go
Dim destRange As Range
With dest
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
If lastRow > 1 Then lastRow = lastRow + 1
Set destRange = .Cells(lastRow, 1)
Set destRange = destRange.Resize(srcRange.Rows.Count, TOTAL_COLUMNS)
End With
'--- now copy the data
destRange.Value = srcRange.Value
'--- optionally delete the source data
If deleteSource Then
srcRange.Clear
End If
End Sub

Macro to copy cells four rows apart without using select

This code copies the entries from Sheet1!A2, Sheet1!B2, etc. and pastes them onto Sheet2 with 3 rows between each entry. I want to duplicate this code without using .select.
Option Explicit
Sub Copy_Paste()
Dim i As Integer
For i = 1 To 100
Sheets("Sheet1").Select
Range("A2,B2,C2,D2,E2").Select
ActiveCell.Range(Cells(i, 1), Cells(i, 2)).Select
Selection.Copy
Sheets("Sheet2").Select
Cells(((i - 1) * 4) + 1, 1).Select
ActiveSheet.Paste
Next i
End Sub
This is what I have so far, but it is not working.
Option Explicit
Sub Copy_Paste()
Dim i As Integer
For i = 1 To 100
Dim ws1 As Worksheet, rng As Range, act As Range
Set ws1 = Worksheets("Data")
Set rng = ActiveSheet.Range("A2,B2,C2,D2,E2")
Set act = ActiveCell.Range(Cells(i, 1), Cells(i, 2))
Selection.Copy
Dim ws2 As Worksheet, rng2 As Range
Set ws2 = Worksheets("Calculate")
Set rng2 = Cells(((i - 1) * 4) + 1, 1)
ActiveSheet.Paste
Next i
End Sub
I used this type of operation in one of my vba codes:
'do copy from reference "Answers_Source" worksheet
wb.Sheets("Answers_Source").Range("h1:z160").Copy
'now paste the formulas into the student exam workbook
wb2.Sheets("Answers").Range("h1:z160").Paste
So you can edit that to your situation.
you could use Offset() property of Range object
Sub Copy_Paste()
Dim i As Long
For i = 1 To 100
Sheets("Sheet1").Range("A2,B2").Offset(i - 1).Copy Destination:=Sheets("Sheet2").Range("A1:B1").Offset((i - 1) * 4)
Next
End Sub
while if you only need paste values, then it's quicker:
Sub Copy_Paste_Values()
Dim i As Long
For i = 1 To 100
Sheets("Sheet2").Range("A1:B1").Offset((i - 1) * 4).Value = Sheets("Sheet1").Range("A2,B2").Offset(i - 1).Value
Next
End Sub
You know you can just say something like "Range x values = Range y values":
ws2.Range("A1:B4").Value = ws1.Range("A1:B4").Value
If you can define your ranges using Range(Cells(1,1), Cells(4,2)) then I'm pretty sure you can do everything you want in one line

VBA paste range

I would like to copy a range and paste it into another spreadsheet. The following code below gets the copies, but does not paste:
Sub Normalize()
Dim Ticker As Range
Sheets("Sheet1").Activate
Set Ticker = Range(Cells(2, 1), Cells(65, 1))
Ticker.Copy
Sheets("Sheet2").Select
Cells(1, 1).Activate
Ticker.PasteSpecial xlPasteAll
End Sub
How can I paste the copies into another sheet?
To literally fix your example you would use this:
Sub Normalize()
Dim Ticker As Range
Sheets("Sheet1").Activate
Set Ticker = Range(Cells(2, 1), Cells(65, 1))
Ticker.Copy
Sheets("Sheet2").Select
Cells(1, 1).PasteSpecial xlPasteAll
End Sub
To Make slight improvments on it would be to get rid of the Select and Activates:
Sub Normalize()
With Sheets("Sheet1")
.Range(.Cells(2, 1), .Cells(65, 1)).Copy Sheets("Sheet2").Cells(1, 1)
End With
End Sub
but using the clipboard takes time and resources so the best way would be to avoid a copy and paste and just set the values equal to what you want.
Sub Normalize()
Dim CopyFrom As Range
Set CopyFrom = Sheets("Sheet1").Range("A2", [A65])
Sheets("Sheet2").Range("A1").Resize(CopyFrom.Rows.Count).Value = CopyFrom.Value
End Sub
To define the CopyFrom you can use anything you want to define the range, You could use Range("A2:A65"), Range("A2",[A65]), Range("A2", "A65") all would be valid entries. also if the A2:A65 Will never change the code could be further simplified to:
Sub Normalize()
Sheets("Sheet2").Range("A1:A65").Value = Sheets("Sheet1").Range("A2:A66").Value
End Sub
I added the Copy from range, and the Resize property to make it slightly more dynamic in case you had other ranges you wanted to use in the future.
I would try
Sheets("Sheet1").Activate
Set Ticker = Range(Cells(2, 1), Cells(65, 1))
Ticker.Copy
Worksheets("Sheet2").Range("A1").Offset(0,0).Cells.Select
Worksheets("Sheet2").paste
This is what I came up to when trying to copy-paste excel ranges with it's sizes and cell groups. It might be a little too specific for my problem but...:
'**
'Copies a table from one place to another
'TargetRange: where to put the new LayoutTable
'typee: If it is an Instalation Layout table(1) or Package Layout table(2)
'**
Sub CopyLayout(TargetRange As Range, typee As Integer)
Application.ScreenUpdating = False
Dim ncolumn As Integer
Dim nrow As Integer
SheetLayout.Activate
If (typee = 1) Then 'is installation
Range("installationlayout").Copy Destination:=TargetRange '#SHEET2 TEM DE PASSAR A SER A SHEET DO PROJECT PLAN!#####
ElseIf (typee = 2) Then 'is package
Range("PackageLayout").Copy Destination:=TargetRange '#SHEET2 TEM DE PASSAR A SER A SHEET DO PROJECT PLAN!#####
End If
Sheet2.Select 'SHEET2 TEM DE PASSAR A SER A SHEET DO PROJECT PLAN!#####
If typee = 1 Then
nrow = SheetLayout.Range("installationlayout").Rows.Count
ncolumn = SheetLayout.Range("installationlayout").Columns.Count
Call RowHeightCorrector(SheetLayout.Range("installationlayout"), TargetRange.CurrentRegion, typee, nrow, ncolumn)
ElseIf typee = 2 Then
nrow = SheetLayout.Range("PackageLayout").Rows.Count
ncolumn = SheetLayout.Range("PackageLayout").Columns.Count
Call RowHeightCorrector(SheetLayout.Range("PackageLayout"), TargetRange.CurrentRegion, typee, nrow, ncolumn)
End If
Range("A1").Select 'Deselect the created table
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
'**
'Receives the Pasted Table Range and rearranjes it's properties
'accordingly to the original CopiedTable
'typee: If it is an Instalation Layout table(1) or Package Layout table(2)
'**
Function RowHeightCorrector(CopiedTable As Range, PastedTable As Range, typee As Integer, RowCount As Integer, ColumnCount As Integer)
Dim R As Long, C As Long
For R = 1 To RowCount
PastedTable.Rows(R).RowHeight = CopiedTable.CurrentRegion.Rows(R).RowHeight
If R >= 2 And R < RowCount Then
PastedTable.Rows(R).Group 'Main group of the table
End If
If R = 2 Then
PastedTable.Rows(R).Group 'both type of tables have a grouped section at relative position "2" of Rows
ElseIf (R = 4 And typee = 1) Then
PastedTable.Rows(R).Group 'If it is an installation materials table, it has two grouped sections...
End If
Next R
For C = 1 To ColumnCount
PastedTable.Columns(C).ColumnWidth = CopiedTable.CurrentRegion.Columns(C).ColumnWidth
Next C
End Function
Sub test ()
Call CopyLayout(Sheet2.Range("A18"), 2)
end sub
You can do something like below to paste values in other ranges. (faster than copying and pasting values)
ThisWorkbook.WorkSheets("Sheet2").Range("A1:A2").Value = Sheets`("Sheet1").Range("A1:A2").Value

Resources