Reputation: 1820
I need to temporarily store my macro's settings for each worksheet. I thought about extending the active sheet's properties to store the settings there. The goal would be to read a property such as ActiveSheet.Setting1. I've tried wrapping the ActiveSheet object in a class:
"cCustomSheet" class module:
Public WithEvents WS As Worksheet
Public Setting1 As String
"Module1" module:
Dim ActiveWS As cCustomSheet
Sub test1()
Set ActiveWS = New cCustomSheet
Set ActiveWS.WS = ActiveSheet
End Sub
Sub test2()
MsgBox ActiveWS.WS.Name
End Sub
This code works without an error, but ActiveWS
should be updated to the new active sheet if the user activates another sheet, and it's not. If I remove the Set
keyword from the line Set ActiveWS.WS = ActiveSheet
, I get the following error:
Error n° 91: Object variable or With block variable not set
How should I do it, and is this even possible?
I also thought about using ActiveSheet.CustomProperties but this seems rather clumsy since you can't retrieve a setting by its name (without looping through all of the items), and you have to rely on index numbers.
Thanks in advance.
Update: I should add that my macro will be stored as an Excel Add-in, therefore I won't have access to the code of the workbooks of the users. I cannot take advantage of the Worksheet_Activate() event to keep track of the active sheet. Also, the settings would preferably be lost or reset to their default values when the workbook is reopened, that's why I can't save them inside the user's file (in a hidden sheet for example).
Upvotes: 2
Views: 1598
Reputation: 1820
Thanks everyone for your suggestions. They have helped me finding a way to store my settings for each worksheet. I've used ActiveWorkbook.CustomDocumentProperties
to assign a random ID to the active workbook. Each worksheet is identified by the concatenation of the workbook's ID and the sheet's codename (which is unique inside a workbook). The settings for the active worksheet are added to a collection where the sheet's ID serves as the index, so that they can be retrieved easily.
This is not 100% safe since two workbooks can hypothetically get the same ID, since it's a random number. The workbook's ID is also saved to the Excel file. It becomes useless after the workbook is closed but "pollutes" the custom properties list of the file.
I also needed to store the address of the column holding the values on which to apply my macro. This is set by the user. Instead of storing the absolute address of the range, I'm using the .ID property of the first cell of the column. This way, if the user moves the cells, the ID sticks to the values. The downside is that I have to cycle through every cell of the first row of the selection to check if a cell holds an .ID value, which is quite inelegant. The .ID property is gone after the workbook is reopened, which is fine for me because I didn't want the settings to be persistent.
Upvotes: 0
Reputation: 328669
As your macro is in an Excel Addin, you could store the information in the sheets of that addin, which are not visible. You can even make that sheet "very hidden" if you want to make sure nobody unhides it by mistake. For example, you could name the Sheet1 of your addin "Parameters" and store on each line, the workbook name in column A and the parameter in column B.
By the way, this makes sure that the data is not lost if an error in the code causes all the variables to be reset.
Alternatively, if you need that setting to be available after closing and reopening Excel, which does not seem to be the case, you could create a very hidden sheet in the workbook and store your data there, but that requires changing that workbook.
Upvotes: 0
Reputation: 1935
I had a project where I needed to send out sheets with settings but the macros were in my master sheet, not the distributed sheets.
I found storing the settings in a named range worked very well. You can store any string, number or formula and you can even use the values in the sheet if required.
Upvotes: 0
Reputation: 27478
To get you at least part way there:
In Module1 just have the line:
Public ActiveWS As cCustomSheet
Notice that it's now declared as Public.
In the ThisWorkbook module try this code:
Private Sub Workbook_Open()
Set ActiveWS = New cCustomSheet
End Sub
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Set ActiveWS.WS = ActiveSheet
With ActiveWS
Debug.Print .WS.Name
.Setting1 = "something important about this sheet"
End With
End Sub
The thing to note is you'll lose whatever is in Setting1 for one sheet once you activate the next, but if you just want to access the properties while the sheet is active, this should do it. If not, you can add all the sheets to a Collection or Dictionary, which will keep the properties for all of them accessible as long as the Collection or Dictionary exists. So... let us know a little more about your goals here and I'll try to help you think through the best option.
EDIT: In a more general answer to your question, I tend to store settings in worksheet names, which can be completely hidden from users if desired. This could be a good way to go especially if you need the settings to persist between times that the workbook is opened.
Upvotes: 4