How can I autofill the entirety of column B based on column A but with n empty rows in between each letter?
Column A:
a
b
c
Column B:
a
...
...
b
...
...
c
I have tried the VBA code below:
Range("A1:A3").AutoFill Destination:=Range("A1:A10"), Type:=xlFillDefault
The code works with numbers but not when the cell references a formula (in this case, =A1, ...) as the code seems to reference the row the formula is, instead of the list in column A.
For example, the code inserts the formula a row after c in B7, however would insert =A7 instead of =A4 which would be the letter d.
Any help with this would be greatly appreciated.
To insert n row for each value in Column A, I will use offset to solve it, here is the solution and hope you find it useful:
Sub ty()
Dim count As Long, i As Long, nextrow As Long
count = Application.WorksheetFunction.CountA(Sheet1.Range("A:A"))
nextrow = 1
For i = 1 To count
Sheet1.Cells(nextrow, 2).Value = Sheet1.Cells(i, 1).Value
nextrow = Cells(nextrow, 2).Offset(3, 1).Row
Next
End Sub
Expected Output:
In order to preserve the formula into new cells, then you may need copy method` by change this part:
For i = 1 To count
Sheet1.Cells(i, 1).Copy Sheet1.Cells(nextrow, 2)
nextrow = nextrow + 3
Next
AutoFill Every n Rows
You run GetGappedColumnTEST. GetGappedColumn is being called by the GetGappedColumnTEST.
Adjust the values in the constants section and the workbook, and rename the Sub appropriately.
Option Explicit
Sub GetGappedColumnTEST()
Const sName As String = "Sheet1"
Const sFirst As String = "A1"
Const dName As String = "Sheet1"
Const dFirst As String = "B1"
Const dGap As Long = 2
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim Data As Variant
Data = GetGappedColumn(wb.Worksheets(sName).Range(sFirst), dGap)
If IsEmpty(Data) Then Exit Sub
Dim drCount As Long: drCount = UBound(Data, 1)
With wb.Worksheets(dName).Range(dFirst)
.Resize(drCount).Value = Data
.Resize(.Worksheet.Rows.Count - .Row - drCount + 1) _
.Offset(drCount).ClearContents
End With
End Sub
Function GetGappedColumn( _
ByVal FirstCell As Range, _
Optional ByVal Gap As Long = 0) _
As Variant
Const ProcName As String = "GetGappedColumn"
On Error GoTo clearError
If FirstCell Is Nothing Then Exit Function
If Gap < 0 Then Exit Function
Dim srg As Range
With FirstCell.Cells(1)
Dim lCell As Range
Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If lCell Is Nothing Then Exit Function
Set srg = .Resize(lCell.Row - .Row + 1)
End With
Dim rCount As Long: rCount = srg.Rows.Count
Dim sData As Variant
If rCount = 1 Then
ReDim sData(1 To 1, 1 To 1): sData(1, 1) = srg.Value
Else
sData = srg.Value
End If
Dim dData As Variant: ReDim dData(1 To rCount + rCount * Gap - Gap, 1 To 1)
Dim d As Long: d = 1
Dim s As Long
For s = 1 To rCount - 1
dData(d, 1) = sData(s, 1)
d = d + 1 + Gap
Next s
dData(d, 1) = sData(s, 1)
GetGappedColumn = dData
ProcExit:
Exit Function
clearError:
Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
Resume ProcExit
End Function
Related
I have an Excel sheet with 4 pages that takes input budgetary adjustment data and reformats into two different formats for entry into different budget softwares.
On the sheets first page, the upload page (feed data), data is given in rows of budget adjustments. These adjustments always come in even numbers of rows because for every account that has money adjusted out of it, another account has that money adjusted into it. In each row there are a number of non-unique qualitative columns that describe the adjustment and then 12 month columns that record the monetary aspects of the adjustment. Some rows have only one month of the 12 filled and can be left alone. Other adjustments occur over several months and thus have several of the months columns filled.
For input into the two budget softwares, these rows that have multiple month columns filled with data need to be expanded into multiple new rows with only one of the 12 columns filled. For clarity, here's what the transformation should look like:
Input:
Output:
How can you do this with input data where some rows don't need to be transformed, some include 2 months of transactions, and some could include up to 12?
Option Explicit
Sub Only_one_data_value_per_row()
Dim myR As Range
Dim rowCt As Integer
Dim actRange As Range
Dim dataCt As Integer
Dim iCt As Integer
Dim myCell As Range
Set actRange = Range("A1").CurrentRegion
For rowCt = actRange.Rows.Count To 2 Step -1
With ActiveSheet.Rows(rowCt)
dataCt = Application.WorksheetFunction.Count(.Range("E1:P1"))
'Debug.Print .Range("E1:P1").Address, dataCt)
For iCt = 1 To dataCt - 1
Rows(rowCt + 1).EntireRow.Insert
Rows(rowCt).Range("A1:D1").Copy Rows(rowCt + 1).Range("A1")
Next iCt
iCt = 0
For Each myCell In Rows(rowCt).Range("E1:P1")
'Debug.Print rowCt; ":"; (nonEmptyCell)
If myCell.Value <> "" Then
Debug.Print myCell.Value
If Val(myCell.Value) = 0 Then
MsgBox "The value of the cell " & myCell.Address & _
" is 0! The cell will be deleted!"
myCell.Value = ""
Else
If iCt > 0 Then
myCell.Offset(iCt, 0).Value = myCell.Value
myCell.Value = ""
End If
iCt = iCt + 1
End If
End If
Next myCell
End With
Next rowCt
End Sub
Input:
Output:
Transform Data: One Value Per Row
Adjust the values in the constants section.
Option Explicit
Sub TransformOneValuePerRow()
' Source
Const sName As String = "Sheet1"
Const sFirstCellAddress As String = "C4"
' Destination
Const dName As String = "Sheet2"
Const dFirstCellAddress As String = "A1"
' Both
Const FixedColumnsCount As Long = 4
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Reference the current region starting with the first cell.
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim sFirstCell As Range: Set sFirstCell = sws.Range(sFirstCellAddress)
Dim srg As Range
With sFirstCell.CurrentRegion
Set srg = sFirstCell.Resize(.Row + .Rows.Count - sFirstCell.Row, _
.Column + .Columns.Count - sFirstCell.Column)
End With
' Using 'GetTransformOneValuePerRow', return the transformed data
' in a 2D one-based array.
Dim Data As Variant
Data = GetTransformOneValuePerRow(srg, FixedColumnsCount)
If IsEmpty(Data) Then
MsgBox "An error occurred.", vbCritical
Exit Sub
End If
' Write to the destination range and clear below.
Dim rCount As Long: rCount = UBound(Data, 1)
With wb.Worksheets(dName).Range(dFirstCellAddress).Resize(, UBound(Data, 2))
.Resize(rCount).Value = Data
.Resize(.Worksheet.Rows.Count - .Row - rCount + 1).Offset(rCount).Clear
End With
MsgBox "Data transformed.", vbInformation
End Sub
Function GetTransformOneValuePerRow( _
ByVal SourceRange As Range, _
Optional ByVal FixedColumnsCount As Long = 1, _
Optional ByVal IncludeBlanks As Boolean = False) _
As Variant
Const ProcName As String = "GetTransformOneValuePerRow"
On Error GoTo ClearError
Dim sData As Variant ' Source Array
Dim srCount As Long ' Source Rows Count
Dim cCount As Long ' Source/Destination Columns Count
Dim drCount As Long ' Destination Rows Count
With SourceRange
srCount = .Rows.Count
cCount = .Columns.Count
With .Resize(srCount - 1, cCount - FixedColumnsCount) _
.Offset(1, FixedColumnsCount - 1) ' Values Range
drCount = .Rows.Count * .Columns.Count + 1
If Not IncludeBlanks Then _
drCount = drCount - Application.CountBlank(.Cells)
End With
sData = .Value
End With
Dim dData As Variant: ReDim dData(1 To drCount, 1 To cCount) ' Dest. Array
Dim fvCol As Long: fvCol = FixedColumnsCount + 1 ' First Value Column
Dim dr As Long: dr = 1 ' Destination Row
Dim sr As Long ' Source Row
Dim fc As Long ' Fixed Column
Dim vc As Long ' Value Column
' Write headers.
For fc = 1 To cCount
dData(dr, fc) = sData(1, fc)
Next fc
' Write rest.
If IncludeBlanks Then ' all
For sr = 2 To srCount
For vc = fvCol To cCount
dr = dr + 1
dData(dr, vc) = sData(sr, vc)
For fc = 1 To FixedColumnsCount
dData(dr, fc) = sData(sr, fc)
Next fc
Next vc
Next sr
Else ' non-blank
For sr = 2 To srCount
For vc = fvCol To cCount
If Len(CStr(sData(sr, vc))) > 0 Then
dr = dr + 1
dData(dr, vc) = sData(sr, vc)
For fc = 1 To FixedColumnsCount
dData(dr, fc) = sData(sr, fc)
Next fc
End If
Next vc
Next sr
End If
GetTransformOneValuePerRow = dData
ProcExit:
Exit Function
ClearError:
Debug.Print "'" & ProcName & "' Run-time error '" _
& Err.Number & "':" & vbLf & " " & Err.Description
Resume ProcExit
End Function
I have the following bit in a macro in my workbook. It selects the last n=10 rows to set as the data source.
.lstDbase.RowSource = "Stencils!A" & iRow - 10 & ":R" & iRow
Am I able to reverse this selection without actually saving the reversed data?
Get Range Rows Reverse
Option Explicit
Sub PopulateRangeRowsReverse() ' ???
Const fRow As Long = 2 ' ???
Const rMaxOffset As Long = 10
'Const iRow As Long = 11 ' ???
'With ???
Dim lrCount As Long: lrCount = iRow - fRow + 1
If lrCount < 1 Then Exit Sub ' no data
If lrCount > rMaxOffset Then lrCount = rMaxOffset
Dim rg As Range
Set rg = ThisWorkbook.Worksheets("Stencils") _
.Rows(iRow - lrCount + 1).Columns("A:R").Resize(lrCount)
Dim Data As Variant: Data = GetRangeRowsReverse(rg)
With .lstDbase
.Clear
.ColumnCount = rg.Columns.Count
.List = Data
End With
'End With
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns the reversed rows of a range in a 2D one-based array.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function GetRangeRowsReverse( _
ByVal rg As Range) _
As Variant
Const ProcName As String = "GetRangeRowsReverse"
On Error GoTo ClearError
Dim sData As Variant
Dim rCount As Long
Dim cCount As Long
With rg
rCount = .Rows.Count
cCount = .Columns.Count
If rCount + cCount = 2 Then
ReDim sData(1 To 1, 1 To 1): sData(1, 1) = .Value
Else
sData = .Value
End If
End With
Dim dData As Variant: ReDim dData(1 To rCount, 1 To cCount)
Dim r As Long
Dim c As Long
For r = 1 To rCount
For c = 1 To cCount
dData(r, c) = sData(rCount, c)
Next c
rCount = rCount - 1
Next r
GetRangeRowsReverse = dData
ProcExit:
Exit Function
ClearError:
Debug.Print "'" & ProcName & "' Run-time error '" _
& Err.Number & "':" & vbLf & " " & Err.Description
Resume ProcExit
End Function
So I have a VBA macro that lets me use Cells like a Userform.
What it basically does is, that it takes the Values of the defined Range("E2:E11")
and transposes them to the next BlankRow.
So with that the User can easily generate a Matrix that ranges from C16:L100
The VBA Code looks like this:
Sub NeuesKFZ()
Dim sh As Worksheet, arr, lastERow As Long, matchCel As Range
Set sh = ActiveSheet
arr = sh.Range("E2:E11").Value
lastERow = sh.Range("C" & sh.Rows.Count).End(xlUp).Row + 1
If Range("E2") = "" Then
MsgBox "Wählen Sie ein KFZ aus!"
Range("E2").Select
Exit Sub
End If
If lastERow < 16 Then lastERow = 16
'check if the range has not been already copied:
Set matchCel = sh.Range("C16:C" & lastERow - 1).Find(WHAT:=sh.Range("E2").Value, LookIn:=xlValues, Lookat:=xlWhole, MatchCase:=False)
If Not matchCel Is Nothing Then
If MsgBox(sh.Range("E2").Value & " Existiert bereits " & vbCrLf & "Sollen die Daten aktualisiert werden?", vbYesNo) = vbYes Then
sh.Range("C" & matchCel.Row).Resize(1, UBound(arr)).Value = Application.Transpose(arr)
End If
sh.Range("E2:E11").ClearContents
Exit Sub
End If
sh.Range("C" & lastERow).Resize(1, UBound(arr)).Value = Application.Transpose(arr)
sh.Range("E2:E11").ClearContents
End Sub
My Problem is now that excel doesn't seem to know what kind of values are getting transposed to the new cells.
In my case I'm working with Dates and I want to know if a date is within the next three months.
But Excel doesn't recognize that it is working with date values.
Trying to format or delete all formatting doesn't help.
And when I'm trying to use this formula:
=if(and(C16>=$AA16$,C16<=$AB$17),TRUE,FALSE)
Some explenation:
C16 is the value that got transposed by the Macro.
AA16 and AB16 are the starting date and end date.
TRUE and FALSE are just to give me feedback if it works or not.
It just gives me FALSE all the time.
Is there a way to get the Date transposed so Excel still knows that its a Date?
Or Maybe force Excel to handle those values as dates.
Transpose Column
I think I read somewhere that besides the size limitation, Transpose 'doesn't like' dates. Anyway, make the following corrections to your code and copy the function to a standard module of your workbook.
Corrections
Replace arr = sh.Range("E2:E11").Value
with arr = GetRowData(sh.Range("E2:E11")).
Replace sh.Range("C" & matchCel.Row).Resize(1, UBound(arr)).Value = Application.Transpose(arr)
with sh.Range("C" & matchCel.Row).Resize(1, UBound(arr, 2)).Value = arr.
Replace sh.Range("C" & lastERow).Resize(1, UBound(arr)).Value = Application.Transpose(arr)
with sh.Range("C" & lastERow).Resize(1, UBound(arr, 2)).Value = arr
The Function
Function GetRowData( _
ByVal ColumnRange As Range) _
As Variant
If ColumnRange Is Nothing Then Exit Function
With ColumnRange.Columns(1)
Dim rCount As Long: rCount = .Rows.Count
Dim rData As Variant
If rCount = 1 Then
ReDim rData(1 To 1, 1 To 1): rData(1, 1) = .Value
Else
Dim cData As Variant: cData = .Value
ReDim rData(1 To 1, 1 To rCount)
Dim r As Long
For r = 1 To rCount
rData(1, r) = cData(r, 1)
Next r
End If
GetRowData = rData
End With
End Function
EDIT
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns a 2D one-based one-row array containing the values
' from a one-column range.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function GetRowFromColumn( _
ByVal ColumnRange As Range) _
As Variant
If ColumnRange Is Nothing Then Exit Function
With ColumnRange.Columns(1)
Dim rCount As Long: rCount = .Rows.Count
Dim rData As Variant
If rCount = 1 Then
ReDim rData(1 To 1, 1 To 1): rData(1, 1) = .Value
Else
Dim cData As Variant: cData = .Value
ReDim rData(1 To 1, 1 To rCount)
Dim r As Long
For r = 1 To rCount
rData(1, r) = cData(r, 1)
Next r
End If
GetRowFromColumn = rData
End With
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns a 2D one-based one-column array containing the values
' from a one-row range.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function GetColumnFromRow( _
ByVal RowRange As Range) _
As Variant
If RowRange Is Nothing Then Exit Function
With RowRange.Rows(1)
Dim cCount As Long: cCount = .Columns.Count
Dim cData As Variant
If cCount = 1 Then
ReDim cData(1 To 1, 1 To 1): cData(1, 1) = .Value
Else
Dim rData As Variant: rData = .Value
ReDim cData(1 To cCount, 1 To 1)
Dim c As Long
For c = 1 To cCount
cData(c, 1) = rData(1, c)
Next c
End If
GetColumnFromRow = cData
End With
End Function
I don't know if it's possible to do it,
I need to copy data from sheet 2 from column B with a variable range,
selecting 8 lines at a time from sheet 2,
pasting with transposition in sheet 1 starting from row 9 onwards? thank you
Sub copy()
Sheets(2).Range("B1:B8").Copy
With Sheets(1).Range("B9:I9")
.PasteSpecial Paste:=xlPasteValues, Transpose:=True
End With
Sheets(2).Range("B9:B16").Copy
With Sheets(1).Range("B10:I10")
.PasteSpecial Paste:=xlPasteValues, Transpose:=True
End With
Sheets(2).Range("B17:B24").Copy
With Sheets(1).Range("B11:I11")
.PasteSpecial Paste:=xlPasteValues, Transpose:=True
End With
Sheets(2).Range("B25:B32").Copy
With Sheets(1).Range("B12:I12")
.PasteSpecial Paste:=xlPasteValues, Transpose:=True
End With
Application.CutCopyMode = True
End Sub ```
The code assumes that the range we want to copy and paste is always the same and always 8 rows.
I assume the original data looks like this:
Then we can copy and transpose the range to this:
by using this code:
Sub Copy_paste_transpose()
Dim lrow_copy As Long
Dim i As Long, j As Long
Dim rows_to_copy As Long
lrow_copy = Sheets(2).Cells(Rows.Count, "B").End(xlUp).Row 'Find last row in Sheet2
i = 9 'Start pasting at row 9
rows_to_copy = 7 'always "remove" one row.
For j = 1 To lrow_copy Step 8 'Loop through range and "jump" 8 rows at each looping.
Sheets(2).Range(Sheets(2).Cells(j, "B"), Sheets(2).Cells(j + rows_to_copy, "B")).Copy 'Copy range
Sheets(1).Range(Sheets(1).Cells(i, 2), Sheets(1).Cells(i, 2 + rows_to_copy)).PasteSpecial Paste:=xlPasteValues, Transpose:=True 'Paste range and transpose the copied range
i = i + 1 'add one row after each paste
Next j
Application.CutCopyMode = False 'Deselect last copy selection
End Sub
Try this code:
Sub copy()
Const PERIOD = 8, PASTE_FROM_ROW = 9
Dim last_row As Long, i As Long
last_row = Sheets(2).Cells(Rows.Count, "B").End(xlUp).Row
For i = 0 To last_row \ PERIOD - 1
Sheets(1).Cells(PASTE_FROM_ROW + i, "B").Resize(, PERIOD) = _
WorksheetFunction.Transpose(Sheets(2).Cells(i * PERIOD + 1, "B").Resize(PERIOD))
Next
End Sub
Transpose a Column
Option Explicit
Sub TransposeColumn()
Const ProcName As String = "TransposeColumn"
On Error GoTo ClearError
Const sID As Variant = 2 ' or "Sheet2"
Const sFirst As String = "B1"
Const dID As Variant = 1 ' or "Sheet1"
Const dFirst As String = "B9"
Const dcCount As Long = 8
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Create a reference to the Source First Cell Range.
Dim sws As Worksheet: Set sws = wb.Worksheets(sID)
Dim sfCell As Range: Set sfCell = sws.Range(sFirst)
' Using the 'GetTransposedColumn' function, write the transposed data
' to the Destination Array.
Dim dData As Variant: dData = GetTransposedColumn(sfCell, dcCount)
If IsEmpty(dData) Then Exit Sub
' Create a reference to the Destination First Cell Range.
Dim dws As Worksheet: Set dws = wb.Worksheets(dID)
Dim dfCell As Range: Set dfCell = dws.Range(dFirst)
' Check if the values from the Destination Array fit
' into the Destination Worksheet.
Dim drCount As Long: drCount = UBound(dData, 1)
If drCount > dws.Rows.Count - dfCell.Row + 1 Then Exit Sub
If dcCount > dws.Columns.Count - dfCell.Column + 1 Then Exit Sub
' Create a reference to the Destination Range.
Dim drg As Range: Set drg = dfCell.Resize(drCount, dcCount)
' Write the values from the Destination Array to the Destination Range.
drg.Value = dData
' Clear the contents below the Destination Range.
With drg
Dim crCount As Long: crCount = .Worksheet.Rows.Count - .Row + 1
If crCount > drCount Then
.Resize(crCount - drCount).Offset(drCount).ClearContents
End If
End With
MsgBox "Data transposed.", vbInformation, ProcName
ProcExit:
Exit Sub
ClearError:
Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
Resume ProcExit
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns the transposed values of a one-column range
' in a 2D one-based array.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function GetTransposedColumn( _
ByVal FirstCell As Range, _
Optional ByVal ColumnsCount As Long = 1) _
As Variant
Const ProcName As String = "GetTransposedColumn"
On Error GoTo ClearError
If FirstCell Is Nothing Then Exit Function
If ColumnsCount < 1 Then Exit Function
Dim srg As Range
Dim srCount As Long
With FirstCell.Cells(1)
Dim lCell As Range
Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If lCell Is Nothing Then Exit Function
srCount = lCell.Row - .Row + 1
Set srg = .Resize(srCount)
End With
Dim sData As Variant
If srCount = 1 Then
ReDim sData(1 To 1, 1 To 1): sData(1, 1) = srg.Value
Else
sData = srg.Value
End If
Dim dcrCount As Long: dcrCount = Int(srCount / ColumnsCount)
Dim dcRem As Long: dcRem = srCount Mod ColumnsCount
Dim drCount As Long
If dcRem = 0 Then
drCount = dcrCount
Else
drCount = dcrCount + 1
End If
Dim dData As Variant: ReDim dData(1 To drCount, 1 To ColumnsCount)
Dim r As Long
Dim c As Long
Dim n As Long
If dcrCount > 0 Then
For r = 1 To dcrCount
For c = 1 To ColumnsCount
n = n + 1
dData(r, c) = sData(n, 1)
Next c
Next r
Else
r = 1
End If
If dcRem > 0 Then
For c = 1 To dcRem
n = n + 1
dData(r, c) = sData(n, 1)
Next c
End If
GetTransposedColumn = dData
ProcExit:
Exit Function
ClearError:
Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
Resume ProcExit
End Function
We have a spreadsheet of hundreds of Employees and their respective roles that looks like this:
We need to reformat this spreadsheet so that each role is its own separate line item:
We found a VBA Macro that allows us to insert a row if "/" is found in our Roles column, but it only inserts one row instead of based on the number of roles that person has. The rows inserted are also blank.
Sub Insertrowbelow()
'updateby Extendoffice
Dim i As Long
Dim xLast As Long
Dim xRng As Range
Dim xTxt As String
On Error Resume Next
xTxt = Application.ActiveWindow.RangeSelection.Address
Set xRng = Application.InputBox("please select the column with specific text:", "Kutools for Excel", xTxt, , , , , 8)
If xRng Is Nothing Then Exit Sub
If (xRng.Columns.Count > 1) Then
MsgBox "the selected range must be one column", , "Kutools for Excel"
Exit Sub
End If
xLast = xRng.Rows.Count
For i = xLast To 1 Step -1
If InStr(1, xRng.Cells(i, 1).Value, "/") > 0 Then
Rows(xRng.Cells(i + 1, 1).Row).Insert shift:=xlDown
End If
Next
End Sub
Is there a way to add on to this code snippet so that we can get our spreadsheet formatted correctly?
You can use Split to split the roles into separate roles. The rest of the code is boilerplate.
SourceRow = 1
DestinationRow = 1
For SourceRow = 1 To LastSourceRow
Employee = SourceWorksheet.Cells(SourceRow, 1).Value
Roles = Split(SourceWorksheet.Cells(SourceRow, 2).Value, "/")
For i = LBound(Roles) To UBound(Roles)
DestinationWorksheet.Cells(DestinationRow, 1).Value = Employee
DestinationWorksheet.Cells(DestinationRow, 2).Value = Roles(i)
DestinationRow = DestinationRow + 1
Next i
Next SourceRow
Split Column
Adjust the values in the constants section.
Option Explicit
Sub unPivot()
Const wsName As String = "Sheet1"
Const HeaderRow As Long = 1
Const Header As String = "Employee"
Const Delimiter As String = " / "
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sCell As Range
With wb.Worksheets(wsName).Rows(HeaderRow)
Set sCell = .Find(Header, .Cells(.Cells.Count), xlFormulas, xlWhole)
End With
If sCell Is Nothing Then
MsgBox "The header '" & Header & "' was not found.", _
vbCritical, "Missing Header"
Exit Sub
End If
Dim dcell As Range: Set dcell = sCell.Offset(1)
Dim srg As Range
With dcell
Dim lCell As Range
Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If lCell Is Nothing Then
MsgBox "No data found.", vbCritical, "No Data"
Exit Sub
End If
Set srg = .Resize(lCell.Row - .Row + 1, 2)
End With
Dim Data As Variant: Data = srg.Value
Dim srCount As Long: srCount = UBound(Data, 1)
ReDim Preserve Data(1 To srCount, 1 To 3)
Dim drCount As Long
Dim r As Long
For r = 1 To srCount
Data(r, 2) = Split(Data(r, 2), Delimiter)
Data(r, 3) = UBound(Data(r, 2))
drCount = drCount + Data(r, 3) + 1
Next r
Dim Result As Variant: ReDim Result(1 To drCount, 1 To 2)
Dim n As Long
Dim k As Long
For r = 1 To srCount
For n = 0 To Data(r, 3)
k = k + 1
Result(k, 1) = Data(r, 1)
Result(k, 2) = Data(r, 2)(n)
Next n
Next r
With dcell.Resize(, 2)
.Resize(k).Value = Result
'.Resize(.Worksheet.Rows.Count - .Row - k + 1).Offset(k).ClearContents
End With
End Sub