convert numeric to alphanumeric excel cell reference - vb.net

How can I convert from numeric to alphanumeric cell references? For example, I have the numeric row,col(0,1) and I want to convert to a standard MS Excel alphanumeric col,row(B,1)? I'm sorry, but I don't know the proper terminology to describe different cell references.
I want to write VB.NET code with numeric cell references so my code can iterate but convert to alphanumeric so I can insert formulas into my spreadsheet.

To convert from a numerical column designator to a alphabetic designator, consider:
Sub qwerty()
n = 134
s = Cells(1, n).Address(0, 0)
MsgBox Left(s, Len(s) - 1)
End Sub
EDIT#1:
For a function to perform the conversion:
Public Function ColumnId(N As Long) As String
s = Cells(1, N).Address(0, 0)
ColumnId = Left(s, Len(s) - 1)
End Function

If you want to get the full address. Then you can just use the .Address property of a range.
If you want to separate the row and column then you can split the address into the individual parts using Split on the $.
Sub RangeAddressTest()
Dim cell As Range
Dim fullAddress As String
Dim rowAddress As String, columnAddress As String
Dim detailsArray As Variant
'select your cell
Set cell = ActiveSheet.Cells(30, 25)
fullAddress = cell.Address
detailsArray = Split(fullAddress, "$")
columnAddress = detailsArray(1)
rowAddress = detailsArray(2)
MsgBox "Full Address: " & fullAddress _
& vbCrLf & vbCrLf & _
"Column Address: " & columnAddress _
& vbCrLf & vbCrLf & _
"Row Address: " & rowAddress
End Sub

Thanks for your answers to my question, both seem like they should work but while looking around I found a very simple answer from the Aspose forum that gets the job done with two lines of code. Thanks for your ideas - I learn more by seeing different ways of getting to the same solution.
Aspose Forum:
As per my understanding, you wish to get the cells reference in the syntax of "A1" (Cell Name). You may consider using the following code snippet that returns the alphanumeric cell reference for cell[0,0].
VB
Dim r As Integer = 0, c As Integer = 0
Dim Cell As String = CellsHelper.ColumnIndexToName(c) + (r + 1)

Related

Works with long type, but not with any other variable type

This is the code, that is bug-free:
Sub Minus()
Dim cell As Long
cell = ActiveCell.Value
Dim offsetcell As Long
offsetcell = ActiveCell.Offset(0, -1).Value
ActiveCell.Formula = "=" & cell & "-" & offsetcell
End Sub
As soon as I change the variable to any other type (preferably Double) the code stops working and bug appears in the concatenated function below.
Any ideas why?
i would like full original value minus adjacent cell (one left).
You are probably casting a decimal comma to text which will break the formula. So, convert using Str that will return a dot as the decimal separator:
ActiveCell.Formula = "=" & Str(cell) & "-" & Str(offsetcell)
That works here.
PS: Don't use native object names (cell) as the name for variables holding completely different values types.

Calculate standard deviation of same text values in same column

I am trying to write a macro in Excel to calculate the standard deviation of same text in column A taking the values from column B and giving the results in column C:
I did it manually by putting the equation=STDEV.S(A2;A3;A4;A16)for "aaa". But I need to do this automatically because I am doing another calculation and procedures which are completing by macros. Here is my code:
Option Explicit
Sub Main()
CollectArray "A", "D"
DoSum "D", "E", "A", "B"
End Sub
' collect array from a specific column and print it to a new one without duplicates
' params:
' fromColumn - this is the column you need to remove duplicates from
' toColumn - this will reprint the array without the duplicates
Sub CollectArray(fromColumn As String, toColumn As String)
ReDim arr(0) As String
Dim i As Long
For i = 1 To Range(fromColumn & Rows.Count).End(xlUp).Row
arr(UBound(arr)) = Range(fromColumn & i)
ReDim Preserve arr(UBound(arr) + 1)
Next i
ReDim Preserve arr(UBound(arr) - 1)
RemoveDuplicate arr
Range(toColumn & "1:" & toColumn & Range(toColumn & Rows.Count).End(xlUp).Row).ClearContents
For i = LBound(arr) To UBound(arr)
Range(toColumn & i + 1) = arr(i)
Next i
End Sub
' sums up values from one column against the other column
' params:
' fromColumn - this is the column with string to match against
' toColumn - this is where the SUM will be printed to
' originalColumn - this is the original column including duplicate
' valueColumn - this is the column with the values to sum
Private Sub DoSum(fromColumn As String, toColumn As String, originalColumn As String, valueColumn As String)
Range(toColumn & "1:" & toColumn & Range(toColumn & Rows.Count).End(xlUp).Row).ClearContents
Dim i As Long
For i = 1 To Range(fromColumn & Rows.Count).End(xlUp).Row
Range(toColumn & i) = WorksheetFunction.SumIf(Range(originalColumn & ":" & originalColumn), Range(fromColumn & i), Range(valueColumn & ":" & valueColumn))
Next i
End Sub
Private Sub RemoveDuplicate(ByRef StringArray() As String)
Dim lowBound$, UpBound&, A&, B&, cur&, tempArray() As String
If (Not StringArray) = True Then Exit Sub
lowBound = LBound(StringArray): UpBound = UBound(StringArray)
ReDim tempArray(lowBound To UpBound)
cur = lowBound: tempArray(cur) = StringArray(lowBound)
For A = lowBound + 1 To UpBound
For B = lowBound To cur
If LenB(tempArray(B)) = LenB(StringArray(A)) Then
If InStrB(1, StringArray(A), tempArray(B), vbBinaryCompare) = 1 Then Exit For
End If
Next B
If B > cur Then cur = B
tempArray(cur) = StringArray(A)
Next A
ReDim Preserve tempArray(lowBound To cur): StringArray = tempArray
End Sub
It would be nice if someone could please give me an idea or solution. The above code is for calculating the summation of same text values. Is there any way to modify my code to calculate the standard deviation?
I went in a different direction and provided a pseudo-STDEV.S.IF to be used much like the COUNTIF or AVERAGEIF function.
Function STDEV_S_IF(rAs As Range, rA As Range, rBs As Range)
Dim a As Long, sFRM As String
sFRM = "STDEV.s("
Set rBs = rBs(1).Resize(rAs.Rows.Count, 1)
For a = 1 To rAs.Rows.Count
If rAs(a).Value2 = rA.Value2 Then
sFRM = sFRM & rBs(a).Value2 & Chr(44)
End If
Next a
sFRM = Left(sFRM, Len(sFRM) - 1) & Chr(41)
STDEV_S_IF = Application.Evaluate(sFRM)
End Function
Syntax: STDEV_S_IF(<criteria range>, <criteria>, <stdev.s values>)
In your sample, the formula in C2 would be,
=STDEV_S_IF(A$2:A$20, A2, B$2:B$20)
Fill down as necessary.
    
Here is a formula and VBA route that gives you the STDEV.S for each set of items.
Picture shows the various ranges and results. My input is the same as yours, but I accidentally sorted it at one point so they don't line up.
Some notes
ARRAY is the actual answer you want. NON-ARRAY showing for later.
I included the PivotTable to test the accuracy of the method.
VBA is the same answer as ARRAY calculated as a UDF which could be used elsewhere in your VBA.
Formula in cell D3 is an array formula entered with CTRL+SHIFT+ENTER. That same formula is in E3 without the array entry. Both have been copied down to the end of the data.
=STDEV.S(IF(B3=$B$3:$B$21,$C$3:$C$21))
Since it seems you need a VBA version of this, you can use the same formula in VBA and just wrap it in Application.Evaluate. This is pretty much how #Jeeped gets an answer, converting the range to values which meet the criteria.
VBA Code uses Evaluate to process a formula string built from the ranges given as input.
Public Function STDEV_S_IF(rng_criteria As Range, rng_criterion As Range, rng_values As Range) As Variant
Dim str_frm As String
'formula to reproduce
'=STDEV.S(IF(B3=$B$3:$B$21,$C$3:$C$21))
str_frm = "STDEV.S(IF(" & _
rng_criterion.Address & "=" & _
rng_criteria.Address & "," & _
rng_values.Address & "))"
'if you have more than one sheet, be sure it evalutes in the right context
'or add the sheet name to the references above
'single sheet works fine with just Application.Evaluate
'STDEV_S_IF = Application.Evaluate(str_frm)
STDEV_S_IF = Sheets("Sheet2").Evaluate(str_frm)
End Function
The formula in F3 is the VBA UDF of the same formula as above, it is entered as a normal formula (although entering as an array does not affect anything) and is copied down to the end.
=STDEV_S_IF($B$3:$B$21,B3,$C$3:$C$21)
It is worth noting that .Evaluate processes this correctly as an array formula. You can compare this against the NON-ARRAY column included in the output. I am not certain how Excel knows to treat it this way. There was previously a fairly extended conversion about how Evaluate process array formulas and determines the output. This is tangentially related to that conversation.
And for completeness, here is the test of the Sub side of things. I am running this code in a module with a sheet other than Sheet2 active. This emphasizes the ability of using Sheets("Sheets2").Evaluate for a multi-sheet workbook since my Range call is technically misqualified. Console output is included.
Sub test()
Debug.Print STDEV_S_IF(Range("B3:B21"), Range("B3"), Range("C3:C21"))
'correctly returns 206.301357242263
End Sub

VBA for Excel - building .Formula with contents containing quotation marks

I'm coding a project in VBA for Excel, which loops to a file, matches the 'code' for each of the quantities, and then feeds all the matches for that code to a user defined function, which goes onto the Excel sheet.
I can read the info, sort it so postdata(nr_of_datafield, nr_of_item) returns me the row in the source sheet on which the value is listed. Based on this, I need to create (through .Formula) a syntax like this:
=formul(raming!J104) (if there's only one occurence)
=formul(raming!J104;"+";raming!J108) (etc., always adding the same extra if there's multiple occurences)
=formul(raming!J104;"+";raming!J108;"+";raming!312;"+";raming!J403) etcetera, with always needing to get the previous values from what's already in Cells.Formula.
Based on this check:
Code:
Right(Workbooks(meetstaatfile).Sheets("HOR_raming").Cells(lusteller12, 9 + CInt(postdata(3, eerstepositie)) * 3).Formula, 2) = "()"
I can detect if there is already any contents added here. If not (meaning the check for () ending is positive), I replace with this:
Code:
Workbooks(meetstaatfile).Sheets("HOR_raming").Cells(lusteller12, 9 + postdata(3, eerstepositie) * 3).Formula = "=formul('raming'!J" & postdata(2, eerstepositie) & ")"
To create a formula that looks like: =formul(raming!J104)
(the '104' in this example is the output from postdata(2,eerstepositie)
However, if it doesn't trigger for the () ending, there already is a value, and I need to extend the formula to something like this: =formul(raming!J104;"+";raming!J108)
I've been trying to figure out how to do this by replacing ')' with the block I want added, but I cannot get it to work to input the quotation marks. ('formul' is very similar to concatenating text).
How can I make a variation of the codeline above that lets me alter the cell input? Either by a Replace() like I was trying, or reading what's between the formul() brackets and rebuilding the formula?
If you need to have quotation marks as content within a string literal in VBA, you have to double them. See: http://msdn.microsoft.com/en-us/library/ms234766.aspx
.Formula = "=formul('raming'!J" & 104 & ",""+""," & "'raming'!J" & 108 & ")"
Or with your postdata:
.Formula = "=formul('raming'!J" & postdata(2, eerstepositie) & ",""+""," & "'raming'!J" & postdata(2, whatevergets108) & ")"
I don't know, whether I have understood it right, but if you need to concatenate the formula in dependence of the contents of an array, then this can be achieved like so:
Sub test()
'one occurrence
postdata = [{0;104}]
sFormulaString = getFormulaString(postdata, 2)
MsgBox sFormulaString
'two occurrences
postdata = [{0,0;104,108}]
sFormulaString = getFormulaString(postdata, 2)
MsgBox sFormulaString
'three occurrences
postdata = [{0,0,0;104,108,312}]
sFormulaString = getFormulaString(postdata, 2)
MsgBox sFormulaString
End Sub
Function getFormulaString(postdata As Variant, nr_of_datafield As Long) As String
sFormula = "=formul("
For i = LBound(postdata, 2) To UBound(postdata, 2)
sFormula = sFormula & "'raming'!J" & postdata(nr_of_datafield, i) & ",""+"","
Next
sFormula = Left(sFormula, Len(sFormula) - 5) & ")"
getFormulaString = sFormula
End Function
Hm, or is the real need, to append new formula parts into an existing formula? If so, the following code will append a new part into the Formula in A1 every time it runs.
Sub test2()
postdata = [{0;104}]
sFormula = Range("A1").Formula
If sFormula = "" Then sFormula = "=formul("
If Right(sFormula, 1) = ")" Then sFormula = Left(sFormula, Len(sFormula) - 1) & ",""+"","
sFormula = sFormula & "'raming'!J" & postdata(2, 1) & ")"
Range("A1").Formula = sFormula
End Sub
Greetings
Axel

Concatenating Variables Into String to be Set to a Range in VBA

I am having a problem with a particular line of code:
ActiveSheet.Range("A" & rowCount & ":" & Mid(alphabet, totHdrLngth, 1) & belowRowCount)
Where alphabet is a string containing uppercase letters A to Z.
I keep getting the following error:
Run-time error '5':
Invalid Procedure call or argument
I tried creating a String "inRange" and changing the code to this:
inRange = "A" & rowCount & ":" & Mid(alphabet, totHdrLngth, 1) & belowRowCount
curRange = ActiveSheet.Range(inRange)
But that did not help (as I thought it wouldn't). Any suggestions?
Although creating ranges like this is frowned upon in general, the way to do it is with the word SET (like #Gary McGill stated in the comments). Here is an example of how to do this:
Sub test()
Dim alphabet As String
Dim totHrdrLngth As Long
Dim belowRowCount As Long
Dim rowCount As Long
Dim inRange As Range
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
totHrdrLngth = 5
belowRowCount = 10
rowCount = 5
' Gives us A5:E10
Set inRange = Range("A" & rowCount & ":" & range2 & _
Mid$(alphabet, totHrdrLngth, 1) & belowRowCount)
End Sub
You are running this macro in the current range, so there should be no need to specify ActiveSheet.Range. I hope this helps get you toward what you are trying to achieve.
As far as I can tell, you're getting an error because your types don't match up. I imagine rowCount is an integer, as is belowRowCount. If you convert them to strings before concatenating them, you can fix it. str() will convert an integer to a string with a space before it, and LTrim() will remove the space. Try code as below:
Dim sRowCount As String
Dim sBelowRowCount As String
and later
sRowCount = LTrim(Str(RowCount))
sBelowRowCount = LTrim(Str(belowRowCount))
inRange = "A" & sRowCount & ":" & Mid(alphabet, totHdrLngth, 1) & sBelowRowCount
curRange = ActiveSheet.Range(inRange)
Hope this helps.

How do I get a range's address including the worksheet name, but not the workbook name, in Excel VBA?

If I have a Range object--for example, let's say it refers to cell A1 on a worksheet called Book1. So I know that calling Address() will get me a simple local reference: $A$1. I know it can also be called as Address(External:=True) to get a reference including the workbook name and worksheet name: [Book1]Sheet1!$A$1.
What I want is to get an address including the sheet name, but not the book name. I really don't want to call Address(External:=True) and try to strip out the workbook name myself with string functions. Is there any call I can make on the range to get Sheet1!$A$1?
Only way I can think of is to concatenate the worksheet name with the cell reference, as follows:
Dim cell As Range
Dim cellAddress As String
Set cell = ThisWorkbook.Worksheets(1).Cells(1, 1)
cellAddress = cell.Parent.Name & "!" & cell.Address(External:=False)
EDIT:
Modify last line to :
cellAddress = "'" & cell.Parent.Name & "'!" & cell.Address(External:=False)
if you want it to work even if there are spaces or other funny characters in the sheet name.
Split(cell.address(External:=True), "]")(1)
Ben is right. I also can't think of any way to do this. I'd suggest either the method Ben recommends, or the following to strip the Workbook name off.
Dim cell As Range
Dim address As String
Set cell = Worksheets(1).Cells.Range("A1")
address = cell.address(External:=True)
address = Right(address, Len(address) - InStr(1, address, "]"))
The Address() worksheet function does exactly that. As it's not available through Application.WorksheetFunction, I came up with a solution using the Evaluate() method.
This solution let Excel deals with spaces and other funny characters in the sheet name, which is a nice advantage over the previous answers.
Example:
Evaluate("ADDRESS(" & rng.Row & "," & rng.Column & ",1,1,""" & _
rng.Worksheet.Name & """)")
returns exactly "Sheet1!$A$1", with a Range object named rng referring the A1 cell in the Sheet1 worksheet.
This solution returns only the address of the first cell of a range, not the address of the whole range ("Sheet1!$A$1" vs "Sheet1!$A$1:$B$2"). So I use it in a custom function:
Public Function AddressEx(rng As Range) As String
Dim strTmp As String
strTmp = Evaluate("ADDRESS(" & rng.Row & "," & _
rng.Column & ",1,1,""" & rng.Worksheet.Name & """)")
If (rng.Count > 1) Then
strTmp = strTmp & ":" & rng.Cells(rng.Count) _
.Address(RowAbsolute:=True, ColumnAbsolute:=True)
End If
AddressEx = strTmp
End Function
The full documentation of the Address() worksheet function is available on the Office website: https://support.office.com/en-us/article/ADDRESS-function-D0C26C0D-3991-446B-8DE4-AB46431D4F89
I found the following worked for me in a user defined function I created. I concatenated the cell range reference and worksheet name as a string and then used in an Evaluate statement (I was using Evaluate on Sumproduct).
For example:
Function SumRange(RangeName as range)
Dim strCellRef, strSheetName, strRngName As String
strCellRef = RangeName.Address
strSheetName = RangeName.Worksheet.Name & "!"
strRngName = strSheetName & strCellRef
Then refer to strRngName in the rest of your code.
You may need to write code that handles a range with multiple areas, which this does:
Public Function GetAddressWithSheetname(Range As Range, Optional blnBuildAddressForNamedRangeValue As Boolean = False) As String
Const Seperator As String = ","
Dim WorksheetName As String
Dim TheAddress As String
Dim Areas As Areas
Dim Area As Range
WorksheetName = "'" & Range.Worksheet.Name & "'"
For Each Area In Range.Areas
' ='Sheet 1'!$H$8:$H$15,'Sheet 1'!$C$12:$J$12
TheAddress = TheAddress & WorksheetName & "!" & Area.Address(External:=False) & Seperator
Next Area
GetAddressWithSheetname = Left(TheAddress, Len(TheAddress) - Len(Seperator))
If blnBuildAddressForNamedRangeValue Then
GetAddressWithSheetname = "=" & GetAddressWithSheetname
End If
End Function
rngYourRange.Address(,,,TRUE)
Shows External Address, Full Address
The best way I found to do this is to use the following code:
Dim SelectedCell As String
'This message Box allows you to select any cell on any sheet and it will return it in the format of =worksheetname!$A$X" where X is any number.
SelectedCell = Application.InputBox("Select a Cell on ANY sheet in your workbook", "Bookmark", Type:=8).Address(External:=True)
SelectedCell = "=" & "'" & Right(SelectedCell, Len(SelectedCell) - Len("[" & ActiveWorkbook.Name & "]") - 1)
'Be sure to modify Sheet1.Cells(1,1) with the Sheet and cell you want to use as the destination. I'd recommend using the Sheets VBA name.
Sheet1.Cells(1, 1).Value = SelectedCell
How it works;
By Clicking on the desired cell when the message box appears. The string from "Address(External:=True)" (i.e ['[Code Sheet.xlsb]Settings'!$A$1) is then modified to remove the full name of the worksheet([Code Sheet.xlsb]).
Using the previous example it does this by taking the "Len" of the full length of;
[Code Sheet.xlsb]Settings'!$A$1 and subtracts it with the Len of ([Code Sheet.xlsb] -1). leaving you with Settings'!$A$1.
SelectedCell = "=" & "'" & Right(SelectedCell, Len(SelectedCell) - Len("[" & ActiveWorkbook.Name & "]") - 1)
The Code then its and "='" to insure that it will be seen as a Formula (='Settings'!$A$1).
Im not sure if it is only on Excel on IOS but for some reason you will get an Error Code if you add the "='" in any other way than "=" & "'" as seen bellow.
SelectedCell = "=" & "'" & Right....
From here all you need is to make the program in the Sheet and cell you want your new formula in.
Sheet1.Cells(1, 1).Value = SelectedCell
By Opening a new Workbook the full Code above will work as is.
This Code is Especially useful as changing the name of the workbook or the name of the sheet that you are selecting from in the message box will not result in bugs later on.
Thanks Everyone in the Forum before today I was not aware that External=True was a thing, it will make my coding a lot easier. Hope this can also help someone some day.
Why not just return the worksheet name with
address = cell.Worksheet.Name
then you can concatenate the address back on like this
address = cell.Worksheet.Name & "!" & cell.Address
Dim rg As Range
Set rg = Range("A1:E10")
Dim i As Integer
For i = 1 To rg.Rows.Count
For j = 1 To rg.Columns.Count
rg.Cells(i, j).Value = rg.Cells(i, j).Address(False, False)
Next
Next
For confused old me a range
.Address(False, False, , True)
seems to give in format TheSheet!B4:K9
If it does not why the criteria .. avoid Str functons
will probably only take less a millisecond and use 153 already used electrons
about 0.3 Microsec
RaAdd=mid(RaAdd,instr(raadd,"]") +1)
or
'about 1.7 microsec
RaAdd= split(radd,"]")(1)
[edit on 2009-04-21]
As Micah pointed out, this only works when you have named that
particular range (hence .Name anyone?) Yeah, oops!
[/edit]
A little late to the party, I know, but in case anyone else catches this in a google search (as I just did), you could also try the following:
Dim cell as Range
Dim address as String
Set cell = Sheet1.Range("A1")
address = cell.Name
This should return the full address, something like "=Sheet1!$A$1".
Assuming you don't want the equal sign, you can strip it off with a Replace function:
address = Replace(address, "=", "")