Excel VBA .saveas premission denied with onedrive - excel

I've created a macro to get data from active workbook, copy it into a new one and save new file. Whole code worked perfect until I changed Office to 365 with Onedrive on my computer.
When I run this macro, I get error 1004: Premission denied in macro below
Sub create_new()
Dim SheetI As Worksheet
Dim SheetO As Worksheet
Dim BookO As Workbook
Dim BookI As Workbook
Dim row As Long
Dim i As Long
Dim dict As Object
Dim path As String
Dim brng As Range
Dim found As Boolean
path = CreateObject("WScript.Shell").SpecialFolders("MyDocuments") & "\path\"
If Len(Dir(path, vbDirectory)) = 0 Then MkDir path
path = path & _
Format(Date, "ddmmmyyyy") & ".xlsx"
If Dir(path) <> "" Then Kill path
Set BookI = ThisWorkbook
Set BookO = Workbooks.Add
With BookO
BookO.Sheets.Add.Name = "Name"
Set SheetO = BookO.Sheets("Name")
SheetO.Cells(1, 1).Value = "1"
SheetO.Cells(1, 2).Value = "2"
SheetO.Cells(1, 3).Value = "3"
SheetO.Columns("A:H").AutoFit
SheetO.Range("a1:h1").Font.Bold = True
Application.DisplayAlerts = False
.SaveAs path
Application.DisplayAlerts = True
End With
Set dict = SubTotals(BookI)
For Each SheetI In BookI.Sheets
If SheetI.Name <> "Dane" Then
For row = 10 To SheetI.Cells(Rows.Count, 1).End(xlUp).row Step 1
If i <= row Then
If SheetI.Cells(row, 2).Value = "Oprysk" Then
If Not found Then found = True
i = row
If SheetI.Cells(row, 2).MergeCells Then i = row + SheetI.Cells(row, 2).MergeArea.Rows.Count - 1
With BookO
Range(SheetI.Cells(row, 1), SheetI.Cells(i, 1)).Copy
SheetO.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
Range(SheetI.Cells(row, 5), SheetI.Cells(i, 8)).Copy
SheetO.Cells(Rows.Count, 5).End(xlUp).Offset(1, 0).PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
SheetI.Cells(2, 2).Copy
SheetO.Cells(Rows.Count, 2).End(xlUp).Offset(1, 0).PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
SheetI.Cells(3, 5).Copy
SheetO.Cells(Rows.Count, 3).End(xlUp).Offset(1, 0).PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
SheetO.Cells(Rows.Count, 4).End(xlUp).Offset(1, 0).Value = SearchDict(dict, SheetO.Cells(Rows.Count, 3).End(xlUp).Value)
If i <> row Then
For l = 1 To 8 Step 1
If l <> 6 And l <> 7 Then
Application.DisplayAlerts = False
Range(SheetO.Cells(Rows.Count, l).End(xlUp), SheetO.Cells(Rows.Count, l).End(xlUp).Offset(i - row, 0)).Merge
Application.DisplayAlerts = True
End If
Next l
End If
End With
End If
End If
Next row
End If
Next SheetI
If found Then
Set brng = Range(SheetO.Cells(1, 1), SheetO.Cells(Rows.Count, 6).End(xlUp).Offset(0, 2))
With BookO
brng.BorderAround xlContinuous, xlThin
brng.Borders(xlInsideHorizontal).LineStyle = xlContinuous
brng.Borders(xlInsideVertical).LineStyle = xlContinuous
Application.DisplayAlerts = False
.SaveAs path
Application.DisplayAlerts = True
End With
MsgBox "File saved in path: " & path
Else
With BookO
Application.DisplayAlerts = False
BookO.Close
Application.DisplayAlerts = True
End With
Kill path
MsgBox "Data not found"
End If
End Sub
So basicly I check here if the path and file exists. If not, its created. I save the new workbook for the first time when its formated but before data is copied. Secondly its saved when the data is copied and this second attempt to save workbook fails with error above. Why I was able to overwrite this workbook when I didnt use Onedrive and now, when I do it shows me the error?

Related

Wait until other users close the Excel file

I have created a 'Login Tracker' system where 100 people all use an excel form saved to their computer, and when they hit "submit" it opens another .xlsb file(RTS Report) in a shared drive, finds the next line, and puts the data on the next line. This all takes 2-5 seconds to complete, however, if two people hit "submit" at the same time then one gets an error that the file is already open.
im new in vba please help me code for following scenarios
Check if Database.xlsb is open by another user
If not, continue with the code
If yes (file is not available) code need wait for until file close
Sub RTS()
ThisWorkbook.Activate
Application.DisplayAlerts = False
ActiveSheet.Range("A7:D7", "Q7").Select
Range("Q7").Activate
Application.CutCopyMode = False
Selection.Copy
Application.ScreenUpdating = False
Workbooks.Open Filename:="RTS Report.xlsx", ReadOnly:=False
Dim she As Worksheet
Dim a As Integer
ActiveWorkbook.Sheets("data").Activate
Set she = actveworkbook.actvesheet
b = she.Range("A" & Rows.Count).End(xlUp).Row
she.Range("A" & b + 1).PasteSpecial Paste:=xlPasteFormulasAndNumberFormats, operation:=xlNone, Skipblanks:=False, Transpose:=False
Cells.Select
Cells.EntireColumn.AutoFit
ActiveWorkbook.Save
Application.ScreenUpdating = True
ThisWorkbook.Activate
End Sub
As mentioned in the comments, excel is not ideal for this, but if is the only thing you have the following should work.
try to open until error disappears
Sub RTS()
ThisWorkbook.Activate
Application.DisplayAlerts = False
ActiveSheet.Range("A7:D7", "Q7").Select
Range("Q7").Activate
Application.CutCopyMode = False
Selection.Copy
Application.ScreenUpdating = False
cont = True
On Error Resume Next
While cont
Err.Clear
Workbooks.Open Filename:="RTS Report.xlsx", ReadOnly:=False
If Err.Number <> 0 Then
Application.Wait (Now + TimeValue("0:00:01"))
Err.Clear
Else
cont = False
End If
Wend
On Error GoTo 0
Dim she As Worksheet
Dim a As Integer
ActiveWorkbook.Sheets("data").Activate
Set she = actveworkbook.actvesheet
b = she.Range("A" & Rows.Count).End(xlUp).Row
she.Range("A" & b + 1).PasteSpecial Paste:=xlPasteFormulasAndNumberFormats, operation:=xlNone, Skipblanks:=False, Transpose:=False
Cells.Select
Cells.EntireColumn.AutoFit
ActiveWorkbook.Save
Application.ScreenUpdating = True
ThisWorkbook.Activate
End Sub
Sub RTS()
ThisWorkbook.Activate
Application.DisplayAlerts = False
ActiveSheet.Unprotect ("GLOLOGIN")
Application.ScreenUpdating = False
'Copy & Paste the data from " Scheduled Ad " sheet to "RTS Report.Xlsb" Sheet
ActiveSheet.Range("A7:D7", "Q7").Select
ActiveSheet.Range("A7:D7,Q7").Select
Range("Q7").Activate
Application.CutCopyMode = False
Selection.Copy
'RTS Report is not open then open the doc & pasete this data
cont = True
On Error Resume Next
While cont
Err.Clear
Dim wb As Workbook
Set wb = Workbooks.Open(Filename:="G:\PPR MUMBAI\Everythig Else\MIS\LILO\.Data\RTS Report.xlsx")
Do Until wb.ReadOnly = False
wb.Close
Application.Wait Now + TimeValue("00:00:01")
Set wb = Workbooks.Open(Filename:="G:\PPR MUMBAI\Everythig Else\MIS\LILO\.Data\RTS Report.xlsx")
Loop
If Err.Number <> 0 Then
Application.Wait (Now + TimeValue("0:00:01"))
Err.Clear
Else
cont = False
End If
Wend
On Error GoTo 0
Dim She As Worksheet
Dim b As Integer
ActiveWorkbook.Sheets("Data").Activate
Set She = ActiveWorkbook.ActiveSheet
b = She.Range("A" & Rows.Count).End(xlUp).Row
She.Range("A" & b + 1).PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Cells.Select
Cells.EntireColumn.AutoFit
ActiveWorkbook.Save
ActiveWorkbook.Close
ThisWorkbook.Activate
ActiveSheet.Protect ("GLOLOGIN")
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub

Add a workbook once and paste the data in the same workbook on subsequent runs

I have a worksheet (sheet2) which contains a vlookup function with changing values in certain cells to refresh data. I want to copy any changed values to another workbook.
Sub Copy_file()
Dim xWs As Worksheet
Dim Rng As Range
Set Rng = Range("C6:M124")
Application.Workbooks.Add
Set xWs = Application.ActiveSheet
Rng.Copy
xWs.Cells(2, 2).PasteSpecial Paste:=xlPasteValues
xWs.Cells(2, 2).PasteSpecial Paste:=xlPasteColumnWidths, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
xWs.Cells(2, 2).PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
xWs.Cells(2, 2).PasteSpecial Paste:=xlPasteValuesAndNumberFormats
End Sub
Every time the code runs it creates a new workbook.
I need to modify it so that I can add a new workbook with a specific name and the copied data is pasted in sheet1 only when the macro runs for the first time.
On subsequent runs the copied data should be pasted in the next sheet (e.g. Sheet2, Sheet3, Sheet4,... etc.) in the single workbook.
Please, try the next code:
Sub Copy_file()
Dim xWs As Worksheet, Rng As Range, wb As Workbook, wsMark As Worksheet
Dim wbFullName As String, wbName As String, lastR As Long
wbName = "MyWorkbook.xlsx"
wbFullName = ThisWorkbook.Path & "\" & wbName
Set Rng = Range("C6:M124") 'the range is set in the active workbook
'if the one keeping the code, please state it
'and the range will be fully qualified
If dir(wbName) = "" Then 'if the necessary workbook does not exist
Set wb = Application.Workbooks.Add 'create it
wb.saveas wbName 'name the newly created workbook
Set wsMark = wb.Sheets(wb.Sheets.count)
wsMark.Name = "UsedSheets" 'name the last sheet keeping copying order
End If
If wb Is Nothing Then 'if not created above, but exists:
On Error Resume Next
Set wb = Workbooks(wbName) 'check if it is open
Set wsMark = wb.Worksheets("UsedSheets") 'set the sheet keeping copying order
On Error GoTo 0
End If
'if not open, open it:
If wb Is Nothing Then
Set wb = Workbooks.Open(wbFullName)
Set wsMark = wb.Worksheets("UsedSheets") 'set the sheet keeping copying order
End If
lastR = wsMark.Range("A" & wsMark.rows.count).End(xlUp).row 'last used row in the sheet
If lastR > 1 Then
If CLng(wsMark.Range("A" & lastR).value) < (wb.Sheets.count - 2) Then
Set xWs = wb.Sheets(CLng(wsMark.Range("A" & lastR).value + 1))
wsMark.Range("A" & lastR + 1).value = xWs.Index
Else
Set xWs = wb.Sheets.Add(Before:=wsMark)
wsMark.Range("A" & lastR + 1).value = xWs.Index
End If
Else
Set xWs = wb.Sheets(1): wsMark.Range("A" & lastR + 1).value = 1
End If
Rng.copy
With xWs.cells(2, 2)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteColumnWidths, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
.PasteSpecial Paste:=xlPasteValuesAndNumberFormats
End With
End Sub
Edited:
Please, test the next variant. It open a new workbook, first time you run the code and uses it until you close it. You must manually save it, when finished the copying process...
Sub Copy_file()
Dim xWs As Worksheet, Rng As Range, wb As Workbook, wsMark As Worksheet
Dim wbFullName As String, wbName As String, lastR As Long
wbName = "MyWorkbook.xlsx"
wbFullName = ThisWorkbook.Path & "\" & wbName
Set Rng = Range("C6:M124")
If dir(wbName) = "" Then 'if the necessary workbook does not exist
Set wb = Application.Workbooks.Add 'create it
wb.saveas wbName 'name the newly created workbook
Set wsMark = wb.Sheets(wb.Sheets.count)
wsMark.Name = "UsedSheets" 'name the last sheet keeping copying order
End If
If wb Is Nothing Then 'if not created above, but exists:
On Error Resume Next
Set wb = Workbooks(wbName) 'check if it is open
Set wsMark = wb.Worksheets("UsedSheets") 'set the sheet keeping copying order
On Error GoTo 0
End If
'if not open, open it:
If wb Is Nothing Then
Set wb = Workbooks.Open(wbFullName)
Set wsMark = wb.Worksheets("UsedSheets") 'set the sheet keeping copying order
End If
lastR = wsMark.Range("A" & wsMark.rows.count).End(xlUp).row 'last used row in the sheet
If lastR > 1 Then
If CLng(wsMark.Range("A" & lastR).value) < wb.Sheets.count - 1 Then
Set xWs = wb.Sheets(CLng(wsMark.Range("A" & lastR).value + 1))
wsMark.Range("A" & lastR + 1).value = xWs.Index
Else
Set xWs = wb.Sheets.Add(Before:=wsMark)
wsMark.Range("A" & lastR + 1).value = xWs.Index
End If
Else
Set xWs = wb.Sheets(1): wsMark.Range("A" & lastR + 1).value = 1
End If
Rng.copy
With xWs.cells(2, 2)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteColumnWidths, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
.PasteSpecial Paste:=xlPasteValuesAndNumberFormats
End With
End Sub
Sub Copy_file1()
Dim xWs As Worksheet, Rng As Range, wb As Workbook
Dim w As Workbook, wsMark As Worksheet, lastR As Long
Set Rng = Range("C6:M124") 'if active sheet belongs to the workbook keeping this code
'it should be adapted to fully qualify the range
If wb Is Nothing Then 'check if wb exists but it losts the reference because of an error:
For Each w In Workbooks 'iterate between open workbooks:
If w.Sheets(w.Sheets.count).Name = "UsedSheets" Then
Set wb = w
Set wsMark = wb.Worksheets("UsedSheets"): Exit For
End If
Next w
End If
'if wb does not exist:
If wb Is Nothing Then
Set wb = Application.Workbooks.Add 'open a new workbook and set it
Set wsMark = wb.Sheets(wb.Sheets.count) 'set the last sheet like the one to keep copying order
wsMark.Name = "UsedSheets"
End If
If left(Rng.Parent.Parent.Name, 4) = "Book" Then 'if, by mistake, the selection is done on a wb sheet:
MsgBox "The active sheet where ""Rng"" was set belongs to the workbook where to copy..." & vbCrLf & _
"It should be a mistake. Please, select the appropriate sheet!", vbInformation, "Wrong sheet selected.."
Exit Sub
End If
lastR = wsMark.Range("A" & wsMark.rows.count).End(xlUp).row 'last used row in the sheet
If lastR > 1 Then 'for the first time (when wb has been created):
If CLng(wsMark.Range("A" & lastR).value) < wb.Sheets.count - 1 Then
Set xWs = wb.Sheets(CLng(wsMark.Range("A" & lastR).value + 1))
wsMark.Range("A" & lastR + 1).value = xWs.Index
Else 'if is not the first copying time:
Set xWs = wb.Sheets.Add(Before:=wsMark)
wsMark.Range("A" & lastR + 1).value = xWs.Index
End If
Else
Set xWs = wb.Sheets(1): wsMark.Range("A" & lastR + 1).value = 1
End If
Rng.copy
With xWs.cells(2, 2)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteColumnWidths, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
.PasteSpecial Paste:=xlPasteValuesAndNumberFormats
End With
End Sub
Try:
Sub Copy_file()
Application.ScreenUpdating = False
Dim xWs As Worksheet
Static WB As Workbook ' static variables stores its values between proc calls
If WB Is Nothing Then ' check if a certain workbook exists. if no, create it
Set WB = Workbooks.Add
Else
WB.Worksheets.Add after:=WB.Sheets(WB.Sheets.Count) ' create the next WS
End If
Set xWs = ActiveSheet
ThisWorkbook.Sheets("Sheet2").Range("C6:M124").Copy
With xWs.Cells(2, 2)
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteColumnWidths, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
.PasteSpecial Paste:=xlPasteValuesAndNumberFormats
End With
Application.ScreenUpdating = True
End Sub

Trying to set text in a colum based on a match on a different sheet

I am creating a inventory control workbook and I am looking to have a column with the words "Order Placed" once I have clicked on the button to place order. I want to make sure that it is based on the right criteria. Currently in I am using a formula to place that text but once I clear the order form that goes away because its using an index match function within an if statement.
This is my current Order Placed Sub
Sub orderPlaced()
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Application.ScreenUpdating = False
Dim startCell As range, lastRow As Long, lastCol As Long, ws As Worksheet
Set ws = Sheets("Re-Order List")
'This part Copies the requested information
Sheets("Re-Order List").Select
range("A1").Select
Application.CutCopyMode = False
Selection.Copy
'This part Pastes the requested information in the history
Sheets("Order History").Select
Selection.End(xlDown).Select
range("A65536").Select
Selection.End(xlUp).Offset(1, 0).Select
Selection.PasteSpecial Paste:=xlPasteAllExceptBorders, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
'This part Copies the requested information
Sheets("Re-Order List").Select
Set startCell = range("A3")
lastRow = ws.Cells(ws.Rows.Count, startCell.Column).End(xlUp).Row
lastCol = ws.Cells(startCell.Row, ws.Columns.Count).End(xlToLeft).Column
ws.range(startCell, ws.Cells(lastRow, lastCol)).Select
Application.CutCopyMode = False
Selection.Copy
'This part Pastes the requested information in the history
Sheets("Order History").Select
Selection.End(xlDown).Select
range("A65536").Select
Selection.End(xlUp).Offset(1, 0).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
'This part adds orderplaced below order form
Sheets("Order History").Select
range("A65536").Select
Selection.End(xlUp).Offset(2, 0).Select
With Selection
.Value = "Order Placed :"
.HorizontalAlignment = xlRight
End With
'This part adds the date
Sheets("Order History").Select
range("B65536").Select
Selection.End(xlUp).Offset(2, 0).Select
With Selection
.Value = Date
.NumberFormat = "dd/mmm/yyyy"
.HorizontalAlignment = xlLeft
End With
'this will set the comment in inventory to ordered
'*************************
'NEEDED CODE WILL GO HERE
'*************************
Sheets("Inventory").Select
range("K6:K400").ClearContents
'This part Clears the order form
Sheets("Re-Order List").Select
range("A4:D5000").ClearContents
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
This is my Add to Order Sub
Sub add2Order()
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Application.ScreenUpdating = False
Dim C As range, rng As range, D As range, Rng1 As range, mnrng As range, acrng As range
Sheets("Inventory").Select
Set rng = range("K6:K400")
For Each C In rng
If InStr(1, C, "X") > 0 Then
'first select material number and name
Set mnrng = range(C.Offset(0, -9), C.Offset(0, -8))
Application.CutCopyMode = False
mnrng.Copy
'paste in reorder sheet
Sheets("Re-Order List").Select
Selection.End(xlDown).Select
range("A400").Select
Selection.End(xlUp).Offset(1, 0).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = True
End If
Next
Sheets("Inventory").Select
Set Rng1 = range("K6:K400")
For Each D In Rng1
If InStr(1, D, "X") > 0 Then
'Second select amount and cost
Set acrng = range(D.Offset(0, -2), D.Offset(0, -1))
Application.CutCopyMode = False
acrng.Copy
'paste in reorder sheet
Sheets("Re-Order List").Select
Selection.End(xlDown).Select
range("C400").Select
Selection.End(xlUp).Offset(1, 0).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = True
End If
Next
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Code that is close is as follows
Sub test()
'
Dim w1 As Worksheet, w2 As Worksheet
Dim C As range, a As range
Set w1 = Sheets("Inventory")
Set w2 = Sheets("Re-Order List")
With w1
For Each C In .range("$A$6:$A$400")
Set a = w2.Columns(1).Find(C.Value, LookAt:=xlWhole)
If Not a Is Nothing Then
If IsEmpty(.Cells(C.Row, 1)) And .Cells(C.Row, 1).Value = w2.Cells(a.Row, 1) Then
w1.Cells(C.Row, 12).Value = "Order Placed"
End If
End If
Next C
End With
End Sub
This is the last piece to this puzzle to get it how I want it to work, I know for sure I will only have less than 400 materials to manage and if that grows I can update then but any help would be fantastic.
This is the drive link for the actual sheet
This isn't an answer until you tell us exactly where do you want to place the information
I refactored your code so you don't use select and added some pseudo code that may give you a hint
Public Sub orderPlaced()
' Turn off stuff to speed up process
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Application.ScreenUpdating = False
'This part Copies the requested information
Dim reorderListSheet As Worksheet
Set reorderListSheet = ThisWorkbook.Worksheets("Re-Order List")
reorderListSheet.Range("A1").Copy
'This part Pastes the requested information in the history
Dim orderHistorySheet As Worksheet
Set orderHistorySheet = ThisWorkbook.Worksheets("Order History")
orderHistorySheet.Cells(orderHistorySheet.Rows.Count, "A").End(xlUp).Offset(1, 0).PasteSpecial Paste:=xlPasteAllExceptBorders, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
' Find last row in reorder sheet
Dim reorderLastRow As Long
reorderLastRow = reorderListSheet.Cells(reorderListSheet.Rows.Count, "A").End(xlUp).Row
' Find last column in reorder sheet
Dim reorderLastColumn As Long
reorderLastColumn = reorderListSheet.Cells(3, reorderListSheet.Columns.Count).End(xlToLeft).Column
'This part Copies the requested information
Dim reorderStartCell As Range
Set reorderStartCell = reorderListSheet.Range("A3")
reorderListSheet.Range(reorderStartCell, reorderListSheet.Cells(reorderLastRow, reorderLastColumn)).Copy
'This part Pastes the requested information in the history
Dim orderHistoryLastRow As Long
orderHistoryLastRow = orderHistorySheet.Cells(orderHistorySheet.Rows.Count, "A").End(xlUp).Row
orderHistorySheet.Range("A" & orderHistoryLastRow).Offset(1, 0).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
'This part adds orderplaced below order form
With orderHistorySheet.Range("A" & orderHistoryLastRow).Offset(3, 0)
.Value = "Order Placed :"
.HorizontalAlignment = xlRight
End With
'This part adds the date
With orderHistorySheet.Range("B" & orderHistoryLastRow).Offset(3, 0)
.Value = Date
.NumberFormat = "dd/mmm/yyyy"
.HorizontalAlignment = xlLeft
End With
'this will set the comment in inventory to ordered
'*************************
' THIS NEXT IS PSEUDO CODE BECAUSE I COULDN'T UNDERSTAND YOUR REQUIREMENT
Dim targetCell As Range
Set targetCell = orderHistorySheet.Range("A1").Value = "=IFERROR(IF(INDEX(Table2[Material Number],MATCH(C6,Table2[Name],0)) = [#[Material Number]],""Order Placed"",""""),"""")"
' turn that into a value
targetCell.Value = targetCell.Value
'*************************
' Clear inventory sheet
Dim inventorySheet As Worksheet
Set inventorySheet = ThisWorkbook.Worksheets("Inventory")
inventorySheet.Range("K6:K400").ClearContents
'This part Clears the order form
reorderListSheet.Range("A4:D5000").ClearContents
' Turn on stuff again
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
I FIGURED IT OUT!!!!!!!!
'this will set the comment in inventory to ordered
'*************************
Dim r1 As range
Dim r2 As range
Dim cell As range
Set r1 = Sheets("Inventory").range("B6:B400")
Set r2 = Sheets("Re-Order List").range("A4:A400")
For Each cell In r1
If IsError(Application.Match(cell, r2, 0)) Then
cell.Offset(, 12) = ""
Else
cell.Offset(, 12) = "Order Placed"
' If found I need the value from Sheet2 that is in Col B of the matching row.
End If
Next cell
'*************************

How to optimize multiple loops in VBA code within Excel

I am not a very efficient vba coder, but I can brute force my way through something. I am trying to optimize this code to have it run more quickly. I would imagine it should be possible to combine the loops somehow, but I am not exactly sure where to start since the Sheets are within the formulas. Any assistance would be greatly appreciated.
Sub Import()
Application.EnableEvents = False 'This stops the background codes on the sheets from activating (smoothens out the process).
Application.ScreenUpdating = False 'Stops the screen from switching back and forth between the Input and the Master
Application.DisplayAlerts = False
If InStr(1, Worksheets("Lookup").Range("B44").Value, "STATE1", vbTextCompare) <> 0 Then
Sheets("SHEET2").Activate
Range("A4").Select
ElseIf InStr(1, Worksheets("Lookup").Range("B44").Value, "STATE2", vbTextCompare) <> 0 Then
Sheets("SHEET2").Activate
Range("A4").Select
ElseIf InStr(1, Worksheets("Lookup").Range("B44").Value, "STATE3", vbTextCompare) <> 0 Then
Sheets("SHEET2").Activate
Range("A4").Select
ElseIf InStr(1, Worksheets("Lookup").Range("B44").Value, "All", vbTextCompare) <> 0 Then
Sheets("SHEET2").Activate
Range("A4").Select
Else:
Sheets("SHEET1").Columns("KA:KC").Hidden = True
Sheets("SHEET2").Columns("KA:KC").Hidden = True
Sheets("SHEET3").Columns("KA:KC").Hidden = True
Sheets("SHEET4").Columns("KA:KC").Hidden = True
MsgBox "Doesn't exist for these locations"
Exit Sub
End If
Sheets("SHEET1").Columns("KA:KC").Hidden = False
Sheets("SHEET2").Columns("KA:KC").Hidden = False
Sheets("SHEET3").Columns("KA:KC").Hidden = False
Sheets("SHEET4").Columns("KA:KC").Hidden = False
`'This removes the old DATASHEET tab from the model before starting (if it exists)
Dim SummaryWB As Workbook
Dim vrtSelectedItem As Variant
For Each Sheet In ActiveWorkbook.Worksheets
If Sheet.Name = "DATASHEET" Then
Sheet.Delete
End If
Next Sheet
''' The below opens the RRS file from the file path defined
Workbooks.Open Filename:="\\Template_Current.xlsx"
'' This just pauses the operating for 1 second to allow the file to be opened seamlessly, can probably be removed.
Application.Wait Now + #12:00:01 AM#
'' This copies the Data from the RRS file and moves it into the CPM model in a new tab, and renames it.
'' It then closes the Source file.
Sheets("Data").Select
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
Windows("Report.xlsm").Activate
Sheets("YAdd").Select
Sheets.Add After:=ActiveSheet
ActiveSheet.Paste
ActiveSheet.Select
ActiveSheet.Name = "DATASHEET"
Windows("Template_Current.xlsx").Activate
Sheets("List View").Select
Range("D3").Select
Selection.Copy
Windows("Report.xlsm").Activate
Sheets("DATASHEET").Select
Range("W1").Select
ActiveSheet.Paste
Windows("Template_Current.xlsx").Activate
ActiveWorkbook.Close True
Windows("Report.xlsm").Activate
'' and performs a lookup against the DATASHEET tab, matching the Account Number. It currently only
'' shows values if they are found/non-zero. It also clears old data from the columns
'' This also copies the outputed data and pastes only the values.
'' By doing so, we are saving future memory space, so that it doesn't need to recalc everytime you open
'' the file, only when you run this macro.
Sheets("SHEET1").Select
Range("KA25:KC5000").Select
Selection.Delete
Dim LastRow As Long, i As Long
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
For i = 25 To LastRow
Range("KA1").Offset(i - 1, 0).Select
ActiveCell.FormulaR1C1 = _
"=IF(SUMIF(DATASHEET!R2C1:R712C1,SHEET1!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275])>0,SUMIF(DATASHEET!R2C1:R712C1,SHEET1!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275]),"""")"
Range("KB1").Offset(i - 1, 0).Select
ActiveCell.FormulaR1C1 = _
"=IF(SHEET1!RC[-1]="""","""",If(SHEET1!RC[-1]>1.1,""RED"",If(SHEET1!RC[-1]<0.8,""GREEN"",""YELLOW"")))"
Range("KC1").Offset(i - 1, 0).Select
ActiveCell.FormulaR1C1 = _
"=IF(SHEET1!RC[-1]="""","""",SUMIF(DATASHEET!R2C1:R712C1,SHEET1!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275]))"
Next i
Sheets("SHEET1").Select
Range("KA25").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
Selection.PasteSpecial xlPasteValues
Range("KA25").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.NumberFormat = "0.00"
Range("KC25").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.NumberFormat = "0.00%"
Range("KA25").Select
Sheets("SHEET2").Select
Range("KA25:KC5000").Select
Selection.Delete
Dim LastRow1 As Long, i1 As Long
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
For i1 = 25 To LastRow
Range("KA1").Offset(i1 - 1, 0).Select
ActiveCell.FormulaR1C1 = _
"=IF(SUMIF(DATASHEET!R2C1:R712C1,SHEET2!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275])>0,SUMIF(DATASHEET!R2C1:R712C1,SHEET2!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275]),"""")"
Range("KB1").Offset(i1 - 1, 0).Select
ActiveCell.FormulaR1C1 = _
"=IF(SHEET2!RC[-1]="""","""",If(SHEET2!RC[-1]>1.1,""RED"",If(SHEET2!RC[-1]<0.8,""GREEN"",""YELLOW"")))"
Range("KC1").Offset(i1 - 1, 0).Select
ActiveCell.FormulaR1C1 = _
"=IF(SHEET2!RC[-1]="""","""",SUMIF(DATASHEET!R2C1:R712C1,SHEET2!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275]))"
Next i1
Sheets("SHEET2").Select
Range("KA25").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
Selection.PasteSpecial xlPasteValues
Range("KA25").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.NumberFormat = "0.00"
Range("KC25").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.NumberFormat = "0.00%"
Range("KA25").Select
Sheets("SHEET3").Select
Range("KA25:KC5000").Select
Selection.Delete
Dim LastRow2 As Long, i2 As Long
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
For i2 = 25 To LastRow
Range("KA1").Offset(i2 - 1, 0).Select
ActiveCell.FormulaR1C1 = _
"=IF(SUMIF(DATASHEET!R2C1:R712C1,SHEET3!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275])>0,SUMIF(DATASHEET!R2C1:R712C1,SHEET3!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275]),"""")"
Range("KB1").Offset(i2 - 1, 0).Select
ActiveCell.FormulaR1C1 = _
"=IF(SHEET3!RC[-1]="""","""",If(SHEET3!RC[-1]>1.1,""RED"",If(SHEET3!RC[-1]<0.8,""GREEN"",""YELLOW"")))"
Range("KC1").Offset(i2 - 1, 0).Select
ActiveCell.FormulaR1C1 = _
"=IF(SHEET3!RC[-1]="""","""",SUMIF(DATASHEET!R2C1:R712C1,SHEET3!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275]))"
Next i2
Sheets("SHEET3").Select
Range("KA25").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
Selection.PasteSpecial xlPasteValues
Range("KA25").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.NumberFormat = "0.00"
Range("KC25").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.NumberFormat = "0.00%"
Range("KA25").Select
Sheets("SHEET4").Select
Range("KA25:KC5000").Select
Selection.Delete
Dim LastRow3 As Long, i3 As Long
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
For i3 = 25 To LastRow
Range("KA1").Offset(i3 - 1, 0).Select
ActiveCell.FormulaR1C1 = _
"=IF(SUMIF(DATASHEET!R2C1:R712C1,SHEET4!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275])>0,SUMIF(DATASHEET!R2C1:R712C1,SHEET4!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275]),"""")"
Range("KB1").Offset(i3 - 1, 0).Select
ActiveCell.FormulaR1C1 = _
"=IF(SHEET4!RC[-1]="""","""",If(SHEET4!RC[-1]>1.1,""RED"",If(SHEET4!RC[-1]<0.8,""GREEN"",""YELLOW"")))"
Range("KC1").Offset(i3 - 1, 0).Select
ActiveCell.FormulaR1C1 = _
"=IF(SHEET4!RC[-1]="""","""",SUMIF(DATASHEET!R2C1:R712C1,SHEET4!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275]))"
Next i3
Sheets("SHEET4").Select
Range("KA25").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
Selection.PasteSpecial xlPasteValues
Range("KA25").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.NumberFormat = "0.00"
Range("KC25").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.NumberFormat = "0.00%"
Range("KA25").Select
Sheets("DATASHEET").Visible = xlSheetHidden
Application.EnableEvents = True 'Turns background code back on.
Application.ScreenUpdating = True 'Turns ScreenUpdating back on.
Application.DisplayAlerts = True 'Turns Alerts back on.
MsgBox "Import Complete"
End Sub
You want to avoid repeating yourself. Whenever you have duplicate code you need to break it out in to it's own procedure and then call it using the variable that makes it unique. In your case the only unique part is the sheet you are operating on. So I made this example procedure that you can pass sheet objects to:
Private Sub ProcessSheet(thisSheet As Worksheet)
thisSheet.Range("KA25:KC5000").Delete
Dim LastRow As Long, i As Long
LastRow = thisSheet.Cells(thisSheet.Rows.Count, "A").End(xlUp).Row
For i = 25 To LastRow
thisSheet.Range("KA1").Offset(i - 1, 0).FormulaR1C1 = _
"=IF(SUMIF(DATASHEET!R2C1:R712C1," & thisSheet.Name & "!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275])>0,SUMIF(DATASHEET!R2C1:R712C1," & thisSheet.Name & "!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275]),"""")"
thisSheet.Range("KB1").Offset(i - 1, 0).FormulaR1C1 = _
"=IF(" & thisSheet.Name & "!RC[-1]="""","""",If(" & thisSheet.Name & "!RC[-1]>1.1,""RED"",If(" & thisSheet.Name & "!RC[-1]<0.8,""GREEN"",""YELLOW"")))"
thisSheet.Range("KC1").Offset(i - 1, 0).FormulaR1C1 = _
"=IF(" & thisSheet.Name & "!RC[-1]="""","""",SUMIF(DATASHEET!R2C1:R712C1," & thisSheet.Name & "!R25C2:R59C2,DATASHEET!R2C[-275]:R712C[-275]))"
Next i
With thisSheet
.Range("KA25").UsedRange = Sheets("SHEET1").Range("KA25").UsedRange
.Range("KA25", Selection.End(xlDown)).NumberFormat = "0.00"
.Range("KC25", Selection.End(xlDown)).NumberFormat = "0.00%"
End With
End Sub
Then you can call it from your main import procedure like this:
Sub Import()
With Application
.EnableEvents = False 'This stops the background codes on the sheets from activating (smoothens out the process).
.ScreenUpdating = False 'Stops the screen from switching back and forth between the Input and the Master
.DisplayAlerts = False
End With
If InStr(1, Worksheets("Lookup").Range("B44").Value, "STATE1", vbTextCompare) <> 0 Then
Sheets("SHEET2").Activate
Range("A4").Select
ElseIf InStr(1, Worksheets("Lookup").Range("B44").Value, "STATE2", vbTextCompare) <> 0 Then
Sheets("SHEET2").Activate
Range("A4").Select
ElseIf InStr(1, Worksheets("Lookup").Range("B44").Value, "STATE3", vbTextCompare) <> 0 Then
Sheets("SHEET2").Activate
Range("A4").Select
ElseIf InStr(1, Worksheets("Lookup").Range("B44").Value, "All", vbTextCompare) <> 0 Then
Sheets("SHEET2").Activate
Range("A4").Select
Else
Sheets("SHEET1").Columns("KA:KC").Hidden = True
Sheets("SHEET2").Columns("KA:KC").Hidden = True
Sheets("SHEET3").Columns("KA:KC").Hidden = True
Sheets("SHEET4").Columns("KA:KC").Hidden = True
MsgBox "Doesn't exist for these locations"
Exit Sub
End If
Sheets("SHEET1").Columns("KA:KC").Hidden = False
Sheets("SHEET2").Columns("KA:KC").Hidden = False
Sheets("SHEET3").Columns("KA:KC").Hidden = False
Sheets("SHEET4").Columns("KA:KC").Hidden = False
'This removes the old DATASHEET tab from the model before starting (if it exists)
Dim SummaryWB As Workbook
Dim vrtSelectedItem As Variant
For Each Sheet In ActiveWorkbook.Worksheets
If Sheet.Name = "DATASHEET" Then
Sheet.Delete
End If
Next Sheet
''' The below opens the RRS file from the file path defined
Dim RRSFile As Workbook
Set RRSFile = Workbooks.Open(Filename:="\\Template_Current.xlsx")
'' This will allow the workbook to open before continuing
DoEvents
'' This copies the Data from the RRS file and moves it into the CPM model in a new tab, and renames it.
'' It then closes the Source file.
Dim dataRange As Range
dataRange = RRSFile.Sheets("Data").Range("A1").UsedRange
Dim dataSheet As Worksheet
Windows("Report.xlsm").Activate
Set dataSheet = Sheets.Add(After:=Sheets("YAdd"))
dataSheet.Range("A1") = dataRange
dataSheet.Name = "DATASHEET"
RRSFile.Sheets("List View").Range ("D3")
dataSheet.Range("W1") = RRSFile.Sheets("List View").Range("D3")
RSSFile.Close True
Windows("Report.xlsm").Activate
'' and performs a lookup against the DATASHEET tab, matching the Account Number. It currently only
'' shows values if they are found/non-zero. It also clears old data from the columns
'' This also copies the outputed data and pastes only the values.
'' By doing so, we are saving future memory space, so that it doesn't need to recalc everytime you open
'' the file, only when you run this macro.
ProcessSheet Sheets("SHEET1")
ProcessSheet Sheets("SHEET2")
ProcessSheet Sheets("SHEET3")
ProcessSheet Sheets("SHEET4")
Sheets("DATASHEET").Visible = xlSheetHidden
With Application
.EnableEvents = True 'Turns background code back on.
.ScreenUpdating = True 'Turns ScreenUpdating back on.
.DisplayAlerts = True 'Turns Alerts back on.
End With
MsgBox "Import Complete"
End Sub
The big benefit you get here is that you can change that code in one place and it affects all 4 of your loops. Instead of trying to maintain 4 identical copies of the same code.

Need help cleaning up my currently working code

Just wondering if anyone can help me clean up my code. It currently works perfectly for what I need it to do. Just wondering if it can run faster. Right now it seems to open and close each workbook 3 times before moving to the next one.
Sub JanuaryMacro()
Dim strF As String, strP As String
Dim wb As Workbook
Range("B2:M2").clearcontents
'Edit this declaration to your folder name
strP = "\\My path" 'change for the path of your folder
strF = Dir(strP & "\*.xlsx")
Application.DisplayAlerts = False
Application.AskToUpdateLinks = False
Do While strF <> vbNullString
Set wb = Workbooks.Open(strP & "\" & strF)
Range("Totals").Select
Selection.Copy
Windows("Monthly Report.xlsm").Activate
Range("D2:M2").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlAdd, SkipBlanks _
:=False, Transpose:=False
Set wb = Workbooks.Open(strP & "\" & strF)
Range("FG_Approvals").Select
Selection.Copy
Windows("Monthly Report.xlsm").Activate
Range("C2").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlAdd, SkipBlanks _
:=False, Transpose:=False
Set wb = Workbooks.Open(strP & "\" & strF)
Range("Allocations").Select
Selection.Copy
Windows("Monthly Report.xlsm").Activate
Range("B2").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlAdd, SkipBlanks _
:=False, Transpose:=False
wb.Close SaveChanges:=False
strF = Dir()
Loop
Application.DisplayAlerts = True
End Sub
You should use references to your monthly-report-sheet, the new workbook and its sheet e. g. like this:
Sub JanuaryMacroVersion2()
Dim strF As String, strP As String
Dim mr As Worksheet
Dim wb As Workbook, ws As Worksheet
Set mr = ActiveSheet ' your monthly report
mr.Range("B2:M2").ClearContents
strP = "\\My path" 'change for the path of your folder
strF = Dir(strP & "\*.xlsx")
Application.DisplayAlerts = False
Application.AskToUpdateLinks = False
Do While strF <> vbNullString
Set wb = Workbooks.Open(strP & "\" & strF)
Set ws = ActiveSheet
ws.Range("Totals").Copy
mr.Range("D2:M2").PasteSpecial _
Paste:=xlPasteValues, Operation:=xlAdd, _
SkipBlanks:=False, Transpose:=False
ws.Range("FG_Approvals").Copy
mr.Range("C2").PasteSpecial _
Paste:=xlPasteValues, Operation:=xlAdd, _
SkipBlanks:=False, Transpose:=False
ws.Range("Allocations").Copy
mr.Range("B2").PasteSpecial _
Paste:=xlPasteValues, Operation:=xlAdd, _
SkipBlanks:=False, Transpose:=False
wb.Close SaveChanges:=False
strF = Dir()
Loop
Application.DisplayAlerts = True
End Sub
If the range names like "FG_Approvals" refer to a workbook wide name, replace ws.Range("FG_Approvals")by wb.Range("FG_Approvals").
Next optimization step would be omitting copy/paste by assigning their Range.Value directly:
Sub JanuaryMacroVersion3()
Dim strF As String, strP As String
Dim mr As Worksheet
Dim wb As Workbook, ws As Worksheet
Dim lastRow As Long
Set mr = ActiveSheet
mr.Range("B2:M2").ClearContents
strP = "\\My path" 'change for the path of your folder
strF = Dir(strP & "\*.xlsx")
Application.DisplayAlerts = False
Application.AskToUpdateLinks = False
Do While strF <> vbNullString
Set wb = Workbooks.Open(strP & "\" & strF)
Set ws = ActiveSheet
lastRow = mr.Cells(mr.Rows.Count, "D").End(xlUp).Row
mr.Cells(lastRow + 1, "D").Resize _
(ws.Range("Totals").Rows.Count, _
ws.Range("Totals").Columns.Count).Value _
= ws.Range("Totals").Value
lastRow = mr.Cells(mr.Rows.Count, "C").End(xlUp).Row
mr.Cells(lastRow + 1, "C").Resize _
(ws.Range("FG_Approvals").Rows.Count, _
ws.Range("FG_Approvals").Columns.Count).Value _
= ws.Range("FG_Approvals").Value
lastRow = mr.Cells(mr.Rows.Count, "B").End(xlUp).Row
mr.Cells(lastRow + 1, "B").Resize _
(ws.Range("Allocations").Rows.Count, _
ws.Range("Allocations").Columns.Count).Value _
= ws.Range("Allocations").Value
wb.Close SaveChanges:=False
strF = Dir()
Loop
Application.DisplayAlerts = True
End Sub

Resources