I'm required to upload excel B to SQL database. But the users only managed to provide the format in excel A due to some reasons. Therefore, I need a transpose method to convert excel A into excel B so that my upload can be done.
Here are the format for excel A and B.
Excel A (user provided)
AREA CATEGORY 202033 202034 202035 202036
WET FISH 33 34 35 36
WET CHICKEN 36 35 34 33
DRY VEGETABLES 34 28 24 24
Excel B (required format to upload to SQL database)
AREA CATEGORY WEEK SALES
WET FISH 202033 33
WET FISH 202034 34
WET FISH 202035 35
WET FISH 202036 36
WET CHICKEN 202033 36
WET CHICKEN 202034 35
WET CHICKEN 202035 34
WET CHICKEN 202036 33
DRY VEGETABLES 202033 34
DRY VEGETABLES 202034 28
DRY VEGETABLES 202035 24
DRY VEGETABLES 202036 24
I'm totally new to VBA excel macro but I need to get this completed. Anyone can guide me?
I shouldn't answer this post because there the OP has provided no coding examples. But the OP did make an effort to write an otherwise good post and I'm quite bored.
Sub ConvertUserData()
Const SourceWorksheetName As String = "Sheet1"
Const HeaderColumnCount As Long = 2
Dim Data As Variant
Data = Worksheets(SourceWorksheetName).Range("A1").CurrentRegion
Dim RowCount As Long
RowCount = (UBound(Data, 2) - HeaderColumnCount) * (UBound(Data) - 1)
Dim Results() As Variant
ReDim Results(1 To RowCount, 1 To 4)
Dim Row As Long
Dim Column As Long
Dim n As Long
For Row = 2 To UBound(Data)
For Column = HeaderColumnCount + 1 To UBound(Data, 2)
n = n + 1
Results(n, 1) = Data(Row, 1)
Results(n, 2) = Data(Row, 2)
Results(n, 3) = Data(1, Column)
Results(n, 4) = Data(Row, Column)
Next
Next
With Workbooks.Add
With Worksheets(1)
.Range("A1:D1").Value = Array("AREA", "CATEGORY", "WEEK", "SALES")
.Range("A2").Resize(RowCount, 4) = Results
End With
End With
End Sub
Try,
Sub test()
Dim vDB, vR()
Dim Ws As Worksheet
Dim toWs As Worksheet
Dim i As Long, r As Long, n As Long
Dim j As Integer, c As Integer
Set Ws = ActiveSheet 'set your Orginal data sheet
Set toWs = Sheets(2) 'set Result sheet
vDB = Ws.Range("a1").CurrentRegion
r = UBound(vDB, 1)
c = UBound(vDB, 2)
For i = 2 To r
For j = 3 To c
If vDB(i, j) <> "" Then
n = n + 1
ReDim Preserve vR(1 To 4, 1 To n)
vR(1, n) = vDB(i, 1)
vR(2, n) = vDB(i, 2)
vR(3, n) = vDB(1, j)
vR(4, n) = vDB(i, j)
End If
Next j
Next i
With toWs
.UsedRange.Clear
.Range("a1").Resize(1, 4) = Array("AREA", "CATEGORY", "WEEK", "SALES")
.Range("a2").Resize(n, 4) = WorksheetFunction.Transpose(vR)
End With
End Sub
Related
Would appreciate any help here based on a previous question.
The code below was the original ask and finding a way in VBA to turn the original table into the output excel.
Data 4/1/2012 4/2/2012 4/3/2012 4/4/2012 4/5/2012
V 10 20 30 40 50
H 5 10 15 20 25
S 6 12 18 24 30
R 8 16 24 32 40
A 9 18 27 36 45
Output : Excel Table
V 4/1/2012 10
V 4/2/2012 20
V 4/3/2012 30
V 4/4/2012 40
V 4/5/2012 50
H 4/1/2012 5
H 4/2/2012 10
H 4/3/2012 15
H 4/4/2012 20
H 4/5/2012 25
.
.
.
A 4/1/2012 9
A 4/2/2012 18
A 4/3/2012 27
A 4/4/2012 36
A 4/5/2012 45
The answer is below and works, but I was hoping for some help in terms of adapting the code below so the output is created on a new sheet within the same workbook. What code should be added? Thank you.
Option Explicit
Sub colsToRows()
Dim ws1 As Worksheet
Dim a As Long, lr As Long, lc As Long
Dim va As Variant, vd As Variant
Dim LastRow As Long, LastCol As Long
'-- set e.g. sheet name Sheet1, starting column = B, dates starting cell = C2
Set ws1 = Sheets("Sheet1")
LastRow = ws1.Range("B" & ws1.Rows.Count).End(xlUp).Row
LastCol = ws1.Cells(Range("C2").Row, ws1.Columns.Count).End(xlToLeft).Column - 1
'--put dates into this array as it repeats for each item
vd = WorksheetFunction.Transpose(WorksheetFunction.Transpose(ws1.Range("C2").Resize(1, LastCol - 1)))
'-- titles
ws1.Range("B2").Offset(LastRow + 1) = "Item"
ws1.Range("C2").Offset(LastRow + 1) = "Dates"
ws1.Range("D2").Offset(LastRow + 1) = "Data"
'--2 is deducted as the main range is starting from B3. So B3-B1 = 2
For a = 1 To LastRow - 2
'--to get next last row
lr = Cells(Rows.Count, "B").End(xlUp).Row
'--items
va = Array(ws1.Range("B2").Offset(a).Value)
ws1.Range("B1").Offset(lr).Resize(LastCol - 1) = Application.Transpose(va)
'--dates
ws1.Range("C1").Offset(lr).Resize(UBound(vd)) = Application.Transpose(vd)
'--data
va = WorksheetFunction.Transpose(WorksheetFunction.Transpose(ws1.Range("C2").Offset(a).Resize(1, LastCol - 1)))
ws1.Range("D1").Offset(lr).Resize(UBound(va)) = Application.Transpose(va)
Next a
End Sub
This code will put the result on a new sheet.
Note, it assumes the data starts in A1 on Sheet1.
Option Explicit
Sub colsToRowsToNewSheet()
Dim ws1 As Worksheet
Dim wsNew As Worksheet
Dim arrData As Variant
Dim arrOut As Variant
Dim idxRow As Long
Dim idxCol As Long
Dim cnt As Long
'-- set e.g. sheet name Sheet1, starting column = B, dates starting cell = C2
Set ws1 = Sheets("Sheet1")
' Set ws1 = ActiveSheet
arrData = ws1.Range("A1").CurrentRegion
ReDim arrOut(1 To (UBound(arrData, 1) - 1) * (UBound(arrData, 2) - 1), 1 To 3)
For idxRow = LBound(arrData, 1) + 1 To UBound(arrData, 1)
For idxCol = LBound(arrData, 2) + 1 To UBound(arrData, 2)
cnt = cnt + 1
arrOut(cnt, 1) = arrData(idxRow, 1)
arrOut(cnt, 2) = arrData(1, idxCol)
arrOut(cnt, 3) = arrData(idxRow, idxCol)
Next idxCol
Next idxRow
Set wsNew = Sheets.Add
wsNew.Range("A1:C1").Value = Array("Data", "Date", "Item")
wsNew.Range("A2:C2").Resize(cnt).Value = arrOut
End Sub
How can I turn this table
ID Date Type Date
26 Date of Hire 01/15/1996
27 Date of Hire 10/01/2003
27 Seniority Date 12/04/1989
38 Date of Hire 07/13/2000
39 Date of Hire 06/01/1987
40 Date of Hire 12/11/1995
41 Date of Hire 05/01/2005
41 Seniority Date 09/22/1986
into this table, using VBA
ID Date Hired Sen Date
26 01/15/1996
27 10/01/2003 12/04/1989
38 07/13/2000
39 06/01/1987
40 12/11/1995
41 05/01/2005 09/22/1986
I've been trying to figure this our for far to long and unable to find a similar question on here which works with my data.
Appreciate any input!
Here is some code i've been playing with but i'm unable to get it to work. I know m offsests are likely not where they should be and im unable to get past the error commented below.
Sub LongtoWide()
Dim Rng As Range
Dim Dn As Range
Dim n As Long
Dim Col As Date
Dim twn As String
Dim c As Long
Set Rng = Range(Range("A2"), Range("A" & Rows.Count).End(xlUp))
ReDim Ray(1 To Rng.Count, 1 To 3)
With CreateObject("scripting.dictionary")
.CompareMode = vbTextCompare
For Each Dn In Rng
twn = Dn & Dn.Offset(, 1)
Col = Asc(Dn.Offset(, 1))
If Not .Exists(twn) Then
n = n + 1
.Add twn, n
Ray(n, 1) = Dn: Ray(n, 1) = Dn.Offset(, 1)
Ray(n, Col) = Dn.Offset(, 1) '<----Subscript out of range error
Else
Ray(.Item(twn), Col) = Dn.Offset(, 2)
End If
Next
c = .Count
End With
With Range("F1")
.Resize(, 3) = Array("ID", "DOH", "SenDate")
.Offset(1).Resize(c, 3) = Ray
End With
End Sub
Here's a VBA approach if you are interested. This works by looping through the ID column to detect when there is a change, then add the item to an array to output in the correct format.
Public Sub TransformData()
Dim IDs As Range
Dim ID As Range
Dim ws As Worksheet
Dim Output As Variant
Dim i As Long
Dim PrevID As String
Set ws = ThisWorkbook.Sheets("Sheet1") ' adjust as needed
Set IDs = ws.Range("A2:A9") 'Specify range to scan
ReDim Output(1 To 3, 1 To 5000) 'Create an array large enough
'Loop through each ID
For Each ID In IDs
i = i + 1
'When the id is the same, this is the seniority row, assuming seniority appears after DateHired
If ID = PrevID Then
i = i - 1
Output(3, i) = ID.Offset(0, 2) 'Update 3rd element
Else
Output(1, i) = ID
Output(2, i) = ID.Offset(0, 2)
End If
PrevID = ID
Next
'Output data
ReDim Preserve Output(1 To 3, 1 To i)
ws.Range("E1:G1") = Array("ID", "Date Hired", "Sen Date")
ws.Range("E2:G" & UBound(Output, 2) + 1) = Application.Transpose(Output)
End Sub
I have a sorted list of names in a single column. I would like to transform the names to 3X8 tables before printing them (printing single column would use too much paper). This is Excel. I'll copy names one by one and paste to a blank sheet.
Using numbers as an example, the resulting order should look like this:
1 9 17
2 10 18
3 11 19
4 12 20
5 13 21
6 14 22
7 15 23
8 16 24
25 33 41
26 34 42
27 35 43
........
Possible to get a general answer (n x m table)?
Below is what I have got. It's close but not quite right.
last_row = ThisWorkbook.Sheets(1).Cells(20000,1).End(xlUp).Row
For i = 1 To last_row/24 +1 Step 1
For k = 1 To 3 Step 1
For j = 1 To members_per_column Step 1
ThisWorkbook.Sheets(1).Cells( i + j + (k - 1) * 8 + (i - 1) * 16 + 1, _
name_column).Copy
Worksheets(destination_page).Cells( i + j - 1, (k - 1) +1).PasteSpecial _
Paste:=xlPasteValues
Next j
Next k
Next i
You were already close. I wrapped the code into a function so you can easily re-use it on any matrix size:
Option Explicit
Public Sub TransformIntoBlocks(ByVal MatrixRows As Long, ByVal MatrixColumns As Long, ByVal SourceRange As Range, ByVal OutputStartRange As Range)
Dim BlockStartRow As Long
BlockStartRow = 1
Dim iRowSource As Long
iRowSource = 1
Dim AmountOfBlocks As Long
AmountOfBlocks = WorksheetFunction.RoundUp(SourceRange.Rows.Count / (MatrixRows * MatrixColumns), 0)
Dim iBlock As Long
For iBlock = 1 To AmountOfBlocks
Dim iCol As Long
For iCol = 1 To MatrixColumns
Dim iRow As Long
For iRow = BlockStartRow To BlockStartRow + MatrixRows - 1
OutputStartRange.Offset(iRow - 1, iCol - 1).Value = SourceRange(iRowSource, 1).Value
iRowSource = iRowSource + 1
Next iRow
Next iCol
BlockStartRow = BlockStartRow + MatrixRows
Next iBlock
End Sub
Sub test()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
TransformIntoBlocks MatrixRows:=8, MatrixColumns:=3, SourceRange:=ws.Range("A1", ws.Cells(ws.Rows.Count, "A").End(xlUp)), OutputStartRange:=Tabelle2.Range("C1")
End Sub
Rather than going through three loops, I ended up just using one loop to write in the correct position using mod.
Seems obvious to me as the writer, but please ask questions if it's unclear- it helps the next reader.
Option Explicit
Sub ColumnSplit()
Dim input_rows As Integer
Dim output_columns As Integer
Dim output_rows As Integer
Dim i As Integer
Dim input_sheet As Worksheet
Dim output_sheet As Worksheet
Set input_sheet = Sheet1
Set output_sheet = Sheet2
'output_sheet.Cells.Clear 'optional
output_columns = 3 'Hard coded. Set to whatever you like
input_rows = input_sheet.Cells(Rows.Count, 1).End(xlUp).Row
output_rows = CInt(WorksheetFunction.Ceiling(CDbl(input_rows) / CDbl(output_columns), 1))
For i = 1 To input_rows
output_sheet.Cells( _
((i - 1) Mod output_rows) + 1 _
, (WorksheetFunction.Floor((i - 1) / output_rows, 1) Mod output_columns) + 1 _
) _
= input_sheet.Cells(i, 1) 'cells(calculate output row,calculate output column) = input value
Next i
End Sub
How can I repeat rows in a spreadsheet by number of times specified in a cell in that row and decrement an ID in the same row?
E.g. from this table:
Column A Column B Column C
Peter 123 3
James 32 7
David 90 4
I need to produce this table:
Column A Column B Column C
Peter 123 3
Peter 122 3
Peter 121 3
James 32 7
James 31 7
James 30 7
James 29 7
James 28 7
James 27 7
James 26 7
David 90 4
David 89 4
David 88 4
David 87 4
Find below the code I'm using.
Public Sub CopyData()
Dim rngSinglecell As Range
Dim rngQuantityCells As Range
Dim intCount As Integer
Set rngQuantityCells = Range("C1", Range("C1").End(xlDown))
For Each rngSinglecell In rngQuantityCells
If IsNumeric(rngSinglecell.Value) Then
If rngSinglecell.Value > 0 Then
For intCount = 1 To rngSinglecell.Value
Range(rngSinglecell.Address).EntireRow.Copy Destination:=Sheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Offset(1)
Next
End If
End If
Next
End Sub
This quick code will do what you want:
Sub myDup()
With Worksheets("Sheet3") ' change to your sheet
Dim rngArr As Variant
rngArr = .Range(.Cells(1, 1), .Cells(.Rows.Count, 3).End(xlUp)).Value
Dim outarr As Variant
ReDim outarr(1 To Application.Sum(Application.Index(rngArr, 0, 3)), 1 To 3)
Dim k As Long
k = 1
Dim i As Long
For i = LBound(rngArr, 1) To UBound(rngArr, 1)
Dim j As Long
For j = 1 To rngArr(i, 3)
outarr(k, 1) = rngArr(i, 1)
outarr(k, 2) = rngArr(i, 2) - j + 1
outarr(k, 3) = rngArr(i, 3)
k = k + 1
Next j
Next i
.Range("A1").Resize(UBound(outarr, 1), 3).Value = outarr
End With
End Sub
I am stuck on problem where my vba won't increment row number. My tables looks like:
Sheet1
name value
aa 11
bb 12
cc 13
aa 14
cc 15
cc 16
aa 17
bb 18
aa 19
Sheet2
name
aa
bb
cc
I need to search for each specific value, if found copy adjacent cell to sheet2 right next searched value. This is code doing but problem is with row incrementation, all searched values are in one row (variable k is not working).
Sub finall()
Dim cable As String
Dim finalrow1 As Integer
Dim finalrow2 As Integer
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim l As Integer
l = 2
k = 2
finalrow2 = Sheets("Sheet2").Range("A1000").End(xlUp).Row
finalrow1 = Sheets("Sheet1").Range("A1000").End(xlUp).Row
For j = 2 To finalrow2
cable = Sheets("Sheet2").Cells(j, 1).Value
For i = 2 To finalrow1
If Cells(i, 1) = cable Then
Sheets("Sheet1").Cells(i, 2).Copy
Sheets("Sheet2").Cells(k, l).End(xlUp).Offset(1, 0).PasteSpecial
l = l + 1
End If
Next i
k = k + 1
Next j
End Sub
This is only example in final i want to apply this code to table with 50-60k rows.
Final table should look like:
name
aa 11 14 17 19
bb 12 18
cc 13 15 16
Thx
Final code would be as below
Sub finall()
Dim cable As String
Dim finalrow1 As Long
Dim finalrow2 As Long
Dim i As Long
Dim j As Long
Dim k As Long
Dim l As Long
l = 2
k = 2
finalrow2 = Sheets("Sheet2").Range("A1000").End(xlUp).Row
finalrow1 = Sheets("Sheet1").Range("A1000").End(xlUp).Row
Worksheets("Sheet2").Select
For j = 2 To finalrow2
cable = Sheets("Sheet2").Cells(j, 1).Value
For i = 2 To finalrow1
If Sheets("Sheet1").Cells(i, 1) = cable Then
Sheets("Sheet1").Cells(i, 2).Copy
Sheets("Sheet2").Cells(k, l).PasteSpecial
l = l + 1
End If
Next i
k = k + 1
l = 2
Next j
End Sub
Proof of work