How to shift a range down one row based upon adjacent cell value using VBA? - excel

I'm attempting to move the adjacent cell range D:E down one row based upon the value in column B.
For example, if a row in column B contains the word "Deposit", then the macro should shift the adjacent cell range D:E down one row.
My issue is that the macro is inserting two rows instead of just one.
I've included some screenshots of my data.
Here is my code:
Sub InsertCellsDown()
Application.ScreenUpdating = False
Dim LastRow As Long
Dim cba As Range
LastRow = Cells.Find("Deposit", SearchOrder:=xlRows, SearchDirection:=xlPrevious).Row
For Each cba In Range("B2:B" & LastRow)
If cba <> cba.Offset(1, 0) Then
Range("D" & cba.Row & ":E" & cba.Row).Insert Shift:=xlDown
End If
Next cba
Application.ScreenUpdating = True
End Sub
Starting data:
Goal:
Problem:

Related

vba, sum based on column header

I need your help with VBA!
I want to write a code that will sum the "sales" column in different 7 sheets. The problem is that the column has a different location in each sheet and a dinamic rows' count. The sum should be in the last row + 1.
I am not very good at macros, but I guess I should start with checking i to 7 sheets. Then I should sum a range based on the header ("Sales"). I am lost about how to write all of this..
Try the next code, please:
Sub SumSales()
Dim sh As Worksheet, rngS As Range, lastRow As Long
For Each sh In ActiveWorkbook.Sheets 'iterate through all sheets
'find the cell having "Sales" text/value
Set rngS = sh.Range(sh.Cells(1, 1), sh.Cells(1, _
sh.Cells(1, Columns.count).End(xlToLeft).Column)).Find("Sales")
'if the cell has been found (the cell range is NOT Nothing...)
If Not rngS Is Nothing Then
'Determine the last row of the found cell column:
lastRow = sh.Cells(Rows.count, rngS.Column).End(xlUp).row
'Write the Sum formula in the last empty cell:
rngS.Offset(lastRow).formula = "=Sum(" & rngS.Offset(1).address & _
":" & sh.Cells(lastRow, rngS.Column).address & ")"
sh.Range("A" & lastRow + 1).Value = "Sum of sales is:"
Else
'if any cell has been found, it returns in Immediate Window (Being in VBE, Ctrl + G) the sheet names not having "Sales" header:
Debug.Print "No ""Sales"" column in sheet """ & sh.name & """."
End If
Next
End Sub

Excel VBA Select every other cell and paste it into another sheet?

I need to copy data from the 8th row into another sheet(sheet 2). I only need to copy every other cell, it should copy cell C8(first cell where the value is), E8, G8, I8 and so on from all the upto cell IK8.
Is there any way to do this? I have tried the step function in the for loop but its not working and only selecting one cell.It only pastes one value for cells H2:H130.
Sub Workplace()
Dim rng As Range
Dim LastRow As Long
Dim I As Long
LastRow = Worksheets("Questions").Range("C" & Rows.Count).End(xlUp).Row
For I = 8 To LastRow Step 3
Set rng = Worksheets("Questions").Range("C" & I)
rng.Copy
Next I
Worksheets("Sheet1").Range("H2:H130").PasteSpecial Transpose:=True
End Sub
You need to increment the column, not the row.
And move the paste inside the loop, though you need to increment the destination cell.
For i = 3 to 245 Step 2 ' column C to column IK
Set rng = Worksheets("Questions").Cells(8, i)
With Worksheets("Sheet1")
Dim dest as Range
Set dest = .Range("H" & .Rows.Count).End(xlUp).Offset(1)
End With
rng.copy Destination:=dest
Next
Or better, just use Union to build up a range to copy and then copy in one step:
For i = 3 to 245 Step 2 ' column C to column IK
If rng Is Nothing Then
Set rng = Worksheets("Questions").Cells(8, i)
Else
Set rng = Union(rng, Worksheets("Questions").Cells(8, i))
End If
Next
rng.Copy
Worksheets("Sheet1").Range("H2").PasteSpecial Transpose:=True
Application.CutCopyMode = False
EDIT:
"Is there a way to paste it in the first empty cell for Row H in sheet 1 instead of giving it a range?"
Yes, like the following:
Worksheets("Sheet1").Range("H" & Rows.Count).End(xlUp).Offset(1).PasteSpecial Transpose:=True

Excel VBA: Maintaining number formatting with digits and letters

I am writing a code where basically I need to follow the sequence in logic. I am going through all the lines
Set rep = Sheets("Details")
For i = 2 To n
If Sheets("Work").Range("A:A").Find(Worksheets("Work_report").Range("E" & i).Value, lookat:=xlWhole) Is Nothing Then
Else:
o = rep.Range("A" & Rows.Count).End(xlUp).Row + 1
rep.Range("A" & o).Value = "FT_EXCEL"
rep.Range("B" & o).Value = Sheets("Start").Range("C5") & "AB" & o - 1
End If
Next i
So this the last line (there are more than 50 in original code) returns me a value of the cell C5 (20170331) & AB & the o minus 1 (because I have started at 2 (1st line header)). So this is giving 20170331AB1, but it should give 20170331AB01 (zero before the 0). This sequence works like a charm after 10, but before ten when I need to add a zero - I got stuck.
Any ideas? Thank you.
Try this:
rep.Range("B" & o).Value = Sheets("Start").Range("C5") & "AB" & Format(o - 1, "00")
you can do it in one shot with exploiting AutoFilter() method's operator xlFilterValues value
Sub main()
Dim rep As Worksheet
Dim criteriaArr As Variant
With Worksheets("Work_report") '<--| reference "Work_report" sheet
criteriaArr = Application.Transpose(.Range("E2", .Cells(.Rows.Count, "E").End(xlUp)).Value) '<--| store its column E cells content from row 2 down to last not empty one
End With
Set rep = Sheets("Details")
With Worksheets("Work") '<--| reference "Work" sheet
With .Range("A1", .Cells(.Rows.Count, "A").End(xlUp)) '<--| reference its column A cells from row 1 (header) down to last not empty one
.AutoFilter Field:=1, Criteria1:=criteriaArr, Operator:=xlFilterValues '<--| filter it with "Work_report" sheet column E content
If Application.WorksheetFunction.Subtotal(103, .Cells) > 1 Then '<--| if any filtered cells other then headers
With .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible) '<--| reference filtered cells skipping header
rep.Range("A" & Rows.Count).End(xlUp).Offset(1).Resize(.Rows.Count).Value = "FT_EXCEL" '<--| write 'rep' sheet column A corresponding cells content
With rep.Range("B" & Rows.Count).End(xlUp).Offset(1).Resize(.Rows.Count)
.Formula = "=CONCATENATE(Start!$C$5,""AB"",TEXT(ROW(),""00""))" '<--| '<--| write 'rep' sheet column B corresponding cells content
.Value = .Value
End With
End With
End If
End With
.AutoFilterMode = False
End With
End Sub

Distributing evenly the Cell value of column A to B C D

I'm very new to Excel VBA so please be good to me :)
My problem is I want to copy values of Column A until the last cell with value and paste it to B C D respectively
Example
Column A has 3 Rows with values Tim,john,Mer respectively
I want to paste it to Columns B2 C2 D2 respectively too
Problem: Column A has a dynamic number of row so I want it to copy until the last notempty cell. but when column A is more than 3 (number of columns to paste) it will loop and paste it to B3 then C3 then D3 and so on until all non empty cell is distributed evenly to the 3 columns(B,C, and D)
Hope this problem is clear
Sub CopyData()
Dim x As Long, i As Long
Application.ScreenUpdating = False
For i = 1 To 100 Step 3
x = x + 1
Range("A" & i & ":A" & i + 2).Copy
Range("B" & x).PasteSpecial xlPasteValues, , , True
Next i
Application.ScreenUpdating = True
End Sub
Maybe make use of the TRANSPOSE function?
Sub TransposeToColumns()
Dim lLastRow As Long
With ThisWorkbook.Worksheets("Sheet1")
'Get the last row (same as going to end of sheet and pressing Ctrl+Up).
lLastRow = .Range("A" & Rows.Count).End(xlUp).Row
If lLastRow > 3 Then
'Cells(1,2) is row 1, column 2.
With .Range(.Cells(1, 2), .Cells(1, lLastRow + 1))
'R1C1 style of referencing - absolute reference to A1 is R1C1 (row 1 column 1).
.FormulaArray = "=TRANSPOSE(R1C1:R" & lLastRow & "C1)"
'Replace formula with values.
.Value = .Value
End With
End If
End With
End Sub
Just realised - this will error out if you try and do it with more than 16383 rows (i.e. the number of columns -1). But it will do all columns in 0.040469668631069 seconds. :)

Match name and copy from sheet 1 to sheet 2 next to matched name

I have an Excel sheet with names in column A and an amount in column B for sheet 1.
I have a another sheet that is sheet2 with names in A just like in sheet 1 and column B is blank.
How can I check sheet 1 A name to check with sheet2 A name, if they match then take amount next to that name on sheet1 and copy the amount into the cell next to the matching name on sheet2 next to the name? The names on sheet1 change daily.
I have tried this and get nothing.
Sub Macro1()
'
' Macro1 Macro
'
Dim RowIndex As Integer
Sheets("Sheet1").Select
RowIndex = Cells.Row
While DoOne(RowIndex)
RowIndex = RowIndex + 3
Wend
End Sub
Function DoOne(RowIndex As Integer) As Boolean
Dim Key
Dim Target
Dim Success
Success = False
If Not IsEmpty(Cells(RowIndex, 1).Value) Then
Key = Cells(RowIndex, 1).Value
Sheets("sheet2").Select
Set Target = Columns(2).Find(Key, LookIn:=xlValues)
If Not Target Is Nothing Then
Rows(Target.Row).Select
Selection.Copy
Sheets("Sheet1").Select
Rows(RowIndex + 1).Select
Selection.Insert Shift:=xlDown
Rows(RowIndex + 2).Select
Application.CutCopyMode = False
Success = True
End If
End If
DoOne = Success
End Function
Sheet 1:
A B
A One Preservation $16.00
A&D Recovery, Inc. $8,108.46
A&S Field Services, Inc. $4,941.56
A&T Jax Inc $1,842.48
Sheet 2:
A B - blank cell
A One Preservation - Calvin & Renee
A&D Recovery, Inc. - Drew & Adam
A&S Field Services, Inc. - Aaron
A&T Jax Inc - Tyson
This code uses an Index/Match solution to copy the matched B values from sheet1 from sheet2. The code will work with variable sheet names
blank cells are ignored
Non-matches on the second sheet are flagged as "no match".
The code removes the formulae from column B on the second sheet by updating with values only
Update: if you second sheet names are the same as sheet1, but have a " -some text" to the right, then use this updated part of the code
With rng1.Offset(0, 1)
.FormulaR1C1 = "=IF(RC[-1]<>"""",IF(NOT(ISERROR(MATCH(LEFT(RC[-1],FIND("" -"",RC[-1])-1),'" & ws1.Name & "'!C[-1],0))),INDEX('" & ws1.Name & "'!C,MATCH(LEFT(RC[-1],FIND("" -"",RC[-1])-1),'" & ws1.Name & "'!C[-1],0)),""no match""),"""")"
.Value = .Value
End With
original
Sub QuickUpdate()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim rng1 As Range
Set ws1 = Sheets(1)
Set ws2 = Sheets(2)
Set rng1 = ws2.Range(ws2.[a1], ws2.Cells(Rows.Count, "A").End(xlUp))
With rng1.Offset(0, 1)
.FormulaR1C1 = "=IF(RC[-1]<>"""",IF(NOT(ISNA(MATCH(RC[-1],'" & ws1.Name & "'!C[-1],0))),INDEX('" & ws1.Name & "'!C,MATCH(RC[-1],'" & ws1.Name & "'!C[-1],0)),""no match""),"""")"
.Value = .Value
End With
End Sub
Why not use the VLOOKUP function?
Sheet1 has your names in column A, and values in column B.
Sheet2 has your lookup names in column A, and in column B, you put:
=VLOOKUP(A1,Sheet1!$A$1:$B$n,2,FALSE)
Where 'n' is the number of rows in your Sheet1 table.
The only issue with this is it will put an #N/A if it can't find the name in Sheet1. There's likely a way to put in an alternate entry using a conditional.

Resources