Copy original row to new sheet when cells are changed - excel

I am trying to create a log sheet to keep track of a fleet's service. A vehicle can be in service, out of service, or both during each month (in/ out of service 9/1/21 - 9/30/21; in service 9/1/21 - 9/15/21, out of service 9/16/21 - 9/30/21). When the information is changed each month, I want the old row information to be recorded in another sheet with an identical table. Preferably, the row would only be recorded/ moved once all the necessary dates are changed.
.
So ideally, it would somehow wait until all changes to the row are made - I think it would be too complicated to check whether each date cell is properly changed because some can be left empty, but maybe a check if the user is finished updating a row before moving on?
I found this code on a Microsoft forum. It's close to what I need, but not quite. I'm just not 100% clear on the syntax, so I've had a hard time knowing what and how to change things. I changed Range("A:A") to Range("A:J") to look for changes in every column, and Range("A" & a) to Range("C" & a) to at least put data changed in column C to the new column C.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A:J")) Is Nothing Then
a = Sheets("Sheet2").Cells(Rows.Count, "C").End(xlUp).Row + 1
ActiveCell.Offset(-1, 0).Activate
Sheets("Sheet2").Range("C" & a).Value = ActiveCell.Value
ActiveCell.Offset(1, 0).Select
End If
End Sub

Related

Excel 2016 VBA , How to Insert Page Break on Every 2nd occurrence of particular text?

For example, on some sites,
I already study & try on Macro for insert HPageBreak Present on Every occurrence on particular text, with loop every cell of single column, but my requirement is every 2nd occurrence of particular txt
https://answers.microsoft.com/en-us/msoffice/forum/all/excel-macro-that-will-insert-horizontal-macros/9976e30a-8aae-4bec-84e8-43b35b113ec2
https://answers.microsoft.com/en-us/msoffice/forum/all/insert-dynamic-page-breaks-with-vba-for-excel/85790a6a-ef93-4354-8ad5-3cc5e4399285
https://www.extendoffice.com/documents/excel/1774-excel-insert-page-break-every-row.html
I already use Below code to put Hpagebreak on every found
but now requirement raise as every 2nd occurrence of "DISPATCH JAN TO NOV-22"
Sub Insert_Pagebreak_On_EveryFoundok()
Dim MYCOLUMN As Range
Dim MyCell As Range
'For Each MyCell In Range("G2:G" & Rows.Count).End.xlUp))
'For Each MyCell In Range Cells(Rows.Count, 2).End(xlUp).row 2
ActiveSheet.Range("G" & Rows.Count).End(xlUp).row))
ActiveWindow.view = xlPageBreakPreview
Set MYCOLUMN = ActiveSheet.Range("F2:F" & ActiveSheet.Range("F" & Rows.Count).End(xlUp).row)
For Each MyCell In MYCOLUMN
MyCell.Select
'If MyCell.Value Like "*Page 1 of 1*" Then
If MyCell.Value Like "*DISPATCH JAN TO NOV-22*" Then
ActiveCell.EntireRow.Select
ActiveWindow.SelectedSheets.HPageBreaks.Add
ActiveCell.offset(1, 0)
Else
ActiveCell.offset(1, 0).Select
End If
Next
ActiveWindow.view = xlNormalView
End Sub
This Loop check every cell that take more time, but I believe if use Range.Find method, then it can be more robust.
I am not knowing very well all aspects of VBA, but I daily use VBA in my many types of daily routine work & without it, I can't complete my work on time.
Currently I manually select 2 sets of data, adjust rows height to fit on A4, select -set-click print area & then print, and after print that I select below further 2 sets & do same thing, till sheet's data end,
painfully pass whole my day, just for print 2 data set on 1 A4 page.
There are need to beware for Hidden rows which hides for reason (not requirement in print). so, condition is only visible rows should be count for 2nd occurrence.
I attached Screen shot of whole scenario for reference.
[Plese Refer This Image as my situation]
enter image description here
Hundreds of data sets on this worksheet.
There should be 2 sets of data as pair require on every A4 size page.
so obviously page break requires on every 2nd occurrence of particular text.
If, that happen successfully, I am ready to manually adjust rows height to fit 2 sets in A4 page, so I get whole sheet ready for print in one go.
Hope, I try my best to describe my situation if require further, please mention.
Can anyone help regarding this?
I really appreciate & will be thankful forever.
Regards,
Chirag Raval

Copy column data based on a specific year

I have an Excel sheet with prices (of materials used in construction) from previous years.
I am trying to make a code that will show me all the data based on a certain year that I choose.
What my list/excel looks like
In cell E3 (in yellow), I input the year to "analyse".
I need a function that will search columns K to Q (and more since every year, prices change), for that year, and copy all the data of sales, reg. loc. and spec. loc. into the columns F, G and H.
If it's easier that, instead of putting the year in cells K3, L3 and M3 (for example), if I put it in cell N3, R3, etc. (in red) instead, the function will take the 3 previous columns and copy/paste them in columns F to H.
Option 2, if it makes the coding easier
Also the list goes until row 381, and there's a potential that more data will be input eventually so take into consideration as if the list had an infinite amount of rows. However, for the columns, it's always fixed to 3 columns.
FYI: it is not a school project. I'm trying to simplify my work instead of manually searching and copy/pasting the data every time.
Please, try the next code. It should do what (I understand) you need. It should be fast, not using clipboard for copying. As I suggested in my comment, it firstly searches/finds in the third row the year (long or string, as it is written in "E3"), starting searching after "E3", then copying the range built according to the found cell. If not a match is found, the code exits on the line If rngFirstCol Is Nothing Then Exit Sub. You may place a message there, to warn in such a case. It works on your first arrangement/picture, meaning that the year must be filled in the third row of the first column where from the necessary data should be collected/copied:
Sub ExtractPricesPerYear()
Dim sh As Worksheet, lastR As Long, rngFirstCol As Range, lngYear, necCol As Long
Set sh = ActiveSheet 'use here your necessary sheet
lngYear = sh.Range("E3").value 'the year to be searched
Set rngFirstCol = sh.rows(3).Find(What:=lngYear, After:=sh.Range("E3"), LookIn:=xlValues, Lookat:=xlWhole)
If rngFirstCol Is Nothing Then Exit Sub
necCol = rngFirstCol.Column
lastR = sh.cells(sh.rows.count, necCol).End(xlUp).row
With sh.Range(rngFirstCol.Offset(1), sh.cells(lastR, necCol + 2))
sh.Range("E4").Resize(.rows.count, .Columns.count).value = .value
End With
End Sub
Please, send some feedback after testing it.
And another issue: It is good to show us what you tried by your own. If not a piece of code, at least, something to prove that you investigated and had some ideas about the task to be solved, asking for hints, suggestions etc. proving that you know something about how it can be done...
Edited:
Following your requirement from last comment, please use the next solution. Please, copy the next code in the respective sheet code module (right click on the sheet name, then choose View Code):
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim lastR As Long, lastRF As Long, rngFirstCol As Range, lngYear, necCol As Long
If Target.Address(0, 0) = "E3" Then 'the code exits for any other change on the sheet
lngYear = Target.value 'the year to be searched
Set rngFirstCol = Me.rows(3).Find(What:=lngYear, After:=Me.Range("E3"), LookIn:=xlValues, Lookat:=xlWhole)
If rngFirstCol Is Nothing Then MsgBox "No such year found on the third row...:": Exit Sub
necCol = rngFirstCol.Column 'column number of the found cell
lastR = Me.cells(Me.rows.count, necCol).End(xlUp).row 'last row on the found column
lastRF = Me.Range("F" & Me.rows.count).End(xlUp).row 'last row on F:F column (to delete its content, if any)
If lastRF > 4 Then Me.Range("F4:H" & lastRF).ClearContents 'clear the range to make place for the new data
With Me.Range(rngFirstCol.Offset(1), Me.cells(lastR, necCol + 2))
Me.Range("F4").Resize(.rows.count, .Columns.count).value = .value
End With
End If
End Sub

Conditionally copy, paste, delete between worksheets data missing

I have inherited a workbook that has suffered months of abuse (poor data entry, poor cut and paste, duplications, etc). I have nearly finished sorting the data but to prevent similar problems I am trying to automate some of the process. I am new to VBA and cannot figure out why my code isn't working. There are several worksheets that track an application through our new client process. Each worksheet has the same fifteen columns, metadata in the first 10 rows (=sum counts) and headers in the 11th row. When we receive interest in joining our organisation some simple data is entered into columns A-D and L-O inclusive. I want a particular row to move to the next worksheet when a date is entered to indicate a step in the process has been completed. For example when a client returns an application form, the date is entered into column G and the specific row is moved to the next worksheet and deleted from the original. The date entry works but columns L-O are not being copied. HELP!
The code I'm using is:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("G12:G100" & Range("A" & Rows.Count).End(xlUp).Row)) Is Nothing And Target.Cells.Count = 1 Then
If IsDate(Target.Value) = True Then
Range(Cells(Target.Row, "A"), Target).Copy Sheets("Awaiting Interview").Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
Target.EntireRow.Delete
End If
End If
End Sub
Thank in advance.
AlVBA

Deleting cell value if "Quit" button selected

I have 1 userform for login called "LoginForm" and 3 additional userforms "AMForm", "FMForm" and "HRMForm" that open up if the user's details are correct. There are 3 spreadsheets "AMChoices", "FMChoices" and "HRMChoices" where the contents from the 3 additional userforms are recorded into the relevant spreadsheet i.e. FMForm into FMChoices.
To specify the user, their UserID appears in the relevant spreadsheet if their credentials are accepted. For example, if is userform "AMForm" their UserID is entered into the next available cell in column B in "AMChoices" (starting at B3). As there are multiple users logging in, it enters to the next empty row.
The code I have works perfectly. However, on each userform "AMForm", "FMForm" and "HRMForm" there is a "quit" button. So I want it to delete the recently entered UserID.
How can I code this? I have entered the code I use to enter the UserID into the spreadsheet from the LoginForm. Please let me know :)
Private Sub btnAMLogout_Click()
If MsgBox("Are you sure you want to quit? Press Yes to proceed and No to cancel.", vbYesNo) = vbYes Then
Unload Me
End If
End Sub
If aCell.Offset(, 4) = "SBUB10" Then
AMForm.Show
With Worksheets("AMChoices")
LastRow = .Range("B" & .Rows.CountLarge).End(xlUp).Row + 1
If LastRow < 3 Then LastRow = 3
.Cells(LastRow, "b") = WorksheetFunction.Proper(ID)
End With
The snippet of code you've shown writes the ID into the worksheet. To remove it, you need to find it and blank out the cell it is in. This action can be performed either before theUnload Me call or after it. The code you have needs some modifications:
Private Sub btnAMLogout_Click()
If MsgBox("Are you sure ...", vbYesNo) = vbYes Then
Unload Me
' Let's say the new code goes here. The last ID (whichever it is) will be removed.
With Worksheets("AMChoices")
LastRow = .Range("B" & .Rows.CountLarge).End(xlUp).Row ' no need for: + 1
If LastRow < 3 Then Exit Sub ' no need for: LastRow = 3
.Cells(LastRow, "b") = "" ' no need for: WorksheetFunction.Proper(ID)
End With
End If
End Sub
Now, since you've mentioned multiple users, it might be a bit more complicated because you need to find the cell with the ID in question (it might not be the last one!) and then delete it. The "deleting" could be just emptying the cell (as above) or deleting the whole row of that cell, or something else--I do not know your situation well enough to say which it is.
Anyway, to look for the last occurrence of that ID in column "B:B" you need to test the cells in the column to have that ID, starting from the last cell and going up, one cell at a time, something like
For i = LastRow to 3 Step -1
If .Cells(i, "B") = WorksheetFunction.Proper(ID) Then
.Rows(i).Delete
Exit For
End If
Next
I sure hope this helps.

Excel Range.Find not working the way I thought it would

So I have been trying to figure out why this isn't working and I am getting really frustrated.
When I click on my "Search" button, it takes the text from a text box, and uses that as the search criteria. I want it to skip whatever row is currently active, so that as long as I keep pressing my "Search" buttton it will move on, and not keep finding the same row. And I had it working for a long time, then I upgraded to Windows 10 and stuff stopped working. This is just the one thing I can't seem to figure out. I made some changes to my original, so this is not the same code that used to work. No matter what I do it keeps showing me the same row even though the one RIGHT BELOW it has identical data. Like in the picture below, if I search for TRACE the third row of data is selected, but when I hit "Search" again, it doesnt move to the next row like it should. I am using Range.Find(What:= , After:=) and setting the After range to the very left cell of the current activated range. Which should start the search on the next row. But that is not happening.
Private Sub Search_Next_Click()
Dim Fnd As Range
Dim S_Range as Range
Dim CurrRow As Integer: CurrRow = ActiveCell.Row
Dim CurrColumn As Integer: CurrColumn = ActiveCell.Column
'Last row of data
LastRow = Range("B24").End(xlDown).Row
AC = ActiveCell.Address
''If the Find button is pressed and the current active cell is outside the range of my data
''this makes sure that the active cell moves to the upper left of that range
If AC = "" Or CurrRow < 24 Or CurrColumn > 10 Then
AC = "B24"
Range(AC).Activate
End If
ACr = ActiveCell.Row
On Error Resume Next
Set S_range = Range("B24" & ":J" & LastRow)
Set Fnd = S_range.Find(what:=SearchBox.Text, after:=Range(AC))
FR = Fnd.Row
If FR = "" Then
MsgBox ("No Match Found")
DoCmd.CancelEvent
SearchBox.SetFocus
Exit Sub
End If
On Error GoTo 0
Scell = "B" & FR & ":J" & FR
ActiveSheet.Range(Scell).Select
ActiveSheet.Range(Scell).Activate
End Sub
OK as soon as I posted this, I figured out what I did wrong. Although I dont know why it worked in the past, and then stopped. Maybe I changed something without realizing it and screwed myself up. Anyway, I was searching for a value in the D column. Once it was found the cell with the search criteria, the cells in column B through F were selected and activated in that row. But when I hit Search again, it started after the B column of that row. I thought it would skip to the next row, but it was moving to the next column to start the search. So it ran into the same value again, and the cycle repeated.
I just changed the After criteria to
After:=Range("B" & ACr + 1)
Then it started the search on the next row like I wanted.
Im leaving this up in case anyone else comes across this mistake. Hopefully I can help someone else realize that they are not the only ones that make stupid mistakes.....

Resources