Push down values without shifting the row - vba

So have this button on a form and I cant make the data on 3 cells (Ex:C1,D1,E1) go down 1 Row without shifting the whole sheet.
How do i make the values go down after being inserted so that i can leave Row1 allways open for new values?
This is the code on the command button, can i embed the solution on it or do I have to do it somewhere else?
Private Sub CommandButtonAddDes_Click()
Dim emptyRow As Long
'Activate sheet
Sheet1.Activate
'Determine emptyRow
emptyRow = WorksheetFunction.CountA(Range("C:C")) + 1
'Transfer info
Cells(emptyRow, 3).Value = Des
Cells(emptyRow, 4).Value = ComboBox.Value
Cells(emptyRow, 5).Value = TextBox1.Value
End Sub

Looks like you want to make sure that the cells being updated are then moved down automatically. You can do that with a change event on the sheet code behind like this:
Sub Worksheet_Change(ByVal Target As Range)
'Checks if the column being changed is C - E
If Target.Column = 3 Or Target.Column = 4 Or Target.Column = 5 Then
'Checks if the row being changed is row 2
If Target.Row = 2 Then
'Inserts a new row and pushes what is in C2:E2 down one row
Range("C2:E2").Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
End If
End If
End Sub
This code will go in the sheets code behind. So, you will have to right-click on the sheet that you have this data on and then click on view code (or just double-click the sheet)
Putting the code there will tell Excel to watch that sheet for changes and then the code checks if it is happening to one of those 3 cells (C2:E2)

With data in C1, D1 and E1 just:
Range("C1:E1").Insert Shift:=xlDown
This pushes down the three cells rather than the entire row.
EDIT#1:
Put this event macro in the worksheet code area:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim c As Long
c = Target.Column
If c = 3 Or c = 4 Or c = 5 Then
If Application.WorksheetFunction.CountA(Range("C1:E1")) = 3 Then
Application.EnableEvents = False
Range("C1:E1").Insert shift:=xlDown
Application.EnableEvents = True
End If
End If
End Sub
Once you have entered all 3 values in C1 through E1, the values will get pushed down automatically.

Replace you code on your userform. Ensure your input box names are correct, i.e. ComboBox1, TextBox1, etc. I don't understand what "Des" is. If you need it in row 2 then just change the 1s to 2s.
Private Sub CommandButton1_Click()
With Sheets("Sheet1")
.Range("C1:E1").Insert Shift:=xlDown
.Range("C1").Value = Des.Value
.Range("D1").Value = ComboBox.Value
.Range("E1").Value = TextBox1.Value
End With
End Sub

Edited: changed lat column index from "D" to "E" and starting row index from "3" to "2"
Maybe you’re after this
Private Sub CommandButtonAddDes_Click()
With Sheet1
With .Range("C2:E" & .Cells(.Rows.Count, "C").End(xlUp).Row)
.Offset(1).Value = .Value
.Resize(1) = Array(Des, ComboBox.Value, TextBox1.Value)
End With
End With
End Sub
Should different rows need to be "inserted" you just change the row index.

Related

Excel VBA: How to create macro to change text color using if statement

This is a continuation for the following question: What is the cause for Conditional Formatting to get jumbled up?
In an attempt to prevent my conditional formatting from going haywire, I decided to convert it into code in VBA. I decided to start small and start with converting one conditional formatting into VBA.
Explanation:
In column O there are a series of numbers, obtained from a different sheet. User inputs number in column F. For example if number in F9 is less than O9, the font colour will become red. If not number remains normal. The formula should start at row 9 and can continue down onwards and should be automatic.
Meaning the moment a number is keyed in column F the font colour should change instantly.
The following is the code I created so far:
Sub change_color()
With Me.Range("f9", Range("f" & Rows.Count).End(xlUp)) 'so the formula will carry onwards from f9 onwards
If f9 < o9 Then
Range(f).Font.Color = vbRed
End If
End With
End Sub
But alas it didn't work. I also tried linking it to a button and nothing happens. And I also remember to remove my old conditional formatting as well. Is there something I'm missing?
You are after something like the code below.
This code is to be ran once, it will lopp through the entire column "F" in your worksheet, and change the font of all instances.
Regular Module Code
Option Explicit
Sub change_color()
Dim LastRow As Long, i As Long
With Worksheets("Sheet1") ' modify to your sheet's name
LastRow = .Cells(.Rows.Count, "F").End(xlUp).Row
For i = 1 To LastRow
If .Range("F" & i).Value < .Range("O" & i).Value Then
.Range("F" & i).Font.Color = vbRed
Else
.Range("F" & i).Font.Color = vbBlack
End If
Next i
End With
End Sub
To "catch" the modification in real-time, when someone changes a value in column "F", and then change the font according to the criteria you specified, you need add the following code to the Worksheet module, where you have your data, and add the piece of code below to Worksheet_Change event.
Code in Sheet1 module (modify to your sheet's)
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 6 Then ' if someone changes a value in column "F"
Application.EnableEvents = False
If Target.Value < Range("O" & Target.Row).Value Then
Target.Font.Color = vbRed
Else
Target.Font.Color = vbBlack
End If
End If
Application.EnableEvents = True
End Sub
Does this work for you?
Option explicit
Sub ChangeColor()
With thisworkbook.worksheets(YOURSHEETNAME) 'Replace with sheet name as per your workbook.'
Dim LastRow as long
Lastrow = .cells(.rows.count,"F").end(xlup).row
Dim RowIndex as long
For rowindex = 9 to LastRow
If .cells(rowindex,"F").value2 < .cells(rowindex,"O").value2 then
.cells(rowindex,"F").font.color = vbred
End if
Next rowindex
End With
End Sub

MS Excel worksheet change event - keeping record of old cell value against new value

I'm new to this forum but have been building up my coding experience in the last couple of months due to the VBA requirements of my current role. Today's problem has seen me trawling through many sites (and my Excel VBA for Dummies book), but I haven't quite nailed it.
I am trying to make an audit tracker file in Excel for our company Risk Register. The idea is that once the risk register is established, any changes will create an audit trail (on a separate tab) which shows both the old and the new record.
I have written the code using the Change Event handler. I want my macro to fire every time there is a change and do the following:
1. Make a reference of the old cell value (what the user has just overwritten)
2. Jump to the 'Audit trail' tab and paste two copies of the full risk record - each risk record is a row of data that occupies 17 columns
3. In the first copy of these 17 columns, work out which column was edited and replace this cell with the old cell value (captured in step 1)
4. Insert a time stamp
5. Have conditional formatting highlight the record that has changed [this function is not required in the code as I've set it up within the spreadsheet itself]
6. Jump back to cell where the user just made their edit (on the 'Risk Register' tab)
I have managed steps 1, 2 and 4-7 but I am having problems getting the code to input the "old cell value" into the right spot in the 'Audit Tracker' tab. I can get it there if I manually define the cell range for it to paste into, but I can't seem to make it dynamic so that it will automatically recognize what field the user is changing and ensure the same field is amended in the audit trail.
Would really appreciate any insights as to why the "PasteRange.Value = Worksheets("Risk Register").Range("oldValuePaste")" line isn't working
My code is as follows:
Dim oldValue As Variant
Dim LastRow As Long
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Application.ScreenUpdating = False
If Not Intersect(Target, Range("b13:r13")) Is Nothing Then
oldValue = Target.Value
End If
Application.ScreenUpdating = True
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Application.ScreenUpdating = False
If Not Intersect(Target, Range("b13:r14")) Is Nothing Then
If Target.Value <> oldValue Then
'MsgBox "You just changed " & Target.Address
Cells(65, 5).Value = oldValue 'this cell is a named range called: OldValuePaste
Cells(66, 5).Value = Target.row 'this cell is a named range called: OldValueRowNumber
Cells(67, 5).Value = Target.Column 'this cell is a named range called: OldValueColumnNumber
Range(Cells(Target.row, 2), Cells(Target.row, 18)).Copy
'Cells(70, 2).PasteSpecial xlPasteValues
Call Paste_on_AuditSheet
Sheets("Risk Register").Activate
Target.Select
Application.CutCopyMode = False
End If
End If
Application.ScreenUpdating = True
End Sub
_____________________________________________________________________________________________________
Sub Paste_on_AuditSheet()
Application.ScreenUpdating = False
Dim LastRow As Long
Dim ColNum As Long
Dim PasteRange As Range
ColNum = OldValueColumnNumber
Sheets("Audit trail").Select
'MsgBox "Activated " & ActiveSheet.Name
'Find the last used row in a Column: column B in this example
With ActiveSheet
LastRow = .Cells(.Rows.Count, "B").End(xlUp).row
End With
Set PasteRange = Cells(LastRow, ColNum)
'The following two lines bring in the new data and paste into old record and new record sections:
Cells(LastRow + 1, 2).PasteSpecial xlPasteValues
Cells(LastRow + 1, 20).PasteSpecial xlPasteValues
'Then this line goes back over the piece just pasted in and changes one cell in "old record" section to what it was prior to the edit:
'PasteRange.Value = Worksheets("Risk Register").Range("oldValuePaste")
'Above line of code is not working, but can get it to do the right thing using this code (although it's not dynamic):
Range("E3").Value = Worksheets("Risk Register").Range("oldValuePaste")
'Add a time stamp:
Cells(LastRow + 1, 1) = Now
Application.ScreenUpdating = True
End Sub
One last point - despite my repeated use of Application.ScreenUpdating commands, I still get some screen flashing - any ideas why?
Thanks in advance for the help!
In reviewing your code, I saw a few things that I didn't think would work as you supposed they would, and also recognized that your code could be made much simpler and just be called from the Worksheet_Change event.
So the refactored code below and let me know if you have issues:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("b13:r14")) Is Nothing Then
'get oldValue
Dim sNewVal As String, sOldVal As String
sNewValue = Target.Value 'store current or "new" value since this is what is stored after the cell change takes place
With Application
.EnableEvents = False 'turns off event firing so the code will not go into endless loop
.Undo 'undo the change (to store old value in next line)
End With
sOldValue = Target.Value 'store old value
Target.Value = sNewValue 'reset new value
Dim lCol As Long
lCol = Target.Column 'which column of data was changed
'assumes columns A-Q are 17 columns
Me.Range(Me.Cells(Target.Row, 1), Me.Cells(Target.Row, 17)).Copy
With Sheets("Audit Trail")
Dim lRow As Long
lRow = .Range("B" & .Rows.Count).End(xlUp).Offset(1).Row
.Range("B" & lRow).PasteSpecial xlPasteValues
.Range("B" & lRow + 1).PasteSpecial xlPasteValues
.Range("A" & lRow).Value = Now
.Cells(lRow, lCol + 1).Value = sOldValue 'store old value in first pasted line ... add 1 since starting from column B
End With
End If
Application.EnableEvents = True
End Sub

Conditionally copy selected cells from one sheet to another once for each new entry

I have two worksheets. On sheet 1, I have set up a macro that changes the color of the row and assigns "TRUE" value by selecting the cell or removes the color and "TRUE" value by selecting the cell again.
Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim i As Integer
Dim kod As Worksheet
Set kod = Worksheets("kodas")
If Target.Column <> 12 Then Exit Sub
If Target.Row = 1 Then Exit Sub
If Target.Cells.Count > 1 Then Exit Sub
Application.EnableEvents = False
If Target.Value <> "" Then
Target.ClearContents
Target.EntireRow.Interior.ColorIndex = 0
Else
Target.Value = "Taip"
Target.EntireRow.Interior.ColorIndex = 4
Target.EntireRow.Range(Cells(1), Cells(12)).Copy
i = kod.Cells(2, 3)
Sheets("Kodas2").Select
ActiveSheet.Paste Destination:=Sheets("Kodas2").Cells(i, 1)
End If
Application.EnableEvents = True
End Sub
*The above edited code worked for me - i = kod.Cells(2, 3) is a cell with formula: count(table4[bla])+2 that gives the first empty row number for pasting.
I now need some additional actions to be completed upon selecting the cell -OR- upon having the "TRUE" value assigned:
(1) Specific cells from the same row to be copied and pasted to sheet 2
(2) This action to be completed only once for each row (regardless of how many times the cell is selected) - perhaps locking the row would work?
The color and "True" shows which rows from sheet1 are suitable for continued work in sheet2, where some more data will be added. I essentially want to funnel only the suitable rows into the next datasheet automatically upon entry - it is important that the values are copied to the new table ByVal and not ByRef.
What about this (not using a For...Next Loop):
Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Column <> 12 Then Exit Sub
If Target.Row = 1 Then Exit Sub
If Target.Cells.Count > 1 Then Exit Sub
Application.EnableEvents = False
If Target.Value <> "" Then
Target.ClearContents
Target.EntireRow.Interior.ColorIndex = 0
Else
Target.Value = "TRUE"
Target.EntireRow.Interior.ColorIndex = 4
Target.EntireRow.Copy
DestLast = Sheets("Dest Sheet Name").Range("A" & Rows.Count).End(xlUp).Row + 1
Sheets("Dest Sheet Name").Range("A" & DestLast).Paste
End If
Application.EnableEvents = True
End Sub
Only problem is when you select the cell again, and "turn off" the row, it will still be on your "further work" sheet.

Copy and paste automatically on cell change using private sub

I am trying to add an archive sheet to my workbook where closed tickets are collected. I would like the row of a particular ticket to be cut from a sheet labeled 'Tickets' and pasted into a sheet labeled 'Archive' once its status has changed from open to closed. I would like this to happen using a private sub so that it happens on cell change. The Status is found in column 4.
If that is possible im assuming it will be possible to do it the other way round too. So if a ticket is re-opened again and its status is changed in the 'Archive' sheet it will be cut and paste back into the 'Tickets' sheet.
This is the code we have so far. We can seem to get it to work. Any help would be greatly appreciated. Thank you
Private Sub Worksheet_Change (ByVal Target As Range)
If Target.Column = 4 Then
If Target.Value = "Closed" Then
R = Target.Row
Rows(R).Cut
Worksheets("Archive").Select
With ActiveSheet
lastrow = .Cells(.Rows.Count,"B").End(xlUp).Row
End With
Cells(lastrow,1).Select
Selection.Paste
End If
End If
End sub
Just making small amendments to your current code:
If Target.Column = 4 Then
If Target.Value = "Closed" Then
R = Target.Row
Rows(R).Cut
Worksheets("sheet3").Select
With ActiveSheet
lastrow = .Cells(.Rows.Count, "B").End(xlUp).Row + 1
.Cells(lastrow, 1).Select
.Paste
End With
End If
End If

VBA( macros) copy and paste

I am trying to create a macros that will allow me each time it's activated to copy the value of a cell in worksheet 1 (the same cell but which would probably have differrent results after my calculation) and to paste the value of those results in worksheet 2 (maybe in A1;A2;A3;....... each time I make a calcul) this is a sample of a code i have written but which isn'working:
Sub recorder()
If Cells(B, i) <> Empty Then
i = i + 1
Worksheets(1).Select
Cells(A1).Copy
Worksheets(2).Select
Cells(B, i) = Cells(A1)
End If
End Sub
Any help would be appreciated. Thanks
Paste this into ThisWorkbook.
Whatever you change the value in Cell A1 on Sheet1 it will appear on Sheet2 in the nearest blank cell in column A. Note you don't need to run a macro it happens automatically.
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Not Sh.Index = 1 Then Exit Sub
If Not Target.Address = "$A$1" Then Exit Sub
If Worksheets(2).Range("A65536").End(xlUp).Value = Empty Then
Worksheets(2).Range("A65536").End(xlUp).Value = Target.Value
Else
Worksheets(2).Range("A65536").End(xlUp).Offset(1, 0).Value = Target.Value
End If
End Sub
I think this is what you're looking for:
Sub recorder()
Sheets(2).Cells(Rows.Count, "B").End(xlUp).Offset(1).Value = Sheets(1).Range("A1").Value
End Sub