I have searched inside a folder in outlook, found all emails with a defined title, and downloaded their attachments into a folder via Excel VBA.
I now need to print those to new pdfs via Adobe Reader XI through VBA - as they are password protected- to be able to convert to RFT (I use VBA to get data from the PDF converted to RFT).
Somehow the correct RF layout is only created if the already saved pdf file is printed to a secondary pdf- Saving doesn't work - whether by explorer pdf viewer, Nitro or Adobe makes no difference.
I have tried Attachment.Printout but get error that the object does not support, am not able to find the option within a Shellexecute that will allow printing to file, as the main advice online allows printing via:
Call apiShellExecute(Application.hwnd, "print", strPathAndFilename, vbNullString, vbNullString, 0)
with options /p and /h for printing. any help on how to accomplish this with or without shell (or directly convert secured pdf to rft is appreciated).
The code I use ( borrowed and edited from VBA to loop through email attachments and save based on given criteria) for automatically downloading the files is listed bellow:
Sub email234()
Application.ScreenUpdating = False
Dim sPSFileName As String
Dim sPDFFileName As String
Dim olApp As Object
Dim ns As Namespace
Set olApp = CreateObject("Outlook.Application")
Set ns = olApp.GetNamespace("MAPI")
Dim oItem As Object
Dim olMailItem As Outlook.MailItem
Dim olNameSpace As Object
Dim olFolder As Object
Dim olFolderName As String
Dim olAtt As Outlook.Attachments
Dim strName As String
Dim sPath As String
Dim i As Long
Dim j As Integer
Dim olSubject As String
Dim olSender As String
Dim sh As Worksheet
Dim LastRow As Integer
olFolderName = "\\Subscriptions\Inbox" 'ThisWorkbook.Worksheets("Control").Range("D10")
olSender = "Argus Alerts" 'ThisWorkbook.Worksheets("Control").Range("D16")
sPath = Application.FileDialog(msoFileDialogFolderPicker).Show
sPathstr = Application.FileDialog(msoFileDialogFolderPicker).SelectedItems(1)
Set olNameSpace = olApp.GetNamespace("MAPI")
'check if folder is subfolder or not and choose olFolder accordingly
Set olFolder = ns.Folders("Subscriptions").Folders("Inbox")
strName = "Argus Ammonia"
h = 2
For i = 1 To olFolder.Items.Count
If olFolder.Items(i).Class <> olMail Then
Else
Set olMailItem = olFolder.Items(i)
'check if the search name is in the email subject
'If (InStr(1, olMailItem.Subject, olSubject, vbTextCompare) <> 0) Then
If (InStr(1, olMailItem.Sender, olSender, vbTextCompare) <> 0) Then
With olMailItem
For j = 1 To .Attachments.Count
strName = .Attachments.Item(j).DisplayName
'check if file already exists
If Not Dir(sPathstr & "\" & strName) = vbNullString Then
strName = "(1)" & strName
Else
End If
If Err.Number <> 0 Then
Else
.Attachments(j).SaveAsFile sPathstr & "\" & strName
End If
Err.Clear
Set sh = Nothing
'wB.Close
On Error GoTo 0
h = h + 1
Next j
End With
End If
End If
Next i
Application.ScreenUpdating = True
MsgBox "Download complete!", vbInformation + vbOKOnly, "Done"
End Sub
You can hard code the path to your EXE, please refer to the below code:
Declare Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" _
(ByVal lpFile As String, ByVal lpDirectory As String, ByVal lpResult As String) As Long
Sub Test_Printpdf()
Dim fn$
fn = "C:\Users\Ken\Dropbox\Excel\pdf\p1.pdf"
PrintPDf fn
End Sub
Sub PrintPDf(fn$)
Dim pdfEXE$, q$
pdfEXE = ExePath(fn)
If pdfEXE = "" Then
MsgBox "No path found to pdf's associated EXE.", vbCritical, "Macro Ending"
Exit Sub
End If
q = """"
'http://help.adobe.com/livedocs/acrobat_sdk/10/Acrobat10_HTMLHelp/wwhelp/wwhimpl/common/html/wwhelp.htm?context=Acrobat10_SDK_HTMLHelp&file=DevFAQ_UnderstandingSDK.22.31.html
'/s/o/h/p/t
Shell q & pdfEXE & q & " /s /o /h /t " & q & fn & q, vbHide
End Sub
Function ExePath(lpFile As String) As String
Dim lpDirectory As String, sExePath As String, rc As Long
lpDirectory = "\"
sExePath = Space(255)
rc = FindExecutable(lpFile, lpDirectory, sExePath)
sExePath = Left$(sExePath, InStr(sExePath, Chr$(0)) - 1)
ExePath = sExePath
End Function
Sub Test_ExePath()
MsgBox ExePath(ThisWorkbook.FullName)
End Sub
Added an API method to find the path, the command line parameters don't work as well with the newer Adobe Acrobat Reader DC.
For more information, please refer to these links:
Printing a file using VBA code
Print a PDF file using VBA
Related
I made the code myself, and I am by no means someone with a lot of coding experience. I made loops that auto validate my files here to accommodate the different strength of machines at my current workplace. While these work fine a lot of the times, sometimes I get a "file not found" error pointing at my FileLen(NewFileName) on line 53. Which is weird because the file was referred to above this line. Could anyone help debug this?
here's the code:
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal Milliseconds As LongPtr)
Sub PrintAttachments()
'Section where I declare all the variables the code uses.
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Dim olFolder As Outlook.Folder
Dim RootFol As Outlook.Folder
Dim Item As Outlook.MailItem
Dim Items As Outlook.Items
Dim Att As Outlook.Attachment
Dim OldLen As Long
Dim NewLen As Long
Dim p As Object
Dim q As Object
Dim qLoop As Long
Dim TempFolder As Scripting.Folder
Dim FSO As Scripting.FileSystemObject
Dim TempDir As String
Dim NoSpace As String
Dim NewFileName As String
Dim Acrobat As String
Dim Qo As String
Qo = Chr(34)
'Set Outlook Objects in Variables to simplify code writing and understanding.
Set FSO = New Scripting.FileSystemObject
Set olApp = New Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set RootFol = objNS.GetDefaultFolder(olFolderInbox)
Set olFolder = RootFol.Folders("Print")
Set Items = olFolder.Items
'Set the location of a temp folder to store temporary PDF.
TempDir = Environ("LOCALAPPDATA") & "\TempPrint"
i = 1
'Check if the temp folder exists, if not, create it. If it exists, confirm its value to insert into future filename.
If FSO.FolderExists(TempDir) Then
Set TempFolder = FSO.GetFolder(TempDir)
Else
Set TempFolder = FSO.CreateFolder(TempDir)
End If
'Clean up the PDF used last time the macro was run.
Shell ("cmd /c Del /A /F /S /Q " & TempDir & "\*.*")
'Validate that the last command is done running before continuing.
While FSO.GetFolder(TempDir).Size > 0
Sleep (50)
Wend
'Loop that searches in every mail in "Print" folder for .pdf type attachments.
For Each p In Items
If p.Class = olMail Then
Set Item = p
If Item.Attachments.Count > 0 Then
For Each Att In Item.Attachments
If Att.FileName Like "*.pdf" Then
'Replace every space (as string) found in the attachment name with "_", then write a new filename including
'the time and date of the mail's reception time to ensure a unique name for each attachment. Then save the file in the temporary folder path.
NoSpace = Replace(Att.FileName, " ", "_")
NewFileName = TempFolder.Path & "\" & Format(Item.ReceivedTime, "yyyy-mm-dd_hh-mm-ss_") & NoSpace
'Save the file and validate it exists before continuing.
Att.SaveAsFile NewFileName
Do
If FSO.FileExists(NewFileName) Then
Exit Do
Else
DoEvents
Sleep (60)
End If
Loop
'Loop to validate that the file has finished saving properly before sending a print request.
NewLen = 1
Do While NewLen > OldLen
Sleep (60)
OldLen = NewLen
NewLen = FileLen(NewFileName)
If NewLen < OldLen Then
NewLen = OldLen + 1
End If
Loop
OldLen = 0
'Send a Print request through Adobe Acrobat Reader DC.
Acrobat = "cmd /c " & Qo & "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" & Qo & " /n /s /h /t "
Shell (Acrobat & NewFileName)
End If
Next Att
End If
End If
Next p
'Move every email back into the inbox
For qLong = Items.Count To 1 Step -1
Set q = Items(qLong)
If q.Class = olMail Then
q.Move RootFol
End If
Next qLong
End Sub
I'm coding macros in vba Word and on visio 2013. I wanted to open a fileDialog so that the user can choose where to save his file.
I succeded in word, but in visio it doesn't to work the same.
I wrote this in word:
Dim dlg As FileDialog
Dim strPath As String
'Boite de dialogue pour choisir où enregistrer son fichier
Set dlg = Application.FileDialog(msoFileDialogFolderPicker)
With dlg
.InitialFileName = Application.ActiveDocument.Path
.AllowMultiSelect = False
.Title = "Choisir le répertoire d'enregistrement"
.Show
End With
strPath = dlg.SelectedItems(1)
but it doesn't work in visio. Can someone help me do the same in visio?
If you don't want to use other office application, you can use winapi OpenFileDialog to achieve similar behavior, but it won't as easy as with .FileDialog.
See more details here:
Open File Dialog in Visio
The module source code (compatible with Visio 2010 and above, i.e. with editions which have x64 version). For the original source code, compatible with previous versions, chech the above link.
'// This is code that uses the Windows API to invoke the Open File
'// common dialog. It is used by users to choose a file
Private Declare PtrSafe Function GetOpenFileName Lib "comdlg32.dll" _
Alias "GetOpenFileNameA" (OFN As OPENFILENAME) As Boolean
Private Type OPENFILENAME
lStructSize As Long
hwndOwner As LongPtr
hInstance As LongPtr
lpstrFilter As String
lpstrCustomFilter As String
nMaxCustFilter As Long
nFilterIndex As Long
lpstrFile As String
nMaxFile As Long
lpstrFileTitle As String
nMaxFileTitle As Long
lpstrInitialDir As String
lpstrTitle As String
flags As Long
nFileOffset As Integer
nFileExtension As Integer
lpstrDefExt As String
lCustData As Long
lpfnHook As LongPtr
lpTemplateName As String
End Type
Public Sub OpenFile(ByRef filePath As String, _
ByRef cancelled As Boolean)
Dim OpenFile As OPENFILENAME
Dim lReturn As Long
Dim sFilter As String
' On Error GoTo errTrap
OpenFile.lStructSize = LenB(OpenFile)
'// Sample filter:
'// "Text Files (*.txt)" & Chr$(0) & "*.sky" & Chr$(0) & "All Files (*.*)" & Chr$(0) & "*.*"
sFilter = "All Files (*.*)" & Chr(0) & "*.*"
OpenFile.lpstrFilter = sFilter
OpenFile.nFilterIndex = 1
OpenFile.lpstrFile = String(257, 0)
OpenFile.nMaxFile = Len(OpenFile.lpstrFile) - 1
OpenFile.lpstrFileTitle = OpenFile.lpstrFile
OpenFile.nMaxFileTitle = OpenFile.nMaxFile
OpenFile.lpstrInitialDir = ThisDocument.Path
OpenFile.lpstrTitle = "Find Excel Data Source"
OpenFile.flags = 0
lReturn = GetOpenFileName(OpenFile)
If lReturn = 0 Then
cancelled = True
filePath = vbNullString
Else
cancelled = False
filePath = Trim(OpenFile.lpstrFile)
filePath = Replace(filePath, Chr(0), vbNullString)
End If
Exit Sub
errTrap:
Exit Sub
Resume
End Sub
Although it says that Visio has Application.FileDialog, it will fail in Visio VBA.
However as a workaround, you can access the FileDialog object through Excel, Word or other Office applications. The code below does it using Word as you are using both.
This is a function that will return an array containing all the path from the selected files :
Public Function Get_File_via_FileDialog() As Variant
'fd will be a FileDialog object
Dim fd As Object
'Array of pathes
Dim A()
ReDim A(0)
'Create an Word object. You can access the FileDialog object through it.
Dim WordApp As Object
On Error Resume Next
Set WordApp = GetObject(, "Word.Application")
If Err.Number > 0 Then Set WordApp = CreateObject("Word.Application")
On Error GoTo 0
WordApp.Visible = True 'This statement necessary so you can see the FileDialog.
'Declare a variable to contain the path
'of each selected item. Even though the path is aString,
'the variable must be a Variant because For Each...Next
'routines only work with Variants and Objects.
Dim vrtSelectedItem As Variant
'Create a FileDialog object as a File Picker dialog box.
Set fd = WordApp.FileDialog(msoFileDialogFilePicker)
'Use a With...End With block to reference the FileDialog object.
With fd
'Use the Show method to display the File Picker dialog box and return the user's action.
'The user pressed the button.
If .Show = -1 Then
WordApp.Visible = False 'Hide the Excel application
'Step through each string in the FileDialogSelectedItems collection.
For Each vrtSelectedItem In .SelectedItems
'vrtSelectedItem is a string that contains the path of each selected item.
'You can use any file I/O functions that you want to work with this path.
'This example displays the path in a message box.
A(UBound(A)) = vrtSelectedItem
ReDim Preserve A(UBound(A) + 1)
Next vrtSelectedItem
'The user pressed Cancel.
End If
End With
'Set the object variable to nothing.
ReDim Preserve A(UBound(A) - 1)
Set fd = Nothing
Set xl = Nothing
Get_File_via_FileDialog = A
End Function
I've got a code from here and I'm tweaking it for my need. My need is quite simple: I need it to download if it has the name of the Daily Tracker I'm keeping track of (as it changes daily with the Format(Now)). The problem is that it is not finding the attachment.
The code can find the email if I substitute the ElseIf to Next part for oOlItm.Display, but won't download the attachment.
Sub AttachmentDownload()
Const olFolderInbox As Integer = 6
'~~> Path for the attachment
Const AttachmentPath As String = "C:\TEMP\TestExcel"
Dim oOlAp As Object
Dim oOlns As Object
Dim oOlInb As Object
Dim oOlItm As Object
Dim oOlAtch As Object
Dim NewFileName As String
NewFileName = "Daily Tracker " & Format(Now, "dd/MM/yyyy")
Set oOlAp = GetObject(, "Outlook.application")
Set oOlns = oOlAp.GetNamespace("MAPI")
Set oOlInb = oOlns.GetDefaultFolder(olFolderInbox)
For Each oOlItm In oOlInb.Items
If InStr(oOlItm.Subject, NewFilename)) <> 0 Then
ElseIf oOlItm.Attachments.Count <> 0 Then
For Each oOlAtch In oOlItm.Attachments
oOlAtch.SaveAsFile (AttachmentPath)
Exit For
Next
Else
MsgBox "No attachments found"
End If
Exit For
Next
End Sub
The email:
This should work for you:
Sub AttachmentDownload()
Const olFolderInbox As Integer = 6
'~~> Path for the attachment
Const AttachmentPath As String = "C:\TEMP\TestExcel"
Dim oOlAp As Object
Dim oOlns As Object
Dim oOlInb As Object
Dim oOlItm As Object
Dim oOlAtch As Object
Dim oOlResults As Object
Dim x As Long
Dim NewFileName As String
NewFileName = "Daily Tracker " & Format(Now, "dd-MM-yyyy")
'You can only have a single instance of Outlook, so if it's already open
'this will be the same as GetObject, otherwise it will open Outlook.
Set oOlAp = CreateObject("Outlook.Application")
Set oOlns = oOlAp.GetNamespace("MAPI")
Set oOlInb = oOlns.GetDefaultFolder(olFolderInbox)
'No point searching the whole Inbox - just since yesterday.
Set oOlResults = oOlInb.Items.Restrict("[ReceivedTime]>'" & Format(Date - 1, "DDDDD HH:NN") & "'")
'If you have more than a single attachment they'll all overwrite each other.
'x will update the filename.
x = 1
For Each oOlItm In oOlResults
If oOlItm.attachments.Count > 0 Then
For Each oOlAtch In oOlItm.attachments
If GetExt(oOlAtch.FileName) = "xlsx" Then
oOlAtch.SaveAsFile AttachmentPath & "\" & NewFileName & "-" & x & ".xlsx"
End If
x = x + 1
Next oOlAtch
End If
Next oOlItm
End Sub
'----------------------------------------------------------------------
' GetExt
'
' Returns the extension of a file.
'----------------------------------------------------------------------
Public Function GetExt(FileName As String) As String
Dim mFSO As Object
Set mFSO = CreateObject("Scripting.FileSystemObject")
GetExt = mFSO.GetExtensionName(FileName)
End Function
Another way of doing it is from within Outlook:
Create a new folder in your Outlook Inbox and set a rule to move the email to this folder when it arrives. You can then write code to watch this folder and save the file as soon as it arrives.
Place this code within the ThisOutlookSession module in Outlook.
Dim WithEvents TargetFolderItems As Items
Const FILE_PATH As String = "C:\TEMP\TestExcel\"
Private Sub Application_Startup()
Dim ns As Outlook.NameSpace
Set ns = Application.GetNamespace("MAPI")
Set TargetFolderItems = ns.Folders.Item("Mailbox - Darren Bartrup-Cook") _
.Folders.Item("Inbox") _
.Folders.Item("My Email For Processing").Items
End Sub
Sub TargetFolderItems_ItemAdd(ByVal Item As Object)
'when a new item is added to our "watched folder" we can process it
Dim olAtt As Attachment
Dim i As Integer
Dim sTmpFileName As String
Dim objFSO As Object
Dim sExt As String
If Item.Attachments.Count > 0 Then
Set objFSO = CreateObject("Scripting.FileSystemObject")
For i = 1 To Item.Attachments.Count
Set olAtt = Item.Attachments(i)
sExt = objFSO.GetExtensionName(olAtt.FileName)
If sExt = "xlsx" Then
sTmpFileName = "Daily Tracker " & Format(Now, "dd-mm-yyyy") & ".xlsx"
End If
Item.UnRead = False
olAtt.SaveAsFile FILE_PATH & sTmpFileName
DoEvents
Next
End If
Set olAtt = Nothing
MsgPopup "A new attachment has been saved.", vbOKOnly, "New Daily Tracker"
End Sub
Private Sub Application_Quit()
Dim ns As Outlook.NameSpace
Set TargetFolderItems = Nothing
Set ns = Nothing
End Sub
Create a new module in Outlook and put this code in there. This will create a messagebox that won't stop whatever you're doing.
Public Function MsgPopup(Optional Prompt As String, _
Optional Buttons As VbMsgBoxStyle = vbOKOnly, _
Optional Title As String, _
Optional SecondsToWait As Long = 0) As VbMsgBoxResult
' Replicates the VBA MsgBox() function, with an added parameter
' to automatically dismiss the message box after n seconds
' If dismissed automatically, this will return -1: NOT ‘cancel’ or the default button choice.
' Nigel Heffernan, 2006. This code is in the public domain.
' Uses late-binding: bad for performance and stability, useful for code portability
' The correct declaration is: Dim objWshell As IWshRuntimeLibrary.WshShell
Dim objWshell As Object
Set objWshell = CreateObject("WScript.Shell")
MsgPopup = objWshell.Popup(Prompt, SecondsToWait, Title, Buttons)
Set objWshell = Nothing
End Function
Does anyone have an idea how to return parameter name in VBA?
This is what I have:
Sub Main()
Dim MyString As String
MyString = "Hello World"
MsgBox MyString
End Sub
It shows only "Hello World". I would like to have it "MyString says Hello World", but dynamically, not by entering
MsgBox "MyString says " & MyString
I would prefer something like
MsgBox ParamName(MyString) & " says " & MyString
but it actually won't work... Could anyone help?
I believe I have accomplished what you are looking to do here. However, please note that this will currently only work for your first parameter in a macro assigned to a Form control:
Step 1
Add the following code, adapted from here, to a new Module:
Public Function ExportModules(ModuleName As String) As String
Dim bExport As Boolean
Dim wkbSource As Excel.Workbook
Dim szSourceWorkbook As String
Dim szExportPath As String
Dim szFileName As String
Dim cmpComponent As VBIDE.VBComponent
''' The code modules will be exported in a folder named.
''' VBAProjectFiles in the Documents folder.
''' The code below create this folder if it not exist
''' or delete all files in the folder if it exist.
If FolderWithVBAProjectFiles = "Error" Then
MsgBox "Export Folder not exist"
Exit Function
End If
On Error Resume Next
Kill FolderWithVBAProjectFiles & "\*.*"
On Error GoTo 0
''' NOTE: This workbook must be open in Excel.
szSourceWorkbook = ActiveWorkbook.Name
Set wkbSource = Application.Workbooks(szSourceWorkbook)
If wkbSource.VBProject.Protection = 1 Then
MsgBox "The VBA in this workbook is protected," & _
"not possible to export the code"
Exit Function
End If
szExportPath = FolderWithVBAProjectFiles & "\"
Set cmpComponent = wkbSource.VBProject.VBComponents(ModuleName)
bExport = True
szFileName = cmpComponent.Name
''' Concatenate the correct filename for export.
Select Case cmpComponent.Type
Case vbext_ct_ClassModule
szFileName = szFileName & ".cls"
Case vbext_ct_MSForm
szFileName = szFileName & ".frm"
Case vbext_ct_StdModule
szFileName = szFileName & ".bas"
Case vbext_ct_Document
''' This is a worksheet or workbook object.
''' Don't try to export.
bExport = False
End Select
If bExport Then
''' Export the component to a text file.
cmpComponent.Export szExportPath & szFileName
''' remove it from the project if you want
'''wkbSource.VBProject.VBComponents.Remove cmpComponent
End If
ExportModules = szExportPath & szFileName
End Function
Function FolderWithVBAProjectFiles() As String
Dim WshShell As Object
Dim FSO As Object
Dim SpecialPath As String
Set WshShell = CreateObject("WScript.Shell")
Set FSO = CreateObject("scripting.filesystemobject")
SpecialPath = WshShell.SpecialFolders("MyDocuments")
If Right(SpecialPath, 1) <> "\" Then
SpecialPath = SpecialPath & "\"
End If
If FSO.FolderExists(SpecialPath & "VBAProjectFiles") = False Then
On Error Resume Next
MkDir SpecialPath & "VBAProjectFiles"
On Error GoTo 0
End If
If FSO.FolderExists(SpecialPath & "VBAProjectFiles") = True Then
FolderWithVBAProjectFiles = SpecialPath & "VBAProjectFiles"
Else
FolderWithVBAProjectFiles = "Error"
End If
End Function
Step 2
Add the following code, adapted from answer #7 here, and from here, along with my own function, to a new module (it could be the same module as the first if preferred):
Public Function MyMacroInfo() As String
Dim MacroName$, SubName$, ModArr As Variant
Dim ModName As Object, strModName$, i&, j&
MacroName = ActiveSheet.Buttons(Application.Caller).OnAction
SubName = Application.Replace(MacroName, 1, Application.Search("!", MacroName), "")
ModArr = Array(0, 1, 2, 3)
For Each ModName In ActiveWorkbook.VBProject.VBComponents
For j = LBound(ModArr) To UBound(ModArr)
i = 0
On Error Resume Next
i = ModName.CodeModule.ProcStartLine(SubName, CLng(ModArr(j)))
Err.Clear
If i > 0 Then
strModName = ModName.Name
Exit For
End If
Next j
Next ModName
MyMacroInfo = strModName
End Function
Public Function GetParamName(ModulePath As String) As String
Dim text As String
Dim textline As String
Dim ParamStartLocation As Long
Dim ParamEndLocation As Long
Dim ParamLength As Long
Dim i As Long
Open ModulePath For Input As #1
Do Until EOF(1)
Line Input #1, textline
text = text & textline
Loop
Close #1
ParamStartLocation = 0
For i = 1 To 3
ParamStartLocation = InStr(ParamStartLocation + 1, text, "Dim ")
Next i
ParamEndLocation = InStr(ParamStartLocation, text, " As ")
ParamLength = ParamEndLocation - ParamStartLocation
GetParamName = Left(Right(text, Len(text) - ParamStartLocation - 3), ParamLength - 4)
End Function
Step 3
Change your sub to the following:
Sub Main()
'--------Leave this section at the top of your sub---------
Dim strExportedModule As String
Dim strParamName As String
strExportedModule = ExportModules(MyMacroInfo)
strParamName = GetParamName(strExportedModule)
'-----------------Start your code here---------------------
Dim MyString As String
MyString = "Hello World"
MsgBox strParamName & " says " & MyString
End Sub
Step 4
Assign Main to a Form Button.
Notes
As noted above, this will only get the first parameter that you dimension in the macro assigned to the Form Button. If this is not acceptable, I'll have to take a look at it to see if it can be modified to meet your needs.
As Ron de Bruin notes on his site, you'll need to do the following:
In the VBE Editor set a reference to "Microsoft Visual Basic For
Applications Extensibility 5.3" and to "Microsoft Scripting Runtime"
and then save the file.
This code will export the module to a folder named "VBAProjectFiles" in your My Documents folder. If you happen to have a folder saved there with the same name (as unlikely as that is), it will delete all the files in that folder.
I have a script that goes and grabs all of the documents from a certain folder and lists all of the files in that folder. It then goes and makes a link to open these files from inside of Excel. I was wondering if there was a way to put it in a shell so that the files only opened in notepad. The code that I am using right now is:
Sub MakeLink(ByVal cell As Range, ByVal url As String, ByVal txt As String, ByVal tooltip_text As String)
ActiveSheet.Hyperlinks.Add _
Anchor:=cell, _
Address:=url, _
ScreenTip:=tooltip_text, _
TextToDisplay:=txt
End Sub
Sub Portfolios()
Range("A1:Z200").Clear
Dim objFSO As Object
Dim objFolder As Object
Dim objFile As Object
Dim ws As Worksheet
Range("A3").Font.Bold = True
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set ws = Worksheets("Library")
'Get the folder object associated with the directory
Set objFolder = objFSO.GetFolder("C:\Portfolios")
ws.Cells(3, 1).Value = "The files found in " & objFolder.Name & " are:"
'Loop through the Files collection
For Each objFile In objFolder.Files
'ws.Cells(ws.UsedRange.Rows.Count + 3, 2).Value = objFile.Name
MakeLink ws.Cells(ws.UsedRange.Rows.Count + 3, 2), objFile, objFile.Name, objFile.Name
Next
'Clean up!
Set objFolder = Nothing
Set objFile = Nothing
Set objFSO = Nothing
End Sub
I know I have to do something along the lines of MakeLink = Shell("C:\WINDOWS\notepad.exe", 1) but I seem to be hitting a bit of a snag as to where this will fit.
Thanks,
F
Files will open in whatever is the default program for the file type.
If you want to force them to open in notepad then you'll have to write some code to process the Worksheet_FollowHyperlink event: you can get the cell text from the Target parameter and shell out notepad from there.
To prevent problems with the hyperlink taking users elsewhere, just set the target address to the same cell as the one containing the hyperlink.
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Dim fPath As String, res
fPath = Target.TextToDisplay
res = Shell("notepad.exe """ & fPath & """", vbNormalFocus)
End Sub
To create the hyperlinks:
Sub MakeLink(rng As Range, txt As String)
Dim addr As String
addr = "'" & rng.Parent.Name & "'!" & rng.Address(False, False)
rng.Parent.Hyperlinks.add Anchor:=rng, Address:="", _
SubAddress:=addr, TextToDisplay:=txt
End Sub