Outlook 2010 - strange item.Attachments error - excel

I have the following code, that should save a specific Excel file attached to an email. The code is combined with a rule, that trigger this script when an emai lwith a specific subject is received.
The code is triggered, but here comes the strangest error I saw lately: itm.Attachments.Count appear to be zero and obviously the file is not saved! But... if I put a breakpoint on "For each..." line and add itm.Attachments.Count to watch window, it is shown as zero. If I add itm only, then browse to Attachments property, then to Count property it shows 1 for Count (as it should) and the code is executed fine. I spent half a day trying to understand what's going on, but I can't figure it out.
The behaviour is the same both on a Outlook 2010 x64 on a Windows 7 x64 and on a Outlook 2010 x86 on a Windows 7 x86. Macros are enabled in Trust Center. I have attached some screenshot with the code and rule settings and also a movie showing the watch windows strangeness.
The script was built some time ago and it worked well on a couple of PCs and it was based on the steps from here: iterrors.com/outlook-automatically-save-an-outlook-attachment-to-disk/.
Any ideas?
Rule screen here
1 min. movie here
Public Sub Kona(itm As Outlook.MailItem)
Dim objAtt As Outlook.Attachment
Dim saveFolder As String
saveFolder = "C:\test"
For Each objAtt In itm.Attachments
If InStr(objAtt.DisplayName, "Kona Preferred Fixed Price Matrix (ALL)") Then
objAtt.SaveAsFile saveFolder & "\" & objAtt.DisplayName
End If
Set objAtt = Nothing
Next
End Sub

In case if you have an IMAP account configured in Outlook: your Offline Settings might be set to only store up to 1 month, 3 months, 12 month worth of emails on your local disk.
If you’ve got enough space on your disk and want to cache more emails locally, you can set the sync slider in the following way:
File-> Account Settings-> Account Settings…-> double click on your IMAP account.
Try to increase the offline storage in Outlook. See Empty Inbox and other IMAP synching issues in Outlook 2013 for more information.

My best understanding of this behavior is that Microsoft Outlook (at least the versions of 2010 that I tested) has a bug. There may be other factors that I'm not aware of contributing to this, but I was able to reproduce the error using different service pack levels / builds of Outlook 2010 on Windows Vista. Office 2013 does not appear to be affected.
I managed to create a workaround.
I found that by displaying the message while stepping through the code in debug mode using
objMailItem.GetInspector.Activate
the number of attachments was subsequently correctly detected (without having to do strange things like setting up a watch for the object variable and then clicking on it in the IDE).
However, this only worked while stepping through the code, not during normal execution.
For this reason, I suspected the message might not be displaying long enough during normal code execution for Outlook to get the twist out of its knickers. I reasoned that it might be possible to insert a delay to allow sufficient time for this.
I tried out several methods of inserting a delay. Here is the one that worked for me. I created a form called
frmTimer
and added the freeware RSTimer OCX control (http://www.softpedia.com/get/Programming/Components-Libraries/RS-Timer.shtml) to it.
I set the
Interval
property of the OCX to 1000 ms.
The form is loaded right after displaying the message like this:
objMailItem.GetInspector.Activate
frmTimer.Show ' <-- form is loaded and displayed (it is not sufficient to just 'load' it)
objMailItem.Close OlInspectorClose.olDiscard
The form has one single event handler:
Private Sub RSTimer1_Timer()
Unload frmTimer
End Sub
When the event fires, the form is unloaded and code execution continues with
objMailItem.GetInspector.Activate
frmTimer.Show
objMailItem.Close OlInspectorClose.olDiscard ' <-- code execution continues here
Here is a complete function that allows the attachment to be detected correctly.
Function EmailHasAttachments(ByVal objMailItem As Outlook.MailItem) As Boolean
On Error GoTo ErrHandler
objMailItem.GetInspector.Activate
frmTimer.Show
objMailItem.Close OlInspectorClose.olDiscard
If objMailItem.Attachments.Count > 0 Then
EmailHasAttachments = True
Else
EmailHasAttachments = False
End If
ExitHere:
Exit Function
ErrHandler:
Debug.Print Err.Number, Err.Description
Select Case Err.Number
Case 12345
' handle the error
Case Else
MsgBox "An unknown error has occurred."
Exit Function
End Select
End Function

Related

UserInterfaceOnly = True is discarded when opening a file

I have an Excel+VBA file named "Myfile.xlsm" which needs that UserInterfaceOnly = True property so the VBA code can perform many operations without the user being aware.
I did place the following code to set UserInterfaceOnly = True property in the Workbook_Open event (also tried in the Workbook_Activate event) of "Myfile.xlsm".
Private Sub Workbook_Open()
Dim WSh As Worksheet
For Each WSh In ThisWorkbook.Worksheets
WSh.Protect Password:="myPWD", UserInterfaceOnly:=True
DoEvents
If WSh.ProtectionMode = False Then MsgBox "UIFOnly Init Failed on " & WSh.Name & " !!"
End If
Next WSh
End Sub
In some cases the UserInterfaceOnly is not set as expected and I get the "UIFOnly Init Failed on " message at opening "Myfile.xlsm" and as a consequence many other problems later.
EVEN BETTER: I created a new very simple "UnlockUIFOnly.xlsm" file which has the same code in Private Sub Workbook_Open().
If I open "UnlockUIFOnly.xlsm" first, protection works as expected. If I then open "Myfile.xlsm" (keeping "UnlockUIFOnly.xlsm" open) it works as expected.
If I close both files and open ONLY "Myfile.xlsm" it fails again.
I'm running Office 365 (version 2203 Build 16.0.150028.20512) 32 bits with Windows 10.
FURTHER OBSERVATION #1: I copied this not working "MyFile.xlsm" from its original directory to a new one.
When I opened it from its new directory, I got a banner to enable contents, and I answered yes. Then everything went smooth (No UIFOnly Init Failed on " message, no error 1004 ...). I checked some functionalities, so Excel asked whether I wanted to save changes, answered yes, then later if I wanted that document to be a trusted document, answered Yes as well.
At second open, I did not get any banner to enable contents (normal) but the problems were back.
FURTHER OBSERVATION #2: I again copied this not working "MyFile.xlsm" from its original directory to a new one.
When I opened it from its new directory, I got a banner to enable contents, and I answered yes. Then everything went smooth (No UIFOnly Init Failed on " message, no error 1004 ...). I checked some functionalities, so Excel asked whether I wanted to save changes, answered YES, then later if I wanted that document to be a trusted document, answered no. All further open tentatives asked to enable contents (answer yes) but were smooth.
It looks like declaring a document as trusted bypasses something or changes in which order events are generated, and has a huge impact on my problem

the remote server machine is unavailable error '462'

I have an excel userform a screen shot of which I would like to include in an outlook email. It works fine on my main programming computer, but when I run the same program on other computers I get the above error. The excel workbook is in the cloud and is run from the cloud (google drive) on various computers. the code is:
Function outlookEmail()
Dim doc As Object, rng As Range
Application.SendKeys "(%{1068})"
DoEvents
'ActiveSheet.Paste
With CreateObject("Outlook.Application").CreateItem(0)
.display
Set doc = .GetInspector.WordEditor
doc.Range(0, 0).Paste
.To = sDetail.Cells(myRow, headerDict.item("email"))
.Subject = "documents for you"
End With
End Function
the error is on the set doc line, if I mark it out, the error moves the the next line: doc.range...
Outlook is a singleton. That means you can't run two instances of the application at the same time. If the Outlook Application is already running under the different security context you may get into troubles. So, I'd suggest checking whether Outlook is already running and make sure it is running under the same security context, so you could reach the instance.
You can use the Visual Basic GetObject function to return a reference to the Application object that represents a session that is already running. Note that because there can be only one instance of Outlook running at any given time, GetObject usually serves little purpose when used with Outlook. CreateObject can always be used to access the current instance of Outlook or to create a new instance if one does not exist. However, you can use error trapping with the GetObject method to determine whether Outlook is currently running.
Read more about that in the Automating Outlook from Other Office Applications article.

VBA EXCEL VBA How to enable (check) specific Type Library in Tools/References programmatically?

That's basically my question. Doing googling didn't return anything that I am looking for, but basically I am running SOLIDWORKS from Excel and for that I need "sldworks 2016 Type Library" and "SOLDIWORKS 2016 Constant Type Library" to be enabled. Of course you'd say to do it manually, BUT my program is being run both, by people with and without Solidworks installed and if a user doesn't have SOLDIWORKS on their PC - the entire thing won't even run. So I am looking to enable and disable those two type libraries upon necessity in the code.
Could, someone, please help me?
P.S. I am not looking for any workarounds etc.
BUT my program is being run both, by people with and without Solidworks installed and if a user doesn't have SOLDIWORKS on their PC - the entire thing won't even run.
Is this what you are trying? The below code will first try to bind with an open instance of SOLIDWORKS. If it is not open, then it will try to create a new instance. Obviously if SOLIDWORKS is not installed then the CreateObject will fail but the code will not crash because of On Error Resume Next. Finally check if objSolid is not nothing. This is late binding and you do not have to set any references.
Dim objSolid As Object
'~~> Establish an SOLIDWORKS application object
On Error Resume Next
Set objSolid = GetObject(, "SldWorks.Application")
'~~> If not found then create new instance
If Err.Number <> 0 Then Set objSolid = CreateObject("SldWorks.Application")
Err.Clear
On Error GoTo 0
If objSolid Is Nothing Then
MsgBox "SOLIDWORKS not installed"
Exit Sub
End If
'
'~~> Rest of your code
'
EDIT
You cannot say Solidworks is not properly documented without putting in the right efforts to search. It took me less than 30 seconds to find this SOLIDWORKS Example of Late Binding. Of course their code will fail if the user doesn't have SOLIDWORKS and that is because they have not done proper error handling. My answer above does that for you.
Their website has all the information that you need. You just need to put in the right efforts to search. As I mentioned in the chat below, when you convert the code into late binding, you will have to search for the value of those constants. No one will give them to you in a platter. :) You can either search Google with swDocPART Constant value or as #FunThomas pointed out, type ?swDocPART in Immediate Window to get the value when the reference to SOLIDWORKS has been established.

How to work around Excel 2016 halting without message when trying to assign variable to VBProject?

System Details.
Windows 10
Excel 365 64-bit V16.0 (Apps for Enterprise)
Issue.
I have a macro that opens a file, checks if the user has allowed programmatic access to the VBA Project in the trust center and raises an alert if they have not. This works fine on windows 7 machines with both 32bit and 64bit Excel from 2013 onwards.
The specific problem I am having on the Windows 10 machine is that when workbooks.open(path) is executed the file opens but in the VBA Project explorer window the VBAProject object for that file does not appear. I also get a popup saying that code cannot be run in break mode when I try this while stepping through the code. When run on Win 7 with this version of Excel and others both 32 and 64-bit the VBAProject object appears and no popup is generated.
This lack of the VBA Project causes an issue later when I run set vbproj = ActiveWorkbook.VBProject. At this point when stepping through the code execution halts with no messages at all. The Project pops up in the Project explorer window and it takes me to a module in the opened workbook. This gets opened with Design Mode turned on and when you click to turn it off I get an error message saying 'Macros have been disabled'
Notes
set vbproj = ActiveWorkbook.VBProject works fine if the file is open and the VBAProject is visible in the Project explorer window.
If the file being opened does not contain a macro then it works correctly.
I have made sure that the files are in a Trusted Location.
I have set Enable all macros in the Macro Settings of the Trust Center.
When opening the files manually I do not get any alerts that macros have been disabled by an administrator and I do not get any message asking if I want to enable macros.
I have looked at W10 group policies to see if there is one that would block VBAProjects / Macros from files opened via VBA and there does not appear to be one as far as I can see.
The Trust Center setting for programmatic access to the VBA Project does not matter to this test case. It will return True if it is allowed and False if it is not allowed.
This has been tested on another Windows 10 laptop with the same version of Excel 64-bit and it has the same result so is not an issue with a specific users laptop.
I removed the folder from the Trusted Location on the Windows 7 machine and the code still executes correctly and returns True/False.
In the actual macro this check is done for each opened file in a loop and the variant vbproj is used to remove data from the modules within that project. I have considered working around the issue by using Application.onTime and that may be a solution but have not spent much time on that and with how it halts it may not be viable.
Attempted Solutions
I have tried set wb = workbooks.open(path) to open the workbook and then using set vbproj = wb.VBProject but it has the same behavior as above.
I have tried doing ActiveWorkbook.Activate and similar actions to see if that will make the VBA project appear, it does not.
I have tried setting Application.FileValidation = msoFileValidationSkip before opening the file, this does not change the behavior.
I have tried setting Application.EnableEvents=False before opening the file, this does not change the behavior.
I have tried making vbproj a variant, an object and a VBProject, this does not change the behavior.
Steps to Recreate
Create a new workbook.
Put the below code into Module 1.
Function projectAccess()
Dim vbproj As Variant
On Error GoTo noaccess
Set vbproj = ActiveWorkbook.VBProject 'If access is denied an error is raised.
projectAccess = True
Exit Function
noaccess:
projectAccess = False
End Function
Sub openfile()
Dim filepath As String
filepath = Application.ThisWorkbook.Path
Workbooks.Open (filepath & "\openfile.xlsm")
Debug.Print projectAccess
End Sub
Save the workbook
Create a 2nd workbook, in my case it was called openfile.xlsm and put some code into Module 1.
put both workbooks in the same location and make sure it is a Trusted Location in Excel.
run openfile().
If successful the immediate window will display True / False depending on the Trust Center setting.
I am out of ideas. Any suggestions for some setting that I may have overlooked to make the Win 10 machines behave the same as the Win 7 machines or suggestions for a possible work around?
Even if it is a group policy setting that would be something I can raise with IT as long as I know what to ask for.
Many Thanks
Andrew
EDIT: Thanks to Rory in the comments the issue was making sure that the automation security was set like so Application.AutomationSecurity = msoAutomationSecurityLow as the way the new Win 10 + Office 64 systems have been set up by my IT dept is to have it default to msoAutomationForceDisable

ExportAsFixedFormat fails sometimes

I have a spreadsheet with forms and macros that worked until recently. The first time I saw the described behavior was the first time I tried using this particular function in Excel 2016 (Windows 10), though I'm not sure that's the cause.
The issue I'm having is with the following line
Worksheets("Label Template - 100X150").ExportAsFixedFormat Type:=xlTypePDF, _
Filename:=pdfFilePath, Quality:=xlQualityMinimum, _
IncludeDocProperties:=False, _
IgnorePrintAreas:=False, OpenAfterPublish:=True
Which comes from the following macro:
Sub PDFLabelsSheet()
'On Error GoTo errHandler
'enter name and select folder for file
strFile = "Labels_PrintGroup-" & lstPrintGroup.Value _
& "_" _
& Format(Now(), "yyyy-mm-dd\_hhmm") _
& ".pdf"
strFile = ThisWorkbook.Path & "\" & strFile
Worksheets("Label Template - 100X150").Visible = True
UnprotectTab "Label Template - 100X150"
pdfFilePath = Application.GetSaveAsFilename(InitialFileName:=strFile, _
FileFilter:="PDF Files (*.pdf), *.pdf", _
Title:="Select Folder and FileName to save")
If pdfFilePath <> "False" Then
Worksheets("Label Template - 100X150").Select
Worksheets("Label Template - 100X150").Range("A1").Select
Worksheets("Label Template - 100X150").Range("A1").Activate
Cells.Activate
Worksheets("Label Template - 100X150").PageSetup.FirstPageNumber = 1
Worksheets("Label Template - 100X150").ExportAsFixedFormat Type:=xlTypePDF, _
Filename:=pdfFilePath, Quality:=xlQualityMinimum, _
IncludeDocProperties:=False, _
IgnorePrintAreas:=False, OpenAfterPublish:=True
End If
exitHandler:
ExecutionEnd
Exit Sub
errHandler:
MsgBox "Something went wrong, a PDF could not be created", vbCritical
Resume exitHandler
End Sub
I've tried permutations of the ExportAsFixedFormat function, changing it to Worksheets("name"), (number), ActiveSheet.... etc.
Prior to executing this particular Sub, the worksheet is unhidden and unprotected. I've tried setting the entire range as PrintArea, I've tried selecting and activating the range to be exported as well.
The most frustrating part is it works sometimes. I've gone as far as putting in code that spits out every property of the PageSetup collection to make sure that something is not blowing things up since the output depends so strictly on the page setup.
When I navigate to this worksheet manually and choose the export function from the file menu, I get the same error. If I click around in that worksheet for a bit the Export function as well as the Macro work.
The PDFLabelSheets Sub does get called from another Sub (invoked by a form's button press) which compiles a boatload of data into this tab, though I've ruled it out as the culprit as successive runs of just the PDF code will succeed then fail without running the other code.
I’ve recently solved a problem that was similar in the following ways:
It involved the failure of the ExportAsFixedFormat, Type:=xlTypePDF
statement
The statement failed with no error message; it simply
stopped the execution of the VBA code
The failure was inconsistent,
and the conditions for failure or success were not obvious
Below is a summary of how I solved it; perhaps this will suggest some useful approaches you can use.
My Excel VBA code was running under Windows 7 as an unattended, end-of-day scheduled task in the background, usually when no one was logged in. Most of the time the code would work, but sometimes it would not. I could not capture the screen after a crash, and capturing the various window contents did not help: there was no useful diagnostic text. I finally tried logging program execution milestones to a disk file, reopening and closing the file for each milestone, so no text would be lost if the program subsequently crashed. That isolated the problem to the ExportAsFixedFormat statement but did not diagnose the problem.
I finally tried having the VBA code save a copy of the workbook just prior to the point of failure. I was hoping that, on re-opening the copy, I’d be able to see what was wrong. That did not help. However, I did notice something strange when comparing the .xlsm files saved on successful and unsuccessful executions – the former were just a little larger.
Digging into the .xlsm files (which are really .zip files), I noticed that, in the xl\printerSettings subfolder, the printerSettings1.bin file was larger after successful runs. Using the SysInternals Strings utility to inspect the .bin files, I found that, in the unsuccessful runs, this file contained only the name of the default printer on the home computer where I had developed the application, which was not the office computer where it was executing. On the successful runs, the .bin file also contained the name of the default printer in the office.
This was the critical difference. In that office, the main computer executes the Excel program shortly after the end of the working day. Ordinarily, during the day this computer prints to a laser printer (set as the default printer) attached to another computer on the network, and that other computer is turned off at the end of the working day. Therefore, depending on accidents of timing, sometimes the end-of-day Excel program would see a valid, available default printer, sometimes not.
Some Excel commands, including the command to save as a .pdf, work properly only when the active printer is valid. There is a similar observation at can't set PageSetup.Orientation = xlLandscape from MS Project, concerning assignments to the fields of .PageSetup. In my case, failing to work properly meant crashing without generating any error message.
I later discovered that my problem was not simply the unavailability of the default laser printer over the network; it was also caused by something irregular about the printer definition. I had added code to log the VBA property Application.ActivePrinter; just prior to a crash, it was returning the value “unknown printer (check your Control Panel)”, rather than containing the name of the printer. When I re-installed the default printer, Application.ActivePrinter always returned the proper printer name, whether or not that printer was available for use, and the program stopped crashing.
My problem was a true Heisenbug – it disappeared whenever I re-ran the Excel workbook at random times. That ultimately turned out to help me confirm its diagnosis. Running unattended, sometimes there was no valid printer. When I logged into my account and ran it attended, either it was during the business day or else LogMeIn temporarily assigned my home printer as a valid default printer. This finally made sense of the fact that the program failed only when it wasn’t being closely observed at the time of execution.
In summary, I’d look at inconsistent printer availability and irregular printer installation as possible underlying causes of failure to consistently export .pdf files using Excel VBA.
Frogrammer-Analyst's analysis is great, but the error is not that ambiguous. You will not have this issue if you login to the server using the user that is running the unattended script. But if you sign out and then try rerunning your script unattended you will see that no printers are mapped and {ExportAsFixedFormat} fails for PDF and or XPS formats.
I have found a solution for my case. A true headeache. Maybe it can help others:
Try uncheking the "PDF/A compliant" option under Options dialog when you export as PDF. After that, run the VBA code again.
For my, it was the solution.
PDF Options

Resources