Executing a macro in another workbook - vba

I'm doing an internship as a student developer and I have to program something that will automatically analyse spreadsheets every month.
I will have an Excel file that the users will open, and after typing the name of the files he wants to analyse and compare, generate graphs and other statistics.
Completely new to VBA (I only learned C#, PHP and Python at school), I figured out how to open a new Excel file with workbooks.open, but running a macro after opening a file won't work.
I guess it may be because my macros aren't recorded on those other files, but I need my program to work even after I'm gone, and I can't tell my users to copy the macros into new files every month.
I'm also looking into passing variables between workbooks, since for statistics purposes, I will have to retrieve, for instance, the value of cell G22 in every file opened and copy them in my primary file in order to make a graph out of those values.
Can someone point me in the right direction?

If you make a function or sub public you should be able to call it from another workbook, provided both are open.
public sub testMessage(input as string)
msgbox input
end sub

Related

Prevent >1 person from running VBA macro at a time (shared wkb)

What I'm aiming at is getting a list of all currently running scripts in order to check if other users aren't running the same VBA macro at the same time (and if yes, then stop the code etc., similar to what the OP of the below question wanted). This would be for a shared workbook (I learned it's not designed for this type of work, but I need to try it).
https://stackoverflow.com/a/36116091/5947935
I've been trying to make the code in the above answer work in VBA, but it seems it's a vbs thing and I would like to avoid that.
I'm not an expert to say the least, so I'm having trouble understanding how to get this to work in Excel VBA. I don't even know if it's possible at all.
I've found this as well: VBA Getting program names and task ID of running processes and it works fine but it only lists the running processes.
I've no idea however how to merge the two... or even if the WMI is the correct way to go.
I'd appreciate any sort of help.
I used to create a "locking file" which was just an empty text file with the name of the workbook followed by the username and an extension of .LCK
First thing my code did on auto open was look for a locking file then report back to the user which user had it open then cancel the open.
If it didn't find a locking file then it created one and proceeded as normal. If it found one but it was the same username (ie that user had it crash on them) it proceeded with the open.
The last thing the code did was delete the file.
No codes here and theory not tested yet, but the idea of preventing a different user executing a Macro on a shared workbook requires some thinking.
I would create a hidden worksheet, and use one of the cells to store the Environ("USERNAME") when the macro is first started - to indicate who has it running, then clear it when complete, first-in-first-out.
Lets say named range MUser (macro user) is range A1 in that hidden worksheet
When the macro runs, it will first check if MUser is empty, if so then change it's value to Environ("USERNAME") and Save the file before next step (here I am not certain the value is updated on others session).
If MUser is not empty, either abort or retry in a few second.
When macro completes, MUser will be ClearContents, and save the File to free up the workbook for macro.
Idea is here but please test. Post your own code for us to troubleshoot. You may also use Workbook events to "lock" the macro execution this way. Or even use this hidden sheet to make a log record for debug. Also some fail-safe needs to be implemented (such as a time stamp at macro start and override the lock after some minutes).

Delete excel workbook connection on external document or launch VBA on external file

I am facing a problem with excel files given to managers. They have copied files to their computers and in these files are already written workbook connection string. But files in our server were updated, we put versions on them, however people are lazy to download them from server. Is there a way to launch through group-policy (or any another way) an VBA script that could delete workbook connection strings if version of file does not match the one that is placed in server??
VBA is easy, but do not know how to launch automatically on external files.
sub deleteConnections()
For Each cn In ThisWorkbook.Connections
cn.Delete
Next cn
end sub
Assuming it's not impossible, you could put that code within
Private Sub Workbook_Open()
End Sub
In ThisWorkbook section of each file. It would delete the connection on opening. If you'd add some code to compare the files with the ones on server, then that would do exactly what you're looking for, though not exactly the way you've asked

Can you schedule periodic data imports in VBA?

I have a VBA function that, when invoked via a button on a sheet, extracts a .csv file from a website and imports it into my workbook. The problem is the file is uploaded in different time intervals during the day, so I have to periodically check the website.
Is there a way in VBA that I can schedule when a function is invoked?
You can use the Application.OnTime() method which will allow you to schedule a Macro for a specific time amongst other settings. However you're probably best using VB Script or similar.
It's also important to note that the workbook would need to be open the entire time if you are going to use VBA, whereas a VBS file will run silently and can be triggered to run at startup.
If you're proficient enough with VBA then you shouldn't have a problem writing VBS.

Excel. Use vba to record when someone removes the shared feature

We have a problem at work. Im not sure if this is due to an individual or the system admin applying patches during working hours but... we use an Excel sheet at work to track engineering work. It is a shared workbook so that multiple people can work at any time and is working well. Recently people have been losing their work because something is removing the shared status from the file during the day. It is only discovered when people go to save their work or open the workbook again after lunch. Is it possible to write a macro that records when the shared feature is applied or removed. I assume it is a property of the workbook collection/object but cant see how to do it from the docs
Take a look at the Workbook.MultiUserEditing property.
This code snippet (from Microsoft help) would save the workbook in shared mode if the workbook is not currently in shared mode.
If Not ActiveWorkbook.MultiUserEditing Then
ActiveWorkbook.SaveAs fileName:=ActiveWorkbook.FullName, _
accessMode:=xlShared
End If
You may consider placing this code (or similar) in the Workbook_BeforeClose() event or other relevant event.

Copy Range from Form, and Paste into Workbook (preferably closed)

I have a macro-enabled form that is intended to allow of a team of data-entry staff to record their daily efforts by transaction number. As forms go, it's pretty basic. However, I need to write a macro for a button that will let each person submit their records to a master sheet at the end of their shifts. I need to copy the range data and paste to a master workbook, with the person's name and the date being added to the individual rows.
I'm not sure how to facilitate the copy and paste to a closed workbook, or how to prevent problems with multiple people submitting to the form at the same time. Can anyone offer any suggestions please?
Make it update a database and then generate the report at the end of the day from that. I would also recommend that it inserts into the database each time the user inputs a record so that in the case of a power outage, all of their work from the day doesn't get lost. This will likely reduce the amount of concurrency issues too as the users will be periodically adding records instead of many records at the same time. Search 'VBA DAO' or 'VBA ADODB' to find examples on how to connect to a database with VBA.
You can do this simply by opening the workbook, inserting, and then closing the workbook. There is no simple way to insert into a closed workbook. Note, you could keep things hidden if you're trying to hide things from the user.
Add a reference to the "Microsoft Scripting Runtime" to get access to the filesystem and then use a simple file semaphore to control access to the common workbook.
Regarding the closed workbook, you use Application.Workbooks.Open(...) and .Close
Primary Choice would be to send the items to a database. Since thats already ruled out, I would suggest you write the data to a plain old .csv file. This will be easier to implement, and will not be limited by excel row limits.