Run Time Error 13 - Mismatch on Date - vba

avid reader, first time poster here. I have a Macro that I obtained from the internet for the most part, then made some adjustments. It's purpose is to color code cells that have passed a certain duration. It was working fine earlier, but now I am getting an error on it for a "Type Mismatch". The line that reads "This is where the error is" is where I am getting the mismatch. I am puzzled because it was working fine earlier. I am not a seasoned programmer by any means, but I just try to troubleshoot things. I have looked all over the net and cant find a specific answer to my question.
In addition, if any of you are willing, I would appreciate your advice on how to make this code run ONLY at startup of the workbook and NOT periodically as it is set up to do so now.This code is not placed in a worksheet, but in a Module.I mention this because I am not sure how much of a practical difference it can make any help is appreciated, thanks!
Public TimeToRun As Date
Sub Auto_Open()
Call ScheduleCompareTime
End Sub
Sub ScheduleCompareTime()
TimeToRun = Now + TimeValue("00:00:10")
Application.OnTime TimeToRun, "CompareTimeStamp"
End Sub
Sub CompareTimeStamp()
Dim rgTimeStamp As Range
Dim rdTimeStamp As Range
Dim i As Long
Dim j As Long
Dim MyNow As Date
Dim TimeStamp As Date, TimeStampp As Date
Set rgTimeStamp = Range("c1:c500")
Set rdTimeStamp = Range("H1:h500")
For i = 1 To rgTimeStamp.Rows.Count
If Not rgTimeStamp.Cells(i, 1) < 1 Then 'don't run for an empty cell
MyNow = CDate(Now - TimeSerial(0, 0, 0)) 'time instantly
TimeStamp = CDate(rgTimeStamp.Cells(i, 1)) 'THIS IS WHERE THE ERROR IS!!
If TimeStamp < MyNow Then 'if it's old at all
rgTimeStamp.Cells(i, 1).Interior.ColorIndex = 3 'make fill colour red
End If
End If
Next
For j = 1 To rdTimeStamp.Rows.Count
If Not rdTimeStamp.Cells(j, 1) < 1 Then
MyNow = CDate(Now - TimeSerial(0, 0, 0))
TimeStampp = CDate(rdTimeStamp.Cells(j, 1))
If TimeStampp < MyNow Then
rdTimeStamp.Cells(j, 1).Interior.ColorIndex = 3
End If
End If 'closes If Not
Next
Call ScheduleCompareTime 'begins the scheduler again
End Sub
Sub auto_close() 'turn the scheduler off so you can close workbook
Application.OnTime TimeToRun, "CompareTimeStamp", , False
End Sub

You probably have data in one or more cells that Excel cannot convert to a date. You can get around this by adding some simple checking such as this:
'.... beginning of your code
If Not rgTimeStamp.Cells(i, 1) < 1 Then 'don't run for an empty cell
MyNow = CDate(Now - TimeSerial(0, 0, 0)) 'time instantly
If IsDate(rgTimeStamp.Cells(i, 1)) = False Then
MsgBox "Invalid date found in cell " & rgTimeStamp.Cells(i, 1).Address(False, False)
Exit Sub
End If
TimeStamp = CDate(rgTimeStamp.Cells(i, 1)) 'THIS IS WHERE THE ERROR IS!!
If TimeStamp < MyNow Then 'if it's old at all
rgTimeStamp.Cells(i, 1).Interior.ColorIndex = 3 'make fill colour red
End If
End If
'... rest of your code
If you only want the code to run at startup then change Sub Auto_Open to this:
Sub Auto_Open()
Call CompareTimeStamp
End Sub

Related

VBA to open Excel file, refresh bloomberg data, save, close

I'm trying to write a vba script that gets called in a batch file to open an excel file, refresh bloomberg data, save the file, and then quit excel.
There was a historical question which asked something similar, but the suggested answer didn't seem to work - I can open the file and refresh the data, but it doesn't save the file or close excel.
I tried also putting in as a macro with the workbook_open file, but then ran into a problem where excel is saving and closing the file before refreshing the data. Any suggestions would be much appreciated.
Immediately below is the modified vba code that refreshes the data, but doesn't save or close the excel workbook.
'Write Excel.xls Sheet's full path here
strPath = "C:\MngXL\testbook.xlsm"
'Create an Excel instance and set visibility of the instance
Set objApp = CreateObject("Excel.Application")
objApp.Visible = True
Set wbToRun = objApp.Workbooks.Open(strPath)
StartAutomation
DoneNow
Sub StartAutomation()
Dim oAddin
Set oAddin = objApp.Workbooks.Open("C:\blp\API\Office Tools\BloombergUI.xla")
If Not oAddin Is Nothing Then
objApp.DisplayAlerts = False
objApp.Calculate
objApp.Run "RefreshAllStaticData"
objApp.Calculate
objApp.Run "RefreshAllStaticData"
'WaitTillUpdateComplete
End If
dim count
dim updated
updated = false
for count = 0 to 12
if updated = false then
if objApp.WorksheetFunction.CountIf(objApp.Range("rng_inWorkbook"),"#N/A Requesting Data...") = 0 Then
updated = true
else
Application.OnTime Now + TimeValue("00:00:15"), WaitTillUpdateComplete
end if
end if
next
End Sub
Private Sub WaitTillUpdateComplete()
Dim t
t = 0
objApp.Calculate
If objApp.WorksheetFunction.CountIf(objApp.Range("rng_inWorkbook"),"#NAME?") > 0 Then
Application.OnTime Now + TimeValue("00:00:15"), "WaitTillUpdateComplete"
ElseIf objApp.WorksheetFunction.CountIf(objApp.Range("rng_inWorkbook"),"#N/A") > 0 Then
Application.OnTime Now + TimeValue("00:00:15"), "WaitTillUpdateComplete"
ElseIf objApp.WorksheetFunction.CountIf(objApp.Range("rng_inWorkbook"),"#N/A Requesting Data...") > 0 Then
If t < 5 Then
t = t+ 1
waitlonger
Else
Exit Sub
End If
Else
Exit Sub
End If
End Sub
Sub waitlonger()
Dim x
x = Now + TimeValue("00:00:40")
Do While x > Now
Loop
objApp.Calculate
End Sub
Sub DoneNow()
wbToRun.Save
wbToRun.Close
objApp.DisplayAlerts = False
objApp.Quit
MsgBox strPath & " " & strMacro & " macro and .vbs successfully completed!!!!", vbInformation
End Sub
You need a strategy to let the refresh of Bloomberg data take about the right amount of time.
Currently, your program seems to allow only certain small amounts of time to pass with no feedback. Instead, you need to make a loop that cycles once every 10 seconds (or whatever makes sense) and checks to see if the program is done.
I like to do it this way:
dim count as integer
dim updated as boolean
updated = false
for count = 1 to 12 'or any value you choose
if updated = false then
if objApp.WorksheetFunction.CountIf(objApp.Range("rng_inWorkbook"),"#NAME?") = 0 Then
updated = true
else
Application.OnTime Now + TimeValue("00:00:15"), "WaitTillUpdateComplete"
end if
end if
next

Runtime error '70': Permission Denied VBA word

I am trying to create a countdown timer in word.
While running the code i am getting "Runtime error '70': permission denied" for a line in the code: time = time + TimeValue("00:00:01") in modtimer module.
I have created a userform and a separate module named modtimer, the code is given below:
The word document code: (ThisDocument) to show timer when word document opens
Sub Document_Open()
UserForm1.time_left.Visible = False
UserForm1.Label1.Visible = False
UserForm1.Show
End Sub
The code given in userform is as follows:
Dim g_start As Variant
Dim start As Variant
Dim timeEnd As Variant
Dim g_time As Variant
Dim time As Variant
Dim g_timeEnd As Variant
Dim time_duration As Variant
Dim g_time_duration As Variant
Dim g_End As Boolean
Private Sub btnStart_Click()
start = Now
g_start = Format(start, "hh:mm:ss")
timeEnd = Now + TimeValue("00:30:00")
g_timeEnd = Format(timeEnd, "hh:mm:ss")
time_duration = timeEnd - start
g_time_duration = Format(time_duration, "hh:mm:ss")
Label1.Visible = True
time_left.Caption = g_time_duration
time_left.Visible = True
btnStart.Visible = False
time = start + TimeValue("00:00:01")
time_duration = timeEnd - time
g_time_duration = Format(time_duration, "hh:mm:ss")
time_left.Caption = g_time_duration
modtimer.time_count
End Sub
The module code is as follows:
Sub time_count()
If time_duration = TimeValue("00:05:00") Then
MsgBox "Only 5 minutes remaining", vbInformation
End If
time = time + TimeValue("00:00:01")
time_duration = timeEnd - time
If time_duration = TimeValue("00:00:00") Then
g_End = True
End_Exam
End If
'If g_End = True Then
' End_Exam
'End If
g_time_duration = Format(time_duration, "hh:mm:ss")
time_left.Caption = g_time_duration
Call time_count
End Sub
Sub End_Exam()
MsgBox "Examination Time has Expired, Click Ok to Submit", vbCritical
'Documents.Save False, wdOriginalDocumentFormat
Documents.Close wdPromptToSaveChanges, wdPromptUser
End Sub
What is the reason behind it? Can anybody help?
Time is a vba function (and also a vba statement btw).
It is not a good idea to define a variable with the same name.
In your userform, you are overloading the function with your variable, but in the module every time you use Time your are referring to the standard Function (or statement), not the variable from the userform.
By the way, variables in userforms are private by default, so you cannot access the time variable in the userform from the module, you need to specify Public instead of Dim.
Once the variable is Public, you will be able to access it but you will need to use Userform1.time instead of only time.
But it still isn't a good idea to name it time
Additional explanation:
In the module, in the line
time = time + TimeValue("00:00:01")
The first time is the time statement (to change system time)
The second time is the time function (returns current time)
So you are trying to set the system time to the current time + 1 second.
This operation can be done only if you have elevated rights, hence the Runtime error '70': permission denied you get.
Time is an VBA property, and it is read-only (it gives simple the actual time). If you need a variable, use a different name.

Excel VBA UserForm 'OK'

Does anyone know how to make a userform function in the same way as the Message Box 'ok' button? I'll explain.
I'm detecting errors in a column in a spreadsheet. When an error is found, a message box pops up as follows:
MsgBox "Please enter valid data"
When I select "OK" it goes to the next error in the column. This is great, except of course a message box is modal, which freezes the application. I want the user to be able to edit the data and then move to the next error. So, I designed a userform, which can be non-modal. Great, except I want the macro to advance to the next error. It will do that IF the user corrects the error. If they do not, it just stays at that error cell.
I know WHY this happens. My userform 'Next' button just calls the macro which finds the first error. But what I want to know is if there is a way around this.
Error checking starts at row 19 because that is where user input data starts.
I'm including a link to the spreadsheet here. Module 1 'NextValidationError' works great and proceeds to the next error. Module 14 just hangs at the error until it is resolved. I'd like it to be able to skip.
https://www.dropbox.com/s/yqko5kj19pnauc9/Transparency%20Data%20Input%20Sheet%20for%20Indirect%20Spend%20V7%2009212016%20v2%200.xlsm?dl=0
Can anyone give me advice on how to make module 14 proceed as module 1?
Something like this:
Dim r_start As Long
Sub CheckNames()
Dim r As Long
'Dim emptyRow As Boolean
If r_start = 0 Then r_start = 19
With ActiveSheet
For r = r_start To 5000
'Checks entire row for data. User may skip rows when entering data.
If WorksheetFunction.CountA(.Range(.Cells(r, 1), .Cells(r, 33))) > 0 Then
If ((.Cells(r, 2) = "") <> (.Cells(r, 3) = "")) Or _
((.Cells(r, 2) = "") = (.Cells(r, 4) = "")) Then
MsgBox "Please fill in First and Last Name or HCO in Row " & r & "."
End If
End If
Next
End With
End Sub
Unless I'm mis-reading your code you can combine your two checks with Or.
You will need some method to reset r_start when the user is done checking (if the form stays open after that).
EDIT: here's a very basic example.
UserForm1 has two buttons - "Next" and "Close"
Code for "next" is just:
Private Sub CommandButton1_Click()
ShowErrors
End Sub
In a regular module:
Dim r_start As Long
'this kicks off the checking process
Sub StartChecking()
r_start = 0
UserForm1.Show vbModeless
ShowErrors
End Sub
'a simple example validation...
Sub ShowErrors()
Dim c As Range, r As Long
If r_start = 0 Then r_start = 9
For r = r_start To 200
With ActiveSheet.Rows(r)
If Not IsNumeric(.Cells(1).Value) Then
UserForm1.lblMsg.Caption = "Cell " & .Cells(1).Address() & " is not numeric!"
r_start = r + 1
Exit Sub
End If
End With
Next r
r_start = 0
UserForm1.lblMsg.Caption = "No more errors"
End Sub

How do I create a stop for the Application.OnTime event in my code?

I have some code here that works perfectly except for when I try to close the Excel Sheet. I have tried to program the timer to stop when i close the Workbook but it does not seem to be working. Whenever I close the workbook it automatically re-opens. Any help with tweaking my code would be gratly appreciated. Here it is:
Code in Module 1:
Dim RT1 As Date
Dim Lunch As Date
Dim ApT As Date
Dim RT3 As Date
Dim NextTick As Date
Public Sub UpdateTime()
' Places a bug fix for stopping the clock when closing the workbook
Debug.Print "UpdateTime" & Format(RunWhen, "00:00:00")
' Updates cell D8 with the Current time
ThisWorkbook.Sheets(1).Range("D8") = Now()
' Set up next event 1 second from now
NextTick = Now + TimeValue("00:00:01")
Application.OnTime NextTick, "UpdateTime"
End Sub
Public Sub StopClock()
' Cancels the OnTime event
On Error Resume Next
Application.OnTime NextTick, "UpdateTime", , False
End Sub
Code in Module 2:
Sub PhoneHours()
'Time left at the beginning of the day
If Range("B12") < Range("A3") Then Range("E12").FormulaR1C1 = "=(R[3]C[-3]-R[0]C[-3])- (2*R[0]C[1])"
'Time left after the first Research Time Has passed
If Range("B12") >= Range("A3") Then Range("E12").FormulaR1C1 = "=(R[3]C[-3]-R[0]C[-3])- (1.75*R[0]C[1])"
'Time left after Lunch and Second Research Time
If Range("B12") >= Range("B3") Then Range("E12").FormulaR1C1 = "=(R[3]C[-3]-R[0]C[-3])- (0.5*R[0]C[1])"
'Time left afetr Apple Time
If Range("B12") >= Range("D3") Then Range("E12").FormulaR1C1 = "=(R[3]C[-3]-R[0]C[-3])- (0.25*R[0]C[1])"
'Time left after Final Research Time
If Range("B12") >= Range("E3") Then Range("E12").FormulaR1C1 = "=(R[3]C[-3]-R[0]C[-3])"
NextCheck = Now + TimeValue("00:00:10")
Application.OnTime NextCheck, "PhoneHours"
End Sub
Sub StopCheck()
' Cancels the OnTime event
On Error Resume Next
Application.OnTime NextCheck, "PhoneHours", , False
End Sub
Code in ThisWorkbook:
Sub Worksheet_Deactivate()
Call StopClock
Call StopCheck
End Sub
Sub Workbook_Activate()
Call UpdateTime
Call PhoneHours
End Sub
Sub Workbook_Open()
Call UpdateTime
Call PhoneHours
End Sub
Sub Workbook_Close()
Call StopClock
Call StopCheck
End Sub
Thanks in Advance!
When I tried do something similar I found that the main problem was that OnTime calls were being raised far more frequently than I expected - if you put a debug.print in your PhoneHours sub then you'll see that this is the case here. Your StopCheck routine is only cancelling the latest call, but all earlier ones are still active (and are causing the book to be reopened after closing).
You may want to create some breakpoints/debugs to find out exactly where and why each one is being called in order to make your sheet run more efficiently, but in any case I found that the most reliable way of cancelling all future ontime calls was a bit of a scattergun approach as follows:
Sub StopCheck()
' Cancels the OnTime event
Debug.Print "Cancelled Phonehours"
On Error Resume Next
' Cancels all OnTime events scheduled in the next 15 seconds
For i = 0 To 15
Application.OnTime Now + TimeValue("00:00:" & i), "PhoneHours", , False
Next i
On Error GoTo 0
End Sub
and
Public Sub StopClock()
' Cancels the OnTime event
On Error Resume Next
Debug.Print "Cancelled UpdateTime"
' Cancels all OnTime events scheduled in the next 3 seconds
For i = 0 To 3
Application.OnTime Now + TimeValue("00:00:" & i), "UpdateTime", , False
Next i
On Error GoTo 0
End Sub
This should leave no remaining future OnTimes scheduled and you should be able to close your sheet successfully.
(Incidentally, should your Worksheet_Deactivate be a Workbook_Deactivate?)

quickest way to check a range for valid data points ... avoiding a loop in vba

Hi I'm wondering what is the quickest (least memory using) way to check a range of data points to see if the points are valid.
Lets say I have a rng = Range("A1:A100"). I want to write something such that
If c in rng = "N/A Requesting Data..." Then
x = false
Else
Application.OnTime Now() + TimeValue("00:00:05"), "refresh" .... etc.
End if
Can i do this without looping?
This checks A1:A100 of the ActiveSheet. If no cells contain "N/A" as part of their text RangeLooksGood is set to True.
Sub TestRangeForValidContent()
Dim RangeLooksGood As Boolean
With ActiveSheet
RangeLooksGood = (Application.WorksheetFunction.CountIf(.Range("A1:A100"), "*N/A*") = 0)
End With
If RangeLooksGood Then
Application.OnTime Now() + TimeValue("00:00:05"), "refresh"
End If
End Sub