How does this code about arrays work? - arrays

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

Related

VBA: Return the closest value using a 1-Dimensional Array

I am using the WorksheetFunction.Large and WorksheetFunction.CountIf commands to determine the closest "jaw size" using a 1-Dimensional array as the source data, shown below.
wsSheet.Range("H2").Value = WorksheetFunction.Large(myArray, WorksheetFunction.CountIf(myArray, ">" & SizePush) + 1)
The problem I am having is when I use whole numbers (1, 2, 3, 4) the resulting jaw size does not take the closest value from the array, it takes the second closest value. The array I am using is shown in image 1 (myArray), and 'SizePush' refers to the following equation: (Start Diameter - (Start Diameter - End Diameter))-0.05.
a snippet of the jaw size array
I have attached the code that I am using. If anyone can help that would be greatly appreciated because I cannot figure out why only whole numbers cause an issue.
Dim StartDiam, EndDiam, PReduction, Push1, Push2, Push3, Push4, SizePush
StartDiam = 0.5
EndDiam = 4.75
PReduction = Worksheets("Sheet1").Range("D2").Value
Push1 = Worksheets("Sheet1").Range("I2").Value
Push2 = Worksheets("Sheet1").Range("I3").Value
Push3 = Worksheets("Sheet1").Range("I4").Value
Push4 = Worksheets("Sheet1").Range("I5").Value
SizePush = Worksheets("Sheet1").Range("I6").Value
Dim myArray
Set myArray = Range("T2:T51")
Dim wsSheet As Worksheet
Set wsSheet = Worksheets("Sheet1")
If StartDiam < wsSheet.Range("B2").Value Then
If EndDiam > wsSheet.Range("C2").Value Then
'size of jaw if the push is one
If wsSheet.Range("I2").Value = Push1 Then
wsSheet.Range("H2").Value = WorksheetFunction.Large(myArray, WorksheetFunction.CountIf(myArray, ">" & SizePush) + 1)
Exit Sub
End If

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)

Transform Integer Cell Range into Excel Cell Range

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'

Matrix Math with VBA (System of Linear Equations)

I'm looking for a little help performing some matrix mathematics in Excel's VBA. I've read a ton of replies that suggest using the Excel worksheet but I'm hoping to solve this within the VBA code itself.
Although my application is much larger, let's say I have a system of linear equations that I need to solve:
x1 + x2 = 8
2*x1 + 4*x2 = 100
This can be solved with the simple matrix formula A*x = B or x = A^(-1) * B where,
A = [1, 1; 2, 4]
B = [8; 100]
If you solve this, you'll find x1 = -34 and x2 = 42. In terms of the matrix, then:
X = [-34; 42]
Using Excel's worksheets alongside its MMULT and MINVERSE functions makes this easy and I've gotten it to work just fine. My problem is I'm needing to do this calculation inside a VBA function. Here's what I'm trying:
Dim A(0 To 1, 0 To 1) As Single
Dim B(0 To 0, 0 To 1) As Single
Dim X(0 To 0, 0 To 1) As Single
A(0, 0) = 1
A(1, 0) = 1
A(0, 1) = 2
A(1, 1) = 4
B(0, 0) = 8
B(0, 1) = 100
X = Application.WorksheetFunction.MMult(Application.WorksheetFunction.MInverse(A), B)
Unfortunately, the last line yields a "Compile error: can't assign to array" message. I think it's because I have to specify each element of the array one at a time, but the worksheet functions are array functions.
How do I fix this?
Two things:
The same rule applies as in actual mathematics: B must be a vertical array for matrix multiplication to be possible in your case. Declare it as
Dim B(0 To 1, 0 To 0) As Single
and initialize it accordingly. Also, just declare
Dim X As Variant
since the MMult returns a Variant array. This is what was causing your original error.

Resources