My vba code closes a document before the print command can be executed - excel

The code I am trying to run is in excel vba and its supposed to open a word document print it and then close the document. For some reason it seems that the code doesn't finish sending the document to the printer and yet it still closes. So the code runs to completion and doesn't generate an error message but nothing manages to print.
When I run the code step by step the document does manage to print. I tried adding: Application.Wait(Now + TimeValue("0:00:05")) to give it time to work. I tried a another form of that line in case the program was telling word to wait instead of excel: Excel.Application.Wait(Now + TimeValue("0:00:05")). I've also tried playing around with the time making it wait 10 second instead of 5.
Any help would be great
If ENG28 = "" Then
Else
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Open(ENG28)
objWord.Visible = True
objDoc.PrintOut
Application.Wait(Now + TimeValue("0:00:05"))
objWord.Quit 0
End If

I see that you made use of the .Wait method however there is a better way as you can never guarantee that your document is in a printed state within the 5-10 seconds threshold.
The PrintOut method basically has an argument you may add named Background. The default value of this argument is True which would mean that printing occurs in the background and the code continues to run which is causing your file to close before completing the print function. In this case, if you set the Background argument value to False, the macro will not take any more instructions until the printing is done.
try changing the PrinOut line to the following, see if that helps:
objDoc.PrintOut Background:=False

Related

Stepping through with F8 the code runs, stops in standard execution with F5

I've written a macro which sums numbers, grouping by year and by month based on our projection model.
It runs from start to end when stepping through with F8.
It stops immediately in standard execution with F5.
The first trouble is
Runtime error 91
in
issmIndex = Range("A1:Z1").Find("ck.IssMon").Column 'issmIndex an integer
Originally I tried Application.WorksheetFunction.Match(...) but had the same problem: runs in debug, but not in execute (Error 1004 instead).
I considered it could have been an Excel version issue (the Match function has a different name in the Italian version). I switched to a more neutral Find, but still no luck.
When you have an error with a line that is a combination of several commands, try breaking it down into the individual steps.
For example, this works:
Sub findDemo()
Const toFind = "blah"
Dim rg As Range, f As Range
Set rg = Range("A2:C5")
Set f = rg.Find(toFind)
If f Is Nothing Then
Stop 'not found
Else
Debug.Print "found in column #" & f.Column
End If
End Sub
Also see the example in the documentation for Range.Find().
Welcome to SO. Sometimes Excel reads code faster than executing, so when reading a command there is a previous one not finished. IT's weird but it happens a lot if your code does a lot of stuff and calculus.
Besides, when debugging, every command line is executed before reading next one, so you cannot detect this just debugging.
So if your code runs perfect when debugged but errors if executed as normal, try to add the command DoEvents right before the problematic line. Something like this:
' your previous code
'
'
'
Doevents
issmIndex = Range("A1:Z1").Find("ck.IssMon").Column 'issmIndex an integer
'
'rest of your code
This commands forces Excel to make sure everything has been executed before reading. It's kind of like a checkpoint, something like make sure you've done everything before going to next line.
DoEvents
function

Word gets stuck during export via Excel VBA

My Excel VBA script contains an export function which results in one Word document of about 12 pages.
On my private computer, this works.
On my company's laptop this seems to take too long and probably some kind of Word watchdog is triggered. Word gets stuck after about 75% of the code and the message "Word has stopped working" pops up.
I determined the point where it gets too much for Word to handle. As the export code is quite extensive and also contains several company and project details that I don't want to reveal, I prefer to not post it here.
Here is the snippet at which Word gets stuck:
ThisWorkbook.Worksheets("Backup - Do not change").Shapes("companyLogo").Copy
With wdFrontHeaderTable
.rows.Height=30
With .Cell(1,1).Range
.Paste
.ParagraphFormat.Alignment=0
End With
With .Cell(1,1).Range.InlineShapes(.Cell(1,1).Range.InlineShapes.Count)
.LockAspectRatio=msoTrue
.Width=120 'this one still works
End With 'here, the error occurs
End With
If I set one before that point and then run the two halves of code, one after another, it works.
If I uncomment the whole block, the error occurs in the next block.
The code does what it is supposed to do, even on the company laptop. I guess it just takes too long and the watchdog "thinks" Word was stuck.
Is there a way to disable the watchdog or another way to solve this?
I tried Application.Wait (1000).
Word is initialized by
Dim wdApp As Object
Dim wdDoc As Object
Set wdApp = CreateObject("Word.Application")
Set wdDoc = wdApp.Documents.Add

Excel VBA hangs when expanding [+] workbooks object variable in locals window

I'm having a problem trying to debug some code I've written that opens a shared Excel file from SharePoint (in desktop Excel app), scrapes schedule data, makes a few changes, saves and closes that file, then populates the scraped data into the current workbook formatted as a calendar.
As is typical, the code executes fine for me, but only works about 50% of the time when another user runs it. I'm still searching for fixes to those bugs - they are not the reason for my question today. I'll try as best I can to describe my problem and hopefully someone can tell what I'm doing wrong.
First step I do is to check whether the SharePoint file exists and if so, open it (no problems/errors typically encountered here for myself or anyone else):
Sub getcalendardata()
...define variables...
Application.EnableEvents = False
Application.ScreenUpdating = False
schedule = "https://mycompany.sharepoint.com/sites/Schedule/Shared Documents/Schedule.xlsx"
If URLExists(schedule) = 0 Then
MsgBox "Schedule not found. Check internet connection, login to Office 365, and try again."
Exit Sub
End If
Set schedulewb = Workbooks.Open(schedule, False, False)
schedulewb.AutoSaveOn = False
Application.WindowState = xlMinimized
Set schedulews = schedulewb.Worksheets("Design")
...more code here...
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Function URLExists(url As String) As Boolean
Dim Request As Object
Dim ff As Integer
Dim rc As Variant
On Error GoTo EndNow
Set Request = CreateObject("WinHttp.WinHttpRequest.5.1")
With Request
.Open "GET", url, False
.Send
rc = .StatusText
End With
Set Request = Nothing
If rc = "OK" Then URLExists = True
Exit Function
EndNow:
On Error Goto 0
End Function
*** Occasionally, I run into issues with the cached file in MS Office's Upload Center becoming out-dated and asking to save a copy or discard changes, but that is a problem for another day.
The main problem I've come here for is that after stepping through the Workbooks.Open line, if I open the "Locals Window" to view the stored variables and try and expand the Workbook object "schedulewb" (Here:
Locals Window during code execution), code execution seems to stop or go into an infinite loop. It's like VBA is trying to expand the schedulewb object to display the properties, but isn't getting a response, so it just waits. I've not been patient enough to see if it ever self recovers.
The only thing I see is that the Locals Window schedulewb line goes blank (like it's trying to expand) and I can no longer step through, continue, or reset/end the code execution. I can however, break/pause the execution, at which point, schedulewb returns to the Locals Window list and I'm able to expand it with a very brief delay. Restarting or resetting code execution after this just puts the program into the previous stall pattern and the only recovery option (besides waiting potentially forever) is to close and restart excel via Task Manager. Interestingly, the actual Schedule Workbook I'm trying to peak inside now shows up in the Office Upload Center as a pending upload or having just been synced.
I've tried bypassing SharePoint by opening a local version of the Schedule Workbook saved to my computer, and as expected, I can interact with the Locals Window variables without consequence.
Is there something wrong with setting a SharePoint Workbook to a variable like I've done?
Has an upload/refresh been triggered by me trying to inspect the object properties, causing some other uncontrollable VBA/SharePoint event to infinitely loop in the background?
Could this be connected somehow to the Upload Center cache headache that I think is unrelated?
Thank you in advance for any insight...

VBA EXCEL error 91 object variable or with block variable not set

Hi I have this weird problem where I get error 91 ("object variable or with block variable not set"). I do not always get the error when I run the script, only now and then (random). I have tried to do as much as I can without success.
I am scraping a site to get the most recent prices of some pc components.
In order to do that I made a script and call the script sequentially multiple times for different parts. The error is not related to a specific part. I get the error randomly on all the parts. Sometimes I can do all the calls without any errors.
The script (not the full script, only what you need):
Sub ImportUrlData(url As String)
Dim ie As InternetExplorer
Dim html As HTMLDocument
Dim varListingIDElement As IHTMLElement
Dim varShopName As String
varShopName = ""
Set ie = New InternetExplorer
ie.Visible = False
ie.navigate url
Do While ie.readyState <> READYSTATE_COMPLETE
DoEvents
Loop
Set html = ie.document
Set varListingIDElement = html.getElementById("listing")
varShopName = getXPathElement("/table/tbody/tr[1]/td[1]/p/a", varListingIDElement).innerText
I always get the error on this last line:
varShopName = getXPathElement("/table/tbody/tr[" & count & "]/td[1]/p/a", varListingIDElement).innerText
(The error is not occurring inside the 'getXPathElement' function, so no need to show that too. If you do want to take a look at it just ask and I'll post it here in an edit.)
When I debug from start to end with F8 I never get the error. Is it possible that the next call already starts before the previous one isn't finished yet?
Thanks in advance!
(Sorry if there are some dutch words I have overseen.)
There are some cases where you can encounter an issue like this (where F8 always works, but a normal run doesn't) if the object return, in whatever way, isn't fully connected. It is difficult to say for certain if this is the case, and I have only encountered this when I am setting an object to something that has it's own process for initializing, and when this process is outside of the control of the VBA routine.
For your problem, specifically, there are a couple of approaches you can take:
Set varListingIDElement = html.getElementById("listing")
If Not varListingIDEElement is Nothing Then
varShopName = getXPathElement("/table/tbody/tr[1]/td[1]/p/a", varListingIDElement).innerText
End If
The above approach should prevent the error entirely, but it also means varShopName may not be set.
On the other hand:
Set varListingIDElement = html.getElementById("listing")
Application.Wait(Now + TimeValue("00:00:03"))
varShopName = getXPathElement("/table/tbody/tr[1]/td[1]/p/a", varListingIDElement).innerText
This will force the application to wait three seconds between the initial setting of the variable, and the final calling of the variable. You could use this approach if it is indeed an issue of the prior process not finishing before the new one begins. You could also combine this approach with the first to get the best of both.
Good luck!

Wait for CSV file to open?

I am trying to download and open a CSV file using VBA in Excel. When I step through using the debugger my code works fine but when I try to run it normally it won't work, it is trying to copy the info from the newly opened CSV file into the existing .xlsm file but it isn't finding anything. I have found ways of checking that the file is open but I need it to keep checking and once it does exist to continue with the code.
Here is how Im getting the file to download:
Sub getFile(address)
On Error Resume Next
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = False
ie.navigate address
ie.Quit
Set ie = Nothing
On Error GoTo 0
End Sub
And then after this in the sub that calls getFile,
Do While Workbooks(Workbooks.Count).Name <> "file.csv"
Loop
Ive tried a few variations that all work fine when taking it slow in the debugger but crashes otherwise. Does anyone know a way to have it keep checking and wait until the file is open? It requires the user to do something so what it to make sure that file.csv is open. Should I put my check in sub getFile or keep it after it is called?
SOULTION:
Taking hnk's advice below I tried this and it worked perfectly:
Sub getFile(address)
On Error Resume Next
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = False
ie.navigate address
Do While Workbooks(Workbooks.Count).Name <> "file.csv"
DoEvents
Loop
ie.Quit
Set ie = Nothing
On Error GoTo 0
End Sub
Moved the check to before closing IE and added DoEvents to my loop.
Usually such behavior happens not because of the code logic but because of interrupts. Depending on the nature of your environment it could be one of two things
some background refreshing process is getting executed sometime in between your code execution time causing some issues. e.g. in a financial services environment, your Bloomberg API could be doing its timely BlpUpdate event
your code blocks up a large chunk of time and causes unexpected behavior because event which was triggered during your loop was blocked too long waiting for your code to complete on the main thread.
So you need to try the following two solutions, one of which should work
For the second problem, inside your
Do While Condition
' ... your code ...
Loop
add a line of code that checks for and clears any pending Event queues, making it...
Do While Condition
DoEvents ' either put it at the start or at the end of your code
' ... your existing code ...
Loop
This will give the system some 'breathing space' to wrap up pending events. You'll need to experiment with the location of your DoEvents code.
For the first problem, you can try enclosing your entire loop within an Event Protected area of code, to ensure it finishes running before anything disturbs it.
Application.EnableEvents = False
'your loop and other code comes here
Application.EnableEvents = True
Once again, you might need a bit of trial and error to see how much of the code needs to be thrown into the Event-free zone before it works as expected.

Resources