Excel VBA Macro for Printing URLs in Spreadsheet by Page Number - vba

What I have is an excel spreadsheet with hyperlinks to documents online, I want to print a certain range of these depending on requirements. Most of the time the whole document needs printed, but sometimes we only want certain pages printed, ideally this range of pages would be printed stapled as well.
I have a macro that somewhat does what I'm after:
Option Explicit
Sub PrintHyperlinkedPDFs()
Dim PDFrng As Range, PDF As Range
Dim AdobeReader As String, pdfLINK As String
'there is an extra space at the end of this string
AdobeReader = "C:\Program Files\Adobe\Reader 11.0\Reader\AcroRd32.exe "
Set PDFrng = Selection 'change this to whatever method you want for setting
'the range of PDF link cells to process and print
For Each PDF In PDFrng
If PDF.Hyperlinks.Count > 0 Then pdfLINK = PDF.Hyperlinks(1).Address
Shell """" & AdobeReader & """/n /t """ & pdfLINK & """"
Next PDF
End Sub
You highlight what cells containing the links you want to print then run and it sends some of them (if its more than around 4 documents it freezes and doesn't send them all).
Ideally, I would like to set-up some buttons to print pre-defined combinations of these documents but I'm not exactly a VBA professional and therefore this may be out of my skill range..
Any help would be much appreciated.

You can add a Button directly on the Sheet and assign the macro SetupBtn already stored in the sheet:
Sub SetupBtn()
ActiveSheet.Range("B2,B4").Select
PrintHyperlinkedPDFs
End Sub
This macro use your Sub, selecting the cells you want before the Sub.
Creating the combination of cells, you create combination of print.
The sequence of cells are the sequence of print. If you want two copy of a document (for example a separator of pages), write something like that:
ActiveSheet.Range("B2,B4,B2").Select
It's strange, but print 3 doc with 2 cells selected...

Related

Excel Macro to read multiple files in a folder and search in it

I have some excel workbooks of same header rows. I need to search in a particular column in all these workbooks and do a countif kind of functionality in a corresponding column( different than the first column)
For eg.. Column A has names of boxes, B has information about the contents in each box. I would like to search multiple excels in folder and get a report of unique box names and their content counts. Box A has 5 apples, 2 oranges , 1 mango.
I hope this requirement is clear enough. Could anyone help me with a base axcel macro code?
Talking about workbooks you have different files (*.xls) in one folder? Then you can start with something like this:
Dim Path As Integer
Path = "Type in the path with your workbooks"
File = Dir$(Path & "\*.xls")
Do While File <> ""
'Do stuff like:
'opening your workbook and search for the names of the boxes
'save your needed informations in a variable or array
'close the workbook
File = Dir$()
Loop
Or do you mean you have one workbook (one file) with more worksheets? Then do something like this:
Dim i
For i = 1 To ThisWorkbook.Worksheets.Count
'Do your stuff here
Next i
If you want to get better help please post some of your code with specific questions

Programmatically Update Linked Named Range of excel object in MS Word (2007)

First question, excuse me if this has already been solved, but I've searched thoroughly and cannot find an answer:
I have linked several named ranges into a word document. This word doc (and the related excel workbook with named ranges) is a template: it's for a coworker who will make many copies of these templates (of both the word doc and the excel workbook).
I would like to include a command button in the word doc that, when clicked, will update the sources for the linked named ranges. Specifically, I want it to set the workbook with the same name as the worddoc, as the source.
The issue is that it does not like the named range I have entered. I get the:
Run-time error '6083': Objects in this document contain links to files that cannot be found. The linked information will not be updated.`
However, I have quadrupled-checked my excel doc, the named range exists. AND, when I hit Alt+F9 in word, I clearly see the link contains the named range!
{LINK Excel.Sheet.8 C:\Users\Marc\Documents\WIP_SSS.xlsm CED \a \p}
Here is my code:
Public Sub ChangeSource()
Dim filename As Variant
Dim fieldcount As Integer
Dim x As Integer
filename = Left(Application.ActiveDocument.Name, Len(Application.ActiveDocument.Name) - 4) & "xlsm"
fieldcount = ActiveDocument.Fields.Count
For x = 1 To fieldcount
'Debug.Print ActiveDocument.Fields(x).Type
If ActiveDocument.Fields(x).Type = 56 Then
ActiveDocument.Fields(x).LinkFormat.SourceFullName = ActiveDocument.Path & "\" & _
filename & "!CED"
End If
Next x
End Sub
If I don't enter the named range at all, the macro works, but it embeds the entire excel worksheet (which I do not want it to do). Any ideas on how/ why it is not liking the named range?
Thanks,
Marc
UPDATE:
With help from Bibadia, I found a solution; in addition, I want to document some strange behavior exhibited by Word VBA:
First off, the solution code:
Public Sub ChangeSource()
Dim filename As Variant
Dim fieldcount As Integer
Dim x As Integer
filename = ThisDocument.Path & "\" & Left(Application.ActiveDocument.Name, Len(Application.ActiveDocument.Name) - 4) & "xlsm"
fieldcount = ActiveDocument.Fields.Count
For x = 1 To fieldcount
On Error Resume Next
If ActiveDocument.Fields(x).Type = 56 Then
ActiveDocument.Fields(x).Delete
End If
Next x
ActiveDocument.Bookmarks("R1").Range.InlineShapes.AddOLEObject filename:=filename & "!Range1", LinkToFile:=True
End Sub
I first deleted all type 56 fields (linked object, or more technically, "wdfieldlinked"). Then, I added OLEObjects at pre-set bookmark locations.
Interestingly, just as Bibadia noted, the key was to input the LinkToFile:=True code. It seems Word will not accept the object if it is embedded: if I remove that line, I get the error Word Cannot obtain the data for the C:\...\document!NamedRange link.
Finally, I found one other odd behavior: When trying to simply replace the link, using this code,
ActiveDocument.Fields(1).LinkFormat.SourceFullName = filepath+name & _
"!CED" 'that is the named range
it would work once, when I changed both the word document's and the excel workbook's filenames (see original message for context). So, when the new filepath+name DID NOT match the existing filepath+name, Word VBA accepted the change. However, once initially updated, if I tried to run the macro again, I would get:
run-time error '6083': Objects in this document contain links to files that cannot be found. The linked information will not be updated.
I would get this error even if I changed the named range to another named range in the same worksheet (and obviously same workbook). So it appears that Word VBA does not like "updating" filepath+name when the filepath+name does not change.
Just so anyone who didn't know (like me) now knows. Sorry for the long update, I just wanted to be thorough.
I am not completely sure of this, but it is a little too long for a comment.
As far as I know, you can only set LinkFormat.FullSourceName to the name of a file, not a fullname + subset name, which is what you are trying to do when appending the "!CED". Although you can read the subset name (CED) from OleFormat.Label, you can't modify it as it's a read-only property.
So if you actually need to modify the subset name (CED), AFAICS the only way to do it is to delete and reinsert the LINK field. If you reinsert using Fields.Add, you just specify the text of the field, so you can get the file name and Subset name right. What is slightly confusing is that if you insert a LINK using InlineShapes.AddOleObject, you can specify fullname+subset name in exactly the way that you are trying to do in your code.
However, I do not think you are trying to modify the Subset name. So let's assume that you already have a LINK field along the lines of
{ LINK Excel.SheetMacroEnabled.12 "the full pathname of a .xlsm file" CED \a f 0 \p }
Word will only be able to update that link if the path+filename is valid (i.e. there's a .xlsm at that location, the workbook has a Range Name called CED, and the Range Name is in the first Sheet. Otherwise, you have to specify a Sheet name as well, e.g.
{ LINK Excel.SheetMacroEnabled.12 "the full pathname of a .xlsm file" Sheet2!CED \a f 0 \p }
It's just a guess, but if your code is trying to connect to a Workbook where the range defined by CED is not in the first sheet, you would see the error you describe.
Further, the scope of the CED Range Name has to be either "workbook" or the name of the first sheet. Otherwise, if the scope is the first sheet but the range is actually in another sheet, or vice versa, I do not think Word can make the connection whatever subset name you provide (my guess is that Word never really caught up with Excel after Excel introduced multi-sheet workbooks).
If CED can reference sheets other than the first one, I think you will probably have to use the Excel object model to discover which sheet its Range is in, construct the appropriate Subset name, and delete/re-insert the LINK field.

how to create relative path in hyperlink excel ? (Word.Document.12)

I have two documents, one which has all the info and it is a word document, and another that is an excel document, that have just some highlights from the word document.
I want to create some links between some selected text in word and excel cells, so far the special past is doing a great job, and create link in this format
=Word.Document.12|'C:\Users\...\xxx.docx'!'!OLE_LINK9'
Now i want to copy both documents in my usb and past them in other computers, this where the problem is, i would have to do the special past all over again since the path is different now, what i though as a solution was to put the path to the word document in cell let say A1 and concatenate the formula above, something like
=Word.Document.12|A1!'!OLE_LINK9'
but it doesnt work, it throws an error message, can you please help me?
PS : I would like to avoid vba if possible
PS : I would like to avoid vba if possible
I have included both ways to do it since the question is tagged with Excel-VBA as well :)
Take your pick.
VBA Way
Is this what you are trying?
Sub Sample()
Dim objOle As OLEObject
'~~> Change this to the respective Sheet name
With ThisWorkbook.Sheets("Sheet1")
'~~> This is your embedded word object
Set objOle = .OLEObjects("Object 1")
'~~> Cell A1 has a path like C:\Temp\
objOle.SourceName = "Word.Document.12|" & .Range("A1").Value & "xxx.docx!'"
End With
End Sub
Non VBA Way
Create a named range and call it say Filepath. Set the formula to
="Word.Document.12|'" & Sheet1!$A$1 & "xxx.docx'!'"
Where Cell A1 will have the file path.
Next Select your word document and in the formula bar, type =Filepath and you are done.

Error 1004 with VBA code with bookmarks

I am using a macro to populate a word document with text from named ranges in excel. The word document has bookmarks that correspond with the named excel ranges. I did not write the code, but rather copied it from another source.
There is quite a bit more to this macro than the snippet I posted. I could post the rest if that is useful. I had about half of my word document bookmarked and the macro was working fine then it suddenly stopped working.
I am receiving a error 1004 in the line highlighted below. I am a newbie so I'm not even quite sure what I should be searching for to fix this issue. Any assistance you could provide would be appreciated! Thanks in advance!
P.S. In case it's relevant, I am using Word and Excel 2007
'PASTE TEXT STRINGS LOOP
n = 1
For Each temp In BkmTxt
p = p + 1
Prompt = "Please wait. Copying text. Carrying out operation " & p & " of " & pcount & "."
Application.StatusBar = Prompt
'If The Bkmtxt(n) is empty then go to the next one, once that has been found do next operation.
If BkmTxt(n) = Empty Then
n = n + 1
'should find match and work
Else
'You might want to use multiple copies of the same text string.
'In this case you need to call the bookmark as follows: "ARTextWhatever_01"
'You can use as many bookmarks as you want.
BkmTxtSplit = Split(BkmTxt(n), "_")
vValue = Range(BkmTxtSplit(0)).Text **<----- ERROR HERE**
Set wdRng = wdApp.ActiveDocument.Bookmarks(BkmTxt(n)).Range
If Len(sFormat) = 0 Then
'replace the bookmark text
wdRng.Text = vValue
Else
'replace the bookmark text with formatted text
wdRng.Text = Format(vValue, sFormat)
End If
'Re-add the Bookmark
wdRng.Bookmarks.Add BkmTxt(n), wdRng
n = n + 1
End If
Next
Step 1: Don't copy code from external sources. Use external sources as a learning tool and try to understand what they are actually doing.
Now if I understand you correctly, you simply have an Excel sheet with named ranges, I assume they have information already within them, and a word document with bookmarks that EXACTLY match the named ranges:
Step 2: Make sure you have the word object library reference within excel
Here:
sub KeepItDoin()
dim xlRange as Excel.Range
dim wdApp as new Word.Application
dim wdDoc as Word.Document
dim wdBkm as Word.Bookmark
set wdDoc = wdApp.Documents.Open( "Filepath" ) 'get filepath from where ever
for each wdBkm in wdDoc.Bookmarks
set xlRange = Application.Range(wdBkm.Name)
wdBkm.range.text = xlRange.Value
next wdBkm
end sub
That will get you close probably (didn't test, don't care if it works. Use it to learn). The idea is that if the bookmarks match up to the range, we can use their names to find the ranges in excel and then tell excel to move the data within it into the bookmarks range.
You will likely need to add some formatting or maybe create a table and then move cell by cell in the range and fill the table but this is as close as I'm willing to get since you like to copy pasta.
In case anyone is interested, I figured it out. There was an error with the bookmarks I inserted into my Word document. This macro returns Error 1004 if the word document contains a bookmark that does not correspond to a range in excel. Thank you for your help.

Using vba to copy the contents of a word document into another word document

I haven't used VB for years, so please forgive me if this turns out to be obvious. I'm trying to write a word vba macro for use in a template which will display a userform and then import the contents of fileA.docx, fileB.docx, or fileC.docx depending on the userform. (After that I'm going to use bookmarks to fill in some form data, I don't know if that's relevant). Files A, B, and C will contain text with some basic formatting such as lists, but nothing fancy.
The solutions I've seen online can copy the contents of file to a new file, but ideally I would like to import the entirety of one of those files into the new, currently unnamed file that I'm getting from the template. I think where I'm running into problems is with switching the selection to one of those files, and then back to the new unnamed document, though I could use a hand to make sure I'm copying correctly as well.
Update: I was making things too hard, though the answers here got me pointed in the right direction (thanks!). In the end I just did
ThisDocument.Activate
Selection.InsertFile("fileA")
which gives me the raw dump of everything that I wanted.
Using commands such as these you can switch between which Document you're using and copy and paste elements:
ThisDocument.Activate 'Sets the main document active
Documents("Name.doc").Activate 'Activates another document
You can insert, copy and paste things in and out of documents using copy commands.
ThisDocument.Range.InsertAfter("String") 'Insert text
Selection.WholeStory 'Select whole document
Selection.Expand wdParagraph 'Expands your selection to current paragraph
Selection.Copy 'Copy your selection
Documents("name.doc").Activate 'Activate the other document
Selection.EndKey wdStory 'Move to end of document
Selection.PasteAndFormat wdPasteDefault 'Pastes in the content
You can then go and format such, or copy and paste them with original formatting from before.
Here is a significant improvement (I think) you will want to incorporate because it:
does not use the clipboard and thus does not make your macro vulnerable to the user changing the contents of the clipboard while your macro is running
does not use a file and thus greatly improve the speed by eliminating I/O and eliminates the potential of having to deal with file system security/permissions, etc. Please do not use .InsertFile() if you are looping through documents you will slow yourself down. Use it once, at the end -only if you have to. The example below shows how to accomplish the same result without using .InsertFile()
The idea is to transfer some portion of text found in 1 source document, to a destination document that is different than the source, and keep the source formatting.
To accomplish the above (skipping the code to open documents):
For Each oTable In oDoc_Source
'the above could have been anything that returns a Range object
'such as: ActiveDocument.Content.Find.Execute ....
'...
'logic here to identify the table, or text, you are looking for
'...
'I can't believe the MS Dev Center folks could only think
'of .InsertFile(), which is the last resort I would go for,
'especially if your code runs on a web server [concurrent web requests]!
'SAFEST
'(no user interference on clipboard possible, no need to deal with file i/o and permissions)
'you need a reference to Document.Content,
'as the act of obtaining a reference "un-collapses" the range, so the below 3 lines must be in that order.
Set oRange = oDoc_DestinationDoc.Content
oRange.Collapse Direction:=wdCollapseEnd
oRange.FormattedText = oTable.Range
'BRUTE, AND PRONE TO RANDOM ERRORS AND HANGS DUE TO USER INTERFERENCE WITH CLIPBOARD
'find a way to implement WIHTOUT using the CLIPBOARD altogether to copy the below range object
'it will be easier for PC users to use the clipboard while the macro runs
'and it will probably be safer for the output of this macro to remain uncorrupted
'oTable.Range.Copy
'Set oRange = oDoc_DestinationDoc.Content
'oRange.Collapse Direction:=wdCollapseEnd
'oRange.Paste
'THE BELOW DOES NOT WORK
' '1) - cannot add a range from another document
' 'adds only text, not the formats and not the table layout
' oTable.Range.TextRetrievalMode.IncludeFieldCodes = True
' oTable.Range.TextRetrievalMode.IncludeHiddenText = True
' oDoc_DestinationDoc.Content.InsertAfter oTable.Range
'
' '2) - cannot add a range from another document
' oDoc_DestinationDoc.Content.Tables.Add oTable.Range, iRowMax, iColMax
'
' '3) - only puts in plain text, and it replaces the range without the .Collapse call
' oDoc_DestinationDoc.Content.Text = oTable.Range
Record a macro...
start in the source document
press ctrl-a to select everything
press ctrl-c to copy it to the clipboard
switch to the target document
press ctrl-v to paste into the document
stop recording
or (assuming word 2007 or later)
start in the target document with the source document closed
on the ribbon click insert > object > Text from file...
navigate to the source document
click the insert button
stop recording
I prefer the second version so I should have put it first
I was doing the same thing, tried to select the other document, copy and paste. But it didn't worked (I received an error probably because some other application was using the clipboard, but I am not sure.). So I did a little search and found the perfect solution on Microsoft Dev Center.
https://msdn.microsoft.com/en-us/vba/word-vba/articles/selection-insertfile-method-word
Selection.Collapse Direction:=wdCollapseEnd
Selection.InsertFile FileName:="C:\TEST.DOC"
'set current doc name and path
Dim docName As String: docName = ActiveDocument.name
Dim filepath As String: filepath = ActiveDocument.Path
'create a new file
Documents.Add
'get the path of a current file
ChangeFileOpenDirectory filepath
'insert content of current file to newly created doc
Selection.InsertFile _
FileName:=docName, _
Range:="", _
ConfirmConversions:=False, _
Link:=False, _
Attachment:=False
'open prompt to save a new file
With Dialogs(wdDialogFileSaveAs)
.name = docName & "-copy"
.Show
End With