I have a code that copies all sheets from book 1 to book 2. It copies the sheets several times, so I change the names by adding 001_, 002_ and etc in front of the copied sheets names. All of the sheets have dropdown menues. The problem is that they are referenced (Formulas--> Name Manager) to the previous workbook and they are not working.
There are 5 sheets to be copied and 4 of them are taking the values for the dropdown menues from the sheet TypeLists. This sheet is copied only once, so the code doesn't copy it, if it is already present in Book 2.
Using Record Macro, in changing one of the references, I got this:
ActiveWorkbook.Worksheets("003_TDT").Names("List_DataType").RefersToR1C1 = _
"=TypeLists!R3C14:R5C14"
What I did is, I went to Formulas --> Name Manager and changed one of the references from:
='C:\Users\z183464\Desktop[seq_tdt_template.xlsx]TypeLists'!$N$3:$N$5
to:
=TypeLists!$N$3:$N$5
My question is: How can I write a Macro that changes all the references from Book1/TypeLists to Book2/TypeLists ?
Cheers!
You can use this code. It iterates through all the defined names and changes its reference to the same value with the undesired part extracted (replaced by "").
This is not a macro, but VBA. You need to insert it in the VBA editor (Alt+F11).
Sub replaceNameValues()
Dim oName As Excel.Name
For Each oName In ThisWorkbook.Names
oName.RefersTo = Replace(oName.RefersTo, "C:\Users\z183464\Desktop[seq_tdt_template.xlsx]", "")
Next
End Sub
Regards,
Related
I have inherited an Excel workbook with several worksheets, all with named tabs. I have some VBA code that runs depending on buttons and inputs. When I compare the VBAProject and the list of Excel Objects, the sheet's names match the tabs. All good so far.
However, within the VBA code and on the spreadsheets itself, it refers to other worksheets. They are still part of the workbook, and I think that the code was created, and then tabs were renamed. But I don't know how Excel keeps the connection, or, more importantly, how I am supposed to figure out the connections.
So, for instance, I have a VLOOKUP that refers to MiscDataRange
=IF((VLOOKUP(E4,MiscDataRange,4,0))="Y"...
I don't know what MiscDataRange is, but within the VBA code I find one reference. Right after specifying worksheet "Misc Interrupt", which is NOT any of the named tabs.
Worksheets("Misc Interrupt").Range("H2:H47") = "N" 'Reset to N at noon.
UpdateData
Range("MiscDataRange").ClearContents
I do have a sheet called MiscInt, and it appears to be the sheet that "Misc Interrupt" is using and MiscDataRange is referencing.
My problem is there is a hole in my knowledge - I can guess that MiscInt and Misc Interrupt are the same worksheet, that the VLookup is referring to data on the MiscInt sheet. But I am reduced to guessing. I cannot find anything in the file that maps those two as the same. Where would I look to find that?
This question seems related, except he simply has a VLookup, and isn't looking at the VBA code: Non-existent Excel Worksheet, but Formulas and Defined names still work?. In addition, from the VBA code, I can see hidden and visible worksheets.
You can open the Names manager by going to the Formula Tab and clicking Names Manager or pressing ctrl+F3 or you can paste a list of Names and what the names reference by pressing F3. It may be necessary to unhide the names first.
Sub ShowAllNames()
Dim n As Name
For Each n In ThisWorkbook.Names
n.Visible = True
Next
End Sub
If I understand your question, you're looking to find where those named ranges are.
You can use a sub like this:
Sub t()
Debug.Print "Sheet: " & Range("testNamedRange").Parent.Name
Debug.Print "Full Location: " & Range("testnamedrange").Name
Debug.Print "File path: " & Range("testnamedrange").Worksheet.Parent.Path
End Sub
Does that help?
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.
The following code works fine when I run it from the vba editor. When I assign this macro to a button, however, it does not copy the columns as written. The other parts of the code work?
Is there something about assigning the macro that changes how the code is interpreted?
Sub copy_ids_user_output()
' copy the first column to the last column
Dim last_col As Integer
last_col = Worksheets("usersFullOutput.csv").Cells(1, Columns.Count).End(xlToLeft).column
Debug.Print last_col
Columns(1).Copy Columns(last_col + 1)
Worksheets("WorkStation").Range("B9").Value = Now()
MsgBox "id's copied to last col in email logs sheet"
End Sub¨
If I have understood well, you have:
a clickable button placed in Worksheets("WorkStation");
a column in Worksheets("usersFullOutput.csv") that you want to be copied at the end of the same sheet
If this is the case, most probably you have this behavior because you don't reference the worksheet in the line of code that executes the copy:
Columns(1).Copy Columns(last_col + 1)
Which means:
When you run from VBA editor, you're watching the sheet usersFullOutput.csv so the above line of code executes on this sheet;
When you run from the button, you're watching the sheet WorkStation and since you don't reference any sheet in the above line, it assumes to execute on this other sheet.
If this is the problem, just add the worksheet reference:
Worksheets("usersFullOutput.csv").Columns(1).Copy Worksheets("usersFullOutput.csv").Columns(last_col + 1)
If this is not the problem, please clarify on which worksheets you work on and I will delete/adapt my answer accordingly.
P.s. for information, anyway, the answer to your title question "Does initiating a macro from a button in a sheet change how vba interprates the code?" is no, it doesn't; but adding no references to the variables change the way VBA interprets them because it chooses the default ones, which are not always the same you want.
I have an excel template which is filled by added sheets that I receive from colleagues.
Each sheet that I receive contains about 12 named ranges which do all have the same names. Each name begins with "flags".
I found another question on stackoverflow that gives a solution to delete name ranges with names that are not equal to given names:
loop through names and delete those not matching specified pattern
I used this solution to create my own code.
The names I want to delete (because they make my file awfully slow) all start with "flags".
I therefore used the
left(myname.namelocal, 5)
function to find each name in my workbook which starts with "flags" and have it deleted.
However, this code does not work. The names are not deleted when I execute the code.
And I do not understand why it does not work. I have tried a similar code on a small file to test the code. It worked fine.
The only difference is that the test file was not password protected. That is what I added to the code to make sure the code can delete the names.
Sub deletenames()
'verwijderd alle naam-bereiken waarvan de naam begint met flags uit het verwerkingsbestand.
Dim ws As Worksheet
Dim myName As Name
For Each ws In ThisWorkbook.Worksheets
ws.Unprotect ("TM")
Next ws
For Each myName In ThisWorkbook.Names
If Left(myName.NameLocal, 5) = "flags" Then myName.Delete
Next
End Sub
what can I do to make this code work?
The problem is most likely that Excel allows both sheet-specific and workbook-wide named ranges. Since you've mentioned that all sheets are copied together, I suspect that named ranges are associated with sheets.
Edit:
The sheet-specific named ranges have a name Sheet!Range, and thus your check must consider the sheet prefix. A solution as in your comment to compare the name with Like is ok:
If myName.NameLocal Like "*!flags*" Then myName.Delete
This seems like such a simple question, but I can't seem to find a good way to do it. I want to check if the name of an Excel Worksheet with an index of 'n' is not in the original set of worksheet names of my VSTO workbook.
The workbook has 13 worksheets in the template and the program adds more sheets to the end and sometimes the middle. Any sheet added wouldn't be named one of the sheet names included in the template (I've successfully blocked this). I often want to take actions to all the sheets added that are not of the orginal 13, so I had hoped to try and use an array, or the list ThisWorkbook.Names as it exists from the initial template.
Right now my work around is:
If ThisWorkbook.Worksheets(n).Name <> Sheet1.Name OrElse ThisWorkbook.Worksheets(n).Name <> wbX.Sheet2.Name ..... <>wbX.Sheet13.Name
Needless to say this is cumbersome. Am I even thinking about this the right way, or is there an easier way to check if a name is not in the original sheet names?
I know that if I could force all the sheets after 13 I could just use the index, but at the moment that's not feasible for the intention of the project.
At startup fill all worksheetnames from the template into a List:
Dim templateSheets As List(Of String) = new List(Of String)
For Each sheet As Excel.Worksheet in Globals.ThisWorkbook.Worksheets
templateSheets.Add(sheet.Name)
Next
Then your above query can get abbreviated to
If Not templateSheets.Contains(ThisWorkbook.Worksheets(n).Name) Then