Transform Integer Cell Range into Excel Cell Range - arrays

I am coding in Ruby / Rails, and I have a cell range, an example is:
[0,1]..[0,3] with the convention [row, column]..[row..column]
Excel uses cell ranges like:
A2:A4 with the convention <column><row>:<column><row>
I need to convert from the former to the latter.
It is mainly the letter's that I am concerned with:
A => 0,
B => 1,
C => 2,
AA => 26
AB => 27
How would I go about doing that?
I essentially need to do the reverse of this:
Generate letters to represent number using ruby?

VBA Solution
Sub test_JohnLinux()
MsgBox ColLet(4) & vbCrLf & InvColLet("D")
End Sub
Get number from letters :
Public Function InvColLet(x As String) As Long
ActiveSheet.Cells(1, x).EntireColumn.Column
End Function
Get letters from numbers :
Public Function ColLet(x As Integer) As String
With ActiveSheet.Columns(x)
ColLet = Left(.Address(False, False), InStr(.Address(False, False), ":") - 1)
End With
End Function

Ruby Solution
Credit must go to Howard, I adapted the answer from here: https://codegolf.stackexchange.com/questions/3971/generate-excel-column-name-from-index
excel_column_ref =-> array_column_ref do
ref = "A"
array_column_ref.times{ ref.next! }
ref
end
This returns a proc.
Usage excel_column_ref[26] = 'AA'

Related

VBA Change a 1 column array to a one dimensional array

I am loading an array from a table.
aryNonE = ActiveSheet.Range("AA1:AA" & lRowNonE - 1)
test = Array("Bob Smith", "John Davies"...)
Want to use Filter but get type mismatch on aryNonE.
test works fine
[Debug shows1
How do I get aryNonE to look like test??
Thanks
Try this way, please:
Sub test2DTo1DArray()
Dim aryNonE, lRowNonE As Long
lRowNonE = 10
aryNonE = ActiveSheet.Range("AA1:AA" & lRowNonE - 1) '2D array
aryNonE = Application.Transpose(Application.Index(aryNonE, 0, 1)) '1D array
'You can test it in this way:
Debug.Print Join(aryNonE, ",")
End Sub
In this way, it can be used to filter using an array like Criteria1...
But, if the values in the 2D array are numbers, since the Criteria array must keep only strings, the range where the array is extracted from, must preliminarily be formatted as text.

Returning from an array

Maybe this has been asked before, but I don't even know what to search.
I have an array in Excel of n items.
I also have a binary array of n items and for each 1 in that binary array, I want to return the item its position corresponds to in the original array. For example, let's say I have: {A, B, C, D} and {0,0,1,1}. I want to return only C and D since those are the places that have 1s.
Is there a way to do that in Excel?
Thanks.
Best,
Morris
You can use:
=INDEX({"A","B","C","D"},N(IF({1},MODE.MULT(IF({0,0,1,1},COLUMN($A:$D)*{1;1})))))
Depending on ones version this may need to be confirmed with Ctrl-Shift-Enter instead of Enter when exiting edit mode.
My version automatically spills arrays so putting it in A1 gives me the full array output spilled down.
Try the following User Defined Function:
Public Function xtract(s1 As String, binpatrn As String) As String
Dim arr1, arr2, i As Long
arr1 = Split(s1, ",")
arr2 = Split(binpatrn, ",")
For i = LBound(arr1) To UBound(arr1)
If arr2(i) = "1" Then
xtract = xtract & "," & arr1(i)
End If
Next i
If xtract = "" Then
Exit Function
Else
xtract = Mid(xtract, 2)
End If
End Function
We place the comma-separated list (without braces) in A1 and the binary list (without braces ) in B1. In C1 enter:
=xtract(A1,B1)

defining array from worksheet not working in filter () lines with type mismatch error

I'm using secondarray as range of cells in a worksheet (Ex. "1", "2") to exclude them as autofilter list that I'm defining in the below function in "filtercriteria".
I get "type mismatch" error in the filter (secondarray) line for some reason, but I works flawlessly when I define an array using a list of items instead. For example, if I use below line to define secondarray instead.
secondarray = ("1", "2")
I've researched similar postings and wasn't lucky, can someone help with this instance?
Thanks,
Dim secondArray As Variant
secondArray = Range("L76:M76").Value
c = 0
k = 0
count = 0
rowNumb = Worksheets("List").Range(Worksheets("List").Range("L5"), Worksheets("List").Range("L5").End(xlDown)).Rows.count
For L = 1 To rowNumb
c = Worksheets("List").Range("L5").Offset(L)
If c <> k Then
'check the current activity type against the array of types we don’t want. If it isn’t in the array we add it to an array that will be used as the filter criteria
If UBound(Filter(secondArray, c)) = -1 Then
ReDim Preserve filterCriteria(0 To count)
filterCriteria(count) = c
count = count + 1
End If
k = c
End If
Next
It isn't working because filter function takes a One-dimensional array of strings to be searched for its sourcearray argument.
When you read in a range from the sheet you automatically get a 2d array as opposed to the 1D you have when assigning from a list.
Find a way to use a 1D array to pass in
For example, as your data is coming from 1 row then slice the array by row
UBound(Filter(Application.WorksheetFunction.Index(secondArray, 1, 0), c)) = -1
You may need to find the right method for you.
Another method is given here.

How does this code about arrays work?

The code bellow splits a string into strings of seven characters each into an array. Can someone please explain how it works in detail?
Dim orig = "12344321678900987"
Dim res = Enumerable.Range(0,orig.Length\8).[Select](Function(i) orig.Substring(i*8,8))
Dim orig = "12344321678900987"
Dim res = Enumerable.Range(0,orig.Length\8).[Select](Function(i) orig.Substring(i*8,8))
This code uses a few neat language tricks to reduce the amount of code required for digesting the string into smaller segments. Starting from inside out, first there is a Lambda Expression:
Function(i) orig.Substring(i * 8, 8)
This is a fancy way of creating Subs or Functions 'inline.' It essentially equates to:
Function subStr(ByVal i As Integer) As String
Return orig.Substring(i * 8, 8)
End Function
The next part uses the Enumerable class, and its Range method to generate a series of numbers to feed into the lambda.
Enumerable.Range(0, orig.Length \ 8)
This is a fancier way of writing:
For i As Integer = 0 To (orig.Length \ 8)
'Do something with i
End For
.[Select] is a little bit of magic that takes the current i in the loop (or range), and allows working with it. In this example it's:
subStr(i)
So this neat, one-line job can also be written as:
Dim orig As String = "12344321678900987"
Dim res as String()
For i As Integer = 0 To (orig.Length \ 8)
Array.Resize(res, res.Length + 1)
res(res.Length - 1) = subStr(i)
End For
Function subStr(ByVal i As Integer) As String
Return orig.Substring(i * 8, 8)
End Function

Can I create a line graph from an Array?

I have 6 arrays of data as longs. I want to find a way to graph all six arrays as separate lines on a Chart Control.
I have created the Chart object, in my Series Collection Editor I have 6 members, but I cannot find a function that does something along the lines of chart1.series1.setData(myArray).
I know I can go through and call .add() on every point, but I am wondering if there is a direct way to assign an array to a Series.
There is no built in way to add a whole range apart from databinding. You can call, as you said, the AddXY method of the Points property (or one of the related methods in the type DataPointCollection) of the Series, like so:
'Add data from Array1 to the first series of the chart
Chart.Series(0).Points.Clear() 'Clear all points
For i = 0 to Array1.Count - 1
Chart.Series(0).Points.AddXY(i, Array1(i)) 'Adds the data from the array to the first series
Next
If you have the data in a multidimensional (e.g. Dim Data()() As Long) you can do something like
For a = 0 to Data.Count - 1
Chart.Series(a).Points.Clear() 'Clear all points from the ath series
For i = 0 to Data(a).Count - 1
Chart.Series(a).Points.AddXY(i, Data(a)(i)) 'Adds the data from the ath array to the ath series
Next
Next
Note the X values will be just an index (0 to the array's count - 1) since you provided no further information.
Or you could write an extension method in a new Module
Public Module Extensions
<System.Runtime.CompilerServices.Extension>
Public Sub AddRange(d As System.Windows.Forms.DataVisualization.Charting.DataPointCollection, data() As Long)
Dim meCount As Integer = d.Count
For i = 0 To data.Count - 1
d.AddXY(meCount + i, data(i))
Next
End Sub
End Module
Now you can just call the AddRange method for the Points property of the series:
Chart.Series(0).Points.AddRange(Array1)
You can do it by adding point by point as Jens mentions, and this works find. Another way which should work fine is:
For a as integer = 0 to AmountOfSeries.count - 1 step 1
Chart1.Series(a).Points.DataBindXY(ArrayX1, ArrayY1)
Next
This may be closer to what you were looking for - a way to set two arrays to a series.
Here's what it would look like with only one series:
Dim xs As Double() = {0, 1, 2, 3, 4}
Dim ys As Double() = {0, 1, 2, 3, 4}
Chart1.Series(0).Points.DataBindXY(xs, ys)

Resources