Arranging the row data into Columns using VBA in excel? - vba

I am adapting off of the question: Re-Arranging the row data in columns
I have Excel data set up as follows;
Collection LatDD LonDD Date Location Method Specie1 Specie2 Specie3(+-110 species columns in total)
ABS1 11.35 -10.3 2003-02-01 A Bucket 0 1 3
ABS2 11.36 -10.4 2003-02-02 B Stick 2 0 6
I would Like This Data to appear like so:
Collection Specie Count LatDD LonDD Date Location Method
ABS1 Specie1 11.35 -10.3 2003-02-01 A Bucket
ABS1 Specie2 1 11.35 -10.3 2003-02-01 A Bucket
ABS1 Specie3 3 11.35 -10.3 2003-02-01 A Bucket
ABS2 Specie1 2 11.36 -10.4 2003-02-02 B Stick
ABS2 Specie2 -11.36 -10.4 2003-02-02 B Stick
ABS2 Specie3 6 -11.36 -10.4 2003-02-02 B Stick
I attempted to adapt Ripsters original VBA code answer but unfortunately i was unable to figure how i would need to change it. Could someone please advise me on how to adjust his code to produce the desired output?
Here is his orginal vba code:
Sub Example()
Dim Resources() As String
Dim rng As Range
Dim row As Long
Dim col As Long
Dim x As Long
ReDim Resources(1 To (ActiveSheet.UsedRange.Rows.Count - 1) * (ActiveSheet.UsedRange.Columns.Count - 1), 1 To 3)
'Change this to the source sheet
Sheets("Sheet1").Select
'Read data into an array
For row = 2 To ActiveSheet.UsedRange.Rows.Count
For col = 2 To ActiveSheet.UsedRange.Columns.Count
x = x + 1
Resources(x, 1) = Cells(row, 1).Value ' Get name
Resources(x, 2) = Cells(1, col).Value ' Get date
Resources(x, 3) = Cells(row, col).Value ' Get value
Next
Next
'Change this to the destination sheet
Sheets("Sheet2").Select
'Write data to sheet
Range(Cells(1, 1), Cells(UBound(Resources), UBound(Resources, 2))).Value = Resources
'Insert column headers
Rows(1).Insert
Range("A1:C1").Value = Array("Resource", "Date", "Value")
'Set strings to values
Set rng = Range(Cells(1, 3), Cells(ActiveSheet.UsedRange.Rows.Count, 3))
rng.Value = rng.Value
End Sub

Try this:
Sub Example()
Dim row As Long
Dim col As Long
Dim x As Long
h1 = "Sheet1"
h2 = "Sheet2"
Sheets(h1).Select
x = 2
'Headers Sheet2
Sheets(h2).Cells(1, 1).Value = Sheets(h1).Cells(1, 1)
Sheets(h2).Cells(1, 2).Value = "Specie"
Sheets(h2).Cells(1, 3).Value = "Count"
Sheets(h2).Cells(1, 4).Value = Sheets(h1).Cells(1, 2)
Sheets(h2).Cells(1, 5).Value = Sheets(h1).Cells(1, 3)
Sheets(h2).Cells(1, 6).Value = Sheets(h1).Cells(1, 4)
Sheets(h2).Cells(1, 7).Value = Sheets(h1).Cells(1, 5)
Sheets(h2).Cells(1, 8).Value = Sheets(h1).Cells(1, 6)
For row = 2 To ActiveSheet.UsedRange.Rows.Count
For col = 7 To ActiveSheet.UsedRange.Columns.Count
Sheets(h2).Cells(x, 1).Value = Sheets(h1).Cells(row, 1).Value
Sheets(h2).Cells(x, 2).Value = Sheets(h1).Cells(1, col).Value
Sheets(h2).Cells(x, 3).Value = Sheets(h1).Cells(row, col).Value
Sheets(h2).Cells(x, 4).Value = Sheets(h1).Cells(row, 2).Value
Sheets(h2).Cells(x, 5).Value = Sheets(h1).Cells(row, 3).Value
Sheets(h2).Cells(x, 6).Value = Sheets(h1).Cells(row, 4).Value
Sheets(h2).Cells(x, 7).Value = Sheets(h1).Cells(row, 5).Value
Sheets(h2).Cells(x, 8).Value = Sheets(h1).Cells(row, 6).Value
x = x + 1
Next
Next
End Sub
Sheet1:
Sheet2:
A short versiĆ³n:
Sub Example()
Dim row As Long
Dim col As Long
Dim x As Long
Set Sh1 = ThisWorkbook.Worksheets("Sheet1")
Set Sh2 = ThisWorkbook.Worksheets("Sheet2")
Sh1.Select
'Headers Sheet2
Sh2.Cells(1, 1).Value = Sh1.Cells(1, 1)
Sh2.Cells(1, 2).Value = "Specie"
Sh2.Cells(1, 3).Value = "Count"
For i = 4 To 8
Sh2.Cells(1, i).Value = Sh1.Cells(1, i - 2)
Next
x = 2 'Starting row of sheet2.
For row = 2 To ActiveSheet.UsedRange.Rows.Count
For col = 7 To ActiveSheet.UsedRange.Columns.Count
Sh2.Cells(x, 1).Value = Sh1.Cells(row, 1).Value
Sh2.Cells(x, 2).Value = Sh1.Cells(1, col).Value
Sh2.Cells(x, 3).Value = Sh1.Cells(row, col).Value
For i = 4 To 8
Sh2.Cells(x, i).Value = Sh1.Cells(row, i - 2).Value
Next
x = x + 1
Next
Next
Sh2.Select
End Sub

another idea....
Your source data is in "Sheet1", starting at "A1", no empty values neither in Column A, nor in Row 1.
If you run the code, you will get the re-sorted table in "Sheet2" ( I omitted headers, though - too lazy....)
Hope this helps
Sub sort_new()
Dim col_no As Long, row_no As Long
Dim i As Long, j As Long, k As Long
Dim arr_DB As Variant, arr_new As Variant
Dim ws1 As Worksheet, ws2 As Worksheet
Set ws1 = ThisWorkbook.Worksheets("Sheet1")
Set ws2 = ThisWorkbook.Worksheets("Sheet2")
ws1.Activate
row_no = ws1.Range(Cells(Rows.Count, 1), Cells(Rows.Count, 1)).End(xlUp).Row
col_no = ws1.Range(Cells(1, Columns.Count), Cells(1, Columns.Count)).End(xlToLeft).Column
arr_DB = ws1.Range(Cells(1, 1), Cells(row_no, col_no))
ReDim arr_new(1 To (row_no - 1) * (col_no - 6), 1 To 8)
For i = 2 To row_no
For j = 7 To col_no
k = k + 1
arr_new(k, 1) = arr_DB(i, 1) 'Collection
arr_new(k, 4) = arr_DB(i, 2) 'LatDD
arr_new(k, 5) = arr_DB(i, 3) 'LonDD
arr_new(k, 6) = arr_DB(i, 4) 'Date
arr_new(k, 7) = arr_DB(i, 5) 'Location
arr_new(k, 8) = arr_DB(i, 6) 'Method
arr_new(k, 2) = arr_DB(1, j) 'Each Specie(j) Column
arr_new(k, 3) = arr_DB(i, j) 'Each Specie(j) Column
Next
Next
ws2.Activate
ws2.Range(Cells(2, 1), Cells((row_no - 1) * (col_no - 6) + 1, 8)) = arr_new
End Sub

Related

button different from Module?

Private Sub CommandButton1_Click()
Dim nbp As Long
Dim i As Long
Dim p As Long
Dim FV As Variant
Dim CS As Variant
Dim K As Variant
Dim iFV As Integer
Dim iCS As Double
If Range("B9") = "Semi-Annual" Then
p = DateDiff("yyyy", Cells(4, 3), Cells(5, 3))
nbp = p * 2
For i = 5 To nbp + 4
Cells(5, 10).Value = Cells(4, 3).Value
Cells(i + 1, 10).Value = DateAdd("m", 6, Cells(i, 10).Value)
Next i
For i = 6 To nbp + 5
Cells(i, 14).Value = Cells(7, 2).Value * (Cells(8, 2).Value / 2)
Next i
FV = Sheet2.Range("J5:J10").Value
CS = Sheet3.Range("F1:G8000").Value
For iFV = 1 To UBound(FV)
For iCS = 1 To UBound(CS, 2)
If FV(iFV, 1) = CS(iCS, 1) Then
K(iFV, 1) = CS(iCS, 2)
End If
Next
Next
Sheet2.Range("K5:K10").Value = K
End If
End If
If Range("B9") = "Annual" Then
nbp = DateDiff("yyyy", Cells(4, 3), Cells(5, 3))
For i = 5 To nbp + 4
Cells(5, 10).Value = Cells(4, 3).Value
Cells(i + 1, 10).Value = DateAdd("m", 12, Cells(i, 10).Value)
Next i
End if
If Range("B9") = "Quarterly" Then
p = DateDiff("yyyy", Cells(4, 3), Cells(5, 3))
nbp = p * 4
For i = 5 To nbp + 4
Cells(5, 10).Value = Cells(4, 3).Value
Cells(i + 1, 10).Value = DateAdd("m", 3, Cells(i, 10).Value)
Next i
End If
If Range("B9") = "Monthly" Then ' to choose from a list .
p = DateDiff("yyyy", Cells(4, 3), Cells(5, 3))
nbp = p * 12
For i = 5 To nbp + 4
Cells(5, 10).Value = Cells(4, 3).Value
Cells(i + 1, 10).Value = DateAdd("m", 3, Cells(i, 10).Value)
Next i
End If
End Sub
I have added all the code in the button to help. i am not sure if that will help, anyway here is it. if the user chooses semi annual then couple of things take place. Same goes for the rest "ifs" but i need to fix this issue first then move on to the rest. the code to too long, it is simple and not complicated.
Now that more of the code is posted, I think I understand what the problem is.
Wherever you reference Cells() VBA assumes it applies to ActiveSheet. And I think you should fully qualify the calls to be Sheet2.Cells() for example or whatever you need.
When you call the code behind a button, the button resides on a sheet and it references the cells on that sheet. But when you moved the code to a module it no longer referenced the sheet with the button, but whatever other sheet was active at the time.
So whenever you see Cells() or Range() without a worksheet specification in front of it, change it so that it you target a specific worksheet.
PS. Avoid using Integer and prefer Long instead. Also, prefer relative referencing such as Sheet2.Range("G2").Cells(i,j) instead of absolute referencing Sheet2.Cells(1+i, 6+j) or string math such as Sheet2.Range("G" & 1+i & ":G" & 5+i).

Only transpose data to a new column if it is a new group of data / excel vba

I have a column of data in excel which could potentially have data over 2000 rows. In that data there is groups of data that I would like to send to the top of a new column every time a new group is found. I've looked at the special paste option for transpose along with using a delimiter but i can only move data one column over and not to the top. I'm looking for a solution which is fast due to the amount of data that would need to be split into new columns. I appreciate the help.
Below is a table of how the data looks.
Below is how I would like the data to look
Try this simple code,
Sub splitRange()
Dim i As Long, j As Long, k As Long
Cells(1, 6) = Cells(1, 1)
Cells(1, 7) = Cells(1, 2)
j = 1
k = 6
For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
If Cells(i, 1) = Cells(i - 1, 1) Then
j = j + 1
Cells(j, k) = Cells(i, 1)
Cells(j, k + 1) = Cells(i, 2)
Else
k = k + 3
j = 1
Cells(j, k) = Cells(i, 1)
Cells(j, k + 1) = Cells(i, 2)
End If
Next i
End Sub
Modify the code if you want the output in a separate sheet. I would like you to google it to learn about it.
I had to do something similar. You can try also this code:
Sub Move_Data()
Application.ScreenUpdating = False
Dim r As Integer
Dim StartRow As Integer
Dim EndRow As Integer
Dim ColA As Integer
Dim vLastRow As Integer
Dim vEnd As Integer
r = 1
StartRow = 1
EndRow = 1
ColA = 4
vEnd = 1
vLastRow = Cells.Find("*", [A1], , , xlByRows, xlPrevious).Row
Do Until Cells(r, 1) <> Cells(StartRow, 1)
DoEvents
r = r + 1
Loop
vEnd = r
Do Until r > vLastRow
DoEvents
StartRow = r
Do Until Cells(r, 1) <> Cells(StartRow, 1)
DoEvents
r = r + 1
Loop
EndRow = r - 1
Range(Cells(StartRow, 1), Cells(EndRow, 2)).Select
Selection.Copy
Cells(1, ColA).Select
ActiveSheet.Paste
ColA = ColA + 3
Loop
r = vEnd + 1
Range(Cells(vEnd, 1), Cells(vLastRow, 2)).ClearContents
Cells(1, 1).Select
Application.ScreenUpdating = True
MsgBox "Done"
End Sub

runtime error accured when I run a VBA script to create a simple report out of text output in blocks

Sub blockofdatatoreport()
Dim i As Integer
Dim x As Integer
Dim y As Integer
For i = 1 To 95
actvrw = Sheet1.Range("A:A").Find(what = i, searchdirection = xlNext).Row
'searching cells top to bottom
lr = Sheet2.Range("A:A").Find(what = "*", searchdirection = xlprevious).Row + 1
'searching cells bottom to top
For x = 1 To 5
Sheet2.Cells(lr, 1).Value = Sheet1.Cells(actvrw + (x - 1), 3).Value
'looping the first five columns in sheet2
Next
For y = 1 To 4
Sheet2.Cells(lr, 5 + y).Value = Sheet1.Cells(actvrw + (y - 1), 6).Value
'looping the next four columns after the first four is done in sheet2
Next
'You can also write like this or write a loop in two lines above.
'Sheet2.Cells(lr, 1).Value = Sheet1.Cells(actvrw, 3).Value
'Sheet2.Cells(lr, 2).Value = Sheet1.Cells(actvrw + 1, 3).Value
'Sheet2.Cells(lr, 3).Value = Sheet1.Cells(actvrw + 2, 3).Value
'Sheet2.Cells(lr, 4).Value = Sheet1.Cells(actvrw + 3, 3).Value
'Sheet2.Cells(lr, 5).Value = Sheet1.Cells(actvrw + 4, 3).Value
Next
End Sub
I get error called error 13 y type mismatch, what is in the above code causing the error??

Copy Rows into columns using VBA

I have a very little experience with VBA, and I would really appreciate any help with this issue.
I need to convert rows into columns from sheet 1 to sheet 2.
Input File
Desired Output
Sample data
My Code
Sub TransposeSpecial()
Dim lMaxRows As Long 'max rows in the sheet
Dim lThisRow As Long 'row being processed
Dim iMaxCol As Integer 'max used column in the row being processed
lMaxRows = Cells(Rows.Count, "A").End(xlUp).Row
lThisRow = 2 'start from row 2
Do While lThisRow <= lMaxRows
iMaxCol = Cells(lThisRow, Columns.Count).End(xlToLeft).Column
If (iMaxCol > 1) Then
Rows(lThisRow + 1 & ":" & lThisRow + iMaxCol - 1).Insert
Range(Cells(lThisRow, 2), Cells(lThisRow, iMaxCol)).Copy
Range("C" & lThisRow + 1).Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:=False, Transpose:=True
Range(Cells(lThisRow, 2), Cells(lThisRow, iMaxCol)).Clear
lThisRow = lThisRow + iMaxCol - 1
lMaxRows = Cells(Rows.Count, "A").End(xlUp).Row
End If
lThisRow = lThisRow + 1
Loop
End Sub
Output obtained by Code
Desired output
Here you go, I made this flexible code. Just update the variables in the beginning.
Sub Transpose_my_cells()
Dim rng As Range
Dim sheet1, sheet2, addr As String
Dim src_top_row, src_left_col, dst_top_row, dst_left_col, data_cols, y As Integer
Application.ScreenUpdating = False
sheet1 = "Sheet1" 'Put your source sheet name here
sheet2 = "Sheet2" 'Put your destiny sheet name here
src_top_row = 1 'Put the top row number of the source here
src_left_col = 1 'Put the left col number of the source here
dst_top_row = 1 'Put the top row number of the destiny here
dst_left_col = 1 'Put the left col number of the destiny here
'Count data columns
data_cols = 0
Do Until Worksheets(sheet1).Cells(src_top_row, src_left_col + data_cols + 1) = ""
data_cols = data_cols + 1
Loop
'start copying data
With Worksheets(sheet1)
'first header
.Cells(src_top_row, src_left_col).Copy
addr = Cells(dst_top_row, dst_left_col).Address
Worksheets(sheet2).Range(addr).PasteSpecial
y = 0
'loop for each source row
Do Until .Cells(src_top_row + y + 1, src_left_col) = ""
'Create First column repetitions
.Cells(src_top_row + y + 1, src_left_col).Copy
addr = Cells(dst_top_row + y * data_cols + 1, dst_left_col).Address & ":" & Cells(dst_top_row + y * data_cols + data_cols, dst_left_col).Address
Worksheets(sheet2).Range(addr).PasteSpecial
'Transpose Data Headers
addr = Cells(src_top_row, src_left_col + 1).Address & ":" & Cells(src_top_row, src_left_col + data_cols).Address
.Range(addr).Copy
Worksheets(sheet2).Cells(dst_top_row + y * data_cols + 1, dst_left_col + 1).PasteSpecial Transpose:=True
'Transpose Data columns
Set rng = Cells(src_top_row + y + 1, src_left_col + 1)
addr = rng.Address & ":" & rng.Offset(0, data_cols - 1).Address
.Range(addr).Copy
Worksheets(sheet2).Cells(dst_top_row + y * data_cols + 1, dst_left_col + 2).PasteSpecial Transpose:=True
y = y + 1
Loop
End With
Application.ScreenUpdating = True
End Sub
Using VBA:
Sub Transpose_my_cells()
Worksheets("Sheet1").Range("A1:E1").Copy
Worksheets("Sheet2").Range("A1").PasteSpecial Transpose:=True
End Sub
Notes:
Change Sheet1 and Sheet2 with your sheet names as shown in the VBA sheet list.
change A1:E1 to the source cell range
change A1 to the destiny top cell
There is probably a much easier/cleaner way to do this but it works. The way it's written now, it will take the data in Sheet1 and output the transposed data on Sheet2. It should work as long as your data starts in cell A1.
Option Explicit
Sub transpose()
Dim names() As String
Dim count As Long
Dim i As Long
Dim j As Long
Dim rng As Range
Dim tmp As Long
Sheets("Sheet1").Activate
count = 0
With ThisWorkbook.Sheets("Sheet1")
Do Until .Cells(1, 2 + count) = ""
count = count + 1
Loop
ReDim names(0 To count - 1)
count = 0
Do Until .Cells(1, 2 + count) = ""
names(count) = .Cells(1, 2 + count).Value
count = count + 1
Loop
.Range("A2").Activate
Set rng = Range(Selection, Selection.End(xlDown))
End With
j = 0
With ThisWorkbook.Sheets("Sheet2")
.Cells(1, 1).Value = "ID"
.Cells(1, 2).Value = "Name"
.Cells(1, 3).Value = "Value"
For i = 0 To rng.count * count - 1
If i Mod count = 0 Then
j = j + 1
Range(Cells(j + 1, 2), Cells(j + 1, count + 1)).Copy
.Cells(i + 2, 3).PasteSpecial transpose:=True
End If
.Cells(i + 2, 1).Value = rng(j).Value
.Cells(i + 2, 2).Value = names(i Mod count)
Next i
.Activate
End With
End Sub

Excel - Select Column by number and sheetname

I have 4 columns on Sheet1 and 4 on Sheet2
I have named the columnson sheet 1 as:
MvarNo = 1
Mdesc = 2
Mfile = 3
Mfield = 4
where 1 = a etc....
How do I name these columns with the sheet name and column number?
Thanks
UPDATE
Sub Compare()
MvarNo = 1 'Sheet1
Mdesc = 2 'Sheet1
Mfile = 3 'Sheet1
Mfield = 4 'Sheet1
XvarNo = 6 'Sheet1
Xdesc = 7 'Sheet1
Xfile = 8 'Sheet1
Xfield = 9 'Sheet1
CvarNo = 1 'Sheet2
Cdesc = 2 'Sheet2
Cfile = 3 'Sheet2
Cfield = 4 'Sheet2
'Count rows on Master Sheet (Sheet1)
MvarNoLastRow = Worksheets("Sheet1").Cells(Rows.Count, "A").End(xlUp).Row
MdesclastRow = Worksheets("Sheet1").Cells(Rows.Count, "B").End(xlUp).Row
MfilelastRow = Worksheets("Sheet1").Cells(Rows.Count, "C").End(xlUp).Row
MfieldlastRow = Worksheets("Sheet1").Cells(Rows.Count, "D").End(xlUp).Row
'Count rows on Compare Sheet (Sheet2)
CvarNoLastRow = Worksheets("Sheet2").Cells(Rows.Count, "A").End(xlUp).Row
CdesclastRow = Worksheets("Sheet2").Cells(Rows.Count, "B").End(xlUp).Row
CfilelastRow = Worksheets("Sheet2").Cells(Rows.Count, "C").End(xlUp).Row
CfieldlastRow = Worksheets("Sheet2").Cells(Rows.Count, "D").End(xlUp).Row
For i = 2 To MvarNoLastRow
For j = 2 To CvarNoLastRow
If Cells(i, MvarNo) = Cells(j, CvarNo) Then
Cells(i, XvarNo).Value = "Yes"
' If Cells(i, MvarNo) = Cells(j, CvarNo) And Cells(i, Mdesc) = Cells(j, Cdesc) And Cells(i, Mfile) = Cells(j, Cfile) And Cells(i, Mfield) = Cells(j, Cfield) Then
' Cells(i, XvarNo).Value = "Yes"
' ElseIf Cells(i, MvarNo) <> Cells(j, CvarNo) And Cells(i, Mdesc) <> Cells(j, Cdesc) And Cells(i, Mfile) <> Cells(j, Cfile) And Cells(i, Mfield) <> Cells(j, Cfield) Then
j = j + 1
ElseIf j = CvarNoLastRow Then
Cells(i, XvarNo).Value = "No"
End If
Next j
Next i
End Sub
the reason for this macro is to compare information between sheet 1 and sheet2.
I 'think' from my code it is actually just comparing the data on sheet 1 with sheet1.
Does this work?
Here my sheet is called "Ad revenues"
Sub test()
Dim lC As Long
Dim strColNames(1 To 4) As String
For lC = 1 To 4
strColNames(lC) = Sheet1.Name & vbTab & Str(Cells(1, lC).Column)
Next lC End Sub
End Sub()
If you need to get the sheet name, all of the following will work:
=SUBSTITUTE(CELL("filename"),LEFT(CELL("filename"),FIND("]",CELL("filename"))),"")
=RIGHT(CELL("filename"),LEN(CELL("filename"))-FIND("]",CELL("filename")))
=MID(CELL("filename"),FIND("]",CELL("filename"))+1,31)
The latter works because excel limits you to 31 characters when naming a sheet
To get the name of a column, you can use something like below:
=SUBSTITUTE(MID(ADDRESS(1,CELL("col")),2,2),"$","")
=MID(SUBSTITUTE(ADDRESS(1,COLUMN(R31)),"$1",""),2,2)