Copying multiple columns to another sheet into a single column in chronological order - excel

I have looked for some pseudo code for this, but cannot find it. Any help would be appreciated. Basically I would like to take sample data like:
1 A 2 B 3 C
4 D 5 E 6 F
and copy it to a new sheet as:
1 A
2 B
3 C
4 D
5 E
6 F

According to your picture, we're copying everything in the worksheet. This will work for that case. If it's a subset, please try to modify rngSource to meet your needs:
Sub FlattenAndCopy()
Dim wsSource As Excel.Worksheet
Dim rngSource As Excel.Range
Dim varSource As Variant
Dim wsTarget As Excel.Worksheet
Dim SourceCount As Long
Dim varTarget() As Variant
Dim i As Long, j As Long
Set wsSource = ActiveSheet
Set rngSource = wsSource.UsedRange
varSource = rngSource.Value
SourceCount = rngSource.Cells.Count
ReDim varTarget(1 To SourceCount)
For i = LBound(varSource, 1) To UBound(varSource, 1)
For j = LBound(varSource, 2) To UBound(varSource, 2)
varTarget((i - 1) * (UBound(varSource, 2)) + j) = varSource(i, j)
Next j
Next i
Set wsTarget = wsSource.Parent.Worksheets.Add
wsTarget.Cells(1).Resize(SourceCount, 1) = Application.WorksheetFunction.Transpose(varTarget)
End Sub

Related

Variant Array Not Populating Destination Cells in VBA

I am trying to copy a range of data from one tab into another tab in excel using the fastest way in VBA. After some research, I've decided to use a variant array to do so but my code is not returning anything at all in my destination cells. Can someone spot the issue with my sub?
Sub array_vt()
Dim Arr() As Variant
Dim Arr2() As Variant
Dim Fcst_Essbase As Worksheet
Dim fcst_tab As Worksheet
Dim fcst_rowcnt As Long
fcst_rowcnt = Sheets("Date Dims").Range("B7")
fcst_rowcnt2 = Sheets("Date Dims").Range("B9")
Set fcst_tab = Sheets("Cartesian Product - Fcst")
Set Fcst_Essbase = Sheets("Fcst Essbase Pull")
Arr = Fcst_Essbase.Range("A4:L" & fcst_rowcnt2)
Arr2 = fcst_tab.Range("A2:L" & fcst_rowcnt)
Dim R As Long
Dim C As Long
Dim Destination As Range
Set Destination = fcst_tab.Range("A2")
For R = 4 To UBound(Arr, 1) ' First array dimension is rows.
For C = 1 To UBound(Arr, 2) ' Second array dimension is columns.
Destination.Resize(UBound(Arr2, 1), UBound(Arr2, 2)).Value = Arr
Next C
Next R
End Sub

Adding and Setting Ranges in Excel VBA

I have this sample table.
What I am trying to do is to get all the cell values in all colored cells and transpose them to another worksheet.
I have trouble with the code below to add and set those ranges together so that I can transpose all of them in a ROW in the other worksheet. I have started with the code below
Sub AddRanges()
Dim inRange As Range, inRangeValues() As Variant, outRangeValues() As Variant
Dim finalRow As Long
Dim inRange As Range
Set inRange = Sheet1.Range("A1:A6", "C1:C6", C10:C14) 'I think i got this wrong; Error Type Mismatch
inRangeValues() = inRange.Value 'generate 2d array
outRangeValues = Application.Transpose(inRangeValues)
With Sheet2
finalRow = .Cells(Rows.Count, 1).End(xlUp).Row 'find last row
If inRange.Columns.Count > 1 Then '2d array for output
.Cells(finalRow + 1, 1).Resize(UBound(outRangeValues, 1), UBound(outRangeValues, 2)) = outRangeValues 'Resize according to output array dimensions
Else '1D array for output
.Cells(finalRow + 1, 1).Resize(1, UBound(outRangeValues, 1)) = outRangeValues
End If
End With
End sub
In this example, what is the best approach to combine these ranges so I can transpose them as a ROW? Thanks.
Your code has major problems due to:
Double declaration of inRange
Wrong syntax for Set inRange the entire address needs to be enclosed in a single pair of quotes
Try Set inRange = Range("a1:a6, c1:c6, c10:c14")
Wrong method of reading into an array
When you have a range that consists of multiple areas, you have to convert each area separately.
Then you can create a 1-D array from this depending on the order you wish to have these elements, and write it wherever you want.
For example:
Option Explicit
Sub test()
Dim inRange As Range, inRangeValues As Variant, outRangeValues As Variant
Dim finalRow As Long
Dim I As Long, J As Long, V As Variant, L As Long
Dim lCols As Long
Set inRange = Range("a1:a6, c1:c6, c10:c14")
ReDim inRangeValues(1 To inRange.Areas.Count)
For I = 1 To inRange.Areas.Count
inRangeValues(I) = inRange.Areas(I)
Next I
'how many columns?
lCols = 0
For I = 1 To UBound(inRangeValues, 1)
lCols = lCols + UBound(inRangeValues(I), 1)
Next I
ReDim outRangeValues(1 To lCols)
L = 0
For I = 1 To UBound(inRangeValues, 1)
For J = 1 To UBound(inRangeValues(I), 1)
L = L + 1
outRangeValues(L) = inRangeValues(I)(J, 1)
Next J
Next I
Stop
' enter some code to write the results where you want
' below is just throwaway for proof of concept
Range("f20").Resize(columnsize:=UBound(outRangeValues)).Value = outRangeValues
End Sub
Given your input, the above code would create output like:
You are correct that your code is wrong where you highlight. Try a union. From there, it should be pretty basic to just loop through your range and put them wherever you want in the Sheet2 spreadsheet. See if the below does what you need.
Sub AddRanges()
Dim inRange As Range, acell As Range, aCounter As Long
Const startAddress As String = "A1"
Set inRange = Union(Sheet1.Range("A1:A6"), Sheet1.Range("C1:C6"), Sheet1.Range("C10:C14"))
For Each acell In inRange.Cells
If Not IsEmpty(acell) Then
finalRow = sheet2.Cells(Rows.Count, 1).End(xlUp).Row + 1 'find last row
sheet2.Cells(finalRow, 1).Value = acell.Value
End If
Next acell
End Sub
Check it out.
Sub RngAreaTransps()
Dim RangeArea As Range, LstRw As Long
Dim sh As Worksheet, ws As Worksheet
Dim col As Long, InRange As Range
Set sh = Sheets(1)
Set ws = Sheets(2)
LstRw = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row + 1
With sh
Set InRange = .Range("A1:A6, C1:C6, C10:C14")
For Each RangeArea In InRange.Areas
With ws
col = .Cells(LstRw, .Columns.Count).End(xlToLeft).Column
If col <> 1 Then col = col + 1
RangeArea.SpecialCells(xlCellTypeConstants).Copy
.Cells(LstRw, col).PasteSpecial Transpose:=True
End With
Next RangeArea
End With
Application.CutCopyMode = False
End Sub

Excel VBA Makro compare and copy

I need to copy a row from a sheet into a third sheet, if the ServerID exists in both sheets
Sub XDDXH()
Dim i As Integer
Dim z As Integer
Dim j As Integer
For i = 2 To 3318
For z = 8 To 731
If Worksheets("Sheet1").Range(i, 1).Value = Worksheets("Sheet2").Range(z, 8).Value Then
Worksheets("Sheet1").Range("i:i").Copy Destination:=Worksheets("Sheet3").Range("j:j")
j = j + 1
End If
Next z
Next i
End Sub
With this code I get runtime error 1004.
This is my first time working with VBA.
This can be simplified to one loop with CountIf (untested, but I think I got everything). You could also use Match if you prefer that.
Sub XDDXH()
Dim lookInRng as Range
Set lookInRng = Worksheets("Sheet2").Range("H8:H731")
Dim sourceRng as Range
Set sourceRng = Worksheets("Sheet1").Range("A2:A3318")
Dim rng as Range
For Each rng in sourceRng
If Application.CountIf(lookInRng, rng.Value) > 0 Then
Dim j as Long
j = j + 1
rng.EntireRow.Copy Destination:=Worksheets("Sheet3").Range("A" & j)
End If
Next rng
End Sub
Will implement a couple changes and consolidate the general consensus from comments:
'"As Integer" will get silently converted to "As Long" so just start with Long to save processing power
Dim i As Long, j as long, z as long
Dim ws1 as Worksheet, ws2 as Worksheet, ws3 as Worksheet
'setting sheets to just be cleaner and easier to write
set ws1 = Sheets(1) 'using the index, but could be Sheets("sheet1"), etc.
set ws2 = sheets(2)
set ws3 = sheets(3)
j = 1 'need this or you'll default to j=0 which doesn't work for a range in excel
For i = 2 To 3318
For z = 8 To 731
If ws1.Cells(i, 1).Value = ws2.Cells(z, 8).Value Then
ws1.Rows(i).Copy Destination:=ws3.Rows(j)
j = j + 1
End If
Next z
Next i
Note that Range("A1") and Cells(1,1) are syntactically different ways of saying the same thing. Be careful to not interchange those.
If utilizing a variable, you do not use quotations, e.g., variable j is iterated on a new sheet and you wouldn't write Range("j:j") as that will be the whole column 'J in the worksheet (yes, lowercase doesn't technically matter for that).

Match 2 arrays with rows' values

I want to write a code that uses two 1D arrays and based on the match with the value on the row, it should return the value in the 3rd array.
This is what I want to do:
In Sheet1, I have 3 columns with data on ID, Name, and Amount with a number of rows of uncertain size:
In Sheet2, I have already the columns with data on ID and Name but I don't have the data on Amount:
Therefore, I want to run the code that will match the arrays with ID and Name data in Sheet1 with ID and Name data in Sheet2 and then, return the respective Amount data to Sheet2 as it is in Sheet1.
This is the desired outcome in Sheet2 after running the code, i.e. the data in column Amount are returned based on the match with arrays on ID and Name in Sheet1:
This is my code that does not run as it should:
Sub ArrayMatch()
Dim r As Long
Dim d As Long
Dim w_output As Worksheet
Dim w1 As Worksheet
Dim intLastRow As Integer
Dim IntLastCol As Integer
Dim arrName() As Variant
Dim arrID() As Variant
Dim arrrAmoun() As Variant
d = 8
With ThisWorkbook
Set w1 = .Sheets("Sheet1")
Set w_output = .Sheets("Sheet2")
End With
'***********************************
'Assign arrays
With w1
intLastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
IntLastCol = .Cells(4, Columns.Count).End(xlToLeft).Column
arrID = .Range(.Cells(4, 1), .Cells(intLastRow, 1))
arrName = .Range(.Cells(4, 3), .Cells(intLastRow, 2))
arrAmoun = .Range(.Cells(4, 4), .Cells(intLastRow, 3))
For r = 1 To UBound(arrID, 1)
If Len(arrID(r, 1)) > 0 Then
d = d + 1
If w_output.Cells(d, 1) = arrID(r, 1) Then
If w_output.Cells(d, 2) = arrName(r, 1) Then
w_output.Cells(d, 4) = arrAmoun(r, 1)
End If
End If
End If
Next r
End With
End Sub
My code does not return anything, I can assume that it is because I am comparing the arrays from sheet1 with rows in sheet 2 which is not comparative in the size, but I don't know how to do in another way.
I will appreciate any help.
Just modified your code to include an inner loop to check for ID and name in w_output sheet (it could also be done with Find). Tested with makeshift data. However there are other (more efficient) ways to achieve the same goal.
Sub ArrayMatch()
Dim r As Long
Dim d As Long
Dim w_output As Worksheet
Dim w1 As Worksheet
Dim intLastRow As Long ' Modified to long
Dim IntLastRow1 As Long ' Modified to long
Dim arrName() As Variant
Dim arrID() As Variant
Dim arrrAmoun() As Variant
'd = 8
With ThisWorkbook
Set w1 = .Sheets("Sheet1")
Set w_output = .Sheets("Sheet2")
End With
'***********************************
'Assign arrays
With w1
intLastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
IntLastRow1 = w_output.Cells(Rows.Count, 1).End(xlUp).Row
arrID = .Range(.Cells(4, 1), .Cells(intLastRow, 1))
arrName = .Range(.Cells(4, 3), .Cells(intLastRow, 3))
arrAmoun = .Range(.Cells(4, 4), .Cells(intLastRow, 4))
For r = 1 To UBound(arrID, 1)
If Len(arrID(r, 1)) > 0 Then
For d = 9 To IntLastRow1 ' Modified to for loop for w_output sheet
If w_output.Cells(d, 1) = arrID(r, 1) Then
If w_output.Cells(d, 2) = arrName(r, 1) Then
w_output.Cells(d, 4) = arrAmoun(r, 1)
Exit For ' added once found and amount put in place
End If
End If
Next
End If
Next r
End With
End Sub

VBA Excel- Get Cell value and associated rows into another worksheet based on User Input

All-
I'm very new to VBA and I really need help. I have a worksheet called Sheet 1 that looks like this (This is where the data will be copied from)
and another sheet (Sheet2) that looks like this (this is where the data will be copied to). Notice that the order is not the same as above
When a user types in a place such as "Paris" I want it to copy all corresponding values with "Paris" and it's associated rows. So the end result should look like this
Here is the code I have so far. Right now I can pull all the corresponding values based on the Users input, but I cannot for the life of me figure out how to get the associated rows. Please help! Any input will be highly appreciated.
Dim x As String
Dim K As Long
Dim ct As Variant
Dim r As Range
Dim w1 As Worksheet
Dim w2 As Worksheet
Set w1 = Sheets("Sheet1")
Set w2 = Sheets("Sheet2")
a = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
x = Application.InputBox("Please Enter Place")
w1.Activate
K = 3
For Each r In Intersect(Range("C3:C3" & a), ActiveSheet.UsedRange)
ct = r.Value
If InStr(ct, x) > 0 And ct <> "" Then
r.Copy w2.Cells(K, 1)
K = K + 1
w2.Activate
End If
Next r
End Sub
Assign the entire range to an array for quicker looping, then once the array finds a match to your inputstring, rewrite the values to your 2nd sheet.
Sub test()
Dim ws1 As Worksheet, ws2 As Worksheet, wsArr()
set ws1 = thisworkbook.worksheets("Sheet1")
set ws2 = thisworkbook.worksheets("Sheet2")
With ws1
wsArr = .Range(.Cells(3, 1), .Cells(LastRow(ws1), 4)).Value
End With
Dim findStr As String
findStr = InputBox("Please Enter Place")
Dim i As Long, r as long
Application.ScreenUpdating = False
With ws2
.Range("A3:D3").Value = array("Place", "Name", "Thing", "Animal")
For i = LBound(wsArr) To UBound(wsArr)
If wsArr(i, 3) = findStr Then
r = LastRow(ws2) + 1
.Cells(r, 1) = wsArr(i, 3)
.Cells(r, 2) = wsArr(i, 1)
.Cells(r, 3) = wsArr(i, 2)
.Cells(r, 4) = wsArr(i, 4)
End If
Next
End With
Application.ScreenUpdating = True
End Sub
Function LastRow(ByVal ws As Worksheet, Optional ByVal col As Variant = 1) As Long
With ws
LastRow = .Cells(.Rows.Count, col).End(xlUp).Row
End With
End Function
For even better performance, consider doing a COUNTIF() to get the count of the number of findStr occurances in your range - that way you can use this value to ReDim a new array in order to write the matches there, then write the array to Sheet2 all at once.

Resources