Copy data up to last row and column - vba

I am trying to copy all the data from multiple workbooks to a single workbook and distribute them to different worksheets.
How should I change the code below to automatically select the data up to the last row and column with value and copy them instead of declaring the range?
For i = 16 To ws.Range("I" & Rows.Count).End(xlUp).Row 'Sheet1 is MasterSheet
File = ws.Range("C" & i) & ws.Range("I" & i) 'File Location and Excel Name
Copy = ws.Range("U" & i) & ":" & ws.Range("V" & i) 'Range to be copied
Workbooks.Open File, 0, 1 'Open File as Read Only
Range(Copy).Copy
ThisWorkbook.Sheets(ws.Range("W" & i).Value).Cells(Rows.Count, 1).End(xlUp)(2).PasteSpecial 12 'Paste as Values only
ActiveWorkbook.Close False 'Close WorkBook without saving
Selection.Value = Selection.FormulaR1C1 'Force F2 and Enter selected range
Range("A1").Select
Next i

Your solution works fine, Paolo. I did quite a bit of research on the topic some time ago and I found out these ways are the fastest and simplest ones. I don't think Excel is very good with these things, so I have always tried to stick to the basics.
Just two comments:
I would not use .UsedRange.Copy, since it will return the range of cells that have ever been used.
I would also try to avoid using.select as much as possible. You can find examples on how to avoid it in
How to avoid using Select in Excel VBA

Related

Select one cell in each sheet to put it in another sheet

I am currently building a macro for Excel in order to read hundreds of txt files. For now everything work well and each txt file has its sheet.
I would like to take the value of a precise cell in each sheet (that would always be at the same place) and put it in a created sheet.
It is the value of the cell that I can't get to work, because I don't know how to say in VBA "this cell equal the value of this cell in this sheet, without any R[]C[]."
The naming of the sheets is precise and in function of a concatenated loop of 3 parameters.
Here is what i have done (the sheet result is created at the begining) :
'###loops k, j, i
ActiveSheet.Name = querie 'querie =k & j & i basically
Sheets("Results").Select
Range("A" & j - 1 & i).Select
ActiveCell.FormulaR1C1 = "= querie & "!" & "M1""
Next i
Next j
Next k
Hope it is clear,
Thanks a lot !

VBA - Copy / Paste to multiple columns with variable row start (array)

I'd like to shorten my code by putting multiple columns to one command.
I'm copying formulas from one row but specified columns and want to paste to another sheet in the same wksht. Just the row number is a variable. Maybe do this by an array?
As an example I'm pasting below not working code with only 3 columns.
Sub Copy()
Dim LastrowQ As Long
Dim LastrowR As Long
LastrowQ = Cells(Rows.Count, "B").End(xlUp).Row
LastrowR = LastrowQ + 1
Workbooks(Rep1).Worksheets("Formula").Range("A2, C2:F2, N2, V2:AD2").Copy
*Workbooks(Rep1).Worksheets("Report").Range("A" & LastrowR, "C" & LastrowR & ":F" & LastrowR, "N" & LastrowR, "V" & LastrowR & ":AD" & LastrowR).PasteSpecial Paste:=xlPasteFormulas*
End Sub
Could you please help to modify the code in paste part as it doesn't work right now? This would allow to make original code much shorter and hopefully faster.
What if I'd like to propagate function in second sheet from variable row till the specified row at the same time? ("A" & LastrowR & ":A" & LastrowS,...)
Thanks in advance

How would I go about searching for, and then importing values of a known structure from one excel file to another?

I have an excel file exported from another program with a bunch of data in it. From all of this data, I only need certain pieces of it. The data I need looks like this (with different numbers than 1.111 and 4.444):
C1: 1.111 4.444
C2: 1.111 4.444
...
C10: 1.111 1.111
The file has upwards of 30 sets of this data, all contained in columns A to C, except I do not know which rows they start at and end at. What I want to do is search the excel file for this data, and paste it into another file side-by-side (where C1's, C2's, etc. numbers line up in the same row.)
A YouTube tutorial gave me the following code that would be used to grab values at a known location in the file:
Sub ImportFluidData()
Dim FileNames As Variant
Dim i As Integer
Application.ScreenUpdating = False
Range("A1").Select
FileNames = Applcation.GetOpenFilename(FileFilter:="Excel Filter (*Analysis.xlsx), *.xlsx", Title:="Open Files(s)", MultiSelect:=True)
For i = 1 To UBound(FileNames)
Workbooks.Open FileNames(i)
Range(------------------------).Select
Selection.Copy
Windows("Fluid Properties.xlsm").Activate
Selection.PasteSpecial Paste:=xlPasteAll, Transpose:=True
Workbooks.Open FileNames(i)
ActiveWorkbook.Close SaveChanges:=False
ActiveCell.Offset(0, 1).Activate
Next i
End Sub
My problem is that instead of a known range, I need to replace Range(-------------).Select with a statement that searches for and selects the data descried above. How would I go about searching for and selecting such data? I quite literally just started using VBA today, so please try to avoid any VBA-specific jargo.
Thanks for the help!
Edit: the tutorial was for importing data at a known spot in multiple files, so that's why it's set up for looping through multiple files. I only need to search through one file, which will likely make the code a lot shorter.
If I understood well, you find yourself in a situation in which you have a uniform set of data that can be in a random position of a column (let's do the example with the column B):
If this is the case, then what you need to do is to find the start and the end point of your range. Which means:
Find your start point ##:
Dim startRow As Long: startRow = Range("B1").End(xlDown).Row
Find your end point
Dim endRow As Long: endRow = Range("B" & startRow).End(xlDown).Row
Select your range
Range("B" & startRow & ":B" & endRow).Select
The above will select the range B9:B14, but if there were 10 rather than 15 or 20 elements it would have found them as well.
Looping through the 30+ sets
#pnuts comment made me realized I had "partially" read the question, I report here his comment:
I think there may be 30+ instances all in the same two columns - ie maybe as the populated set you show (though possibly 10 rows rather than 6) and then 29+ other such sets, spaced apart by a variable number of blank rows.
In that case you should first of all define the last row of the sheet, i.e.
Dim lastRowOfSheet As Long: lastRowOfSheet = Range("Z1").End(xlDown).Row '<-- I assume in column Z there's nothing, please choose it accordingly
Hence, you need to Loop through the various datasets until you don't find the last one. which means:
'first static definitions outside the loop
Dim startRow As Long: startRow = Range("B1").End(xlDown).Row
Dim endRow As Long: endRow = Range("B" & startRow).End(xlDown).Row
Do While endRow <> lastRowOfSheet
'************SELECTING THE DATA SET**************
Range("B" & startRow & ":B" & endRow).Select
'do what you need to do after having selected the proper range
'***********************************************
'last re-definition before to loop again
startRow = Range("B" & endRow +1).End(xlDown).Row
endRow = Range("B" & startRow).End(xlDown).Row '<-- if this touches the end, it means it was the last dataset so we will go out of the loop
Loop

Calculating formulas in excel cells with VBA?

I have a series of Excel files all in the same format. The amount of data in each excel file differs. I am making a code that will loop through a folder and perform calculations with all excel files.
I am using the following code in VBA to determine the number of rows in an excel file:
i = .Cells(.Rows.Count, 2).End(xlUp).Row
I am using the following formula to perform calculations on a range of cells:
With .Range("D2:D" & i)
.Formula = "=Log(B2)"
End With
How would I calculate the sum of all values in the "D" column in the next available cell in D? This is how the formula would look in theory
j = i + 1
With .Range("D" & j)
.Formula = "=Sum(D2:D & i)"
End With
How would I use the D cell with the sum for future calculations? Lets say I wanted E1 "=(D2-$D$ & j)^2"
Sorry for the vague title, I didn't know how to describe this problem.
As follow up from comments, this one works:
With .Range("D" & j)
.Formula = "=SUM(D2:D" & i & ")"
End With

Excel VBA Copy and Paste Loop within Loop

I’ve been working on this VBA code for a while and since I’m a complete noob I feel like I haven’t gotten anywhere. I’ve been researching a ton, but can’t seem to combine answers to help with my scenario.
Essentially what I’m trying to do is grab data, line by line, from one worksheet and extrapolate it to another worksheet. I believe this will involve loops and I’m so new with VBA I don’t know how to do it.
Here’s the logic I’m attempting:
For each row on worksheet 1, I would like to perform 3 different copy and paste activities to worksheet 2 and then it will loop down to the next row on sheet1 and do the 3 activities and so on. This will continue downwards until column A is blank in sheet1. Sheet1 data starts at A3 and sheets2 paste area starts at A2.
The first activity is to copy cells F3,D3,A3, and H3 (in that order so F3 will be A2, D3 will be B2 etc) from sheet 1 to sheet 2 to A2,B2,C2, etc. A destination functions can’t be used because I need just the values and no other formats—one of the many issues I’ve ran in to.
The next activity is to copy cells F3,D3,A3 and I3 from sheet 1 to sheet2 pasted below the previous copy and paste—again no formats just values. Also to note, some of these may be blank (except A column) but I still need that row there with at least column A data—this goes to say with all these activities.
The third activity is to copy and paste sheet1’s F3,D3, and A3 a certain number of times referencing K3’s number—and each copy and paste will be in the next available blank cell. So if the number in K3 it will look like it created 3 rows in sheet2—totaling 5 rows on sheet2 since activity1 and 2 each create their own row.
After these three activities are completed for row 3 on sheet 1, it will then move to row 4 and do the previous three activities and paste to sheet2. And again it will be pasting no formats and in the next blank row on sheet 2. Also again, this loop will stop once the cell in Column A is blank.
Below is my incomplete code. I don’t even think it will help one bit and it would probably be better not to even look at it. I’ve just started to get frustrated since I can’t even do a simple copy and paste, yet alone loops within loops. I also haven’t even started on my third activity. I greatly appreciate it!
Sub copyTest3()
Dim proj As Range, release As Range, pm As Range, lead As Range, coord As Range
Dim leadCopy As Range, coordCopy As Range
Dim i As Range
Set proj = Range("A3", Range("A3").End(xlDown))
Set release = Range("D3", Range("D3").End(xlDown))
Set pm = Range("F3", Range("F3").End(xlDown))
Set lead = Range("H3", Range("H3").End(xlDown))
Set coord = Range("I3", Range("I3").End(xlDown))
Set leadCopy = Union(pm, release, proj, lead)
Set coordCopy = Union(pm, release, proj, coord)
For i = 1 To Range(ActiveSheet.Range("A3"), ActiveSheet.Range("A3").End(xlDown))
leadCopy.Copy
Sheets("Sheet2").Activate
Range("A2").Select
ActiveSheet.PasteSpecial xlPasteValues
Application.CutCopyMode = False
Sheets("Sheet1").Activate
coordCopy.Copy
Sheets("Sheet2").Activate
Range("A2").Select
ActiveSheet.PasteSpecial xlPasteValues
Next i
End Sub
There are many ways to do this, and some are more efficient than others. My solution may not be the most efficient, but hopefully it will be easy for you to understand so that you can learn.
It's very difficult to understand what you're attempting to do in activity three, so I wasn't able to provide a solution to that step. Use my code as a template for step three and if you run into issues, feel free to leave a comment.
Notice that I don't use .Activate, .Select, or .Copy in this code. .Activate and .Select are huge efficiency killers, and they make it easier for your code to "break," so avoid using them when possible. .Copy isn't necessary when working with values or formulas and will also slow your code down.
Untested
Sub testLoopPaste()
Dim i As Long
Dim ii As Long
Dim i3 as Long
Dim LastRow As Long
Dim wb As Workbook
Dim sht1 As Worksheet
Dim sht2 As Worksheet
Set wb = ThisWorkbook
Set sht1 = wb.Sheets("Sheet1")
Set sht2 = wb.Sheets("Sheet2")
'Find the last row (in column A) with data.
LastRow = sht1.Range("A:A").Find("*", searchdirection:=xlPrevious).Row
ii = 2
'This is the beginning of the loop
For i = 3 To LastRow
'First activity
sht2.Range("A" & ii) = sht1.Range("F" & i).Value
sht2.Range("B" & ii) = sht1.Range("D" & i).Value
sht2.Range("C" & ii) = sht1.Range("A" & i).Value
sht2.Range("D" & ii) = sht1.Range("H" & i).Value
ii = ii + 1
'Second activity
sht2.Range("A" & ii) = sht1.Range("F" & i).Value
sht2.Range("B" & ii) = sht1.Range("D" & i).Value
sht2.Range("C" & ii) = sht1.Range("A" & i).Value
sht2.Range("D" & ii) = sht1.Range("I" & i).Value
ii = ii + 1
'Third activity
For i3 = 1 To sht1.Range("K" & I)
sht2.Range("A" & ii) = sht1.Range("F" & i).Value
sht2.Range("B" & ii) = sht1.Range("D" & i).Value
sht2.Range("C" & ii) = sht1.Range("A" & i).Value
ii = ii + 1
Next i3
Next i
End Sub
The way I usually approach copying data between sheets in Excel is to create source range and destination range objects, each range referring to just one row. When I want to move on to the next row, I use Offset to return a range offset to the next row.
Since the ranges only refer to one row, you can index them with an integer to get the cells in the row. E.g. if cursor refers to columns A through D in row 3, cursor(3) will give you the cell C3.
Dim src_cursor As Range
Dim dest_cursor As Range
Set src_cursor = ActiveSheet.Range("A3:I3")
Set dest_cursor = Sheets("Sheet2").Range("A2:D2")
'' Loop until column A is empty in source data
Do Until IsEmpty(src_cursor(1))
dest_cursor(1) = src_cursor(6) '' copy F -> A
dest_cursor(2) = src_cursor(4) '' copy D -> B
'' and so on
'' move cursors to next row
Set src_cursor = src_cursor.Offset(1, 0)
Set dest_cursor = dest_cursor.Offset(1, 0)
Loop
Also, this might be getting a little off topic, but it's a better practice to use an Enum to name the column numbers instead of hardcoding them like I did here.