Optimize Excel VBA Macro for Copy-PasteValues - excel

I'm new in Excel-VBA and I need to improve my macro performance. I have a macro that searches an excel, opens it, then goes through every sheet and copy-pastevalues for all cell with a specific color (yellow). Finally saves and closes the excel. In addition, excels sheets are locked and only those yellow cells are editable. This should be done for a list of excel that I indicate in a main template from where I call the macro. The problem is that it takes a lot of time and even gets blocked when the number of excels is more than 3.
I paste my code below and hope anyone can help. Thanks!
Sub Button1_Click()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim filePath As String
Dim rng As Range
Dim cel As Range
Dim cartera As String
Dim plantilla As String
Dim wb As Workbook
Dim ws As Worksheet
Dim obj_Cell As Range
filePath = Application.ThisWorkbook.Path
Range("B9").Select
Set rng = Application.Range(Selection, Selection.End(xlDown))
For Each cel In rng.Cells
cartera = cel.Value
plantilla = cel.Offset(0, 1).Value
If cartera = vbNullString Or plantilla = vbNullString Then
GoTo Saltar
End If
Application.StatusBar = "Ejecutando Cartera: " & cartera & ", Plantilla: " & plantilla
Set wb = Workbooks.Open(filePath & "\" & cartera & "\" & plantilla, UpdateLinks:=3)
For Each ws In wb.Worksheets
If ws.Name <> "Index" And ws.Name <> "Instructions" And ws.Name <> "Glossary" Then
Worksheets(ws.Name).Activate
For Each obj_Cell In Range("A1:DW105")
With obj_Cell
If obj_Cell.Interior.Color = RGB(255, 255, 153) Then
obj_Cell.Select
If obj_Cell.MergeCells = True Then
obj_Cell.MergeArea.Select
End If
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=True, Transpose:=False
If obj_Cell.MergeCells = True Then
If obj_Cell.MergeArea(1).Value = vbNullString Then
obj_Cell.MergeArea.Cells(1, 1).Select
Selection.ClearContents
End If
Else
If obj_Cell.Value = vbNullString Then
obj_Cell.ClearContents
End If
End If
End If
End With
Next obj_Cell
Range("A1").Select
End If
Next ws
Sheets(1).Select
wb.Close SaveChanges:=True
Saltar:
Next cel
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.StatusBar = False
End Sub

Untested- just some "start" ideas for you to use (e.g. no selections, using arrays, fix With statement, no GoTo). I don't understand the logic behind clearing vbNullstring. If it is necessary adapt the code in your way.
I would also suggest opening files with displayalerts on because of few potential problems (e.g. "serious error occur last time file was opened" would hangs your macro)
Sub Button1_Click()
With Application
.ScreenUpdating = False
.StatusBar = True
End With
' If possible change this reference
' from active sheet to sheet's name/codename/index
Dim activeWs As Worksheet
Set activeWs = ActiveSheet
Dim filePath As String
filePath = Application.ThisWorkbook.Path
Dim wb As Workbook
Dim ws As Worksheet
Dim obj_Cell As Range
' range definition
' if lastRow not working change to yours xlDown
' if possible End(xlUp) method is more reliable
Dim rng As Range
Dim lastRw As Long
With activeWs
lastRw = .Cells(.Cells.Rows.Count, "B").End(xlUp).Row
Set rng = .Range("B9:B" & lastRw)
End With
' read whole ranges at once
' instead of offset it is possible also to read
' cartera and plantilla at the same time to 2Darray
Dim cartera As Variant
cartera = Application.Transpose(rng.Value2)
Dim plantilla As Variant
plantilla = Application.Transpose(rng.Offset(, 1).Value2)
' main loop
Dim i As Long
For i = 1 To UBound(cartera)
If cartera(i) <> vbNullString Or plantilla(i) <> vbNullString Then
Application.StatusBar = "Ejecutando Cartera: " & cartera(i) & ", Plantilla: " & plantilla(i)
Set wb = Workbooks.Open(filePath & "\" & cartera(i) & "\" & plantilla(i), UpdateLinks:=3)
For Each ws In wb.Worksheets
If ws.Name <> "Index" And ws.Name <> "Instructions" And ws.Name <> "Glossary" Then
For Each obj_Cell In ws.Range("A1:DW105")
With obj_Cell
If .Interior.Color = RGB(255, 255, 153) Then
.Value2 = .Value2
' I commented this part beacuse it does not make sense for me...
' If .MergeCells Then
' If .MergeArea(1).Value = vbNullString Then _
.MergeArea.Cells(1, 1).ClearContents
' Else
' If .Value = vbNullString Then .ClearContents
' End If
End If
End With
Next obj_Cell
End If
Next ws
' I would place diplayalerts off here because of potential problems
' with opening files
' if problem occurs it can macro hangs
Application.DisplayAlerts = False
wb.Close SaveChanges:=True
Application.DisplayAlerts = True
End If
Next i
With Application
.ScreenUpdating = True
.DisplayAlerts = True
.StatusBar = False
End With
End Sub

Related

Use a Cell Value as a Worksheet Name

I want to paste data from a Workbook to another workbook into a sheet which has the name of a cell value. I don't know if that's possible, but I'm struggling with that and I can't find anything similar on internet.
This is my code so far:
'This creates a sheet from a range and gives it the name of the cell so it can be from 5 to 10 sheets'
For Each Cell In Range("G5:G15")
If Cell.Value <> "" Then
Sheets.Add(After:=Sheets(Sheets.Count)).Name = Cell.Value
End If
Next
After other code which is not important, I made this:
Dim AutoFilterRng As Range
Dim WorksheetName As String
For Each Cell In Range("H5", Range("H5").End(xlDown))
If Cell.Value <> "" Then
WorksheetName = Cell.Offset(0, -1).Value
Workbooks.Open MJFile 'Opens the file where data I want to copy
ActiveSheet.Range("A:U").AutoFilter Field:=12, Criteria1:="*" & Cell.Value 'Filters depending on the cell value
With ActiveSheet.AutoFilter.Range
Set AutoFilterRng = .Offset(1, 0).Resize(.Rows.Count - 1, 1).SpecialCells(xlCellTypeVisible)
End With
ActiveSheet.AutoFilter.Range.Offset(1, 0).Resize(ActiveSheet.AutoFilter.Range.Count - 1).Copy
Workbooks.Open WBOR 'Opens the Workbook where I want to paste data
Worksheets(WorksheetName).Range("A1").Paste 'This gives an error and it is where I would like to paste my data
Workbooks.Open MJFile
AutoFilterMode = False
End If
Next
Thank you very much in advance
If you want to see the whole code:
Sub AddTO()
Application.Calculation = xlManual
Application.ScreenUpdating = False
Application.EnableEvents = False
'------------------------------------------------------------------------------------------------------------------------------------------------------'
'Open TO FIle'
Dim WBOR As String
Dim MJFile As String
Dim TOFile As String
Dim Path As String
WBOR = ActiveWorkbook.Path & "\" & ActiveWorkbook.Name
'On Error GoTo Fin
MsgBox "Choose Bear File"
With Application.FileDialog(msoFileDialogFilePicker)
.Filters.Clear
.AllowMultiSelect = False
If .Show = -1 Then
TOFile = .SelectedItems(1)
End If
End With
Workbooks.Open TOFile
'Filter Bear File to Only Necessary TO'
Dim NameRng As Range
Dim TORng As Range
Dim DeliveryWeek As String
Dim i As Long
Workbooks.Open WBOR
Set NameRng = Worksheets("Tasks_Orders_Info").Range("E5", Range("E5").End(xlDown))
Workbooks.Open TOFile
Set TORng = Worksheets("WS Lead Plan1").Range("G2", Range("G2").End(xlDown))
Workbooks.Open WBOR
DeliveryWeek = "*Week_" & Worksheets("Tasks_Orders_Info").Range("C5").Value & "*"
Workbooks.Open TOFile
For i = TORng.Count To 1 Step -1
Select Case True
Case TORng.Cells(i) Like DeliveryWeek
Case Else
TORng.Cells(i).EntireRow.Delete
End Select
Next i
'Add TO to MJ File'
Workbooks.Open WBOR
TORng.Copy
Worksheets("Tasks_Orders_Info").Range("G5").PasteSpecial xlPasteValues
Worksheets("Tasks_Orders_Info").Range("G5").End(xlDown).PasteSpecial xlPasteValues
Workbooks.Open TOFile
ActiveWorkbook.Close SaveChanges:=False
Range("H5:H15") = "=IF(ISERR(FIND("" "",Table2[#Coder])),"""",LEFT(Table2[#Coder],FIND("" "",Table2[#Coder])-1))"
Range("I5:I15") = "=MID(Table2[#Coder],SEARCH("" "",Table2[#Coder],1)+1,SEARCH("" "", Table2[#Coder],SEARCH("" "",Table2[#Coder],1)+1)-SEARCH("" "",Table2[#Coder],1))"
Range("J5:J15") = "=IFERROR(MID(Table2[#Coder],FIND("" "",Table2[#Coder],FIND("" "",Table2[#Coder])+1)+1,FIND("" "",Table2[#Coder],FIND("" "",Table2[#Coder],FIND("" "",Table2[#Coder])+1)+1)-FIND("" "",Table2[#Coder],FIND("" "",Table2[#Coder])+1)-1),"""")"
Form1 = "=IF(OR(ISNUMBER(FIND(H5,G5,1)),ISNUMBER(FIND(I5,G5,1)),IF(J5="""",FALSE,ISNUMBER(FIND(J5,G5,1)))),LEFT(G5,FIND("" "",G5,1)-3),IF(OR(ISNUMBER(FIND(H5,G6,1)),ISNUMBER(FIND(I5,G6,1)),IF(J5="""",FALSE,ISNUMBER(FIND(J5,G6,1)))),LEFT(G6,FIND("" "",G6,1)-3),IF(OR(ISNUMBER(FIND(H5,G7,1)),ISNUMBER(FIND(I5,G7,1)),IF(J5="""",FALSE,ISNUMBER(FIND(J5,G7,1)))),LEFT(G7,FIND("" "",G7,1)-3),IF(OR(ISNUMBER(FIND(H5,G8,1)),ISNUMBER(FIND(I5,G8,1)),IF(J5="""",FALSE,ISNUMBER(FIND(J5,G8,1)))),LEFT(G8,FIND("" "",G8,1)-3),IF(OR("
Form2 = "ISNUMBER(FIND(H5,G9,1)),ISNUMBER(FIND(I5,G9,1)),IF(J5="""",FALSE,ISNUMBER(FIND(J5,G9,1)))),LEFT(G9,FIND("" "",G9,1)-3),IF(OR(ISNUMBER(FIND(H5,G10,1)),ISNUMBER(FIND(I5,G10,1)),IF(J5="""",FALSE,ISNUMBER(FIND(J5,G10,1)))),LEFT(G10,FIND("" "",G10,1)-3),IF(OR(ISNUMBER(FIND(H5,G11,1)),ISNUMBER(FIND(I5,G11,1)),IF(J5="""",FALSE,ISNUMBER(FIND(J5,G11,1)))),LEFT(G11,FIND("" "",G11,1)-3),IF(OR(ISNUMBER(FIND(H5,G12,1)),ISNUMBER(FIND(I5,G12,1)),IF(J5="""",FALSE,ISNUMBER(FIND(J5,G12,1)))),LEFT(G12,FIND("" "",G12,1)-3),IF("
Form3 = "OR(ISNUMBER(FIND(H5,G13,1)),ISNUMBER(FIND(I5,G13,1)),IF(J5="""",FALSE,ISNUMBER(FIND(J5,G13,1)))),LEFT(G13,FIND("" "",G13,1)-3),IF(OR(ISNUMBER(FIND(H5,G14,1)),ISNUMBER(FIND(I5,G14,1)),IF(J5="""",FALSE,ISNUMBER(FIND(J5,G14,1)))),LEFT(G14,FIND("" "",G14,1)-3),IF(OR(ISNUMBER(FIND(H5,G15,1)),ISNUMBER(FIND(I5,G15,1)),IF(J5="""",FALSE,ISNUMBER(FIND(J5,G15,1)))),LEFT(G15,FIND("" "",G15,1)-3),""NOT FOUND"")))))))))))"
Range("B5", Range("B5").End(xlDown)) = Form1 + Form2 + Form3
Range("B5", Range("B5").End(xlDown)).Copy
Range("B5", Range("B5").End(xlDown)).PasteSpecial xlPasteValues
Range("G5", Range("G5").End(xlDown)).ClearContents
'Create New Sheets"
Range("G5:G15") = "=IFERROR(CONCAT(RIGHT(Table2[#[TASK ORDER]],LEN(Table2[#[TASK ORDER]])-SEARCH("" TO"",Table2[#[TASK ORDER]],1)),""_"",H5),"""")"
Range("G5:G15").Copy
Range("G5:G15").PasteSpecial xlPasteValues
Range("H5", Range("H5").End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Delete
For Each Cell In Range("G5:G15")
If Cell.Value <> "" Then
Sheets.Add(After:=Sheets(Sheets.Count)).Name = Cell.Value
End If
Next
Worksheets("Tasks_Orders_Info").Activate
'Open MJ File'
MsgBox "Choose mj extraction"
With Application.FileDialog(msoFileDialogFilePicker)
.Filters.Clear
.AllowMultiSelect = False
If .Show = -1 Then
MJFile = .SelectedItems(1)
End If
End With
Workbooks.Open MJFile
'Delete non Users'
Dim mapjobdata As Range
Dim WorkUserRg As Range
Worksheets("map_jobs_-_feedback_and_observa").Range("A1").Select
Worksheets("map_jobs_-_feedback_and_observa").Range(Selection, Selection.End(xlDown)).Select
Worksheets("map_jobs_-_feedback_and_observa").Range(Selection, Selection.End(xlToRight)).Select
Set mapjobdata = Worksheets("map_jobs_-_feedback_and_observa").Range(Selection.Address)
Set WorkUserRg = mapjobdata.Find("Worked on by User", , xlValues, xlWhole, , , True).Offset(1, 0)
Set WorkUserRg = Worksheets("map_jobs_-_feedback_and_observa").Range(WorkUserRg, WorkUserRg.End(xlDown))
For i = WorkUserRg.Count To 1 Step -1
If WorkUserRg.Cells(i) Like "*#email.com*" Then
Else
WorkUserRg.Cells(i).EntireRow.Delete
End If
Next i
'Add MapJobs to each Sheet'
Workbooks.Open WBOR
Range("H5:H15") = "=IFERROR(RIGHT(Table2[#Coder],FIND("")"",Table2[#Coder],1)-(FIND("" ("",Table2[#Coder],1))),"""")"
Range("H5", Range("H5").End(xlDown)).Copy
Range("H5", Range("H5").End(xlDown)).PasteSpecial xlPasteValues
Dim AutoFilterRng As Range
Dim WorksheetName As String
For Each Cell In Range("H5", Range("H5").End(xlDown))
If Cell.Value <> "" Then
WorksheetName = Cell.Offset(0, -1).Value
Workbooks.Open MJFile
ActiveSheet.Range("A:U").AutoFilter Field:=12, Criteria1:="*" & Cell.Value
With ActiveSheet.AutoFilter.Range
Set AutoFilterRng = .Offset(1, 0).Resize(.Rows.Count - 1, 1).SpecialCells(xlCellTypeVisible)
End With
ActiveSheet.AutoFilter.Range.Offset(1, 0).Resize(ActiveSheet.AutoFilter.Range.Count - 1).Copy
Workbooks.Open WBOR
Worksheets(WorksheetName).Range("A1").Paste
Workbooks.Open MJFile
AutoFilterMode = False
End If
Next
'------------------------------------------------------------------------------------------------------------------------------------------------------'
Fin:
Application.EnableEvents = True
Application.Calculation = xlAutomatic
Application.ScreenUpdating = True
End Sub
This is the error I get and debug shows the next line:
This is an untested code. I do not have the necessary data to test it. It must give you some hints in order to understand what is to be done:
Please add Option Explicit on top of your module. This will oblige you to declare all variables...
Sub sheetsAddAndCopy()
Dim WBOR As Workbook, Wmjf As Workbook, shW As Worksheet, shMJ As Worksheet
Dim AutoFilterRng As Range, WorksheetName As String, cell As Range
Const MJFile As String = "your workbook full path"
Set WBOR = ThisWorkbook
Set Wmjf = Workbooks.Open(MJFile) 'Opens the file where data I want to copy
For Each cell In WBOR.Range("H5", Range("H5").End(xlDown))
If cell.Value <> "" Then
WorksheetName = cell.Offset(0, -1).Value
Set shW = WBOR.Sheets.Add(After:=Sheets(Sheets.count))
shW.Name = WorksheetName
Set shMJ = Wmjf.ActiveSheet
shMJ.Range("A:U").AutoFilter field:=12, Criteria1:="*" & cell.Value 'Filters depending on the cell value
Set AutoFilterRng = shMJ.AutoFilter.Range.Offset(1, 0).Resize(.Rows.count - 1, 1).SpecialCells(xlCellTypeVisible)
shMJ.AutoFilter.Range.Offset(1, 0).Resize(shMJ.AutoFilter.Range.count - 1).Copy shW.Range("A1")
shMJ.AutoFilterMode = False
End If
Next
This is not the answer BUT may help you:
Sub test()
Dim shtName As String
With ThisWorkbook
'Let assume that the sheet name we want appears in Sheet3, range A1
'Get sheet name
shtName = .Worksheets("Sheet3").Range("A1").Value
'Activate sheet with name shtName
.Worksheets(shtName).Activate
End With
End Sub
I should not use .paste instead it should be .PasteSpecial and set the Worksheet. In this case WorksheetName = Cell.Offset(0,-1).Value and then set the Worksheet with that name so it will be Dim CurrentWSName, Set CurrentWSName = ActiveWorkbook.Sheets(WorksheetName) Code will be like this:
Dim AutoFilterRng As Range
Dim WorksheetName As String
Dim CurrentWSName As Worksheet
For Each Cell In Range("H5", Range("H5").End(xlDown))
If Cell.Value <> "" Then
WorksheetName = Cell.Offset(0, -1).Value
Set CurrentWSName = ActiveWorkbook.Sheets(WorksheetName)
Workbooks.Open MJFile
ActiveSheet.Range("A:U").AutoFilter Field:=12, Criteria1:="*" & Cell.Value
With ActiveSheet.AutoFilter.Range
Set AutoFilterRng = .Offset(1, 0).Resize(.Rows.Count - 1, 1).SpecialCells(xlCellTypeVisible)
End With
ActiveSheet.AutoFilter.Range.Offset(1, 0).Resize(ActiveSheet.AutoFilter.Range.Count - 1).Copy
Workbooks.Open WBOR
CurrentWSName.Activate
Range("A1").PasteSpecial
Workbooks.Open MJFile
AutoFilterMode = False
Workbooks.Open WBOR
End If
Next

Is there a way to skip error "filename is not found" and move to the next file

Is there a way to skip error "filename is not found" and move to the next file?
Sub CopyDataAndMoveDown()
Application.ScreenUpdating = False
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.ActiveSheet
Dim rngToCopy As Range, rngToPaste As Range
Dim x As Long
Dim breakdown1
Dim breakdown As Worksheet: Set breakdown = wb.ActiveSheet
For x = 4 To 504 Step 6
With wb.Sheets("Sheet1")
breakdown1 = breakdown.Cells(9, x - 2)
End With
If IsEmpty(breakdown1) Then
Call MoveBelow
Else
With wb.Sheets("Sheet1")
Set rngToCopy = .Range(.Cells(4, x - 2), .Cells(24, x + 3))
Debug.Print rngToCopy.Address
End With
With wb.Sheets("Sheet2")
Set rngToPaste = .Range(.Cells(4, x - 2), .Cells(rngToCopy.Rows.Count + 3, x + 3))
Debug.Print rngToPaste.Address
End With
rngToPaste = rngToCopy.Value
End If
Next x
Application.ScreenUpdating = True
MsgBox "Valmis."
End Sub
Sub MoveBelow ()
Application.ScreenUpdating = False
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.ActiveSheet
Dim rngToCopy As Range, rngToPaste As Range
Dim x As Long
Dim breakdown1
Dim breakdown As Worksheet: Set breakdown = wb.ActiveSheet
For x = 4 To 504 Step 6
With wb.Sheets("Sheet1")
breakdown1 = breakdown.Cells(9, x - 2)
End With
If IsEmpty(breakdown1) Then
' At this point when the macro meet again a empty cell
' it should keep moving from the same counted X
' but start the paste operation from 24 rows below.
Else
With wb.Sheets("Sheet1")
Set rngToCopy = .Range(.Cells(4, x - 2), .Cells(24, x + 3))
Debug.Print rngToCopy.Address
End With
With wb.Sheets("Sheet2")
Set rngToPaste = .Range(.Cells(28, x - 2), .Cells(rngToCopy.Rows.Count + 3, x + 3))
Debug.Print rngToPaste.Address
End With
rngToPaste = rngToCopy.Value
End If
Next x
Application.ScreenUpdating = True
MsgBox "Valmis."
End Sub
So when the macro is copying / pasting data from Sheet 1 to Sheet 2 and meets an empty cell it should keep going, copying next available data, but paste it 24 rows below.
--------Below the old question.
I have a VBA which is opening and closing file for that INDEX function get data. My problem is that. VBA is getting the filename from reference cell which contain the full path. But some of the reference cells are blanks/zeros and then the running VBA stops and give me error "filename is not found". Is there a way to skip that and move to next step?
Sub HaeReseptiTiedot()
Dim myfile As String
Dim myfile1 As String
Dim myfile2 As String
Dim myfile3 As String
Dim myfile4 As String
Dim myfile5 As String
Dim myfile6 As String
Dim myfile7 As String
Dim myfile8 As String
Dim myfile9 As String
myfile = Cells(19, 4).Value
myfile1 = Cells(19, 9).Value
myfile2 = Cells(19, 14).Value
myfile3 = Cells(19, 19).Value
myfile4 = Cells(19, 24).Value
myfile5 = Cells(19, 29).Value
myfile6 = Cells(19, 34).Value
myfile7 = Cells(19, 39).Value
myfile8 = Cells(19, 44).Value
myfile9 = Cells(19, 49).Value
Application.ScreenUpdating = False
Workbooks.Open Filename:=myfile, UpdateLinks:=0
ActiveWorkbook.Close False
Sheets("Aputaulukko 2").Select
Range("D16:G30").Select
Selection.Copy
Sheets("Aputaulukko 3").Select
Range("B4").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Workbooks.Open Filename:=myfile1, UpdateLinks:=0
ActiveWorkbook.Close False
Sheets("Aputaulukko 2").Select
Range("I16:L30").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Aputaulukko 3").Select
Range("G4").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
The best way I have found to handle this is to use the "On Error" statement. You can keep it really simple and use On Error Resume Next, which tells the code to skip the error entirely and move to the next statement (that does not have an error). The main issue with this is that it covers ALL errors, not just the specific one you are having issues with currently. It can make it hard to know if errors are occurring/if your code is functioning as you expect.
The other option, which can help avoid the issues mentioned above, is to use something like this:
On Error GoTo ErrH
'Main Body of Your Code
Exit Sub 'Use to avoid continuing on to the ErrH section.
ErrH:
'Some method for handling the error, such as a message box or other notification.
This usually isn't necessary with small chunks of code, but when you start combining your subs and functions it can be a life saver!
Good Luck!
Edit: You could/should also consider removing those blanks if they are not necessary for the sheet to work.
Here is a function that can check if a file exists:
'********************************************************************************************************************************
' To check if a particular file exists
' Set excelFile = False, if it is not an Excel file that is being checked
'********************************************************************************************************************************
Public Function isAnExistingFile(ByVal fileNameStr As Variant, Optional ByVal excelFile As Boolean = True) As Boolean
Dim wb As Workbook
isAnExistingFile = True
Err.Clear
On Error GoTo errHandler
If Not VarType(fileNameStr) = vbString Then
isAnExistingFile = False
ElseIf Len(fileNameStr) = 0 Then
isAnExistingFile = False
ElseIf Len(Dir(fileNameStr)) = 0 Then
isAnExistingFile = False
ElseIf ((GetAttr(fileNameStr) And vbDirectory) <> vbDirectory) = False Then
isAnExistingFile = False
Else
If excelFile Then
On Error Resume Next
Set wb = Application.Workbooks.Open(Filename:=fileNameStr, UpdateLinks:=0, ReadOnly:=True)
If wb Is Nothing Then isAnExistingFile = False
If Not wb Is Nothing Then
wb.Close False
Set wb = Nothing
End If
GoTo Out
End If
End If
errHandler:
If Not Err.Number = 0 Then isAnExistingFile = False
Out:
Err.Clear: On Error GoTo 0
End Function
I took the liberty to rewrite your code... i'm still not quite sure why you are openning and closing the workbook immediately, but in essence this is what your code does at the moment:
Option Explicit
Sub HaeReseptiTiedot()
Application.ScreenUpdating = False
Dim wbSource As Workbook
Dim wb As Workbook: Set wb = ThisWorkbook 'Or ActiveWorkbook or Workbooks("book name")
Dim ws As Worksheet: Set ws = wb.ActiveSheet 'Or wb.Sheets("Sheet Name")
Dim rngToCopy As Range, rngToPaste As Range
Dim X As Long
For X = 4 To 49 Step 5
On Error Resume Next
Set wbSource = Workbooks.Open(FileName:=ws.Cells(19, X), UpdateLinks:=0)
On Error GoTo 0
If Not wbSource Is Nothing Then
wbSource.Close False
With wb.Sheets("Aputaulukko 2")
Set rngToCopy = .Range(.Cells(16, X), .Cells(30, X + 3))
'Debug.Print rngToCopy.Address
End With
With wb.Sheets("Aputaulukko 3")
Set rngToPaste = .Range(.Cells(4, X - 2), .Cells(rngToCopy.Rows.Count + 3, X + 1))
'Debug.Print rngToPaste.Address
End With
rngToPaste = rngToCopy.Value
End If
Set wbSource = Nothing
Next X
Application.ScreenUpdating = True
End Sub
You could work around this by creating a second Sub that opens the file and handles the error if the file doesn't exist. That way you are still able to catch other Errors in the main Sub without going to next. Example:
Sub MainSub()
myFile1 = "C:\Temp\New1.xlsx"
myFile2 = "C:\Temp\New2.xlsx"
CheckAndOpen (myFile1)
CheckAndOpen (myFile2)
End Sub
Sub CheckAndOpen(myFileName As String)
On Error Resume Next
Workbooks.Open Filename:=myFileName
Debug.Print Err.Number, myFileName
End Sub
You could, alternatively, just put the following in your code:
If dir("FILENAME") <> "" Then
Add the rest of your code
End If
I usually run 3 or 4 for loops inside of each other with different variables to get the full path of each file, then put this to ensure I do not open files where there are blanks.

If autofilter gives no data move to next file

I have a code to copy the filtered data and paste. But it throws an error if there are blanks.Kindly help me on this.
This is my code. Getting an error when there are blanks for filtered criteria. Kindly suggest me what needs to be added to ignore the error and go to next file
Sub GetSheets()
Dim shtname As String
Dim Path As String
Dim Filename As String
Dim myRange As Range
Dim NumRows As Long
Path = ThisWorkbook.Sheets("Filepath").Range("B2").Value
shtname = ThisWorkbook.Sheets("Filepath").Range("B3").Value
Filename = Dir(Path & "*.xls")
Do While Filename <> ""
Workbooks.Open Filename:=Path & Filename, ReadOnly:=True
Sheets(shtname).Select
Columns("A:U").EntireColumn.Hidden = False
Set myRange = ActiveSheet.Range("A:A")
NumRows = Application.Count(myRange)
r = Application.WorksheetFunction.CountA(Sheets(shtname).Range("A:A"))
ActiveSheet.Range("$A$1:$U$1").AutoFilter Field:=19, Criteria1:="D.C"
ActiveSheet.Range("A2:U" & NumRows).SpecialCells(xlCellTypeVisible).Select
Selection.Copy
Windows("Combined - Dc Pharmacy chargeback.xlsm").Activate
Sheets("Sheet1").Select
Range("A1").Select
Selection.End(xlDown).Select
ActiveCell.Offset(1, 0).Select
ActiveSheet.Paste
Application.CutCopyMode = False
Application.DisplayAlerts = False
Workbooks(Filename).Close
Filename = Dir()
Loop
End Sub
Kindly suggest on this
An error will occur when no cells are visible. You can trap this error with On Error Resume Next as shown below.
Private Sub CopyFiltered()
Dim Rng As Range
Dim Rl As Long ' last row
Application.ScreenUpdating = False
With ActiveSheet
Rl = .Cells(.Rows.Count, "A").End(xlUp).Row
Set Rng = Range(.Cells(2, "A"), .Cells(Rl, "A"))
.Range("$A$1:$U$1").AutoFilter Field:=19, Criteria1:="D.C"
On Error Resume Next
Set Rng = Rng.SpecialCells(xlCellTypeVisible)
If Err = 0 Then
Rng.Copy
' Change this address as required
Worksheets("Manager").Cells(20, 3).Resize(Rng.Cells.Count, 1).PasteSpecial xlValues
End If
On Error GoTo 0
.ShowAllData
Rng.AutoFilter
End With
With Application
.ScreenUpdating = True
.CutCopyMode = False
End With
End Sub
Sub GetSheets()
Dim shtname As String
Dim Path As String
Dim Filename As String
Dim myRange As Range
Dim NumRows As Long
Path = ThisWorkbook.Sheets("Filepath").Range("B2").Value
shtname = ThisWorkbook.Sheets("Filepath").Range("B3").Value
Filename = Dir(Path & "*.xls")
On Error Resume Next
Do While Filename <> ""
Workbooks.Open Filename:=Path & Filename, ReadOnly:=True
Sheets(shtname).Select
Columns("A:U").EntireColumn.Hidden = False
Set myRange = ActiveSheet.Range("A:A")
NumRows = Application.Count(myRange)
r = Application.WorksheetFunction.CountA(Sheets(shtname).Range("A:A"))
ActiveSheet.Range("$A$1:$U$1").AutoFilter Field:=19, Criteria1:="D.C"
ActiveSheet.Range("A2:U" & NumRows).SpecialCells(xlCellTypeVisible).Select
x = ActiveSheet.Range("A65000").End(xlUp).Row
If x > 1 Then
Selection.Copy
Windows("Combined - Dc Pharmacy chargeback.xlsm").Activate
Sheets("Sheet1").Select
Range("A1").Select
Selection.End(xlDown).Select
ActiveCell.Offset(1, 0).Select
ActiveSheet.Paste
End If
Application.CutCopyMode = False
Application.DisplayAlerts = False
Workbooks(Filename).Close
Filename = Dir()
Loop
End Sub

Excel VBA - open a workbook and pasting data

I found this excellent code however I need to adapt it for my purposes.
Firstly I need to open a data workbook that is on our network. The problem I have is that it is likely at times to be open by another user and will offer the option of "read only". How can I get it to accept the read-only option so that I can commence extracting the data.
Secondly it copies using the "=" . How can I change it to copy just the values?
First macro:
Sub test()
'to open another workbook
Application.ScreenUpdating = False
Workbooks.Open Filename:=ThisWorkbook.Path & "\Schedule.xls"
ThisWorkbook.Activate
Application.ScreenUpdating = True
End Sub
2nd Macro:
Dim Sh As Worksheet
Dim Newsh As Worksheet
Dim myCell As Range
Dim ColNum As Integer
Dim RwNum As Long
Dim Basebook As Workbook
With Application
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
'Delete the sheet "Summary-Sheet" if it exist
Application.DisplayAlerts = False
On Error Resume Next
ThisWorkbook.Worksheets("Summary-Sheet").Delete
On Error GoTo 0
Application.DisplayAlerts = True
'Add a worksheet with the name "Summary-Sheet"
Set Basebook = ThisWorkbook
Set Newsh = Basebook.Worksheets.Add
Newsh.Name = "Summary-Sheet"
'The links to the first sheet will start in row 2
RwNum = 1
For Each Sh In Basebook.Worksheets
If Sh.Name <> Newsh.Name And Sh.Visible Then
ColNum = 1
RwNum = RwNum + 1
'Copy the sheet name in the A column
Newsh.Cells(RwNum, 1).Value = Sh.Name
For Each myCell In Sh.Range("A1,D5:E5,Z10") '<--Change the range
ColNum = ColNum + 1
Newsh.Cells(RwNum, ColNum).Formula = _
"='" & Sh.Name & "'!" & myCell.Address(False, False)
Next myCell
End If
Next Sh
Newsh.UsedRange.Columns.AutoFit
With Application
.Calculation = xlCalculationAutomatic
.ScreenUpdating = True
End With
End Sub
You could always open the workbook as read-only if you are only extracting data.
Instead of using .formula use .value

Generating a macro button with a macro

Using Excel 2013, I am looking to insert code into preexisting macro called "Rebuild_TOC" to generate a macro button on my "TOC" worksheet which calls "Repair_Back_To_TOC", a macro. I would like it to appear on my TOC at cells C2:E3, if possible, named "Rebuild Back to TOC Hyperlinks".
How would I go about accomplishing this with my current code?:
Sub Rebuild_TOC()
Dim wbBook As Workbook
Dim wsActive As Worksheet
Dim wsSheet As Worksheet
Dim lnRow As Long
Dim lnPages As Long
Dim lnCount As Long
Set wbBook = ActiveWorkbook
With Application
.DisplayAlerts = False
.ScreenUpdating = False
End With
' If the TOC sheet already exist delete it and add a new worksheet.
On Error Resume Next
Application.EnableEvents = False
With wbBook
.Worksheets("TOC").Delete
.Worksheets.Add Before:=.Worksheets(1)
End With
Application.EnableEvents = True
On Error GoTo 0
Set wsActive = wbBook.ActiveSheet
With wsActive
.Name = "TOC"
With.Range("A1:B1")
.Value = Array("Table of Contents", "Sheet # – # of Pages")
.Font.Bold = True
End With
End With
lnRow = 2
lnCount = 1
' Iterate through the worksheets in the workbook and create sheetnames, add hyperlink
' and count & write the running number of pages to be printed for each sheet on the TOC.
For Each wsSheet In wbBook.Worksheets
If wsSheet.Name <> wsActive.Name Then
wsSheet.Activate
With wsActive
.Hyperlinks.Add .Cells(lnRow, 1), "", _
SubAddress:= wsSheet.Name & "!A1", _
TextToDisplay:=wsSheet.Name
lnPages = wsSheet.PageSetup.Pages().Count
.Cells(lnRow, 2).Value = "‘" & lnCount & "-" & lnPages
End With
lnRow = lnRow + 1
lnCount = lnCount + 1
End If
Next wsSheet
wsActive.Activate
wsActive.Columns("A:B").EntireColumn.AutoFit
With Application
.DisplayAlerts = True
.ScreenUpdating = True
End With
End Sub

Resources