I have about a dozen linked excel OLE objects in my word document. These files get moved around the network frequently so I need an easy intuitive way for the underlying links to be updated. I tried a code I found on this website however while it updated the source it seems to also update what is being shown in the object itself so all the objects change to whatever worksheet was in focus when the excel workbook was saved last. I'm trying to retain format and range while updating the source. Any help would be great.
Here is the code I tried presently:
Private Sub CommandButton1_Click()
Dim OldFile As String
Dim xlsobj As Object
Dim xlsfile_chart As Object
Dim dlgSelectFile As FileDialog 'FileDialog object '
Dim thisField As Field
Dim selectedFile As Variant
'must be Variant to contain filepath of selected item
Dim newFile As Variant
Dim fieldCount As Integer '
Dim x As Long
On Error GoTo LinkError
'create FileDialog object as File Picker dialog box
Set dlgSelectFile = Application.FileDialog
(FileDialogType:=msoFileDialogFilePicker)
With dlgSelectFile
.Filters.Clear 'clear filters
.Filters.Add "Microsoft Excel Files", "*.xls, *.xlsb, *.xlsm,*.xlsx" 'filter
for only Excel files
'use Show method to display File Picker dialog box and return user's action
If .Show = -1 Then
'step through each string in the FileDialogSelectedItems collection
For Each selectedFile In .SelectedItems
newFile = selectedFile 'gets new filepath
Next selectedFile
Else 'user clicked cancel
Exit Sub
End If
End With
Set dlgSelectFile = Nothing
'update fields
Set xlsobj = CreateObject("Excel.Application")
xlsobj.Application.Visible = False
Set xlsfile_chart = xlsobj.Application.Workbooks.Open(newFile, ReadOnly =
True)
Application.ScreenUpdating = False
With xlsobj.Application
.calculation = xlcalculationmanual
.enableevents = False
End With
fieldCount = ActiveDocument.Fields.Count
For x = 1 To fieldCount
With ActiveDocument.Fields(x)
If .Type = 56 Then
.LinkFormat.SourceFullName = newFile
End If
End With
Next x
With xlsobj.Application
.calculation = xlcalculationmanual
.enableevents = True
End With
Application.ScreenUpdating = True
MsgBox "Data has been sucessfully linked to report"
'clean up
xlsfile_chart.Close SaveChanges:=False
Set xlsfile_chart = Nothing
xlsobj.Quit
Set xlsobj = Nothing
Exit Sub
LinkError:
Select Case Err.Number
Case 5391 'could not find associated Range Name
MsgBox "Could not find the associated Excel Range Name " & _
"for one or more links in this document. " & _
"Please be sure that you have selected a valid " & _
"Quote Submission input file.", vbCritical
Case Else
MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical
End Select
' clean up
Set xlsfile_chart = Nothing
xlsobj.Quit
Set xlsobj = Nothing
End Sub
Related
I am searching for a string in a table inside a PDF file using a VBA script. The script is working when called from Word but not when called from Excel.
My PDF has many tables and the goal is to get the table number of the table containing a specific string.
Sub FindTableno()
Dim oTbl As Table
Dim oRow As Row
Dim oCell As Cell
Dim tblno As Integer
On Error Resume Next
' Create a "FileDialog" object as a File Picker dialog box.
Dim fd As Office.FileDialog
Set fd = Application.FileDialog(msoFileDialogFilePicker)
Dim sfileName As String
With fd
.AllowMultiSelect = False
.Filters.Clear
.Title = "Select a PDF File"
.Filters.Add "All PDF Documents", "*.pdf?", 1
If .Show = True Then
sfileName = Dir(.SelectedItems(1)) ' Get the file.
End If
End With
Application.ScreenUpdating = False
Application.DisplayAlerts = False
If Trim(sfileName) <> "" Then
Dim objWord As Object ' Create a Word object.
Set objWord = CreateObject("Word.Application")
objWord.Visible = False ' Do not show the file.
' Create a Document object and open the Word file.
Dim objDoc As Word.Document
Set objDoc = objWord.Documents.Open(FileName:=fd.InitialFileName & sfileName, Format:="PDF Files", ConfirmConversions:=False)
' Search within tables in selected PDF file
objDoc.Activate
If ActiveDocument.Tables.Count > 0 Then
tblno = 1
For Each oTbl In ActiveDocument.Tables
For Each oRow In oTbl.Rows
For Each oCell In oRow.Cells
oCell.Select
Selection.Find.Execute FindText:="Nutrition Information"
If Selection.Find.Found = True Then
MsgBox (tblno)
Exit Sub
Else
End If
Next
Next
tblno = tblno + 1
Next
End If
MsgBox ("Not Found, Total Tables Searched:" & ActiveDocument.Tables.Count)
End If
Dim X As Variant
X = Shell("powershell.exe kill -processname winword", 1)
End Sub
The main issue is in this part where you use oCell.Select and afterwards Selection.Find. In this case Selection refers to the selected cell in Excel! This is because you didn't specifiy any relation to Word here, so Excel assumes you mean the selected cell in Excel.
I recommend to read How to avoid using Select in Excel VBA. The same is valid for Word VBA code.
Also don't use .Activate or you will get a similar issue. Always reference the worksheet or document directly:
If objDoc.Tables.Count > 0 Then
tblno = 1
For Each oTbl In objDoc.Tables
For Each oRow In oTbl.Rows
For Each oCell In oRow.Cells
oCell.Range.Find.Execute FindText:="Nutrition Information"
If oCell.Range.Find.Found = True Then
MsgBox (tblno)
Exit Sub
End If
Next
Next
tblno = tblno + 1
Next
End If
MsgBox ("Not Found, Total Tables Searched:" & objDoc.Tables.Count)
Thanks #Pᴇʜ, this worked for me
Sub FindTableno()
Dim oTbl As Table
Dim oRow As Row
Dim oCell As Cell
Dim tblno As Integer
' Create a "FileDialog" object as a File Picker dialog box.
Dim fd As Office.FileDialog
Set fd = Application.FileDialog(msoFileDialogFilePicker)
Dim sfileName As String
With fd
.AllowMultiSelect = False
.Filters.Clear
.Title = "Select a PDF File"
.Filters.Add "All PDF Documents", "*.pdf?", 1
If .Show = True Then
sfileName = Dir(.SelectedItems(1)) ' Get the file.
End If
End With
Application.ScreenUpdating = True
Application.DisplayAlerts = True
If Trim(sfileName) <> "" Then
Dim objWord As Object ' Create a Word object.
Set objWord = CreateObject("Word.Application")
objWord.Visible = True ' Do not show the file.
' Create a Document object and open the Word file.
Dim objDoc As Word.Document
'Set objDoc = objWord.Documents.Open(Filename:=fd.InitialFileName & sfileName, Format:="PDF Files", ConfirmConversions:=False)
Set objDoc = objWord.Documents.Open(Filename:=fd.InitialFileName & sfileName, Format:="PDF Files", ConfirmConversions:=False)
' Search within tables in selected PDF file
If objDoc.Tables.count > 0 Then
tblno = 1
For Each oTbl In objDoc.Tables
For Each oRow In oTbl.Rows
For Each oCell In oRow.Cells
pos = InStr(oCell.Range.Text, "Nutrition Information ")
If pos <> 0 Then
GoTo line1
End If
'Else
'End If
Next
Next
tblno = tblno + 1
Next
End If
MsgBox ("Not Found, Total Tables Searched:" & objDoc.Tables.count)
'MsgBox (oCell.Range.Text)
End If
line1:
MsgBox (tblno)
End Sub
I'm running code which opens a user provided spreadsheet. It just brings in the first column excluding the header. running the code once works as expected except it leaves the EXCEL.EXE instance open at the end. I've read several questions having this similar problem, all the answers surround finding any object which was not quit/closed and then set to nothing. I do this for every object in my code and even have error checking which catches if it doesn't complete and to quit and clear the objects. On the second run of the code after the EXCEL.EXE doesn't close it throws a "(1004) Application-defined or Object Defined error" on .Cells(Rows.Count, 1).End(xlUp).Row anyone know why that is?
any help would be appreciated
Private Sub SplitImports()
Dim StringVar As Variant
Dim strLn As String
'Asks user for Filepath
StringVar = InputBox("Please enter the file path for your list", "Import", "H:\FNMA_WFDC")
'Ends Function if no input or cancel is detected
MsgBox (StringVar)
If (StringVar = vbNullString) Then
MsgBox ("No input, Please try again")
Quittracker = True
Exit Sub
End If
'Scrubs outer quotes if present
StringVar = Replace(StringVar, Chr(34), "", 1, 2)
'Creates the object to check the file
Dim FSO As Object
Set FSO = CreateObject("Scripting.Filesystemobject")
MsgBox ("Got Passed the FSO Object")
'Checks that our file exists, exits if not
If (Not FSO.FileExists(StringVar)) Then
MsgBox ("File does not exist, try again")
Quittracker = True
Exit Sub
End If
Set FSO = Nothing
Dim xlApp As Object 'Excel.Application
Dim xlWrk As Workbook 'Excel.Workbook
Dim i As Long
Set xlApp = New Excel.Application
MsgBox ("Dimmed the excel objects")
xlApp.Visible = False
On Error GoTo ErrorTrap
Set xlWrk = xlApp.Workbooks.Open(StringVar) 'opens the excel file for processing
MsgBox ("objects are set")
With xlWrk.Worksheets("Sheet1")
.Columns("A").NumberFormat = "#"
MsgBox (.Cells(Rows.Count, 1).End(xlUp).Row)
'walks through the excel sheet to the end and inserts the lines below the headerline into the database
For i = 2 To .Cells(Rows.Count, 1).End(xlUp).Row
DoCmd.RunSQL "Insert Into Split_List(Criteria) values('" & .Cells(i, 1).Text & "')"
Next i
End With
MsgBox ("About to Clear and close the objects")
'closes the workbook and quits the application
xlWrk.Saved = True
xlWrk.Close
Set xlWrk = Nothing
xlApp.Quit
Set xlApp = Nothing
MsgBox ("End of the import sub")
Exit Sub
ErrorTrap:
xlWrk.Saved = True
xlWrk.Close
Set xlWrk = Nothing
xlApp.Quit
Set xlApp = Nothing
MsgBox ("(" & Err.Number & ") " & Err.Description
Quittracker = True
Exit Sub
I have ContentControl drop down box in Word. Once I select an item from a Drop Down list I want to search for that in an Excel document and set the row number equal to a variable.
The code below is what I tried but the Columns("G:G").Find part says its not defined.
Sub findsomething(curRow)
Dim rng As Range
Dim rownumber As Long
curPath = ActiveDocument.path & "\"
Call Set_Variable(curPath)
StrWkShtNm = "Chapters"
If Dir(StrWkBkNm) = "" Then
MsgBox "Cannot find the designated workbook: " & StrWkBkNm, vbExclamation
Exit Sub
End If
Set rng = Columns("G:G").Find(what:=curRow)
rownumber = rng.Row
MsgBox rownumber
' Release Excel object memory
Set xlWkBk = Nothing
Set xlApp = Nothing
Application.ScreenUpdating = True
End Sub
While using more than one MS Office application it is a good idea to specify which application you are targeting:
Excel.Application.ThisWorkbook.Sheets(1).Range("A1").Select
this is what ended up working. you set me on the right track with referencing Excel.
Sub findsomething(curRow)
Dim rng As Long
Dim rownumber As Long
curPath = ActiveDocument.path & "\"
Call Set_Variable(curPath)
StrWkShtNm = "Chapters"
MsgBox "curRow = " & curRow
If Dir(StrWkBkNm) = "" Then
MsgBox "Cannot find the designated workbook: " & StrWkBkNm, vbExclamation
Exit Sub
End If
With xlApp
.Visible = False
Set xlWkBk = .Workbooks.Open(FileName:=StrWkBkNm, ReadOnly:=True, AddToMRU:=False)
With xlWkBk
With .Worksheets(StrWkShtNm)
rng = .Range("G:G").Find(what:=curRow)
MsgBox rng
End With
.Close False
End With
.Quit
End With
' Release Excel object memory
Set xlWkBk = Nothing: Set xlApp = Nothing
Application.ScreenUpdating = True
End Sub
I'm trying to open an Excel file from Access and do some stuff with It, but code is not stable. Sometimes It works, other times not. Here's how I do this:
Dim FilePath As String
Dim ExcelApp As Excel.Application
FilePath = "C:\Users\Lucky\Desktop\Test.xls"
Set ExcelApp = CreateObject("Excel.Application")
ExcelApp.Workbooks.Open (FilePath)
With ExcelApp
'do some stuff here
End With
ExcelApp.Workbooks.Close
Set ExcelApp = Nothing
I've also noticed that once I run code, Excel starts proccess under Task Manager, that has to be killed manually in order to get code working again. Otherwise I get two types of error with Excel file:
one is that If I click Excel file, It doesn't open, It just flashes for a second and dissapears
and other is that Excel file opens in "read-only" mode...
So I reckon there is some flaw when file is closed in my code. How can I fix this ?
I can't see what's wrong with your code - maybe the path to the desktop?
This is the code I usually use - I've added another function to help choose the file. It uses late binding, so no need to set a reference to Excel - you don't get the IntelliSense and can't use Excel constants such as xlUp - you have to use the numerical equivalent.
Public Sub Test()
Dim oXLApp As Object
Dim oXLWrkBk As Object
Dim oXLWrkSht As Object
Dim vFile As Variant
Dim lLastRow As Long
vFile = GetFile()
Set oXLApp = CreateXL
Set oXLWrkBk = oXLApp.WorkBooks.Open(vFile, False)
Set oXLWrkSht = oXLWrkBk.WorkSheets(1) 'First sheet. Can also use "Sheet1", etc...
lLastRow = oXLWrkSht.Cells(oXLWrkSht.Rows.Count, "A").End(-4162).Row '-4162 = xlUp
MsgBox "Last row in column A is " & lLastRow
oXLWrkBk.Close False
oXLApp.Quit
Set oXLWrkBk = Nothing
Set oXLApp = Nothing
End Sub
Public Function CreateXL(Optional bVisible As Boolean = True) As Object
Dim oTmpXL As Object
'''''''''''''''''''''''''''''''''''''''''''''''''''''
'Defer error trapping in case Excel is not running. '
'''''''''''''''''''''''''''''''''''''''''''''''''''''
On Error Resume Next
Set oTmpXL = GetObject(, "Excel.Application")
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
'If an error occurs then create an instance of Excel. '
'Reinstate error handling. '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
If Err.Number <> 0 Then
Err.Clear
On Error GoTo ERROR_HANDLER
Set oTmpXL = CreateObject("Excel.Application")
End If
oTmpXL.Visible = bVisible
Set CreateXL = oTmpXL
On Error GoTo 0
Exit Function
ERROR_HANDLER:
Select Case Err.Number
Case Else
MsgBox "Error " & Err.Number & vbCr & _
" (" & Err.Description & ") in procedure CreateXL."
Err.Clear
End Select
End Function
Function GetFile(Optional startFolder As Variant = -1, Optional sFilterName As String = "") As Variant
Dim fle As Object
Dim vItem As Variant
'''''''''''''''''''''''''''''''''''''''''''
'Clear the file filter and add a new one. '
'''''''''''''''''''''''''''''''''''''''''''
Application.FileDialog(3).Filters.Clear
Application.FileDialog(3).Filters.Add "'Some File Description' Excel Files", "*.xls, *.xlsx, *.xlsm"
Set fle = Application.FileDialog(3)
With fle
.Title = "Select a file"
.AllowMultiSelect = False
If startFolder = -1 Then
.InitialFileName = CurrentProject.Path
Else
If Right(startFolder, 1) <> "\" Then
.InitialFileName = startFolder & "\"
Else
.InitialFileName = startFolder
End If
End If
If .Show <> -1 Then GoTo NextCode
vItem = .SelectedItems(1)
End With
NextCode:
GetFile = vItem
Set fle = Nothing
End Function
I have managed to solve my problem. There is nothing wrong with code in my question, except that instead of declaring
Dim ExcelApp As Excel.Application
It's better to use
Dim ExcelApp As Object
But much bigger problem is with code that does changes in Excel, such as this line:
x = Range(Cells(1, i), Cells(Rows.Count, i).End(xlUp)).Value
And correct synthax is:
x = ExcelApp.Range(ExcelApp.Cells(1, i), ExcelApp.Cells(ExcelApp.Rows.Count, i).End(xlUp)).Value 'maybe also better to replace xlUp with -4162
So, whenever you use some code for Excel file from Access, DON'T FORGET to reference everything to Excel object. And ofcourse, before everything, a proper reference must be set in VBA console, in my case Microsoft Office 15.0 library.
I am trying to update the source to all the links in a word report by using a macro in word VBA. I want to be able to offer a dialog box to user then they select file and it replaces current source in all links in the word doc. The code i have below works but really slowly. I also seem to have to open excel in the background or the links wont work? not sure why this is??
It seems to go through eack link in tuen. Is there a way to globally change all the links at the same time possibly using find and repalce? please any help is greatly appreciated! I need this for a reprot in work and so i need to find a solution as soon as possible.
Private Sub CommandButton1_Click()
Dim OldFile As String
Dim xlsobj As Object
Dim xlsfile_chart As Object
Dim dlgSelectFile As FileDialog 'FileDialog object '
Dim thisField As Field
Dim selectedFile As Variant
'must be Variant to contain filepath of selected item
Dim newFile As Variant
Dim fieldCount As Integer '
Dim x As Long
On Error GoTo LinkError
'create FileDialog object as File Picker dialog box
Set dlgSelectFile = Application.FileDialog
(FileDialogType:=msoFileDialogFilePicker)
With dlgSelectFile
.Filters.Clear 'clear filters
.Filters.Add "Microsoft Excel Files", "*.xls, *.xlsb, *.xlsm,
*.xlsx" 'filter for only Excel files
'use Show method to display File Picker dialog box and return user's
action
If .Show = -1 Then
'step through each string in the FileDialogSelectedItems collection
For Each selectedFile In .SelectedItems
newFile = selectedFile 'gets new filepath
Next selectedFile
Else 'user clicked cancel
Exit Sub
End If
End With
Set dlgSelectFile = Nothing
' update fields
Set xlsobj = CreateObject("Excel.Application")
xlsobj.Application.Visible = False
Set xlsfile_chart = xlsobj.Application.Workbooks.Open(newFile,
ReadOnly = True)
Application.ScreenUpdating = False
With xlsobj.Application
.calculation = xlcalculationmanual
.enableevents = False
End With
fieldCount = ActiveDocument.Fields.Count
For x = 1 To fieldCount
With ActiveDocument.Fields(x)
If .Type = 56 Then
.LinkFormat.SourceFullName = newFile
End If
End With
Next x
With xlsobj.Application
.calculation = xlcalculationmanual
.enableevents = True
End With
Application.ScreenUpdating = True
MsgBox "Data has been sucessfully linked to report"
'clean up
xlsfile_chart.Close SaveChanges:=False
Set xlsfile_chart = Nothing
xlsobj.Quit
Set xlsobj = Nothing
Exit Sub
LinkError:
Select Case Err.Number
Case 5391 'could not find associated Range Name
MsgBox "Could not find the associated Excel Range Name " & _
"for one or more links in this document. " & _
"Please be sure that you have selected a valid " & _
"Quote Submission input file.", vbCritical
Case Else
MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical
End Select
' clean up
Set xlsfile_chart = Nothing
xlsobj.Quit
Set xlsobj = Nothing
End Sub
Dim FolderName As String
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
.Show
On Error Resume Next
FolderName = .SelectedItems(1)
On error go to 0
End With
If FolderName = "" Then
Exit Sub
End If
'Continue with code using FolderName as your source path
Hopefully this will serve as a good starting point for you. This will get you the path of the source folder and store it in FolderName. You can then build your link using:
CompletePath = FolderName + [FileNameGoesHere]
(Don't forget to make sure your FolderName has a "\" on the end, else the path will be incorrectly formatted, if it doesn't you can add it in or perform a check to ensure it is present on the end of the FolderName string