I am running a [Edit] read-only (3rd party!) [/Edit] SQL database, an xlsm, an xls (saved copy of the xlsm, just without macros), and an mdb (Access database).
They are linked as follows:
The xlsm gets data from the SQL database every 5 minutes by Application.OnTime code, triggered on Workbook_Open.
The xlsm then saves itself as a 2003 xls.
Since the code modules still exist at that moment (the workbook is not yet closed), I can open the Access mdb and refresh the Excel link to a table in the 2003 data, then close Access.
I then reopen the xlsm, triggering a new Application.Ontime instance.
I finally close the 2003 xls workbook.
This sequence runs during office hours and at the first run after 5pm sets a timer to start the process again in the morning.
My problem is whenever I open a file with a connection or link to the xlsm, the Workbook_Open event seems to trigger and I end up with the 2003 xls open on the 'client' computers. I know it's not just a leftover Application.OnTime on mine (the PC I originally created the files on) because now it's in use and other clients who have never opened the xlsm get the 2003 file randomly popping up when they're using Excel.
If that's not enough to trigger someone to know what's going on, I'll happily post code - but I am hoping someone has seen this before or knows of this rookie mistake and can simply give me a line I'm missing.
Thanks so much for your help!
I would think the reason the XLS pops up on your clients is because Excel has to open the linked XLSM in order to access the data, and as such, Workbook_Open gets triggered.
A few alternatives to the suggestions you have in the comments;
Check Environ("Username") before executing Application.OnTime so that it will only run if the file is opened by specific users.
Use a launcher-file to open the XLSM in "admin mode" - you can do this by using the launcher-file to set a Global-scope variable, and then have the XLSM check this variable before running Application.OnTime.
Make the XLSM test for some dummy-file on the local computer - one that you easily can create by hand on the computer you need regular access to the XLSM on. For example the XLSM can look for C:\Data\xlsm-enabler.txt or whatever works, and only run the relevant macro if the file exists.
Similar to the above, use SaveSetting to set a registry key on the "admin" machine(s) and check against this inside the XLSM.
Set your XLSM up to accept parameters, and use such parameters to open the file in "admin mode". This method is outlined several other places # SO, like here.
This is more of a hunch - you might be able to leverage the Workbook.ReadOnly property in your XLSM as a conditional. This assumes that Excel opens the XLSM in readonly-mode when accessing it via data connections, which I don't know whether is actually the case.
An easy solution would be to have all other files link to the .xls file, instead of the .xlsm macro enabled file. Downside to this approach would be that you have to (manually) update all your references.
It would be way easier to do everything in Access. Then if you need to represent the data in Excel you can have a Workbook with a link to the Access table. This removes a step and it uses the right tool for the job. Access is for linking to database tables. Excel is for processing data views.
SQL > Access > Excel
Related
I have created an extensive macro in excel, that I now want to distribute. I decided I want to do this by saving the macro as add in to a shared network, where all of my collegues have access to it. This way maintaining the macro will be way easier, as I am sure that there are plenty of updates, and bugfixing to come.
I have never created an add in before, so I read several online tutorials + stack overflow questions about it. Up until now I always saved my macros in personal.xlsb, likewise with the macro I now want to save as add in.
My first attempt was to simply save the workbook, where I run the macro, as .xlam, which did not work (I guess because the macro was not saved in that workbook, but in the personal.xlsb).
So I deleted the macro from the personal.xlsb, opened a new workbook, opened the VBA editor, created a new module in that workbook and inserted my code. I then saved the workbook as .xlam. I checked that in the VBA Editor the IsAddin is set to True.
From here it gets confusing somehow. When I open the .xlam file there are no worksheets in it, the add-in is loaded, but the macro does not show up in "Macros", even though the code shows up in the Editor.
When
However the .xlam is still empty when I open it - no code to be seen.
When I open another workbook and load the add-in, in the VBA editor the add-in does show up, and the module with the code of the macro is there as well. But when I click on "macro" it does not show up.
When I open a different Excel file, the add-in is loaded as well (in Excel-add-ins the box is ticked), the module does not show up, and in the VBA editor the .xlam also does not show up.
I have saved, closed, opened, and restarted several times. I have checked if the add-in is saved anywhere else - it was, but I deleted all .xlam files (as non of them worked anyway), and repeated my attempts stated above. When I load the .xlam from the shared network it seems to save itself into the addin folder of microsoft (I guess that is what it should do when it is loaded).
I would really appreciate if someone could help me with how to properly set this up.
I have:
a VBA code that runs fine, when I run it as macro.
I want
to save it to a shared network as add-in, and get it to run.
Edit1:
the add-in shows up in the active add-ins section in options:
My macro-enabled workbook has been working fine until recently. It runs fine on my local drive, but no longer saves itself when run from a remote folder. I suspect some recent updates on the server are to blame.
If I open the workbook and press the save button, a pop-up appears with a progress bar for a second or two. This has not happened before, but the pop-up does close and allow me to continue.
When I run the macro in the workbook, the last line is ThisWorkbook.Save. The same pop-up appears and hangs. If I close the pop-up and press the save button, it also hangs now. If I choose File> SaveAs, all I get is a blank page with no folders to choose from.
I have a workaround to copy the workbook to a local folder, run the macro, then copy it back to the remote drive, but this may be difficult for my users to handle.
I made a new workbook with a macro that only calls ThisWorkbook.Save from a single button, and this works fine. The problematic workbook gets data from csv files and copies it into itself. Maybe this is causing a problem? Maybe the macros are too large for the anti-malware software to handle?
Does anyone know what recent changes have been made to Server that would cause my old macro to hang on saving?
I got the macro working, but not sure why.
The problem arose with an inefficient way to merge data from two sheets together. I had been using Find, and changed it to march through the data row by row instead. The saving window still pops up, but only for a second.
I don't know exactly why the old method prevented the workbook from being saved. The main difference is that the Find method uses objects, while the method I changed it to use integers and compare cell contents with an if statement. Maybe the memory was being filled with orphaned objects? I don't see what difference that should make when saving the file. The data in the sheets being saved is the same.
If anyone knows what difference this would make in saving a workbook, please add and answer or comment for posterity. It might help someone with a similar problem.
I have around 10 different excel files. For each file, I have a process saved in notepad
Every day i need to open each file, copy - paste the code from notepad to VB-excel & run the code
Is there any way I can kind of do this in batch file
Something like
Open File1
Run code of File1.
Save File 1
Repeat the same for File 2
Pls help
You should store your macro in a "Personal Workbook" described here.
The macros you store there load together with the Excel application and will be available to all workbooks you open.
In addition to the "Personal Workbook", I may even suggest automating that personal sub to open the workbooks automatically?
This could also potentially just point to a folder and For Each Workbook in definedSelectedWindowsPath
call subToAutomate()
similar to this
BIG thanks to Mr. Newman, he has certainly saved my back from a few sleepless coding problems.
I wanted to save all my VBA Project in a Excel workbook (or other type of file if possible) and then embbed it to run in another workbook. I've seen topics about it but only found ways to run the macros opening the first sheet.
I want to run a macro from a first workbook in a second one without opening the first workbook to do it. How can I do that?
Save the file with the macros as a xlam file and Excel can load them each time Excel opens.
You need to open File -> options -> add-ins.
At the bottom there is a button Go to (or something, I don't have English Excel on the current computer.)
Then add the file to the list by clicking Browse and finding the file you just saved as xlam file.
Two scenarios comes to mind:
1) You have a second macro for personal use and can save it locally (save in: %USERPROFILE%\AppData\Roaming\Microsoft\Excel\XLSTART). This will allow you to create quick-buttons for your macros, etc. These types of macros open with Excel and will be separate VBA Projects inside of the default VBA editor.
2) You have a network or drive that multiple users need to access, so each user has a macro in their file (.xlsm or .xlsb), where that internal macro reads Application.Run "filepath\workbookname.xlsb!macro", which also allows you to call a private subroutine (note that you could use Call, but Application.Run will ensure that even Private macros are able to be accessed). This shouldn't require the other workbook be open, though I have personally had one user whose computer always opens the other file, regardless.
Edit:
Third scenario (really 2b):
3) You have files where you want to regularly access another file... you will follow a similar approach to point 2 where you make a macro to Application.Run, though you can save that macro in your XLSTART folder... this will allow you to have a source macro location where others may also want to access and utilize. The source document would allow you to maintain 1 file for many users.
Your answers were great! Great to know about XLSTART folder from #Cyril, but based on #Andreas answer I found my path.
The "problems" with adding an Add-In as #Andreas said, are cause my VBA Project would be avaliable on the VB Editor to every workbook on that computer, and to run my macros I'd have to use Application.Run("workbook.xlam!Macro").
Then I found References, which I have the same features, including I can delete my .xlam file to remove my code, and don't have the problems I mentioned above.
Adding my VBA .xlam file as an reference, it'll be avaliable only to that specific workbook and I can run my macro just like it was on the same workbook.
For general knowledge:
ADDING A REFERENCE:
1- Save your project as an Excel Add-In (.xlam file)
2- Open your target workbook, go to the Visual Basic Editor
3- Go to Tools > References > Browse... find your .xlam file and make sure it's checked.
4- Done! Now you'll see the project on the editor and can run your macros just like it was on the same workbook.
I need to modify Excel workbooks from within VBA itself, where the user will point out which workbook to modify, after which a copy of the workbook will be modified and saved under a new name. This can be either an already open workbook, or a closed one on disk, and I need to support all workbook types from 2000 onward (2000-2016, binary, add-ins, templates, etc.). I need to modify the workbook's content as well as any custom UI (ribbon xml) in it. This all has to be done from random Excel installations not under my control.
The problem I'm facing is dealing with password protected workbooks - encrypted ones, i.e. a password for opening. My code needs to be able to handle those, and ideally apply any used password to the saved, updated copy as well.
The code flow is as follows:
let the user select the workbook to modify (via a form)
if the workbook is open:
.SaveCopyAs it to a temp folder
point to the saved copy for further processing
open the user-selected file in a 2nd instance of Excel (invisible)
update the opened temp copy's content
.SaveAs the temp copy to a temp folder without a password and close it
update the closed temp copy's custom UI
re-open the updated temp copy and .SaveAs it again with any password that was on the original workbook
With step 2.1 above, the .SaveCopyAs will save the open workbook and apply any password to the copy as well, which results in step 3 asking for the password in all cases. I cannot remove the pass in step 2.1 by using a .SaveAs, since that will result in the open workbook not being open anymore in the end. It would also only be a half-measure since it doesn't stop the same thing happening with closed files.
In this case, when Excel asks the user for the password (in Excel 2010 at least), the password prompt only shows the filename of the file with an edit box for the pass, all with a popped-up empty 2nd Excel window beneath it open, which is an ugly sight to behold. And it doesn't allow me to capture the entered password as well for step 7.
The best I can do I think is to detect when a closed workbook on disk is encrypted, and show my own password prompt instead before trying to open it. But how to do this? These are the options I can come up with;
When I use Workbooks.Open(Filename:=...), then Excel shows the password prompt, which I like to evade by asking for any pass beforehand myself.
When I use Workbooks.Open(Filename:=..., Password:="notthepassword"), at least Excel won't show a password prompt anymore, workbooks without a password open fine, and those with a pass now generate error 1004. However, I can't act on that to infer that a password is needed, since 1004 is Excel's catch-all error number, and I cannot inspect the Err.Description either for "wrong password" or such, since I do not know the Excel GUI language running on the client. And then there's also Check whether Excel file is Password protected ; when encrypted files have workbook structure protection on as well, apparently Excel won't open them anymore this way - I tested this and it does work with my 2010 Excel, but it's not very encouraging to hear.
Ignoring the ugliness of Excel asking for the pass, reading any Workbook.PasswordXxx property afterwards doesn't reveal anything; they always return the same values in all cases (with or without a password on the workbook).
For OOXML files (.xlsm / .xlsx etc.) I can inspect the file's zip content beforehand for the presence of the two files "EncryptionInfo" and "EncryptedPackage", indicating the file is encrypted, but what about 2000-2003 (.xls) files? There is Microsoft's documentation on the BIFF file structure used in those files telling to check for a FilePass record in the workbook stream; while I know I could implement that logic (there's e.g. the now unsupported Koogra project), I'd rather just not :) (side-question: since when did Microsoft publish these details without first signing NDA's and jumping through their legal hoops?!)
Does anyone have any insight as to how I can make code step 7. above work, short of just living with Excel's prompt and adding a key logger to my app? :)