how to insert n number of blank rows between existing rows alternatively - excel

Can anyone suggest me procedure or a formula to insert n blank rows in between a existing data?
for example:
I have data from A1 to A50, now I have insert n number of blank rows between each row.
input:
required output:

Consider this screenshot:
In cell C3 enter the number of rows you want to insert between cells from column A. This cell has the range name "RowsToInsert". Alternatively, you can use $C$3 in the formulas below
The formula in cell E2 is
=INDEX(A:A,CEILING(ROW(A1)/(RowsToInsert+1),1))
or type the first value manually. The formula in E3 is as follows, copied down:
=IF(CEILING(ROW(A2)/(RowsToInsert+1),1)=CEILING(ROW(A1)/(RowsToInsert+1),1),"",INDEX(A:A,CEILING(ROW(A2)/(RowsToInsert+1),1)))
When you change the value in cell C3, blank rows are added accordingly. Copy the formula down as far as required. Then copy column E and use Paste Special > Values to paste only the results.

I would use VBA to achieve what you require and this is the code I would propose
Dim n As Long 'number of blanks
Dim dataLen As Long ' number of used rows
Dim currentRow As Long
Dim i, j As Long
dataLen = Sheet1.Range("A" & Rows.Count).End(xlUp).Row
n = 3 'number of blanks
currentRow = 2 'start insert at row 2
For i = 1 To dataLen
For j = 1 To n
Sheet1.Rows(currentRow).Insert
Next j
currentRow = currentRow + n + 1 'offset the next row to start insertion
Next i

With formula It will be little complicated I guess.
Is this what you want?
=IF(ROW(B1)-(9*TRUNC(ROW(B1)/9,0))=1,"one",IF(ROW(B1)-(9*TRUNC(ROW(B1)/9,0))=4,"two",IF(ROW(B1)-(9*TRUNC(ROW(B1)/9,0))=7,"three","")))

Related

Excel 3D Reference: Delineate string results from range of Worksheets

Hopefully I can explain this right.
Looking to combine cells of text strings from multiple worksheets into one master worksheet.
Basically 3-D References. But formatted into rows and columns. And referencing a range of worksheets so new worksheets can be added or removed in between the bookends.
Desired output:
Column 1
Column 2
Column 3
WS01 Cell B1
WS02 Cell B1
WS03 Cell B1
WS01 Cell B2
WS02 Cell B2
WS03 Cell B2
WS01 Cell B3
WS02 Cell B3
WS03 Cell B3
Input: Strings from B1:B3 (should become matching rows separated into columns for each linked worksheet)
Each worksheet ('Worksheet 01:Worksheet 03') follows same format:
Column B
WS## Cell B1
WS## Cell B2
WS## Cell B3
Attempts:
=CONCAT('Worksheet 01:Worksheet 03'!B1:B3)
Result:
WS01 Cell B1WS01 Cell B2WS01 Cell B3WS02 Cell B1WS02 Cell B2WS02 Cell B3WS03 Cell B1WS03 Cell B2WS03 Cell B3
Please let me know what you think. Thank you for your time.
You can use:
=HSTACK(Sheet1:Sheet3!B1:B3)
Even though the answer below works fine, please look at this answer by JvdV that is far easier to use:
https://stackoverflow.com/a/74077560/12634230
=LET(
c,CONCAT(Sheet1:Sheet4!B1:B3),
q,SEQUENCE(LEN(c)/36,3,,12),
TRANSPOSE(MID(c,q,12)))
c uses your CONCAT formula to retrieve a concatenation of all values.
q calculates a sequence by the length of c divided by the length of text for the 3 values per Sheet (3* length 12 = 36) by 3 with steps of the length of each value (12).
This sequence is used in the MID function and needs the result to be transposed to meet your requirements:
If a Sheet will be added, changing the Sheet names in c will change the result to show the values from that Sheet as well. No further adjustments of the formula are required.
And if the number of outputs per sheet, or string length may change in future you could define these as variables too:
=LET(c,CONCAT('Worksheet 01:Worksheet 03'!B1:B3),
stringlength,12,
stringcount,3,
q,SEQUENCE(LEN(c)/(stringlength*stringcount),stringcount,,stringlength),
TRANSPOSE(MID(c,q,stringlength)))
#P.b just posted a formula approach, but as an alternative here's a VBA user-defined formula which returns an array. The only tricky part is getting the 3D reference in the UDF, since there's no structure or type equivalent to that in VBA: if you try to get it directly from the argument you just get an error.
Building from: https://www.excelforum.com/excel-programming-vba-macros/476283-user-defined-function-receiving-a-range-as-parameter.html
Function MyUDF(v)
Dim c As Range, f, arr, arrWs, rngAddr
Dim arrout, indx1, indx2, i As Long, r As Long, data
On Error Resume Next
Set c = Application.Caller
On Error GoTo 0
If c Is Nothing Then
f = "=myudf(Sheet1:Sheet3!A1:A3)" 'for testing purposes (adjust as needed)...
Else
f = c.Formula 'read the formula from the calling cells
End If
f = Mid(f, 8, Len(f) - 8) 'parse out the parens and formula name
arr = Split(f, "!") 'get an array from splitting on !
arrWs = Split(arr(0), ":") 'get the start/end worksheet names
indx1 = ThisWorkbook.Worksheets(arrWs(0)).Index
indx2 = ThisWorkbook.Worksheets(arrWs(1)).Index
rngAddr = arr(1) '...and the range address
'size the output array
ReDim arrout(1 To Range(rngAddr).Rows.Count, 1 To 1 + (indx2 - indx1))
For i = indx1 To indx2 'loop over the worksheets
data = ThisWorkbook.Sheets(i).Range(rngAddr).Value
For r = 1 To UBound(data)
arrout(r, i) = data(r, 1)
Next r
Next i
MyUDF = arrout 'return the array
End Function

Highlight cells with different values than present in the column

I need to go through a table (X by Y) where every column (X) should have the same value (string) and would like the cell to get highlighted if is not the same value. I'm stuck in building the comparison method, because I would like it to be dynamic. I would like to first determine what is the value that is present the most in the column and determine that is what everything else needs to be compared against and highlight the cell that is not equal to this value.
Example (6x5 table) -
A 3 4 C M R
A 3 4 O M R
8 3 T O M F
8 3 4 O M G
A 3 T O Y K
In the first column, A is the most prevalent value therefore the (8s) are highlighted, second column nothing is highlighted, third both (T) are highlighted, fourth column (C), fifth column (Y) and sixth column (F),(G) and (K) are highlighted.
Thank you in advance.
I can suggest a workaround. Not sure if this is the best way though.
Step 1. Create a count if table which basically gives you the count of a value in the column. Ex: for cell F4 use formula =COUNTIF($B$4:$B$8,B4)
Step 2. Create a row with max values of each column. Ex: Cell F11 =MAX(F4:F8)
Step 3. For each cell, give a conditional formatting condition that if the value in the count table does not match the max value, color it. Ex: for cell B4, go to conditional formatting -> new rule -> use a formula and write this formula =F4<>F$11. Then copy paste the format to all other cells.
Note: this will not work when multiple values in a column have the same max count.
Here is a VBA solution, I've commented the code so you can understand
Sub HighlightNonFrequentInColumn()
Dim rng As Range
Dim col As Range
Dim cell As Range
Dim myVal As String
Dim colRng As String
Set rng = Selection '<<change range as required
For Each col In rng.Columns
'determine the most frequent value
colRng = col.Address
On Error Resume Next
myVal = Application.Evaluate("INDEX(" & colRng & ",MODE(IF(" & colRng & "<>"""",MATCH(" & colRng & "," & colRng & ",0))))")
If Application.countblanks(col) > Application.CountIf(col, myVal) Then myVal = "" '<<if blanks are most frequent
'highlight all cells not equals to most frequent value
For Each cell In col.Cells
If Not cell = myVal Then cell.Interior.Color = vbYellow '<<change colour as desired
Next
Next
End Sub

Excel convert comma seperated downwards WITH other columns

I'm trying to do this:
The long way to do this:
Highlight 1 cell in B. Text to columns. Copy all the cells in the output. Paste using transpose. Then drag col A to fill in the blanks downwards.
There must be an easier way :(
I claimed in the comments that you could also do this by formula with a couple of helper columns and wanted to see (a) if that was true and (b) how difficult it would be to do. The answers were (a) yes, just about and (b) very (although there are people out there who are more skilled in complex formulae than I am).
Here is the result:-
So the helper columns are just like the i's and j's in the VBA where
Column C (i) is source row
Column D (j) is string number within source row
But to achieve this you need some long formulae.
C7 and C8 are just hard-coded to 1.
In D8:-
=IF(C7="","",IF(D7<LEN(INDEX(B$2:B$4,C7))-LEN(SUBSTITUTE(INDEX(B$2:B$4,C7),",",""))+1,D7+1,IF(C7=ROWS($B$2:$B$4),"",1)))
In C8:-
=IF(D8="","",IF(D8>D7,C7,C7+1))
In B7:-
=IF(C7="","",MID(","&INDEX(B$2:B$4,C7)&",",FIND("<",SUBSTITUTE(","&INDEX(B$2:B$4,C7)&",",",","<",D7))+1,FIND(">",SUBSTITUTE(","&INDEX(B$2:B$4,C7)&",",",",">",D7+1))-FIND("<",SUBSTITUTE(","&INDEX(B$2:B$4,C7)&",",",","<",D7))-1))
In A7:-
=IF(C7="","",INDEX($A$2:$A$4,C7))
It is semi-dynamic because any changes to the source cells will be reflected in the destination cells. It is tied to a fixed source range $B$2:$B$4, but could be changed to work with a variable source range fairly easily. I haven't assumed that the numbers all have 7 digits, but if you did it would simplify the formula in B7.
I wondered how the VBA would compare with doing it with formulae.
Here is a sample VBA and it is pretty short even though there might be smarter ways of doing it:-
Option Explicit
Public Sub SplitRows()
Dim a() As String
Dim r1, r2 As Range
Dim i, j, k As Integer
Set r1 = Range("A2:B4")
Set r2 = Range("A7:B1000")
j = 1
For i = 1 To r1.Rows.Count
a = Split(r1.Cells(i, 2), ",")
For k = LBound(a) To UBound(a)
r2.Cells(j, 1) = r1.Cells(i, 1)
r2.Cells(j, 2) = a(k)
j = j + 1
Next k
Next i
End Sub

Copy and paste repeatedly a set of values one after the other for multiple times using Macro

I have a set of strings lets say A, B, C, D, E, F, G, etc. in my 1st row in different cells. Now I want to copy and paste A 5 times beginning with row 1 which is followed by B 5 times and then C and so on. I know there is for loop involved in that but am unable to make my way through it. I will be grateful if someone could help me on this.
You can use the following:
Dim LastCol As Integer
Dim cel As Range
Dim count As Integer
Dim CurrentCel As Range
'Find the last used column in the first row
LastCol = Range("A1").End(xlToRight).Column
Set CurrentCel = Range("A1")
'Loop through each cell in the top row with the values in
For Each cel in Range(Cells(1,1),Cells(1,LastCol)).cells
'Add the value in that cell to the list 5 times
For count = 1 To 5
CurrentCel.value = cel.value
Set CurrentCel = CurrentCel.Offset(1,0)
Next count
Next
Note that this will overwrite the value currently in A1, and it will only work if you have an unbroken list in the first row.
Without VBA
With data in A1 thru G1, in A2 enter:
=INDEX($A$1:$G$1,1,ROUNDUP(ROWS($1:1)/5,0))
and copy down:

Macro to insert blank cells below if value >1 and copy/paste values from cell above

This site already has something similar: Copy and insert rows based off of values in a column
but the code doesn't take me quite where I need to go, and I haven't been able to tweak it to make it work for me.
My user has a worksheet with 4 columns, A-D. Column A contains specific contract numbers, column B is blank, column C has part numbers, and column D has the entire range of contract numbers. My user wants to count the number of times the entire range contract numbers has duplicates so I entered the formula =countif($D$2:$D$100000,A2) in cell E2 and copied down, giving me the number of times the specific contract in column A appears in column D. The numbers range from 1 to 11 in this workbook but the number may be higher in other workbooks this method will be used in.
The next thing I need to do is to enter blank cells below all values in column E that are greater than 1, very much like the example in the previously asked question. I then also need to copy in the same row and insert copied cells exactly to match in the same row in column A. Example: Cell E21 has the number 5 so I need to shift cells in column E only so that there are 4 blanks cells directly below it. In column A, I need to copy cell A21 and insert copied cells in four rows directly below.
Just trying to get the blank cells to insert has been a trial, using the code as given in the previous question.
Dim sh As Worksheet
Dim lo As ListObject
Dim rColumn As Range
Dim i As Long
Dim rws As Long
Set sh = ActiveSheet
Set lo = sh.ListObjects("Count")
Set rColumn = lo.ListColumns("Count").DataBodyRange
vTable = rColumn.Value
For i = rColumn.Rows.Count To 1 Step -1
If rColumn.Cells(i, 1) > 1 Then
rws = rColumn.Cells(i, 1) - 1
With rColumn.Rows(i)
.Offset(1, 0).Resize(rws, 1).Cells.Insert
.EntireRow.Copy .Offset(1, 0).Resize(rws, 1).Cells
.Offset(1, 0).Resize(rws, 1).EntireRow.Font.Strikethrough = True
End With
End If
Next
I would be very grateful for any help as I have been fighting with this monster for a week.
While this is indeed possible to do, it might be a good idea to look into moving the list of all contract numbers from column D to a different sheet. Even though it is quite simple to loop through a range and insert rows based on cell values - it'll also create holes in columns D and E.
Here's code for simply adding the rows and copying the values as you specified.
Sub Main()
'---Variables---
Dim source As Worksheet
Dim startRow As Integer
Dim num As Integer
Dim val As String
Dim i As Long
'---Customize---
Set source = ThisWorkbook.Sheets(1) 'The sheet with the data
startRow = 2 'The first row containing data
'---Logic---
i = startRow 'i acts as a row counter
Do While i <= source.Range("E" & source.Rows.Count).End(xlUp).Row
'looping until we hit the last row with a value in column E
num = source.Range("E" & i).Value 'Get number of appearances
val = source.Range("A" & i).Value 'Get the value
If num > 1 Then 'Number of appearances > 1
Do While num > 1 'Create rows
source.Range("A" & i + 1).EntireRow.Insert 'Insert row
source.Range("A" & i + 1) = val 'Set value
num = num - 1
i = i + 1 'Next row
Loop
End If
i = i + 1 'Next row
Loop
End Sub
Of course you could also remove the holes from column D after inserting the new rows and modify the formula in column E so that it remains copyable and doesn't calculate for the copied rows.
Generally it makes things easier if a single row can be thought of as a single object, as creating or deleting a row only affects that one single object. Here we have one row represent both a specific contract and a contract in the all contracts list - this could end up causing trouble later on (or it could be totally fine!)

Resources