How can I change the name of another Excel workbook I'm referencing in my code by entering the file name into a cell? - vba

Here's what I'm trying to do.
My Excel workbook, InspectionFormTemplate3.4.xlsm, exists as a template to copy over data from various other workbooks that have a totally different format. The code works for copying the data over, but I have 1500 reports to convert and every time I have to manually go into my code and ctrl+f replace all instances it references the report to be converted. Instead, I enter data into a cell (S50) and tried replacing the referenced file name with a variable I named oldfilename. That is what gives me an error, and that's what I'm stuck on.
I've looked around for hours in order to find something that does what I'm trying to do, but I have no real experience with VBA at all. I think this is probably just a simple syntax error.
So, here's what I tried so far with my current code.
Private Sub ConvertButton_Click()
Dim oldfilename As String
oldfilename = Range("S50")
'Name of bldg and date
Workbooks("InspectionFormTemplate2018.3.4.xlsm").Worksheets("COVER PAGE").Range("C9").Value = Workbooks("ReporttoConvert.xls").Worksheets("Cover Page").Range("B5").Value
Obviously here, "ReporttoConvert" is a placeholder for an actual workbook name. It works when I manually insert file names, but I need it to look more like this instead:
Workbooks("oldfilename")
in order for it to change to whatever I input as the file name in cell S50. I'm sure this is probably pretty simple, but I have no clue what this would be called or how to do it.

Try this, your macro enabled workbook should be saved in the same folder as the other workbooks, else you will have to change 'ThisWorkbook.path...
Dim OpenWb As String
OpenWb = ThisWorkbook.Worksheets("COVER PAGE").Range("S50").Value
Workbooks.Open Filename:=ThisWorkbook.Path & "\" & OpenWb
ThisWorkbook.Worksheets("COVER PAGE").Range("C9").Value = Workbooks(OpenWb).Worksheets("Cover Page").Range("B5").Value

Related

How to open and activate another workbook in VBA?

I'm creating a macro where I will need to run it in 1 file (called "Masterfile"), it will open and execute the macro on another file ("SurveyReport") and then give me a message box saying "done!".
The code I have to execute on the SurveyReport file works fine when I open that file manually and execute it. The code I need to open SurveyReport from MasterFile is also working it seems, I ran the below with no issues:
Sub PivotTable()
'
' PivotTable Macro
Dim MasterFile As String
MasterFile = ActiveWorkbook.Name
Dim SurveyReport As String
SurveyReport = Application.GetOpenFilename("Excel files (*.xlsx), *xlsx", 1, "Please select the Survey Create Report file", , False)
Workbooks.Open (SurveyReport)
End Sub
But, when I try to activate the SurveyReport file so I can begin executing the macro in it, I get a "Subscript out of range" error. I've tried using the following code after the above block and before the code to execute in the SurveyReport file:
Windows(SurveyReport).Activate
This didn't work, not did:
ThisWorkbook.Activate
...which only had the effect of activating the MasterFile.
SurveyReport file is a .xlsx file. I tried saving it as a .xls file and amending the code, but no joy.
I also tried passing it the file name directly (i.e. Windows("filename.xlsx").Activate), same issue.
ActiveWorkbook is as it says on the tin - whichever workbook happens to be active when the code runs.
ThisWorkbook is always the workbook that the code is sitting in.
You can SET references to specific workbooks rather than just using their names each time. A name can change, or reference the wrong object.... imagine you have a friend called Darren. Each time you mention him you mention him by name. Someone that doesn't know Darren hasn't a clue which Darren out of all the ones available in the world you're talking about. Now imagine you have a little replica of Darren in your pocket... nah, that's a terrible anology - it wouldn't be a replica, it would be a reference to the real Darren... anyway, I digress.
This code sets a reference to the workbook, you can then use that reference any time you want to refer to the correct workbook:
Sub PivotTable()
Dim MasterFile As Workbook
Dim SurveyRptName As String
Dim SurveyReport As Workbook
Set MasterFile = ThisWorkbook '
SurveyRptName = Application.GetOpenFilename("Excel files (*.xlsx), *xlsx", 1, _
"Please select the Survey Create Report file", , False)
If SurveyRptName <> "False" Then
Set SurveyReport = Workbooks.Open(SurveyRptName)
End If
SurveyReport.Activate 'You don't need this line. It doesn't matter if
'the workbook is active, the code knows which one
'you're talking about in the next line.
MsgBox "This is " & SurveyReport.Name & _
" containing " & SurveyReport.Worksheets.Count & " sheets." & vbCr & _
"The value in cell A1 of the first sheet is " & _
SurveyReport.Worksheets(1).Range("A1")
End Sub
Edit: Of course, if you press Cancel when selecting a file then the lines following the IF...THEN code won't have a reference to work on and you'll get a Object Variable or With block variable not set - best not to run the bottom bit of code if you haven't successfully opened the Survey Report file.
The part of the answer that is missing - is that he tried to call a method of an object when his variable was STRING - the open command and subsequent commands will give you an OBJECT - which has properties and methods like .Activate. The STRING type has no such method or property (to be sure - it may have others).
the solution provided by Darren solves this by declaring his SurveyReport as type Workbook - an object of Excel.

Excel VBA: SaveAs, then killing old file has permission error

I have Excel VBA code, which I have distributed, to produce some reports. The code has errors, and I have now fixed them. I want to update the end users.
Assume that the code is in a macro workbook "software.xlsm", as is any data that they have entered.
What I have done is to create "software v1.0.1.xlsm". It checks for the presence of "software.xlsm" and copies all the data and parameters from it to itself. It then renames "software.xlsm" as "software v1.0.0.xlsm.old", and saves itself as "software.xlsm". At this point, Excel is quite happy that this is the new name for the workbook.
All that remains is to delete the "updater". But this is where I run into permission errors - Excel won't let me kill it. It is not in use anywhere else, and it seems as if Excel isn't letting go of the original file name.
This is my code:
set newWb = ActiveWorkbook
thisName = newWb.FullName ' get full name of updater
newWb.SaveAs newWb.Path & "\software.xlsm" ' save updater as code file
Kill thisName ' delete updater <!! FAILS
I'm tearing my hair out here. I have checked here an online, and what I am doing should work - but it doesn't!
Thanks.
EDIT: I should mention that I have also tried SetAttr on the file, which also has no effect.
EDIT2: I am not sure I am being clear about what I want to do. I want to get rid of the updater once it has run, so as to not confuse the users. So I used "SaveAs" to save the updater with a new name, which left TWO files on the disk, and ONE file open in Excel. I am then trying to kill / delete the file that IS NO LONGER open in Excel (i.e. the updater before I saved it with a new name).
newWb.Close (you have to close it before you can delete it)
You can also try setting the variable to nothing.
Set newWb = Nothing
The error you are encountering is because you are trying to access the FullName of the workbook which has since changed after the SaveAs. For example. If I have a workbook with the FullName "SomeFilePath.foo" and I do a SaveAs with FullName & ".old" the FullName is now "SomeFilePath.foo.old".
This makes sense, but the part you are getting tripped up on is your thisname variable. For example:
Dim thisName as String
thisName = ActiveWorkbook.FullName
Debug.Print thisName ' E.G "SomeFilePath.Foo"
ActiveWorkbook.SaveAs ActiveWorkbook.FullName & ".old"
Debug.Print thisname ' Still "SomeFilePath.Foo"
The workbook by the old name simply doesn't exist anymore. It has been changed to the new name.
How do we fix this? You could find the new name and still Kill it, but you dont see Kill often for a reason, it is a bad practice.
The ideal would be to properly host, and reference, your workbook. For example:
thisName = thisWorkbook.FullName
thisWorkbook.SaveAs thisWorkbook.FullName & ".old"
thisWorkbook.Close(False)
We are almost there. We are saving the workbook and closing the current workbook, but this isnt actually what we want. What we need instead is:
thisWorkbook.SaveCopyAs thisWorkbook.FullName & ".old"
thisWorkbook.Close(False)
Instead of changing the FilePath of the updating workbook, just make a copy of it. Not only is it cleaner, but it allows us to not have to worry about the funky things that can happen when we mess with a file when it has code currently running.
Note though, you will want to chance the output file path to the path you actually intend. The ".old" is purely for example. Likewise, ThisWorkbook.Close(False) isn't ideal, but if you must close immediately after finishing then this will work best.
TLDR: The permission denied error is caused by referencing a workbook, by name, that no longer exists within the processes.

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.

Excel macro to save only values of a file with different file names

I wish to save my current excel file as a different file with file name as the value in the cell B10 and taking only values (not formulas) from the current file.
I got the code for getting only values from this link: Saving values from a workbook
Any help appreciated. Thanks.
EDIT:
I want to make a kind of template which will help my colleagues to document in a better way, without wasting disk space in formulas, which takes up about 1.7 mb per *.xls file. If I save only values, it takes about 600 kb. I want it to be flexible to different users, people who won't have to use long instructions to do this.
* vba isn't my area of expertise, and I haven't written any code for this work, so basically any possible way is welcome.
This code will do the need
Sub Macro1()
Dim x As String
Dim y As String
x = "C:\" 'path to file
y = Range("C1").Value 'Reference of the cell which contains the value
Z = x + y
Z = Z + ".xlsm" 'Format of macro enabled worksheet
ActiveWorkbook.SaveAs Filename:=Z, _
FileFormat:=xlOpenXMLWorkbookMacroEnabled, CreateBackup:=False
End Sub
Since you provided a Text only question, I should give you a Text Only Answer.
To do what you want you have to:
Copy your worksheet using Sheets Object Copy method. It has optional arguments and if you omit it, it automatically creates a new workbook that contains the copied worksheet.
After copying, you can use ActiveObject (e.g. ActiveWorkbook, ActiveSheet etc.) to make reference to your newly created workbook and worksheet.
Once you have referenced the objects properly, you can now use Cells property to select all ranges and copy. Then use Range PasteSpecial Method to convert formulas to values.
Lastly you'll need to save the workbook using the Workbook Object SaveAs Method.
Hope this somehow leads you to a solution. HTH.