I'm new at this, apologies in advance.
This code searches for specific values in a column in one sheet, stores the row reference of the value found then uses it to copy input values into the spreadsheet then copies output values into a summary. It works ... but is there a way of setting "Set" variables into a loop?
Dim i As Long
Dim wb As Workbook
Dim sht1 As Worksheet
Dim sht2 As Worksheet
Dim RNG(1 To 8) As Range
Dim MyVal As Variant
'Set value of rows to work down
MyVal = InputBox("To what row to calculate", "Enter a row number", 36)
If MyVal > 52 Then
MsgBox ("You can't enter a number greater than 52")
MyVal = InputBox("To what row to calculate", "Enter a row number", 52)
End If
Set wb = ThisWorkbook
Set sht1 = wb.Sheets("Individual Carry")
Set sht2 = wb.Sheets("Detail")
Set RNG1 = sht2.Range("A:A").Find("V1", LookIn:=xlValues, LookAt:=xlWhole)
Set RNG2 = sht2.Range("A:A").Find("V2", LookIn:=xlValues, LookAt:=xlWhole)
Set RNG3 = sht2.Range("A:A").Find("V3", LookIn:=xlValues, LookAt:=xlWhole)
Set RNG4 = sht2.Range("A:A").Find("V4", LookIn:=xlValues, LookAt:=xlWhole)
Set RNG5 = sht2.Range("A:A").Find("V5", LookIn:=xlValues, LookAt:=xlWhole)
Set RNG6 = sht2.Range("A:A").Find("V6", LookIn:=xlValues, LookAt:=xlWhole)
Set RNG7 = sht2.Range("A:A").Find("V7", LookIn:=xlValues, LookAt:=xlWhole)
Set RNG8 = sht2.Range("A:A").Find("V8", LookIn:=xlValues, LookAt:=xlWhole)
'Set variables equal to Rows of output cells
V1 = RNG1.Row
V2 = RNG2.Row
V3 = RNG3.Row
V4 = RNG4.Row
V5 = RNG5.Row
V6 = RNG6.Row
V7 = RNG7.Row
V8 = RNG8.Row
'Clear result range
sht1.Range("U8:Z52").ClearContents
'Loop through assumptions and copy outputs to result field
For i = 8 To MyVal
'Copy inputs into calculation sheet
sht2.Range("J" & V1) = sht1.Range("D" & i).Value
sht2.Range("E" & V2) = sht1.Range("E" & i).Value
sht2.Range("E" & V2 + 1) = sht1.Range("F" & i).Value
sht2.Range("E" & V2 + 2) = sht1.Range("G" & i).Value
sht2.Range("E" & V2 + 3) = sht1.Range("H" & i).Value
sht2.Range("E" & V2 + 4) = sht1.Range("I" & i).Value
sht2.Range("E" & V2 + 5) = sht1.Range("J" & i).Value
sht2.Range("E" & V2 + 6) = sht1.Range("K" & i).Value
sht2.Range("E" & V2 + 7) = sht1.Range("L" & i).Value
sht2.Range("E" & V2 + 8) = sht1.Range("M" & i).Value
sht2.Range("E" & V2 + 9) = sht1.Range("N" & i).Value
sht2.Range("E" & V2 + 10) = sht1.Range("O" & i).Value
sht2.Range("E" & V2 + 11) = sht1.Range("P" & i).Value
sht2.Range("E" & V2 + 12) = sht1.Range("Q" & i).Value
sht2.Range("E" & V2 + 13) = sht1.Range("R" & i).Value
sht2.Range("E" & V2 + 14) = sht1.Range("S" & i).Value
sht2.Range("E" & V2 + 15) = sht1.Range("T" & i).Value
'Copy result to inputs sheet
sht1.Range("U" & i).Value = sht2.Range("E" & V3) / 1000
sht1.Range("V" & i).Value = sht2.Range("E" & V4) / 1000
sht1.Range("W" & i).Value = sht2.Range("E" & V5) / 1000
sht1.Range("X" & i).Value = sht2.Range("E" & V6) / 1000
sht1.Range("Y" & i).Value = sht2.Range("E" & V7) / 1000
sht1.Range("Z" & i).Value = sht2.Range("E" & V8) / 1000
Next i
MsgBox ("Command Complete")
Concentrating on the part you were asking about:
Dim arrVals, R() As Long, x, wb As Workbook, sht2 As Worksheet
'all the values to be located in ColA...
arrVals = Array("V1", "V2", "V3", "V4", "V5", "V6", "V7", "V8")
Set wb = ThisWorkbook
Set sht2 = wb.Sheets("Detail")
'resize the "rows" array to have the same # of elements as arrVals
ReDim R(1 To UBound(arrVals) + 1) '+1 is because arrVals is zero-based
For x = 1 To UBound(R)
'Note: if there's any possibility of a value not being found, this will error
' at runtime
R(x) = sht2.Range("A:A").Find(arrVals(x - 1), LookIn:=xlValues, LookAt:=xlWhole).Row
Next x
Debug.Print R(3) 'just checking one of the values...
'R(1) is now the same as V1 in you posted code, R(2)=V2, etc
If using an ascending notation starting with 1, also a collection will do, like this:
Dim sht As Worksheet, MyVal As Variant, x As Variant
Dim MyCol As New Collection, i As Long
'Set value of rows to work down
MyVal = 53
While MyVal > 52
MyVal = InputBox("To what row to calculate", "Enter a row number", 36)
If Not IsNumeric(MyVal) Then Exit Sub
If MyVal > 52 Then MsgBox ("You can't enter a number greater than 52")
Wend
With ThisWorkbook.Sheets("Detail")
Set sht = .Parent.Sheets("Individual Carry")
For Each x In Evaluate("""v""&ROW(1:8)")
MyCol.Add .Columns(1).Find(x, , &HEFBD, 1).Row
Next
'Clear result range
sht.[U8:Z52].ClearContents
'Loop through assumptions and copy outputs to result field
For x = 8 To MyVal
'Copy inputs into calculation sheet
.Cells(MyCol(1), 10).Value2 = sht.Cells(x, 4).Value2
.Cells(MyCol(2), 5).Resize(15).Value2 = Application.Transpose(sht.Cells(x, 5).Resize(, 15).Value2)
'Copy result to input sheet
For i = 3 To 8
sht.Cells(x, 18 + i).Value2 = .Cells(MyCol(i), 5).Value2 / 1000
Next
Next
End With
MsgBox "Command Complete"
Because there is no way of testing this without proper data, there may be some errors :P
Related
I have a very large data set that gets updated multiple times a day. It can vary from 1000-20000 entries. I have a macro in place that searches for specific criteria and makes a new table from that data and works but it takes a very long time to sift through all the points. I want to know if there is a more eloquent way to achieve the same result.
I tried a new different methods of the same thing. Poked around at other solutions but could not get them to fit what I needed. I even tried the advanced filtering tables but to no avail.
Function AgedDivert()
'Pull from scraped data to display compact data set
On Error GoTo ErrorHandler
ufProgress.Caption = "Loading Aged Divert"
ufProgress.LabelProgress.Width = 0
pasterow = 31
sname = "Aged Divert Report"
ThisWorkbook.Sheets(sname).Rows(30 & ":" & 999999).Clear
ThisWorkbook.Sheets("Temp").Range("1:1").Copy ThisWorkbook.Sheets(sname).Range("30:30")
RowCount = WorksheetFunction.CountA(ThisWorkbook.Sheets("Scraped Data").Range("A:A"))
'Create new data sort by age and location
For i = 2 To RowCount
pctComplete = (i - 2) / (RowCount - 2)
'Filter out Direct Loads, PA2, Less than 180 Minutes, Secondary, not diverted
If Len(ThisWorkbook.Sheets("Scraped Data").Range("D" & i).Value) <> 2 And _
(ThisWorkbook.Sheets("Scraped Data").Range("J" & i).Value = "Ship Sorter" Or _
ThisWorkbook.Sheets("Scraped Data").Range("K" & i).Value = "Divert Confirm") And _
ThisWorkbook.Sheets("Scraped Data").Range("D" & i).Value <> "" And _
ThisWorkbook.Sheets("Scraped Data").Range("M" & i).Value > 180 And _
ThisWorkbook.Sheets("Scraped Data").Range("I" & i).Value <> "Left to Pick" And _
InStr(1, ThisWorkbook.Sheets("Scraped Data").Range("C" & i).Value, "Location") = 0 And _
(InStr(1, ThisWorkbook.Sheets("Scraped Data").Range("C" & i).Value, "Warehouse A") > 0 Or _
InStr(1, ThisWorkbook.Sheets("Scraped Data").Range("C" & i).Value, "Warehouse C") > 0 Or _
InStr(1, ThisWorkbook.Sheets("Scraped Data").Range("C" & i).Value, "PA") = 0) Then
ThisWorkbook.Sheets("Scraped Data").Range(i & ":" & i).Copy ThisWorkbook.Sheets(sname).Range(pasterow & ":" & pasterow)
pasterow = pasterow + 1
End If
ufProgress.LabelProgress.Width = pctComplete * ufProgress.FrameProgress.Width
ufProgress.Repaint
Next i
ufProgress.Caption = "Loading Complete. Cleaning Data"
'Remove Unnecessary Data
ThisWorkbook.Sheets(sname).Columns("R").Delete
ThisWorkbook.Sheets(sname).Columns("Q").Delete
ThisWorkbook.Sheets(sname).Columns("O").Delete
ThisWorkbook.Sheets(sname).Columns("N").Delete
ThisWorkbook.Sheets(sname).Columns("L").Delete
ThisWorkbook.Sheets(sname).Columns("K").Delete
ThisWorkbook.Sheets(sname).Columns("J").Delete
ThisWorkbook.Sheets(sname).Columns("H").Delete
ThisWorkbook.Sheets(sname).Columns("F").Delete
ThisWorkbook.Sheets(sname).Columns("E").Delete
ThisWorkbook.Sheets(sname).Range("C30:C999999").Delete
ThisWorkbook.Sheets(sname).Range("B30:B999999").Delete
'Set Data as Table
ThisWorkbook.Sheets(sname).ListObjects.Add(xlSrcRange, ThisWorkbook.Sheets(sname).Range("A30:F" & pasterow), , xlYes).Name = "AgedDivert"
AgedDivert = True
Exit Function
ErrorHandler:
AgedDivert = False
Debug.Print "Error occured in Aged Divert"
Debug.Print Err.Number & ": " & Err.Description
End Function
Copy the data to an array, filter to another array and copy back to sheet. 20,000 rows should take a few seconds.
Function AgedDivert()
Dim wb As Workbook
Dim wsData As Worksheet, wsReport As Worksheet, wsTemp As Worksheet
Dim arData, arReport
Dim lastrow As Long, i As Long, r As Long
Dim colC, colD, colI, colJ, colK, colM, msg As String
Dim t0 As Single: t0 = Timer
Const RPT_NAME = "Aged Divert Report"
'Pull from scraped data to display compact data set
On Error GoTo ErrorHandler
Set wb = ThisWorkbook
With wb
Set wsData = .Sheets("Scraped Data")
Set wsReport = .Sheets(RPT_NAME)
Set wsTemp = .Sheets("Temp")
End With
' copy data
With wsData
lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
' copy sheet to array
arData = .Range("A1:P" & lastrow)
ReDim arReport(1 To lastrow, 1 To 6) ' A to F
For i = 2 To lastrow
colC = arData(i, 3)
colD = arData(i, 4)
colI = arData(i, 9)
colJ = arData(i, 10)
colK = arData(i, 11)
colM = arData(i, 13)
'Filter out Direct Loads, PA2, Less than 180 Minutes,
'Secondary, not diverted
If Len(colD) <> 2 And colD <> "" And _
(colJ = "Ship Sorter" Or colK = "Divert Confirm") _
And colM > 180 _
And colI <> "Left to Pick" _
And InStr(1, colC, "Location") = 0 And _
(InStr(1, colC, "Warehouse A") > 0 Or _
InStr(1, colC, "Warehouse C") > 0 Or _
InStr(1, colC, "PA") = 0) Then
r = r + 1 ' report row
arReport(r, 1) = arData(i, 1) ' A
arReport(r, 2) = arData(i, 4) ' D
arReport(r, 3) = arData(i, 7) ' G
arReport(r, 4) = arData(i, 9) ' I
arReport(r, 5) = arData(i, 13) ' M
arReport(r, 6) = arData(i, 16) ' P
End If
Next i
End With
' output
With wsReport
' delete existing table
.Rows("30:" & .Rows.Count).Clear
.Range("A30:F30") = Array("Col A", "Col D", "Col G", "Col I", "Col M", "Col P")
If r = 0 Then
MsgBox "No data to report", vbExclamation
Else
' copy rows and set Data as Table
.Range("A31").Resize(r, 6) = arReport
.ListObjects.Add(xlSrcRange, .Range("A30:F" & 30 + r), xlYes).Name = "AgedDivert"
End If
End With
msg = lastrow - 1 & " rows scanned from " & wsData.Name & vbLf & _
r & " rows copied to " & wsReport.Name
MsgBox msg, vbInformation, Format(Timer - t0, "0.0 secs")
AgedDivert = True
Exit Function
ErrorHandler:
AgedDivert = False
Debug.Print "Error occured in Aged Divert"
Debug.Print Err.Number & ": " & Err.Description
End Function
I have Excel with data.
I wrote a code that allows me to filter data depending on the company.
Sub testProjectMl()
Dim sh As Worksheet, shDest As Worksheet, lastRow As Long, firstRow As Long, lastERowDest As Long
Dim i As Long, arrA, dictKP As Object
'Create a variable
Dim dictKS
Dim dictVT
Dim dictAK
Dim dictPP
Set sh = ActiveSheet
lastRow = sh.Range("A" & sh.Rows.Count).End(xlUp).Row
firstRow = 8 'first row with data
arrA = sh.Range("A" & firstRow & ":A" & lastRow).Value 'place the range in an array for faster iteration
Set dictKP = CreateObject("Scripting.Dictionary")
Set dictKS = CreateObject("Scripting.Dictionary")
Set dictVT = CreateObject("Scripting.Dictionary")
Set dictPP = CreateObject("Scripting.Dictionary")
Set dictAK = CreateObject("Scripting.Dictionary")
With Sheets(ActiveSheet.Name)
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = 8 To lastRow
If IsNumeric(.Range("H" & i)) And Trim(.Range("H" & i).Value) <> "" And .Range("H" & i).Value <> 0 And .Range("H" & i).Value > 7000 Then
Select Case True
Case .Range("A" & i).Value Like "KP*"
dictKP.Add .Range("A" & i).Value, Union(sh.Range(sh.Range("A" & firstRow), sh.Range("K" & firstRow)), _
sh.Range(sh.Cells(i + firstRow - 1, "A"), sh.Cells(i + firstRow - 1, "K")))
Case .Range("A" & i).Value Like "KS*"
dictKS.Add .Range("A" & i).Value, Union(sh.Range(sh.Range("A" & firstRow), sh.Range("K" & firstRow)), _
sh.Range(sh.Cells(i + firstRow - 1, "A"), sh.Cells(i + firstRow - 1, "K")))
Case .Range("A" & i).Value Like "VT*"
dictVT.Add .Range("A" & i).Value, Union(sh.Range(sh.Range("A" & firstRow), sh.Range("K" & firstRow)), _
sh.Range(sh.Cells(i + firstRow - 1, "A"), sh.Cells(i + firstRow - 1, "K")))
Case .Range("A" & i).Value Like "PP*"
dictPP.Add .Range("A" & i).Value, Union(sh.Range(sh.Range("A" & firstRow), sh.Range("K" & firstRow)), _
sh.Range(sh.Cells(i + firstRow - 1, "A"), sh.Cells(i + firstRow - 1, "K")))
Case .Range("A" & i).Value Like "AK*"
dictAK.Add .Range("A" & i).Value, Union(sh.Range(sh.Range("A" & firstRow), sh.Range("K" & firstRow)), _
sh.Range(sh.Cells(i + firstRow - 1, "A"), sh.Cells(i + firstRow - 1, "K")))
End Select
End If
Next i
End With
Sheets.Add.Name = "KP"
Sheets.Add.Name = "KS"
Sheets.Add.Name = "VT"
Sheets.Add.Name = "PP"
Sheets.Add.Name = "AK"
Set shDestKp = Sheets("KP")
Set shDestKs = Sheets("KS")
Set shDestVt = Sheets("VT")
Set shDestPp = Sheets("PP")
Set shDestAk = Sheets("AK")
For i = 0 To dictKP.Count - 1
lastERowDest = shDestKp.Range("A" & shDestKp.Rows.Count).End(xlUp).Row + 1
If lastERowDest = 2 Then lastERowDest = 1
dictKP.items()(i).Copy shDestKp.Range("A" & lastERowDest)
shDestKp.Range("L" & lastERowDest).Value = "7000" ' insert a static franchise value
shDestKp.Range("M" & lastERowDest).Value = "0.12" ' insert a static tarrif cost value
shDestKp.Range("K" & lastERowDest).Copy ' copy the target format
shDestKp.Range("L" & lastERowDest).PasteSpecial (xlPasteFormats) 'paste format into cell
shDestKp.Range("M" & lastERowDest).PasteSpecial (xlPasteFormats)
shDestKp.Range("N" & lastERowDest).PasteSpecial (xlPasteFormats)
Application.CutCopyMode = False
Next i
For i = 0 To dictKS.Count - 1
lastERowDest = shDestKs.Range("A" & shDestKs.Rows.Count).End(xlUp).Row + 1
If lastERowDest = 2 Then lastERowDest = 1
dictKS.items()(i).Copy shDestKs.Range("A" & lastERowDest)
shDestKs.Range("L" & lastERowDest).Value = "7000" ' insert a static franchise value
shDestKs.Range("M" & lastERowDest).Value = "0.12" ' insert a static tarrif cost value
shDestKs.Range("K" & lastERowDest).Copy ' copy the target format
shDestKs.Range("L" & lastERowDest).PasteSpecial (xlPasteFormats) 'paste format into cell
shDestKs.Range("M" & lastERowDest).PasteSpecial (xlPasteFormats)
shDestKs.Range("N" & lastERowDest).PasteSpecial (xlPasteFormats)
Application.CutCopyMode = False
Next i
For i = 0 To dictVT.Count - 1
lastERowDest = shDestVt.Range("A" & shDestVt.Rows.Count).End(xlUp).Row + 1
'If lastERowDest = 2 Then lastERowDest = 1
dictVT.items()(i).Copy shDestVt.Range("A" & lastERowDest)
shDestVt.Range("L" & lastERowDest).Value = "7000" ' insert a static franchise value
shDestVt.Range("M" & lastERowDest).Value = "0.12" ' insert a static tarrif cost value
shDestVt.Range("K" & lastERowDest).Copy ' copy the target format
shDestVt.Range("L" & lastERowDest).PasteSpecial (xlPasteFormats) 'paste format into cell
shDestVt.Range("M" & lastERowDest).PasteSpecial (xlPasteFormats)
shDestVt.Range("N" & lastERowDest).PasteSpecial (xlPasteFormats)
Application.CutCopyMode = False
Next i
For i = 0 To dictPP.Count - 1
lastERowDest = shDestPp.Range("A" & shDestPp.Rows.Count).End(xlUp).Row + 1
If lastERowDest = 2 Then lastERowDest = 1
dictPP.items()(i).Copy shDestPp.Range("A" & lastERowDest)
shDestPp.Range("L" & lastERowDest).Value = "7000" ' insert a static franchise value
shDestPp.Range("M" & lastERowDest).Value = "0.12" ' insert a static tarrif cost value
shDestPp.Range("K" & lastERowDest).Copy ' copy the target format
shDestPp.Range("L" & lastERowDest).PasteSpecial (xlPasteFormats) 'paste format into cell
shDestPp.Range("M" & lastERowDest).PasteSpecial (xlPasteFormats)
shDestPp.Range("N" & lastERowDest).PasteSpecial (xlPasteFormats)
Application.CutCopyMode = False
Next i
For i = 0 To dictAK.Count - 1
lastERowDest = shDestAk.Range("A" & shDestAk.Rows.Count).End(xlUp).Row + 1
If lastERowDest = 2 Then lastERowDest = 1
dictAK.items()(i).Copy shDestAk.Range("A" & lastERowDest)
shDestAk.Range("L" & lastERowDest).Value = "7000" ' insert a static franchise value
shDestAk.Range("M" & lastERowDest).Value = "0.12" ' insert a static tarrif cost value
shDestAk.Range("K" & lastERowDest).Copy ' copy the target format
shDestAk.Range("L" & lastERowDest).PasteSpecial (xlPasteFormats) 'paste format into cell
shDestAk.Range("M" & lastERowDest).PasteSpecial (xlPasteFormats)
shDestAk.Range("N" & lastERowDest).PasteSpecial (xlPasteFormats)
Application.CutCopyMode = False
Next i
End Sub
As you can see, depending on the value at the beginning of cell A, I adding the row in a certain dictionary. Then there is a cycle for each dictionary and inserting values into a specific sheets.
But I have a problem, for some reason the same line is entered in all the sheets when iterating through dictionaries.
For example (KS sheet):
This sheet should have the following value:
When Select Case and adding a row to the dictionary, the value in cell A is specified correctly and corresponds to a specific dictionary. BUT I don't understand why, when iterating through dictionaries, the same value from the dictKP dictionary is inserted.
Example what need in the end:
Please, try using the next code. It needs only a single dictionary, creating keys based on the first two company name characters. It will add new sheets based on the dictionary keys and clear the existing if they exist:
Sub testProjectMl()
Dim sh As Worksheet, newSh As Worksheet, lastRow As Long, firstRow As Long
Dim i As Long, arrA, minVal As Double, dict As Object
Set sh = ActiveSheet
lastRow = sh.Range("A" & sh.rows.count).End(xlUp).row
firstRow = 7 'the row where the headers exist
minVal = 7000 'you can change it (if another limit would be necessary)...
arrA = sh.Range("A" & firstRow & ":K" & lastRow).value
Set dict = CreateObject("Scripting.Dictionary")
For i = 2 To UBound(arrA) 'iterate between the array rows:
If IsNumeric(arrA(i, 8)) And Trim(arrA(i, 8)) <> "" And arrA(i, 8) <> 0 And arrA(i, 8) > minVal Then
If Not dict.Exists(left(arrA(i, 1), 2)) Then
dict.Add left(arrA(i, 1), 2), Union(sh.Range(sh.Range("A" & firstRow), sh.Range("K" & firstRow)), _
sh.Range(sh.cells(i + firstRow - 1, "A"), sh.cells(i + firstRow - 1, "K")))
Else
Set dict(left(arrA(i, 1), 2)) = Union(dict(left(arrA(i, 1), 2)), _
sh.Range(sh.cells(i + firstRow - 1, "A"), sh.cells(i + firstRow - 1, "K")))
End If
End If
Next i
'drop the dictionary items content in the appropriate sheet (add it if not existing):
Application.ScreenUpdating = False 'to make the code faster, when inserts sheet and copy ranges...
Application.EnableEvents = False
For i = 0 To dict.count - 1
If Not sheetExists(CStr(dict.Keys()(i))) Then
Set newSh = ActiveWorkbook.Sheets.Add(After:=sh) 'insert the sheet if it does not exist
newSh.name = dict.Keys()(i)
Else
Set newSh = ActiveWorkbook.Sheets(dict.Keys()(i))'set the existing sheet and clear its content
newSh.cells.ClearContents
End If
dict.items()(i).Copy newSh.Range("A1") 'copy the dictionary range
Next i
End Sub
Function sheetExists(shName As String) As Boolean
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
If ws.name = shName Then sheetExists = True: Exit Function
Next ws
End Function
I am building on some code, partly cut and paste from other posts. I need to concatenate with a VBA code keeping the format and running through rows to output in last cell in each row. (Can't paste image) so hope description is clear:
In A1:D1 values are RED,BLUE,GREEN
In A2:D2 Values are YELLOW,PURPLE,ORANGE
OUTPUT IN E1 should concatenate these values, keeping font colour. Each value should have "ALT ENTR" to give line break.
Next row should be displayed in E2, and so on
'************************************************************************************
Sub test()
Dim rng As Range: Set rng = Application.Range("a1:c1") 'Not yet looping
Dim row As Range
For Each row In rng.Rows
'Debug.Print col.Column
Call concatenate_cells_formats(Cells(1, 4), rng) 'Not yet looping
Next row
End Sub
Sub concatenate_cells_formats(cell As Range, source As Range)
'Anon
Dim c As Range
Dim i As Integer
i = 1
With cell
.Value = vbNullString
.ClearFormats
For Each c In source
.Value = .Value & " " & Trim(c)
Next c
.Value = Trim(.Value)
For Each c In source
With .Characters(Start:=i, Length:=Len(Trim(c))).Font
.Name = c.Font.Name
.FontStyle = c.Font.FontStyle
.Size = c.Font.Size
.Strikethrough = c.Font.Strikethrough
.Superscript = c.Font.Superscript
.Subscript = c.Font.Subscript
.OutlineFont = c.Font.OutlineFont
.Shadow = c.Font.Shadow
.Underline = c.Font.Underline
.ColorIndex = c.Font.ColorIndex
End With
.Characters(Start:=i + Len(c), Length:=1).Font.Size = 1
i = i + Len(Trim(c)) + 1
Next c
End With
End Sub
'*****************************************************************************
Option Explicit
Sub concColour()
Dim i As Long, j As Long, s As Long, l As Long, clr As Long, vals As Variant
With Worksheets("sheet4")
For i = 1 To .Cells(.Rows.Count, "A").End(xlUp).Row
vals = Application.Transpose(Application.Transpose(Intersect(.Range("A:D"), .Rows(i)).Value2))
.Cells(i, "E") = Join(vals, vbLf)
s = 1
For j = LBound(vals) To UBound(vals)
l = Len(vals(j))
clr = .Cells(i, "A").Offset(0, j - 1).Font.Color
With .Cells(i, "E").Characters(Start:=s, Length:=l).Font
.Color = clr
End With
s = s + l + 1
Next j
.Cells(i, "E").Font.Size = 4
Next i
End With
End Sub
enter image description here
I think you require something like this. Change source font and formats as per your requirement.
Sub Adding_T()
Dim lena As Integer
Dim lenc As Integer
Dim lend As Integer
Dim lene As Integer
Dim LastRow As Long
Dim nrow As Long
With Worksheets("Sheet2") 'Change sheet as per your requirement
LastRow = .Cells(.Rows.Count, "A").End(xlUp).row
For nrow = 1 To LastRow
.Range("E" & nrow) = .Range("A" & nrow).Value2 & Chr(13) & Chr(10) & .Range("B" & nrow).Value2 & _
Chr(13) & Chr(10) & .Range("C" & nrow).Value2 & Chr(13) & Chr(10) & .Range("D" & nrow).Value2
lena = Len(.Range("A" & nrow).Value2)
lenc = lena + 2 + Len(.Range("B" & nrow).Value2)
lend = lenc + 2 + Len(.Range("C" & nrow).Value2)
lene = lend + 2 + Len(.Range("D" & nrow).Value2)
For i = 1 To lena
.Range("E" & nrow).Characters(Start:=i, Length:=1).Font.Color = _
.Range("A" & nrow).Characters(Start:=i, Length:=1).Font.Color
Next i
For i = lena + 2 To lenc
.Range("E" & nrow).Characters(Start:=i, Length:=1).Font.Color = _
.Range("B" & nrow).Characters(Start:=i, Length:=1).Font.Color
Next i
For i = lenc + 2 To lend
.Range("E" & nrow).Characters(Start:=i, Length:=1).Font.Color = _
.Range("C" & nrow).Characters(Start:=i, Length:=1).Font.Color
Next i
For i = lend + 2 To lene
.Range("E" & nrow).Characters(Start:=i, Length:=1).Font.Color = _
.Range("D" & nrow).Characters(Start:=i, Length:=1).Font.Color
Next i
Next
End With
End Sub
Snapshot of trial:
EDIT: OP Preferred code does not permit looping through the Range. Amended his Sub Test() to allow looping through the range.
Sub Test2()
Dim ws As Worksheet
Dim LastRow As Long
Set ws = ThisWorkbook.ActiveSheet
Dim rng As Range
Dim row As Range
Dim rw As Long
LastRow = ws.Cells(Rows.Count, "A").End(xlUp).row
rw = 1
For rw = 1 To LastRow
Set rng = ws.Range("A" & rw & ":C" & rw)
Call concatenate_cells_formats(Cells(rw, 4), rng)
Next
End Sub
Results are as per snapshot appended here.
I aim to select the rows corresponding to criteria in inputboxes, copy it, and paste it to another worksheet.
The code works but I need to fill all the inputboxes to copy paste the desired rows.
I would like if I do not fill one inputbox, still return all the rows matching the other criteria (example: if just fill the "Issue" InputBox it returns the rows with the matching issue date).
Sub filter()
Dim Bookrunner As String
Dim Bond_Type As Variant
Dim Currency_st As String
Dim Year_Issue As Integer
Bond_Type = InputBox("Choose a Bond Type", "Bond Type")
Currency_st = InputBox("Choose a Currency", "Currency")
Year_Issue = InputBox("Chosse the Year of Issuance", "Issue")
Bookrunner = InputBox("Choose a Bookrunner", "Bookrunner")
Dim copyFrom As Range
Dim i As Long
With Feuil1
For i = 2 To 54
If .Range("B" & i) = Bond_Type And _
.Range("K" & i) = Currency_st And _
.Range("D" & i).Value = Year_Issue And _
(.Range("R" & i) = Bookrunner Or .Range("S" & i) = Bookrunner Or _
.Range("T" & i) = Bookrunner Or .Range("U" & i) = Bookrunner Or _
.Range("V" & i) = Bookrunner Or .Range("w" & i) = Bookrunner) Then
If copyFrom Is Nothing Then
Set copyFrom = .Range("B" & i)
Else
Set copyFrom = Union(.Range("B" & i), copyFrom)
End If
End If
Next
End With
If Not copyFrom Is Nothing Then copyFrom.EntireRow.Copy Destination:=Sheets("Feuil2").Range("A2")
End Sub
i have several workbooks which get copy from one master workbook. what i want to do is when i enter data into the master workbook, i want to copy it into another workbook based on product type which i get fromn Combobox1.Value. to be more clear, which workbooks i want to copy the data depends on the ComboBox1.value. ie if the ComboBox1.value equals to "Penofix" then i want to copy the data into the workbook "Penofix.xlsm". i have finish coding on master input on how to enter data into particular row based on some condition but facing problem to copy the data into another workbooks.
Private Sub CmdEnter_Click()
Dim CountRow As Long
Dim i As Long
Dim prod as string
Dim j As Long
Dim Ws As Worksheet
Dim Count1 as Long
'CountRow is number of row in master workbook
CountRow = Worksheets("Input").Range("B" & Rows.Count).End(xlUp).Row
'assign variable prod with combobox1 value
prod = ComboBox1.Value
'i=32 because my row start at 32
For i = 32 To countRow + 31
While ComboBox1.Value = Worksheets("Input").Cells(i, 2).Value
Rows(i).Select
Selection.Insert shift = xlDown
With Worksheets("Input")
'insert data into master workbook
.Range("B" & i) = ComboBox1.Text
.Range("C" & i) = TextBox1.Text
.Range("D" & i) = TextBox2.Text
.Range("E" & i) = TextBox3.Text
.Range("F" & i) = TextBox4.Text
.Range("G" & i) = TextBox5.Text
.Range("H" & i) = ComboBox2.Text
.Range("I" & i) = TextBox6.Text
.Range("J" & i) = TextBox7.Text
.Range("K" & i) = TextBox8.Text
End With
'activate other workbook to copy data,if prod = Penofix,the workbook will be "Penofix.xlsm"
workbooks(prod & ".xlsm").Activate
'count the number of row in workbooks(prod & ".xlsm").
' i specified cell (31,3) to calculate the number of row used
Count1 = Workbooks(prod & ".xlsm").Worksheets("Sheet1").Cells(31,3).Value
Count1 = Count1 + 31
'copy data into workbooks(prod & ".xlsm")
'THIS IS THE LINE WHICH ERROR
Workbooks(prod & ".xlsm").Worksheets("Input").Range(Cells(Count1, 2), Cells(Count1 , 11)).Value = Workbooks("Master.xlsm").Worksheets("Input").Range(Cells(i, 2), Cells(i, 11)).Value
If MsgBox("One record written to Input. Do you want to continue entering data?", vbYesNo)= vbYes Then
ComboBox1.Text = ""
TextBox1.Text = ""
TextBox2.Text = ""
TextBox3.Text = ""
TextBox4.Text = ""
TextBox5.Text = ""
ComboBox2.Text = ""
TextBox6.Text = ""
TextBox7.Text = ""
TextBox8.Text = ""
Else
Unload Me
End If
Exit Sub
Wend
Next
End Sub
i've try to replace
Workbooks(prod & ".xlsm").Worksheets("Input").Range(Cells(Count1, 2), Cells(Count1 , 11)).Value = Workbooks("Master.xlsm").Worksheets("Input").Range(Cells(i, 2), Cells(i, 11)).Value
with this
Workbooks(prod & ".xlsm").Worksheets("Input").Cells(Count1, 2).Value = Workbooks("Master.xlsm").Worksheets("Input").Cells(i, 2).Value
and yeah its work but it just for one singe cell only. so i think the error is on the syntax :
Range(Cells(Count1,2), Cells(Count1,11))
but i dont know how to make it to copy the entire row
Workbooks("Master.xlsm").Worksheets("Input").Range(cells(i,B).cells(i,K)).Value = _
Workbooks(prod & ".xlsm").).Worksheets("Sheet1").Range(Cells(CountRow, B). Cells(CountRow, K)).Value
This code will update the master workbook, I doubt you want to this. Also there is a syntax error with .). and then some.
I think this is what you need:
Dim sht1 As Worksheet, sht2 As Worksheet
Set sht1 = Workbooks(prod & ".xlsm").Worksheets("Sheet1")
Set sht2 = Workbooks("Master.xlsm").Worksheets("Input")
sht1.Range(sht1.Cells(CountRow, 2), sht1.Cells(CountRow, 11)).Value = _
sht2.Range(sht2.Cells(i, 2), sht2.Cells(i, 11)).Value
Imroved code: Using resize(<row>, <column>)
Workbooks(prod & ".xlsm").Worksheets("Sheet1").Cells(CountRow, 2).resize(, 11).Value = _
Workbooks("Master.xlsm").Worksheets("Input").Cells(i, 2).resize(, 11).Value
For some added info, the Cells(<Row>, <Column>) will only take integers in for either <Row> and <Column>. Hence the column B is represented as 2.