Need help to build a solid security system for a workbook

garmont

New Member
Joined
Mar 15, 2006
Messages
5

I am developing an application that i want to keep as secure as possible from piracy. I've built in user id and password. i utilize macros wherever possible, but have relied on a couple of workbook events to handle a lot of the security features. i just found a couple of ways to defeat these events and open the workbook to saves without locking away all the good stuff....
does anyone know how to really lock up a workbook and keep it from being copied when sheets are supposed to get hidden upon closing, along with other security features like time checks, id's, and lockout 'flags'???
thanks,
garmont
 

Excel Facts

Do you hate GETPIVOTDATA?
Prevent GETPIVOTDATA. Select inside a PivotTable. In the Analyze tab of the ribbon, open the dropown next to Options and turn it off
The trick is not to only integrate the workbook into your exe, but to also keep all of your code out of the workbook and in the exe.
 
Upvote 0
You all have left me in the dust, but have given me a lot of links and good ideas to pursue. Many thanks for all your responses.
Any suggestions on how best to learn "up to" what you're dealing with are most welcome.
 
Upvote 0
After hours reviewing past posts (about my totally unoriginal excel security question) I think i get it....
I'd like to be certain about the same password issues with addin's: I would assume that the encrypted file open password (available in the tools menu under SaveAs...) is susceptible to the same near-instantaneous pw breaking algorithms that open the workbook and VBA passwords.
Am I correct?

My application can use all of its macros from an addin or other linked resource. I am still looking for ways to use excel workbook for the user interface, not too worried about its security since no features will work without the macros. So if i can do the rest in an addin that can be encrypted, i might be ok.

Does anyone have experience with Visual Baler sw re: these security problems?
 
Upvote 0
In answer to PM's by garmont and shajueasow and also the surprise I had of so little information on how to place VBA code into an ActiveX dll and then use it from VBA. This is a very oversimplified example because there are just too many little points to try and cover. If you guys want to post your code that you wish to place in a dll, I'll try and help you more specifically. I use several custom activex dll's in place of Personal.xls for several reasons. The code runs much faster, is only loaded as needed, and contains functionality available in VB that is not available in VBA. Especially forms development without all of the API calls. In many cases, I have found that creating a COM add-in is too bloated for what I needed and, therefore, simply placed the code into an undressed dll.

This is the most basic example to show you how easy it is. Well, how easy it can be until your try to distribute it. :)

Using this method, you will not need to register or install anything. The only prerequisite on the target machines would be the VB runtime and the dll file remaining in the same or relative path to the workbook.

<table border="1" bgcolor="White"><caption ALIGN=left><font size="2" face=Courier New>Example VBA Code:</FONT></caption><tr><td><font size="2" face=Courier New>  <font color="#0000A0">Option</font> <font color="#0000A0">Explicit</font>
  
        <font color="#008000"> '****************</font>
        <font color="#008000"> ' Main Function *</font>
        <font color="#008000"> '****************</font>
  
         <font color="#0000A0">Function</font> SpellNumber(ByVal MyNumber)
             <font color="#0000A0">Dim</font> Dollars, Cents, Temp
             <font color="#0000A0">Dim</font> DecimalPlace, Count
  
             <font color="#0000A0">ReDim</font> Place(9) <font color="#0000A0">As</font> <font color="#0000A0">String</font>
             Place(2) = " Thousand "
             Place(3) = " Million "
             Place(4) = " Billion "
             Place(5) = " Trillion "
  
            <font color="#008000"> ' String representation of amount.</font>
             MyNumber = Trim(Str(MyNumber))
  
            <font color="#008000"> ' Position of decimal place 0 if none.</font>
             DecimalPlace = InStr(MyNumber, ".")
            <font color="#008000"> ' Convert cents and set MyNumber to dollar amount.</font>
             <font color="#0000A0">If</font> DecimalPlace > 0 <font color="#0000A0">Then</font>
                 Cents = GetTens(Left(Mid(MyNumber, DecimalPlace + 1) & _
                     "00", 2))
                 MyNumber = Trim(Left(MyNumber, DecimalPlace - 1))
             <font color="#0000A0">End</font> <font color="#0000A0">If</font>
  
             Count = 1
             <font color="#0000A0">Do</font> <font color="#0000A0">While</font> MyNumber <> ""
                 Temp = GetHundreds(Right(MyNumber, 3))
                 <font color="#0000A0">If</font> Temp <> "" <font color="#0000A0">Then</font> Dollars = Temp & Place(Count) & Dollars
                 <font color="#0000A0">If</font> Len(MyNumber) > 3 <font color="#0000A0">Then</font>
                     MyNumber = Left(MyNumber, Len(MyNumber) - 3)
                 <font color="#0000A0">Else</font>
                     MyNumber = ""
                 <font color="#0000A0">End</font> <font color="#0000A0">If</font>
                 Count = Count + 1
             <font color="#0000A0">Loop</font>
  
             <font color="#0000A0">Select</font> <font color="#0000A0">Case</font> Dollars
                 <font color="#0000A0">Case</font> ""
                     Dollars = "No Dollars"
                 <font color="#0000A0">Case</font> "One"
                     Dollars = "One Dollar"
                 <font color="#0000A0">Case</font> <font color="#0000A0">Else</font>
                     Dollars = Dollars & " Dollars"
             <font color="#0000A0">End</font> <font color="#0000A0">Select</font>
  
             <font color="#0000A0">Select</font> <font color="#0000A0">Case</font> Cents
                 <font color="#0000A0">Case</font> ""
                     Cents = " and No Cents"
                 <font color="#0000A0">Case</font> "One"
                     Cents = " and One Cent"
                 <font color="#0000A0">Case</font> <font color="#0000A0">Else</font>
                     Cents = " and " & Cents & " Cents"
             <font color="#0000A0">End</font> <font color="#0000A0">Select</font>
  
             SpellNumber = Dollars & Cents
         <font color="#0000A0">End</font> <font color="#0000A0">Function</font>
  
  
  
        <font color="#008000"> '*******************************************</font>
        <font color="#008000"> ' Converts a number from 100-999 into text *</font>
        <font color="#008000"> '*******************************************</font>
  
         <font color="#0000A0">Private</font> <font color="#0000A0">Function</font> GetHundreds(ByVal MyNumber)
             <font color="#0000A0">Dim</font> Result <font color="#0000A0">As</font> <font color="#0000A0">String</font>
  
             <font color="#0000A0">If</font> Val(MyNumber) = 0 <font color="#0000A0">Then</font> <font color="#0000A0">Exit</font> <font color="#0000A0">Function</font>
             MyNumber = Right("000" & MyNumber, 3)
  
            <font color="#008000"> ' Convert the hundreds place.</font>
             <font color="#0000A0">If</font> Mid(MyNumber, 1, 1) <> "0" <font color="#0000A0">Then</font>
                 Result = GetDigit(Mid(MyNumber, 1, 1)) & " Hundred "
             <font color="#0000A0">End</font> <font color="#0000A0">If</font>
  
            <font color="#008000"> ' Convert the tens and ones place.</font>
             <font color="#0000A0">If</font> Mid(MyNumber, 2, 1) <> "0" <font color="#0000A0">Then</font>
                 Result = Result & GetTens(Mid(MyNumber, 2))
             <font color="#0000A0">Else</font>
                 Result = Result & GetDigit(Mid(MyNumber, 3))
             <font color="#0000A0">End</font> <font color="#0000A0">If</font>
  
             GetHundreds = Result
         <font color="#0000A0">End</font> <font color="#0000A0">Function</font>
  
        <font color="#008000"> '*********************************************</font>
        <font color="#008000"> ' Converts a number from 10 to 99 into text. *</font>
        <font color="#008000"> '*********************************************</font>
  
        <font color="#0000A0">Private</font> <font color="#0000A0">Function</font> GetTens(TensText)
             <font color="#0000A0">Dim</font> Result <font color="#0000A0">As</font> <font color="#0000A0">String</font>
  
             Result = "" ' <font color="#0000A0">Null</font> out the temporary function value.
             <font color="#0000A0">If</font> Val(Left(TensText, 1)) = 1 <font color="#0000A0">Then</font> ' <font color="#0000A0">If</font> value between 10-19...
                 <font color="#0000A0">Select</font> <font color="#0000A0">Case</font> Val(TensText)
                     <font color="#0000A0">Case</font> 10: Result = "Ten"
                     <font color="#0000A0">Case</font> 11: Result = "Eleven"
                     <font color="#0000A0">Case</font> 12: Result = "Twelve"
                     <font color="#0000A0">Case</font> 13: Result = "Thirteen"
                     <font color="#0000A0">Case</font> 14: Result = "Fourteen"
                     <font color="#0000A0">Case</font> 15: Result = "Fifteen"
                     <font color="#0000A0">Case</font> 16: Result = "Sixteen"
                     <font color="#0000A0">Case</font> 17: Result = "Seventeen"
                     <font color="#0000A0">Case</font> 18: Result = "Eighteen"
                     <font color="#0000A0">Case</font> 19: Result = "Nineteen"
                     <font color="#0000A0">Case</font> <font color="#0000A0">Else</font>
                 <font color="#0000A0">End</font> <font color="#0000A0">Select</font>
             <font color="#0000A0">Else</font> ' <font color="#0000A0">If</font> value between 20-99...
                 <font color="#0000A0">Select</font> <font color="#0000A0">Case</font> Val(Left(TensText, 1))
                     <font color="#0000A0">Case</font> 2: Result = "Twenty "
                     <font color="#0000A0">Case</font> 3: Result = "Thirty "
                     <font color="#0000A0">Case</font> 4: Result = "Forty "
                     <font color="#0000A0">Case</font> 5: Result = "Fifty "
                     <font color="#0000A0">Case</font> 6: Result = "Sixty "
                     <font color="#0000A0">Case</font> 7: Result = "Seventy "
                     <font color="#0000A0">Case</font> 8: Result = "Eighty "
                     <font color="#0000A0">Case</font> 9: Result = "Ninety "
                     <font color="#0000A0">Case</font> <font color="#0000A0">Else</font>
                 <font color="#0000A0">End</font> <font color="#0000A0">Select</font>
                 Result = Result & GetDigit _
                     (Right(TensText, 1)) ' Retrieve ones place.
             <font color="#0000A0">End</font> <font color="#0000A0">If</font>
             GetTens = Result
         <font color="#0000A0">End</font> <font color="#0000A0">Function</font>
  
  
        <font color="#008000"> '*******************************************</font>
        <font color="#008000"> ' Converts a number from 1 to 9 into text. *</font>
        <font color="#008000"> '*******************************************</font>
  
         <font color="#0000A0">Private</font> <font color="#0000A0">Function</font> GetDigit(Digit)
             <font color="#0000A0">Select</font> <font color="#0000A0">Case</font> Val(Digit)
                 <font color="#0000A0">Case</font> 1: GetDigit = "One"
                 <font color="#0000A0">Case</font> 2: GetDigit = "Two"
                 <font color="#0000A0">Case</font> 3: GetDigit = "Three"
                 <font color="#0000A0">Case</font> 4: GetDigit = "Four"
                 <font color="#0000A0">Case</font> 5: GetDigit = "Five"
                 <font color="#0000A0">Case</font> 6: GetDigit = "Six"
                 <font color="#0000A0">Case</font> 7: GetDigit = "Seven"
                 <font color="#0000A0">Case</font> 8: GetDigit = "Eight"
                 <font color="#0000A0">Case</font> 9: GetDigit = "Nine"
                 <font color="#0000A0">Case</font> Else: GetDigit = ""
             <font color="#0000A0">End</font> <font color="#0000A0">Select</font>
         <font color="#0000A0">End</font> <font color="#0000A0">Function</font>
  
</FONT></td></tr></table>

Take the above function from MS. This is a UDF that you would place in a standard module within a workbook. You would then call it from some cell as such:

=SpellNumber(A1)

What if you wanted a bit more security than is offered by VBA? You could place the code into a dll.

From VB. New project, ActiveX Dll. Name the class "Functions". Name the project "MyFunctions". Paste the above UDF into your class module named "Functions". Still from VB... File menu, Make "MyFunctions.dll..", save to the same folder as your workbook. This is not neccesary but for ease in this example.

Now from VBA. Tools, references, Browse. Locate the dll you just created and set a reference to it.

Delete the SpellNumber UDF in the workbook. Replace it with this code:

<table border="1" bgcolor="White"><caption ALIGN=left><font size="2" face=Courier New>Example VBA Code:</FONT></caption><tr><td><font size="2" face=Courier New>  <font color="#0000A0">Function</font> SpellNumber(ByVal MyNumber)
       <font color="#0000A0">Dim</font> mf <font color="#0000A0">As</font> <font color="#0000A0">New</font> MyFunctions.Functions
       SpellNumber = mf.SpellNumber(MyNumber)
  <font color="#0000A0">End</font> <font color="#0000A0">Function</font>
</FONT></td></tr></table>

Now your code is hidden and not as accessible, will run faster in most cases, and the workbook will generally behave better without the code bloat. There are other things to consider as well. Good and bad.

Briefly. Distributing is easy in this case as long as Excel can find the dll in the expected path. Excel will register the file for you.

To debug these types of projects, set a reference to the VBProjectfile, "MyFunctions.vbp", run it, and then call it from Excel. You can step through the code between VBA and VB just as you would in VBA alone. Note that both devlopement evironments need to be open at the same time. There are tricks and troubles but you can just ask if you have any problems.

Also, note that we did not use anything in Excel's object model in the above example. Most of your code will doubtless use many objects within Excel's and Office's libraries. Converting your VBA to VB code is usually as simple as adding a reference to Excel and then fully qualifying your objects. You will need to distribute the lib and exp files along with your dll as well.

ActiveX Dll Example.zip

The download example will extract all of the files into several folders including the vb project files...

Edit: If you do need to register your dll...

Hi Gary.

No. Your users do not need VB installed. They will need the VB6 runtime files, but very, very rare is the windows system that does not have these files. In fact, the only way a computer that is updated periodically would not have these files is if somebody purposely did not want them there. Make sure the reference to your dll is valid on the target PC. If we need to register the dll you can add some simple code to register it. We should not have to register the file, but I always do register the dll's and place them in the system folder when I distribute an application. Here is some sample code that will register the dll if there is a certain error...

Assumes an activex dll named "MyFunctions.dll" located in the workbook's path. An installation procedure might be a simple VB Script file that would move the dll to the target system's system folder, register it, and update the regerence in your workbook. Very easy. If you need any help, just reply...

<table border="1" bgcolor="White"><caption ALIGN=left><font size="2" face=Courier New>Example VBA Code:</FONT></caption><tr><td><font size="2" face=Courier New> <font color="#0000A0">Function</font> SpellNumber(ByVal MyNumber)
<font color="#0000A0">On</font> <font color="#0000A0">Error</font> <font color="#0000A0">GoTo</font> Err_SpellNumber
<font color="#0000A0">Dim</font> mf <font color="#0000A0">As</font> <font color="#0000A0">New</font> MyFunctions.Functions
<font color="#0000A0">Dim</font> RegServerFailed <font color="#0000A0">As</font> <font color="#0000A0">Boolean</font>

SpellNumber = mf.SpellNumber(MyNumber)

<font color="#0000A0">Exit</font> <font color="#0000A0">Function</font>
Err_SpellNumber:
<font color="#0000A0">If</font> Err.Number = 429 <font color="#0000A0">Then</font>
<font color="#0000A0">If</font> RegServerFailed <font color="#0000A0">Then</font> <font color="#0000A0">Exit</font> <font color="#0000A0">Function</font>
<font color="#0000A0">Call</font> RegServer(Chr(34) & ThisWorkbook.Path & "\MyFunctions.dll")
RegServerFailed = True
<font color="#0000A0">Resume</font>
<font color="#0000A0">End</font> <font color="#0000A0">If</font>
<font color="#0000A0">End</font> <font color="#0000A0">Function</font>

<font color="#0000A0">Private</font> <font color="#0000A0">Sub</font> RegServer(DllPath <font color="#0000A0">As</font> String)
<font color="#0000A0">Call</font> Shell("REGSVR32.EXE /s " & Chr(34) & ThisWorkbook.Path & "\MyFunctions.dll")
<font color="#0000A0">End</font> <font color="#0000A0">Sub</font>

</FONT></td></tr></table>

You may simply want to register the dll on workbook open.

<table border="1" bgcolor="White"><caption ALIGN=left><font size="2" face=Courier New>Example VBA Code:</FONT></caption><tr><td><font size="2" face=Courier New> <font color="#0000A0">Private</font> <font color="#0000A0">Sub</font> Workbook_Open()
<font color="#0000A0">Call</font> Shell("REGSVR32.EXE /s " & Chr(34) & ThisWorkbook.Path & "\MyFunctions.dll")
<font color="#0000A0">End</font> <font color="#0000A0">Sub</font>
</FONT></td></tr></table>
 
Upvote 0

Forum statistics

Threads
1,221,497
Messages
6,160,152
Members
451,625
Latest member
sukhman

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top