Copy and paste loop through 2 sets of ranges - excel

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.

Related

Fill cells with values from another sheet using For Loop VBA

I have a set of information in the same column (H27:O27) in one sheet ("P1-FR1") and would like to paste individual values to another sheet (AQ6:AX6) ("Übersicht GESAMT")
I'm trying to use a For loop but the values just copy one after the other (in the same cell) instead of copying one in each cell. This is my code:
Sub CopyValues()
Dim i As Long
Dim j As Long
Dim Wert As Long
For i = 8 To 14
Wert = Sheets("P1-FR1").Cells(27, i)
For j = 43 To 50
Sheets("Übersicht GESAMT").Cells(6, j) = Wert
Next j
Next i
End Sub
You don't need a double For loop in this case at all. A simple .Value copy will work. The code below shows two examples with different ways to accomplish what you want. (TIP: it always helps me to be VERY clear on how I name the variables, it helps to keep track of where all the data is coming and going)
Option Explicit
Sub CopyTheValues()
Dim datenQuelle As Range
Dim datenZiel As Range
Set datenQuelle = ThisWorkbook.Sheets("P1-FR1").Range("H27:O27")
Set datenZiel = ThisWorkbook.Sheets("Übersicht GESAMT").Range("AQ6:AX6")
'--- method 1 - works because the ranges are the same size and shape
datenZiel.Value = datenQuelle.Value
'--- method 2 - for loops
' index starts at 1 because the Range is defined above
' (and we don't care what rows/columns are used)
Dim j As Long
For j = 1 To datenQuelle.Columns.Count
datenZiel.Cells(1, j).Value = datenQuelle.Cells(1, j).Value
Next i
End Sub
Copying By Assignment
Option Explicit
Sub CopyValuesNoLoop()
ThisWorkbook.Worksheets("Übersicht GESAMT").Range("AQ6:AX6").Value _
= ThisWorkbook.Worksheets("P1-FR1").Range("H27:O27").Value
End Sub
Sub CopyValuesQuickFix()
Dim j As Long: j = 43
Dim i As Long
For i = 8 To 14
ThisWorkbook.Worksheets("Übersicht GESAMT").Cells(6, j).Value _
= ThisWorkbook.Worksheets("P1-FR1").Cells(27, i).Value
j = j + 1
Next i
End Sub
The nesting of the for loops is causing your issue. It is causing each cell from the first sheet to be copied to all cells on the second sheet.
You only need one loop to perform the copy. Something like this should work.
Sub CopyValues()
Dim i As Long
For i = 8 To 15
Sheets("Übersicht GESAMT").Cells(6,i+35) = Sheets("P1-FR1").Cells(27,i)
Next i
End Sub

Compare two data ranges and copy entire row into worksheet VBA

i have found many very similar questions in the forum, but somehow nothing fits what i am looking for.
I have two ranges (a & b) which i'd like to compare and if values do not match, i'd like to copy the entire row to a predefined worksheet. The purpose is to find rows / values that have been changed vs. previous edit.
Dim a, b as range
Dim ws1,ws2,ws3 as worksheet
Dim last_row, last_row2 as integer 'assume last_row =15, last_row2=12
Dim i, j, k as integer
last_row=15
last_row2=12
' the orignal range is not massive, but at 500x 6 not small either
Set a=ws1.range("I5:S"& last_row)
Set b=ws2.range("H2:R"& last_row2)
I have seen different approaches when it comes to addressing each item of the range and don't know which would be quickest / best (loop or for each ).
The main if-statement would look something like this:
'assume i, j are the used as counters running across the range
k = 1
If Not a(i).value=b(j).value then
a(i)EntireRow.copy
ws3.row(k).paste
k = k + 1
end if
The solution cannot be formula based, as I need to have ws3 saved after each comparison.
Any help on this is much appreciated. Thanks!
If you have the ability to leverage Excel Spill Ranges, you can achieve what you want without VBA. Here's a web Excel file that shows all rows in first sheet where column A does not equal column b.
=FILTER(Sheet1!A:ZZ,Sheet1!A:A<>Sheet1!B:B)
If VBA is required, this routine should work. It's not optimal for handling values (doesn't use an array), but it gets it done.
Sub listDifferences()
Dim pullWS As Worksheet, pushWS As Worksheet
Set pullWS = Sheets("Sheet1")
Set pushWS = Sheets("Sheet2")
Dim aCell As Range
For Each aCell In Intersect(pullWS.Range("A:A"), pullWS.UsedRange).Cells
If aCell.Value <> aCell.Offset(0, 1).Value Then
Dim lastRow As Long
lastRow = pushWS.Cells(Rows.Count, 1).End(xlUp).Row
pushWS.Rows(lastRow + 1).Value = aCell.EntireRow.Value
End If
Next aCell
End Sub
This is the small for-loop I ended up using.
Thanks for your input!
For i = 1 To rOutput.Cells.Count
If Not rOutput.Cells(i) = rBackUp.Cells(i) Then
' Debug.Print range1.Cells(i)
' Debug.Print range2.Cells(i)
rOutput.Cells(i).EntireRow.Copy wsChangeLog.Rows(k)
k = k + 1
End If
Next i

Generate 1:N Sequence Array

I am currently trying to generate an array of sequential numbers (1:N) in order to populate a horizontal range ($C$6:N). When I use application.transpose my entire range is populated with 1, and when I don't use it the entire range is blank. I have attached my code below. pn is the range I want to populate and nop is the count of it. Thank you!
Best,
M
pn.Value = Array(Application.WorksheetFunction.Sequence(1, nop.Value))
I've put 2 options below,
Number one: (this seems to be what you want)
Sub generateSequence_MethodOne()
'Start at a cell and generate till a number
Dim pn As Range
Dim nop As Long
Set pn = Range("C6") 'starting cell
nop = 250 'number of entries
With pn
.value = 1
.AutoFill Destination:=pn.Resize(, nop), Type:=xlFillSeries
End With
' 'if you want to loop instead, then use this instead of the above
' For i = 1 To nop
' pn.Offset(, i - 1).value = i
' Next
End Sub
and number two, use this if you have known range that you want to fill, not knowing until what number
Sub generateSequence_MethodTwo()
'set a range and fill it with a sequence
Dim cell As Range
Dim n As Long
n = 1
For Each cell In Range("C6:Z6").Cells 'known range to fill
cell.value = n
n = n + 1
Next
End Sub
To use SEQUENCE() within VBA to fill from B9 to M9:
Sub FillUsingSequence()
Dim rng As Range
Set rng = Range("B9:M9")
rng.Value = Application.WorksheetFunction.Sequence(1, rng.Count, 1, 1)
End Sub

excel: Modify the values of "worksheet1" using values from "worksheet2" where name is the same

We have two worksheets.
Source worksheet is "profes"
Target worksheet is "primaria"
The data common to both worksheets is the name column.
ie: David Smith Weston appears in both worksheets.
We need to "lookup" each students name and paste values from "profes" to "primaria". I have most of the code working already BUT I don't know how to add the "lookup" part. As you can see it's wrong.
Sub Button1_Click()
Set Source = ActiveWorkbook.Worksheets("profes")
Set Target = ActiveWorkbook.Worksheets("primaria")
j = 1 ' Start copying to row 1 in target sheet
For Each c In Source.Range("N5:R1000") ' Do 100 rows
**If Source.Cells(j, "C").Value = Target.Cells(j, "A").Value** Then
Target.Cells(j, "N").Value = Source.Cells(j, "D").Value
j = j + 1
End If
Next c
End Sub
When comparing 2 ranges between 2 worksheets, you have 1 For loop, and replace the second loop with the Match function.
Once you loop over your "profes" sheet's range, and per cell you check if that value is found within the second range in "primaria" sheet, I used LookupRng, as you can see in the code below - you will need to adjust the range cording to your needs.
Code
Option Explicit
Sub Button1_Click()
Dim Source As Worksheet, Target As Worksheet
Dim MatchRow As Variant
Dim j As Long
Dim C As Range, LookupRng As Range
Set Source = ActiveWorkbook.Worksheets("profes")
Set Target = ActiveWorkbook.Worksheets("primaria")
' set up the Lookup range in "primaria" sheet , this is just an example, modify according to your needs
Set LookupRng = Target.Range("A2:A100")
For Each C In Source.Range("N5:R1000") ' Do 100 rows
If Not IsError(Application.Match(C.Value, LookupRng, 0)) Then ' Match was successfull
MatchRow = Application.Match(C.Value, LookupRng, 0) ' get the row number from "primaria" sheet where match was found
Target.Cells(C.Row, "N").Value = Source.Cells(MatchRow, "D").Value
End If
Next C
End Sub
Use the worksheet's MATCH function to locate names from the source column C in the target's column A.
Your supplied code is hard to decipher but perhaps this is closer to what you want to accomplish.
Sub Button1_Click()
dim j as long, r as variant
dim source as worksheet, target as worksheet
Set Source = ActiveWorkbook.Worksheets("profes")
Set Target = ActiveWorkbook.Worksheets("primaria")
with source
for j = 5 to .cells(.rows.count, "C").end(xlup).row
r=application.match(.cells(j, "C").value2, target.columns("A"), 0)
if not iserror(r) then
target(r, "D").resize(1, 5) = .cells(j, "N").resize(1, 5).value
end if
next j
end with
End Sub

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.

Resources