I'm having an issue that when I try to use multiple instances of file dialogs the information from the first is always overwritten by the selection in the second dialog.
What i need to do is:
Select a template file
Select a destination folder
Save the template file as a .docm file.
What happens is that the second time application.FileDialog is used all the information in fd is lost and is overwritten by the entries into fldr.
Can there only be one dialog object per macro?
Dim fd As FileDialog
Dim FileChosen As Integer
Dim FileName As String
Dim fldr As FileDialog
Dim fldrSelect As String
Dim i As Integer
Set fd = Application.FileDialog(msoFileDialogFilePicker)
'use the standard title and filters, but change the
'initial folder
fd.InitialFileName = "H:\UpdatedSalesTemplates\"
fd.InitialView = msoFileDialogViewList
'allow multiple file selection
fd.AllowMultiSelect = True
FileChosen = fd.Show
If FileChosen = -1 Then
'Select the directory using a file dialog
Set fldr = Application.FileDialog(msoFileDialogFolderPicker)
fldr.InitialView = msoFileDialogViewList
fldr.Title = "Select Destination"
fldr.AllowMultiSelect = False
fldrSelected = fldr.Show
'
Microsoft says that there may be only one: "...Each host application can only create a single instance of the FileDialog object...".
In any case, this shouldn't represent a serious problem as far as you can store all the relevant information (selected path, initial directory, etc.) in (string) variables.
For such scenarios where you need a file/folder picker in one macro/procedure/userform, I use a custom made userform. See if you like it. Place commandbuttons and textboxes as shown below
Screenshot
Code
Note: Both the textboxes .Locked property was set to True in design time so that the user cannot modify the textboxes manually.
Option Explicit
Dim Ret
'~~> Browse File
Private Sub CommandButton1_Click()
Ret = Application.GetOpenFilename("Excel Files (*.xlsx), *.xlsx")
If Ret <> False Then TextBox1.Text = Ret
End Sub
'~~> Browse Folder
Private Sub CommandButton2_Click()
Ret = BrowseForFolder("C:\")
If Ret <> False Then TextBox2.Text = Ret
End Sub
Function BrowseForFolder(Optional OpenAt As Variant) As Variant
Dim ShellApp As Object
Set ShellApp = CreateObject("Shell.Application"). _
BrowseForFolder(0, "Please choose a folder", 0, OpenAt)
On Error Resume Next
BrowseForFolder = ShellApp.self.Path
On Error GoTo 0
Set ShellApp = Nothing
Select Case Mid(BrowseForFolder, 2, 1)
Case Is = ":"
If Left(BrowseForFolder, 1) = ":" Then GoTo Invalid
Case Is = "\"
If Not Left(BrowseForFolder, 1) = "\" Then GoTo Invalid
Case Else
GoTo Invalid
End Select
Exit Function
Invalid:
'~~> If it was determined that the selection was invalid, set to False
BrowseForFolder = False
End Function
Related
Trying to save word file, from excel vba, without over-writing any existing files. The possibility exists that the filename chosen (taken from the spreadsheet) may be a duplicate, in which case I would like to pause or stop the code, but instead it over-writes automatically) As below, though my two prong attempt to error catch fails, and the word document is over written:
Sub automateword()
Dim fileToOpen As String
Dim intChoice As Integer
Dim myFile As Object
mysheet = ActiveWorkbook.Name
Set Wst = Workbooks(mysheet).ActiveSheet
Application.FileDialog(msoFileDialogOpen).AllowMultiSelect = False
'make the file dialog visible to the user
intChoice = Application.FileDialog(msoFileDialogOpen).Show
If intChoice <> 0 Then
'get the file path selected by the user
fileToOpen = Application.FileDialog( _
msoFileDialogOpen).SelectedItems(1)
End If
Set wordapp = CreateObject("word.Application")
Set myFile = wordapp.documents.Add(fileToOpen)
i = 1
Do Until IsEmpty(Wst.Cells(i, 2))
i = i + 1
Loop
i = i - 1
wordapp.Visible = True
Filename = Wst.Cells(i, 2) + " " + Wst.Cells(i, 3) + Str(Wst.Cells(i, 10))
On Error GoTo errorline
wordapp.DisplayAlerts = True
FullPath = "\\networkpath\" & Filename & ".doc"
myFile.SaveAs (FullPath)
Exit Sub
errorline:
MsgBox ("filename error")
End Sub
You can add this if-statement before adding a word document.
If Dir(fileToOpen) <> "" Then Exit Sub
I am currently using to following code to prompt the user for a workbook, open it, get some information from it and then close it. at the moment, I address the opened workbook by using the workbooks collection with and index ("woorkbooks(2)"). Now I need to open two workbooks, and my problem is that I wouldn't know which of the workbooks will be indexed as 2 and which will be indexed as 3. So, I figured there must be a way to get a reference to each workbook.
Function openfile() As Boolean
Dim fd As FileDialog
Dim file_was_chosen As Boolean
Set fd = Application.FileDialog(msoFileDialogOpen)
With fd
.Filters.Clear
.Filters.Add "Excel File", "*.xl*"
End With
file_was_chosen = fd.Show
If Not file_was_chosen Then
MsgBox "You didn't select a file"
openfile = False
Exit Function
End If
fd.Execute
openfile = True
End Function
Now I've seen some solutions to this problem involving getting the full path of each workbook, but I'd prefer avoid using the full path since it contains words in different language (and the name of the workbook appears with question marks). Moreover, I'd prefer a solution in which the user is promped only once for 2 files and not twice.
This version gives the user a single dialog. Enjoy. And whoever downvoted my other answer, please add a comment to that explaining what you so disliked about it that it required a downvote.
Function openfile() As Variant
Dim aOpen(2) As String, itm As Variant, cnt As Long, lAsk As Long
Dim fd As FileDialog
Dim file_was_chosen As Boolean
Set fd = Application.FileDialog(msoFileDialogOpen)
With fd
.Filters.Clear
.Filters.Add "Excel File", "*.xl*"
End With
Do
file_was_chosen = fd.Show
If Not file_was_chosen Or fd.SelectedItems.Count > 2 Then
lAsk = MsgBox("You didn't select one or two files, try again?", vbQuestion + vbYesNo, "File count mismatch")
If lAsk = vbNo Then
openfile = aOpen
Exit Function
End If
End If
Loop While fd.SelectedItems.Count < 1 Or fd.SelectedItems.Count > 2
cnt = 0
For Each itm In fd.SelectedItems
aOpen(cnt) = itm
cnt = cnt + 1
Next
openfile = aOpen
fd.Execute
End Function
Sub test()
Dim vRslt As Variant
Dim wkb As Excel.Workbook, wkb1 As Excel.Workbook, wkb2 As Excel.Workbook
vRslt = openfile
For Each wkb In Application.Workbooks
If wkb.Path & "\" & wkb.Name = vRslt(0) Then Set wkb1 = wkb
If wkb.Path & "\" & wkb.Name = vRslt(1) Then Set wkb2 = wkb
Next
If vRslt(0) = "" Then ' no files
MsgBox "No files opened so nothing happens..."
ElseIf vRslt(1) = "" Then ' one file was opened
MsgBox "One file so do whatever you want for one file"
Else ' two files were opened
MsgBox "Two files so do whatever you want for two files"
End If
End Sub
Working with your existing openfile function, change the return from Boolean to Excel.Workbook. If they don't open a workbook you set it to Nothing instead of false, otherwise you set it to the workbook reference of the file you just opened (You'll need to modify openfile to get that reference). You then just call it twice and set a workbook reference for each call that is not Nothing.
Example code below is written freeform and is untested - it's really just glorified pseudocode - but should point you the right general direction.
sub test
dim lAsk as long
dim wkb1 as excel.workbook
dim wkb2 as excel.workbook
do
if wkb1 is Nothing then
set wkb1 = openfile
if wkb1 is Nothing then
lAsk = msgbox("you didn't select a first file, try again?",vbyesno,"No file selected")
if lAsk = vbNo then exit do
end if
elseif wkb2 is Nothing then
set wkb2 = openfile
if wkb2 is Nothing then
lAsk = msgbox("you didn't select a second file, try again?",vbyesno,"No file selected")
if lAsk = vbNo then exit do
end if
end if
loop while wkb1 is Nothing or wkb2 is Nothing
' do whatever with wkb1 and wkb2 here
end sub
Edited to add:
Here's a very basic shape for your revised openfile function. Again, untested but I've modified it from one of my own procs so it should work
Function openfile() As Excel.Workbook
Dim sFilter As String
Dim sTitle As String
Dim vFileName As Variant
sFilter = "Excel Files (*.xl*), *.xl*, CSV Files (*.csv), *.csv, All Files (*.*), *.*"
sTitle = "Select file to process"
vFileName = Application.GetOpenFilename(filefilter:=sFilter, Title:=sTitle)
If vFileName = False Then
Set openfile = Nothing
Else
Set openfile = Workbooks.Open(Filename:=vFileName)
End If
End Function
I've recently started experimenting with vba to automate some of my daily tasks in Microsoft Word. I am working on a code that will allow the user to select a destination folder and also the files (.doc) to be copied into the selected destination folder.
The following code runs with no errors, however the files do not get copy pasted into the destination folder.
I will greatly appreciate any help to resolve this minute issue.
Regards,
Derek
Sub copydocs()
Dim items As Long
Dim file_path As Variant
Dim folder_path As Variant
'Ask user for input'
items = InputBox("Give me some input")
'Select Destination Folder
With Application.FileDialog(msoFileDialogFolderPicker)
folder_path = .SelectedItems(1)
.Show
End With
' Open the file dialog
For i = 1 To items
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = True
.Show
file_path = .SelectedItems(1)
End With
' Copy paste
Dim fs As Object
Set fs = CreateObject("Scripting.FileSystemObject")
fs.CopyFile file_path, folder_path
Set fs = Nothing
Next i
End Sub
There are a couple of issues.
The variable i isn't declared anywhere.
You are attempting to save the folder path before the dialogue has returned it.
Sub copydocs()
Dim i As Integer ' CHANGE: New declare.
Dim fs As Object ' CHANGE: Moved to top.
Dim items As Long
Dim file_path As Variant
Dim folder_path As Variant
'Ask user for input.
items = InputBox("Give me some input")
'Select Destination Folder
With Application.FileDialog(msoFileDialogFolderPicker)
' CHANGE: Switched order of next two lines.
.Show
folder_path = .SelectedItems(1)
End With
' Open the file dialog
For i = 1 To items
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = True
.Show
file_path = .SelectedItems(1)
End With
' Copy paste
Set fs = CreateObject("Scripting.FileSystemObject")
fs.CopyFile file_path, folder_path
Set fs = Nothing
Next i
End Sub
I have VBA in Word that opens multiple files from a folder that I select, replaces the logo in the header with a new file that I direct it to, and then saves the files in a different folder.
I have the files saving in a different folder not because I want to, but because they are opening as read-only and I can't figure out how to make that not happen. I have tried everything I can find on here. I'm fine with them saving to a new folder. That's not the issue for me right now.
Right now, this code works, but I have to click "Save" for each document. I would like that to be automated. The code right here is the saveas
End With
With Dialogs(wdDialogFileSaveAs)
.Name = "\\i-worx-san-07.i-worx.ca\wardell$\Redirection\billy.bones\Desktop\Test 3\" & ActiveDocument.Name
.Show
End With
End With
objDocument.SaveAs
objDocument.Close (True)
The following is the complete VBA code. I'm an absolute novice, so go easy. I want to know how to go about making the saveas include the original filename, a new specified folder (can be specified in the code, doesn't have to be specified by the user) and do it without the user having to press "save" a brazillion times. I appreciate your help.
Sub Example1()
'Declaring the required variables
Dim intResult As Integer
Dim strPath As String
Dim arrFiles() As String
Dim i As Integer
'the dialog is displayed to the user
intResult = Application.FileDialog(msoFileDialogFolderPicker).Show
'checks if user has cancled the dialog
If intResult <> 0 Then
'dispaly message box
strPath = Application.FileDialog( _
msoFileDialogFolderPicker).SelectedItems(1)
'Get all the files paths and store it in an array
arrFiles() = GetAllFilePaths(strPath)
'Modifying all the files in the array path
For i = LBound(arrFiles) To UBound(arrFiles)
Call ModifyFile(arrFiles(i))
Next i
End If
End Sub
Private Sub ModifyFile(ByVal strPath As String)
Dim objDocument As Document
Set objDocument = Documents.Open(strPath)
With ActiveDocument.Sections(1)
With ActiveDocument.Sections(1)
.Headers(WdHeaderFooterIndex.wdHeaderFooterPrimary).Range.Delete
End With
Dim imagePath As String
'Please enter the relative path of the image here
imagePath = "C://FILEPATH\FILENAME.jpg"
Set oLogo = .Headers(wdHeaderFooterPrimary).Range.InlineShapes.AddPicture(FileName:=imagePath, LinkToFile:=False, SaveWithDocument:=True)
With oLogo.Range
.ParagraphFormat.Alignment = wdAlignParagraphRight
'Right alignment for logo image
.ParagraphFormat.RightIndent = InchesToPoints(-0.6)
End With
End With
With oLogo
.Height = 320
.Width = 277
With Selection.PageSetup
'Header from Top value
.HeaderDistance = InchesToPoints(0.5)
End With
With Dialogs(wdDialogFileSaveAs)
.Name = "\\i-worx-san-07.i-worx.ca\wardell$\Redirection\billy.bones\Desktop\Test 3\" & ActiveDocument.Name
.Show
End With
End With
objDocument.SaveAs
objDocument.Close (True)
End Sub
Private Function GetAllFilePaths(ByVal strPath As String) _
As String()
Dim objFSO As Object
Dim objFolder As Object
Dim objFile As Object
Dim i As Integer
Dim arrOutput() As String
ReDim arrOutput(1 To 1)
'Create an instance of the FileSystemObject
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Get the folder object
Set objFolder = objFSO.GetFolder(strPath)
i = 1
'loops through each file in the directory and
'prints their names and path
For Each objFile In objFolder.Files
ReDim Preserve arrOutput(1 To i)
'print file path
arrOutput(i) = objFile.Path
i = i + 1
Next objFile
GetAllFilePaths = arrOutput
End Function
Remove this line which calls the FileSaveAs dialogue.
With Dialogs(wdDialogFileSaveAs)
.Name = "\\i-worx-san-07.i-worx.ca\wardell$\Redirection\billy.bones\Desktop\Test 3\" & ActiveDocument.Name
.Show
End With
Then modify this line:
objDocument.SaveAs
and include the filepath like this:
objDocument.SaveAs "\\i-worx-san-07.i-worx.ca\wardell$\Redirection\" _
& "billy.bones\Desktop\Test 3\" & ActiveDocument.Name
In newer version of Word, it was change to SaveAs2 but SaveAs still works.
That method takes the file path where you want the file saved as first argument.
I'm using Application.FileDialog to let the user select a folder, as in:
Dim F As FileDialog
Set F = Application.FileDialog(msoFileDialogFolderPicker)
In this case the default folder contains no subfolders, so what the user sees is an empty box. Ideally, the dialog would not just list folders, but would list files disabled/grayed out so that the user would be able to see the contents of the folder he is picking.
Is there a way to do this on the cheap with a FileDialog or do I have to create my own form (ugh) ?
Here is something from my database. I have been using this for quite sometime now for VBA. This code is not mine and I found it long time ago on the web.
Sub Sample()
ret = BrowseForFolder("C:\")
End Sub
Function BrowseForFolder(Optional OpenAt As Variant) As Variant
Dim ShellApp As Object
Set ShellApp = CreateObject("Shell.Application"). _
BrowseForFolder(0, "Please choose a folder", 0, OpenAt)
On Error Resume Next
BrowseForFolder = ShellApp.self.Path
On Error GoTo 0
Set ShellApp = Nothing
Select Case Mid(BrowseForFolder, 2, 1)
Case Is = ":"
If Left(BrowseForFolder, 1) = ":" Then GoTo Invalid
Case Is = "\"
If Not Left(BrowseForFolder, 1) = "\" Then GoTo Invalid
Case Else
GoTo Invalid
End Select
Exit Function
Invalid:
BrowseForFolder = False
End Function