I am very new to the world of code and VBA - but I am having a lot of fun learning and exploring just how powerful these tools are.
I am working on pulling data from one worksheet and placing it in my "master roadmap" spreadsheet. Just a little background: In the master sheet, I have been inserting data in columns A-S; however, column 'A' is reserved on the worksheet I am pulling data from so this is why the range below is set as Range (B:T). I am scanning columns by B:T; pulling that data and inserting it in columns A:S of my master sheet. However, my boss wants to make a change reserve columns "U' through "AD" on her spreadsheet.
So I would like to have VBA scan through two ranges "B:T" and then "AE:BB" (skipping U:AD) and then plug that information in my "master sheet" into columns "A:AQ."
In short, I am hoping all I have to do is insert a 'second range' in the code below to complete this task. Any help would be greatly appreciated!
Sub LoopThroughDirectory()
Dim MyFile As String
Dim erow As Double
Dim lastrow As Double
Dim MasterWorkbook As Workbook
Dim TempWorkbook As Workbook
Dim DirPath As String
'Clear current data
Sheet1.Visible = xlSheetVisible
Sheet2.Visible = xlSheetHidden
Sheet3.Visible = xlSheetHidden
Sheet1.Activate
lastrow = ActiveWorkbook.ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
If lastrow > 1 Then
Range("A2:AQ" & lastrow).Select
Selection.Clear
End If
DirPath = "C:\Users\rspktcod\Documents\RoadMap Test\Roadmaps\"
MyFile = Dir(DirPath)
Set MasterWorkbook = ActiveWorkbook
Do While Len(MyFile) > 0
Set TempWorkbook = Workbooks.Open(DirPath & MyFile)
lastrow = ActiveWorkbook.ActiveSheet.Range("B" & Rows.Count).End(xlUp).Row
Range("B2:T" & lastrow).Copy
MasterWorkbook.Activate
erow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
ActiveSheet.Paste Destination:=Worksheets("Roadmap").Range(Cells(erow, 1), Cells(erow, 43))
TempWorkbook.Activate
Application.CutCopyMode = False
ActiveWorkbook.Close
MyFile = Dir
Loop
End Sub
The short answer is, yes, you can just add another range.
Here is the long answer (with a few improvments...):
Sub LoopThroughDirectory()
Dim DirPath As String, MyFile As String
Dim LastRow As Long, eRow As Long ' Rows should be Long
'Dim MasterWorkbook As Workbook
Dim TempWorkbook As Workbook
Dim DestSheet As Worksheet
'Clear current data
Sheet1.Visible = xlSheetVisible
Sheet2.Visible = xlSheetHidden
Sheet3.Visible = xlSheetHidden
' Added DestSheet to be more clear, since Sheet1 is specific to this file.
' It also make the code more portable, if you want to change it to a different sheet, in a different file.
Set DestSheet = Sheet1
' MasterWorkbook is a good idea, but not required here.
'Set MasterWorkbook = ThisWorkbook 'ActiveWorkbook
LastRow = DestSheet.Range("A" & Rows.Count).End(xlUp).Row
If LastRow > 1 Then Range("A2:AQ" & LastRow).Clear
DirPath = "C:\Users\rspktcod\Documents\RoadMap Test\Roadmaps\"
' Added "*.xls*" to limit it to just Excel Workbooks
' You don't want to process the current and previous folders, which come across as "." & ".."
MyFile = Dir(DirPath & "*.xls*")
Do While Len(MyFile) > 0
Set TempWorkbook = Workbooks.Open(DirPath & MyFile)
' Used [TempWorkbook.ActiveSheet].Rows.Count, instead of just Rows.Count to be more percise
With TempWorkbook.ActiveSheet ' <-- Not a fan of Activesheet here
LastRow = .Range("B" & .Rows.Count).End(xlUp).Row
If LastRow > 1 Then
' Excel 2003-/2007+ have different number of rows, so be specific about what sheet to get the Rows from
eRow = DestSheet.Cells(DestSheet.Rows.Count, 1).End(xlUp).Row + 1
.Range("B2:T" & LastRow).Copy Destination:=DestSheet.Cells(eRow, 1)
.Range("AE2:BB" & LastRow).Copy Destination:=DestSheet.Range("T" & eRow)
End If
TempWorkbook.Close False ' Added SaveSanges = False for good measure
MyFile = Dir
End With
Loop
End Sub
Related
I am cycling through all the Green Tabs in a workbook. When I come to a row of data where there is no value in Column G, I select that row, cut it, and open another workbook entitled "Unpaid AR." In that workbook, I find the first unused row, and Paste. Everything functions properly except for the Paste - nothing pastes, and I have tried several different techniques. Any ideas what could be going wrong?
Public Sub CutNPaste()
Dim ws As Worksheet
Dim ARRange As String
Dim ARFilePath As String
Dim ARcell As Range
Dim CopyRange As String
Dim i As Integer
Dim varRange As String
ARFilePath = "Unpaid AR.xlsx"
For Each ws In ThisWorkbook.Worksheets
ws.Activate
If ws.Tab.ColorIndex = 10 Then 'If Tab is Green, Then...
ReportRows = ActiveSheet.UsedRange.Rows.Count 'Get how many rows in the report
Let ARRange = "G" & "2" & ":" & "G" & ReportRows 'Range to Inspect for Blanks
i = 2
For Each ARcell In Range(ARRange)
Let CopyRange = "A" & i & ":" & "I" & i 'Set the copy range when blank is encountered
If ARcell.Value = "" Then
Range(CopyRange).Select
Selection.Cut
Workbooks.Open ARFilePath 'Open the Unpaid AR workbook
Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Select 'Find the first open row
ActiveSheet.Paste 'This is where NOTHING happens
Workbooks("Unpaid AR.xlsx").Close SaveChanges:=True 'Save and close destination wkbk
Application.CutCopyMode = False
End If
i = i + 1
Next ARcell
End If
Next ws
End Sub
i change a little bit...
Public Sub CutNPaste()
Dim ws As Worksheet
Dim ARRange As String
Dim ARFilePath As String
Dim ARcell As Range
Dim CopyRange As Range
Dim i As Integer
Dim varRange As String
Dim wkbTarget As Workbook
Dim ReportRows As Long
ARFilePath = ThisWorkbook.Path & "\Unpaid AR.xlsx"
Set wkbTarget = Workbooks.Open(ARFilePath) 'Open the Unpaid AR workbook
For Each ws In ThisWorkbook.Worksheets
If ws.Tab.ColorIndex = 10 Then
ReportRows = ws.UsedRange.Rows.Count
For i = ReportRows To 2 Step -1
Set CopyRange = ws.Range("A" & i & ":" & "I" & i)
If ws.Cells(i, 7).Value = "" Then
CopyRange.Cut Destination:=wkbTarget.Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
Application.CutCopyMode = False
End If
Next i
End If
Next ws
wkbTarget.Close SaveChanges:=True 'Save and close destination wkbk
End Sub
BR
Bernd
I am trying to copy Range(A14:N26) from every closed workbook in a folder on my desktop and paste them into the current worksheet (which is my master worksheet). The code does grab the right range of data but struggles with the pasting part.
It is supposed to SpecialPaste the code as there are formulas in the cells and I want to only copy what is visible in the cells. (Note: The outcome of some of of the formulas are words, the outcome of others are numbers)
Option Explicit
Sub CopySheetFromFileOnDesktop()
Dim wkbDest As Workbook
Dim wksDest As Worksheet
Dim wkbSource As Workbook
Dim wksSource As Worksheet
Dim MyPath As String
Dim MyFile As String
Dim SheetIndex As Integer
Application.ScreenUpdating = False
Set wkbDest = ThisWorkbook
Set wksDest = wkbDest.Worksheets("Master Sheet")
SheetIndex = 1
MyPath = "C:\Users\.."
If Right(MyPath, 1) <> "\" Then MyPath = MyPath & "\"
MyFile = Dir(MyPath & "*.xlsm")
Do While Len(MyFile) > 0
Set wkbSource = Workbooks.Open(MyPath & MyFile)
Set wksSource = wkbSource.Worksheets("Sheet containing the info")
If WorksheetFunction.CountA(wkbSource.Sheets("Sheet containing the
info").Range("A14:L26")) <> 0 Then
'lRow = .Range("L" & Rows.Count).End(xlUp).Row 'UNSURE HOW TO LAST ROW
wkbSource.Sheets("Sheet containing the info").Range("A14:L26").Copy
wkbDest.Range("A:L" & Rows.Count).End(xlUp)(2).PasteSpecial _
Paste:=xlPasteValues 'PASTESPECIAL SEEMS TO BE THE PROBLEM
wkbSource.Close savechanges:=False
Application.CutCopyMode = False
Else
End If
Loop
Application.ScreenUpdating = True
MsgBox "Completed...", vbInformation
End Sub
when running the macro it shows this bug: Runtime Error 438: Object does not support Properties or Method. And the debugger highlights the line where I define where to paste the copied range
The code row with your destination range needs an optimization:
You erroneously used wkbDest instead of wksDest
A partly row can not be addressed by Range("A:L" & 1000)
If you use Rows.Count without a leading dot, then the ActiveSheet is assumed
First attempt
wksDest.Cells(wksDest.Rows.Count, 1).End(xlUp).Offset(1, 0).Resize(1, 12).PasteSpecial _
Paste:=xlPasteValues
The destination is built as follows:
Find the last used cell in column 1 (e. g. A100)
Offset it to the next row (e. g. A101)
Resize it to a new dimension of 1 row and 12 columns (e. g. A101:L101)
Second attempt:
If you paste, it is only necessary to address the first cell of the destination. So following should also work:
wksDest.Cells(wksDest.Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial _
Paste:=xlPasteValues
Recommendation:
If you define source and destination range of the same size, you can just assign their values (simular to PastSpecial of values, but faster):
wksDest.Cells(wksDest.Rows.Count, 1).End(xlUp).Offset(1, 0).Resize(1, 12).Value = _
wksSource.Range("A14:L26").Value
I'm running into an issue with looping through tabs in my workbook. The code I am working on is supposed to perform the following:
Loop through all worksheets except the ones titled "BOAT" & "Data"
Select cell "A2" (A2 contains the value to filter)in each worksheet that it is looping through and use it as the autofilter value for the "Data" tab
Then copy and paste the filtered data into the respective tab that is looping through.
The issue I am running into is my code isn't picking up on the active sheet in the loop. Is there a way to create a variable to for the worksheet currently being looped through?
Code below. Thank you!
Sub updatedata()
Dim ws As Worksheet
Dim wsheet2 As Worksheet
For Each ws In ActiveWorkbook.Worksheets
If ws.name <> "BOAT" And ws.name <> "Data" Then
Call filter1
End If
Next ws
End Sub
Sub filter1()
Dim lastrow As Long
Dim lastrow2 As Long
Dim wSheet As Worksheet
Dim rInput As String
Application.DisplayAlerts = False
Set wSheet = ActiveSheet
rInput = wSheet.Range("A2").Value
Sheets("Data").Activate
lastrow = Range("A" & Rows.Count).End(xlUp).Row
ActiveSheet.Range("A1:Y" & lastrow).AutoFilter field:=4, Criteria1:="=*" & rInput & "*"
lastrow2 = Range("G" & Rows.Count).End(xlUp).Row
Range("G1:G" & lastrow2).Copy
wSheet.Activate
Range("A4").PasteSpecial xlPasteValues
Rows(4).EntireRow.Delete
Application.DisplayAlerts = True
End Sub
"Is there a way to create a variable to for the worksheet currently being looped through?"
Yes, using a Worksheet variable as an argument in filter1.
Avoid using Activate or making Range calls without specifying the Worksheet.
Sub updateData()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
If ws.Name <> "BOAT" And ws.Name <> "Data" Then
filter1 ws 'no need to use Call
End If
Next ws
End Sub
By passing ws as an Argument to filter1, all Range calls are fully qualified with the Worksheet in question. This is easily accomplished with a With...End With block - note the period . in front of .Range("A2").Value, .Range("A4"), etc - equivalent to myWs.Range("A2").Value, myWs.Range("A4")..., etc.
Sub filter1(myWs As Worksheet)
Dim lastRow As Long, lastRow2 As Long
Dim rInput As String
Application.DisplayAlerts = False
With myWs
rInput = .Range("A2").Value
With .Parent.Sheets("Data")
lastRow = .Range("A" & .Rows.Count).End(xlUp).Row
.Range("A1:Y" & lastRow).AutoFilter field:=4, Criteria1:="=*" & rInput & "*"
lastRow2 = .Range("G" & .Rows.Count).End(xlUp).Row
.Range("G1:G" & lastRow2).Copy
End With
.Range("A4").PasteSpecial xlPasteValues
.Rows(4).EntireRow.Delete
End With
Application.DisplayAlerts = True
End Sub
I want to copy multiple range to another workbook. I have the code below. How can I replace the number 1000 by iLastRow
iLastRow = Sh.Range("B" & Rows.Count).End(xlUp).Row
sh.Range("A3:AG1000, AL3:EJ1000").Select
Selection.Copy
Try the code below, explanation inside the code as comments:
Option Explicit
Sub CopyMultipleRanges()
Dim iLastRow As Long
Dim sh As Worksheet
Dim MultiRng As Range
Set sh = ThisWorkbook.Worksheets("Sheet1") ' <-- change to your sheet's name
With sh
iLastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
' use the union to set a range combined from multiple ranges
Set MultiRng = Union(.Range("A3:A" & iLastRow), .Range("AL3:EJ" & iLastRow))
End With
' copy the range, there's no need to select it first
MultiRng.Copy
End Sub
Another question is how you want to paste the merged reanges that have a gap in the middle.
The Union method is a solution to this problem. but it also has its cons
The union range should be the same first row and last row.
On the other hand, you can just select the first cell to paste.
you can alway do like this. the main point here is the row number should be the same. here I synchronize both range with the same variable. in your case, change to last cell.
j=1
i = 4
Set MultiRng = Union(Range("A" & j & ":B" & i), Range("D" & j & ":E" & i))
Change Range params from this:
iLastRow = Sh.Range("B" & Rows.Count).End(xlUp).Row
sh.Range("A3:AG1000, AL3:EJ1000").Select
To:
iLastRow = Sh.Range("B" & Rows.Count).End(xlUp).Row
sh.Range("A3:AG" & iLastrow &", AL3:EJ" & iLastRow).Select
Since with multiple selection Copy will not work. You may need to call it twice in your case. (as per suggestion by #YowE3K)
sh.Range("A3:AG" & iLastrow).Select
Selection.Copy
sh.Range("AL3:EJ" & iLastrow).Select
Selection.Copy
Option Explicit
Sub import_APVP()
Dim master As Worksheet, sh As Worksheet
Dim wk As Workbook
Dim strFolderPath As String
Dim selectedFiles As Variant
Dim iFileNum As Integer, iLastRowReport As Integer, iNumberOfRowsToPaste As Integer
Dim strFileName As String
Dim iCurrentLastRow As Integer, iRowStartToPaste As Integer
Dim MultiRng As Range
Dim startTime As Double
getSpeed (True)
Set master = ActiveWorkbook.ActiveSheet
strFolderPath = ActiveWorkbook.Path
ChDrive strFolderPath
ChDir strFolderPath
Application.ScreenUpdating = False
'On Error GoTo NoFileSelected
selectedFiles = Application.GetOpenFilename( _
filefilter:="Excel Files (*.xls*),*.xlsx*", MultiSelect:=True)
For iFileNum = LBound(selectedFiles) To UBound(selectedFiles)
strFileName = selectedFiles(iFileNum)
Set wk = Workbooks.Open(strFileName)
For Each sh In wk.Sheets
If sh.Name Like "DATA*" Then
With sh
iLastRowReport = .Range("D" & .Rows.Count).End(xlUp).Row
iNumberOfRowsToPaste = iLastRowReport + 2 - 1
'.Range("A3:AG" & iLastRowReport & " , AL3:EJ & iLastRowReport").Select
' Selection.Copy
Set MultiRng = Union(.Range("A3:AG" & iLastRowReport), .Range("AL3:EJ" & iLastRowReport))
'you delete the 3 in range ("AL:EJ....) that make your code not work.
MultiRng.Copy
With master
iCurrentLastRow = .Range("B" & .Rows.Count).End(xlUp).Row
iRowStartToPaste = iCurrentLastRow + 1
'.Activate ' <-- not needed
.Range("A" & iRowStartToPaste).PasteSpecial xlPasteAll
'ActiveSheet.Paste <-- not needed
End With
End With
End If
Next sh
wk.Close
Next
getSpeed (False)
Application.ScreenUpdating = True
NoFileSelected:
End Sub
I am new at creating macros. Only created 5 of them for specific problems.
Could someone help me amend the below macro? I found it on the internet, I amended it to my preferences. But still there is room from improvement. Anyways it works perfectly except for the below.
There would be a lot of files in folder. Each file contains a tab named "PIVOT", where the format are the same, but the amount of data are different.
The range is in the PIVOT tab are from A to AM columns. They start at row 15. And I would only need those lines where the "closed" indication is not written (Status column is in AJ column). I want all of these rows to be copied into a master file under each other. The amount of rows varies greatly - like 0 to 200 depending on the open items.
Secondly, can someone tell me a book, that could be purchased so that I could evolve my knowledge?
Thank For your help!
Tibor
Sub Import_to_Master()
Dim sFolder As String
Dim sFile As String
Dim wbD As Workbook, wbS As Workbook
Application.ScreenUpdating = False
Set wbS = ThisWorkbook
sFolder = wbS.Path & "\"
sFile = Dir(sFolder)
Do While sFile <> ""
If sFile <> wbS.Name Then
Set wbD = Workbooks.Open(sFolder & sFile) 'open the file; add condition to
' >>>>>> Adapt this part
wbD.Sheets("PIVOT").Range("A15:AM26").Copy
wbS.Activate
Sheets("Template").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
Application.CutCopyMode = False
' >>>>>>
wbD.Close savechanges:=True 'close without saving
End If
sFile = Dir 'next file
Loop
Application.ScreenUpdating = True
End Sub
you may be after this:
' >>>>>> Adapted part
With wbD.Sheets("PIVOT")
With .Range("AM14", .Cells(.Rows.count, 1).End(xlUp)) '<--| reference its column "A:AM" range from row 14 down to column "A" last not empty row
.AutoFilter Field:=36, Criteria1:="<>closed" '<--| filter referenced range on its 36th column (i.e. column "AJ") with values different from "closed"
If Application.WorksheetFunction.Subtotal(103, .Resize(, 1)) > 1 Then
.Resize(.Rows.count - 1).Offset(1).SpecialCells(xlCellTypeVisible).Copy
Sheets("Template").Range("A" & Rows.count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
Application.CutCopyMode = False
End If
End With
.AutoFilterMode = False
End With
' >>>>>>
If you need to check each row for a certain cell value use something like the following. This will loop through line by line checking for lines that don't say "Closed".
Dim sFolder As String, sFile As String, wbD As Workbook, wbS As Workbook
Dim lastRowS As Integer, lastRowD As Integer
Application.ScreenUpdating = False
Set wbS = ThisWorkbook
sFolder = wbS.Path & "\"
sFile = Dir(sFolder
lastRowS = Sheets("Template").Range("A" & Rows.Count).End(xlUp).Row + 1
Do While sFile <> ""
If sFile <> wbS.Name Then
Set wbD = Workbooks.Open(sFolder & sFile) 'open the file; add condition to
lastRowD = wbD.Sheets("PIVOT").Range("A" & Rows.Count).End(xlUp).Row
For i = 15 To lastRowD
If Cells(i, 3) <> "Closed" Then 'change 3 to whatever column number has Closed in
wbD.Sheets("PIVOT").Rows(i).EntireRow.Copy
wbS.Sheets("Template").Cells(lastRowS, 1).PasteSpecial xlPasteValues
lastRowS = lastRowS + 1
End If
Next i
Application.CutCopyMode = False
' >>>>>>
wbD.Close savechanges:=False 'close without saving
End If
sFile = Dir 'next file
Loop
Application.ScreenUpdating = True
End Sub