Excel adding multiple rows - excel

IS there a quick way to do this?
For example I have two rows
A B
34 5
56 6
34 3
25 2
I want to do the following calculation down the rows.
A1 = A1+B1
A2 = A2+B2
A3 = A3+B3
..
..
Now I can do this with a macro that loops though the rows like
for x = 1 to 500
sheet1.cells(x,1).vlaue = sheet1.cells(x,1).vlaue + sheet1.cells(x,2).vlaue
next x
but it there a more efficient way by using ranges or something where it can be carried out as a single step?
Cheers

A quick way is to enter from the immediate window:
[a1:a500]=[a1:a500+b1:b500]
The square brackets are a shortcut for the Evaluate function

I can think of two options:
Option 1
Use Copy, Paste Special, Add
Sub AddStep()
Dim rng1 As Range, rng2 As Range
Set rng1 = Range([A1], [A1].End(xlDown))
Set rng2 = rng1.Offset(, 1)
rng2.Copy
rng1.PasteSpecial xlPasteValues, xlPasteSpecialOperationAdd
Application.CutCopyMode = False
End Sub
Option 2
Loop over a variant array. This is much faster than looping over a range
Sub AddStep()
Dim rng As Range
Dim dat As Variant
Dim i As Long
Set rng = Range([B1], [A1].End(xlDown))
dat = rng
For i = LBound(dat, 1) To UBound(dat, 1)
dat(i, 1) = dat(i, 1) + dat(i, 2)
Next
rng = dat
End Sub
Option 1 is faster, but in some circumstances it is best to avoid the clipboard.
Tested on a sample of 1,000,000 rows:
Option 1 - 435ms
Option 2 - 2589ms

The way I would do it is create a formula for the first row, then just select all the rows after and press Ctrl+D. Isn't this what you are after? Unless I misunderstood the question.

Related

Delete rows based on multiple columns and multiple conditions

I have an excel sheet, and I'm trying. to write VBA code to delete rows from the excel sheet based on the following conditions:
If Column A contains strings "string1" and "string2".
OR
If Column B contains strings "string3" or "string4"
Im using the below code:
Sub DeleteRows()
Dim rng As Range
Dim pos As Integer
Set rng = ActiveSheet.UsedRange
For i = rng.Cells.Count To 1 Step -1
pos = InStr(LCase(rng.Item(i).Value), "string1"))
If pos > 0 Then
rng.Item(i).EntireRow.Delete
End If
Next i
End Sub
But it only deletes rows if the single string is located in any column , and I couldn't specify the column name to search in.
Any help is appreciated.
Thanks,
With rng.Cells.Count you loop through all cells in the range:
Dim i As Long
For i = rng.Columns(2).Cells.Count To 1 Step -1
will only loop through the cells of column 2.
The issue is with your Loop - you're looping through each Item in the range, rather than each row
Try the below
Sub DeleteRows()
Dim rng As Range
Dim rownum As Long
Set rng = ActiveSheet.UsedRange
For rownum = rng.rows.Count To 1 Step -1
If LCase(Rng.Cells(rownum, 1) Like "*String1*" And _
LCase(rng.Cells(rownum, 1) Like "*String2*" Or _
LCase(rng.Cells(rownum, 2) Like "*String3*" Or _
LCase(rng.Cells(rownum, 2) Like "*String4*" Then
rng.Cells(rownum, 1).EntireRow.Delete
End If
Next
End Sub

Is there a concise way to do Range("A1:A10").Value = Range("A1:A10").Value + 1 in vba

I have a bit of problem working with range variable. for example, I can directly do assignment on a range of cells like this:
Range("B1:B10").Value = Range("A1:A10").Value
However, is there a concise way to do increment of range of values then assignment, following is what i mean but resulted in type-mismatch error
Range("A1:A10").Value = Range("A1:A10").Value + 1
Edit: Ultimately what i want to implement is a scroll_button, when _UP is clicked, all the cells in the range increase value by 1, when _Down is clicked, all the cells in the range decrease value by 1. What's the most efficient way to do this?
This is what I'd do if you have a large chunk of data:
Option Explicit
Sub Increase_Decrease(UpOrDown As Long)
Dim LastRow As Long, i As Long
Dim arr As Variant
With ThisWorkbook.Sheets("MySheet") 'Change MySheet for your sheet
LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
arr = .Range("A1", .Cells(LastRow, 1)).Value
For i = 1 To UBound(arr)
arr(i, 1) = arr(i, 1) + UpOrDown
Next i
.Range("A1", .Cells(LastRow, 1)).Value = arr
End With
End Sub
Sub Increase()
Increase_Decrease 1
End Sub
Sub Decrease()
Increase_Decrease -1
End Sub
Then you link your scroll up button to the Increase procedure, and the scroll down button to the decrease button.
You can do this without VBA as well.
Demonstration setup will be
Insert form control from Developer >> Insert >> Form Controls >> Scroll Bar.
Parameters will be
Minimum Value = 1
Maximum Value = 100
Incremental Change = 1
Page Change = 10
Cell Link = $B$1
And then insert following formula in cell A1:
=ROW()-$B$1
Copy down.

Copy and paste loop through 2 sets of ranges

I am working on an excel sheet. I have titles of data entries, which I wish to copy to other locations on the sheet. The titles range from c3 to c122, and I intend to copy and paste them in cells 70 rows apart. The code below doesn't suffice; I am given error 450 (wrong number of arguments or invalid property assignment).
Option Explicit
Sub Titles()
Dim i As Integer
Dim n As Integer
For i = 151 To 8971 Step 70
For n = 3 To 122 Step 1
Cells.Value(i, 3) = "c" & n
Next n
Next i
End Sub
I desire to have what is in each of cells C3:C122 to be copied into C150, C220,...,C8791. Is this a good approach? Thank you for your help.
There is a lot wrong here.
The double for loop is not required. If the code did work, it would overwrite Cells.Value(i, 3) 120 times on each iteration of i
Cells on its own refers to all the cells on the Active Sheet
Cells.Value returns the cell values as a variant array, in this case a 1,048,576 x 16,384 array
"c" & n creates a string (eg c3) not a cell reference
Try someting like this (note, please check the initial value of rw as there is a contradiction in your post 150 vs 151)
Sub Demo()
Dim ws As Worksheet
Dim rng As Range
Dim cl As Range
Dim rw As Long
Set ws = ActiveSheet
Set rng = ws.Range("C3:C122")
rw = 151 '<--- check if this is right
For Each cl In rng.Cells
ws.Cells(rw, 3).Value = cl.Value
rw = rw + 70
Next
End Sub
Syntax on Cells.Value(i, 3) is wrong it should be Cells(i, 3).Value
Change that and see if everything works as you wanted.

VBA Excel: Non-Active Sheet and Unknown Number of Rows. If cell contains value, perfom calculation and insert new value into cell on same row

I have tried my best to search for the answer but can't get what I'm looking for. I'm very new to VBA so may be going wrong in several places here . . .
I'm creating a data formatter that processes data with a different numbers of records (rows) each time it is used. Data will be on non-active sheet. First row has headings. I've successfully used similar code to the code below to identify rows with certain data on it and clear the contents of other cells on that row.
The reason I refer to column E is because it is the only column that has data in every record. I then have to find the rows that have a value in column BU, then multiply that value by 20 and insert the result in column BX of the same row.
I keep getting Run-time Error 13 but don't understand as it's simply a number with 2 decimal places in cell BU, and currently there is nothing in BX.
Sub CalcTotalLTA()
Dim i As Variant
'counts the no. of rows in E and loops through all
For i = 1 To Sheets("Input").Range("E2", Sheets("Input").Range("E2").End(xlDown)).Rows.Count
'Identifies rows where columns BU has a value
If Sheets("Input").Cells(i, 73).Value <> "" Then
'calculate Total LTA
Sheets("Input").Cells(i, 76).Value = Sheets("Input").Cells(i, 73).Value * 20
End If
Next i
End Sub
You're most likely having an issue because Application.Sheets holds both sheet types, which are Charts and Worksheets. Application.Sheets does not have a .Range() property.
Replace all instances of Sheets() with Worksheets().
Worksheets("Input").Cells(i, 76).Value = Worksheets("Input").Cells(i, 73).Value * 20
Even better:
Dim ws as Worksheet
Set ws = Worksheets("Input")
..
ws.Cells(i,76).Value = ws.Cells(i,73).Value * 20
Exclude Header Row From Range
Public Function rngExcludeHeaders(rng As Range) As Range
Set rng = rng.Offset(1, 0).Resize(rng.rows.count - 1, rng.Columns.count)
Set rngExcludeHeaders = rng
End Function
usage:
Dim MyRange as Range
Set MyRange = rngExcludeHeaders(ws.UsedRange)
Thanks to input from #Adam Vincent and #Vityata, and some other research (the reason why I'm solving this myself, hope that's not bad etiquette) I've found the solution. Starting the index 'i' at 2 and adding 1 at the end avoids the header row text and includes the last row too:
Option Explicit
Sub CalcTotalLTA()
Dim i As Variant
Dim ws As Worksheet
Set ws = Worksheets("Input")
'counts the no. of rows in E and loops through all
For i = 2 To ws.Range("E2", ws.Range("E2").End(xlDown)).Rows.Count + 1
'Identifies rows where columns BU has a value
If ws.Cells(i, 73).Value <> "" Then
'calculate Total LTA
ws.Cells(i, 76).NumberFormat = "0.00"
ws.Cells(i, 76).Value = ws.Cells(i, 73).Value * 20
End If
Next i
End Sub
Try it like this:
Option Explicit
Sub CalcTotalLTA()
Dim i As Long
With Worksheets("Input")
For i = 1 To .Range("E2", .Range("E2").End(xlDown)).Row
If .Cells(i, 3) <> "" Then
.Cells(i, 6) = .Cells(i, 3) * 20
End If
Next i
End With
End Sub
This is what I have changed:
Adding Option Explicit on top
I have used With Worksheets("Input") to make your code more understandable.
Furthermore, I suppose you do not need Rows.Count but .Row
I have changed 76 and 73 to 3 and 6 to avoid some scrolling to the right, thus be careful when you use it over your workbook.
Removed .Value as far as it is the default one.

Loop through each row of a range in Excel

This is one of those things that I'm sure there's a built-in function for (and I may well have been told it in the past), but I'm scratching my head to remember it.
How do I loop through each row of a multi-column range using Excel VBA? All the tutorials I've been searching up seem only to mention working through a one-dimensional range...
Dim a As Range, b As Range
Set a = Selection
For Each b In a.Rows
MsgBox b.Address
Next
Something like this:
Dim rng As Range
Dim row As Range
Dim cell As Range
Set rng = Range("A1:C2")
For Each row In rng.Rows
For Each cell in row.Cells
'Do Something
Next cell
Next row
Just stumbled upon this and thought I would suggest my solution. I typically like to use the built in functionality of assigning a range to an multi-dim array (I guess it's also the JS Programmer in me).
I frequently write code like this:
Sub arrayBuilder()
myarray = Range("A1:D4")
'unlike most VBA Arrays, this array doesn't need to be declared and will be automatically dimensioned
For i = 1 To UBound(myarray)
For j = 1 To UBound(myarray, 2)
Debug.Print (myarray(i, j))
Next j
Next i
End Sub
Assigning ranges to variables is a very powerful way to manipulate data in VBA.
In Loops, I always prefer to use the Cells class, using the R1C1 reference method, like this:
Cells(rr, col).Formula = ...
This allows me to quickly and easily loop over a Range of cells easily:
Dim r As Long
Dim c As Long
c = GetTargetColumn() ' Or you could just set this manually, like: c = 1
With Sheet1 ' <-- You should always qualify a range with a sheet!
For r = 1 To 10 ' Or 1 To (Ubound(MyListOfStuff) + 1)
' Here we're looping over all the cells in rows 1 to 10, in Column "c"
.Cells(r, c).Value = MyListOfStuff(r)
'---- or ----
'...to easily copy from one place to another (even with an offset of rows and columns)
.Cells(r, c).Value = Sheet2.Cells(r + 3, 17).Value
Next r
End With

Resources