VBA to close excel file when Windows7 computer is locked - windows

I have an excel file on a shared drive used by 6/7 people, however only one person can edit at a time. The frustration comes when one person opens the file for editing then disappears for lunch for an hour, leaving the excel file open and un-editable for other users.
Is it possible for VBA to listen for when a station is locked, and activate a macro accordingly?
Sorry I am not posting any of my own attempts as I'm a bit of a fish out of water with this level of VBA.
Any points that may help get me started would be really useful.

You have a few options:
Kill the co-workers who do this
Have other users create a copy and save-as to then merge latter (quite hacky)
Or you try a timeout - so if the user selects nothing i 10 minutes the workbook closes. Selecting lock would be a issue with security I think and windows wouldnt let you have that kind of power.
So to timeout call a function every ten minutes to check if user has selected any other cells in the worbook.
If difference("n", lastaction , Now) > 10 Then
ThisWorkbook.Close SaveChanges:=True
End If
You can use NOW function in vba to find current date and time and the work out difference with when an action was made to find the value of 'lastaction'. To do this use:
Sub AnAction(ByVal Sh As Object, ByVal Target As Range)
lastaction = now
End Sub
Hopefully that answers your question.

Related

Powershell Script is slow in opening an application

I have a PowerShell script that opens a file when you press a hotkey like: ctrl + alt + f so that the app automatically runs every time the user presses those key combinations.
Now, the problem is that it indeed opens the application/file, but it takes 4-5 second to process it. I want the process to be fast enough so that the script opens the desired files the moment the user presses the key combinations and not seconds after it. I don't know what caused this slowdown...
Here's the script:
# Get the Desktop dir. path.
$desktopDir = [Environment]::GetFolderPath('Desktop')
# Create the shortcut object, initially in-memory only.
$shc =
(New-Object -ComObject 'Wscript.Shell').CreateShortcut("$desktopDir\linkthis.lnk")
# Set the target executable (name will do if in $env:PATH).
$shc.TargetPath = 'C:\Users\abhay\Downloads\Test\script.py'
# Assign the hotkey.
$shc.Hotkey = 'Ctrl+Alt+F'
$shc.Save()
(Code originally taken from this question asked by me earlier)
Edit1:
It isn't just the case with my .py script. It's the same when opening even notepad too! And the script indeed runs fast when I boot up my PC but after some time (2-3min) it causes the delay in opening again. I Just can't figure it out why...
I don't know why it runs fast at the first 1-2 min and then slows down
(Also, running the files manually is quick. It's just slow with the script)
Edit 2
Hey guys, I just discovered that it's just the case with my computer. It's working fine on my dad's PC with pentium processor 🥲 but I still appreciate any fix for my system if possible. Thanks. May god bless you and my father. Things are really wrong with me these days...

How to profile/debug VBA script that works fine on XLS files, but hangs on XLSX files?

I have a VB script that does row processing on a small Excel file (35 columns, 2000 rows, no hidden content). It takes about 3 seconds to process the file when applied to an .xls file. If I save the .xls as a .xlsx file, the same script takes about 30 to 60 seconds, completely freezing Excel several times in the process (although it finishes and the results are correct).
I suspect some loop parts of the code are responsible, but I need to find out which. I have found scripts like https://stackoverflow.com/a/3506143/5064264 which basically amount to timing all parts of the script by hand - similar to printf-debugging, which is not very elegant and also consumes much time for large scripts.
Is there a better alternative to semi-manual profiling, like performance analyzers in most IDEs, or exist any other approaches to this problem? I do not want to post the code as it is rather long and I also want to solve it for other scripts in the future.
yes - kind of. I use this to test how fast things are running and experiment with different approaches to get better timings. I stole this from somewhere here on SO.
sub thetimingstuff()
Dim StartTime As Double
Dim SecondsElapsed As Double
StartTime = Timer
'your code goes here
SecondsElapsed = Round(Timer - StartTime, 2)
MsgBox "This code ran successfully in " & SecondsElapsed & " seconds", vbInformation
end sub
Another EDIT
you could bury debug.print lines sporadically through your code to see how much each chunk takes to execute.
The error in my case was as Comintern's comment suggested - a method was copying whole columns into a dictionary to reorder them, instead of just the cells with values in them. To preserve this for future readers, I am copying his/her excellent comment here, thanks again!
An xls file has a maximum of 65,536 rows. An xlsx file has a maximum of 1,048,576 rows. I'd start by searching for .Rows. My guess is that you have some code iterates the entire worksheet instead of only rows with data in them.
As for generic profiling or how to get there, I used a large amount of breakpoints in the editor (set/remove with left-click in the line number column of the code editor):
I first set them every 20 lines apart in the main method, ran the program with the large dataset, then after each press of continue (F5) manually measured if it was slow or not.
Then I removed the breakpoints in the fast regions and added additional ones in the slow regions to further narrow it down into methods and then into lines inside the methods.
At the end, I could verify if by commenting out the responsible line of code and fix it.

Using VBScript to control an MMC object

Alright, so, I'm working on a script to execute some commands in an MMC Snapin, and I'm not very experienced with doing this kind of scripting, but i've made a lot of progress...the problem I am having, is if I create a new object every time the script runs, it will massively delay my overall script while the snapin and everything in it loads(which can take as long as five minutes). If it could load the snapin content once and then just take control of it as needed, and only create a new object IF there's not one open already, I'll save a massive amount of time when I run the script sometimes 100 times in a day.
The problem is, I'm not entirely certain how to achieve this. I thought, after some research, that it would be GetObject, but when I do
Dim objMMC
Set objMMC = GetObject("", "MMC20.Application")
It seems to create a new mmc window with no snapins loaded, rather than get the existing one with snapins loaded that I want.
Any advice? Am I just totally off base here, using completely the wrong command, or is there some simple change that I can make to fix this?
Edit:
Is there some weird workaround way I could achieve this, like storing an object to a temporary file so i can at least reuse it through a single session.
I'm in a weird situation where I am trying to add functionality to a powershell script and couldn't find a way to do it directly in powershell, so i'm setting up a vbscript to do one piece of it and calling the vbscript from powershell. I already had to do a lot of research to figure out how to do it in vbscript(and i'm still not sure about all of it) so i guess before i go any further, I'll try to figure out if this is even viable(in vbscript or c# or c++ or any other language someone could suggest)...
What i want to do, overall, is check if an MMC window is open that contains a DHCP snapin. If so, assign it to a variable. If not, create one.
Then it will read from a csv or txt file, and use the values to determine what node to navigate to within the snapin(DHCP>ServerName>IPv4>ScopeName>Scope Options).(I've mostly solved this part in vbscript, but don't know how to do it in C++ or C#)
Finally, I need to be able to execute a right-click menu item to "configure options", navigate the tabs of the popup that comes up, enter a value, and apply the changes/hit ok to close the popup. Worst case, If I can't do it "normally" by actually sending commands to the objects themselves, this part I can do with imitating keystrokes, but i don't want to do that if it's avoidable because it's sloppy.
Then, I basically will just need to somehow alert the powershell script that i'm "finished" so it can continue, or give an alert if there's an error.
I'm not asking anyone to walk me through all this, I just want to know if any of those steps aren't viable as i've described them, especially if I'm going to have to switch to c++ or c# to achieve the first part and therefore relearn the commands needed.
... and only create a new object IF there's not one open already ...
No, this is not possible in VBS, you need to do
Dim objMMC
Set objMMC = WScript.CreateObject("MMC20.Application")
if I create a new object every time the script runs, it will massively delay my overall script
In this case is the VBS the wrong language, you need to use C# or C++ executable.

Auto enter items into 3rd party website

So I have to scan and manually enter 1200 scanner number every week for inventory. The process goes in this order:
Open Website < Click text box < Enter numbers < hit submit < wait 20 seconds < hit submit again (it makes me confirm i entered right) < Wait another 20 seconds.
At this point, the page refreshes, and IO start over at the Click text box part.
I already converted the numbers to barcodes and scan them instead of typing, I also use 2 screens with 8 open windows to make it a bit faster.
But I was wondering if there was a batch file or another way to automate the process?
Even with the scanner, and 8 open windows, it takes 4 hours roughly to do them all.
I have been searching on google for a few days, and decided to ask here since most the pages i read go back to this site.
http://www.autohotkey.com/
Awesome macro software. Very flexible for a macro and easy language to learn.
Try searching for automated keyboard/mouse macro software. Never used it, just a tip.
This question appears to be similar on SuperUser: Redirecting input from file to command-line program
It appears to be effective for telnet sessions - not sure about http sessions. You might look into TCL and Expect as options though.

HTA - VBScript - Install program but wait for installation to complete

If you could give my a hand that would be great?
I have a HTA file nothing to fancy its to install a few programs one by one
I have been reading in a few places on how to wait for installation to complete
then install the next program but none make sense to me for what i want, also
they are saying to use wscript.sleep that would be great but it doesnt work in a HTA right ?
I have firefox, utorrent, symantec antivirus, adobe reader, office 2003 (packaged with KEY already)
and a few others.
i want to find switches to install silently but thats not important if this code someone is willing to show me works...
I hope I make sense ?
If you can help me it would be great ?
Cheers Pavle.
You might find something useful in my answer (https://stackoverflow.com/a/3742182/128427) to this question: How to get an HTA to restart itself?
It uses a VBScript helper to wait for a process to end (the HTA itself) then restarts the HTA. You could modify the vbscript instead to wait for a specific process to end (one of your installers), then return control to the HTA which starts the next installer and calls the wait script again.
I don't think an HTA can call the WScript.Sleep routine, but there are the setTimeout and setInterval methods in HTA that call a routine after X seconds, or repeatedly call a routine after every X seconds until cancelled. You can use these to check periodically if a process is still running (using WMI Win32_Process as I show in my other answer).
To process a list of items like this, instead of using a loop to go through a list and pause after each item, you have a central state-machine routine that calls itself every so often to advance the system.
'!! extremely "pseudo" pseudo-code follows
sub StartSystem()
state = "next program"
list = list of programs to install
AdvanceSystem()
end sub
sub AdvanceSystem()
if state = "next program"
if more items in list
start next installer
remove from list (or increment an index)
set state to "check program"
else
set state to "done"
if state = "check program"
use WMI to see if process is still running
if no
state = "next program"
if state <> "done"
setInterval(AdvanceSystem, 5000) ' call again in 5 seconds
end sub
' then somewhere in your HTA interface have a button to start things off
buttonClick = StartSystem()
Using an arrangement like this you may not even need to run a separate VBScript to check the process and sleep. Also, with this kind of incremental process, you can send output to a DIV somewhere so the user can see progress, whereas when processing things in a loop, output doesn't show up until the whole process has finished. After each pass through AdvanceSystem, the control returns to the HTA level and the system can update itself.
Let me know if you need a more specific example, I'll try to write something up.

Resources