Excel - convert column letter to number equivalent vbs - excel

I'm writing a vbs script to extract some data from an excel spreadsheet. Currently using the function:
objSheet.Cells(rowNum, colNum).Value
To get cell values, this allows me to do maths on the column number, e.g. add three to move across three columns. But in some instances I want to specify which Columns to get by letter:
objSheet.Cells(4, E).Value
I therefore need to write a vbs function to convert column letter to numbers E => 5. Needs to be able to handle a spreadsheet more than 26 cols wide.
I've seen lots of functions on the internet and SO for doing the opposite but not found much for doing the conversion this way.
Thanks

This code will run without Excel:
Function ColNum(strCol As String) As Integer
Dim i As Integer, col As Integer
For i = Len(strCol) To 1 Step -1
col = col + (Asc(Mid(strCol, i, 1)) - 64) * (26 ^ (i - 1))
Next
ColNum = col
End Function
Alternatively, in Excel, you can simply use this:
Function ColNum(strCol As String) As Integer
ColNum = Range(strCol & "1").Column
End Function

without vba:
To convert a column number to a letter you enter this formula:
=LEFT(ADDRESS(1,3,4)) (returns the column letter for the cell C1=C)
But this is still not satisfactory because if you insert a column before the column C the number 3 won't change to 4, so here is a fix:
=LEFT(ADDRESS(1,COLUMN(C1),4))
Hope this helps.
This is especially helpful when you need to create strings that specify a cell range for example.

Related

Divide all cells in column A by last cell in column A and repeat for columns B-L

I have a spreadsheet of numbers from A1 to L10. I need to divide cells A2-A9 by the last number in the column (A10). I need the result of those calculations to go into column N (N1-N8). Then I need to repeat that for column B - divide B2-B9 by B10 and put the result of those calculations into column O (O1-O8). This needs to repeat for columns C-L putting the result of the calculations into columns P-Y. I have the code to divide A2-A9 by A10, but I cannot figure out how to repeat this for the rest of the columns.
Sub Divide_a_range_by_last_number()
Dim i As Long
For i = 2 to 9
Worksheets("sheet1").Cells(i,14).Value = Worksheets("sheet1").Cells(i,1).Value / (Range("A1").End(xlDown))
Next i
End Sub
Any suggestions are appreciated.
It sounds like you need one more level of iteration, to repeat the divide process for columns A through L. You could accomplish this using another for-loop - to iterate through each column, and call your "divide" function each time. You'll just need to update your divide function to accept the current column number to operate on:
' Iterate through columns A-L.
For j = 1 to 12
' Provide the current column that you want the divide function to operate on.
Call Divide_a_range_by_last_number(i)
Next
' Update the function signature to accept the current column number.
Sub Divide_a_range_by_last_number(curColumn as Long)
Dim i As Long
For i = 2 to 9
' Update this line to use curColumn variable, instead of static column numbers (i.e. 1 and 14).
Worksheets("sheet1").Cells(i,curColumn + 13).Value = Worksheets("sheet1").Cells(i,curColumn).Value / Worksheets("sheet1").Cells(10,curColumn).Value
Next i
End Sub
I'm pretty new to VBA, so the syntax may not be perfect. But, this should get you started.

Match multiple criteria within range of values

In Sheet1 I have several input values x, y and z in columns A, B and C. To simplify let's say I only have two rows with values (as in the picture).
In Sheet2 I have the thresholds; min and max-values for x, y and z, in addition to the corresponding codes.
I want to retrieve, in Sheet1, all codes where the input values fall within the thresholds (matching the values) in Sheet2. The codes do not need to be listed in the same cell if this complicates things; they can be listed in separate columns. I am also open for both formulas and VBA.
I know how to list several results using JOINTEXT if the criteria are exact matches. I also know how to list one result based on several inaccurate matches using INDEX + MATCH + <= >=. I don't know how to combine them.
I looked at these:
EXCEL index match by multiple criteria AND multiple match types?
https://exceljet.net/formula/multiple-matches-in-comma-separated-list
https://exceljet.net/formula/index-and-match-with-multiple-criteria
...and tried this:
=INDEX(F5:L8;SMALL(IF(COUNTIF(F5:F8;"<="&A5)*COUNTIF(G5:G8;">"&A5)*COUNTIF(H5:H8;"<="&B5)*COUNTIF(I5:I8;">"&B5)*COUNTIF(J5:J8;"<="&C5)*COUNTIF(K5:K8;">"&C5);ROW(F5:L8)-MIN(ROW(F5:L8))+1);COLUMN(F4));ROW(F4)+6)
...without any result.
I managed to solve it by using Jeeped's impressive code (see comments). However, since I'm using comma (,) as decimals-seperator I needed to include a small adjustmen. I changed "iOptions", "iIgnoreHeaderRows", "i" and "j" from Variant to Double, and "a" from Variant to Long. I also included the following code:
Dim counter As Integer, sizeOfPairs As Integer
Dim test As String
counter = 0
sizeOfPairs = UBound(pairs, 1)
For counter = 0 To sizeOfPairs
If TypeName(pairs(counter)) = "String" Then
pairs(counter) = Replace(pairs(counter), ",", ".")
End If
Next counter

counting multiple instances of a number in a range

I have a range of numbers and I need to identify if the first number of each cell is repeated anywhere in the corresponding row.
For example, in row 2 below, column 2 and column 3 both start with a 3. I know that if I do =LEFT(TRIM(cell)) to get just the first number but how do I find the rows that have repeated numbers in the row so row 1 isn't marked but row 2 is?
100|600|203|700| |
202|302|301|400|600|
Use a helper column with this as an array formula:
=SUMPRODUCT(--(COLUMN($A1:$E1)<>MATCH(INT($A1:$E1/100),INT($A1:$E1/100),0)))>0
Being an array formula it must be confirmed with Ctrl-Shift-Enter instead of Enter when exiting edit mode. If done correctly then Excel will put {} around the formula.
Consider the following UDF():
Public Function AnyDups(rng As Range) As Boolean
Dim valu() As String
Dim i As Long, L As Long
L = rng.Count
ReDim valu(1 To L)
AnyDups = False
If L = 1 Then Exit Function
i = 1
For Each r In rng
valu(i) = Left(r.Value, 1)
i = i + 1
Next r
For i = 1 To L - 1
v = valu(i)
For j = i + 1 To L
If v = valu(j) Then AnyDups = True
Next j
Next i
End Function
For example:
The code just loops through the possible combinations of left-most characters in the cells.
It should work with either text or numeric data.
One way to do it would be to use this formula as a basis:
=IF(ISERROR(FIND(LEFT(TRIM(A1),1),B1)),FALSE,"Row "& ROW(A1))
Depending on how you want to check your row, you can adapt it. You could either have one formula to check one cell (Lock the A1 reference and drag right) - which would allow you to know where the match is but take more space on the sheet.
Or, if you don't have too many cells to check in each row, you could concatenate all cells in the same formula:
=IF(ISERROR(FIND(LEFT(TRIM(A1),1),B1&C1&D1&E1)),FALSE,"Row "& ROW(A1))
I'm sure Gary's Student will have a more elegant answer though!

Concatenate permutations between two columns

I need help with an excel assignment.
Name City
---------------
John London
Maxx NY
Ashley DC
Paris
Solution for this must be:
John-london
John-NY
John-DC
John-Paris
Maxx-london
Maxx-NY
.
.
.
.so on.
Simply I have to add text of all elements in one column to text of all elements in other column. I will appreciate if a solution without macros or VB is provided.
You can use this formula (start in Row 1 and fill down until you run out of combinations):
=IFERROR(INDEX(L_1, CEILING(ROW()/COUNTA(L_2),1) ,1) & "-" &
INDEX(L_2, 1+MOD(ROW()-1, COUNTA(L_2)) ,1), "That's it!")
I'm using named ranges "L_1" and "L_2" to refer to the first and second lists respectively
Here's an Array Formula you can use, though you will need to modify the size of the matrix depending on how many entries you have
=CONCATENATE(INDEX(A:A,MMULT(ROW(A1:A3),TRANSPOSE(ROW(B1:B4))/TRANSPOSE(ROW(B1:B4)))),"-",INDEX(B:B,MMULT(ROW(A1:A3)/ROW(A1:A3),TRANSPOSE(ROW(B1:B4)))))
Assuming Column A is Names and Column B is Cities, you would select 12 cells (3 rows high, 4 columns wide), paste the above formula in the first cell and press Ctrl + Shift + Enter to create the array formula.
If you want to see a little simpler version to see what it does before the INDEX references, check with the same area:
=CONCATENATE(MMULT(ROW(A1:A3),TRANSPOSE(ROW(B1:B4))/TRANSPOSE(ROW(B1:B4))),"-",MMULT(ROW(A1:A3)/ROW(A1:A3),TRANSPOSE(ROW(B1:B4))))
Here's a screenshot (with the formula split in 2 lines) of the single formula displaying the output over multiple cells:
This is a simple example in VBA. It is intended to show the concept, not the best practices. Please use it to get you started, and get back here if you need more help, if you want to improve the performances, etc.
The example assumes that the two lists are in A1:An and B1:Bm, and the resulting list goes in column C.
Sub Test()
Dim R1 As Integer, R2 As Integer, R As Integer, NR As Integer
NR = ActiveSheet.UsedRange.Rows.Count
Columns(3).Clear
For R1 = 1 To NR
If Not IsEmpty(Cells(R1, 1)) Then
For R2 = 1 To NR
If Not IsEmpty(Cells(R2, 2)) Then
R = R + 1
Cells(R, 3) = Cells(R1, 1) & " - " & Cells(R2, 2)
End If
Next R2
End If
Next R1
End Sub
resulting column formula should be
=column1&"-"&column2

Search a column to match data in another column and count the number of occurences

I've searched the web but I can't find anything specific for this.
I have column A as below, I need to search this column and find out how many occurrences there are of the data in column B, in the example below there a 4 (70011x3 + 70014x1).
A B
h323:70011 70011
70007 70012
70011 70013
h323:70014 70014
sip:70011#domain.com 70015
What formula would I need to use in Excel?
Thanks in advance
... I don't know if there's a simple way to do this with a single worksheet function, but I could think of 2 methods I would use to accomplish this (and would love to see if any person could figure out how to do this in a single, simple, worksheet function I couldn't think of).
Either way, my solutions would be:
1) Use Array Formulas:
This would look as follows:
A B C
h323:70011 70011 {=SUM(--ISNUMBER(FIND(B1,$A$1:$A$5,1)))}
70007 70012 {=SUM(--ISNUMBER(FIND(B2,$A$1:$A$5,1)))}
...etc
Note that for this solution, you have to type it in as an array formula (Hit ctrl+shift+enter) at the end, but when you drag down column C and sum it up, you will get the correct total.
The challenge with this one is that it doesn't really give you the answer in one cell.
2) Use a Custom VBA Function (My Preferred method):
You can write your own VBA function to do this VERY EASILY.
The one I created was:
Function MyFunc(CriteriaRng As Range, SearchRange As Range) As Double
Dim CriteriaCl As Range
Dim SearchCl As Range
Dim RunningTotal As Double: RunningTotal = 0
For Each CriteriaCl In CriteriaRng
For Each SearchCl In SearchRange
If InStr(1, SearchCl.Value, CriteriaCl.Value) > 0 Then RunningTotal = RunningTotal + 1
Next SearchCl
Next CriteriaCl
MyFunc = RunningTotal
End Function
All you can then do is in any cell type in =myfunc(B1:B5,A1:A5) and you will get the right answer.
Hope this helps!
the function COUNTIF takes wildcards.
with excel 2007, you can simply reference the whole column:
=COUNTIF(A:A,"*"&B1&"*")
with 2003 or lower, you have to put the range in as cell references
=COUNTIF(A1:A2000,"*"&B1&"*")
note that numbers will have to be formatted as text, or you can add in the countif to cover numbers
=COUNTIF(A:A,"*"&B1&"*")+COUNTIF(A:A,B1)
You can then use a SUM on the column to get the total.

Resources