Multiple array assignment to an excel range - excel

Just out of curiosity ,I am asking you a question which is as below:
Suppose i do have an array A1(6)=(45,25,,36,88),A2(6)=(14,25,11),A3(6)=(11,21,20,25,48).Now can we put those array values with the help of a single statement like single array assignment to a row,as here all the rows to a range of an Excel, Say here "C1:R3" range.
EDIT
If I need to assign them to a row like R1<- A1 + A2 +A3,R2<- A1 + A2 +A3. Can you tell me how to this?
R1<- (45,25,,36,88),14,25,11,,,,11,21,20,25,48,) same for R2.
Thanks,

Dim A(2,5)
For i = 0 to 5
A(0, i) = A1(i)
A(1, i) = A2(i)
A(2, i) = A3(i)
Next i
Range("C1:R3").Value = A
EDIT
For second part, to the best of my understanding:
Dim R(17)
For i = 0 To 2
For j = 0 To 5
R(6 * i + j) = A(i, j)
Next j
Next i
Range("C5:T5").Value = R
EDIT 2
Alternatively:
Dim R
R = Split(Join(A1, ",") & "," & Join(A2, ",") & "," & Join(A3, ","), ",")
Range("C5:T5").Value = R
You can use any delimiter you like (if it's appropriate for your data).

Related

Copy output value to another sheet when the range input changes

I have three scenarios of input range ("A1&C3") it can be F1&H3/ J1&L3 /N1&P3.
When I change value of A1&C3 to one of three scenarios, the value in A10&C12 also change (because it contains formula).
I don't want to copy each output result ("A10& C12") to another sheet of three scenarios manually.
I tried to use VBA to make it automatically (3 outputs in 3 new sheets).
Option Explicit
Sub Save()
If Worksheets("Sheet1").Range("A1&C3").Value = Worksheets("Sheet1").Range("F1&H3").Value Then
Worksheets("Sheet1").Range("A1&C3").Copy
Worksheets("BC").Range("A1&C3").PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
Exit Sub
ElseIf Worksheets("Sheet1").Range("A1&C3").Value = Worksheets("Sheet1").Range("J1&L3").Value Then
Worksheets("Sheet1").Range("A1&C3").Copy
Worksheets("UB").Range("A1&C3").PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
Exit Sub
ElseIf Worksheets("Sheet1").Range("A1&C3").Value = Worksheetss("Sheet1").Range("N1&P3").Value Then
Worksheets("Sheet1").Range("A1&C3").Copy
Worksheets("LB").Range("A1&C3").PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
End If
End Sub
Your arrays are wrongly notated within that Range field. Should be A1:C3 and likewise throughout your ranges.
You can't use "Value" as an array comparison in this method. Unless you convert the entire array to a single string and then compare it, its likely going to require some for loops to iterate thru the arrays... that's just a lot of ugly code.
Understanding that when you select a A1:C3, you're creating a you're creating an indexed array or "variant" as they're called in the "land of VB"... needless to say, here's some tweaks that just iterate throughout each of the cells and perform comparative operations for each column/row value and then determine if there's a reasonable match.
Or you could just concatenate it as one big string like this...
For col = 0 To 2 'For Each Column (3 columns)
For Row = 0 To 2 'For each row (3 rows)
'These variable declarations are simply going to append the "Alphabetical" character representation
Z = Chr(Delta + col) & (Row + 1)
A = Chr(Comp1 + col) & (Row + 1)
B = Chr(Comp2 + col) & (Row + 1)
C = Chr(Comp3 + col) & (Row + 1)
1starraystr = 1starraystr & Worksheets("Sheet1").Range(Z).Value
2ndarraystr = 2ndarraystr & Worksheets("Sheet1").Range(A).Value
3ndarraystr = 2ndarraystr & Worksheets("Sheet1").Range(B).Value
4ndarraystr = 2ndarraystr & Worksheets("Sheet1").Range(C).Value
Next
Next
if 1starraystr = 2ndarraystr then... ' you get the idea.
You could compare strings like that afterwards. It's cheeky but could be cleaner than counting a variable upwards. Up to you.. I'll present both options.
Sub Save()
'Set the numeric DEC value for each letter to easily iterate thru alphabet / array comparison.
Const Delta = 65, Comp1 = 70, Comp2 = 74, Comp3 = 78
'Set Counters to 0 to just use a simple counter to validate accuracy of 3 matches.
C1 = 0: C2 = 0: C3 = 0
For col = 0 To 2 'For Each Column (3 columns)
For Row = 0 To 2 'For each row (3 rows)
'These variable declarations are simply going to append the "Alphabetical" character representation
Z = Chr(Delta + col) & (Row + 1)
A = Chr(Comp1 + col) & (Row + 1)
B = Chr(Comp2 + col) & (Row + 1)
C = Chr(Comp3 + col) & (Row + 1)
'Debug.Print Z & vbTab & A & vbTab & B & vbTab & C
If Worksheets("Sheet1").Range(Z).Value = Worksheets("Sheet1").Range(A).Value Then C1 = C1 + 1 ': Debug.Print C1
If Worksheets("Sheet1").Range(Z).Value = Worksheets("Sheet1").Range(B).Value Then C2 = C2 + 1 ': Debug.Print C2
If Worksheets("Sheet1").Range(Z).Value = Worksheets("Sheet1").Range(C).Value Then C3 = C3 + 1 ': Debug.Print C3
Next
Next
'Debug.Print "C1 Count: " & C1
'Debug.Print "C2 Count: " & C2
'Debug.Print "C3 Count: " & C3
If C1 <= 9 Then
Worksheets("Sheet1").Range("A1:C3").Copy
Worksheets("BC").Range("A1:C3").PasteSpecial Paste:=xlPasteValues
'Debug.Print "Copied Cells to BC"
ElseIf C2 <= 9 Then
Worksheets("Sheet1").Range("A1:C3").Copy
Worksheets("UB").Range("A1:C3").PasteSpecial Paste:=xlPasteValues
'Debug.Print "Copied Cells to UB"
ElseIf C3 <= 9 Then
Worksheets("Sheet1").Range("A1:C3").Copy
Worksheets("LB").Range("A1:C3").PasteSpecial Paste:=xlPasteValues
'Debug.Print "Copied Cells to LB"
End If
Application.CutCopyMode = False
End Sub

Get XPATH for selenium VBA

I am struggling with a web page on a secure website. I will put a snapshot of what I am working on.
The XPATH that has the rows of a table (equals to 13 rows) is that
//div[#id='Section3']
But the data is not inside that XPATH but after it in 9 columns.
How can I refer to those children or ancestors ( I don't know the exact term)?
Here's the HTML for that page ( I couldn't include it in the question)
https://pastebin.com/hEq8K75C
Here's the snapshot (may clarify the issue well)
How to implement the variable j in such lines?
Dim x As Long, i As Long, j As Long
x = .FindElementsByXPath("//div[#id='Section3']")
For i = 1 To x
For j = 1 To 9
Cells(i, j).Value = .FindElementByXPath("//div[#id='Section3']/following-sibling::div[following-sibling::div[#id='Section3'][count(preceding-sibling::div[#id='Section3'])=" & i & " and count(following-sibling::div[#id='Section3'])=" & x - (i + 1) & "]][" & j & "]").Text
Next j
Next i
Try to use below code:
counter = len(driver.find_elements_by_id("Section3"))
xpath = "//div[#id='Section3']/following-sibling::div[count(preceding-sibling::div[#id='Section3'])={0} and count(following-sibling::div[#id='Section3'])={1}]"
for i in range(counter):
print('\nRow #{} \n'.format(i + 1))
_xpath = xpath.format(i + 1, counter - (i + 1))
cells = driver.find_elements_by_xpath(_xpath)
for cell in cells:
value = cell.find_element_by_xpath(".//td").text
print(value)

Adding gaps into dynamic array

I'm using the =Filter() function to produce a dynamic array that I am referencing in another cell. Where the output is of the format: example1
However, I'd like to return the array in the format: example2 with a gap before each record where the "type" changes.
I've tried using a helper column and using an IF statement to enter a blank if the previous record had a different value in column A, and then concatenating the cell reference using the =COUNTBLANK() function to refer to correct record. However, this resulted in a different number of blank rows depending on the order of column A.
Is there a better way of achieving this result?
Thanks,
-L.
First put this User Defined Function in a standard module:
Option Explicit
Public Function separate(rng As Range)
Dim arr
arr = rng
Dim U As Long, i As Long, j As Long
Dim L As Long
arr = rng
U = UBound(arr, 1)
L = LBound(arr, 1)
ReDim arrbig(1 To U * 2, 1 To 2)
j = 2
arrbig(1, 1) = arr(1, 1)
arrbig(1, 2) = arr(1, 2)
For i = 2 To U
If arr(i, 1) <> arr(i - 1, 1) Then
arrbig(j, 1) = ""
arrbig(j, 2) = ""
j = j + 1
End If
arrbig(j, 1) = arr(i, 1)
arrbig(j, 2) = arr(i, 2)
j = j + 1
Next i
j = j - 1
ReDim temp(1 To j, 1 To 2)
For i = 1 To j
temp(i, 1) = arrbig(i, 1)
temp(i, 2) = arrbig(i, 2)
Next i
separate = temp
End Function
If we start with raw data in cols A and B like:
We create a dynamic array in cols D and E by putting:
=FILTER(A1:B15,(A1:A15<>"junk")*(A1:A15<>"Peaches"),"X")
in D1:
We create the formatted array in cols G and H by putting this formula in G1:
=separate(D1#)

VBA Grid Generation with User Input

The aim of this code is to have the user input that they want an, e.g. 4x10 grid. I have attached a photo below of the desired output.
However, I'm stuck on the logic of the problem. I can generate one set of grid numbers (e.g. 1-25), but unsure how to duplicate this process to create the whole grid.
Hard to explain using words....
In short I am aiming for:
A1, A2, A3, A4, B1, B2, B3, B4 ...
But I am currently getting: A1, B2, C3, D4 ...
Tried experimenting with different code but to no success. Current code has a loop that I think is right in principle, but re-writes the data in the rows above it once it finishes one 'j' loop and goes back to the start. I'm not sure how to get 'j' to start on a blank cell rather than overwrite what is already in it.
['Userform prior to this step gathers user input
Dim Axial_Data_Points As Variant
Dim Circum_Data_Points As Variant
Axial_Data_Points = Axial_Data_Points_Box.Value 'User input value
Circum_Data_Points = Circum_Data_Points_Box.Value 'User input value
'Basic loop to generate a list of numbers up to the user imposed limit
For j = 1 To Axial_Data_Points
Worksheets("Data Entry").Activate
For k = 1 To Circum_Data_Points
Range("E" & ((j + k) + 1)).Select
ActiveCell.FormulaR1C1 = j
Next k
Next j]
1
This will produce output like:
Dim Axial_Data_Points As Variant
Dim Circum_Data_Points As Variant
Axial_Data_Points = Axial_Data_Points_Box.Value 'User input value
Circum_Data_Points = Circum_Data_Points_Box.Value 'User input value
'Basic loop to generate a list of numbers up to the user imposed limit
Dim i As Integer
Dim j As Integer
For i = 1 To Axial_Data_Points
For j = 1 To Circum_Data_Points
Worksheets("Data Entry").Cells(j + (i - 1) * 10, 4).Value = Chr(i + 64)
Worksheets("Data Entry").Cells(j + (i - 1) * 10, 5).Value = j
Next j
Next i
End Sub
Using Something of this type you can generate what you require:
j = 1
k = 1
For i = 1 To 200
If j < 27 Then
Range("A" & i).Value = Chr(j + 64)
j = j + 1
ElseIf j > 26 And j < 53 Then
G:
Range("A" & i).Value = Chr(k + 64) & Chr(j - 26 + 64)
j = j + 1
Else
j = 27
k = k + 1
GoTo G
End If
Next
You will have to put it in your code.

Vba how to compare 2 column

I'm making an heuristic analyse and i have the fallowing problem : I want to find in column D numbers that match with column J and replace them by a "0". You can see what I'm trying to do on this image :
Problem : Column D have multiples values per cell and column J have one value per cell.
some part of the code:
Dim i,j As Integer
Dim temp As String
Dim x As Integer
Dim d As String
i = Application.CountA(Range("E:E")) + 10
'number of cell with values
j = Application.CountA(Range("J:J")) + 10
For j = 11 To j
temp = Range("J" & j).Value
For i = 11 To i
d = Range("D" & i).Value
*For x = LBound(vec) To UBound(vec)
If vec(x) = temp Then
vec(x) = 0
Range("D" & i).Value = vec(x)
End If
Next
Next
Next
*-> Here it is the problem, i cant figured out how to pass over the coma "," in column D,and store the data. I want to compare the temp with value on "d", but "d" can i have multiple numbers on the same cell, like " 3, 2, 1", and if there is any match like temp = 3, then d= "0,2,1".
English is not my native language so i hope you can understand what i want.
Thanks!
I think your almost there you just need to split up each cell and then search then recreate and replace the string in the cell. Please note I've not tested this.
Dim i,j As Integer
Dim temp As String
Dim x As Integer
Dim d As String
i = Application.CountA(Range("E:E")) + 10
'number of cell with values
j = Application.CountA(Range("J:J")) + 10
For j = 11 To j
temp = Range("J" & j).Value
For i = 11 To i
d = Range("D" & i).Value
Vec = split(d, ",") 'split the cell
d = "" 'clear the string
For x = LBound(vec) To UBound(vec)
If vec(x) = temp Then
vec(x) = 0
End If
d = d & vec(x) & "," 'recreate the string
Next
Range("D" & i).Value = left(d, len(d) - 1) 'save the string without the last ,
Next
Next
you can do this with the below formula - no need for VBA
Make a new column somewhere near column D.
In your new column, use this FIND and Substitute formula:
=IF(NOT(ISERROR(FIND(J:J,D:D))),SUBSTITUTE(D:D,J:J,"0"),D:D)
This formula looks for the value in column J within the cells in column D.
If a match is found, 0 is substituted for the found number. Otherwise, column D is returned.
If you want, you can hide column D to avoid confusion.
in VBA you have a string function called Split(vString, delimiter) that will split a string into tokens using the specified delimiter. See
MSDN Library: VB Split Function
examples:
Mr Spreadsheet John Walkenbach: Split Function examples
VB-Helper

Resources