Excel doesn't release a shape's creation name - excel

I’m posting this in the hope that it might help someone else, as none of my searches revealed any information regarding this.
I ran into this while building a procedure that would copy an imbedded form shape, and paste it on the same sheet, then run a renaming scheme that would facilitate referencing either of these shapes
This should be simple enough, but I was running into an intermittent problem. Eventually I came to realize that Excel appears to “remember” the shape’s original name at the time of its creation, and keeps it flagged as being in use, releasing it only when the shape is deleted. So if you rename the shape, you can never return it to the original name. E.g., if you rename “Button 1” to “Btn1”, you can never change it back to “Button 1”. Interestingly, you can now reference the shape by either name, “Button 1” or “Btn1”.
In the macro below, assuming “Button 1” is the creation name, s.Name will end up as “Btn1”, even though it looks like it would return to “Button 1”.
Sub RenameShape()
Dim s As Shape
Dim nm As String
Set s = ActiveSheet.Shapes("Button 1")
nm = s.Name
s.Name = "Btn1"
s.Name = nm
End Sub
I have since come across a couple of links that talk about the shape’s “internal” and “external” names – I’m assuming the “internal” name is the inaccessible one that Excel won’t forget, while the “external” name is the exposed name that one normally sees.
I’d be interested to hear from anyone who can shed more insight into this.

As the main purpose of this post was to pass along information, I'm going to make this an answer so it can be closed.

Related

Excel Template has reference invalid links that I can't break

I am in the process of creating a new version of the Template. Excel 2019 Windows 10 64 bit. I have already gone through the exercise of creating a new template and copying the worksheets one at a time. There were a number of references that I found and deleted. Many of them were in the Names dictionary. I am now down to 2 that should not have been present in the first place because they are only to be used in the workbooks that are created from the templates.
I have tried and exhausted all of the samples in questions that I have found. It is distilled into the following code:
`Public Sub FindLinks()
Dim i As Integer
Dim olinks As Object
Dim v() As Variant
Dim strLink As String
v = ActiveWorkbook.LinkSources(xlExcelLinks)
For i = 1 To UBound(v)
strLink = v(i)
Debug.Print i, "Link = "; strLink
' Now break the link
ActiveWorkbook.BreakLink Name:=strLink, Type:=xlLinkTypeExcelLinks
Next i
End Sub`
The above example finds two links and displays them but will not break the links - just does nothing.
Anyone have a notion of what I could try next?
The standard "Break Links" route does not capture links that are referenced through:
Named ranges
Conditional formatting
Data validation
Graph sources
Pivot Table sources
If you have any of these components or functionalities, look through their corresponding interfaces (e.g. the Name Manager for named ranges, etc.) and check for linked content.
SIE_Vict0ria - Thank you. I had actually fixed all the references in the Name Manager, but I discovered the two references that were "invalid" were in combo-boxes. I deleted them from the combo boxes and voila, no more external references at all. So the problem is fixed.
One thing I do not know, however, is why those references were bogus. The spreadsheets being references were just where they were supposed to be and were shared and marked full control to everyone.
I did not find any documentation on why a reference would be marked as "invalid".
I hope this helps others when they are chasing this kind of problem.

Sheet name does not exist when obviously it does

I have been developing a VBA, UserForm1 program for the past few weeks and I have performed numerous test and never once had this problem.
The code, shown below, is part of the Initialization routine. I made some enhancements to the program, far deeper in the code than the code under discussion. Now, I can't get past this point in the program. I replaced "Activate" with "Select", but this did not affect the outcome, i.e., an aborted run.
Please, can someone suggest what I am doing wrong? Or, how can a program that been tested dozens of times, suddenly develop a fault out of thin air?
'======================================================================
Dim WPA() As Variant 'Workbook path for Category Class
Dim WBA() As Variant 'Workbook name for Category Class
Dim WSA() As Variant 'Worksheet name for Category Class
'======================================================================
Dim WBK() As Workbook
..........
Set WBK(S) = Workbooks.Open(WPA(S))
Workbooks(WBA(S)).Worksheets(WSA(S)).Activate 'Activate Worksheet
NWS(S) = CheckSheetExists(WSA(S)) 'Check for Worksheet
..........
Function CheckSheetExists(SheetName) As Boolean
CheckSheetExists = Evaluate("ISREF('" & SheetName & "'!A1)")
If CheckSheetExists = False Then
MsgBox "Worksheet " & SheetName & " does not exist. Run aborted."
End '<==================Run aborts
End If
End Function
It looks like you are using global variables?
If so, you should be aware that they are not as permanent as you might expect.
There are a number of things which cause global variables to reset and become undefined.
See this answer for more info: https://stackoverflow.com/a/7043901/1473412
Using "End"
An unhandled runtime error
Editing code
Closing the workbook containing the VB project
Is it possible that the "enhancements to the program, far deeper in the code than the code under discussion", causes one of these things to happen, and so resets the global variables?
If you have to use global variables, you could store them safely in a worksheet. Or, everytime you try and use one, you could check that it is defined, and if not, redefine it?
That is a good question, Storaxs' answer should have fixed this though to my knowledge.
However when something like this happens I try to create a whole new workbook and paste all of this code into it (just for the sheet in question) and then copy all the cells data into the new sheets.
This has saved me once before and it may help you in this case as well.
I also recommend not deleting your old workbook in case you don't port everything over.
If this still doesn't work let us know and we will continue to look into this.

vba Userform macro edits wrong sheet

I have a userform that is supposed to insert a row on Sheet3 and populate some cells in that row with some values. it works great as long as I have sheet3 displayed. (The form is shown modeless to give me access to the sheets).
Anyway, I happened to have another sheet active and ran it again and was surprised to see it inserted the row not in sheet3, but in the one I had displayed... (Thank God I saved first!)
In the code, I specified a range object as follows to find the insertion point: (I'll truncate the code a bit to keep it simple)
Dim RecordRange As Range
Set RecordRange = Sheet3.Cells(RowVariable,ColumnVariable)
RecordRange.Offset(1,0).EntireRow.Insert
blah blah blah.
A workaround is to activate the sheet first:
Sheet3.Activate
That at least inserts into the correct sheet, but I'd rather not have sheet3 be displayed when I add the record, so I even surrounded that line with:
Application.ScreenUpdating = False
Sheet3.Activate
Application.ScreenUpdating = True
unfortunately, ScreenUpdating doesn't work from within a Userform Code module, so that bites...
I still don't understand why it chooses to insert the row into whatever sheet is active, when I've already specified sheet3 in the code. I have another Macro very similar that doesn't have this problem.
any ideas?
...so you figure your workaround needs a workaround? Hmm... I think that qualifies as a double-negative since a workaround is supposed to, by definition, fix problems rather than cause them...
A workaround is a bypass of a recognized problem in a system. A
workaround is typically a temporary fix that implies that a genuine
solution to the problem is needed. But workarounds are frequently as
creative as true solutions, involving outside the box thinking in
their creation.
Typically they are considered brittle in that they will not respond
well to further pressure from a system beyond the original design. In
implementing a workaround it is important to flag the change so as to
later implement a proper solution.
Placing pressure on a workaround may result in later system failures.
For example, in computer programming workarounds are often used to
address a problem or anti-pattern in a library, such as an incorrect
return value. When the library is changed, the workaround may break
the overall program functionality, effectively becoming an
anti-pattern, since it may expect the older, wrong behaviour from the
library. (Wikipedia)
Just sayin'... :-)
So instead of fixing the workaround, your original issue is (thankfully) straightforward.
You're using Sheet3 as an object, and I suspect you haven't assigned anything (like Worksheets("Sheet3") to an object called Sheet3.
Try this instead:
Dim RecordRange As Range
Set RecordRange = Worksheets("Sheet3").Cells(RowVariable,ColumnVariable)
RecordRange.Offset(1,0).EntireRow.Insert
If you indeed intended to use Sheet3 as an object then make sure it's declared as set, so for example you could instead use:
Dim RecordRange As Range
Dim Sheet3 As Worksheet
Set Sheet3 = Worksheets("Sheet3")
Set RecordRange = Sheet3.Cells(RowVariable,ColumnVariable)
RecordRange.Offset(1, 0).EntireRow.Insert
Also, just to point out: If either of these solves your issue then the problem would've "made itself known", by including one line at the top of every module (at least during development & troubleshooting):
Option Explicit
This link has a short explanation, but basically it forces you to properly declare all variables (thus helping to prevent future workarounds!)

Referencing Active Table in VBA

I'm creating a macro to manipulate a table in excel. I've been able to create code to do what I need, the problem is, my table names might not always be the same.
As an example:
Range("DATA_INPUT4[MFG Catalog]").Copy
This code copies the MFG Catalog column in my table just fine, but the table isn't always going to be named "DATA_INPUT4".
I've played around with a few things to try to get it to work with the active table and I feel like I'm close, but I can't get any progress.
I've tryed:
Sub Copy_Active_Table()
Dim activeTable As String
activeTable = ActiveSheet.ListObjects(1).Name
MsgBox activeTable 'To make sure it's pulling the correct table name
Range("activeTable[MFG Catalog]").Copy
End Sub
This is probably completely wrong, but you can see where I'm going with it.
I have a feeling that I have to Dim activeTable As ListObject but I haven't been able to figure that out either.
This seemingly simple problem is driving me nuts, any help would be awesome.
Thanks,
Brian
For those who look for a solution to reference active table, the solution is:
ActiveCell.ListObject.Name
Other solutions fix problem in the question (using variable to refer to the table) - but the script in the question does NOT refer to the active table - but rather the first table in the sheet (which might be the same as active table).
Answered in the comments,
Yes indeed, you are very close. Try this: Range(activeTable & "[MFG Catalog]").Copy
Ralph
Thanks, Ralph.
Just had a similar problem and ended up here.
Along the lines of #choukkos's answer, you can also use the ListObject's properties (which is even a bit faster as it doesn't need to do the name resolution twice)
ActiveCell.ListObject.ListColumns("MFG Catalog").DataBodyRange.Copy
in the same manner other table data can also be extracted...
Set t = ActiveCell.ListObject
'copy line 3 of the table
t.ListRows(3).Range.Copy
'select current line
t.ListRows(Selection.Row - t.Range.Row).Range.Select

Excel VBA getting and using Name of Table

I got stuck at a problem with Excel VBA.
I am supposed to do the kinda easy task of copy/paste a variable range of cells from "sheet2" into the same range in "sheet1".
500 Rows like in my code is far too much, but I tried it this way, to "catch" the variable aspect.
The tricky part is, that the range in "sheet1" is a table(which gets created from TFS).
Sub CopyP()
Sheets("Sheet1").Range("B3:F500").Value = Sheets("Sheet2").Range("B3:F500").Value
SheetObject.ListObjects (ListObjectName)
Range("NAME OF TABLE[Iteration Path]").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub
The [Iteration Path] is a column name of my table, i want to check in this column/with this parameter, if the "row" is empty.
I know the code is far from being good or clean but the table is giving me a hard time copying.
With this code I got another problem: the table gets created from TFS, no problem to copy into that, BUT the name of the table is variable(seems like TFS creates the name), so unless I put the name manually in the code, the "program" cant execute, because of missing range.
Didn't find a way to get a return of the table name somehow.
But I think I am just following the wrong path overall, maybe someone can be bring me on the right track.
My other Idea is to Iterate through the Rows in Sheet 2 to fetch just as much data is needed and then copy them with an iteration into the table. But i guess I would be the same problem with the table-name there.
Every information I find using google , talks about tables where the user can "name" the table. In my case I cant, so I have to work with the name TFS uses for my table.
Further to my comments below your question, I just typed this in notepad. Please amend it to suit your need.
This will give you the names of all tables in the activesheet. If there are multiple tables then you will get multiple names. (UNTESTED AS POSTING FROM PHONE)
Sub sample()
Dim objLB As ListObject, TableName As String
For Each objLB In ActiveSheet.ListObjects
TableName = objLB.Name
Exit For
Next
Range(TableName & "[Iteration Path]").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub

Resources