How to optimize VBA code to run faster [closed] - excel

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I need someone to save me on this one. I'm not a developer; I'm a QA. However, I've been tasked with creating a script that will take the mass data from one xlsx and creating new xlsx documents based on salesman, customer, and branch location. I have the code working, but it will take days for it to run if the computer it is running on does not run out of memory. I will post the code I have below. Is there any way to optimize it in order to run faster? We need it by Friday morning. Let me reiterate, I'm a QA. If you say do this or do that, I have no idea what you are talking about. I literally need "replace this with this". You guys have been awesome in you help so far, and I can't thank you enough. I don't know why you do what you do, but thank you for doing it.
Option Explicit
' get a named worksheet from specified workbook, creating it if required
Public Function GetSheet(ByVal Name As String, ByVal Book As Workbook, Optional ByVal Ignore As Boolean = False) As Worksheet
Dim Sheet As Worksheet
Dim Key As String
Dim Result As Worksheet: Set Result = Nothing
Key = UCase(Name)
' loop over all the worksheets
For Each Sheet In Book.Worksheets
' break out of the loop if the sheet is found
If UCase(Sheet.Name) = Key Then
Set Result = Sheet
Exit For
End If
Next Sheet
' if the sheet isn't found..
If Result Is Nothing Then
If Ignore = False Then
If Not GetSheet("Sheet1", Book, True) Is Nothing Then
' rename sheet1
Set Result = Book.Worksheets("Sheet1")
Result.Name = Name
End If
Else
' create a new sheet
Set Result = Book.Worksheets.Add
Result.Name = Name
End If
Result.Cells(1, 1) = "Rank"
Result.Cells(1, 2) = "Customer Segment"
Result.Cells(1, 3) = "Salesrep Name"
Result.Cells(1, 4) = "Main_Customer_NK"
Result.Cells(1, 5) = "Customer"
Result.Cells(1, 6) = "FY13 Sales"
Result.Cells(1, 7) = "FY13 Inv Cost GP$"
Result.Cells(1, 8) = "FY13 Inv Cost GP%"
Result.Cells(1, 9) = "Sales Growth"
Result.Cells(1, 10) = "GP Point Change"
Result.Cells(1, 11) = "Sales % Increase"
Result.Cells(1, 12) = "Budgeted Total Sales"
Result.Cells(1, 13) = "Budget GP%"
Result.Cells(1, 14) = "Budget GP$"
Result.Cells(1, 15) = "Target Account"
Result.Cells(1, 16) = "Estimated Total Purchases"
Result.Cells(1, 17) = "Estimated Sales Calls Monthly"
Result.Cells(1, 18) = "Notes"
Result.Cells(1, 19) = "Reference 1"
Result.Cells(1, 20) = "Reference 2"
'and the rest....
End If
Set GetSheet = Result
End Function
Sub Main()
Dim Source As Worksheet
Dim Location As Workbook
Dim Sales As Worksheet
Dim LocationKey As String
Dim SalesKey As String
Dim Index As Variant
Dim Map As Object: Set Map = CreateObject("Scripting.Dictionary")
Dim Row As Long
Dim InsertPos As Long
Set Source = ThisWorkbook.ActiveSheet
Row = 2 ' Skip header row
Do
' break out of the loop - assumes that the first empty row signifies the end
If Source.Cells(Row, 1).Value2 = "" Then
Exit Do
End If
LocationKey = Source.Cells(Row, 3).Value2
' look at the location, and find the workbook, creating it if required
If Map.Exists(LocationKey) Then
Set Location = Map(LocationKey)
Else
Set Location = Application.Workbooks.Add(xlWBATWorksheet)
Map.Add LocationKey, Location
End If
SalesKey = Source.Cells(Row, 5).Value2
' get the sheet for the salesperson
Set Sales = GetSheet(SalesKey, Location)
' Get the location to enter the data
InsertPos = Sales.Range("A1").End(xlDown).Row + 1
'check to see if it's a new sheet, and adjust
If InsertPos = 1048577 Then
'Stop
InsertPos = 2
'change to 65537 is using excel 2003 or before
Macro1
End If
' populate said row with the data from the source
Sales.Cells(InsertPos, 1).Value2 = Source.Cells(Row, 1)
Sales.Cells(InsertPos, 2).Value2 = Source.Cells(Row, 2)
Sales.Cells(InsertPos, 3).Value2 = Source.Cells(Row, 5)
Sales.Cells(InsertPos, 4).Value2 = Source.Cells(Row, 6)
Sales.Cells(InsertPos, 5).Value2 = Source.Cells(Row, 7)
Sales.Cells(InsertPos, 6).Value2 = Source.Cells(Row, 8)
Sales.Cells(InsertPos, 7).Value2 = Source.Cells(Row, 9)
Sales.Cells(InsertPos, 8).Value2 = Source.Cells(Row, 10)
Sales.Cells(InsertPos, 9).Value2 = Source.Cells(Row, 11)
Sales.Cells(InsertPos, 10).Value2 = Source.Cells(Row, 12)
Sales.Cells(InsertPos, 11).Value2 = Source.Cells(Row, 13)
Sales.Cells(InsertPos, 12).Value2 = Source.Cells(Row, 14)
Sales.Cells(InsertPos, 13).Value2 = Source.Cells(Row, 15)
Sales.Cells(InsertPos, 14).Value2 = Source.Cells(Row, 16)
Sales.Cells(InsertPos, 19).Value2 = Source.Cells(Row, 17)
Sales.Cells(InsertPos, 20).Value2 = Source.Cells(Row, 18)
Sales.Range("L" & InsertPos).Formula = "=(F2*K2)+F2"
Sales.Range("N" & InsertPos).Formula = "=(M2+H2)*L2"
'increment the loop
'Range("H" & InsertPos).Activate
'If Range("F" & InsertPos) = 0 Then ActiveCell.Value = 0 Else If 1 = 1 Then ActiveCell.Formula = (100 * Range("G" & InsertPos) / Range("F" & InsertPos))
'Range("I" & InsertPos).Activate
'If Range("S" & InsertPos) = 0 Then ActiveCell.Value = 0 Else If 1 = 1 Then ActiveCell.Formula = (Range("F" & InsertPos) / Range("S" & InsertPos) - 1)
'Range("J" & InsertPos).Activate
'If Range("S" & InsertPos) = 0 Then ActiveCell.Value = 0 Else If 1 = 1 Then ActiveCell.Formula = (Range("T" & InsertPos) / Range("S" & InsertPos))
Row = Row + 1
Macro2 'runs on each cell
Loop
' loop over the resulting workbooks and save them - using the location name as file name
For Each Index In Map.Keys
Set Location = Map(Index)
Location.SaveAs Filename:=Index
Next Index
End Sub
Sub Macro1()
'
' Macro1 Macro
'
'
Cells.Select
Cells.EntireColumn.AutoFit
Columns("F:G").Select
Selection.NumberFormat = "$#,##0.00"
ActiveWindow.SmallScroll ToRight:=3
Columns("H:J").Select
Selection.NumberFormat = "0.00%"
Selection.NumberFormat = "0.0%"
ActiveWindow.ScrollColumn = 5
ActiveWindow.ScrollColumn = 6
Range("K:K,M:M").Select
Range("M1").Activate
Selection.NumberFormat = "0.0%"
Range("N:N,L:L").Select
Range("L1").Activate
Selection.NumberFormat = "$#,##0.00"
ActiveWindow.SmallScroll ToRight:=5
Columns("S:T").Select
Selection.EntireColumn.Hidden = True
ActiveWindow.SmallScroll ToRight:=-4
Range("K:K,M:M").Select
Range("M1").Activate
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorLight2
.TintAndShade = 0.599993896298105
.PatternTintAndShade = 0
End With
Cells.Select
'Selection.Subtotal GroupBy:=2, Function:=xlSum, TotalList:=Array(6, 7, 12, _
'14), Replace:=True, PageBreaks:=False, SummaryBelowData:=True
'Cells.Select
'Range("L9").Activate
'Selection.Subtotal GroupBy:=2, Function:=xlSum, TotalList:=Array(6, 7, 12, _
'14), Replace:=True, PageBreaks:=False, SummaryBelowData:=True
'Cells.Select
'Cells.EntireColumn.AutoFit
'Selection.Subtotal GroupBy:=2, Function:=xlSum, TotalList:=Array(6, 7, 12, _
'14), Replace:=True, PageBreaks:=False, SummaryBelowData:=True
End Sub
Sub Macro2()
'
' Macro2 Macro
'
'
Cells.EntireColumn.AutoFit
Selection.Subtotal GroupBy:=2, Function:=xlSum, TotalList:=Array(6, 7, 12, _
14, 20), Replace:=True, PageBreaks:=False, SummaryBelowData:=True
End Sub

Just got rid of some select statements, added some loops, and turned off screen updating and set calculation to manual while executing. I have added some comments here and there, check them out too. See if that helps
Option Explicit
Sub Main()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim Source As Worksheet
Dim Location As Workbook
Dim Sales As Worksheet
Dim LocationKey As String
Dim SalesKey As String
Dim Index As Variant
Dim Map As Object: Set Map = CreateObject("Scripting.Dictionary")
Dim Row As Long
Dim InsertPos As Long
Set Source = ThisWorkbook.ActiveSheet
Row = 2 ' Skip header row
Do
' break out of the loop - assumes that the first empty row signifies the end
If Source.Cells(Row, 1).Value2 = "" Then
Exit Do
End If
LocationKey = Source.Cells(Row, 3).Value2
' look at the location, and find the workbook, creating it if required
If Map.Exists(LocationKey) Then
Set Location = Map(LocationKey)
Else
Set Location = Application.Workbooks.Add(xlWBATWorksheet)
Map.Add LocationKey, Location
End If
SalesKey = Source.Cells(Row, 5).Value2
' get the sheet for the salesperson
Set Sales = GetSheet(SalesKey, Location)
' Get the location to enter the data
InsertPos = Sales.Range("A1").End(xlDown).Row + 1
'check to see if it's a new sheet, and adjust
If InsertPos = 1048577 Then
'Stop
InsertPos = 2
'change to 65537 is using excel 2003 or before
Macro1
End If
' populate said row with the data from the source
Dim i As Long
For i = 1 To 2
Sales.Cells(InsertPos, i).Value2 = Source.Cells(Row, i)
Next i
For i = 3 To 14
Sales.Cells(InsertPos, i).Value2 = Source.Cells(Row, i + 2)
Next i
For i = 19 To 20
Sales.Cells(InsertPos, i).Value2 = Source.Cells(Row, i - 2)
Next i
Sales.Range("L" & InsertPos).Formula = "=(F2*K2)+F2"
Sales.Range("N" & InsertPos).Formula = "=(M2+H2)*L2"
'increment the loop
'Range("H" & InsertPos).Activate
'If Range("F" & InsertPos) = 0 Then ActiveCell.Value = 0 Else If 1 = 1 Then ActiveCell.Formula = (100 * Range("G" & InsertPos) / Range("F" & InsertPos))
'Range("I" & InsertPos).Activate
'If Range("S" & InsertPos) = 0 Then ActiveCell.Value = 0 Else If 1 = 1 Then ActiveCell.Formula = (Range("F" & InsertPos) / Range("S" & InsertPos) - 1)
'Range("J" & InsertPos).Activate
'If Range("S" & InsertPos) = 0 Then ActiveCell.Value = 0 Else If 1 = 1 Then ActiveCell.Formula = (Range("T" & InsertPos) / Range("S" & InsertPos))
Row = Row + 1
Macro2 'runs on each cell
Loop
' loop over the resulting workbooks and save them - using the location name as file name
For Each Index In Map.Keys
Set Location = Map(Index)
Location.SaveAs Filename:=Index
Next Index
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
' get a named worksheet from specified workbook, creating it if required
Public Function GetSheet(ByVal Name As String, ByVal Book As Workbook, Optional ByVal Ignore As Boolean = False) As Worksheet
Dim Sheet As Worksheet
Dim Key As String
Dim Result As Worksheet: Set Result = Nothing
Key = UCase(Name)
' loop over all the worksheets
For Each Sheet In Book.Worksheets
' break out of the loop if the sheet is found
If UCase(Sheet.Name) = Key Then
Set Result = Sheet
Exit For
End If
Next Sheet
' if the sheet isn't found..
If Result Is Nothing Then
If Ignore = False Then
If Not GetSheet("Sheet1", Book, True) Is Nothing Then
' rename sheet1
Set Result = Book.Worksheets("Sheet1")
Result.Name = Name
End If
Else
' create a new sheet
Set Result = Book.Worksheets.Add
Result.Name = Name
End If
Dim arr
arr = Array("Rank", "Customer Segment", "Salesrep Name", "Main_Customer_NK", "Customer", "FY13 Inv Cost GP$", "FY13 Inv Cost GP%", "Sales Growth", "GP Point Change", "Sales % Increase", _
"Budgeted Total Sales", "Budget GP%", "Budget GP$", "Target Account", "Estimated Total Purchases", "Estimated Sales Calls Monthly", "Notes", "Reference 1", "Reference 2")
Dim i As Long
For i = LBound(arr) To UBound(arr)
Result.Cells(1, i + 1) = arr(i)
Next i
' stick the rest in the arr variable and you dont need the below anymore
'Result.Cells(1, 1) = "Rank"
'Result.Cells(1, 2) = "Customer Segment"
'Result.Cells(1, 3) = "Salesrep Name"
'Result.Cells(1, 4) = "Main_Customer_NK"
'Result.Cells(1, 5) = "Customer"
'Result.Cells(1, 6) = "FY13 Sales"
'Result.Cells(1, 7) = "FY13 Inv Cost GP$"
'Result.Cells(1, 8) = "FY13 Inv Cost GP%"
'Result.Cells(1, 9) = "Sales Growth"
'Result.Cells(1, 10) = "GP Point Change"
'Result.Cells(1, 11) = "Sales % Increase"
'Result.Cells(1, 12) = "Budgeted Total Sales"
'Result.Cells(1, 13) = "Budget GP%"
'Result.Cells(1, 14) = "Budget GP$"
'Result.Cells(1, 15) = "Target Account"
'Result.Cells(1, 16) = "Estimated Total Purchases"
'Result.Cells(1, 17) = "Estimated Sales Calls Monthly"
'Result.Cells(1, 18) = "Notes"
'Result.Cells(1, 19) = "Reference 1"
'Result.Cells(1, 20) = "Reference 2"
'and the rest....
End If
Set GetSheet = Result
End Function
Sub Macro1()
' avoid using Select
Columns.AutoFit
Columns("F:G").NumberFormat = "$#,##0.00"
Columns("H:J").NumberFormat = "0.0%"
Range("K:K,M:M").NumberFormat = "0.0%"
Range("N:N,L:L").NumberFormat = "$#,##0.00"
Columns("S:T").EntireColumn.Hidden = True
With Range("K:K,M:M").Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorLight2
.TintAndShade = 0.599993896298105
.PatternTintAndShade = 0
End With
'Selection.Subtotal GroupBy:=2, Function:=xlSum, TotalList:=Array(6, 7, 12, _
'14), Replace:=True, PageBreaks:=False, SummaryBelowData:=True
'Cells.Select
'Range("L9").Activate
'Selection.Subtotal GroupBy:=2, Function:=xlSum, TotalList:=Array(6, 7, 12, _
'14), Replace:=True, PageBreaks:=False, SummaryBelowData:=True
'Cells.Select
'Cells.EntireColumn.AutoFit
'Selection.Subtotal GroupBy:=2, Function:=xlSum, TotalList:=Array(6, 7, 12, _
'14), Replace:=True, PageBreaks:=False, SummaryBelowData:=True
End Sub
Sub Macro2()
Columns.AutoFit
'Selection.Subtotal GroupBy:=2, Function:=xlSum, TotalList:=Array(6, 7, 12, _
14, 20), Replace:=True, PageBreaks:=False, SummaryBelowData:=True
End Sub

Related

Copy cell values for each unique row value

I have created a report that copy/paste values from different columns in each row to a new sheet and then saves it as a pdf.
Instead of saving the PDF after each row, I would like to have it loop through all the rows with the same pile number. For example, each pile might have three rows, in which case I want to copy/paste values from the three rows before saving the pdf. Once the unique pile is done, it can continue to save the pdf and then loop to the next pile.
Any suggestions would be greatly appreciated.
Sub ExportingPDF()
'Defining worksheets
Dim detailsSheet As Worksheet
Dim reportSheet As Worksheet
Dim i As Long
Dim LastRow As Long
LastRow = Range("B" & Rows.Count).End(xlUp).Row
'Looping the through each row
For i = 2 To LastRow
Set reportSheet = ActiveWorkbook.Sheets("Contract Form")
Set detailsSheet = ActiveWorkbook.Sheets("New POs")
'Assigning values
SPile = detailsSheet.Cells(i, 2)
SClient = detailsSheet.Cells(i, 1)
SCommodity = detailsSheet.Cells(i, 2)
SOption = detailsSheet.Cells(i, 3)
SQtyMT = detailsSheet.Cells(i, 4)
SPriceMT = detailsSheet.Cells(i, 5)
SWhs = detailsSheet.Cells(i, 6)
SIncoterm = detailsSheet.Cells(i, 8)
SDeliveryCity = detailsSheet.Cells(i, 9)
SPO = detailsSheet.Cells(i, 11)
SDeliveryDate = detailsSheet.Cells(i, 14)
SWhsAddress = detailsSheet.Cells(i, 18)
SClientAddress = detailsSheet.Cells(i, 15)
SClientTownZip = detailsSheet.Cells(i, 16)
'Generating the output
'reportSheet.Cells(19, 1).Value = SPile
'reportSheet.Cells(17, 1).Value = SClient
reportSheet.Cells(17, 1).Value = SCommodity
reportSheet.Cells(17, 5).Value = SOption
reportSheet.Cells(17, 4).Value = SIncoterm
'reportSheet.Cells(1, 1).Value = SWhs
reportSheet.Cells(17, 2).Value = SDeliveryCity
reportSheet.Cells(21, 2).Value = SPriceMT
reportSheet.Cells(17, 6).Value = SPO
reportSheet.Cells(17, 3).Value = SDeliveryDate
'reportSheet.Cells(5, 1).Value = SWhsAddress
reportSheet.Cells(21, 1).Value = SQtyMT
reportSheet.Cells(10, 6).Value = SClient
reportSheet.Cells(11, 6).Value = SClientAddress
reportSheet.Cells(12, 6).Value = SClientTownZip
'Save the PDF file
Worksheets("Contract Form").Range("A1:G28").ExportAsFixedFormat Type:=xlTypePDF,
Filename:= _
Environ("Userprofile") & "\Desktop\" & SPO & ".PDF", Quality:=xlQualityStandard, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, _
OpenAfterPublish:=False
With ActiveSheet.PageSetup
.Zoom = False
.Orientation = xlPortrait
.FitToPagesWide = 1
.FitToPagesTall = 1
End With
Next i
End Sub

VBA Displaying Cell Reference and Table Range

So i have this userform that allows the user to key in the number of creditors and the number of rows for the table, then after the user clicks confirm, it will generate based on the input values
And now I need this details like which cell contains creditor name 1 and which range is creditor name 1 table like this picture below:
My current code is
'Clears Sheet then generates Number of Creditors & Rows
Worksheets("Payable Conf - by Invoice").Cells.Clear
Dim CreditorsCount As Integer
Dim Counter As Integer
Dim Rows As Integer
If TextBox1.Text <> "" And TextBox2.Text <> "" Then
CreditorsCount = TextBox1.Value
Counter = 0
CreditorsCount2 = 0
Rows = TextBox2.Value
End If
Worksheets("Payable Conf - by Invoice").Activate
While Counter < CreditorsCount
Cells((Counter * (5 + Rows) + 1), 1).Activate
With Range(ActiveCell.Address, ActiveCell.Offset(0, 4))
.Value = Array("Creditor Name " & CStr(Counter + 1), "Creditor Address 1", "Creditor Address 2", "Creditor Address 3", "Staff Email (e.g. abc123#gmail.com)")
.Font.Bold = True
End With
With Range(ActiveCell.Offset(3, 0), ActiveCell.Offset(3, 2))
.Value = Array("Invoice No.", "Invoice Date", "Amount (e.g. $100)")
.Font.Bold = True
End With
With Union(Range(ActiveCell.Address, ActiveCell.Offset(1, 4)), Range(ActiveCell.Offset(3, 0), ActiveCell.Offset(3 + Rows, 2)))
.BorderAround XlLineStyle.xlContinuous, xlThin
.Borders(xlInsideHorizontal).LineStyle = xlContinuous
.Borders(xlInsideVertical).LineStyle = xlContinuous
End With
Counter = Counter + 1
Wend
Worksheets("Payable Conf - by Invoice").Range("I8") = "Please do not edit"
Worksheets("Payable Conf - by Invoice").Range("I9") = "Number of Creditors:"
Worksheets("Payable Conf - by Invoice").Range("J9") = TextBox1.Value
Worksheets("Payable Conf - by Invoice").Range("I10") = "Number of Rows:"
Worksheets("Payable Conf - by Invoice").Range("J10") = TextBox2.Value
Help is greatly appreciated :)
Maybe something like this ?
Sub test()
Dim rg1 As Range
Dim rg2 As Range
Dim cnt As Integer
Dim TotRow As Integer
Dim tbl As Range
cnt = 5
TotRow = 10
With Sheets("Payable Conf - by Invoice")
'.Activate
.Cells.Delete
Set rg1 = .Range("A1")
Set rg2 = .Range("i8")
End With
With rg2
.Resize(3, 1).Value = Application.Transpose(Array("do not edit", "num cred", "num rows"))
.Offset(1, 1).Value = cnt
.Offset(2, 1).Value = TotRow
Set rg2 = rg2.Offset(4, 0)
End With
For i = 1 To cnt
With rg1.Resize(1, 5)
.Value = Array("cr name " & CStr(i), "add1", "add2", "add3", "email")
.Font.Bold = True
.Resize(2, 5).Borders.LineStyle = xlContinuous
End With
Set rg1 = rg1.Offset(3, 0)
With rg1.Resize(1, 3)
.Value = Array("Inv No", "Inv Date", "Inv Amount")
.Font.Bold = True
Set tbl = .Resize(TotRow + 1, 3)
tbl.Borders.LineStyle = xlContinuous
End With
With rg2
.Offset(0, 0).Value = "cred name " & CStr(i) & ":"
.Offset(0, 1).Value = rg1.Offset(-2, 0).Address(0, 0)
.Offset(1, 0).Value = "tbl " & CStr(i) & ":"
.Offset(1, 1).Value = tbl.Address(0, 0)
End With
Set rg1 = rg1.Offset(TotRow + 2, 0)
Set rg2 = rg2.Offset(3, 0)
Next i
End Sub
Please try to run the sub on a new workbook.
If the result is the one that you expected, just change the cnt variable value and the TotRow variable value to your TextBox1.value and TextBox2.value

How can I speed this vba code up which involves formatting?

I am setting up a new pricing schedule which reads selected information from a 'Register' tab, based on selected criteria, and copying this into a new tab. This data is formatted so it looks aesthetically pleasing.
I am finding formatting the code is slowing down the run speed significantly. If possible I would like to speed this up as I will be iterating this multiple times.
I hae sped the program up a reasonable amount. Initially it took 30s, whereas now it is about 10s.
I have followed information from this website as best as I can:
https://www.soa.org/News-and-Publications/Newsletters/Compact/2012/january/com-2012-iss42-roper.aspx
I feel there is still scope to improve more, though I am unsure how, and am reaching out to see if there is, or are, better ways to improve the code so it runs quicker.
Option Explicit
Sub create_pricing_schedule()
'define workbook variables
Dim Start_Time As Double, End_Time As Double
Dim file1 As Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim ws3 As Worksheet
Dim ws4 As Worksheet
Dim namedRange1 As Range
Dim namedRange2 As Range
Set file1 = ThisWorkbook
Set ws2 = file1.Worksheets("Pricing Schedule")
Set ws3 = file1.Worksheets("Control")
Set ws4 = file1.Worksheets("Register")
Set namedRange1 = file1.Names("Client_Register").RefersToRange
Set namedRange2 = file1.Names("Pricing_Range").RefersToRange
'define general variables
Dim i As Integer
Dim collect(1 To 500, 1 To 10) As Variant
Dim rw As Range
Dim selectedClient As String
Dim lastrow As Integer, lastrow2 As Integer, lastrow3 As Integer
i = 1
'time how long it takes to improve efficiency
Start_Time = Timer
'speedup so less lagg
Call speedup
'delete everything from the pricing schedule/reset
With Sheets("Pricing Schedule")
.UsedRange.ClearContents
.Cells.Interior.ColorIndex = 0
.Cells.Borders.LineStyle = xlNone
.Cells.HorizontalAlignment = xlLeft
.Cells.MergeCells = False
.Range("A:Z").WrapText = False
.Rows.RowHeight = "15"
End With
'resize the client register
lastrow = ws4.Range("A100000").End(xlUp).Row
With ActiveWorkbook.Names("Client_Register")
.RefersTo = "=Register!$A$1:$AE$" & lastrow
End With
selectedClient = ws3.Range("B3").Value
'copy from database to the pricing schedule as a non formatted list of all the info - this runs quickly, but I am open to changing it
For Each rw In Range("Client_Register").Rows
If Range("Client_Register").Cells(rw.Row, 2) = selectedClient Then
collect(i, 1) = Range("Client_Register").Range("E" & rw.Row)
collect(i, 2) = Range("Client_Register").Range("D" & rw.Row)
collect(i, 3) = Range("Client_Register").Range("F" & rw.Row)
collect(i, 4) = Range("Client_Register").Range("J" & rw.Row)
collect(i, 5) = Range("Client_Register").Range("K" & rw.Row)
collect(i, 6) = Range("Client_Register").Range("L" & rw.Row)
collect(i, 7) = Range("Client_Register").Range("M" & rw.Row)
collect(i, 8) = Range("Client_Register").Range("P" & rw.Row)
collect(i, 9) = Range("Client_Register").Range("I" & rw.Row)
collect(i, 10) = Range("Client_Register").Range("H" & rw.Row) ' used to determine if pass through fee
ws2.Range("B" & i + 6) = collect(i, 1)
ws2.Range("C" & i + 6) = collect(i, 2)
ws2.Range("D" & i + 6) = collect(i, 3)
ws2.Range("E" & i + 6) = collect(i, 4)
ws2.Range("F" & i + 6) = collect(i, 5)
ws2.Range("G" & i + 6) = collect(i, 6)
ws2.Range("H" & i + 6) = collect(i, 7)
ws2.Range("I" & i + 6) = collect(i, 8)
ws2.Range("J" & i + 6) = collect(i, 9)
ws2.Range("K" & i + 6) = collect(i, 10)
i = i + 1
End If
Next
'add in the colour and count how many rows there are
lastrow2 = ws2.Range("C5000").End(xlUp).Row
With ActiveWorkbook.Names("Pricing_Range")
.RefersTo = "='Pricing Schedule'!$A$1:$K$" & lastrow2
End With
ws2.Range("B7" & ":" & "J" & lastrow2).Interior.Color = RGB(242, 242, 242)
'==========this bit is slow, can it be quicker?==========
'add spacing, titles, and colour to sub headers
i = 7
For Each rw In Range("Pricing_Range").Rows
If Range("Pricing_Range").Cells(i, 3) <> Range("Pricing_Range").Cells(i + 1, 3) Then
Range("Pricing_Range").Rows(i + 1).Insert Shift:=xlShiftDown
Range("Pricing_Range").Rows(i + 1).Insert Shift:=xlShiftDown
Range("Pricing_Range").Rows(i + 1).Interior.ColorIndex = 0
Range("Pricing_Range").Rows(i + 2).Interior.ColorIndex = 0
Range("Pricing_Range").Range("B" & i + 2 & ":" & "J" & i + 2).Interior.Color = RGB(255, 128, 1)
Range("Pricing_Range").Range("B" & i + 2 & ":" & "J" & i + 2).Borders(xlEdgeTop).Color = RGB(0, 0, 0)
Range("Pricing_Range").Range("B" & i + 2 & ":" & "J" & i + 2).Borders(xlEdgeBottom).Color = RGB(0, 0, 0)
Range("Pricing_Range").Range("B" & i + 2).Value = Range("Pricing_Range").Range("C" & i + 3).Value
'if it is a pass through fee then add it in to the sub headers
If Range("Pricing_Range").Range("K" & i + 3).Value = "Pass-Through" Then
Range("Pricing_Range").Range("J" & i + 2).Value = "Pass-Through Fees"
Range("Pricing_Range").Range("J" & i + 2).HorizontalAlignment = xlRight
End If
i = i + 3
Else
i = i + 1
End If
Next
'==================================================
'set up the main title rows
ws2.Select
Range("Pricing_Range").Range("B2").Value = ws3.Range("B3").Value
Range("Pricing_Range").Range("B2").Font.Size = 20
Range("Pricing_Range").Range("B2").Font.Bold = True
Range("Pricing_Range").Range("B2").Font.FontStyle = "Calibri Light"
Range("Pricing_Range").Range("B2:J3").Select
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = False
.MergeCells = True
.Cells.Interior.Color = RGB(255, 128, 1)
.Cells.Borders(xlEdgeTop).Color = RGB(0, 0, 0)
.Cells.Borders(xlEdgeBottom).Color = RGB(0, 0, 0)
End With
'tidy up things in the sheet
With Worksheets("Pricing Schedule")
'set up the headers and first title
.Range("B6") = .Range("C7")
.Range("B5:J6").Interior.Color = RGB(255, 128, 1)
.Range("B5:J5").Borders(xlEdgeTop).Color = RGB(0, 0, 0)
.Range("B5:J5").Borders(xlEdgeBottom).Color = RGB(0, 0, 0)
.Range("B6:J6").Borders(xlEdgeTop).Color = RGB(0, 0, 0)
.Range("B6:J6").Borders(xlEdgeBottom).Color = RGB(0, 0, 0)
.Range("B5").Value = "Fee Code"
.Range("C5").Value = "Product Line"
.Range("D5").Value = "Item"
.Range("E5").Value = "Volume From"
.Range("F5").Value = "Volume To"
.Range("G5").Value = "Frequency"
.Range("H5").Value = "Location"
.Range("I5").Value = "Price"
.Range("J5").Value = "Nature of Fee"
'tidy up column widths
.Range("A5").RowHeight = 30
.Range("A1").ColumnWidth = 2
.Range("B1").ColumnWidth = 15
.Range("C1").ColumnWidth = 40
.Range("D1").ColumnWidth = 45
.Range("E1").ColumnWidth = 11
.Range("F1").ColumnWidth = 11
.Range("G1").ColumnWidth = 35
.Range("H1").ColumnWidth = 15
.Range("I1").ColumnWidth = 12
.Range("J1").ColumnWidth = 50
.Range("J:J").WrapText = True
.Range("K:K").Delete
End With
'clear the extra orange line at the end
lastrow3 = ws2.Range("B1000").End(xlUp).Row
With ws2.Rows(lastrow3 + 2)
.Cells.Interior.ColorIndex = 0
.Cells.Borders.LineStyle = xlNone
.ClearContents
End With
'add print area
With Worksheets("Pricing Schedule")
.PageSetup.Zoom = False
.PageSetup.Orientation = xlPortrait
.PageSetup.PrintArea = "$B$2:$J$" & lastrow3
.PageSetup.FitToPagesWide = 1
.PageSetup.FitToPagesTall = False
.PageSetup.PrintTitleRows = "$2:$6"
End With
'return to normal
Call slowdown
'time how long it takes to improve efficiency
End_Time = Timer
Worksheets("Control").Cells(6, 2) = End_Time - Start_Time
End Sub
Sub speedup()
Application.Calculation = xlManual
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.DisplayStatusBar = False
End Sub
Sub slowdown()
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.DisplayStatusBar = True
End Sub
I found a few lines that could save you some execution time.
'****EDIT****Changed this to direct range reference rather than go through the Names collection.
'Set namedRange1 = file1.Names("Client_Register").RefersToRange
'Set namedRange2 = file1.Names("Pricing_Range").RefersToRange
Set namedRange1 = file1.Range("Client_Register")
Set namedRange2 = file1.Range("Pricing_Range")
Used range takes more time rather use .cells directly
'delete everything from the pricing schedule/reset
'****EDIT***
With ws2 'Sheets("Pricing Schedule")
'used range takes more time rather use .cells directly
.Cells.ClearContents
Rather than use arrays you can directly update values as shown below
'I am using i for the row count
ws2.Range("B" & i + 6).Value = namedRange1.Cells(i, 5).Value
ws2.Range("C" & i + 6).Value = namedRange1.Cells(i, 4).Value
ws2.Range("D" & i + 6).Value = namedRange1.Cells(i, 6).Value
ws2.Range("E" & i + 6).Value = namedRange1.Cells(i, 10).Value
ws2.Range("F" & i + 6).Value = namedRange1.Cells(i, 11).Value
ws2.Range("G" & i + 6).Value = namedRange1.Cells(i, 12).Value
ws2.Range("H" & i + 6).Value = namedRange1.Cells(i, 12).Value
ws2.Range("I" & i + 6).Value = namedRange1.Cells(i, 16).Value
ws2.Range("J" & i + 6).Value = namedRange1.Cells(i, 9).Value
ws2.Range("K" & i + 6).Value = namedRange1.Cells(i, 8).Value
i = i + 1
The main culprit for your slower performance is the insert operation. try to work the logic to not having insert. If not possible, try to insert rows outside the loop in a single operation rather than in the loop
Range("Pricing_Range").Rows(i + 1).Insert Shift:=xlShiftDown
Range("Pricing_Range").Rows(i + 1).Insert Shift:=xlShiftDown
Your handling of the collect array is inefficient. Consider reading the entire Client Register into an array with MyArray = Range.Value. Then prepare the output array in memory and write it to the worksheet after all looping is done, in one go, with TargetRange.Value = collect.
Avoid inserting rows. What's wrong with the existing? If you are preparing all data in an array to be pasted to the worksheet, empty array elements will produce empty worksheet cells. In this way all inserting can be avoided and all you need to do is to format.
There is time cost for every access to the worksheet, whether to read or write. Even for formatting, try to create ranges that are treated in the same manner. Avoid accessing the worksheet in loops.
Example of With and block assignment from an array:
'copy from database to the pricing schedule as a
' non formatted list of all the info - this runs quickly,
' but I am open to changing it
With Range("Client_Register")
For Each rw In .Rows
If .Cells(rw.Row, 2) = selectedClient Then
collect(i, 1) = .Range("E" & rw.Row)
collect(i, 2) = .Range("D" & rw.Row)
collect(i, 3) = .Range("F" & rw.Row)
collect(i, 4) = .Range("J" & rw.Row)
collect(i, 5) = .Range("K" & rw.Row)
collect(i, 6) = .Range("L" & rw.Row)
collect(i, 7) = .Range("M" & rw.Row)
collect(i, 8) = .Range("P" & rw.Row)
collect(i, 9) = .Range("I" & rw.Row)
collect(i, 10) = .Range("H" & rw.Row)
'you could even skip the row-by-row population of values
' and assign as a block after exiting the loop
ws2.Range("B" & i + 6).Resize(1, 10).Value = _
Array(collect(i, 1), collect(i, 2), collect(i, 3), _
collect(i, 4), collect(i, 5), collect(i, 6), _
collect(i, 7), collect(i, 8), collect(i, 9), _
collect(i, 10))
i = i + 1
End If
Next
End With
Note this will break if your Client_Register refers to a range which doesn't start on Row1, because of the relative range references.
Eg:
Range("A1:A10").Range("A1") 'refers to A1
Range("A2:A10").Range("A1") 'refers to A2

Error on formula in another worksheet cell that includes hyperlink with activesheet.name

[Here is the error code when trying to include the cell reference][1]
Private Sub adduserCommandButton_Click()
Dim finduserrow As Range
Dim rowNo As Integer
Dim findsalesrow As Range
Dim salesNo As Integer
Dim icounter As Long
Dim sales As String
Dim sumformula As String
Dim username As String
Dim lastrow As Long
Dim userMsheet As Worksheet
Dim currentSheetname As Worksheet
Set userMsheet = Sheets("User&Sales Maintenance")
sales = "No. of Sales"
'Value to search for user row
Set findsalesrow = ActiveSheet.Range("C:C").Find(What:=sales)
username = usernameComboBox.Text
If findsalesrow Is Nothing Then
MsgBox "User not found! Please add user!"
Else
salesNo = findsalesrow.Row
sumformula = "=Sum(H" & salesNo - 1 & " : H" & salesNo & ")"
ActiveSheet.Rows(salesNo - 1).Insert Shift:=xlShiftDown,
CopyOrigin:=xlFormatFromRightOrBelow
ActiveSheet.Rows(salesNo - 1).Insert Shift:=xlShiftDown,
CopyOrigin:=xlFormatFromRightOrBelow
ActiveSheet.Cells(salesNo - 1, 2).Value = countryTextBox.Value
ActiveSheet.Cells(salesNo - 1, 3).Value = usernameComboBox.Value
ActiveSheet.Cells(salesNo - 1, 5).Value = ActiveSheet.Name & "IPC Dual
Routers & Leased Lines"
ActiveSheet.Cells(salesNo - 1, 8).Formula = "=$H$5"
ActiveSheet.Cells(salesNo, 4).Value = companyComboBox.Value
ActiveSheet.Cells(salesNo, 5).Value = ActiveSheet.Name & "Client
connection -" & companyComboBox.Value
ActiveSheet.Cells(salesNo, 6).Value = oneTimeTextBox.Value
ActiveSheet.Cells(salesNo, 7).Value = actualMonthlyTextBox.Value
ActiveSheet.Cells(salesNo, 8).Value = actualMonthlyTextBox.Value
ActiveSheet.Cells(salesNo, 9).Value = "Monthly Cost Charge Gross on " &
usernameComboBox.Value
ActiveSheet.Rows(salesNo + 1).Insert Shift:=xlShiftDown,
CopyOrigin:=xlFormatFromRightOrBelow
ActiveSheet.Range(Cells(salesNo + 1, 2), Cells(salesNo + 1, 10)).Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 8388736
.TintAndShade = 0
.PatternTintAndShade = 0
End With
ActiveSheet.Cells(salesNo + 1, 5).Value = "Subtotal for " &
usernameComboBox.Value
ActiveSheet.Cells(salesNo + 1, 5).Select
With Selection.Font
.ThemeColor = xlThemeColorDark1
.TintAndShade = 0
.Bold = True
End With
ActiveSheet.Cells(salesNo + 1, 8).Value = sumformula
ActiveSheet.Cells(salesNo + 1, 8).Select
With Selection.Font
.ThemeColor = xlThemeColorDark1
.TintAndShade = 0
.Bold = True
End With
MsgBox username & " 's Details Has Been added!"
countryTextBox.Text = ""
companyComboBox.Text = ""
usernameComboBox.Text = ""
oneTimeTextBox.Text = ""
actualMonthlyTextBox.Text = ""
With userMsheet
lastrow = Sheets("User&Sales Maintenance").Range("A" &
Rows.Count).End(xlUp).Row
Sheets("User&Sales Maintenance").Cells(lastrow + 1, "A").Formula =
"=HYPERLINK(" & ActiveSheet.Name & "!" & Cells(salesNo - 1, 3).Address
& "," & usernameComboBox.Value & ")"
End With
End If
End Sub
Also the activesheet name is called Sharing Company, so the purpose is to link the cell from Sheet("User and sales Maintenance) to this worksheet called Sharing Company with the respective cells
Can somebody explain to me how to fix this problem? I can't seem to figure out when and where to put & and quotation marks when using activesheet.name as well as cells(salesno - 1, 3) in the script. Thanks in advance!

Copy value of entire row and past it into a different worksheet

I have the following code:
Option Explicit
Dim LastRow As Long
Dim i As Long
Dim myCell2 As Range
Dim oWkSht As Worksheet
Private Sub Worksheet_Activate()
Application.ScreenUpdating = False
'-------------------------------------------
'//Head Row A1\\
'-------------------------------------------
Range("A1").Value = "Department"
Range("B1").Value = "AOS Location"
Range("C1").Value = "Article Number"
Range("D1").Value = "HFB"
Range("E1").Value = "Article Name"
Range("F1").Value = "General Comments"
Range("G1").Value = "Home Location"
Range("H1").Value = "A. Stock"
Range("I1").Value = "SGF"
Range("J1").Value = "Incoming Good"
Range("K1").Value = "M.P.QTY"
Range("L1").Value = "Pallet Qty"
Range("M1").Value = "Start Date"
Range("N1").Value = "AOS SSS"
Range("O1").Value = "End Date"
Range("P1").Value = "End Qty"
Range("Q1").Value = "Promotion week"
Range("R1").Value = "Start-Up Qty"
Range("S1").Value = "Old AWS"
Range("T1").Value = "Goal"
Range("U1").Value = "QTY Sold LW"
Range("V1").Value = "Price"
Range("W1").Value = "GM0"
Range("X1").Value = "Sales Before"
Range("Y1").Value = "Sales this Month"
Range("Z1").Value = "Total Sold this month"
'-----------------------------------------------------------------
'//Date\\
'-----------------------------------------------------------------
Dim FirstDate As Date
Dim LastDate As Date
Dim NextDate As Date
Dim r As Long
Range("AA1").Value = DateSerial(Year(Date), Month(Date), 1)
FirstDate = DateSerial(Year(Date), Month(Date), 1)
LastDate = DateSerial(Year(Date), Month(Date) + 1, 0)
r = 28
Do
FirstDate = FirstDate + 1
Cells(1, r) = FirstDate
r = r + 1
Loop Until FirstDate = LastDate
LastRow = Range("A100000").End(xlUp).Row
Range("Y2").Formula = "=SUM(Registration!AA2:Registration!BE2)"
Range("Y2").Select
Range("Y2:Y" & LastRow).Select
Selection.FillDown
Range("Z2").Formula = "=Registration!Y2*Registration!V2"
Range("Z2").Select
Range("Z2:Z" & LastRow).Select
Selection.FillDown
Selection.NumberFormat = _
"_([$€-x-euro2] * #,##0.00_);_([$€-x-euro2] * (#,##0.00);_([$€-x-euro2] * ""-""??_);_(#_)"
'--------------------------------------------------
'//Format Head, Row A1\\
'--------------------------------------------------
Range("A1", Range("XFD1").End(xlToLeft)).Select
With Selection.Font
.Name = "Calibri"
.FontStyle = "Bold"
.Size = 13
End With
'--------------------------------------------------
'//Select Used rows and column and shift one row down\\
'--------------------------------------------------
Range("A1", Range(Range("A1:A" & LastRow), Range("A1", Range("XFD1").End(xlToLeft)))).Offset(1).Select
With Selection.Font
.Name = "Calibri"
.FontStyle = "Regular"
.Size = 11
End With
'--------------------------------------------------
'//Autofit and Align all cells in rows and columns\\
'--------------------------------------------------
With Cells
.EntireColumn.AutoFit
.EntireRow.AutoFit
.VerticalAlignment = xlCenter
.HorizontalAlignment = xlLeft
End With
'--------------------------------------------------
'//This Code will freeze the first row in the worksheet\\
'--------------------------------------------------
With ActiveWindow
.SplitColumn = 6
.SplitRow = 1
.FreezePanes = True
End With
'--------------------------------------------------
'//This code will delete all of the old products and replace them to the sheet old_products.\\
'--------------------------------------------------
Dim l As Long
Dim dst As Range
Dim sht As Worksheet: Set sht = Worksheets("Old_Products")
With Sheets("Registration")
For l = 2 To LastRow
If .Cells(l, 6).Value = "old product" Then
Set dst = sht.Range("F" & sht.Rows.Count).End(xlUp).Offset(1, -5)
.Cells(l, 6).EntireRow.Copy
dst.PasteSpecial xlPasteValues
.Cells(l, 6).EntireRow.Delete
End If
Next l
End With
'--------------------------------------------------
'//Sorting Column A in Department order\\
'--------------------------------------------------
Dim oRangeSort As Range
Dim oRangeKey As Range
' one range that includes all colums to sort
Set oRangeSort = Range("A1", Range(Range("A1:A" & LastRow), Range("A1", Range("XFD1").End(xlToLeft))))
' start of column with keys to sort
Set oRangeKey = Range("A2")
'//custom sort order\\
Dim sCustomList(1 To 28) As String
sCustomList(1) = "OTW showroom"
sCustomList(2) = "Launch Area"
sCustomList(3) = "Living"
sCustomList(4) = "Media"
sCustomList(5) = "Dining"
sCustomList(6) = "Kitchen"
sCustomList(7) = "Work"
sCustomList(8) = "Sleeping"
sCustomList(9) = "Storage"
sCustomList(10) = "Children"
sCustomList(11) = "Familly"
sCustomList(12) = "Staircase"
sCustomList(13) = "Lift"
sCustomList(14) = "OTW"
sCustomList(15) = "Koken en Eten"
sCustomList(16) = "Textiel"
sCustomList(17) = "Bed"
sCustomList(18) = "Bad"
sCustomList(19) = "Home Organisation"
sCustomList(20) = "Lighting"
sCustomList(21) = "Rugs"
sCustomList(22) = "Wall"
sCustomList(23) = "Home Decoration"
sCustomList(24) = "Self Storage"
sCustomList(25) = "CheckOut"
sCustomList(26) = "Cash Line"
sCustomList(27) = "AS IS"
sCustomList(28) = "SWFOOD"
Application.AddCustomList ListArray:=sCustomList
Sort.SortFields.Clear
oRangeSort.Sort Key1:=Range("A1:A" & LastRow), Order1:=xlAscending, Key2:=Range("B1:B" & LastRow), Order2:=xlAscending, Header:=xlYes, OrderCustom:=Application.CustomListCount + 1, MatchCase:=False, Orientation:=xlTopToBottom, DataOption1:=xlSortNormal
' clean up
ActiveSheet.Sort.SortFields.Clear
Application.DeleteCustomList Application.CustomListCount
'-------------------------------------------------------
'//This code will compare the sart date for the new product and
'if it's more than one day then it will removes the product from the Registration sheet to the Planned New Products.\\
'-------------------------------------------------------
Dim j As Integer
For j = 2 To LastRow
If Sheets("Registration").Cells(j, "M").Value > Date + 1 Then
Sheets("Registration").Cells(j, "M").EntireRow.Copy Destination:=Sheets("Planned_New_Products").Range("A" & Rows.Count).End(xlUp).Offset(1)
Sheets("Registration").Cells(j, "M").EntireRow.Delete
End If
Next j
''// Stop flickering...
'--------------------------------------------------
Range("A2").Select
Application.ScreenUpdating = True
End Sub
This code copies the entire row based on the inserted text in column F and pastes the row in a different sheet. Now the problem is that I have the following code in column Y
=SUM(Registration!AA2:Registration!BE2) 'the number is from 2 to lastrow
And the following code in column Z
=Registration!Y2*Registration!V2 'the number is from 2 to lastrow
Now my question is how can I only copy the value of this entire row and paste it into a different worksheet?
To copy the entire row of values:
Dim dst As Range
Dim sht As Worksheet: Set sht = Worksheets("Old_Products")
With Sheets("Registration")
For l = lastRow to 2 Step -1
If .Cells(l, 6).Value = "old product" Then
Set dst = sht.Range("F" & sht.Rows.Count).End(xlUp).Offset(1, -5)
.Cells(l, 6).EntireRow.Copy
dst.PasteSpecial xlPasteValues
.Cells(l, 6).EntireRow.Delete
End If
Next l
End With

Resources