Just want to ask if how can I shorten the codes below? The codes work fine, but I just want to know if there is a way to shorten it since I'll be using the codes in N-Q1 sheet in other quarter sheets (N-Q1, N-Q2, N-Q3, N-Q4, JK-Q1, etc.). Note that, the quarter sheets have the same structure or column (column 16) to be updated, while the STUDENTS_INFO sheet is in column 20.
STUDENTS INFO sheets:
Set ws = ActiveWorkbook.Worksheets("STUDENTS_INFO")
lastRow = ws.Cells(Rows.Count, "C").End(xlUp).Row
For r = 9 To lastRow
If ws.Cells(r, 3) = CStr(ThisWorkbook.Sheets("HOME").Range("K11").value) Then
If ws.Cells(r, 20) = "0" Or ws.Cells(r, 20) = "" Then
ws.Cells(r, 20) = "1"
Debug.Print "STUDENTS: " & ws.Cells(r, 3) & " Verified!"
Else
Debug.Print "STUDENTS: " & ws.Cells(r, 3) & " Already Verified!"
End If
End If
Next r
N-Q1 code: Quarter Sheets (N-Q1, N-Q2, N-Q3, N-Q4, JK-Q1, etc.)
grd = ThisWorkbook.Sheets("HOME").Range("K16").value
qrt = CStr(ThisWorkbook.Sheets("HOME").Range("K17").value)
If grd = "Nursery" Then
ws_output = "N" + "-" + qrt
ElseIf grd = "Junior Kinder" Then
ws_output = "JK" + "-" + qrt
ElseIf grd = "Senior Kinder" Then
ws_output = "SK" + "-" + qrt
End If
Set ws = ActiveWorkbook.Worksheets(ws_output)
lastRow = ws.Cells(Rows.Count, "C").End(xlUp).Row
For s = 9 To lastRow
If ws.Cells(s, 3) = CStr(ThisWorkbook.Sheets("HOME").Range("K11").value) Then
If ws.Cells(s, 16) = "0" Or ws.Cells(r, 16) = "" Then
ws.Cells(s, 16) = "1"
Debug.Print "GRADES: " & ws.Cells(s, 3) & " Verified!"
Else
Debug.Print "GRADES: " & ws.Cells(s, 3) & " Already Verified!"
End If
End If
Next s
Note that, this code will only work depends on the value of grd and qrt.
I'm thinking of using the code below as a start.
For Each ws In Sheets(Array("STUDENTS_INFO", "N-Q1", "N-Q2", "N-Q3", "N-Q4", "N-D", _
"JK-Q1", "JK-Q2", "JK-Q3", "JK-Q4", "JK-D", "SK-Q1", "SK-Q2", "SK-Q3", "SK-Q4", "SK-D"))
With ws.Cells(8, 3).CurrentRegion
.AutoFilter 2, LRN
ws.AutoFilterMode = False
End With
Next ws
Please see the code below for the solution that I came up. Thank you!
For Each ws In Sheets(Array("N-Q1", "N-Q2", "N-Q3", "N-Q4", "N-D", _
"JK-Q1", "JK-Q2", "JK-Q3", "JK-Q4", "JK-D", "SK-Q1", "SK-Q2", "SK-Q3", "SK-Q4", "SK-D"))
lastRow = ws.Cells(Rows.Count, "C").End(xlUp).Row
For r = 9 To lastRow
If ws.Cells(r, 3) = CStr(ThisWorkbook.Sheets("HOME").Range("K11").value) Then
If ws.Cells(r, 16) = "0" Or ws.Cells(r, 16) = "" Then
ws.Cells(r, 16) = "1"
Debug.Print "STUDENTS: " & ws.Cells(r, 3) & " Verified!"
Else
Debug.Print "STUDENTS: " & ws.Cells(r, 3) & " Already Verified!"
End If
End If
Next r
Next ws
Related
I have two sheets first one called Sheet8 is for the Main table that can be used by the Data Entry Form to enter the data in that table, and the second called Sheet9 that includes the table for the vlookup. What I want is in the data entry user form as soon as I enter the Name the Discipline is created automatically based on that name.
Screenshot of the Data Entry for the Main table in sheet8
Screenshot of the sheet9 Table
The code for Save Button
Private Sub btnSave_Click()
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Sheet8")
Dim n As Long
n = sh.Range("A" & Application.Rows.Count).End(xlUp).Row
sh.Unprotect "1234"
sh.Range("A" & n + 1).Value = Me.txtDate.Value
sh.Range("B" & n + 1).Value = Me.txtName.Value
sh.Range("C" & n + 1).Value = Me.txtProjNo.Value
sh.Range("D" & n + 1).Value = Me.txtProjTitle.Value
sh.Range("E" & n + 1).Value = Me.txtBVEntity.Value
sh.Range("F" & n + 1).Value = Me.txtZIG.Value
sh.Range("G" & n + 1).Value = Me.txtSpenthrs.Value
sh.Range("H" & n + 1).Value = Me.comboCategory.Value
sh.Range("I" & n + 1).Value = Me.txtDiscipline.Value
sh.Range("J" & n + 1).Value = Me.txtSCV.Value
sh.Range("K" & n + 1).Value = Me.txtTotSCV.Value
sh.Range("L" & n + 1).Value = Me.txtCotMER.Value
sh.Range("M" & n + 1).Value = Me.txtBudgethrs.Value
sh.Range("N" & n + 1).Value = Me.txtBudget.Value
sh.Range("O" & n + 1).Value = Me.txtProgress.Value
sh.Range("P" & n + 1).Value = Me.txtEndDate.Value
sh.Protect "1234"
The code for the Name textbox
Private Sub txtName_AfterUpdate()
If WorksheetFunction.CountIf(Sheet9.Range("C:D"), Me.txtName.Value) = 0 Then
MsgBox "This Name is Invalid."
Me.txtName.Value = ""
Exit Sub
End If
With Me
.txtDiscipline = Application.WorksheetFunction.VLookup(Me.txtName, Sheet9.Range("Lookup"), 4, 0)
End With
End Sub
I have some problems with excel and VBA, in that don't know have much knowledge. I copied text from pdf and it's awful.
I have cells which contain some text.
The problem is that the text from one paragraph is broken down over several cells. At the beginning of each paragraph is a word in bold (e.g. CLR.) which describes the rest of the text. As such, it defines where each paragraph should start. How I can merge these cells into one?
I see
I want
Sub MergeText()
Dim strMerged$, r&, j&, i&
r = 1
Do While True
If Cells(r, 1).Characters(1, 1).Font.Bold Then
strMerged = "": strMerged = Cells(r, 1)
r = r + 1
While (Not Cells(r, 1).Characters(1).Font.Bold) And Len(Cells(r, 1)) > 0
strMerged = strMerged & Cells(r, 1)
r = r + 1
Wend
i = i + 1: Cells(i, 2) = strMerged
Cells(i, 2).Characters(1, InStr(1, strMerged, ".", vbTextCompare)).Font.Bold = True
Else
Exit Do
End If
Loop
End Sub
Modify (if needed) and try:
Option Explicit
Sub test()
Dim LastRow As Long, i As Long, j As Long, Count As Long
Dim str As String
With ThisWorkbook.Worksheets("Sheet1") 'Change sheet name if needed
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = LastRow To 2 Step -1
If (UCase(Left(.Range("A" & i), 1)) <> Left(.Range("A" & i), 1)) And UCase(Left(.Range("A" & i - 1), 1)) = Left(.Range("A" & i - 1), 1) Then
Count = 0
For j = 1 To Len(.Range("A" & i - 1))
If .Range("A1").Characters(j, 1).Font.FontStyle = "Bold" Then
Count = Count + 1
Else
Exit For
End If
Next j
str = .Range("A" & i - 1).Value & " " & .Range("A" & i).Value
With .Range("A" & i - 1)
.Value = str
.Font.Bold = False
With .Characters(Start:=1, Length:=Count).Font
.FontStyle = "Bold"
End With
End With
.Rows(i).EntireRow.Delete
ElseIf (UCase(Left(.Range("A" & i), 1)) <> Left(.Range("A" & i), 1)) And UCase(Left(.Range("A" & i - 1), 1)) <> Left(.Range("A" & i - 1), 1) Then
str = .Range("A" & i - 1).Value & " " & .Range("A" & i).Value
With .Range("A" & i - 1)
.Value = str
.Font.Bold = False
End With
.Rows(i).EntireRow.Delete
End If
Next i
End With
End Sub
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
I am trying to automate my SKU numbers. I have 3 columns. The first column has 28, the second has 6 and finally the third has 58.
I want the SKU to have a Trend like so 0{(###)col1}{(##)col2}{(##)col3}0
My Code looks like this
Sub SKU()
Dim x As Long
x = 1
i = 1
j = 1
k = 1
Do While Cells(i, 1) <> ""
Do While Cells(j, 2) <> ""
Do While Cells(k, 3) <> ""
Cells(x, 4).Value = Format(0, "0") & Format(i, "000") & _
Format(j, "00") & Format(k, "00") & Format(0, "0")
k = k + 1
x = x + 1
Loop
j = j + 1
Loop
i = i + 1
Loop
End Sub
No need to use the Do Loop. Find the last row and then use a For loop.
Is this what you are trying?
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long, i As Long
'~~> Change this to the relevant sheet
Set ws = ThisWorkbook.Sheets("Sheet2")
With ws
'~~> Find last row
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = 1 To lRow
If .Cells(i, 1) <> "" And .Cells(i, 2) <> "" And .Cells(i, 3) <> "" Then
'0{(###)col1}{(##)col2}{(##)col3}0
.Cells(i, 4).Value = "'0" & _
Format(.Cells(i, 1), "000") & _
Format(.Cells(i, 2), "00") & _
Format(.Cells(i, 3), "00") & _
"0"
End If
Next i
End With
End Sub
Output for 28,6,58 is 002806580
As i mentioned in the comment to the question, remove first and second do-while loop then replace:
Cells(x, 4).Value = Format(0, "0") & Format(i, "000") & _
Format(j, "00") & Format(k, "00") & Format(0, "0")
with:
Cells(k, 4) = "'" & Format(Cells(k, 1), "000") & _
Format(Cells(k, 2), "00") & Format(Cells(k, 3), "00")
Result: 0280658
In case you want to add leading and ending zeros:
Cells(k, 4) = "'0" & Format(Cells(k, 1), "000") & _
Format(Cells(k, 2), "00") & Format(Cells(k, 3), "00") & "0"
Result: 002806580
I have two tables
A B C
name surname address
and
A B C D
id address name surname
I need to union the tables and matching the cols, so
table1, colA = table2, colC
table1, colC = table2, colB
etc
I use this code, which works fine, but for big data is slow
Sub unionrep()
Dim lastRow As Long
Sheets("decl").Select
With ActiveSheet
lastRow = .Cells(.Rows.Count, "b").End(xlUp).Row
End With
With Sheets("onl")
tlastRow = .Cells(.Rows.Count, "b").End(xlUp).Row
End With
For i = 1 To lastRow
Sheets("onl").Range("a" & tlastRow + i + 1).Value = Range("a" & i).Value
Sheets("onl").Range("b" & tlastRow + i + 1).Value = Trim(Range("b" & i).Value)
Sheets("onl").Range("c" & tlastRow + i + 1).Value = "*" & Range("c" & i).Value
Sheets("onl").Range("d" & tlastRow + i + 1).Value = Range("g" & i).Value
Sheets("onl").Range("e" & tlastRow + i + 1).Value = Range("d" & i).Value
Sheets("onl").Range("f" & tlastRow + i + 1).Value = ""
Sheets("onl").Range("g" & tlastRow + i + 1).Value = ""
Sheets("onl").Range("h" & tlastRow + i + 1).Value = ""
Sheets("onl").Range("i" & tlastRow + i + 1).Value = Range("e" & i).Value
Sheets("onl").Range("j" & tlastRow + i + 1).Value = Range("i" & i).Value
Sheets("onl").Range("k" & tlastRow + i + 1).Value = Range("f" & i).Value
Next
Sheets("onl").Select
End Sub
You could copy and paste the entire ranges instead of looping through the rows. For example, to copy from column A in the "decl" sheet to column C in the "onl" sheet, something like:
Sheets("decl").Range(Cells(1, 1), Cells(lastRow, 1)).Copy
Sheets("onl").Range("C" & tlastRow + 1).PasteSpecial
Try using arrays:
Sub unionrep()
Dim lastRow As Long
Dim vDataIn, vDataOut
With Sheets("decl")
lastRow = .Cells(.Rows.Count, "b").End(xlUp).Row
vDataIn = .Range("A1:I" & lastRow).Value
End With
ReDim vDataOut(1 To lastRow, 1 To 11)
With Sheets("onl")
tlastRow = .Cells(.Rows.Count, "b").End(xlUp).Row + 1
End With
For i = 1 To lastRow
vDataOut(i, 1) = vDataIn(i, 1)
vDataOut(i, 2) = Trim(vDataIn(i, 2))
vDataOut(i, 3) = "*" & vDataIn(i, 3)
vDataOut(i, 4) = vDataIn(i, 7)
vDataOut(i, 5) = vDataIn(i, 4)
vDataOut(i, 9) = vDataIn(i, 5)
vDataOut(i, 10) = vDataIn(i, 9)
vDataOut(i, 11) = vDataIn(i, 6)
Next
Sheets("onl").Range("a" & tlastRow).Resize(UBound(vDataOut, 1), UBound(vDataOut, 2)).Value = vDataOut
Sheets("onl").Select
End Sub