1

So I have a VBScript that I run through my task scheduler. Been testing it and running it everyday and about 50% of the time I see this error in the morning when I come into work: enter image description here

And then if I hit 'notify' the program then finishes executing. But that doesn't help me, because it defeats the purpose of having the program run automatically. My assumption for why it only happens 50% of the time is that after I hit notify the program executes properly and closes everything, then the next day when it runs it doesn't properly close APG.xlsx so then the next day when it runs it produces the same error message.

Program Layout

  1. Open a master excel sheet to run VBA script
  2. Open up the list of files 1 by 1 refresh the live data connections and then save the excel sheet as name_POSReport.xlsx (i.e. APG_POSReport.xlsx)
  3. Close the file, and move to the next file.

My thinking is that even though I am saving the report as another file, do I still have to close the original file as well? It doesn't really make sense that that would be the case, but maybe it is. So I am hoping for some sort of clarification.

Visual Basic Script :

Dim xlApp
Dim xlBook

Set xlApp = CreateObject("Excel.Application")
Set xlBook = xlApp.Workbooks.Open("\\fileserver\homeshares\asweet\My Documents\POS Reports\POS Live Reports\runReport.xlsm", 0, False)

xlApp.Run "executeUpdate"

xlBook.Close
xlApp.Quit

Set xlBook = Nothing
Set xlApp = Nothing

VBA Code

Public wb As Workbook

Sub executeUpdate()
' Vendors will be specified later
'    Dim vendors(0 To 12) As String
    Dim testArray(0 To 2) As String
    Dim path, savePath, ext As String
    Dim i, x, erow As Long

    Application.DisplayAlerts = False

    x = Sheets(1).Cells(Rows.Count, "A").End(xlUp).row + 1

    path = "\\fileserver\homeshares\asweet\My Documents\POS Reports\POS Live Reports\"
    savePath = "\\fileserver\homeshares\asweet\My Documents\POS Reports\POS Live Reports\Monthly POS Report\"
    ext = ".xlsx"

    testArray(0) = "APG"
    testArray(1) = "Code"
    testArray(2) = "IPC"

    For i = LBound(testArray) To UBound(testArray)
        Cells(x, 1).FormulaR1C1 = Now
        Cells(x, 2).FormulaR1C1 = testArray(i)
        Cells(x, 3).FormulaR1C1 = "Fail"

        openBook path & testArray(i) & ext, testArray(i), True
        saveBookAs savePath & testArray(i)
        closeBook

        Cells(x, 3).FormulaR1C1 = "Pass"
        x = x + 1
    Next i

    ThisWorkbook.Save
    Application.DisplayAlerts = True
End Sub

Sub openBook(ByVal fileName As String, ByVal baseName As String, ByVal refresh As Boolean)

    Set wb = Workbooks.Open(fileName, 0, False)

    If refresh = True Then
        If Application.ProtectedViewWindows.Count > 0 Then
            Application.ActiveProtectedViewWindow.Edit
        End If
        wb.Connections(baseName & " POS Report").OLEDBConnection.BackgroundQuery = False
        wb.RefreshAll
        wb.Connections(baseName & " POS Report").OLEDBConnection.BackgroundQuery = True
    End If
End Sub

Sub closeBook()
    wb.Close
End Sub

Sub saveBookAs(ByVal fName As String)
    wb.SaveAs fileName:=fName & "_posReport.xlsx"
End Sub
Instant Breakfast
  • 1,383
  • 2
  • 14
  • 28
Adjit
  • 10,134
  • 12
  • 53
  • 98
  • This is due to the fact that the workbook is shared. Check out http://office.microsoft.com/en-gb/excel-help/features-that-are-unavailable-in-shared-workbooks-HP005201080.aspx – Pankaj Jaju Dec 20 '13 at 14:38
  • @PankajJaju So then why is it not happening every time the program runs? – Adjit Dec 20 '13 at 14:41
  • 2
    No the workbook is not shared but I guess, it is already opened by another application. Are you closing up and cleaning the excel objects correctly? Can you share the code of vbs? – Siddharth Rout Dec 20 '13 at 14:47
  • Yes, I'd say it's a problem of cleaning up the objects. Next time before you run it, display hidden files and look if you have a ghost file (a file that looks like "~Myworkbook.xls" if your workbook is "MyWorkbook.xls") – Julien Marrec Dec 20 '13 at 14:55
  • @metsales - What I meant to say is that the workbook is shared and someone might have opened it while you tried to run your macro. It is not happening every time because the workbook may not be opened up by someone else ... try to check `Tool`->Share Workbook` – Pankaj Jaju Dec 20 '13 at 14:56
  • After your vbscript runs, check the running processes in the Task Manager. Is Excel.exe still open? – Blackhawk Dec 20 '13 at 14:57
  • Also @PankajJaju may have a point if you you are not `Alan Sweet` or you are not logged on using that id ;) – Siddharth Rout Dec 20 '13 at 14:58
  • @SiddharthRout I'll post the code in a minute, have to get it off of the other computer which is currently in use (I have the original code, but there are some issues with it so I don't want to post code that I know doesn't work properly). But the user `Alan Sweet` is always logged on. We use a fileserver, and through the VBScript I run it whether the user is logged on or not. This is that same program that you helped me out with earlier. – Adjit Dec 20 '13 at 15:05
  • Did you say you're saving the opened workbook as something else in your code? If so, open the original as read-only. It's a good practice to open as read-only if you don't intend to write to it. Plus you won't get that prompt. – Dick Kusleika Dec 20 '13 at 15:22
  • @DickKusleika but I am actually doing things to that sheet aka updating live data connections. I wouldn't be able to do that if I open it as read-only. – Adjit Dec 20 '13 at 15:29
  • @SiddharthRout see post for updated code – Adjit Dec 20 '13 at 15:44
  • @metsales I disagree. The only thing opening a file with `ReadOnly:=True` prevents is saving the file. It doesn't prevent changing it or Save-As-ing it. At least not in my experience. Even if it did, just do the Save As first. Surely it can't prevent you modifying a file you've saved. – Dick Kusleika Dec 20 '13 at 15:54
  • So you would say change this: `Set wb = Workbooks.Open(fileName, 0, False)` to this: `Set wb = Workbooks.Open(fileName, 0, True)`? – Adjit Dec 20 '13 at 15:57
  • wb is a global variable, you assign it but I do not see you ever release it. Remove it from being a global variable and use it as a local variable in each routine/function and explicitly free it. This could be the reason it is locked – Sorceri Dec 20 '13 at 19:20
  • Yes, make the third argument True and that box will not be an issue. I realize it doesn't solve the root cause of the problem, which you still may be interested in finding. – Dick Kusleika Dec 20 '13 at 19:21
  • @Sorceri I tried, in my `closeBook` method which is called at the end of every loop to set `wb = null` but I kept getting errors. – Adjit Dec 20 '13 at 19:32
  • @SiddharthRout I believe I am closing it properly. You think opening as 'read-only' fix this? – Adjit Dec 20 '13 at 22:18
  • Sorry had missed this. Quick question. Do you get the `readonly` message when you rung it for the first time or the subsequent times? – Siddharth Rout Dec 20 '13 at 22:26
  • @SiddharthRout honestly it seems like it is random, but once it starts happening it continues to happen. The user was having issues and then rebooted his computer and it was working fine up until a few days ago. – Adjit Dec 20 '13 at 22:47
  • If you are not planning to save the opened files then yes you can open them as readonly – Siddharth Rout Dec 20 '13 at 23:07
  • @SiddharthRout so I changed the files that I open and refresh to readonly, and that worked, but my macro excel book that I use to run the code still hangs after execution. This book I don't open as readonly because I have pass-fail statements that print to the excel sheet so I know if the code was executed. So the sheets that I want updated and saved are updated and saved. However, the workbook I use for execution hangs, and is not saved or closed. – Adjit Dec 27 '13 at 21:13
  • I am not sure what else to suggest :) – Siddharth Rout Jan 09 '14 at 21:45
  • @SiddharthRout is it possible for me to close excel from within that VBA script? Initial thoughts say no, because if I close the workbook then the script is going to be killed, even though there may not be any real code after the close statement I can't imagine that being 'good' – Adjit Jan 09 '14 at 23:04
  • To get rid of what `CreateObject("Excel.Application")` creates is not as trivial as it seems. See http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects for a good source of information. – TheBlastOne Jan 27 '14 at 19:35

2 Answers2

0

You can make a call to the VBA ontime method in order to get excel to close after the procedure has run. I'm assuming that you have saved (or closed) any workbooks including the one containing your excecuteUpdate procedure.

You will need a procedure to call to close excel for example:

Sub excelQuit()
   Application.Quit
End Sub

And a call to the ontime method in your executeUpdate procedure e.g.

Call Application.OnTime((Now + TimeValue("00:00:10")), "excelQuit")

This would attempt to close the application 10 seconds after the call is made to ontime, however it will wait until the any active procedures have finished first.

Graham Anderson
  • 1,209
  • 10
  • 17
0

I had the same issue. However I found a work around. Basically I created a folder and used shutil copyfile to create a copy of the desired file. Afterwards I run my pywin32 script and delete the copies. This will stop the message from appearing.

Hugo Alain Oliva
  • 237
  • 1
  • 10