I have a spreadsheet, with whatever in it. Now I want use one specific region (let's say C1:D10) to hold temporary data (in case I cannot remember clearly or mess them up).
However, I don't want keep the data for ever, and it is totally useless when this spreadsheet is used next time. Is there any way to erase this part when the spreadsheet is closed, no matter whether the user choose "save the change" or not, so that (C1:D10) is blank when I open the spreadsheet next time.
Instead of clearing the cells upon exit, use the Workbook_Open to clear the cells. This way you don't need to bother whether the user save the workbook on exit or not. This code will clear the cell the moment the workbook is opened.
Change Sheet1 below to the relevant sheet.
Private Sub Workbook_Open()
Sheets("Sheet1").Range("C1:D10").ClearContents
End Sub
Related
I have a worksheet containing a column of numbers. The column is formatted with a background color, number formats, etc. The column is unlocked. I protect the sheet manually by right-clicking on the tab and selecting Protect. In the Protect Sheet dialog, 'format cells' is unchecked. I interpret to mean that the user should not be able to format cells. Yet when the user pastes into the column, formats are pasted along with values.
If I protect the sheet in VBA using
sh.Protect UserInterfaceOnly:=True
I get the same result: formats are pasted. I do not specify AllowFormattingCells:=False because the default is False.
I have seen posts suggesting that formats can be restored by copying and pasting them from a shadow area. I have used this solution before I started protecting worksheets and found it overly complex. I had hoped this was something protection would handle. If there is a way to handle it, I'd like to do it in VBA.
This question is a little old, but I had the same one, and so have many people in the past. With a bit of browsing I came up with a solution which seems quite clean and appears to work. Am I missing something?
Private Sub Worksheet_Change(ByVal rngTarget As Range)
Dim vPaste As Variant
With Application.CommandBars("Standard").Controls("&Undo")
If Not .Enabled Then Exit Sub
If .ListCount < 1 Then Exit Sub
If .List(1) <> "Paste" Then Exit Sub
End With
vPaste = rngTarget.Value2
On Error Resume Next
Application.EnableEvents = False
Application.Undo
rngTarget.Value2 = vPaste
Application.EnableEvents = True
On Error GoTo 0
End Sub
This could go in Workbook_SheetChange, but not if you already have code in Worksheet_Change, because the worksheet event handler gets called before the workbook event handler. But this code can go in a module to keep things tidy.
There is no built-in protection option you can use to achieve your desired result.
The only thing that works in this case is the clunky workaround that you mention, i.e. use a Worksheet_Change event that ensures the correct format after a cell has been modified.
Since there are many different ways to paste content, i.e. via various menus, ribbon commands, keyboard shortcuts, etc., any VBA solution that tries to intercept pasting will become very complex, much more complex than the change event that restores the format to its original state.
Another option might be user education and training (so they know to paste values only), although user behaviour may be the toughest element to change in the whole scenario.
So I am currently studying SQL Server but right now I am just working a standard office admin job while I'm studying.
I never really made macro's before and little knowledge on VB but decided to design a macro for work to make things a bit easier for my team.
The macro just very simply allows the user to enter data, stats etc and gives the percentage or average statistic resulting in a total letting the user know if the statistics have been hit that day, week, month etc.
It works well but I would like to add a "SUBMIT" button that when a user clicked it would send the data they have entered in specified cells to myself. I am not sure how to go about it, If needed I don't have access to systems like SQL, Visual Studio etc in work as said just basic admin job at the moment.
Would It need to be submitted as a CSV? or could it be submitted from the user's sheet straight onto another macro I have designed giving the results for the whole team? As said I am totally new to this idea.
Cheers Guys.
Awright, according to what you may need in a very simple approach, the first thing you need to do it's to know the cells where they're going to enter info (care with ranges ), let's assume for this example that whe only had one data entered in the first cell of the team worksheet. So, create a button called 'button1' or as you wish and on the click event use this code :
Private Sub button1_click()
Teamsheet.Cells(row,column) = Yoursheet.Cells(destinyrow,destinycolumn)
End Sub
That would copy the value from one sheet to another, now, if you had you sheet locked via password, you must unlock it before doing that,then lock it again so code would be like this :
Private Sub button1_click()
On Error Resume Next
yoursheet.unprotect password:="yourpassword"
Teamsheet.Cells(row,column) = Yoursheet.Cells(destinyrow,destinycolumn)
On Error Resume Next
yoursheet.PROTECT password:="yourpassword"
End Sub
I clarify that this is a very simple approach, so, if you're using specific cells you can copy one by one and this would do (so you can make anny calculation son your admin sheet), but when you're copying ranges should be like this :
Teamsheet.Range("A1:D3").Value = yoursheet.Range("A1:D3").Value
Also, always consider how they enter this data you need.
UPDATE :
Let's say you have a team workbook and yours is admin_workbook, concept it's similar. This code will do what you need but both workbooks should be at the same folder or path :
Private Sub button1_click()
Var_data = Teamsheet.Cells(row,column)
Application.ScreenUpdating = False
Workbooks.Open Filename:=ThisWorkbook.Path & "\admin_workbook.xls"
ThisWorkbook.Activate
Admin_sheet.Cells(destinyrow,destinycolumn) = var_data
Workbooks("admin_workbook.xls").Close SaveChanges:=True
Application.ScreenUpdating = True
End Sub
First you capture data on a var, then you open your admin book, put the data on the cell you want and close that workbook saving changes (you decide if you keep this line or mantain the workbook open and save manually). Also, Application.screenupdating it's a line that helps your screen doesn't flick when changing between workbooks.
Hope it helps friend !
My macro is going to compare a sheet with another sheet. This second sheet needs the user to paste data in there. (Note: The data being copied is not in Excel).
One way is to run the macro, and end it by prompting the user to paste the data in, then run "Macro2". However, I'd like to keep it all in one macro, so have found a way to wait for user input before continuing. This seems to work for me, so my main question is:
How stable is doing it this way?
...macro stuff above here
MsgBox ("[Please copy the data into the new sheet, after clicking 'OK']")
Do While WorksheetFunction.CountA(newWS.Cells(1, 7)) < 1
DoEvents
Loop
...then after the user pastes info, continue on, using the data that's been pasted.
The idea is that DoEvents just runs and runs while my sheet is blank. Right after the user pastes the data into the newWS, the macro continues on (since it will see data in column 7)...
Is this an okay method, or is it a bad idea to use like that? I've never really used DoEvents, so don't know if it's doing something in the background that could cause issues.
Edit: The data is in Lotus Notes, which I can export to Excel. However, that takes a few more steps (and I'd rather not create some new temporary excel files), so copy/pasting is my preferred method. This question is half practical, and half theoretical. Sorry for any confusion!
Probably not the best idea. Instead, allow them to select the data and perform the copy, all through VBA:
MsgBox ("[Please select data to copy into the new sheet, then press 'OK']")
newWs.Cells(1,1).PasteSpecial '### Modify to your specific location to paste the data
'Here you can add logic to validate that they have pasted enough data,
' and use control statement to prompt them to paste more data, etc.,
' if necessary, or exit sub early
'For example:
If WorksheetFunction.CountA(newWS.Cells(1, 7)) < 1 Then
MsgBox "Try again!"
Exit Sub
End If
Alternatively, you can use a DataObject:
Dim dataObj As New MSForms.DataObject
dataObj.GetFromClipboard
newWs.Cells(1,7).Value = dataObj.GetText
You could restructure the code so that it lives inside of a userform with ShowModal set to false (in the properties). Code prior to when you want the user to gather data can be put in the useform's initialize event. Then the userfrom shows (with a simple label caption and an okay button). Since it is modeless the user can copy data from an external program and paste it in. Then the rest of the code runs after the user hits okay. The form itself can be hidden during this phase. As proof of concept I created the following form:
with the following code:
Private Sub CommandButton1_Click()
Me.Hide
MsgBox Range("A1").Value
Unload Me
End Sub
Private Sub UserForm_Initialize()
'macro code can go here
'it runs before the form shows
'e.g.
MsgBox "Initializing"
End Sub
I launch the form on a blank sheet. First a message box appears before the code (confirming that code can run while the form is being initialized but before it is visible) then the form shows:
I go to an open instance of Notepad which contain a sentence and, while the form is still open -- paste it into A1:
Finally I press okay and the userform then hides itself but continues to run code (which now has access to the copied data):
Remember to unload the form at the end.
I've researched this to death and feel like I'm the only person it's ever happened to.
I have some VBA that:
Creates a copy of 3 sheets to a new wb
In the new wb converts to values, deletes objects (shapes and controls) and all but 3 ranges
Opens an existing third file and sets the contents of three ranges in that to match the new wb
Closes the existing file (saved)
Closes the new wb (saved)
Gives a message box saying complete
At the end of all this, something weird happens with the state of the windows. The selected cell does not appear selected. If I try and click a control afterwards, it selects the object (hence users could drag them). It shouldn't and this is the big problem.
I've tried selecting a cell through code, it throws an error. I had limited success by forcing drawing mode off using Call CommandBars("Drawing").Controls("Select Objects").Execute and activating a specific sheet & selecting a cell. However, even then if I even click on a few cells afterwards, the next time I select a control it will select it as an object rather than click the thing.
I have no idea why and can't find anyone who's seen this before.
Any ideas on what I can do?
Thanks,
Basil
I didn't figure it out entirely, but I did find a fix. Hopefully it works for anyone else who finds this problem.
At the end of the code I added this:
ActiveSheet.Shapes.Range("ctrlExportPrices").Select
ActiveSheet.Range("B8").Select
So it forced a control on the sheet to be selected, and then a cell.
The next time I select the control manually, it clicks it rather than selecting the drawing object.
I want to create an excel template that will includes formulas for dating the columns. However, since those formulas will be based on TODAY(), I need to convert them to static strings (so the dates don't change everytime someone opens it). Is there a way to add a macro that will run automatically when someone creates a new spreadsheet based on the template? (Similarly to Auto_Open(), only on Create, rather than Open). If so, I could just create a macro that will replace the formulas with their results upon document creation. Can this be done?
[Note: I'm not married to this solution; it just seemed like the simplest way to protect my spreadsheet. If someone can suggest an alternative approach, I'd be obliged.]
I have a couple thoughts...
If you run a copy/paste values macro every time it really won't matter, right?
You could check if the file exists yet (has been saved), and if not
then this must be the template opened as a new workbook, maybe?
Code:
Private Sub Workbook_Open()
If Dir(ActiveWorkbook.Name) = "" Then
'run the macro?
MsgBox "I'm gonna run this macro"
End If
End Sub
You could have a cell on one of the sheets, that will never be used,
or is hidden, that will store whether or not to run the macro, and
change that when the file is opened or when the macro is ran. Then
have a macro run on open that checks that cell. (Or custom/document property)
You could populate the cells that have the today() formula only on
open and if they are already populated then don't run the macro?
I realized that there is no need for a Workbook_Create() function, as that behavior can be emulated by simply deleting the macro after it has run once (which happens when it is first created). Deleting macros is done automatically when the file is saved with a .xlsx extension. In addition, you need to prevent the macro from running when you open the template itself (while editing the it). You can hold the SHIFT key when opening it to prevent auto-run macros, but since that method isn't foolproof, I added this code at the top:
Private Sub Workbook_Open()
'If we're opening the template, don't run the macro
If Application.ActiveWorkbook.FileFormat = xlOpenXMLTemplateMacroEnabled Then
Exit Sub
End If
...
'add code here to SaveAs .xlsx, thus removing the macros, so it won't run every time.
End Sub
(Note: I didn't show my SaveAs code as it is rather messy: I wanted to suppress the default warning about losing macros, but wanted to also protect the user from inadvertantly overwriting previous file. If anyone is interested, I could post it)