Transpose a range in VBA - vba

I am Trying to Transpose a range of cells in Excel through VBA macro but I am getting some errors, mostly Error 91.
I am pretty new to VBA and don't have much idea about functions either.
Range(InRng).Select
Set Range1 = Selection
Dim DestRange As Range
Set DestRange = Application.WorksheetFunction.Transpose(Range1)
After going through a couple of forums, this is what I have come up with. One thing to note is that I don't have to copy them into any other cells.
What I am trying to achieve is to create a co-variance method and in the option window the user will have the option to select the range and then choose either by columns or rows, this will then affect the resulting covariance matrix.

This gets you X and X' as variant arrays you can pass to another function.
Dim X() As Variant
Dim XT() As Variant
X = ActiveSheet.Range("InRng").Value2
XT = Application.Transpose(X)
To have the transposed values as a range, you have to pass it via a worksheet as in this answer. Without seeing how your covariance function works it's hard to see what you need.

First copy the source range then paste-special on target range with Transpose:=True, short sample:
Option Explicit
Sub test()
Dim sourceRange As Range
Dim targetRange As Range
Set sourceRange = ActiveSheet.Range(Cells(1, 1), Cells(5, 1))
Set targetRange = ActiveSheet.Cells(6, 1)
sourceRange.Copy
targetRange.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=True
End Sub
The Transpose function takes parameter of type Varaiant and returns Variant.
Sub transposeTest()
Dim transposedVariant As Variant
Dim sourceRowRange As Range
Dim sourceRowRangeVariant As Variant
Set sourceRowRange = Range("A1:H1") ' one row, eight columns
sourceRowRangeVariant = sourceRowRange.Value
transposedVariant = Application.Transpose(sourceRowRangeVariant)
Dim rangeFilledWithTransposedData As Range
Set rangeFilledWithTransposedData = Range("I1:I8") ' eight rows, one column
rangeFilledWithTransposedData.Value = transposedVariant
End Sub
I will try to explaine the purpose of 'calling transpose twice'.
If u have row data in Excel e.g. "a1:h1" then the Range("a1:h1").Value is a 2D Variant-Array with dimmensions 1 to 1, 1 to 8.
When u call Transpose(Range("a1:h1").Value) then u get transposed 2D Variant Array with dimensions 1 to 8, 1 to 1. And if u call Transpose(Transpose(Range("a1:h1").Value)) u get 1D Variant Array with dimension 1 to 8.
First Transpose changes row to column and second transpose changes the column back to row but with just one dimension.
If the source range would have more rows (columns) e.g. "a1:h3" then Transpose function just changes the dimensions like this: 1 to 3, 1 to 8 Transposes to 1 to 8, 1 to 3 and vice versa.
Hope i did not confuse u, my english is bad, sorry :-).

You do not need to do this. Here is how to create a co-variance method:
http://www.youtube.com/watch?v=RqAfC4JXd4A
Alternatively you can use statistical analysis package that Excel has.

Strictly in reference to prefacing "transpose", by the book, either one will work; i.e., application.transpose() OR worksheetfunction.transpose(), and by experience, if you really like typing, application.WorksheetFunction.Transpose() will work also-

Something like this should do it for you.
Sub CombineColumns1()
Dim xRng As Range
Dim i As Long, j As Integer
Dim xNextRow As Long
Dim xTxt As String
On Error Resume Next
With ActiveSheet
xTxt = .RangeSelection.Address
Set xRng = Application.InputBox("please select the data range", "Kutools for Excel", xTxt, , , , , 8)
If xRng Is Nothing Then Exit Sub
j = xRng.Columns(1).Column
For i = 4 To xRng.Columns.Count Step 3
'Need to recalculate the last row, as some of the final columns may not have data in all rows
xNextRow = .Cells(.Rows.Count, j).End(xlUp).Row + 1
.Range(xRng.Cells(1, i), xRng.Cells(xRng.Rows.Count, i + 2)).Copy .Cells(xNextRow, j)
.Range(xRng.Cells(1, i), xRng.Cells(xRng.Rows.Count, i + 2)).Clear
Next
End With
End Sub
You could do this too.
Sub TransposeFormulas()
Dim vFormulas As Variant
Dim oSel As Range
If TypeName(Selection) <> "Range" Then
MsgBox "Please select a range of cells first.", _
vbOKOnly + vbInformation, "Transpose formulas"
Exit Sub
End If
Set oSel = Selection
vFormulas = oSel.Formula
vFormulas = Application.WorksheetFunction.Transpose(vFormulas)
oSel.Offset(oSel.Rows.Count + 2).Resize(oSel.Columns.Count, oSel.Rows.Count).Formula = vFormulas
End Sub
See this for more info.
http://bettersolutions.com/vba/arrays/transposing.htm

if you just want to copy and transpose the values in the clipboard you can use the following makro:
Sub PasteVal()
Selection.PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=True
End Sub

Related

VBA VLookup in Loop

I´m trying to do a VLOOKUP of a column data set at a Sheet called "SyS" in G column. and I'd like to Vlookup relevant data using columns in another sheet called "CONF_mapping", located in the same Workbook. I need to find my data located at the range ("A1:E65000") (It's at column A, but I need to retrieve data from other columns with my vlookup to SyS). I'm not getting good results with my code, and I beg your pardon, it´s my first question in the forum.
Worksheets("SyS").Select
Dim wsThis As Worksheet
Dim aCell As Range
Sheets("CONF_mapping").Columns(2).Copy Destination:=Sheets("SyS").Columns(8)
Set wsThis = Sheets("SyS")
With wsThis
For Each aCell In .Range("A1:E65000")
'.Cells(aCell.Row, 8) = "Not Found"
On Error Resume Next
.Cells(aCell.Row, 8) = Application.WorksheetFunction.VLookup( _
aCell.value, wsThat.Range("G2:G65000"), 2, False)
On Error GoTo 0
Next aCell
End With
Worksheets("SyS").Select
I have find this code but I was not able to make it works for me.
I would appreciate any help.
You have mistake here:
VLookup(aCell.value, wsThat.Range("G2:G65000"), 2, False)
Range "G2:G65000" Have just 1 column G, but you try to get column#2 which does not exists.
UPD:
I guess you need something like this:
Const COLUMN_TO_MATCH_IN_SYS = 8
Const COLUMN_TO_MATCH_IN_CONF = 1
Sub test()
Dim wsSys As Worksheet
Dim wsConf As Worksheet
Set wsSys = Sheets("SyS")
Set wsConf = Sheets("CONF_mapping")
Dim RowSys As Range
Dim RowConf As Range
For Each RowSys In wsSys.UsedRange.Rows
For Each RowConf In wsConf.UsedRange.Rows
If RowSys.Cells(1, COLUMN_TO_MATCH_IN_SYS) = _
RowConf.Cells(1, COLUMN_TO_MATCH_IN_CONF) Then
' Copy row values which is needed
RowSys.Cells(1, 6) = RowConf.Cells(1, 1) ' From column A(conf) to G(sys)
RowSys.Cells(1, 7) = RowConf.Cells(1, 2) ' From column B(conf) to H (sys)
End If
Next aCell
Next
End Sub
With this solution you don't need to search the Range for each cell (just for each row), so it will work 5 times faster.

Need VBA for loop referencing a named range which contains all the sheet names

I have a piece of "crude" code which copies some data from one sheet to Another, and the sheet-name from which the data is copied can be found in a cell. However, the number of sheets are now growing, and I have created a dynamic named range for the sheetnames, and would like to perform the following code for all the sheets in the dynamic range. My code looks like this:
Calculate
' get the worksheet name from cell AA3
Worksheets(Range("AA3").Value).Activate
' Copy the data
Range("A1:A1500").Select
Selection.Copy
' Paste the data on the next empty row in sheet "Artiklar"
Sheets("Artiklar").Select
Dim NextRow As Range
Set NextRow = Range("A65536").End(xlUp).Offset(1, 0)
NextRow.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Now, I would like to have something like a loop with reference to the dynamic range but I am unable to get it to work as VBA really is not my cup of tea...So, instead of referencing AA3, AA4 etc I would like to referebnce the named range which contains the data of AA3, AA4....AAx. The named range might also contain blank cells, as it is the result of an Array formula in AA3....AA150.
Thank you!
/Fredrik
The following code should work for you. I assumed that the named range (i called it copysheets) is in the active workbook (scope workbook).
Sub copySheets()
Dim sheetName As Range
Dim copyRange As Range
Dim destinationRange As Range
For Each sheetName In Range("copysheets")
If sheetName.Value <> "" And sheetName.Value <> 0 Then
Set copyRange = Sheets(sheetName.Value).Range("A1:A1500")
Set destinationRange = Sheets("Artiklar").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
copyRange.Copy
destinationRange.PasteSpecial xlPasteValues
End If
Next
End Sub
Dim myNamedRng as Range, cell as Range
'...
Set myNamedRng = Worksheets("MySheet").Range("myRange") '<-- set a variable referencing your named Range
With Sheets("Artiklar")
For Each cell In myNamedRng
If cell.Value <>"" Then .Range("A" & .Rows.Count).End(xlUp).Offset(1, 0).Resize(1500).Value = Worksheets(cell.Value).Range("A1:A1500").Value
Next cell
End With
The following example loops through each cell in a named range by
using a For Each...Next loop. If the value of any cell in the range
exceeds the value of Limit, the cell color is changed to yellow.
vba
Sub ApplyColor()
Const Limit As Integer = 25
For Each c In Range("MyRange")
If c.Value > Limit Then
c.Interior.ColorIndex = 27
End If
Next c
End Sub
Source
So you might start off with something like this:
Calculate
Dim NextRow As Range
' get a range object from the named range
For Each c In Range("[File.xls]Sheet1!NamedRange")
' Copy the data
Worksheets(c.Value).Range("A1:A1500").Copy
' Paste the data on the next empty row in sheet "Artiklar"
Sheets("Artiklar").Activate
Set NextRow = Range("A65536").End(xlUp).Offset(1, 0)
NextRow.PasteSpecial xlPasteValues
Next c
You'll notice that I was a bit more explicit with how the named range is being referred to - the requirement here might vary depending on how you declared the range to begin with (what its scope is), but the way I did it will most likely work for you. See the linked article for more information about scope of named ranges.
-= Problem Solved =-
Thank you all for your contribution to my question! All the answers that I received has helped me refine my code, which is now functioning properly!
Regards,
Fredrik

Trying to Cross Sheet Copy and Paste into a single sheet, with different ranges of information

I have a Sheet that allows for a part number to be selected and all the Operations it goes through is pulled up, every Operations' steps are on different sheets. What I'm trying to create is based on what operations it pulls up all operations procedures into one sheet to print. Not all operations have same number of steps and not every part has the same number of operations.
The code I have works for the first operation, and the first 3 rows of the second operation. But I can't get it to pull all of the sheet. Below is the code I'm using. At the moment I'm only focused on OP 1 and 2 once I get that it has to be able to go 16 different Ops out of about 30 choices.
Dim rng As Range
If Sheets("Selection").Range("D3").Text = "N/A" Then
Exit Sub
Else
Set rng = Sheets(Sheets("Selection").Range("D3").Text).Range("A12:" & ActiveSheet.Range("S12").End(xlDown).Address)
With rng
.Copy
End With
With Sheets("Print FMEA").Range("S" & Rows.Count).End(xlUp).Offset(1, -18)
.PasteSpecial xlPasteFormats
.PasteSpecial xlPasteValues
End With
End If
If Sheets("Selection").Range("D4").Text = "N/A" Then
Exit Sub
Else
Set rng = Sheets(Sheets("Selection").Range("D4").Text).Range("A12:" & ActiveSheet.Range("S12").End(xlDown).Address)
With rng
.Copy
End With
With Sheets("Print FMEA").Range("S" & Rows.Count).End(xlUp).Offset(1, -18)
.PasteSpecial xlPasteFormats
.PasteSpecial xlPasteValues
End With
End If
End Sub
Let's deal with the errors first:
This line will throw an error Sheets("Print FMEA").Row (Lastrow + 1). I'm not sure what you're trying to do with it, but the syntax is incorrect. I'm slightly surprised you say the code has worked for you.
This line will only select data to the next blank cell Set rng = Sheets(Sheets("Selection").Range("D4").Text).Range("A12:" & ActiveSheet.Range("S12").End(xlDown).Address). You're probably only getting the first three rows because the fourth has a blank.
To answer your question, I think you need to think of this problem in two parts:
Store the reference details of each operation.
Loop through each operation and process the details.
There are many ways you could do this, but a Class object would work well. I've given an example which doesn't make optimum use of a class, but it does distinguish the two tasks.
So for part 1, insert a new class (Insert ~> Class Module) and name it OpsFields. Insert the following code which stores the sheet and cell references:
Private mSourceSheet As Worksheet
Private mRefSheet As Worksheet
Private mRefFirstRange As Range
Public Sub SetRefSheetAddress(sourceSheet As String, cellAddress As String)
Dim sheetName As String
Set mSourceSheet = ThisWorkbook.Worksheets(sourceSheet)
sheetName = mSourceSheet.Range(cellAddress)
Set mRefSheet = ThisWorkbook.Worksheets(sheetName)
End Sub
Public Sub SetFirstRefAddress(columnsAddress As String, firstRow As Long)
Set mRefFirstRange = Intersect(mRefSheet.Columns(columnsAddress), _
mRefSheet.Rows(firstRow).EntireRow)
End Sub
Public Function GetDataRange()
Dim r As Long
Dim c As Long
Dim lastRow As Long
Dim rowCount As Long
r = mRefSheet.Rows.Count
c = mRefFirstRange.Columns(1).Column
lastRow = mRefSheet.Cells(r, c).End(xlUp).Row
rowCount = lastRow - mRefFirstRange.Rows(1).Row + 1
Set GetDataRange = mRefFirstRange.Resize(rowCount)
End Function
You then populate these classes and store them into some kind of list - I've used a Collection as you don't have to redimension it, so the number of operations doesn't matter. In the code below, I've given you an example of two but you could add as many as you want. This code would be in your Module:
Private mOpsList As Collection 'at top of module
Sub CreateOpsFields()
Dim ops As OpsFields
Set mOpsList = New Collection
Set ops = New OpsFields
ops.SetRefSheetAddress "Selection", "D3"
ops.SetFirstRefAddress "A:S", 12
mOpsList.Add ops
Set ops = New OpsFields
ops.SetRefSheetAddress "Selection", "D4"
ops.SetFirstRefAddress "A:S", 12
mOpsList.Add ops
End Sub
As for part 2, you simply loop through your list of classes and perform the paste task, as follows (again in your Module):
Sub RecordOps()
Dim outputSheet As Worksheet
Dim ops As OpsFields
Dim data As Range
Dim nextBlankRow As Long
Set outputSheet = ThisWorkbook.Worksheets("Print FMEA")
nextBlankRow = outputSheet.Cells(outputSheet.Rows.Count, "S").End(xlUp).Row
For Each ops In mOpsList
Set data = ops.GetDataRange
data.Copy
With outputSheet.Cells(nextBlankRow, "A").Resize(data.Rows.Count, data.Columns.Count)
.PasteSpecial xlPasteFormats
.PasteSpecial xlPasteValues
End With
nextBlankRow = nextBlankRow + data.Rows.Count
Next
End Sub
You call these routines in the normal way. An obvious way would be to populate the classes in some kind of Initialisation routine and then call the paste routine when some event is triggered. I've just put both calls in one routine so you can see the syntax:
Sub RunMe()
CreateOpsFields
RecordOps
End Sub

Use a VBA loop to select a series of variables

I have a series of variables (each declared as a range) in a VBA script as follows:
r1 = range
r2 = range
...
r100 = range
Ideally I'd like to use a for loop to select, copy, and paste (transpose) each range in succession. I'm writing my code via trial and error, and I have little familiarity with VBA. Currently I'm using a loop like the following:
For i = 0 To 99 Step 1
Dim Num As Integer
Num = i + 1
Num = CStr(Num)
Dim R As Range
R = "r" & Num
R.Select
Selection.Copy
Range("TARGET RANGE").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Next i
Can anyone help me debug this loop and/or find the best way to achieve this?
You need to Set a Range object.
Dim Num As Integer, R As Range
For i = 0 To 99 Step 1
Num = i + 1
SET R = RANGE("r" & Num)
R.Copy Destination:=Range("TARGET RANGE")
Next i
It is not entirely clear what you intend to accomplish but the above should do what is expected of it.
You can use a For Each ... In loop for this.
Dim Bag As New Collection
Dim Target As Range
Dim r As Range
Bag.Add [A1:A50]
Bag.Add [C3:F100]
Bag.Add [Sheet2!H1:L1]
Bag.Add ['[Another file.xlsx]Sheet1'!A1:B100]
Set Target = [Output!A1]
For Each r In Bag
' Size target to be the same dimensions as r transposed
Set Target = Target.Resize(r.Columns.Count, r.Rows.Count)
' transpose and copy values
Target.Value = Application.Transpose(r.Value)
' shift target down to next empty space
Set Target = Target.Offset(Target.Rows.Count)
Next

Type Mismatch Error when searching for a string in an array

I am working on a macro that will consolidate two different sources of order data. The first source will contain old orders as well as some new, the second source will contain only the old orders and will have additional data in columns that were updated manually.
My idea for this is to take the order totals from the second source, paste them in a sheet after the order totals from the first source, and then search all the order numbers from the new file against the order numbers from the existing tracker. I have a for loop that is supposed to find the order numbers from the new file that are not already in the tracker and then insert a row with that order detail. I am receiving a Type mismatch error on the if statement that checks if the string exists in the array. Please take a look at this code:
Dim r As Integer
For r = 1 To 1000
Dim NewOrd As String
NewOrd = Range(Cells(r, 1), Cells(r, 1)).Value
Dim ExistArray As Variant
ExistArray = Range("a1", Range("a1").End(xlUp))
Sheets("Sheet2").Select
If IsEmpty(NewOrd) Then
Exit For
End If
If Not UBound(Filter(ExistArray, NewOrd)) >= 0 And NewOrd <> "" Then
Rows(r).Select
Selection.Copy
Sheets("Sheet3").Select
Rows(r).Select
Selection.Insert Shift:=xlDown
Application.CutCopyMode = False
End If
r = r + 1
Next r
I have tried a few different ways of setting the array, tried adding option explicit, and tried nesting for loops (not my brightest efficiency moment). Would greatly appreciate another set of eyes!
Thanks!
Assigning a Range object to an array always results in a two-dimensional array, which is causing the error.
Do this:
ExistArray = Application.Transpose(Range("a1", Range("a1").End(xlUp)))
I think that should resolve it for you.
Updates
You may need to:
Dim ExistArray() As Variant
Your range object is also problematic, being a single cell:
ExistArray = Application.Transpose(Array(Range("A1")))
Change the sheet names from "Sheet1" and "Sheet2" as necessary:
Sub tgr()
Dim wsNew As Worksheet
Dim wsTracker As Worksheet
Dim rIndex As Long
'This is the sheet that contains the new data that needs to be added
Set wsNew = Sheets("Sheet1")
'This sheet contains the old data
Set wsTracker = Sheets("Sheet2")
'Go through each row in the new data
For rIndex = 1 To wsNew.Cells(Rows.Count, "A").End(xlUp).Row
'Verify that the row isn't blank and that it doesn't already exist in wsTracker
If Len(wsNew.Cells(rIndex, "A").Value) > 0 And WorksheetFunction.CountIf(wsTracker.Columns("A"), wsNew.Cells(rIndex, "A").Value) = 0 Then
'This is a new item that needs to be added
'Copy the row to the next available row in wsTracker
wsNew.Rows(rIndex).Copy wsTracker.Cells(Rows.Count, "A").End(xlUp).Offset(1)
End If
Next rIndex
Set wsNew = Nothing
Set wsTracker = Nothing
End Sub