I have two columns of data as follows:
A1: A; A2: B; A3: C and B1: 1; B2:2; B3:3
Is there a simple loop in VBA to have on column C the concatenated values as:
C1: A1; C2: A2; C3: A3; C4: B1; C5: B2; C6: B3; etc?
I would use modulo arithmetic to achieve this. The subroutine below assumes that the last row in column C that needs to be populated is lLastRow (I set it =25 for testing):
Sub test()
Dim lLastRow As Long, ACnt As Long, BCnt As Long
ACnt = 1
' Last row of column C that needs to be filled with Data
lLastRow = 25
For BCnt = 1 To lLastRow
' Use modulo arithmetic to point to the right cell in column B
Cells(BCnt, 3) = Cells(ACnt, 1) & IIf(BCnt Mod 3 <> 0, BCnt Mod 3, 3)
' We should increment column A every three rows
ACnt = IIf((Cells(BCnt, 3).Row) Mod 3 = 0, ACnt + 1, ACnt)
' Reset column A pointer when we go beyond 3
ACnt = IIf(ACnt = 4, 1, ACnt)
Next BCnt
End Sub
Column B number:
The idea is that (starting from the first row), the modulo of each row and 3 will be 0,1,2 and will recycle in this fashion forever. Whenever the row number is a multiple of 3, the modulo returns 0 and therefore we need to refer to 3 on column B (i.e., cell (B3). Else, modulo returns exactly what we want (which is either 1 or 2).
Column A number:
This is simpler: every 3rd row we switch row.. So when (Cells(BCnt, 3).Row) Mod 3 = 0, we increment the pointer of column A. Of course, when we reach the 4th row, we need to return back to the 1st row.
I hope this helps!!
I prefer to avoid VBA when possible, so given a data setup like this:
The formula in cell C1 and copied down is:
=IF(ROW(A1)>COUNTA(A:B),"",INDEX(A:B,MOD(ROW(A1)-1,COUNTA(A:A))+1,1+(ROW(A1)>COUNTA(A:A))))
EDIT
As an alternate interpretation, pointed out by Ioannis, given a data setup like this:
The formula in cell C1 and copied down is:
=IF(ROW(A1)>COUNTA(A:A)*COUNTA(B:B),"",INDEX(A:A,INT((ROW(A1)-1)/COUNTA(B:B))+1)&INDEX(B:B,1+MOD(ROW(A1)-1,COUNTA(B:B))))
I can't see it any simpler than below
Sub concat()
Dim i As Integer
With ActiveSheet
For i = 1 To .UsedRange.Rows.Count
.Cells(i, 3) = .Cells(i, 1) & .Cells(i, 2)
Next i
End With
End Sub
Or maybe there is:
Sub concat2()
With ActiveSheet
.Range("C1") = "=CONCATENATE(RC[-2],RC[-1])"
.Range("C1").AutoFill Destination:=.Range("C1:C" & .UsedRange.Rows.Count)
End With
End Sub
That would also make non-vba users understand what column C actually is ;)
Can't you do something like:
Dim i,j AS int
For i = 1 to 3
For j = 1 to 6
NewVal = C(j):A(i)
Next j
Next i
This is untested, but gives you direction of where to go..
Related
I want to use a code to repeat itself through many rows because it would take too much time writing one by one, i dont know if there's a code that takes from the chosen cell that i put the macro the column and row of it.
now in column 1 and row 1 as reference
if (current Column (1), current row (1) ) = 1 then
column number 3, current row = 1
end if
next
now in column 1 and row 2 as reference
if (current Column (1), current row (2) ) = 1 then
column number 3, current row = 1
end if
I wanted to copy paste to code to go on in the entire column 1, but i dont have any idea how to do that, could someone help please?
We can loop over rows:
Sub kayky()
Dim N As Long, i As Long
N = 123
For i = 1 To N
If Cells(i, 1).Value = 1 Then Cells(i, 3).Value = 1
Next i
End Sub
This handles 123 rows; modify to suit your data.
I am trying to create a macro VBA that allow me for example:
Column A: 123456789101112 Column F : 6789101112
Only 10 characters in column F. If we have less than 10 characters in column A to complete with 0 for example:
Column A: 123458 Column F: 0000123458
This is the function that allow me to select the number of characters:
For i = 1 To table1Rows - 1
table1(1 + i, 6) = Right(table1(1 + i, 1), 15)
But I need to complete the 10 characters if I have less than 10 in column A.
This will place the formula in column F based on the amount of data in column A.
The formula uses r1c1 notation - R on its own means this row, C1 means column 1.
It's the same as writing =TEXT(RIGHT(A1,10),REPT(0,10)) and dragging down.
Sub Test()
Dim rLastRow As Range
With ThisWorkbook.Worksheets("Sheet1")
Set rLastRow = .Cells(.Rows.Count, 1).End(xlUp) 'Based on column A (column #1)
'Column A Offset by 5 columns is column F.
.Range(.Cells(1, 6), rLastRow.Offset(, 5)).FormulaR1C1 = _
"=TEXT(RIGHT(RC1,10),REPT(0,10))"
End With
End Sub
I think this is what you're after:
For i = 1 To table1Rows - 1
table1(1 + i, 6) = Format(Right(table1(1 + i, 1), 10), "0000000000")
Next
following code will add the remaing zero's to your string:
Dim strnbr As String
strnbr = 123
While Len(strnbr) < 10
strnbr = "0" + strnbr
Wend
I want to know how to total values in VBA and put it into a cell.
I got:
Dim client As Range, totalPrice As Range, dDate As Range
Dim cell As Range
Dim i As Integer, j As Integer, k As Integer, subT As Double
Set client = Range("A2:A32")
i = 1
j = 1
k = 1
subT = 0
For Each cell In client
If cell(i, 1) = "apple" Then
If cell(j, 3) >= 43191 And cell(j, 3) <= 43220 Then
subT = subT + cell(k, 5)
End If
End If
i = i + 1
j = j + 1
k = k + 1
Next
Cells(10, 10).Value = subT
End Sub
The table has 5 columns (column 1 is fruit name, column 3 is date, and column 5 is price) and there are total of 32 rows.
I'm trying to get April 2018 prices for "apple". There are two apples in April, but the subT variable only stores the first one (it skips the price value at row 32).
Row 1 is headers.
Row 26 has a price for apple of 42.09 (it stores this and prints it).
Row 31 has a price for apple of 14.65 (it does not store this and does not add it to subT).
In your original code, you were iterating through the range but also using the offset method of a range object.
First things first, 'cell' is leads to horrible confusion as a variable name in Excel VBA.
That said:
cell(x,y) is the offset method. It means get me the range that is x - 1 rows down and y - 1 columns right from whatever range is referenced by cell.
The for each loop is automatically updating the range referenced by the variable cell, traversing from A2 to A32 in order. And your i,j,k variables are instructing the program to check ranges that are increasingly offset from your table.
For example in the first pass cell references A2 and cell(i,1) references A2. In the second pass cell references A3 (for each updated this) and cell(i,1) references A4 (i=2 and the offset method says give me the range offset one row down from A3). In the third pass cell references A4 and cell(i=3,1) references A6! (since A6 is offset 3 - 1 =2 rows from A4) and so on.
It's not clear to me why initializing i,j,k to 2 allowed things to work. I suspect that was an accident. The Cells method always offsets from A1 (I believe) so I don't think that helps anything.
My suggestion would be to get rid of i,j and k altogether:
If cell(1, 1) = "apple" Then
If cell(1, 3) >= 43191 And cell(1, 3) <= 43220 Then
subT = subT + cell(1, 5)
They're not doing you any favors.
I hope this helps.
I need to retrieve the last but one row value in column A/B(Value in Date)
Ex1: Row 3 : last column is AB. I need Row 3 Column AA value (Date) in Row 3 Column C.
Ex 2: Row 4:last column in AS: I need Column AR value (date) in ROw 4 column C.
Ex 3:Row 5:last column in BC: I need Column BB value (date) in ROw 5 column C.
there can b one or 2 blank values.
Please let me know if there are any excel formula to tackle this scenario.
with iteration you could use an array-formula like: (for row 3)
=INDIRECT("R3C"&MAX(COLUMN(3:3)*(LEN(3:3)>0))-1, 0)
without you need to exclude the cell itself... having it at column C it would be something like: (for row 3)
=INDIRECT("R3C"&MAX(COLUMN($D3:$ZZ3)*(LEN($D3:$ZZ3)>0))-1, 0)
if you want to simply auto fill the formula down then replace the "R3C" with "R"&ROW()&"C"
The formulas shown here are array formulas and must be confirmed with Ctrl+Shift+Enter.
If you get inclined to VBA, you could try something like this:
' In C3 type =GetSecondLastColumnValue()
' This function will keep on checking values on column at a time to the right
' If 3 continuous empty cells are found, it will assume that there are no more
' columns with values after that. The last known cell with value will be identified
' and value of column just to its left will be plugged in to column C
Public Function GetSecondLastColumnValue()
Dim Looper As Integer
Looper = 1
Const NoOfContinuousEmptyColumns As Integer = 3
Dim m_Address As String, m_LastKnownColumnWithValue
m_Address = Selection.Address
m_LastKnownColumnWithValue = m_Address
Do
m_Address = Range(m_Address).Offset(0, 1).Address
If Range(m_Address).Value = "" Then
Looper = Looper + 1
If Looper > NoOfContinuousEmptyColumns Then Exit Do
Else
Looper = 1
m_LastKnownColumnWithValue = m_Address
End If
Loop
m_LastKnownColumnWithValue = Range(m_LastKnownColumnWithValue).Offset(0, -1).Address
GetSecondLastColumnValue = Range(m_LastKnownColumnWithValue).Value
End Function
Example:
A B C D E F
1 abc def ab cd
2 abc def xy zx st
In C1, type =GetSecondLastColumnValue () and it will be populated with ab.
In C2, type the same formula and it will be populated with zx
This is just an example of what you can do with VBA. Do NOT use this function in production. It is insanely greedy and slow. It's just an illustration.
This subroutine is much faster:
' This method keeps on going to far right till it reaches the end of the columns
' Then it comes back to the last column with value, and hops to the column to its left, and remembers its value
' That value goes in column C. It loops through all rows you specify in startrow and endrow
Sub PopulateColumnC()
Dim StartRow As Integer, EndRow As Integer, RowLoop As Integer
StartRow = 1
EndRow = 3
Dim m_Address As String
For RowLoop = StartRow To EndRow
Range("A" & RowLoop).Select
m_Address = Selection.Address
Do
Selection.End(xlToRight).Select
If m_Address = Selection.Address Then
Selection.End(xlToLeft).Select
Exit Do
Else
m_Address = Selection.Address
End If
Loop
m_Address = Range(Selection.Address).Offset(0, -1).Address
Range("C" & RowLoop).Value = Range(m_Address).Value
Next
End Sub
I have an Excel file that contains some data in column B, now i wish to categories the data in A column like serial number first 1 to 5 again starts from 1 to 5 until the data ends,
for example in below format
1 A
2 B
3 C
4 D
5 E
1 F
2 G
3 H
4 I
5 J
1 K
2 L
3 M
4 N
5 O
I do not have existing code for above task please help me.
you can use the following
put 1 in the Cell A1
put =IF(OFFSET(A2,-1,0)=5,0,OFFSET(A2,-1,0))+1 in cell A2
double click in the bottom corner of cell A2, this will repeat the function for all cells in column A
hope that it will help you
Use some code
Sub DoItGood()
Dim rws As Long, rng As Range, t As Range
Columns(1).ClearContents
rws = Cells(Rows.Count, "B").End(xlUp).Row
Set rng = Range("A1:A" & rws)
x = 1
For Each t In Range("A1:A5")
t = t + x
x = x + 1
Next t
Range("A1:A5").AutoFill Destination:=rng, Type:=xlFillCopy
End Sub
You can get a repeated list of numbers from 1 to n downwards in rows with the following approach:
=MOD((ROW(A1)-1),n)+1
Take the integer remainder of the division row number (starting with 0) and n. You will get 0,1,2,...,n-1,0,1,2,...,n-1,0,1... To this add 1.
In your case n is 5:
=MOD((ROW(A1)-1),5)+1
filled downwards.