VBA: Mirror a cell to another sheet, then keep the data after deleting the original - vba

Apologies if this has been answered, but I couldn't find any details of this being asked before. I know it's a vague question without code, but just looking for ideas of how to approach this. Writing VBA code on Excel.
I have a sheet, which contains 20+ columns and 8,000+ rows of data. The sheet is password protected / read only as I do not want users editing the data (the sheet is linked to several other macros). Called 'Master Data Sheet'.
I have created a macro that will filter the Master Data table and then paste the filtered results on another sheet (called 'Filtered Results') and combines data with another separate sheet. The user can view and edit this sheet.
However there are two columns that I want the user to put data in that needs to be duplicated/mirrored in the Master Data Sheet (in those specific columns) automatically. Issue I'm having is that the 'Filtered Results' sheet gets deleted after a period of time, but I still need the user input data for those specific columns to be in the Master Data Sheet.
I'm unsure how to get around the issue of the sheet being deleted but data being retained.
An alternative workaround I had would be a copy/paste button the user could click to copy the unformatted data from the Filtered Sheet to Master Data Sheet. However, I was hoping to find a solution that would just automatically update as the user types (in case they forget to click the button etc.)
Thanks for all the help!
EDIT: Code I'm working with right now. Still stuck on linking filtered cells though.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents=False
If Not Intersect (Target, Range("D1:D1000")) Is Nothing Then
Target.Copy Destination:=Worksheets("Master Data
File").Range(Target.Address)
End If
Application.EnableEvents=True
End Sub

You can use the Worksheet_Change event to check if a specific range changed and then copy/update the other sheet. This way you have the copy/paste automatically when the original data changed.
Example:
If you want to copy range A1:A5 into another sheet whenever its values changed:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A1:A5")) Is Nothing Then 'range A1:A5 was changed
Target.Copy Destination:=Worksheets("OtherSheet").Range(Target.Address)
End If
End Sub

Related

Saving cell Presets in a dropdown list

At the moment I have created a spreadsheet which takes a bunch of inputs, runs them through a list of formulas, and then spits out the results onto a "report" worksheet.
I've been manually saving each of these reports as separate CSVs but I was hoping for a better method moving forward as it is getting quite tiring to have to open 10 CSVs when i do my monthly reports.
I am looking for a way to start saving all of these reports into a "database". My hope to to have one cell be for an user entry name and for two buttons. One to save the current report under the name entered by the user, and two to remove old records. I would then be able to revisit old entries by selecting them in the dropdown.
I've dabbled with VBA and Macros in the past but this is a little more complicated than what I've dealt with in the past. Looking for some help/direction.
Thanks for your time!
Depending on how your reports need to be used, you might find it satisfactory to simply make your data into one big Excel Table ( Insert Tab > Table ). When you do this, Excel will automatically fill-down any formulas that you enter in a column, and also show the formula using the headers instead of A1-style references.
I use this format, adding Y under Remove from Active List on each line that is already done. Then whenever I save the file or look at it for today's status, I filter out what's old and just look at the new. The other filters enable copy-pasting or printing whatever arrangement I like.
The filters and other things in the table can be referenced in VBA as Sheets("ThisSheet").ListObjects(1), which is an object with a number of useful properties and methods.
For VBA information, read more here: https://www.thespreadsheetguru.com/blog/2014/6/20/the-vba-guide-to-listobject-excel-tables
This is my code for auto-filtering the table to hide inactive items at time of save. You add it at ThisWorkbook in the VBA editor:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Sheets("Sheet1").Activate
SelectedCell = ActiveCell.Address 'this saves your screen selection for after the filtering
ActiveSheet.ListObjects(1).Range(1, 1).Select
If ActiveSheet.ListObjects(1).AutoFilter.FilterMode = True Then
ActiveSheet.ListObjects.Item(1).AutoFilter.ShowAllData
End If
A = ActiveSheet.ListObjects(1).Range.Rows(1).Find("Remove from List").Column - _
ActiveSheet.ListObjects(1).Range.Column + 1
ActiveSheet.ListObjects(1).Range.AutoFilter field:=A, Criteria1:="="
Range(SelectedCell).Select
End sub

Pasting same cell on different rows as value is replaced

This sort of follows up from my previous few questions on the same workbook.
I have two sheets, the first being Car Search, which contains a form (NOT a VBA form, just a normal table that appears like a form) to fill in. The second sheet is Raw Data, and will contain all the information entered in the Car Search sheet. It will be displayed row by row (see 2nd image).
In the Raw Data sheet, I am using the formula =""&'Car Search'!B3 to copy the contents of cell B3 in the Car Search spreadsheet.
My question is: If I had a new Car ID value, how can that automatically be entered into the row below?
Essentially, I am trying to use the form to capture all data for new cars coming in, and then I would like all that data to appear in the second sheet in their respective rows/columns.
Any help much appreciated! :)
EDIT:
Good news!
You need to use VBA:
Sub Range_Copy_Examples()
Worksheets("Car Search").Range("B3").Copy Worksheets("Raw Data").Range("=OFFSET(Sheet3!B1,0,0,COUNTA(B1:B300)+1,1)")
End Sub
However there is a small bug where it keeps pasting across past values, so I have suggested an alternative macro below
Re-edit:
A more mechanical way to make macro work (hopefully someone can improve on it) looks like this:
Sub Macro1()
Sheets("Car Search").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Raw Data").Select
ActiveCell.Offset(1, 0).Range("A1").Select
ActiveSheet.Paste
Worksheets("Car Search").Activate
End Sub
This works as follows:
in Car Search, have cell B3 selected the whole time
in Raw Data, select the cell with the last value in the column where you want you Car Search!B3 data pasted (you only have to do this once)
press Run on the macro (easy enough to just record one yourself)
go back to Car Search and change the value of B3, press Ctrl-Enter to keep the same cell selected after changing value, then press the same macro button without changing a thing.
If someone could add so that when pressing Ctrl-Enter on Car Search!B3 the Raw Data gets automatically added without having to manually run the macro, it would be fully automated!

I need to be able to sort a protected worksheet that has locked column headers in excel (VBA)

I am working on an excel document at the moment and everything is turning out quite nicely. However, I am coming down to the very last issue that I am having a problem resolving: being able to sort my columns in ascending/descending order while the worksheet is protected and the column headers are locked. I will state some facts about my worksheet first, the goal that I am trying to accomplish, then possible solutions that I have researched and why those solutions do not seem to apply to my situation.
First, I am NOT using an excel table object (just plain
rows/columns).
The top row has AutoFilter applied (to work as column headers).
All of the cells in the worksheet are unlocked, EXCEPT for the
entire first row which is locked (aka, the column headers).
The worksheet will be protected.
I do NOT want users to be able to edit data in the first row (this
is important, these must not be editable no matter what).
For my protected sheet settings, I have "Select locked
cells","Select unlocked cells","Insert rows","Delete rows","Sort",
and "AutoFilter" checked.
I am using VBA for my worksheet.
I am using Excel 2013
Now, assuming the worksheet is protected, users are currently able to use the AutoFilter at the top to actually "filter" the data as intended. The issue is whenever they try to "sort" the data in ascending/descending order that I get an error saying that you must unprotect the sheet first.
After researching I have seen that this is due to the fact that when you sort, the AutoFilter automatically counts the column header as part of the range being sorted... but because this column header (row 1) is locked, it is causing this error. However, this row HAS to be locked, my VBA code specifically reads the values in these column headers and under no circumstances can they be changed.
So filtering works just fine, it is just the sorting I am trying to figure out now. My "ideal" solution would be to somehow capture an event when a user clicks on the AutoFilter arrow and selects "Sort" where I can then, in VBA, unprotect the sheet, sort according to their selection, then protect the sheet again. However, again upon research, it seems that there really isn't an option when it comes to an event for this AutoFilter button (I could be wrong, sometimes it can be confusing reading other's suggestions).
I am hoping someone out there can help me out with this situation, I would also LIKE to avoid using an excel table object, however if it is the only solution that works that meets all my above criteria then so-be-it.
Thanks in advance for your help.
If you already use VBA, you can plug this code into the Sheet module. This assumes the headers are in row 1. Change to suit.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("1:1")) Is Nothing Then
Application.EnableEvents = False
Application.Undo
Application.EnableEvents = True
End If
End Sub
The sheet now does not need to be protected.
Borrowing a bit from #Teylyn's and adapted it to disallow selection of the header row, when it is selected, it selects the cell below it directly and displays an error message. The code sits in the sheet module, if it needs to be applied to more sheets, it may be better to use Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range), in that case, replace all instances of Me with Sh in the code below.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, Me.Range("1:1")) Is Nothing Then
Target.Offset(1, 0).Select
MsgBox "You cannot select or edit the headerrow, please use the autofilter button to sort and filter.", vbCritical, "Invalid Selection"
End If
End Sub
Note
Unlocking the cells which is required for the sorting and then allowing unlocked cells to be selected when protecting the worksheet, which is needed to be able to edit the data, makes the worksheet protection effectively useless.
Also wit the code above, there is still a loophole through which cells can be edited. If you select an allowed cell, drag it to the header row, and choose to replace the data in the cell then the header cell to which the allowed cell was moved is selected and editable.
End of note
Select the data range which needs to be sorted and unlock the cells.
When protecting the worksheet, be sure to allow
sort
autofilter
To prevent users from changing the cell contents, disallow the selection of unlocked cells.

Excel macro for automatic data entry

I need a macro to help me with data entry in Excel. Basically I want sheet 1 for data entry, and sheet 2 for the data that are entered. Sheet 1 will only have one row for data entry, and once that row is filled you hit enter. The row is automatically added to the table in sheet 2, and the row is cleared on sheet 1. Now you are ready to enter another entry in sheet 2.
So to summarize sheet 2 will have multiple rows for the data entered, and sheet 1 will only have 1 row because it automatically clears it's row after each entry.
Is something like this possible?? If you guys can post some code for me it would really help, and keep in mind I have never programmed in VBA before. Thanks in advance!!
Place a button on your sheet 1, then put this macro into a regular code module and attach it to your button. Assuming you are entering values across row2 (row1 being titles or such), then this would transfer row2 data to the next empty row on sheet2:
Sub Transfer()
Rows(2).Copy Sheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Offset(1)
Rows(2).ClearContents
End Sub
I'm not totally sure of the use-case, but have you considered using Excel UserForms instead.
The input would be a form that actually appears in front of the user which would collect input. When they hit the enter button, you could have underlying code to update the main sheet, Sheet 2.
http://www.excel-vba-easy.com/vba-userform-excel-vba.html
You could also use the database form. set up your database sheet then Data > Form (in 2003)
In order not to have to "click" on a button, I would suggest to look into this function:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
End Sub
This macro will run every time something in your sheet has changed.
It might be that you have to check if there is data in cell A1, as this VBA might be triggered both after hitting enter and after the data has been transported to the other sheet.

VBA Programming in Excel

I am new to programming in Excel. I have done very little Visual Basic. What I would like to do is check a column on one sheet in Excel and compare all the values to a column in a different sheet in Excel. Now the problem is, is it possible that when i click on one of the cells it is "linked" to the other and takes me to the matching cell. I would like to have this implemented into the spread sheet and not be a "macro". If anyone can help it would be much appreciated.
"macro" and "implementation in spread sheet" is nearly the same. the macro is, depending on how you do it, stored in the spreadsheet-file (.xls)
you can get the content of a cell by reading
Range("A1").Value // Any cell-reference is valid here.
If you want to read an entire column, you need to use some kind of loop.
the linking you're talking about could be done with the event Worksheet.SelectionChange. e.g. following skeleton:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
End Sub
you may now fill what should happen when the selection has changed. With Target.Column and Target.Row you may read the row and do the appropriate tests.
You can switch the View on a special Sheet using the Worksheet.Activate-Method which brings on top the worksheet you call the method on.
hope this clarifies a bit... if you need details, i will do some research...
regards