VBA Handeling of Excel Cell containing both Text and Formula-Value - vba

I just started working with VBA for Excel and I ran into a problem I can't find the solution to. I want to make a macro that makes a copy of a sheet and renames the copy to what is specified in cell B8. Now, Cell B8 contains a string and a value (based on a formula) illustrated below.
Content of Cell B8
How do I get VBA to use the name (string and number) as the name of the new sheet?
Sub NewFunction()
Dim counter As Integer
Sheets(1).Copy After:=Sheets(1)
ActiveSheet.name = Sheets(1).Range("B8").CStr
End Sub
Thanks in advance!

For one, you can't use the "/" in the sheet name. It might error, but Excel will just ignore it.
Secondly, you are changing the name on the wrong sheet. You added a new sheet and then referred to the old sheet.
Thirdly, no need to use .CStr as the value of the cell is what you want, and since that is the default property, no need to use .Value either.

you were almost there
Sheets(1).Copy After:=Sheets(1)
ActiveSheet.name = Replace(Replace(Replace(Replace(Range("B8"), "\", "-"), "/", "-"), "?", "-"), "*", "-")
where
after Copy() method of Worksheet object, the new worksheet becomes the active one
the VBA Replace() method chain is to assure you're not using forbidden characters for your new worksheet name
there remains the issue of possible duplicate names, which can be handled via a specific Function you can find around here if you search for

Related

Excel VBA. How do you get a specific name associated with a range?

I have a cell that has more than one named ranges associated with it. How do I get it to return a specific name without having to loop through all the names in the workbook?
Sub Test()
ActiveWorkbook.Names.Add Name:="AUserDefinedName1", RefersTo:="='Sheet1'!$A$1", Visible:=True
ActiveWorkbook.Names.Add Name:="AUserDefinedName2", RefersTo:="='Sheet1'!$A$1", Visible:=True
ActiveWorkbook.Names.Add Name:="MyName", RefersTo:="='Sheet1'!$A$1", Visible:=True
Dim n As Name
Set n = Range("A1").Name
Debug.Print n.Name
End Sub
If you run the above, for cell A1 it would only return the first name. However, how would I get it to return the other names associated with cell A1 as well or a specifically return 'MyName'?
I could loop through all names in the workbook and see if the 'RefersTo' property of the Name object matches the address for cell A1, but I would like a more direct solution if possible that's faster.
This thread gave a partial answer, but need what if there are more than one name?
How do you get a Range to return its Name?
Use the Workbook.Names collection and test the address:
For Each n In ActiveWorkbook.Names
If n.RefersToRange.Address = "$A$1" Then
Debug.Print n.Name
End If
Next
There's a whole MSDN article about named ranges too for further reading.
There isn't a Names collection for the range object so the only way to accomplish this is at workbook level. Unless you have thousands of named ranges in your workbook there will be no noticeable speed difference in using this method, just create a UDF to get the names that you need.
WB as Workbook
RG as Range
WB.Names(RefersTo:= "=" & RG.Worksheet.Name & "!" & RG.Address(True, True)).Name
Realize this is an antiquated post, but for anyone else looking like I was today, the above worked for me.

Multi language Excel VBA Application

I basically created an Excel VBA application that manipulate Excel worksheets, so in the code, I use the string "Sheet1" to refer to the first sheet of a workbook, but when I try to use this application with the same code with a french version of Excel, it doesn't work until I translate "Sheet1" to "Feuil1". So my question is, is there a way to automatically adapt the code to any version of Excel ?
You can use the following ways to get a sheet from code:
(1) using by Sheets(sheet_index)
This way cannot be adapt because it take the sheet by sheet index (sheet index are start from 1). When sheet are change place, it cannot access the right sheet.So, it should not use.
For example: Set Feuil1Sheet = Sheets(1)
(2) using by (Name) of VBA editor
I think this way should not use never, because it takes the sheet by code name which can only visible by VBA editor(it shows as (Name) field in sheet properties). I think you are using this way for getting the first sheet. So, you not get the right sheet. One thing you need to know is that code name of every first sheet may not be Sheet1 always. It can be Sheet2 or Sheet4, etc.
For example: Set Feuil1Sheet = Sheet1
(3) using Worksheets("sheet-name") or Sheets("sheet-name")
This last way is a very compatible way and can be adapt in anywhere Excel because it take the sheet by its name. So, If names are equal, you will get the right sheet. So, use this for getting the sheet.
For example: Set Feuil1Sheet = Worksheets("Feuil1") or Set Feuil1Sheet = Sheets("Feuil1")
The only possible way I can think of to always reference "sheet1" in the local language is the following code.
Option Explicit
Public Sub GetLocalNameForNewSheets()
Dim strSheetName As String
Dim i As Long
i = ActiveWorkbook.Sheets.Count
ActiveWorkbook.Sheets.Add After:=Worksheets(i)
strSheetName = ActiveWorkbook.Worksheets(i + 1).Name
Application.DisplayAlerts = False
ActiveWorkbook.Worksheets(i + 1).Delete
Application.DisplayAlerts = True
Debug.Print strSheetName
For i = 1 To Len(strSheetName)
While IsNumeric(Mid(strSheetName, i, 1))
strSheetName = Replace(strSheetName, Mid(strSheetName, i, 1), "")
Wend
Next i
Debug.Print strSheetName
Debug.Print strSheetName & "1"
End Sub
Basically, I am asking Excel to create a new sheet and name it for me. Then, I am getting the new name which is "sheet" in the local language and remove from the string the number part. At the end, you can add the number "1" to reference the first sheet.

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.

Split a cell's formulaic elements into seperate cells

So I have a cell with the formula =A+B, A and B are external values for which the external spreadsheet is no longer open. I was wondering if excel remembers the formula elements and if it was possible to get those element values into other cells. i.e.
Row Formula Value
1 =A+B 45
2 =ELEMENT(A1, 1) 10
3 =ELEMENT(A1, 2) 35
I can't imagine it being that simple though? I could seperate out the formula in vba using the + as a pivot, but this is not ideal as it would require the external spreadsheet to be reopened. If the external spreadsheet has to be reopened then I needn't bother trying to seperate the formula in the first place. I hope this makes sense and has an answer.
Your formula is already accessing those values in order to sum them in the open workbook. You do NOT need to re-open the workbook in order to evaluate the reference values, nor to parse the formula in the active workbook.
Assuming your formula references a closed workbook, with a simple sum function like:
='C:\Users\david_zemens\Desktop\[test.xlsx]Sheet1'!$A$1 + ='C:\Users\david_zemens\Desktop\[test.xlsx]Sheet1'!$B$1
You can parse the formula either in VBA or using string functions on the worksheet. As you note, for this example, parsing by the + operator will suffice. Since I think you understand how to do this, my example does not demonstrate how to parse the formula.
As long as you know or can obtain the references from the formula, you should be able to access those cells' values via formula, or programmatically in VBA using ExecuteExcel4Macro.
Sub GetValsFromClosedWorkbook()
Dim fileName As String
Dim filePath As String
Dim sheetName As String
Dim cellref As String
Dim myFormula As String
'This example might be one of the two arguments in your "A+B" formula:
' 'C:\Users\david_zemens\Desktop\[test.xlsx]Sheet1'!A1
'## Assume you can properly parse the formula to arrive at these:
fileName = "test.xlsx"
filePath = "C:\Users\david_zemens\Desktop\"
sheetName = "Sheet1"
cellref = "A1"
'Concatenate in to R1C1 notation
myFormula = "='" & filePath & "[" & fileName & "]" & sheetName & "'!" & _
Range(cellref).Address(, , xlR1C1)
'## First, demonstrate that we can evaluate external references:
With Range("B1")
.Value = myFormula
MsgBox .Value
.Clear
End With
'## Evaluate the formula using ExecuteExcel4Macro:
MsgBox ExecuteExcel4Macro(Replace(myFormula, "=", vbNullString))
End Sub
Additional info
http://spreadsheetpage.com/index.php/tip/a_vba_function_to_get_a_value_from_a_closed_file/
Update
Based on OP's question of how this works (comments, below), I am not certain of how it works behind the scenes but here is my guess/explanation:
Firstly, keep in mind that a cell may have various properties like .Text, .Value, .Value2, .Formula etc. which in one way or another represent its contents.
The values aren't in the active file until the formula is evaluated, at which point Excel queries the external file and returns the current Value at that reference. Now the active file contains that Value as well as a Formula reference the external file.
As you continue working the active file preserves the Value and the reference, but may only update the value when prompted. For example, when you re-open the linked workbook, you will be prompted whether to "update external links".
if you say no, it will use the previously stored values (still preserves the Formula, it just doesn't evaluate it.
if you say yes, it will re-evaluate the formula (in case the value in the external file has changed) and return the new .Value
So, that's what I suspect is happening. If you're asking "How does Excel access the data inside an un-opened workbook" I don't really know how I just know that it does.

Determine if WorkSheet.Name is NOT in Workbook or String is not in Array VB.NET

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