I have what I thought was a very basic VBA challenge, and have spent hours searching for an answer. Thanks if someone can point me to the right place if already addressed.
I have a formula that is B1 + C1 = D1, and have two 1x5 matrix of data inputs, one for cell B1 and one for cell C1, say [1,2,3,4,5] and [A,B,C,D,E], respectively, in cells (B2:B7) and (C2:C7). I would like to loop through the inputs, such that I get five unique answers [1+A, 2+B, 3+C, 4+D, 5+E], and output those answers in an adjacent 1x5 matrix, say in cells (D2:D7).
Recording a macro does not work here, as it records a copy/paste action that is inflexible for future use (for expanded matrices, other sheet locations, more complex formulas, etc).
Any help much appreciated.
Henry
UPDATE: I believe I need to be using "Do While" or some similar loop code, and additional "For" and "Next" coding.
UPDATE: Here is a step-by-step picture of what I am trying to do with the code:
step-by-step process results image
Here's the solution code:
Sub IterationMacro()
'Declare Variables
Dim h, i, j, k As Integer
Dim mySheet As Worksheet
Dim myAnswer As String
'Set Worksheet
Set mySheet = ActiveSheet
'Set # of Iterations
h = Range("B2").Value
'Clear Previous Contents
Range("C4:D4").ClearContents
Range("e5:e11").ClearContents
'Run Through Loops
For i = 5 To h + 4
For j = 3 To 4
mySheet.Cells(4, j).Value = mySheet.Cells(i, j).Value
Next
'Calculate Workbook
Calculate
mySheet.Cells(i, 5).Value = mySheet.Cells(4, 5).Value
Next
End Sub
If you could draw a table or something to use as an example, it might help.
Assuming I'm undersatnding you, you want to use a formula in D1, and fill down to D7, resulting in showing B+C=D in each row:
Range("D1").Formula="=B1+C1"
Range("D1:D7").Filldown
Edit:
Having been given the example image, it looks like you want math to happen in Row 2 (headers in Row 1). In Row 2 you want to pull up values from Row "i" and add them in Row 2, then paste the answer of that sum in Row "i".
Dim i as Integer 'i is the variable for the loop
For i = 3 to 9 'based on the picture, 3 to 9 are the 1 through 7 values
Cells(2,1).Value=Cells(i,1).Value 'pulls up Column A value from the loop to Row 2
Cells(2,2).Value=Cells(i,2).Value 'pulls up Column B value from the loop to Row 2
Cells(2,3).Formula="=A2+B2" 'Sums A2 and B2 into C2
Cells(2,3).Copy Cells(i,3) 'Copies the summed value to Row "i" in Column C
Next i 'Moves to next "i" in the loop
Let me know if that is more to your point.
Edit:
With dynamic ranges, you still know your starting point. You would look at something similar to:
Dim i as Integer
Dim LR as Long
Dim LC as Long
LR=Cells(Rows.Count,"A").End(xlUp).Row
LC=Cells(1,Columns.Count).End(xlToLeft).Column
For i = 3 to LR 'Still starting at 3, because of the example
Cells(2,1).Value=Cells(i,1).Value
Cells(2,2).Value=Cells(i,2).Value
Cells(2,LC+1).Formula="=A2+B2" 'Note the LC+1 goes one row BEYOND the last column
Cells(2,3).Copy Cells(i,LC+1)
Next i
In the last example, you can see syntax for dynamic ranges. Note that LR and LC are defined outside of the loop and do not change for the duration of the subroutine.
Related
I have a worksheet that uses randomly generated numbers in calculations to produce results in two adjacent cells (let's say A1 and A2). I am trying to perform 100 iterations where I'm simply "Calculating Formulas" on the worksheet and then trying to store the results of each iteration next to A1 and A2 (so iteration 1 would be in B1 and B2 and iteration 100 would be in CW1 and CW2). Thanks in advance for your help. Using Excel 2010 if that matters.
Dim Iteration As Integer, i As Integer
Dim val As Variant
Iteration = 100
For i = 1 To Iteration
Calculate
Range("A1:A2").Select
Selection.Copy
Range("B" & Rows.Count).End(x1Up).Offset(0, 1).PasteSpecial
Paste:=xlPasteValues
Next i
End Sub
I think your major problem was with the location you were selecting for the destination address - you were finding the last unused cell in column B, then shifting over one column (i.e. to column C) and pasting the first set of results. Then you were using that same location for the second set of results, etc.
Sub Test()
Dim Iteration As Integer, i As Integer
Dim val As Variant
Iteration = 100
'Use a "With" block so that it can be easily changed in the future
'to refer to a specific sheet if needed
With ActiveSheet
For i = 1 To Iteration
Calculate
'Determine the last used column on row 1,
' offset 1 column to the right,
' resize to refer to 2 rows,
' set values to the values in A1:A2
.Cells(1, .Columns.Count).End(xlToLeft).Offset(0, 1).Resize(2, 1).Value = .Range("A1:A2").Value
Next i
End With
End Sub
As pointed out by Steve Lovell, you also had a typo in your original code. It is a good habit to include Option Explicit as the first line in every code module. That will force you to declare all the variables that you use, and the compiler would have highlighted x1Up and given a "Variable not defined" error.
I have two columns with random times and the times come from two different sources so the columns do not have the same amount of data points. I want to start with the first time in the first column and compare it to each time in the second column. If there is a match in times, I would like to pull relevant data. After a match is found (if there is one) I would like for the code to go to the second cell in the first column and compare it to every value in the second column and so on.
Here is the code I have so far:
Sub TransferInfo()
'Activate the Sub to Convert and Format Dates
Call ConvertDates
'Define Variables
Dim st As Worksheet
Dim ts As Worksheet
Dim lastrow As Long
Dim i As Integer
j = 2
'Find and set the last used row
Set st = ThisWorkbook.Worksheets("Data Table")
lastrow = st.Cells(st.Rows.Count, "B").End(xlUp).Row
Set ts = ThisWorkbook.Worksheets("ShopFloor")
'Cycle through/compare Row J, Column 18 based on each cell in Row I, Column 14
For i = 2 To lastrow
Do Until IsEmpty(ts.Cells(j, 8)) Or IsEmpty(st.Cells(j, 2))
If st.Cells(i, 14).Value = ts.Cells(j, 18).Value Then
st.Cells(i, 15).Value = ts.Cells(j, 2).Value
Exit Do
Else
st.Cells(i, 15).Value = ""
End If
j = j + 1
Loop
j = 2
Next i
End Sub
The other sub that I call at the beginning of this sub simply rounds the times in each column to the nearest 15 minute interval to increase the likelihood of matches between the columns.
My question is: The code does not copy and paste any more information although there are times that match between the two columns. Why would the code that I have not work? Also, with larger data sets I am afraid that this the code may crash Excel and because I have a loop within a loop trying to process a lot of data a lot of times, but I don't know of a more efficient way to accomplish what I am trying to without this code.
If anyone has any insights as to why this code doesn't work I would greatly appreciate any help.
Thanks!
Based on your code, it looks like you just need an INDEX/MATCH formula. Use this in O2 and copy down:
=IFERROR(INDEX(B:B,MATCH(N2,R:R,0)),"")
No need for VBA
I have an excel file which has column B1 to B500 (may vary) filled with numbers. For example:
![sample data](http://i.stack.imgur.com/zSkLt.jpg)
I need the output to be like:
![sample output](http://i.stack.imgur.com/nTqEK.jpg)
I have this much code till now:
Sub Max()
Dim i As Long, j As Long
Dim cl As Excel.Range
i = 1
j = 1
For i = sheet.UsedRange.Rows.Count To 1 Step -1
cl = sheet.Cells(i, 2) '## Examine the cell in Column B
If xl.WorksheetFunction.CountIf(sheet.Range("B:B"), cl.Value) > 1 Then
cl.Value = sheet.Cells(j, 3).value 'copy to Column C
End If
j = j + 1
Next i
End Sub
What this code does is to find duplicates in column B and remove other entries from the column. Nothing gets written in column C. I want the column B to be unedited at the end. Also cannot figure out how to achieve the sorting here.
Please help.
Well, you could use formulas if you want too:
It is very important to use array formulas (Ctrl+Shift+Enter when done editing the cell), my Excel is an Spanish Version, so you just need to change:
- SI by IF
- CONTAR.SI by COUNT.IF
I came up with this solution thinking about the bubble sort algorithm. I hope this will be useful for you.
I'm new to VBA, and I'd love some help.
I have a spreadsheet that has a range that will always have 10 columns, but could have X amount of rows. I'm trying to write a VBA script that will iterate over this range and extract the values out of each cell.
For example, if I have 2 rows I need A1, B1, C1..J1 and then I need A2, B2, C2...J2. The next time I could have 5 rows and then another time 3.
How do I setup my loop to make this work?
something like
Dim lastRow as long
lastRow = UsedRange.Rows.Count 'or some other way of determining the last row used
for i = 1 to lastRow 'loop through all used rows
'ActiveSheet.Cells(i, 1).value 'column A
'ActiveSheet.Cells(i, 2).value 'column B
'ActiveSheet.Cells(i, 3).value 'column C
next i
You could also use a dynamic named range and loop through that. See this link or google for better examples. Dynamic name ranges are powerful, especially for charts.
For your example you would set the name range reference to;
=OFFSET(Sheet1!$A$1,0,0,COUNT(Sheet1!$A:$A),10) '10 is the width and will go to column J
assuming that column A will have the true max row of the table.
Then;
Dim arr() As Variant
arr = Range("YourRangeName")
For x = 1 To UBound(arr,1) 'Finds the max number of rows in the array, UBound(arr,2) finds the total columns.
'Do some code here where x steps through the array arr
' = arr(x, 1) 'column a
' = arr(x,2) 'column b
' = arr(x,3) ....
Next x
It's almost always better/faster to process as much as you can in code, i.e. assigning a range in Excel to an Array then loop through the array rather than referencing cells (especially in a loops).
I have a file that I only want to extract cells B9, B19, B29, etc etc etc in a pattern throughout the entire file. I would preferably like it to be extracted to a different excel file or someway so that I can do stuff with only those cells in another excel worksheet.
Potentially, I may have several excel files that I may need to do this sort of thing so if there were a way where I had the same format throughout a lot of files that I could always extract cells B9, B19, B29 that would be great. any help appreciated
I looking for syntax if possible
EDIT
Was thinking if I could somehow make an excel IF statement saying if Row has a 9 in it and the row is B then print it somewhere but I want it printed in a column
EDIT 2
I just want column B not A like I mentioned before.
B9, B19,B29,B39 through the whole file
Just in case you want to do it with code:
Sub Test()
'Assumes Sheet1 has your values and Sheet2 will be the data extracted from every row ending in 9
Dim iCounter As Long
Dim newSheetRow As Long
Dim aValue As String
Dim bValue As String
newSheetRow = 1
'Start and nine and increment by 10 till you reach end of sheet
For iCounter = 9 To Sheet1.Rows.Count - 1 Step 10 'NOTE: You may not want to do it by RowCount, but just showing you could
aValue = Sheet1.Range("A" & iCounter)
bValue = Sheet1.Range("B" & iCounter)
Sheet2.Range("A" & newSheetRow).Value = "We were on row: " & iCounter
Sheet2.Range("B" & newSheetRow).Value = aValue
Sheet2.Range("C" & newSheetRow).Value = bValue
newSheetRow = newSheetRow + 1
Next iCounter
MsgBox "Done"
End Sub
You could use the INDIRECT function. It takes a cell reference as a text string and returns the value in that cell. So instead of using
=data!a9
to get the value in sheet "data" in cell a9, you use
=indirect("data!a9")
You can also use r1c1 notation, like this:
=indirect("data!r9c1",false)
From there you can use the ROW and COLUMN functions to go in steps of 10:
=INDIRECT("data!r"&-1+10*ROW()&"c"&COLUMN(),FALSE)
If you put this formula in A1 of your output sheet and then copy and paste it down and across, it will give you the values in data!A9, data!A19, data!A29,... in cells A1, A2, A3... Depending on how you want your output arranged, you might have to modify the cell reference string.
Depending on how often you want to do this depends on how you need to do it, if it's a one of them some simple excel commands might help.
e.g.
In Cell C1 put the following:
=MOD(ROW(),10)
then replicate this down to the bottom of your data. the command will return the numbers 1 through to 0. You can then filter the data on column C where value is 9 then select the visible rows and copy the data to a new sheet.
ROW() ' this returns the ROW number of cell the command is in.
MOD(number, divisor) ' this basically divides one number by the other and returns the remainder. so row 9 / 10 = 0 remainder of 9, row 19 / 10 = 1 remainder of 9.
Hope this helps.