Task Scheduler will not run macro - vba

I am using access 2013 and have setup a macro to be called via the task scheduler. I am currently getting the the error 2001 when opened via the task scheduler. My database has been set as a trusted location but the macro will not complete. I am running under my login. All other macros work perfectly. If I manually open access to run the macro It runs just fine without any errors. I am updating two spreadsheets in this one macro so not sure if this has anything to do with it. Here is the function my macro calls below:
Function SendDailyInvoiceReport()
Dim myOutlook As outlook.Application
Dim filename As String
filename = "M:\Shared Documents\Invoices\Invoicing Reports\DAILY\Daily_Clients_Invoiced_" & Format(DateAdd("d", -1, Now()), "mm_dd_yyyy") & ".xlsx"
filename2 = "M:\Shared Documents\Invoices\Invoicing Reports\Daily\MonthToDate\Clients_Invoiced_Month_To_Date_" & Month(Now()) & "_" & Year(Now()) & ".xlsx"
DoCmd.OpenQuery "all invoices"
DoCmd.OutputTo acOutputQuery, "qryDAILYINVOICEREPORT", acFormatXLSX, filename, False
Dim xlApp As Excel.Application
Dim xlWB As Excel.Workbook
Dim ws As Worksheet
Set xlApp = New Excel.Application
With xlApp
.Visible = False
Set xlWB = .Workbooks.Open(filename, , False)
Set ws = .Worksheets("qryDAILYINVOICEREPORT")
End With
Dim LR As Long
Dim TotalBilled As Long
Dim TotalClients As Long
LR = ws.Range("C" & ws.Rows.count).End(xlUp).Row
ws.Range("C" & LR + 1).Value = "TOTAL # OF INVOICES:"
ws.Range("C" & LR + 1).Cells.Interior.ColorIndex = 6
LR = ws.Range("D" & ws.Rows.count).End(xlUp).Row
ws.Range("D" & LR + 1).Formula = "=COUNT(D2:D" & LR & ")"
TotalBilled = ws.Range("D" & ws.Rows.count).End(xlUp).Value
ws.Range("D" & LR + 1).Cells.Interior.ColorIndex = 6
LR = ws.Range("E" & ws.Rows.count).End(xlUp).Row
ws.Range("E" & LR + 1).Value = "TOTAL AMT INVOICED:"
ws.Range("E" & LR + 1).Cells.Interior.ColorIndex = 6
LR = ws.Range("F" & ws.Rows.count).End(xlUp).Row
ws.Range("F" & LR + 1).Formula = "=SUM(F2:F" & LR & ")"
TotalClients = ws.Range("F" & ws.Rows.count).End(xlUp).Value
ws.Range("F" & LR + 1).Cells.Interior.ColorIndex = 6
xlApp.DisplayAlerts = False
xlWB.SaveAs (filename)
xlWB.Close
xlApp.Quit
If Format(Now(), "MM/dd/yyyy") <> DateSerial(Year(Now()), Month(Now()), 1) Then
DoCmd.OutputTo acOutputQuery, "qryMONTHTODATEINVOICED", acFormatXLSX, filename2, False
Set xlApp = New Excel.Application
With xlApp
.Visible = False
Set xlWB = .Workbooks.Open(filename2, , False)
Set ws = .Worksheets("qryMONTHTODATEINVOICED")
End With
LR = ws.Range("C" & ws.Rows.count).End(xlUp).Row
ws.Range("C" & LR + 1).Value = "TOTAL # OF INVOICES:"
ws.Range("C" & LR + 1).Cells.Interior.ColorIndex = 6
LR = ws.Range("D" & ws.Rows.count).End(xlUp).Row
ws.Range("D" & LR + 1).Formula = "=COUNT(D2:D" & LR & ")"
TotalBilled = ws.Range("D" & ws.Rows.count).End(xlUp).Value
ws.Range("D" & LR + 1).Cells.Interior.ColorIndex = 6
LR = ws.Range("E" & ws.Rows.count).End(xlUp).Row
ws.Range("E" & LR + 1).Value = "TOTAL AMT INVOICED:"
ws.Range("E" & LR + 1).Cells.Interior.ColorIndex = 6
LR = ws.Range("F" & ws.Rows.count).End(xlUp).Row
ws.Range("F" & LR + 1).Formula = "=SUM(F2:F" & LR & ")"
TotalClients = ws.Range("F" & ws.Rows.count).End(xlUp).Value
ws.Range("F" & LR + 1).Cells.Interior.ColorIndex = 6
xlApp.DisplayAlerts = False
xlWB.SaveAs (filename2)
xlWB.Close
xlApp.Quit
End If
Set myOutlook = CreateObject("Outlook.Application")
Dim newEmail As outlook.MailItem
Set newEmail = myOutlook.CreateItem(olMailItem)
Dim myAttachments As outlook.Attachments
Set myAttachments = newEmail.Attachments
With newEmail
.Recipients.Add ("test#test.ORG")
.Subject = "--- SYSTEM FUNCTION --- Daily Clients Invoiced in System"
.Body = "Daily Clients Invoiced in System for " & Format(DateAdd("d", -1, Now()), "mm_dd_yyyy") & ""
End With
myAttachments.Add filename, olByValue
myAttachments.Add filename2, olByValue
newEmail.Send
Set newEmail = Nothing
Set myAttachments = Nothing
Set myOutlook = Nothing
Dim oServ As Object
Dim cProc As Variant
Dim oProc As Object
Set oServ = GetObject("winmgmts:")
Set cProc = oServ.ExecQuery("Select * from Win32_Process")
For Each oProc In cProc
'Rename EXCEL.EXE in the line below with the process that you need to Terminate.
'NOTE: It is 'case sensitive
If oProc.Name = "EXCEL.EXE" Then
errReturnCode = oProc.Terminate()
End If
Next
End Function`

After multiple attempts I was only able to get this working by creating a scheduled task that runs a macro that opens a form with the timer interval set to 10000 that checks the time and if it is a certain time run the functions.
Private Sub Form_Timer()
If TimeValue(Now()) > #7:00:00 AM# Then
Me.TimerInterval = 0
Call SendDailyInvoiceReport
Call SendDailyClientsMailReport
Call SendMonthlyClientsMailReport
Call SendYearlyClientsMailReport
DoCmd.Quit
End If
End Sub

Related

Excel VBA manually choosing a folder to loop thorugh all excel files in it

I have the following VBA code, to go through all the excel files in a folder and copy the needed columns from all file to one. Here is the code:
Option Explicit
Const FOLDER_PATH = "C:\Users\user\Desktop\04. April 2018\"
Sub ImportIncidentWorksheets()
Dim sFile As String
Dim wsTarget As Worksheet
Dim wbsource As Workbook
Dim wsSource As Worksheet
Dim rowTarget As Long
Dim rowSource As Long
rowTarget = 2
If Not FileFolderExists(FOLDER_PATH) Then
MsgBox "Specified folder does not exist, exiting!"
Exit Sub
End If
On Error GoTo errHandler
Application.ScreenUpdating = True
Set wsTarget = Sheets("SC")
sFile = Dir(FOLDER_PATH & "*.xlsx*")
Do Until sFile = ""
Set wbsource = Workbooks.Open(FOLDER_PATH & sFile)
Set wsSource = wbsource.Worksheets("sheet1")
With wsSource
rowSource = Application.Max(.Range("A" & .Rows.Count).End(xlUp).Row, .Range("B" & .Rows.Count).End(xlUp).Row, .Range("C" & .Rows.Count).End(xlUp).Row, .Range("D" & .Rows.Count).End(xlUp).Row, .Range("E" & .Rows.Count).End(xlUp).Row)
End With
With wsTarget
.Range("A" & rowTarget & ":E" & rowTarget + rowSource - 2).Value = wsSource.Range("A2:E" & rowSource).Value
.Range("A" & rowTarget & ":C" & rowTarget + rowSource - 2).Value = wsSource.Range("A2:C" & rowSource).Value
.Range("D" & rowTarget & ":D" & rowTarget + rowSource - 2).Value = wsSource.Range("E2:E" & rowSource).Value
.Range("E" & rowTarget & ":E" & rowTarget + rowSource - 2).Value = wsSource.Range("D2:D" & rowSource).Value
.Range("F" & rowTarget).Value = wbsource.Name
End With
wbsource.Close SaveChanges:=False
rowTarget = rowTarget + rowSource - 1
sFile = Dir()
Loop
errHandler:
On Error Resume Next
Application.ScreenUpdating = True
Set wsSource = Nothing
Set wbsource = Nothing
Set wsTarget = Nothing
End Sub
Private Function FileFolderExists(strPath As String) As Boolean
If Not Dir(strPath, vbDirectory) = vbNullString Then FileFolderExists = True
End Function
How can I modify the first part that the path of the folder won't be hard coded but it will give me a pop up window and I can choose the folder manually?
You can use code like below to get path while running the code.
Dim strFolderPath As String
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
.Show
If .SelectedItems.Count <> 0 Then
strFolderPath = .SelectedItems(1)
Else
MsgBox "Path not selected!", vbExclamation
End If
End With

Nielsen Nitro range (Blueberry range) refresh

I am looking for VBA to refresh Nielsen Nitro range.
Nielsen Nitro is an application to extract data from the Database. Also range is called Blueberry range to refresh the data
I've tried to use below VBA, but it was not working
Dim acnNitro As New ACNNITRO
Dim acnNitroUpdate As ACNielsenNitro.ACNNitroUpdate
Dim WS As Worksheet
Dim bret as Boolean
acnNitro.ParentApp = Application
acnNitroUpdate = acnNitro.ACNNitroUpdate
WS = ActiveSheet 'or Set WS = WorkSheets("My Sheet")
bret = acnNitroUpdate.UpdateAllNRanges(WS, ntrSelectGet)
acnNitro = Nothing
acnNitroUpdate = Nothing
WB = Nothing
screenshot
I have also provided screenshot for the range.
Can you please suggest me for VBA code?
I have written a similar code for a project, find code below. It might help you!
Public Sub NeilsenRefresh()
Dim str_RngDesc As Variant
Dim bRet As Boolean
Dim RngObj As NITRORange
Dim acnNITROUpdt As Object
Dim acnNITRO As Object
Dim NRangeObj As NITRORange
Dim cRange As Object
Dim Bubble As String
Set acnNITRO = CreateObject("ACNielsenNitro.ACNNitro")
Set acnNITRO.ParentApp = ActiveWorkbook.Application
Set acnNITROUpdt = acnNITRO.ACNNitroUpdate
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.Calculation = xlCalculationManual
With ThisWorkbook.Sheets("Macro")
WkbName = .Range("G9").Value
Path = .Range("G12").Value
Bubble = .Range("G15").Value
Atribute = .Range("G18").Value
WkList = .Range("G6").Value
End With
'Sheets("Data").Activate
With ThisWorkbook.Sheets("Data")
lr = .Range("A1048576").End(xlUp).Row
If lr > 1 Then
.Range("Q1:Q" & lr).ClearContents
.Range("A2:A" & lr).ClearContents
.Range("B3:C" & lr).ClearContents
.Range("D2:D" & lr).ClearContents
.Range("R2:R" & lr).ClearContents
.Range("S2:S" & lr).ClearContents
End If
Set WkbList = Workbooks.Open(Path & "\" & WkList & ".xlsx")
Set wks = WkbList.Sheets("Sheet1")
lrw = wks.Range("A1048576").End(xlUp).Row
wks.Range("A2:A" & lrw).Copy
.Range("A2").PasteSpecial Paste:=xlPasteValues
wks.Range("B2:B" & lrw).Copy
.Range("D2").PasteSpecial Paste:=xlPasteValues
lr = .Range("A1048576").End(xlUp).Row
.Range("B2:C" & lr).FillDown
.Calculate
Set wksmiss = ThisWorkbook.Sheets("Missing Records")
lrw = wksmiss.Range("A1048576").End(xlUp).Row
If lrw > 1 Then wksmiss.Range("A2:B" & lrw).ClearContents
.Range("A1:D" & lr).AutoFilter Field:=2, Criteria1:="#N/A"
lrw = .Range("A1048576").End(xlUp).Row
If lrw > 1 Then
.Range("B2:B" & lrw).SpecialCells(xlCellTypeVisible).Copy
wksmiss.Range("A2").PasteSpecial Paste:=xlPasteValues
.Range("D2:D" & lrw).SpecialCells(xlCellTypeVisible).Copy
wksmiss.Range("B2").PasteSpecial Paste:=xlPasteValues
.Range("A2:D" & lrw).SpecialCells(xlCellTypeVisible).Delete Shift:=xlUp
End If
.Range("A1:D" & lr).AutoFilter
.Range("B2:C" & lr).FillDown
.Calculate
.Calculate
.Range("A2:A" & lr).Copy
.Range("Q1").PasteSpecial Paste:=xlPasteValues
.Range("Q1:Q" & lr).RemoveDuplicates Columns:=1, Header:=xlNo
lrd = .Range("Q1048576").End(xlUp).Row
.Range("R1:R" & lrd).FillDown
.Range("S1:S" & lrd).FillDown
.Range("A1").Value = "Cum Name"
.Calculate
For i = 1 To lrd
CumName = .Range("Q" & i).Value
Cnt = .Range("R" & i).Value
FstIndex = .Range("S" & i).Value
RowNo = FstIndex + Cnt - 1
val1 = .Range("C" & RowNo).Value
If CumConcat = "" Then
CumConcat = val1 & ","
Else
val1 = Replace(val1, "MKT", "")
CumConcat = CumConcat & val1 & ","
End If
Next
End With
Set wkb = Workbooks.Open(Path & "\" & WkbName & ".xlsx")
Set RngObj = acnNITRO.ACNRangeUtility.GetNRange(Bubble, ActiveWorkbook)
RngObj.DimCount = 4
RngObj.DimIndex = Atribute
RngObj.DimGetString = CumConcat
str_RngDesc = RngObj.RangeDescription
Set acnNITROUpdt = acnNITRO.ACNNitroUpdate
bRet = acnNITROUpdt.UpdateNRange(ActiveWorkbook, Bubble, 0)
WkbList.Close
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.Calculation = xlCalculationAutomatic
ThisWorkbook.Sheets("Macro").Activate
MsgBox "Nielsen Refresh Completed", vbInformation
End Sub

vba listbox to connect with excel

I am getting an error on below line.
ListBox1.RowSource = "Tabelle1!A2:C" & loletzte
Here is my code:
myFileNameDir3 = Sheet3.Range("V10").Value & TextBox116.Text & ".xlsx"
Workbooks.Open fileName:=myFileNameDir3, UpdateLinks:=0
Set ws3 = Worksheets("Sheet1")
With ListBox5
.ColumnCount = 3
.ColumnWidths = "1cm;2cm;2cm"
.ColumnHeads = True
ListBox5.RowSource = ws1.Range("A1").CurrentRegion
'oder:
'ListBox1.RowSource = "Tabelle1!A2:C" & loletzte
End With
The issue is that you need to describe the RowSource as an address (like Sheet1!A1:A12) and not with a Range reference :
Dim RowSrcAddress As String
myFileNameDir3 = Sheet3.Range("V10").Value & TextBox116.Text & ".xlsx"
If InStr(1, ws1.Name, " ") Then
RowSrcAddress = "'" & ws1.Name & "'!" & .Range("A1").CurrentRegion.Address
Else
RowSrcAddress = ws1.Name & "!" & .Range("A1").CurrentRegion.Address
End If
Workbooks.Open Filename:=myFileNameDir3, UpdateLinks:=0
Set ws3 = Worksheets("Sheet1")
With ListBox5
.ColumnCount = 3
.ColumnWidths = "1cm;2cm;2cm"
.ColumnHeads = True
ListBox5.RowSource = RowSrcAddress
'oder:
'ListBox1.RowSource = "Tabelle1!A2:C" & loletzte
End With

Match cell value to a combobox row value

I'm trying to figure out a different method of running a piece of code.
Basically what my code is doing at the moment is, looping though column Q in the Global sheet, then looping though Combobox2, when it finds a match the entire rows get moved to the sheet reference in column 1 of the combobox.
Is it possible to use the Match function to achieve the same results and speed up the code??
This is currently the code I'm using, it does what I need it to do, but I cannot get error handling working for it. And it there are many rows of data to loop through it can take a long time!
Option 1:
Private Sub CommandButton6_Click()
Dim i As Long, j As Long, lastG As Long, strWS As String, rngCPY As Range
Dim StartTime As Double
Dim SecondsElapsed As Double
With Application
.ScreenUpdating = False
.EnableEvents = False
.CutCopyMode = False
End With
StartTime = Timer
If Range("L9") = "" Then
MsgBox "You can't Split the Jobs at this stage. " & vbLf & vbLf & "Please create the form for the Sub-Contractor First." & vbLf & vbLf & "Please press Display Utilities to create form.", vbExclamation, "Invalid Operation"
Exit Sub
End If
If sheets("Global").Range("A3") = "" Then
MsgBox "The appears to be no application loaded." & vbLf & vbLf & "Please load" & " " & Range("C11") & " " & "App and Planet Info, then click button 2 and try again.", vbExclamation, "Invalid Operation"
Exit Sub
End If
On Error GoTo bm_Close_Out
' find last row
lastG = sheets("Global").Cells(Rows.Count, "Q").End(xlUp).row
If InStr(1, sheets("Payment Form").Range("A20").value, "THE VAT SHOWN IS YOUR OUTPUT TAX DUE TO CUSTOMS AND EXCISE") > 0 Then
If sheets("PAYMENT FORM").Range("L40") >= 1 Then
MsgBox "It appears you have already split the jobs, this operation can only be performed once.", vbExclamation, "Invalid Operation"
Exit Sub
Else
For j = 0 To Me.ComboBox2.ListCount - 1
currval = Me.ComboBox2.List(j, 0) ' value to match
For i = 3 To lastG
lookupVal = sheets("Global").Cells(i, "Q") ' value to find
If lookupVal = currval Then
Set rngCPY = sheets("Global").Cells(i, "Q").EntireRow
strWS = Me.ComboBox2.List(j, 1)
On Error GoTo bm_Need_Worksheet '<~~ if the worksheet in the next line does not exist, go make one
With Worksheets(strWS)
rngCPY.Copy
.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Insert shift:=xlDown
End With
End If
Next i
Next j
End If
Else
If sheets("PAYMENT FORM").Range("L35") >= 1 Then
MsgBox "It appears you have already split the jobs, this operation can only be performed once.", vbExclamation, "Invalid Operation"
Exit Sub
Else
For j = 0 To Me.ComboBox2.ListCount - 1
currval = Me.ComboBox2.List(j, 0) ' value to match
For i = 3 To lastG
lookupVal = sheets("Global").Cells(i, "Q") ' value to find
If lookupVal = currval Then
Set rngCPY = sheets("Global").Cells(i, "Q").EntireRow
strWS = Me.ComboBox2.List(j, 1)
On Error GoTo bm_Need_Worksheet '<~~ if the worksheet in the next line does not exist, go make one
With Worksheets(strWS)
rngCPY.Copy
.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Insert shift:=xlDown
End With
End If
Next i
Next j
End If
End If
GoTo bm_Close_Out
bm_Need_Worksheet:
On Error GoTo 0
With Worksheet
Dim wb As Workbook: Set wb = ThisWorkbook
Dim wsTemplate As Worksheet: Set wsTemplate = wb.sheets("Template")
Dim wsPayment As Worksheet: Set wsPayment = wb.sheets("Payment Form")
Dim wsNew As Worksheet
Dim lastRow2 As Long
Dim Contract As String: Contract = sheets("Payment Form").Range("C9").value
Dim SpacePos As Integer: SpacePos = InStr(Contract, "- ")
Dim Name As String: Name = Left(Contract, SpacePos)
Dim Name2 As String: Name2 = Right(Contract, Len(Contract) - Len(Name))
Dim NewName As String: NewName = strWS
Dim CCName As Variant: CCName = Me.ComboBox2.List(j, 2)
Dim LastRow As Long: LastRow = wsPayment.Range("U36:U53").End(xlDown).row
If InStr(1, sheets("Payment Form").Range("A20").value, "THE VAT SHOWN IS YOUR OUTPUT TAX DUE TO CUSTOMS AND EXCISE") > 0 Then
lastRow2 = wsPayment.Range("A23:A39").End(xlDown).row
Else
lastRow2 = wsPayment.Range("A18:A34").End(xlDown).row
End If
wsTemplate.Visible = True
wsTemplate.Copy before:=sheets("Details"): Set wsNew = ActiveSheet
wsTemplate.Visible = False
If InStr(1, sheets("Payment Form").Range("A20").value, "THE VAT SHOWN IS YOUR OUTPUT TAX DUE TO CUSTOMS AND EXCISE") > 0 Then
With wsPayment
For Each cell In .Range("A23:A39")
If Len(cell) = 0 Then
If sheets("Payment Form").Range("C9").value = "Network" Then
cell.value = NewName & " - " & Name2 & ": " & CCName
Else
cell.value = NewName & " -" & Name2 & ": " & CCName
End If
Exit For
End If
Next cell
End With
Else
With wsPayment
For Each cell In .Range("A18:A34")
If Len(cell) = 0 Then
If sheets("Payment Form").Range("C9").value = "Network" Then
cell.value = NewName & " - " & Name2 & ": " & CCName
Else
cell.value = NewName & " -" & Name2 & ": " & CCName
End If
Exit For
End If
Next cell
End With
End If
If InStr(1, sheets("Payment Form").Range("A20").value, "THE VAT SHOWN IS YOUR OUTPUT TAX DUE TO CUSTOMS AND EXCISE") > 0 Then
With wsNew
.Name = NewName
.Range("D4").value = wsPayment.Range("A23:A39").End(xlDown).value
.Range("D6").value = wsPayment.Range("L11").value
.Range("D8").value = wsPayment.Range("C9").value
.Range("D10").value = wsPayment.Range("C11").value
End With
Else
With wsNew
.Name = NewName
.Range("D4").value = wsPayment.Range("A18:A34").End(xlDown).value
.Range("D6").value = wsPayment.Range("L11").value
.Range("D8").value = wsPayment.Range("C9").value
.Range("D10").value = wsPayment.Range("C11").value
End With
End If
wsPayment.Activate
With wsPayment
.Range("J" & lastRow2 + 1).value = 0
.Range("L" & lastRow2 + 1).Formula = "=N" & lastRow2 + 1 & "-J" & lastRow2 + 1 & ""
.Range("N" & lastRow2 + 1).Formula = "='" & NewName & "'!L20"
.Range("U" & LastRow + 1).value = NewName & ": "
.Range("V" & LastRow + 1).Formula = "='" & NewName & "'!I21"
.Range("W" & LastRow + 1).Formula = "='" & NewName & "'!I23"
.Range("X" & LastRow + 1).Formula = "='" & NewName & "'!K21"
End With
End With
On Error GoTo bm_Close_Out
Resume
bm_Close_Out:
SecondsElapsed = Round(Timer - StartTime, 2)
MsgBox "This code ran successfully in " & SecondsElapsed & " seconds", vbInformation
With Application
.ScreenUpdating = True
.EnableEvents = True
.CutCopyMode = True
End With
End Sub
Option 2:
Private Sub CommandButton1_Click()
Dim j As Long, strWS As String, rngCPY As Range, FirstAddress As String, sSheetsWithData As String
Dim sSheetsWithoutData As String, lSheetRowsCopied As Long, lAllRowsCopied As Long, bFound As Boolean, sOutput As String
Dim StartTime As Double
Dim SecondsElapsed As Double
With Application
.ScreenUpdating = False
.EnableEvents = False
.CutCopyMode = False
.EnableEvents = False
End With
StartTime = Timer
On Error GoTo bm_Close_Out
For j = 0 To UserForm2.ComboBox2.ListCount - 1
bFound = False
currval = UserForm2.ComboBox2.List(j, 0) ' value to match
With sheets("Global")
Set rngCPY = sheets("Global").Range("Q:Q").Find(currval, LookIn:=xlValues)
If Not rngCPY Is Nothing Then
bFound = True
lSheetRowsCopied = 0
FirstAddress = rngCPY.Address
Do
lSheetRowsCopied = lSheetRowsCopied + 1
strWS = UserForm2.ComboBox2.List(j, 1)
On Error GoTo bm_Need_Worksheet
With Worksheets(strWS)
rngCPY.EntireRow.Copy
.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Insert shift:=xlDown
End With
Set rngCPY = sheets("Global").Range("Q:Q").FindNext(rngCPY)
Loop Until rngCPY Is Nothing Or rngCPY.Address = FirstAddress
Else
bFound = False
End If
If bFound Then
sSheetsWithData = sSheetsWithData & " " & strWS & " (" & lSheetRowsCopied & ")" & vbLf
lAllRowsCopied = lAllRowsCopied + lSheetRowsCopied
End If
End With
Next j
bm_Need_Worksheet:
Dim wb As Workbook: Set wb = ThisWorkbook
Dim wsTemplate As Worksheet: Set wsTemplate = wb.sheets("Template")
Dim wsPayment As Worksheet: Set wsPayment = wb.sheets("Payment Form")
Dim wsNew As Worksheet
Dim lastRow2 As Long
Dim Contract As String: Contract = sheets("Payment Form").Range("C9").value
Dim SpacePos As Integer: SpacePos = InStr(Contract, "- ")
Dim Name As String: Name = Left(Contract, SpacePos)
Dim Name2 As String: Name2 = Right(Contract, Len(Contract) - Len(Name))
Dim NewName As String: NewName = strWS
Dim CCName As Variant: CCName = UserForm2.ComboBox2.List(j, 2)
Dim LastRow As Long: LastRow = wsPayment.Range("U36:U53").End(xlDown).row
If InStr(1, sheets("Payment Form").Range("A20").value, "THE VAT SHOWN IS YOUR OUTPUT TAX DUE TO CUSTOMS AND EXCISE") > 0 Then
lastRow2 = wsPayment.Range("A23:A39").End(xlDown).row
Else
lastRow2 = wsPayment.Range("A18:A34").End(xlDown).row
End If
wsTemplate.Visible = True
wsTemplate.Copy before:=sheets("Details"): Set wsNew = ActiveSheet
wsTemplate.Visible = False
If InStr(1, sheets("Payment Form").Range("A20").value, "THE VAT SHOWN IS YOUR OUTPUT TAX DUE TO CUSTOMS AND EXCISE") > 0 Then
With wsPayment
For Each cell In .Range("A23:A39")
If Len(cell) = 0 Then
If sheets("Payment Form").Range("C9").value = "Network" Then
cell.value = NewName & " - " & Name2 & ": " & CCName
Else
cell.value = NewName & " -" & Name2 & ": " & CCName
End If
Exit For
End If
Next cell
End With
Else
With wsPayment
For Each cell In .Range("A18:A34")
If Len(cell) = 0 Then
If sheets("Payment Form").Range("C9").value = "Network" Then
cell.value = NewName & " - " & Name2 & ": " & CCName
Else
cell.value = NewName & " -" & Name2 & ": " & CCName
End If
Exit For
End If
Next cell
End With
End If
If InStr(1, sheets("Payment Form").Range("A20").value, "THE VAT SHOWN IS YOUR OUTPUT TAX DUE TO CUSTOMS AND EXCISE") > 0 Then
With wsNew
.Name = NewName
.Range("D4").value = wsPayment.Range("A23:A39").End(xlDown).value
.Range("D6").value = wsPayment.Range("L11").value
.Range("D8").value = wsPayment.Range("C9").value
.Range("D10").value = wsPayment.Range("C11").value
End With
Else
With wsNew
.Name = NewName
.Range("D4").value = wsPayment.Range("A18:A34").End(xlDown).value
.Range("D6").value = wsPayment.Range("L11").value
.Range("D8").value = wsPayment.Range("C9").value
.Range("D10").value = wsPayment.Range("C11").value
End With
End If
wsPayment.Activate
With wsPayment
.Range("J" & lastRow2 + 1).value = 0
.Range("L" & lastRow2 + 1).Formula = "=N" & lastRow2 + 1 & "-J" & lastRow2 + 1 & ""
.Range("N" & lastRow2 + 1).Formula = "='" & NewName & "'!L20"
.Range("U" & LastRow + 1).value = NewName & ": "
.Range("V" & LastRow + 1).Formula = "='" & NewName & "'!I21"
.Range("W" & LastRow + 1).Formula = "='" & NewName & "'!I23"
.Range("X" & LastRow + 1).Formula = "='" & NewName & "'!K21"
End With
On Error GoTo bm_Close_Out
Resume
bm_Close_Out:
If sSheetsWithData <> vbNullString Then
sOutput = "# of rows copied to sheets:" & vbLf & vbLf & sSheetsWithData & vbLf & _
"Total rows copied = " & lAllRowsCopied & vbLf & vbLf
Else
sOutput = "No sheets contained data to be copied" & vbLf & vbLf
End If
If sSheetsWithoutData <> vbNullString Then
sOutput = sOutput & "Sheets with no rows copied:" & vbLf & vbLf & sSheetsWithoutData
Else
sOutput = sOutput & "All sheets had data that was copied."
End If
If sOutput <> vbNullString Then MsgBox sOutput, , "Copy Report"
Set rngCPY = Nothing
SecondsElapsed = Round(Timer - StartTime, 2)
MsgBox "This code ran successfully in " & SecondsElapsed & " seconds", vbInformation
With Application
.ScreenUpdating = True
.EnableEvents = True
.CutCopyMode = True
.EnableEvents = True
End With
End Sub
OK... It's more like a try than an answer. pls check if that is working and if it is faster.
Use this macro only with a copy of your workbook!
Private Sub CommandButton2_Click()
Dim i As Long, j As Long, k As Long, strWS As String, rngCPY As Range
Dim noFind As Variant: noFind = UserForm2.ComboBox2.List '<~~~ get missed items
With Application: .ScreenUpdating = False: .EnableEvents = False: .CutCopyMode = False: End With
If Range("L9") = "" Then: MsgBox "You can't Split the Jobs at this stage. " & vbLf & vbLf & "Please create the form for the Sub-Contractor First." & vbLf & vbLf & "Please press Display Utilities to create form.", vbExclamation, "Invalid Operation": Exit Sub
Dim lastG As Long: lastG = Sheets("Global").Cells(Rows.Count, 17).End(xlUp).row
Dim cVat As Boolean: cVat = InStr(1, Sheets("Payment Form").Range("A20").Value, "THE VAT SHOWN IS YOUR OUTPUT TAX DUE TO CUSTOMS AND EXCISE")
If Sheets("PAYMENT FORM").Cells(35 - cVat * 5, 12) >= 1 Then: MsgBox "It appears you have already split the jobs, this operation can only be performed once.", vbExclamation, "Invalid Operation": Exit Sub
'~~~ acivate next line to sort (will speed up a lot)
'Sheets("Global").Range("A3:R" & Cells(Rows.Count, 17).End(xlUp).row).Sort cells(3,17), 1
For j = 0 To UserForm2.ComboBox2.ListCount - 1
noFind(j, 4) = 0
For i = 3 To lastG
If noFind(j, 0) = Sheets("Global").Cells(i, 17) Then
k = i
strWS = UserForm2.ComboBox2.List(j, 1)
On Error Resume Next
If Len(Worksheets(strWS).Name) = 0 Then
With ThisWorkbook
On Error GoTo 0
Dim nStr As String: With Sheets("Payment Form").Range("C9"): nStr = Right(.Value, Len(.Value) - Len(Left(.Value, InStr(.Value, "- ")))): End With
Dim CCName As Variant: CCName = UserForm2.ComboBox2.List(j, 2)
Dim lastRow As Long: lastRow = Sheets("Payment Form").Range("U36:U53").End(xlDown).row + 1
Dim strRng As String: strRng = Array("A18:A34", "A23:A39")(-1 * cVat)
Dim lastRow2 As Long: lastRow2 = Sheets("Payment Form").Range(strRng).End(xlDown).row + 1
Dim wsNew As Worksheet: .Sheets("Template").Copy .Sheets(.Sheets.Count): Set wsNew = .Sheets(.Sheets.Count): wsNew.Move .Sheets("Details")
With Sheets("Payment Form")
For Each cell In .Range(strRng)
If Len(cell) = 0 Then
If Sheets("Payment Form").Range("C9").Value = "Network" Then
cell.Offset.Value = strWS & " - " & nStr & ": " & CCName
Else
cell.Offset.Value = strWS & " -" & nStr & ": " & CCName
End If
Exit For
End If
Next cell
End With
With wsNew
.Visible = -1
.Name = strWS
.Cells(4, 4).Value = Sheets("Payment Form").Range(strRng).End(xlDown).Value
.Cells(6, 4).Value = Sheets("Payment Form").Cells(12, 12).Value
.Cells(8, 4).Value = Sheets("Payment Form").Cells(9, 3).Value
.Cells(10, 4).Value = Sheets("Payment Form").Cells(11, 3).Value
End With
With .Sheets("Payment Form")
.Activate
.Cells(lastRow2, 10).Value = 0
.Cells(lastRow2, 12).Formula = "=N" & lastRow2 & "-J" & lastRow2 & ""
.Cells(lastRow2, 14).Formula = "='" & strWS & "'!L20"
.Cells(lastRow, 21).Value = strWS & ": "
.Cells(lastRow, 22).Formula = "='" & strWS & "'!I21"
.Cells(lastRow, 23).Formula = "='" & strWS & "'!I23"
.Cells(lastRow, 24).Formula = "='" & strWS & "'!K21"
End With
End With
End If
On Error GoTo 0
While Sheets("Global").Cells(k + 1, 17).Value = noFind(j, 0) And k < lastG
k = k + 1
Wend
Set rngCPY = Sheets("Global").Range("Q" & i & ":Q" & k).EntireRow
With Worksheets(strWS)
rngCPY.Copy
.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Insert shift:=xlDown
End With
noFind(j, 4) = noFind(j, 4) + k - i + 1
i = k
End If
Next i
Next j
With Application: .ScreenUpdating = True: .EnableEvents = True: .CutCopyMode = True: End With
'noFind(x, y) > x = item / y: 0 = name / y: 4 = counter
noFind(0, 0) = noFind(0, 0) & " " & noFind(0, 4) & " times copied"
For i = 1 To UBound(noFind)
noFind(0, 0) = noFind(0, 0) & vbLf & noFind(i, 0) & " " & noFind(i, 4) & " times copied"
Next
MsgBox noFind(0, 0)
End Sub
At first: you may add some empty lines for better understanding...
Most parts are just shortened by view (they still do tha same).
When using the sort option, it will copy/paste all rows for each keyword in one step. That not only sounds faster... However, you may resort at the end again
Pls check if it works with your real workbook (copy of it, but with all data inside). I haven't done any "indeep speed tuning".
Here is a small section of your code that replace the loop through each cell in Global!Q3:Q*<last_row>* with the VBA version of the MATCH function.
Dim rw As Long, rngGQs As Range '<~~ put this closer to the top with the other variable declarations
' find last row
'lastG = Sheets("Global").Cells(Rows.Count, "Q").End(xlUp).Row '<~~old way
With Sheets("Global") '<~~new way
Set rngGQs = .Range(Cells(3, "Q"), .Cells(Rows.Count, "Q").End(xlUp)) '< ~~ all of the cells to look at
End With
If InStr(1, Sheets("Payment Form").Range("A20").Value, "THE VAT SHOWN IS YOUR OUTPUT TAX DUE TO CUSTOMS AND EXCISE") > 0 Then
If Sheets("PAYMENT FORM").Range("L40") >= 1 Then
MsgBox "It appears you have already split the jobs, this operation can only be performed once.", vbExclamation, "Invalid Operation"
Exit Sub
Else
For j = 0 To Me.ComboBox2.ListCount - 1
currval = Me.ComboBox2.List(j, 0) ' value to match
'For i = 3 To lastG '<~~old way
'lookupVal = Sheets("Global").Cells(i, "Q") ' value to find
'If lookupVal = currval Then
If Not IsError(Application.Match(currval, rngGQs, 0)) Then '<~~new way
rw = Application.Match(currval, rngGQs, 0)
Set rngCPY = Sheets("Global").Cells(rw, "Q").EntireRow
'all the rest here
When you get this to a satisfactory working order, it will be a prime candidate for suggestions at Code Review (Excel).
You could try something like this. The Range.Find-Method basically looks through the given range for a value which you can specify. If a match is found, the cell in which the match is found, can then be stored.
You can then also use .FindNext to find the next occurrence of that value, if needed.
For j = 0 To Me.ComboBox2.ListCount - 1
currval = Me.ComboBox2.List(j, 0) ' value to match
Set rngCPY = sheets("Global").Range("Q:Q").Find(currval, LookIn:=xlValues)
Do While Not rngCPY Is Nothing
strWs = Me.ComboBox2.List(j, 1)
rngCPY.EntireRow.Copy
With Worksheets(strWS)
.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Insert shift:=xlDown
End With
Set rngCPY = sheets("Global").Range("Q:Q").FindNext(rngCPY)
Loop
Next j

Runtime Error 1004: Method 'Range' of object '_Global' failed

I've seen numerous questions on the issue but none of the solutions fit my situation (I think) so any help is appreciated. I receive the error when setting the value of the LR integer variable. As with many others having this issue, it only fails the second time the subroutine is run.
Sub SaveEmailAttachments()
' Creates each variable to be used
Dim xlApp As Excel.Application, xlWB As Excel.Workbook, xlAtt As Excel.Workbook
Dim olItem As Outlook.MailItem
Dim LR As Integer, NR As Integer, j As Integer, intDir As Integer, random As Integer
' Path to the HWB Master template to be used
Const strPath As String = "C:\Users\dkirksey\Documents\SOF\SOF Station HWB Master w Macro.xlsm"
' If no emails are selected, present an error and exit
If Application.ActiveExplorer.Selection.Count = 0 Then
MsgBox "No Items selected!", vbCritical, "Error"
Exit Sub
End If
' Creates a new Excel application
On Error Resume Next
Set xlApp = New Excel.Application
xlApp.Visible = False
'Opens the Excel workbook
On Error GoTo 0
Set xlWB = xlApp.Workbooks.Open(strPath)
'Creates a new directory to store today's information
intDir = (fIsFileDIR("C:\Users\dkirksey\Documents\SOF\HWB Files\" & Format(Now, "mmddyy"), vbDirectory))
If intDir = 0 Then
MkDir ("C:\Users\dkirksey\Documents\SOF\HWB Files\" & Format(Now, "mmddyy"))
MkDir ("C:\Users\dkirksey\Documents\SOF\HWB Files\" & Format(Now, "mmddyy") & "\HWBs")
'Process each selected email
For Each olItem In Application.ActiveExplorer.Selection
j = j + 1
For cnt = 1 To olItem.Attachments.Count
If Right(olItem.Attachments(1).FileName, 4) = "xlsx" Or Right(olItem.Attachments(1).FileName, 3) = "xls" Or Right(olItem.Attachments(1).FileName, 4) = "xlsm" Then
olItem.Attachments(cnt).SaveAsFile ("C:\Users\dkirksey\Documents\SOF\HWB Files\" & Format(Now, "mmddyy") & "\HWBs\" _
& Format(Now, "mmddyy") & " " & j & olItem.Attachments(cnt).DisplayName)
Set xlAtt = xlApp.Workbooks.Open("C:\Users\dkirksey\Documents\SOF\HWB Files\" & Format(Now, "mmddyy") & "\HWBs\" _
& Format(Now, "mmddyy") & " " & j & olItem.Attachments(cnt).DisplayName)
xlAtt.Activate
If xlAtt.ActiveSheet.Range("A3").Value = "HWB" And xlAtt.ActiveSheet.Range("B3").Value = "Instruction (optional)" And xlAtt.ActiveSheet.Range("C3").Value = "Route (optional)" Then
LR = xlAtt.ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
xlAtt.ActiveSheet.Range("A4:C4" & LR).Select
Selection.Copy
xlWB.Activate
xlWB.ActiveSheet.Range("A" & Rows.Count).End(xlUp).Offset(1).Select
Selection.PasteSpecial xlPasteValues
xlWB.ActiveSheet.Cells(1, 1).Activate
End If
xlApp.DisplayAlerts = False
xlAtt.Close SaveChanges:=False
Else
olItem.Categories = "Purple Category"
End If
Next
Next olItem
j = 4
LR = xlWB.ActiveSheet.UsedRange.Rows.Count
Do Until j > LR
If IsNumeric(Cells(j, 1)) = False Then
Cells(j, 1).EntireRow.Delete
LR = LR - 1
ElseIf Cells(j, 1).Value = "" Then
Cells(j, 1).EntireRow.Delete
LR = LR - 1
Else
j = j + 1
End If
Loop
xlWB.SaveAs ("C:\Users\dkirksey\Documents\SOF\HWB Files\" & Format(Now, "mmddyy") & "\" & Format(Now, "mmddyy") & " Complete HWB List")
Else
ans = MsgBox("You have already run SOF today, would you like to continue anyway?", vbYesNo)
If ans = vbYes Then
random = Int((9999 - 100 + 1) * Rnd + 100)
MkDir ("C:\Users\dkirksey\Documents\SOF\HWB Files\" & Format(Now, "mmddyy") & random)
MkDir ("C:\Users\dkirksey\Documents\SOF\HWB Files\" & Format(Now, "mmddyy") & random & "\HWBs")
MsgBox "Your new folder is titled " & Format(Now, "mmddyy") & random & ", it is located in the Documents\SOF\HWB Files directory"
'Process each selected email
For Each olItem In Application.ActiveExplorer.Selection
j = j + 1
For cnt = 1 To olItem.Attachments.Count
If Right(olItem.Attachments(1).FileName, 4) = "xlsx" Or Right(olItem.Attachments(1).FileName, 3) = "xls" Or Right(olItem.Attachments(1).FileName, 4) = "xlsm" Then
olItem.Attachments(cnt).SaveAsFile ("C:\Users\dkirksey\Documents\SOF\HWB Files\" & Format(Now, "mmddyy") & random & "\HWBs\" _
& Format(Now, "mmddyy") & " " & j & olItem.Attachments(cnt).DisplayName)
Set xlAtt = xlApp.Workbooks.Open("C:\Users\dkirksey\Documents\SOF\HWB Files\" & Format(Now, "mmddyy") & random & "\HWBs\" _
& Format(Now, "mmddyy") & " " & j & olItem.Attachments(cnt).DisplayName)
xlAtt.Activate
If xlAtt.ActiveSheet.Range("A3").Value = "HWB" And xlAtt.ActiveSheet.Range("B3").Value = "Instruction (optional)" And xlAtt.ActiveSheet.Range("C3").Value = "Route (optional)" Then
LR = xlAtt.ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
xlAtt.ActiveSheet.Range("A4:C4" & LR).Select
Selection.Copy
xlWB.Activate
xlWB.ActiveSheet.Range("A" & Rows.Count).End(xlUp).Offset(1).Select
Selection.PasteSpecial xlPasteValues
xlWB.ActiveSheet.Cells(1, 1).Activate
End If
xlApp.DisplayAlerts = False
xlAtt.Close SaveChanges:=False
Else
olItem.Categories = "Purple Category"
End If
Next
Next olItem
j = 4
LR = xlWB.ActiveSheet.UsedRange.Rows.Count
Do Until j > LR
If IsNumeric(Cells(j, 1)) = False Then
Cells(j, 1).EntireRow.Delete
LR = LR - 1
ElseIf Cells(j, 1).Value = "" Then
Cells(j, 1).EntireRow.Delete
LR = LR - 1
Else
j = j + 1
End If
Loop
xlWB.SaveAs ("C:\Users\dkirksey\Documents\SOF\HWB Files\" & Format(Now, "mmddyy") & random & "\" & Format(Now, "mmddyy") & " Complete HWB List")
Else
xlWB.Close
xlApp.DisplayAlerts = True
xlApp.Quit
Exit Sub
End If
End If
xlWB.Close
xlApp.DisplayAlerts = True
xlApp.Quit
MsgBox "Well played !"
End Sub
I'm a rookie with VBA so excuse any redundant or just plain idiotic coding methods you notice.
The subroutine works perfectly the first time it is run, just not the second. Please help.
Thank you.