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

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.

Related

How to save two workbooks as and mirror the connections that they contain

I need some conceptual help from those more experienced than me --
I know you guys usually like code but I have many pages of code on this project and my question is not regarding any code I have but rather how I might code something I have not been able to figure out.
So basically I have two workbooks whose main purpose is labor tracking. one is the control workbook that has all my code, the other is a workbook where reports are made by field workers. The reason the field workbook cannot have code is because it will be operated from an ipad which I believe cannot yet run VBA. I know how to establish the connections necessary, however for every project a new copy of both the workbooks need to be made. I already have functions that clear out, reset and save the main workbook however I am struggling with the connected workbook. I know how to save the connected workbook, but I was hoping to preserve the connections between the two old workbooks when I run the macro that saves them as and also mirror those connections between the new workbooks. Is this possible or will I need clear all connections and re establish them every time a new set of job books needs to be created?
===> EDIT: I believe that I need to embed the report book into the main book, but that still begs the question on how I save the embedded workbook as at the same time I save the main workbook as in order to create a new book with all the same connections

Speed up Excel 2016 Query Refresh Time when Importing Tables from Access 2016

I have a system where there are about 30 Excel 2016 templates that all pull prices for the items on each template from a single, master Access 2016 file. These are all located on a server that anyone with access may open. The templates are used to request specific items to be sent to a job site, while also tracking its price so it can be charged to that job. The goal of having a single master file with all the pricing is so that every time a price changes (which is fairly often), I don't have to update the price in every single template.
Right now, I have an Auto_Open module in each of these forms that refreshes the data from the Access file every time a copy of the template is opened. This ensures that the prices for the items that the project managers request for their job is updated every time they use the sheet. This usually completes in less than a second, and it updates all the information just fine. Here's the code:
Sub Auto_Open()
Application.ScreenUpdating = False
Sheets("Import Sheet").Unprotect Password:="secret"
Sheets("Import Sheet").Visible = True 'for some reason the data doesn't like to refresh unless the sheet is visible
ThisWorkbook.RefreshAll
Application.CalculateUntilAsyncQueriesDone 'ensures every connection refreshes
Sheets("Import Sheet").Visible = False
Sheets("Import Sheet").Unprotect Password:="secret"
Application.ScreenUpdating = True
End Sub
Recently, Microsoft put out an update to Excel that combines data imports and transformations into a new single section under the Data tab called "Get and Transform Data." Along with this update, new wizards were released to import data under the "Get Data" button in this section. The old "Legacy Wizards" are still available, which is what I was using and what has been working with the above code.
I looked for information on this new tab, but the only usable info was a Microsoft support web page, and it shows the old organization with separated sections, found here. So, I did my own testing, and I found the following differences:
It's possible to change how the data imports in the new wizard, i.e. I can delete rows and columns that I don't want. (This is particularly valuable for what I'm doing since some of the information for each item isn't used to calculate price, such as the supplier or the individual break down for shipping and the actual cost of the item).
I can't have a password on the new wizard, it doesn't let me open the Access file if it is password-protected. If someone has a solution to this one too, that'd be great.
The connection types are different. In the legacy wizards, the connection type is simply "Microsoft Access Database." However, the new wizards show the connection type as an "OLE DB Query."
Finally, the legacy wizard shows the import as a "connection," while the new wizard imports it as a "query."
My worry is that in the next version of Excel, the legacy wizards will no longer be available, so I would like to update to the new wizards. Further, it would also be beneficial to be able to only import specific rows and columns out of the Access file, which I can't do using the legacy wizards.
However, one of these template sheets imports 11 different tables, which ended up taking about 30 seconds to update when I tried opening a new worksheet based off of the template. This is way too long to be efficient or worth the benefits of the new wizard.
In the connection properties of the tables imported with the new wizard, there's a few options that I messed around with. First, I deleted my Auto_Open module and tried to use the "Refresh data when opening the file" option, this ended up taking a minute to update all of the tables, and it forced me to unlock the sheet, which I would strongly prefer to remain locked. Second, I tried the "Enable Fast Data Load" and "Enable background refresh," and I was able to get it down to 17 seconds, but that still is a pretty long time to wait every time you open a file. I would also prefer not to use background refresh, since the time spent on each sheet may not be enough to guarantee every price is updated, especially on some of the files with 10+ imported tables. Anyway, I attempted ever possible combination and I was only able to reduce the time to, on average, 20 seconds.
I guess the big questions of this post are:
How can I speed up the refresh time for the imported tables when I use the new wizards? And if I can't, how can I ensure that I will still have access to the legacy wizards?
Is it possible to lock an Access file while using the new wizards, and how do I do that?
The CAD technician that I work with is also communicating with some of his contacts within Microsoft to see if he can get any information about the future availability of the legacy wizards. If necessary, I can comment a few example files (with fake prices, obviously) so anyone can mess around with them.
Any help is greatly appreciated. Thank you!
If you can use .xlsm files, then you should use ADODB for connecting to the database.
Here is a good tutorial:
http://www.onlinepclearning.com/import-from-access-to-excel/
You can execute SQL statments to modify the database.
However if your database is password protected you will need to include that in the connection string,
and since it is very easy to crack protected vba projects, the password will not be safe at all.

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).

Is there any way to block a workbook from "external" access?

first time asking something here, so I'll apologize beforehand in case I do anything I shouldn't do.
I'm working on a workbook and there are some information in it that shouldn't be available to everyone else, save a few users.
While doing some testing around I've found that it was possible to use another instance of Excel, i.e. another workbook, to access that information (in this case, using VBA).
What I want to know is: is it possible to block another instance of Excel or another workbook from accessing this workbook with the information I want to protect?
The point of this sheet in working on is to be used as a 'database' of sorts for performance feedback of other employees. They fill a form with their self evaluation and then their manager also fill it, evaluating them. All this is stored in a sheet, which is hidden (veryhidden, to be more specific). Using a simple login system, I was able to enable access to this sheet to only one user (one with admin privileges), but assuming someone knows the existence of that sheet, it would be perfectly possible for them to, for example, just copy everything from that sheet to a blank sheet in a new workbook.
Ultimately, what I'm trying to achieve is some kind of restriction in this workbook, allowing only it's own subs and functions to work on it
Thanks in advance
EDIT: Added some info. Hope that helped clarify my problem
The only way to achieve this is encryption. As far as I know Excel only supports one form of encryption, full workbook encryption. In that case there is a password to open the workbook, a user either has access to the full workbook or none at all.
Any other form of encryption in Excel, protected cells, passwords on macros, etc. can all be bypassed easily by a knowledgable user.
However, you could achieve this using either an external database server or implementing your own encryption scheme in the workbook.
There is some information here on howto access the Windows CryptoAPI from VBA.

Running a VBA excel macro at a certain time

Trying to figure out the best way to kick off an excel macro at a certain time. I found a few suggestions, but I still have plenty of questions on the idea and was hoping you guys could provide some clarification.
What I am trying to do: I have live excel workbooks that are connected to my database. So at 11:30PM on the last day of every month I want to go into several excel workbooks (I have one for every vendor that we sell), enable the security and editing and refresh the connection so all of the information in the sheets is up to date. Lastly I would like to then save a copy of that file in a sub folder inside the current folder.
Run on time method:
Here is this run on time method that I found on ozgrid. My question is, I am assuming that excel would need to be running at the time in order to execute the method? If so what would be one way of opening up excel and refreshing a workbook to be saved?
Running excel on Windows Task Scheduler Windows Task Scheduler
Essentially this method is using an Excel Controller to run excel using VBS...Seems more promising than the run on time method but I am not very familiar with how an excel controller works or VBS, so any help or ideas on this one would be greatly appreciated.
Any input is greatly appreciated. If my ideas are way out in left field could you guys help point me in the right direction?
Thanks for all the help in advance!
Turn the problem around. Create a workbook with normal Excel query tools and have it load the result set of the query when the workbook is opened (You don't specify a version, but see Refresh an external data connection for Excel 2013).
Then, either create a view in the database that contains the results you require, or to materialise the result of a view into a staging table that is then read by the workbook.
Users can then open the workbook whenever they require data, and the current results will be available. A parametrised version of the query could then access a history table to older periods.
This way all data is only prepared when required, and is always available without the scheduling complexity.