I have very limited programming experience (i.e. mainly VB in Microsoft Excel and a bit of Visual Studio) so looking for help on how to create a program which is in effect a timer.
I have a boolean cell in Excel (0 or 1) which changes throughout the day. What I want to do is measure the time in a day for which this is 1. What is the easiest way to do this?
I tried doing it in Excel but came across several issues such as constant refreshing needed as it wouldn't pick up when the cell value changed. From years ago having used a bit of Visual Studio I thought this could be a good solution but struggling to understand how to get the cell value imported.
Any help would be greatly appreciated. Thanks.
Can't you simply handle the Worksheet_Change event. Something along the following lines:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngMyCell As Range
Set rngMyCell = Me.Range("A1") ' or whatever cell you're monitoring
If Not Intersect(Target, rngMyCell) Is Nothing Then
If rngMyCell.Value = 1 Then
' Start Stopwatch if it's not running
Else
' Pause Stopwatch if it's running
End If
End If
End Sub
Related
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.
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.
Ok, so the code below is just an example of how I'm progressing my progress bar.
I've been adjusting the following line: System.Threading.Thread.Sleep(100) (fast process) or System.Threading.Thread.Sleep(2000) (slower process).
Is there anyway to adjust this on the fly?
A little background info might help. On a daily basis, I create PDFs ranging from a couple hundred to even a couple thousand. Then, all PDFs get zipped up and transferred via SFTP. The PDF sizes could also vary.
Obviously my System.Threading.Thread.Sleep(100) would be on the lower end if I only had a handful of small PDFs to process.
Which leads me back to my original question, can that sleep number be adjusted on the fly based on number of PDFs and the size of all of them?
Or do I need to process a test run and find that magical number to use?
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim ZipPDFs As BackgroundWorker = CType(sender, BackgroundWorker)
Dim i As Integer
For i = 1 To 10
If (ZipPDFs.CancellationPending = True) Then
e.Cancel = True
Exit For
Else
' Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(100)
ZipPDFs.ReportProgress(i * 10)
End If
Next
End Sub
You got the example wrong! The sleep there, is to demostrate a real time consuming operation. You need to take it out, and write the actual operations that you need to perform ;)
Is their any way for a windows process to block another process from printing?
Basically we are trying to cut costs in the office and we want to block people from printing their emails. So I was asked if it was possible to write a program to block or cancel any print jobs comming from Outlook.
Can use a solution in any language or API, whatever works.
We have Win XP and Win 7 users.
There really isn't a good way to do this on Windows.
Besides, this doesn't seem like a technology problem.
Supply the printer with only one ream of paper per month. Let everyone know that the paper supply is limited.
The obvious work around is that users will bring in their own paper, but that will greatly reduce the operating cost, so it's not really a problem.
Are you using a network printer? If it is so, you can simply audit the printer's log (or the print server's) and "educate" your users accordingly, it will save you the hassle of writing such a program and deploy it on every pc (and make sure no user can override it).
Basically, this is the closest I could find for doing this. If basically waits for a print Job to show up with a particular job name and then cancel that job.
Technically though, I think the answer to my questing is no, since i asked if I could do this by process. Although the below comes close. It just prints out jobs that are happening and cancels any print job that says MS Outlook in its title. The dictionary thing just keeps it from listing the same jobs a bunch of times.
Imports System.Printing
Module Module1
Sub Main()
Using ps As New PrintServer("\\server")
Using Pq = ps.GetPrintQueue("printer")
Dim DetectedJobs As New Dictionary(Of DateTime, String)
Do
Dim Pj = Pq.GetPrintJobInfoCollection
For Each job In Pj
If Not (DetectedJobs.ContainsKey(job.TimeJobSubmitted) AndAlso DetectedJobs(job.TimeJobSubmitted) = job.Name) Then
DetectedJobs.Add(job.TimeJobSubmitted, job.Name)
Console.WriteLine(job.Name & "," & job.JobIdentifier & "," & job.TimeJobSubmitted)
End If
If job.Name.Contains("Microsoft Office Outlook") Then
job.Cancel()
Console.WriteLine(job.Name & "," & job.JobIdentifier & "," & job.TimeJobSubmitted & " - Cancelled")
End If
job.Dispose()
Next
Pj.Dispose()
Threading.Thread.Sleep("200")
Loop
End Using
End Using
Console.ReadKey()
End Sub
End Module
I've got a solution that takes a while to open. (5 minutes) Due to our processes and procedures I'm constantly jumping around between different branches of the same solution. I'm constantly closing and loading different variations of the same solution more than a few times a day. That's over 15 minutes - 30 minutes wasted just wating for my Visual Studio. I'm blaming the outdated computer hardware as the culprit. I want to capture metrics of how long solutions are taking to load as well as how long build times are taking. My goal is to present these metrics to management.
I'm using Visual Studio Macros to track this information.
As it stands right now I'm logging time stamps on these three events EnvDTE.SolutionEvents.BeforeClosing, EnvDTE.SolutionEvents.AfterClosing, EnvDTE.SolutionEvents.Opened.
The problem is, the SolutionEvents.Opened fires after the entire solution has been loaded. I need to generate a timestamp from when I start to load the solution and when it finishes.
How can I find out when Visual Studio starts loading the solution? So that I can compare it to when it finished loading.
Below is my code (My LogWithTimeStamp() function just writes the string to a file with the current timestamp as a prefix:
Private Sub SolutionEvents_BeforeClosing() Handles SolutionEvents.BeforeClosing
LogWithTimeStamp("SolutionEvents.BeforeClosing")
End Sub
Private Sub SolutionEvents_AfterClosing() Handles SolutionEvents.AfterClosing
LogWithTimeStamp("SolutionEvents.AfterClosing")
End Sub
Private Sub SolutionEvents_Opened() Handles SolutionEvents.Opened
LogWithTimeStamp("SolutionEvents.Opened")
End Sub