EDIT: I can make it work in a separate document, but not based on the template documents.
I am trying to edit a textbox within the header of a template-created file within a loop. The textbox name is "Text Box 2." It already has text inside of the box. The goal is replace one of the words ("COUNTRYNAME") with the String CountryName2 (see full sub posted below). Here is the relevant code for actually getting in and editing the textbox:
Set tFile = Documents.Add(tPath)
Selection.InsertFile (cDirPath & "\" & cFile)
Debug.Print tFile.Sections(1).Headers(wdHeaderFooterFirstPage).Shapes.Range(Array("Text Box 2")).TextFrame.TextRange.Text 'This will print the text within the textbox with DebugPrint but if I try to set it = to something and get rid of Debug.Print (allegedly to edit/add text) nothing happens
I can edit the text within the Header using a simple: tFile.Sections(1).Headers(wdHeaderFooterFirstPage).Range.Text = "Replaced Header Text"
But it replaces the entire header with that text (I have a number of things on the header already that I do not want to change - just the one and only textbox.
Entire sub: The point of the sub is to open a bunch of files within a directory and copy them into a new template document, then change that template header to match a country name found within the filename.
Sub CopyAndPaste()
Dim tPath As String 'template path string
Dim tFile As Document 'template file
Dim cDirPath As String 'copy directory Path
Dim cName As String 'name of copy
Dim CountryName As String ' country name1
Dim CountryName2 As String ' country name2
Dim pDir As String
Dim findTextH As String
findTextH = "COUNTRYNAME"
pDir = "C:\Users\XXX\XXXX\Desktop\Test\Saved\"
With Application.FileDialog(msoFileDialogFilePicker) 'pick the template document path
.ButtonName = "Pick Template"
.Title = "Pick the template"
If .Show <> 0 Then
tPath = .SelectedItems(1)
End If
End With
With Application.FileDialog(msoFileDialogFolderPicker) 'pick the directory with the files path
' show the file picker dialog box
If .Show <> 0 Then
cDirPath = .SelectedItems(1)
End If
End With
cFile = Dir(cDirPath & "\" & "*.docx")
Do While cFile <> ""
cName = GetFilenameFromPath(cFile) 'get the original file name without path
CountryName = Mid(cName, 19)
CountryName2 = Left(CountryName, Len(CountryName) - 5)
Set tFile = Documents.Add(tPath)
Selection.InsertFile (cDirPath & "\" & cFile)
Debug.Print tFile.Sections(1).Headers(wdHeaderFooterFirstPage).Range.Text
'.Shapes.Range(Array("Text Box 2")).TextFrame.TextRange.Text = "Testing" ***FOR TESTING&***
tFile.SaveAs2 FileName:=pDir & cName
tFile.Close
cFile = Dir
Loop
End Sub
I solved this issue. This was due to a hidden textbox on the second page header which was messing things up. The textbox was filled with white text!!! Ended up figuring it out somehow.
Related
I frequently run a macro on folders that contain .doc and .docx files. Currently, my macro is only able to edit one type of file and then I have to change my macro from .doc to .docx (or vice versa) and run again.
How could I get both file types in one go?
The current code.
'UpdateDocuments
Sub UpdateDocuments()
Dim file
Dim path As String
'Path to your folder.
'make sure to include the terminating "\"
‘Enter path.
path = "C:\Users\emckenzie\Documents\TEMP PLOT\macro practice\Andria footer change\"
'Change this file extension to the file you are opening
file = Dir(path & "*.docx")
Do While file <> ""
Documents.Open FileName:=path & file
'This is the call to the macro you want to run on each file the folder
'Enter macro.
Call Permit2hundred
' Saves the file
ActiveDocument.Save
ActiveDocument.Close
'set file to next in Dir
file = Dir()
Loop
End Sub
To answer your question:
Use a wildcard like * or ? in this line: fileExtension = "*.doc?"
You can read more about wildcard characters here
Some suggestions on your code:
Assign variable types when you're defining them
Indent your code (You can use www.rubberduckvba.com)
Define your variables close to where you first use them (matter of preference)
When working with documents, assign them to a document variable and refer to that variable instead of ActiveDocument
Use basic error handling
Additional tip:
When calling this procedure Permit2hundred you could pass the targetDocument variable like this:
'This is the call to the macro you want to run on each file the folder
'Enter macro.
Permit2hundred targetDocument
' Saves the file
targetDocument.Save
And the definition of that procedure could be something like this:
Private Sub Permit2hundred(ByVal targetDocument as Document)
'Do something
End Sub
This is the refactored code:
Public Sub UpdateDocuments()
' Add basic Error handling
On Error GoTo CleanFail
'Path to your folder.
'make sure to include the terminating "\"
'Enter path.
Dim folderPath As String
folderPath = "C:\Users\emckenzie\Documents\TEMP PLOT\macro practice\Andria footer change\"
'Change this file extension to the file you are opening
Dim fileExtension As String
fileExtension = "*.doc?"
' Get files in folder
Dim fileName As String
fileName = Dir(folderPath & fileExtension)
' Loop through files in folder
Do While file <> vbNullString
Dim targetDocument As Document
Set targetDocument = Documents.Open(fileName:=folderPath & file)
'This is the call to the macro you want to run on each file the folder
'Enter macro.
Permit2hundred
' Saves the file
targetDocument.Save
targetDocument.Close
'set file to next in Dir
file = Dir()
Loop
CleanExit:
Exit Sub
CleanFail:
MsgBox "Something went wrong. Error: " & Err.Description
GoTo CleanExit
End Sub
Let me know if it works
I prefer to display a file picker dialog and then select what I want. I am then able to choose a doc or docx file without having to alter my code. The Filter property determines the file types allowed. Note that this code clears the filter when it ends, otherwise that is the filter Word will use from that point on, even for manually initiated (non-programmatic) requests of File Open.
This example is setup to allow multiple selections. You can change the AllowMultiSelect to False and then the code will run with only one file at a time.
Dim i As Integer, selFiles() As String
Dim strFolderPath As String, Sep As String
Sep = Application.PathSeparator
Erase selFiles
'Windows Office 2019, 2016, 2013, 2010, 2007
With Application.FileDialog(msoFileDialogFilePicker)
.Title = "Select the files to update"
.InitialFileName = curDir
.AllowMultiSelect = True
.Filters.Clear
.Filters.Add "All Word Files", "*.docx; *.docm; *.doc", 1
If .Show = 0 Then
Exit Sub
End If
ReDim Preserve selFiles(.SelectedItems.Count - 1)
strFolderPath = Left(.SelectedItems(1), InStrRev(.SelectedItems(1), Sep))
For i = 0 To .SelectedItems.Count - 1
selFiles(i) = .SelectedItems(i + 1)
Next
.Filters.Clear
End With
I am not a programmer so not sure what to do here. I would like an option of adding an image file in a Microsoft Word document userform for MAC. I had used a code earlier which works perfectly in Windows but it doesnt work for MAC and gives a 5948 error. I had added a field for the image in the userform with a button to add the image and the final submit button. The add button should allow the user to insert any size image from the local folder.
The code I was using is given below:
Dim ImagePath As String
Private Sub CMDAddImage_Click()
Dim objFileDialog As Office.FileDialog
Set objFileDialog = Application.FileDialog(MsoFileDialogType.msoFileDialogFilePicker)
With objFileDialog
.AllowMultiSelect = False
.ButtonName = "File Picker"
.Title = "File Picker"
If (.Show > 0) Then
End If
If (.SelectedItems.Count > 0) Then
Call MsgBox(.SelectedItems(1))
ImagePath = .SelectedItems(1)
End If
End With
Image1.Picture = LoadPicture(ImagePath)
End Sub
And the code in submit button was:
Dim objWord
Dim objDoc
Dim objShapes
Dim objSelection
'Set objSelection = ActiveDocument.Sections
'objSelection.TypeText (vbCrLf & "One Picture will be inserted here....")
ActiveDocument.Bookmarks("Field04").Select
Set objShapes = ActiveDocument.InlineShapes
objShapes.AddPicture (ImagePath)
End
End Sub
Can someone please help me edit the code for mac. In mac it does not allow to add the file.
You should check out the suggestion made by #JohnKorchok in a comment to your previous question - insert an image Content Control in your document instead, and throw away the VBA.
But if you need to keep using VBA and a UserForm...
Application.FileDialog is not available on Mac.
Application.GetOpenFileName is not avaialble from Word (it's an Excel thing).
Application.Dialogs does not do the same thing as GetOpenFileName so the user experience will be rather different, but at its simplest, you can use it like this:
With Application.Dialogs(wdDialogFileOpen)
' .Display = -1 for "OK" ("Open" in this case)
' .Display = 0 for "Cancel"
' (THere are other possible return values
' but I do not think they are applicable here)
If .Display = -1 Then
ImagePath = .Name
End If
End With
or if you prefer, the lengthier
Dim dlg As Word.Dialog
Set dlg = Application.Dialogs(wdDialogFileOpen)
With dlg
If .Display = -1 Then
ImagePath = .Name
End If
End With
Set dlg = Nothing
However, this dilaog does not let you specify file types or any kind of filtering, a starting folder etc. Attempts to set Finder search criteria via something like
.Name = "(_kMDItemFileName = ""*.jpg"")"
.Update
before the .Display either can't work or need different syntax.
Further, the Apple dialog may start with its
own filtering set up so the user will have to click Options to enable All Files. You don't know what file type the user will choose so you will need to deal with that.
An alternative is to invoke Applescript. For this, it appears that you can still use the VBA MacScript command, which means that you can put all the script in your VBA file. If that does not work, then unfortunately you have to use AppleScriptTask which would require you to work some more on the Script and install the script in the correct folder on every Mac where you need this feature.
Here's the code I used - you would probably need to wrap everything up in another function call and use conditional compilation or other tests to call the correct routine depending on whether the code is running on Mac or Windows
Private Sub CMDAddImage_Click()
Dim s As String
Dim sFileName As String
On Error Resume Next
s = ""
' set this to some other location as appropriate
s = s & "set thePictureFoldersPath to (path to pictures folder)" & vbNewLine
s = s & "set applescript's text item delimiters to "",""" & vbNewLine
s = s & "set theFile to ¬" & vbNewLine
' add the image file types you want here
s = s & "(choose file of type {""png"",""jpg""} ¬" & vbNewLine
s = s & "with prompt ""Choose an image to insert."" ¬" & vbNewLine
s = s & "default location alias thePictureFoldersPath ¬" & vbNewLine
s = s & "multiple selections allowed false) as string" & vbNewLine
s = s & "set applescript's text item delimiters to """"" & vbNewLine
' choose file gives as an AFS path name (with colon delimiters)
' get one Word 2016/2019 will work with
s = s & "posix path of theFile"
sFileName = MacScript(s)
If sFileName <> "" Then
' Maybe do some more validation here
ImagePath = sFileName
Image1.Picture = LoadPicture(ImagePath)
End If
End Sub
Say you want to have a button that the user can click and save a copy of the current file as a PDF(Documentation):
Application.ActiveDocument.SaveAs2 fileName:="fileName.pdf", FileFormat:=wdFormatPDF
This works fine, the user is presented with a save dialog, selects a location and the file is saved, however a few things are not correct:
The type displayed does not match what was specified in the VBA, how can this be correct? It still saves as type "PDF" without issue, even after showing "DOCX" as the file type in the "Save as Type" drop down. Also the "fileName.pdf" is not placed in the "File Name" box, its as if the dialog box is unaware of the options set in the VBA code(This same issue is also referenced in this post).
UPDATE 1
After taking a second look at my code I now realize that the SaveAs2 Method was not displaying the dialog menu, the correct version of the code(simplified) can be described as:
Dim selected As String: selected = Application.FileDialog(msoFileDialogSaveAs).Show()
Dim filePath As String
If selected <> 0 Then
filePath = Application.FileDialog(msoFileDialogSaveAs).SelectedItems(1)
Application.ActiveDocument.SaveAs2 fileName:=Split(filePath, ".")(0), FileFormat:=wdFormatPDF
End If
So then the real question(I guess) is how do you get "Application.FileDialog" to display the proper type you wish to save in under the "Save as type" drop down, and this has already been answered by #PatricK. Thanks everyone for the help, I apologize for the initial confused nature of this question.
I am surprised for SaveAs2 will bring you a prompt to be honest - Only a new document and .Save will bring you that prompt.
If you want to get something similar to that prompt, you use Application.FileDialog with type msoFileDialogSaveAs.
Use this code below (perhaps as an AddIn suits more):
Option Explicit
Sub MySaveAs()
Dim oPrompt As FileDialog, i As Long, sFilename As String
Set oPrompt = Application.FileDialog(msoFileDialogSaveAs)
With oPrompt
' Find the PDF Filter from Default Filters
For i = 1 To .Filters.Count
'Debug.Print i & " | " & .Filters(i).Description & " | " & .Filters(i).Extensions
' Locate the PDF filter
If InStr(1, .Filters(i).Description, "PDF", vbTextCompare) = 1 Then
.FilterIndex = i
Exit For
End If
Next
' Change the title and button text
.Title = "Saving """ & ActiveDocument.Name & """ to PDF format"
.ButtonName = "Save to PDF"
' Default name
.InitialFileName = ActiveDocument.Name
' Show the Prompt and get Filename
If .Show = -1 Then
sFilename = .SelectedItems(1)
Debug.Print "Final filename: " & sFilename
' Save the file as PDF
ActiveDocument.SaveAs2 sFilename, wdFormatPDF
End If
End With
Set oPrompt = Nothing
End Sub
Screenshot sample:
In LibreOffice 4.2 I am trying to open the file picker and select multiple files (which I succeeded), and then to transfer the names (and path) of those files to a variable (or array, does not matter).
Although I can open the file picker and select multiple files, I can get the file name and path of only one file (the first one). And I couldn't find any way to get the others.
I am using the following code:
Sub TakeFile()
Dim FileNames(0 to 100) as String
FileNames() = fImportLocalFile()
Msgbox FileNames
End Sub
Function fImportLocalFile() 'as String
' FJCC: Can't define the function as returning a String because now it returns an array
'this function opens a system file open dialog box and allows the
' user to pick a file from thier computer to open into the
' document for processing
'stores the filedialog object
Dim oFileDialog as Object
'stores the returned result of the activation of the dialog box
Dim iAccept as Integer
'stores the returned file name/path from the file dialog box
Dim sPath as String
'stores the set default path for the dialog box
Dim InitPath as String
'stores the types of files allowed in the filedialog
Dim sFilterNames as String
'setup the filters for the types of files to allow in the dialog
sFilterNames = "*.csv; *.txt; *.odt; *.ods; *.xls; *.xlt; *.xlsx"
'create the dialog box as a Windows File Dialog
oFileDialog = CreateUnoService("com.sun.star.ui.dialogs.FilePicker")
'set the filters for the dialog
oFileDialog.AppendFilter("Supported files", sFilterNames)
'set the path as blank
InitPath = ""
'add the default path to the dialog
oFileDialog.setDisplayDirectory(InitPath)
'setup the dialog to allow multiple files to be selected
oFileDialog.setMultiSelectionMode(True)
'set iAccept as the execution of the dialog
iAccept = oFileDialog.Execute()
'execute and test if dialog works
If iAccept = 1 Then
'set sPath as the chosen file from the dialog
'sPath = oFileDialog.Files(0)
FileArray = oFileDialog.getFiles() 'added by FJCC
'set the function as sPath for returning to the previous sub
fImportLocalFile = FileArray 'modified by FJCC
'end current if statement
End If
End Function
Your error is you are assigning the array of selected files to the funtion name itself! Choose a different name.
This works with me on LO 5.0.0.5
SUB TakeFile()
' Dim FileNames(0 to 100) as String
' Dont limit yourself!
FileNames = fImportLocalFile()
path = FileNames(0)
FOR i = 1 TO Ubound(FileNames)
print path + FileNames(i)
Next
End Sub
and within the function:
path = FileArray(0)
FOR i = 1 TO Ubound(FileArray)
print path + FileArray(i)
Next
fImportLocalFile = FileArray
There is a Interface XFilePicker2 which "extends file picker interface to workaround some design problems." This Interface has a Method getSelectedFiles.
See https://www.openoffice.org/api/docs/common/ref/com/sun/star/ui/dialogs/XFilePicker2.html.
Use this Method instead of XFilePicker.getFiles.
The following should work:
Sub TakeFile()
Dim FileNames() as String
FileNames = fImportLocalFile()
Msgbox Join(FileNames, Chr(10))
End Sub
Function fImportLocalFile() as Variant
Dim oFileDialog as Object
Dim iAccept as Integer
Dim sPath as String
Dim InitPath as String
Dim sFilterNames as String
sFilterNames = "*.csv; *.txt; *.odt; *.ods; *.xls; *.xlt; *.xlsx"
oFileDialog = CreateUnoService("com.sun.star.ui.dialogs.FilePicker")
oFileDialog.AppendFilter("Supported files", sFilterNames)
InitPath = ""
oFileDialog.setDisplayDirectory(InitPath)
oFileDialog.setMultiSelectionMode(True)
iAccept = oFileDialog.Execute()
If iAccept = 1 Then
fImportLocalFile = oFileDialog.getSelectedFiles()
Else
fImportLocalFile = Array()
End If
End Function
I have a button which inserts a hyperlink into a new record. The field's IsHyperlink property is set to "yes", so I get the hand, but clicking on the inserted path does not go anywhere. I believe the button is updating the record with the path of the file as "text to display" rather than "address."
Private Sub MSDS_btn_Click()
Dim fd As Office.FileDialog
'Create a FileDialog object as a File Picker dialog box.
Set fd = Application.FileDialog(msoFileDialogFilePicker)
'Use a With...End With block to reference the FileDialog object.
With fd
'Set the initial path to the D:\Documents\ folder.
.InitialFileName = "D:\Documents\"
.Title = "Select MSDS"
'Use the Show method to display the File Picker dialog box and return the user's action.
'If the user presses the action button...
If .Show = -1 Then
DoCmd.GoToRecord , "", acNewRec
Me![Link MSDS] = .SelectedItems(1)
**
'If the user presses Cancel...
Else
End If
End With
'Set the object variable to Nothing.
Set fd = Nothing
End Sub
I know that putting the following code in at the ** works in Excel, I am after something like it which will work in Access!
ActiveSheet.Hyperlinks.Add Anchor:=Cells(ActiveCell.row, Range("LinkCol").Column), Address:=.SelectedItems(1), TextToDisplay:="MSDS"
Try this if you want the file path as both the hyperlink address and display text.
Me![Link MSDS] = "#" & .SelectedItems(1) & "#"
If you want the address with only the file name (without the path) as the display text, try this:
Me![Link MSDS] = Dir(.SelectedItems(1)) & "#" & .SelectedItems(1) & "#"
See HyperlinkPart Method for more background information. You might even prefer to manipulate your hyperlink field data using HyperlinkPart.