I have a problem with declaring Folder objects.
I'm trying to type plik_zip Folder, but VBA editor (in Excel 2013) converts it to folder
Sub Submitt()
Dim plik_zip As folder
Reference changing makes no effect.
folder is not a type in your case and besides VBA is not case sensitive.
Perhaps you want to do something like this:
Set objFSO = CreateObject("Scripting.FileSystemObject")
' Get the folder object
Set objFolder = objFSO.GetFolder("C:\Temp")
The VBE will do this if you declared a variable named folder anywhere else in your code. You can "correct" (VBA is not case sensitive) the case it uses by typing Dim Folder on an empty line, move the cursor off the line, then delete it. It will use the case of the last variable you declared, regardless of scope.
Note that having objects declared as 'folder' makes no difference to the compiler, but in general I avoid using the names of types as variable for this very reason.
In normal mode without any other code in your Excel you after you type Dim f As FolDer it will never change.
Now add a new line like this:
Dim folder As Object
Then, It will change that line to:
Dim f As folder
Now, Delete all codes! now add this code again: Dim f As FolDer you will see it changes to Dim f As folder !!!
This will be repeated until you close the Excel.
This is a cause of caching variable names in VBE.
Related
All,
I wrote some VBA code to move the currently selected email folder in an Outlook session to a folder called "archive 2023". It did not work; I spent ages working out why but could not fix the code. Eventually, I settled it by researching and then coming at the problem from a different angle. Although happy, and learning a lot, I still don't know why my original code did not work. And that bugs me (if you excuse the pun).
I'll start with my original code that did not work - I've gone heavy on the comments.
Sub archive_a_folder()
'firsty create the variable I'll store the current folder in as an object
Dim current_folder As Outlook.Folder
'then put the folder, selected in the active instance of Outlook, into the variable
Set current_folder = Application.ActiveExplorer.CurrentFolder
Debug.Print current_folder.Name 'I put this in to check the above worked - and it did!
'I wrote a little code to find out the EntryID property of the folder called "archive 2023"
'I then put the EntryID (which is a string) into a variable
Dim archiveID As String
archiveID = "xxxx" 'instead of xxxx this is a really long string
'I then create a MAPI namespace so I can use the GetFolderFromID method
Dim ns As Outlook.NameSpace
Set ns = Application.GetNamespace("MAPI")
'I then create an Outlook.Folder variable and put the "archive 2023" folder in there by ...
'... using the GetFolderFromID method using the EntryID
Dim archive_folder As Outlook.Folder
Set archive_folder = ns.GetFolderFromID(archiveID)
Debug.Print archive_folder.Name 'Did this to check the above works and it does!
'So at this point I thought I had two correctly assigned Outlook.Folder object variables ...
'... One assigned with the folder that needs moving and one being the destination folder
'The documentation states the MoveTo method should be used like this...
'... Folder.MoveTo(Folder) with the first Folder (an object) being moved to the second.
current_folder.MoveTo(archive_folder)
'I get an object expected error.
End Sub
Running the code line by line proved everything was working right up to current_folder.MoveTo(archive_folder).
The debugging print outs show that the variables current_folder and archive_folder are correctly assigned. I even printed out the variables' types to ensure they were both of the Folder type and they were (they were actually type FolderMAPI but I think thats OK).
I tried creating a new Folder.Outlook variable and having the below statement:
set new_folder = current_folder.MoveTo(archive_folder)
or
new_folder = current_folder.MoveTo(archive_folder)
but niether worked. (I saw that the MoveTo method returned a Folder so that's why I tried that.
Eventually, after research, I re-wrote is like this and it worked.
Sub archive_folder()
'get the current folder and put it in a Folder variable
Dim current_folder As Outlook.Folder
Set current_folder = Application.ActiveExplorer.CurrentFolder
'get a namespace variable so I can use some of its methods later
Dim ns As Outlook.NameSpace
Set ns = Application.GetNamespace("MAPI")
'create inbox as a Folder variable
Dim inbox As Outlook.Folder
'using a namespace method assign the actual in-box to the inbox variable
'olFolderInbox is an inbuilt referene to the default in box folder
Set inbox = ns.GetDefaultFolder(olFolderInbox)
'create a Foler variable that will be assigned the destination folder
Dim archive_folder As Outlook.Folder
'this seems oddly cumbersome but works!
'take parent of the inbox Folder and look for "archive 2003" beneath it
'assign this to the archive folder variable.
Set archive_folder = inbox.Parent.Folders("archive 2023")
'The using the MoveTo method move the current_folder to the
'archive folder
current_folder.MoveTo archive_folder
'when I check in my Outlook window, its moved!
Exit Sub
End Sub
If I had to guess at what the problem is, its something to do with GetFolderFromID not returning a Folder object with all the properties needed for the MoveTo method to work.
I'm probably thinking too 'real world' mistakenly imagining folders actually being stored in other folders. The system probably just looks as the Parent and Folders properties of all the folders and builds a tree for the GUI. Mayube GetFolderFromID does not return these property values correctly so MoveTo does not think its an object at all this the error. This would seem likely if MoveTo just messed about with some of the parent / folders properties.
If this is the case though, what would be the point of the GetFolderFromID function?
Or maybe I'm being punished for trying to skip learning the basics of a language.
Any help?
Aldus
Edit:
I can't believe I did not clock that I should not have used parentheses for the MoveTo method. ##DmitryStreblechenko saw me right in the comments.
To make me feel better I massively reduced the size of the code...
Sub archive_a_folder()
archiveID = "xxx" `xxx is the EntrhyID of the destination folder
Application.ActiveExplorer.CurrentFolder.MoveTo Application.GetNamespace("MAPI").GetFolderFromID(archiveID)
End Sub
:-)
I want to show this question as answered but want to make clear it was answered in the comments and not by me. In essence, and I can't believe I made this mistake, I used parenthesis when I should not have.
Where I used current_folder.MoveTo(archive_folder) I should have used current_folder.MoveTo archive_folder
I fell for the old trick of assuming my syntax was correct but there was some deeper problem. But no, I just used a couple of brackets!
I used to code many years ago so have enough of an understanding to risk skipping some of the basics when learning a new language but the danger of that is what led to this question.
Oh well, you live and learn.
Good afternoon guys!
I looked around, but I'm not finding anything that addresses my particular issue, so I'll do my best to explain.
Specs:
Excel 2007, VBA, Outlook 2007
Okay, so I've been reworking some scripts that I created to automate our reports in Excel / Avaya CMS. For the past few years I've been the sole person doing our reports, so it wasn't ever necessary to set things up on anyone else's computers. However, things are changing and I'm in the process of updating the scripts / training others to use them. At the moment, when I put my scripts on their computer, I have to go into the VBA code and manually set every reference to their own relative folder paths / outlook folder paths. Painless enough, except when I do any type of changes to the scripts and have to go through the whole process again on each computer.
So this was my solution: Create a config worksheet on the automated reporting workbook, on that config worksheet store the file paths, and in the code simply use variables to reference the config worksheet. This should make it as easy as setting the variables once from the config on a new computer without having to touch any of the lines of code.
Problem: At midnight there is data that is emailed to us from another office. We use Outlook at this office, so I've simply been having it go to the folder specified in the scripts, download the attachments, and then use the downloaded data for the reports. Since everyone sets up their own outlook folders, the paths inside of outlook are different for each user. Since VBA is accessing a worksheet to grab the config information from a cell, it's returning the path for Outlook folders as a string value. However, the outlook folder variable is of Object type, and so it doesn't allow me to use the string variable as it's value, even though the string itself is the actual value the object needs (just not as a string). So is it possible to convert the string value to a value that can be used in the Object variable?
Worksheet Config Cell Value (B5)- The String Value
outNamespace.Folders("Mailbox - Some Guy").Folders("Reports").Folders("ImportantData")
Code:
'Config tab
Dim serverConfig As Worksheet
Set serverConfig = Sheets("CONFIG")
Dim dirOutlookData As String
dirOutlookData = serverConfig.Range("B5").Value
Dim outFolder As Object
Set outFolder = dirOutlookData
Any ideas? Since the string that's returning for dirOutlookData is the value needed for the object variable value, how can I convert the value from the string variable so it can be used in such a way?
Thanks in advance.
Seems too convoluted a solution. Nobody could share their VBA.
In the example provided
outNamespace.Folders("Mailbox - Some Guy").Folders("Reports").Folders("ImportantData"
you could instead use this directly in the VBA
Set mailboxFolder = outNamespace.GetDefaultFolder(olFolderInbox).Parent
You now have the "Mailbox - Some Guy" folder in a generic way not needing to specify "Some Guy".
Set myFolder = mailboxFolder.Folders("Reports").Folders("ImportantData")
I have a code block (which works) to open a file.
Dim AppVisio
Set AppVisio = CreateObject("visio.InvisibleApp")
Dim vsoDoc
Set vsoDoc = AppVisio.Documents.Open("PathName\Drawing1.vsd")
However, when this file is already open, I want it to be automatically closed without saving changes.
I could not find code such as
AppVisio.Documents.Close ("PathName\Drawing1.vsd")
Any other options to force close the file should it be open?
Dim vsoDoc
You've declared it as an implicit Variant - this would be equivalent:
Dim vsoDoc As Variant
And if you place a breakpoint immediately after the Set vsoDoc = statement, go to the immediate pane (Ctrl+G) and type
?TypeName(vsoDoc)
You'll see that it will print Document. Hence, you can declare it with a Document type instead:
Dim vsoDoc As Document
And then when you want to close this vsoDoc, you work with that object and call its Close method:
Set vsoDoc = AppVisio.Documents.Open("PathName\Drawing1.vsd")
'do stuff...
vsoDoc.Close
That vsoDoc variable is your document object. Declaring it As Document will give you IntelliSense/AutoComplete so when you type the dot in vsoDoc., you'll see a drop-down in the editor showing you all the document's members.
If you're already in Visio, there's no need to late-bind everything; you already have a reference to the Visio object model. Early binding makes it much easier to know which types are involved and what their members are.
The method you are looking for is part of the Document object (not Documents)
Click Here to see the Document Close Method
I am trying to build a Addin for Outlook that allows a user to select a folder they want emails moved to when they hit a certain button. I am ussing a project setting called "EmailDestFolder" to define the folder after the user selects it, thats done as follows:
Dim objOutlook As Object
Dim objOlNamespace As Object
objOutlook = CreateObject("Outlook.Application")
objOlNamespace = objOutlook.GetNamespace("MAPI").PickFolder
If objOlNamespace.Name.Length >= 1 Then
My.Settings.EmailDestFolder = objOlNamespace
End If
Issue is this doesnt work when the setting type is set to "String" I tried changing the setting type to: "Microsoft.Office.Interop.Outlook.MAPIFolder" but I get an error saying that settings cannot be an abstract type. Is there a way to change it to something like a Variant or Object type so I can set the folder.
Read the MAPIFolder.EntryID property to a string variable. When you need to open that folder later, use Namespace.GetFolderFromID.
I'm deploying an early bound styled VBA module that needs Scripting.Dictionary and RegExp.
The script, predictably, fails when it runs on another computer.
The user has to go to Tools->Reference in the VBA IDE and add a reference to those two libraries manually to make it work.
Hence lies the problem. Asking the non-technical end user to go to the IDE and manually add references is asking way too much of them.
The other alternative is to rewrite the whole (very long script written by someone else) to use late binding. I rather not take this path if there are other methods.
As an altervative, some people suggest adding a reference programatically like so:
Application.VBE.ActiveVBProject.References.AddFromFile [Path to library]
Is this the correct solution and if so are there any downsides of this strategy?
If not, are there other methods that will to enable the code to remain early bound yet does not require references to be added manually by the user.
Suggestions involving direct calls to the Win32/64 API are also welcome.
Thanks.
In my own limited environment (small # of other people using spreadsheets I develop, relatively standard machine setups), if I create the file and add the references, and then give a copy to someone else, they can open it with no problems and not have to do anything, so keep that in mind with this answer. (I'm wondering why that doesn't work for you.) Also, this was with Excel.
Rather than adding a reference from a file path, you might consider using the GUID property instead.
Here is some code I once used to automatically create references in a newly created workbook. (It's part of a script that would export code, references, and unit tests on worksheets to text for use with Subversion and then later reconstitute the workbook from the text files.) You might find it useful to your situation. (EH and cleanup removed to keep it short...)
'Export refs in existing workbook to text file
Private Sub exportRefs_(srcWbk As Workbook)
Dim fs As FileSystemObject
Set fs = New FileSystemObject
Dim tsout As TextStream
Set tsout = fs.CreateTextFile(fs.BuildPath(getTargetPath_(srcWbk), "refs.refs"))
Dim ref As Reference
For Each ref In Application.ThisWorkbook.VBProject.References
Call tsout.WriteLine(ref.GUID)
Next ref
'<EH + cleanup...>
End Sub
'Add refs to newly created workbook based on previously exported text file
Private Sub importRefs_(wbk As Workbook, path As String)
Dim fs As FileSystemObject
Set fs = New FileSystemObject
Dim tsin As TextStream
Set tsin = fs.OpenTextFile(path)
Dim line As String
Dim ref As Reference
While Not tsin.AtEndOfStream
line = tsin.ReadLine()
Set ref = Nothing
On Error Resume Next
Set ref = wbk.VBProject.References.AddFromGuid(line, 0, 0)
On Error GoTo 0
If ref Is Nothing Then
Debug.Print "add failed: " & line
End If
Wend
'<EH + cleanup...>
End Sub
Like, I said, limited environment, but hopefully it helps.