The below code is working uses formula to concatenate the result from Range("K:M")
and write the result in column H.
Is there a better way to write the below code that can concatenate the result to the exact location as per below table? Please note that data in the before table is discontinued but sometimes will be from row 4 to 1000 rows down or the below example.
Sub GenerateStyleFabricColourV4()
Dim srcData As Range
Dim rowNum As Long, lastRow As Long
With Worksheets(2)
lastRow = Application.Max(4, _
.Cells(.Rows.Count, "K").End(xlUp).Row, _
.Cells(.Rows.Count, "L").End(xlUp).Row, _
.Cells(.Rows.Count, "M").End(xlUp).Row)
With .Cells(4, "H").Resize(lastRow - 4 + 1, 1)
.FormulaR1C1 = "=rc[3]&rc[4]&rc[5]"
.Value = .Value2
End With
End With
End Sub
Sub ClearAllData()
Rows("4:" & Rows.Count).ClearContents
End Sub
2 Answers 2
To answer another question I provided some helpful information about optimization in vba here, VBA syntax that compiles sub data into master sheet.
This maybe help you to skip the blank rows (You did not clarify your question but based on the data you provided I think that would be your problem) and find the actual last row used. It is in reference to this post. Here's the code:
Dim srcData As Range, rng As Range
Dim rowNum As Long, lastRow As Long
Dim wsh As Worksheet
Sub GSFC_V4()
Set wsh = Worksheets(2)
wsh.Activate
Set srcData = Range("K:M")
Set rng = Range("K4")
With wsh
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
lastrow = srcData.Find(What:="*", _
After:=rng, _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
lastrow = 1
End If
With .Cells(4, "H").Resize(lastRow - 4 + 1, 1)
.FormulaR1C1 = "=rc[3]&rc[4]&rc[5]"
.Value = .Value2
End With
End With
End Sub
This is what I am using to optimize my macros. I call OptimizeVBA True
at the beginning of each macro and at the end call OptimizeVBA False
to set everything back to default. It increases the performance remarkably.
Sub OptimizeVBA(isOn As Boolean)
Application.Calculation = IIf(isOn, xlCalculationManual, xlCalculationAutomatic)
Application.EnableEvents = Not (isOn)
Application.ScreenUpdating = Not (isOn)
Application.StatusBar = Not (isOn)
End Sub
You need to be careful of how you refer to ranges to avoid getting errors.
-
\$\begingroup\$ Gives a run time error 1000 on the ` With .Cells(4, "H").Resize(lastRow - 4 + 1, 1)` can't work out why. \$\endgroup\$QuickSilver– QuickSilver2017年04月14日 07:34:05 +00:00Commented Apr 14, 2017 at 7:34
-
\$\begingroup\$ @QuickSilver This is not the optimized way to do it but you can try this: before that "With block" add this
.Cells(4, "H").Select
and substitute the.Cells(4,"H").
withSelection.
. You may need to put the second with block out of the first one (i.e.With wsh
). \$\endgroup\$M--– M--2017年04月14日 13:19:55 +00:00Commented Apr 14, 2017 at 13:19
I had an old script on hand that accomplished most of what I think you're after, though it uses a different approach. I modified it and it seems to work with your data. You'll need to update at least a couple values in the code — see comments.
Option Explicit
Sub GSFC_V4()
Application.ScreenUpdating = False
Dim wb As Workbook
Set wb = Workbooks("ConcatTest.xlsx") 'update workbook name
Dim ws As Worksheet
Set ws = wb.Sheets("Sheet1") 'update worksheet name
Dim TextS As String
Dim TextF As String
Dim TextC As String
Dim StartRow As Long
StartRow = 5 'assumes row 5 is the first row containing data to be concatenated
Dim LastRow As Long, lRow1 As Long, lRow2 As Long, lRow3 As Long
lRow1 = Range("K" & Rows.Count).End(xlUp).Row
lRow2 = Range("L" & Rows.Count).End(xlUp).Row
lRow3 = Range("M" & Rows.Count).End(xlUp).Row
LastRow = WorksheetFunction.Max(lRow1, lRow2, lRow3)
Dim CheckCell As Range
Dim ConcatRange As Range
Set ConcatRange = Range(ws.Cells(StartRow, "K"), ws.Cells(LastRow, "K"))
Dim i As Long
i = StartRow
For Each CheckCell In ConcatRange
TextS = ws.Cells(i, "K").Value
TextF = ws.Cells(i, "L").Value
TextC = ws.Cells(i, "M").Value
i = i + 1
If Not CheckCell.Value = "" Then
CheckCell.Offset(0, -3).Value = TextS & TextF & TextC
End If
Next CheckCell
Application.ScreenUpdating = True
End Sub
range.currentregion
instead of the multipleend(xlup)
calls. \$\endgroup\$