The cells contain different lengths of data. I tried text to column. It does not work because of the number of dots.
How can I populate each text or number in separate cells by ignoring the number of dots than delete the line anywhere there is an empty cell in column A and B?
Data exemple:
Split Data
Associated
Sub SplitAssociated()
Const sName As String = "Sheet1"
Const sFirstCellAddress As String = "A1"
Const dName As String = "Sheet1"
Const dFirstCellAddress As String = "B1"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim sfCell As Range: Set sfCell = sws.Range(sFirstCellAddress)
Dim srg As Range
Dim rCount As Long
With sfCell.Resize(sws.Rows.Count - sfCell.Row + 1)
Dim slCell As Range
Set slCell = .Find("*", , xlFormulas, , , xlPrevious)
rCount = slCell.Row - .Row + 1
Set srg = .Resize(rCount)
End With
Dim Data As Variant
Data = sws.Evaluate("TRIM(SUBSTITUTE(" & srg.Address & ",""."","" ""))")
Dim SubStrings() As Variant: ReDim SubStrings(1 To rCount)
Dim Lens() As Long: ReDim Lens(1 To rCount)
Dim r As Long
Dim cCount As Long
Dim cString As String
For r = 1 To rCount
cString = Data(r, 1)
If Len(cString) > 0 Then
SubStrings(r) = Split(cString)
Lens(r) = UBound(SubStrings(r)) + 1
If Lens(r) > cCount Then cCount = Lens(r)
End If
Next r
ReDim Data(1 To rCount, 1 To cCount)
Dim c As Long
For r = 1 To rCount
For c = 1 To Lens(r)
Data(r, c) = SubStrings(r)(c - 1)
Next c
Next r
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim dfCell As Range: Set dfCell = dws.Range(dFirstCellAddress)
Dim drg As Range: Set drg = dfCell.Resize(rCount, cCount)
drg.Value = Data
drg.Resize(dws.Rows.Count - drg.Row - rCount + 1).Offset(rCount).Clear
End Sub
Remove Blanks
Sub SplitRemoveBlanks()
Const sName As String = "Sheet1"
Const sFirstCellAddress As String = "A1"
Const dName As String = "Sheet2"
Const dFirstCellAddress As String = "C1"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim sfCell As Range: Set sfCell = sws.Range(sFirstCellAddress)
Dim srg As Range
Dim srCount As Long
With sfCell.Resize(sws.Rows.Count - sfCell.Row + 1)
Dim slCell As Range
Set slCell = .Find("*", , xlFormulas, , , xlPrevious)
srCount = slCell.Row - .Row + 1
Set srg = .Resize(srCount)
End With
Dim Data As Variant
Data = sws.Evaluate("TRIM(SUBSTITUTE(" & srg.Address & ",""."","" ""))")
Dim SubStrings() As Variant: ReDim SubStrings(1 To srCount)
Dim Lens() As Long: ReDim Lens(1 To srCount)
Dim sr As Long
Dim drCount As Long
Dim dcCount As Long
Dim cString As String
For sr = 1 To srCount
cString = Data(sr, 1)
If Len(cString) > 0 Then
drCount = drCount + 1
SubStrings(sr) = Split(cString)
Lens(sr) = UBound(SubStrings(sr)) + 1
If Lens(sr) > dcCount Then dcCount = Lens(sr)
End If
Next sr
ReDim Data(1 To drCount, 1 To dcCount)
Dim dr As Long
Dim dc As Long
For sr = 1 To srCount
If Lens(sr) > 0 Then
dr = dr + 1
For dc = 1 To Lens(sr)
Data(dr, dc) = SubStrings(sr)(dc - 1)
Next dc
End If
Next sr
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim dfCell As Range: Set dfCell = dws.Range(dFirstCellAddress)
Dim drg As Range: Set drg = dfCell.Resize(drCount, dcCount)
drg.Value = Data
drg.Resize(dws.Rows.Count - drg.Row - drCount + 1).Offset(drCount).Clear
End Sub
If the "." (dot) is the element to be stripped from strings in cells (eg no floating point numbers, nor "." is an important mark), you can use this code including deleting entire lines.
The code loops through the specified range (oRng) and when it finds ".." it will replace it with ".". Then, when no more ".." is found, indicating that the replacement job has completed, generating an error (caught), it proceeds to delete the blank rows from the blank cells in column "A".
Option Explicit
Sub fnCleanAndSplit()
Dim oRng As Excel.Range
Dim oCell As Excel.Range
Dim fDone As Boolean
Set oRng = ThisWorkbook.Sheets(1).Range("A1:A7")
Do
For Each oCell In oRng.Cells
oCell.Value = VBA.Replace(oCell.Value, "..", ".")
Next
On Error GoTo lblDone
fDone = oRng.Find("..") = ""
On Error GoTo 0
Loop Until fDone
lblDone:
oRng.TextToColumns Destination:=oRng.Cells(1), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, Other:=True, OtherChar _
:=".", TrailingMinusNumbers:=True
oRng.SpecialCells(xlCellTypeBlanks).Select
oRng.Parent.Activate 'just in case it is not activated
Selection.EntireRow.Delete
End Sub
Related
I want to look for value of Forecast in cell (F column) (more than one instance - unique key is Prod and Cust), then copy corresponding row values to other rows identified by Edited Forecast value in another cell (more than one instance - unique key is Prod and Cust (same column).)
This is only copying Row values.
Private AutomationObject As Object
Sub Save ()
Dim Worksheet as Worksheet
Set Worksheet = ActiveWorkbook.Worksheets("Sheet")
Worksheet.Range("M18:AX18").Value = Worksheet.Range("M15:AX15").Value
End Sub
Fill Blanks (Unique Dictionary)
Option Explicit
Sub FillBlanks()
Const sFirstCellAddress As String = "D3"
Const sDelimiter As String = "#"
Const dCols As String = "I:K"
Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
Dim srg As Range
Dim rCount As Long
With ws.Range(sFirstCellAddress)
Dim lCell As Range: Set lCell = .Resize(ws.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If lCell Is Nothing Then Exit Sub
rCount = lCell.Row - .Row + 1
Set srg = .Resize(rCount, 2)
End With
Dim sData As Variant: sData = srg.Value
Dim drg As Range: Set drg = srg.EntireRow.Columns(dCols)
Dim dcCount As Long: dcCount = drg.Columns.Count
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Dim rg As Range
Dim r As Long
Dim sString As String
For r = 1 To rCount
sString = sData(r, 1) & sDelimiter & sData(r, 2)
If Application.CountBlank(drg.Rows(r)) = dcCount Then
If dict.Exists(sString) Then
If IsArray(dict(sString)) Then
drg.Rows(r).Value = dict(sString)
Else
dict(sString).Add drg.Rows(r)
End If
Else
Set dict(sString) = New Collection
dict(sString).Add drg.Rows(r)
End If
Else
If dict.Exists(sString) Then
If IsArray(dict(sString)) Then
'drg.Rows(r).Value = dict(sString) ' overwrite!?
Else
For Each rg In dict(sString)
rg.Value = drg.Rows(r).Value
Next rg
dict(sString) = drg.Rows(r).Value
End If
Else
dict(sString) = drg.Rows(r).Value
End If
End If
Next r
MsgBox "Data updated.", vbInformation
End Sub
My idea is to get the data that I have on "A4" ("Data" worksheet) and paste it 4 times on "B4" ("Forecast" worksheet). After that, take the data from "A5" and do the same (starting from the first blank cell) until there is no more data on the "A" column. After there is no more data, the process should stop.
How do I tell excel to paste the value in the first blank cell in column B ("Forecast" worksheet)?
Sub Test()
Dim wsSource As Worksheet, wsTarget As Worksheet
Dim i As Integer, k As Integer
Set wsSource = ThisWorkbook.Worksheets("Data")
Set wsTarget = ThisWorkbook.Worksheets("Forecast")
k = wsSource.Range("A4", wsSource.Range("A4").End(xlDown)).Rows.Count
For i = 1 To k
wsTarget.Range("B4", "B7").Value = wsSource.Range("A" & 3 + i).Value
Next
End Sub
Copy Repetitions
A Quick Fix
Sub Test()
Dim wsSource As Worksheet, wsTarget As Worksheet
Dim sCell As Range, tCell As Range
Dim i As Long, j As Long, k As Long
Set wsSource = ThisWorkbook.Worksheets("Data")
Set wsTarget = ThisWorkbook.Worksheets("Forecast")
k = wsSource.Range("A4", wsSource.Range("A4").End(xlDown)).Rows.Count
Set sCell = wsSource.Range("A4")
Set tCell = wsTarget.Range("B4")
For i = 1 To k
For j = 1 To 4
tCell.Value = sCell.Value
Set tCell = tCell.Offset(1)
Next j
Set sCell = sCell.Offset(1)
Next i
End Sub
My Choice
Sub CopyRepetitions()
' Source
Const sName As String = "Data"
Const sfCellAddress As String = "A4"
' Destination
Const dName As String = "Forecast"
Const dfCellAddress As String = "B4"
Const Repetitions As Long = 4
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Reference the source (one-column) range ('srg').
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim srg As Range
Dim srCount As Long
With sws.Range(sfCellAddress)
Dim lCell As Range: Set lCell = .Resize(sws.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If lCell Is Nothing Then Exit Sub ' no data
srCount = lCell.Row - .Row + 1
Set srg = .Resize(srCount)
End With
' Write values from the source range the source array ('sData')
Dim sData As Variant
If srCount = 1 Then
ReDim sData(1 To 1, 1 To 1): sData(1, 1) = srg.Value
Else
sData = srg.Value
End If
' Define the destination array ('dData').
Dim drCount As Long: drCount = srCount * Repetitions
Dim dData As Variant: ReDim dData(1 To drCount, 1 To 1)
' Write the repeating values from the source- to the destination array.
Dim sr As Long
Dim rep As Long
Dim dr As Long
For sr = 1 To srCount
For rep = 1 To Repetitions
dr = dr + 1
dData(dr, 1) = sData(sr, 1)
Next rep
Next sr
' Write the values from the destination array to the destination
' one-column range and clear the data below.
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
With dws.Range(dfCellAddress)
.Resize(drCount).Value = dData
.Resize(dws.Rows.Count - .Row - drCount + 1).Offset(drCount).Clear
End With
' Inform.
MsgBox "Repetitions copied.", vbInformation
End Sub
I have two sheets and I need to get names of fields for each person. For that I need to take a person of a row in sheet2 then i have to get the fields which this person is assigned in the sheet1 on the right table (for every rows). For this part I found and modified this VBA code, but it doesn't do what I need ... :
Dim rgFound As Range
Dim defVal As Range
Dim currParam As Range
Dim currParamDict As Range
With Worksheets("Sheet2")
For Each defVal In .Range("B3", .Range("B" & Rows.Count).End(xlUp)).Offset(, 1)
Set currParam = defVal.Offset(, -1)
If Len(currParam.Value) > 0 Then
Set rgFound = Worksheets("Sheet1").Range("F9:I12").Find(currParam.Value)
If rgFound Is Nothing Then
Debug.Print "Name was not found."
Else
Set currParamDict = rgFound.Offset(, 0)
defVal.Value = currParamDict.Value
End If
End If
Next defVal
End With
I dont know for the range in : Set rgFound = Worksheets("Sheet1").Range("F9:I12").Find(currParam.Value)
I put some example pictures so you can see what it is about.
Sheet1 :
Sheet2 :
After this step, I have to fill the dates corresponding to fields using the left table of the Sheet1...
Fill a Table
Off Track
Ignore possible old data in Sheet2 and write the complete table.
Option Explicit
Sub FillTable()
' Source Dates
Const sdName As String = "Sheet1"
Const sdFirst As String = "B2"
' Source Cities
Const scName As String = "Sheet1"
Const scFirst As String = "F9"
' Destination
Const dName As String = "Sheet2"
Const dFirst As String = "B2"
Const dHeader As String = "Name"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Source Dates
Dim sdws As Worksheet: Set sdws = wb.Worksheets(sdName)
Dim sdrg As Range: Set sdrg = sdws.Range(sdFirst).CurrentRegion
Dim sdData As Variant: sdData = sdrg.Value
Dim sdrCount As Long: sdrCount = sdrg.Rows.Count
Dim sdcCount As Long: sdcCount = sdrg.Columns.Count
' Source Cities
Dim scws As Worksheet: Set scws = wb.Worksheets(scName)
Dim scrg As Range: Set scrg = scws.Range(scFirst).CurrentRegion
Dim scData As Variant: scData = scrg.Value
Dim schrg As Range: Set schrg = scrg.Rows(1)
Dim scrCount As Long: scrCount = scrg.Rows.Count
Dim sctCount As Long: sctCount = Application.CountA(scrg)
' Destination Array
Dim drCount As Long: drCount = sctCount + 1 ' '+ 1' for headers
Dim dcCount As Long: dcCount = 1 + sdcCount ' 1 for 'Name'
Dim dData As Variant: ReDim dData(1 To drCount, 1 To dcCount)
' Write headers to Destination Array.
Dim sdc As Long
dData(1, 1) = dHeader
For sdc = 1 To sdcCount
dData(1, sdc + 1) = sdData(1, sdc)
Next sdc
' Write 'body' to Destination Array.
Dim dr As Long: dr = 1 ' 1 for headers
Dim sccIndex As Variant
Dim scValue As Variant
Dim sdr As Long
Dim scr As Long
For sdr = 2 To sdrCount
sccIndex = Application.Match(sdData(sdr, 1), schrg, 0)
For scr = 2 To scrCount
scValue = scData(scr, sccIndex)
If Not IsError(scValue) Then
If Len(scValue) > 0 Then
dr = dr + 1
dData(dr, 1) = scValue
For sdc = 1 To sdcCount
dData(dr, sdc + 1) = sdData(sdr, sdc)
Next sdc
End If
End If
Next scr
Next sdr
' Write Destination Array to Destination Range.
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim dfcell As Range: Set dfcell = dws.Range(dFirst)
Dim drg As Range: Set drg = dfcell.Resize(drCount, dcCount)
drg.Value = dData
' Clear Destination Clear Range, the range below Destination Range.
Dim dcrg As Range
Set dcrg = drg.Resize(drg.Worksheet.Rows.Count - drg.Row - drCount + 1) _
.Offset(drCount)
dcrg.Clear ' or 'dcrg.ClearContents'
' Format e.g.:
drg.Rows(1).Font.Bold = True
dws.Range(drg.Columns(3), drg.Columns(dcCount)).Resize(drCount - 1) _
.Offset(1).NumberFormat = "dd/mm/yyyy" ' possibly "dd\/mm\/yyyy"
drg.EntireColumn.AutoFit
'wb.Save
End Sub
Meeting the Requirement
There are the names in Sheet2, so fill the other columns.
Sub FillTable2()
' Source Dates
Const sdName As String = "Sheet1"
Const sdFirst As String = "B2"
' Source Cities
Const scName As String = "Sheet1"
Const scFirst As String = "F9"
' Destination
Const dName As String = "Sheet2"
Const dFirst As String = "B2"
Dim wb As Workbook: Set wb = ThisWorkbook
' Source Dates
Dim sdws As Worksheet: Set sdws = wb.Worksheets(sdName)
Dim sdrg As Range: Set sdrg = sdws.Range(sdFirst).CurrentRegion
Dim sddrg As Range: Set sddrg = sdrg.Resize(sdrg.Rows.Count - 1).Offset(1)
Dim sdData As Variant: sdData = sddrg.Value
Dim sdrlrg As Range: Set sdrlrg = sddrg.Columns(1) ' Row Labels
' Source Cities
Dim scws As Worksheet: Set scws = wb.Worksheets(scName)
Dim scrg As Range: Set scrg = scws.Range(scFirst).CurrentRegion
Dim schRow As Long: schRow = scrg.Row ' Header Row
Dim scdrg As Range: Set scdrg = scrg.Resize(scrg.Rows.Count - 1).Offset(1)
Dim scrCount As Long: scrCount = scdrg.Rows.Count
Dim sccCount As Long: sccCount = scdrg.Columns.Count
' Destination Names
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim dfcell As Range: Set dfcell = dws.Range(dFirst)
Dim drg As Range: Set drg = dfcell.CurrentRegion.Columns(1)
Dim dnrg As Range: Set dnrg = drg.Resize(drg.Rows.Count - 1).Offset(1)
Dim dnData As Variant: dnData = dnrg.Value
' Destination Array
Dim drCount As Long: drCount = dnrg.Rows.Count
Dim dcCount As Long: dcCount = sdrg.Columns.Count
Dim dData As Variant: ReDim dData(1 To drCount, 1 To dcCount)
Dim scCell As Range
Dim dnValue As Variant
Dim scValue As Variant
Dim sdrIndex As Variant
Dim r As Long
Dim c As Long
For r = 1 To drCount
dnValue = dnData(r, 1)
If NoErrorNorBlank(dnValue) Then
Set scCell = Nothing
Set scCell = scdrg.Find(dnValue, _
scdrg.Cells(scrCount, sccCount), xlFormulas, xlWhole)
If Not scCell Is Nothing Then
scValue = scCell.EntireColumn.Rows(schRow).Value
If NoErrorNorBlank(scValue) Then
sdrIndex = Application.Match(scValue, sdrlrg, 0)
If IsNumeric(sdrIndex) Then
For c = 1 To dcCount
dData(r, c) = sdData(sdrIndex, c)
Next c
End If
End If
End If
End If
Next r
Set drg = dnrg.Offset(, 1).Resize(, dcCount)
drg.Value = dData
'wb.Save
End Sub
Function NoErrorNorBlank( _
ByVal CheckValue As Variant) _
As Boolean
If Not IsError(CheckValue) Then
If Len(CheckValue) > 0 Then
NoErrorNorBlank = True
End If
End If
End Function
This line is not identifying a district, but the name in the search itself. Change the statement to reference the data in line 9. I assume that position is fixed, if not then you need another approach.
Set currParamDict = rgFound.Offset(, 0)
' becomes
set currParamDict = Worksheets("sheet1").Cells(9, rgFound.Column)
I have below code in which i want to create a loop for multiple values that are available in Sheet1.Range(A2:A100) code will pick one by one each value and match then paste result in Column B.
thisvalue = Sheet1.Range("A2:A100"). Can someone please help me to create the loop. Your help will be appreciated.
Sub Macro1()
Dim thisvalue As Double, sh As Worksheet, lastR As Long, arr, arrFin, i As Long
thisvalue = 3.61
Set sh = Worksheets("Sheet1")
lastR = sh.Range("J" & sh.rows.count).End(xlUp).row
arr = sh.Range("E7:J" & lastR).Value
ReDim arrFin(1 To UBound(arr), 1 To 1)
For i = 1 To UBound(arr)
If arr(i, 1) < thisvalue And arr(i, 2) > thisvalue Then arrFin(i, 1) = arr(i, 6)
Next i
sh.Range("B2").Resize(UBound(arrFin), 1).Value = arrFin
End Sub
Please, try the next code:
Sub Macro1__2()
Dim thisvalue As Double, sh As Worksheet, lastR As Long
Dim arrVal, arr, arrFin, i As Long, j As Long
Set sh = Worksheets("Sheet2")
arrVal = Worksheets("Sheet1").Range("Q2:Q100").Value
Worksheets("Sheet1").Range("R2:R200").ClearContents
lastR = sh.Range("J" & sh.Rows.Count).End(xlUp).Row
arr = sh.Range("E7:J" & lastR).Value
For j = 1 To UBound(arrVal)
thisvalue = arrVal(j, 1)
If CStr(thisvalue) <> "" Then 'excluding the cases of empty cells. I didn't know that they may exist
arrFin = Worksheets("Sheet1").Range("R2:R200").Value 'firstly input the existing range in the array
For i = 1 To UBound(arr)
If arr(i, 1) < thisvalue And arr(i, 2) > thisvalue Then arrFin(j, 1) = arr(i, 6)
Next i
Worksheets("Sheet1").Range("R2").Resize(UBound(arrFin), 1).Value = arrFin
End If
Next j
MsgBox "Ready..."
End Sub
Ranges and Arrays
Option Explicit
Sub Macro1()
' Source
Const sName As String = "Sheet1"
Const slrCol As String = "J"
Const sCols As String = "E:J"
Const sfRow As Long = 7
Const scColLess As Long = 1
Const scColGreater As Long = 2
Const srCol As Long = 6
Const sCriteria As Double = 3.61
' Destination
Const dName As String = "Sheet1"
Const dFirst As String = "B2"
' Create a reference to the Workbook ('wb').
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Create a reference to the Source Worksheet ('sws').
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
' Create a reference to the Source Range ('srg').
If sws.Columns(sCols).Columns.Count < srCol Then Exit Sub ' too few columns
Dim slRow As Long: slRow = sws.Cells(sws.Rows.Count, slrCol).End(xlUp).Row
If slRow < sfRow Then Exit Sub ' no data
Dim rCount As Long: rCount = slRow - sfRow + 1 ' for source and destination
Dim srg As Range
Set srg = sws.Rows(sfRow).Columns(sCols).Resize(rCount)
' Write the values from the Source Range
' to the Source Array ('sData').
Dim sData As Variant: sData = srg.Value
' Define the Destination Array ('dData').
Dim dData As Variant: ReDim dData(1 To rCount, 1 To 1)
' Write the appropriate values from the Source Array
' to the Destination Array.
Dim cValue As Variant
Dim r As Long
For r = 1 To rCount
cValue = sData(r, scColLess)
If IsNumeric(cValue) Then
If cValue < sCriteria Then
cValue = sData(r, scColGreater)
If IsNumeric(cValue) Then
If cValue > sCriteria Then
dData(r, 1) = sData(r, srCol)
End If
End If
End If
End If
Next r
' Create a reference to the Destination Worksheet ('dws').
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
' Create a reference to the Destination Range ('drg').
Dim dfCell As Range: Set dfCell = dws.Range(dFirst)
Dim drg As Range: Set drg = dfCell.Resize(rCount)
' Write the values from the Destination Array
' to the Destination Range ('drg').
drg.Value = dData
' Clear the Destination Clear Range ('dcrg'),
' the range below the Destination Range.
Dim dcrg As Range
Set dcrg = drg.Resize(dws.Rows.Count - drg.Row - rCount + 1).Offset(rCount)
dcrg.Clear ' or maybe rather 'dcrg.ClearContents'
' Format the Destination Range.
'drg.Font.Bold = True
'drg.EntireColumn.AutoFit
'drg.Interior.Color = 14348258
' Save the workbook.
'wb.Save
End Sub
My initial understanding is that I may be able to use Union to solve this:
I have different dynamic named ranges for various product types on separate pages in a workbook. All carry the same start cell and column properties, but vary in length based on input data. Is there an easy way to automatically pool these entries into a consolidated list? These are not formatted tables, and I'd prefer to avoid making them into charts.
Ex: Worksheet 1 carries a list of two products (B2:B3) with associated revenue and cost figures in columns C and D. Worksheet 2 carries a list of three products (B2:B4) with... I'd like to have worksheet 3 automatically update with (B2:B6) and columns C and D with data from the original 2 worksheets. This data will grow and will be changed periodically.
Here's one method to emulate UNION
=LET(
data1,FILTER('Worksheet 1'!B:D,'Worksheet 1'!B:B<>""),
data2,FILTER('Worksheet 2'!B:D,'Worksheet 2'!B:B<>""),
rows1,ROWS(data1),
rows2,ROWS(data2),
cols1,COLUMNS(data1),
rowindex,SEQUENCE(rows1+rows2),
colindex,SEQUENCE(1,cols1),
IF(
rowindex<=rows1,
INDEX(data1,rowindex,colindex),
INDEX(data2,rowindex-rows1,colindex))
)
I know my code is probably wildly inefficient - I'm still at the beginning of my learning... Since I couldn't figure out this "union" thing, I ended up running the following code:
Sub dynamicRangeCons()
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Application.ScreenUpdating = False
Dim startCell As Range, lastRow As Long, lastCol As Long, ws0 As Worksheet, ws1 As Worksheet
Dim ConsItem As String
Set ws = Worksheets("Cons Ingredients Listing")
ws.Activate
Set startCell = ws.Range("B3")
Set ws0 = ThisWorkbook.Sheets("Cons Ingredients Listing")
Set ws1 = ThisWorkbook.Sheets("Spirits Ingredients Listing")
Set ws2 = ThisWorkbook.Sheets("Beer Ingredients Listing")
Set ws3 = ThisWorkbook.Sheets("Misc Ingredients Listing")
Set ws4 = ThisWorkbook.Sheets("Wine Ingredients Listing")
Set ws5 = ThisWorkbook.Sheets("NA Ingredients Listing")
lastRow = ws.Cells(ws.Rows.Count, startCell.Column).End(xlUp).Row
lastCol = ws.Cells(startCell.Row, startCell.Column).End(xlToRight).Column
ws.Range(startCell, ws.Cells(lastRow, lastCol)).Clear
ws1.Range("SpiritsItem").Copy ws0.Range("B3")
ws1.Range("Spirits").Copy ws0.Range("C3")
lastRow = ws.Cells(ws.Rows.Count, startCell.Column).End(xlUp).Row
lastCol = ws.Cells(startCell.Row, startCell.Column).Column
ws2.Range("BeerItem").Copy ws.Cells(lastRow + 1, lastCol)
ws2.Range("Beer").Copy ws.Cells(lastRow + 1, lastCol + 1)
lastRow = ws.Cells(ws.Rows.Count, startCell.Column).End(xlUp).Row
lastCol = ws.Cells(startCell.Row, startCell.Column).Column
ws3.Range("MiscItem").Copy ws.Cells(lastRow + 1, lastCol)
ws3.Range("Misc").Copy ws.Cells(lastRow + 1, lastCol + 1)
lastRow = ws.Cells(ws.Rows.Count, startCell.Column).End(xlUp).Row
lastCol = ws.Cells(startCell.Row, startCell.Column).Column
ws4.Range("WineItem").Copy ws.Cells(lastRow + 1, lastCol)
ws4.Range("Wine").Copy ws.Cells(lastRow + 1, lastCol + 1)
lastRow = ws.Cells(ws.Rows.Count, startCell.Column).End(xlUp).Row
lastCol = ws.Cells(startCell.Row, startCell.Column).Column
ws5.Range("NAItem").Copy ws.Cells(lastRow + 1, lastCol)
ws5.Range("NA").Copy ws.Cells(lastRow + 1, lastCol + 1)
lastRow = ws.Cells(ws.Rows.Count, startCell.Column).End(xlUp).Row
lastCol = ws.Cells(startCell.Row, startCell.Column).Column
ws.Range(startCell, ws.Cells(lastRow, lastCol)).Select
ThisWorkbook.Names.Add Name:="ConsItem", RefersTo:=Selection
lastRow = ws.Cells(ws.Rows.Count, startCell.Column).End(xlUp).Row
lastCol = ws.Cells(startCell.Row, startCell.Column).End(xlToRight).Column
ws.Range(ws.Cells(startCell.Row, startCell.Column + 1), ws.Cells(lastRow, lastCol)).Select
ThisWorkbook.Names.Add Name:="Cons", RefersTo:=Selection
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Consolidate Worksheets
Copy the following into a standard module, e.g. Module1.
Adjust the values in the constants section.
Option Explicit
Sub ConsolidateProducts()
Const sNamesList As String = "Sheet1,Sheet2"
Const sFirst As String = "B2:D2"
Const dName As String = "Sheet3"
Const dFirst As String = "B2"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sNames() As String: sNames = Split(sNamesList, ",")
Dim nUpper As Long: nUpper = UBound(sNames)
Dim nCount As Long: nCount = -1
Dim sData As Variant: ReDim sData(0 To nUpper)
Dim rData() As Long: ReDim rData(0 To nUpper)
Dim sws As Worksheet
Dim srg As Range
Dim sfrrg As Range
Dim slCell As Range
Dim srCount As Long
Dim drCount As Long
Dim n As Long
For n = 0 To nUpper
Set sws = wb.Worksheets(sNames(n))
Set sfrrg = sws.Range(sFirst)
Set slCell = Nothing
Set slCell = sfrrg.Resize(sws.Rows.Count - sfrrg.Row + 1) _
.Find("*", , xlFormulas, , xlByRows, xlPrevious)
If Not slCell Is Nothing Then
nCount = nCount + 1
srCount = slCell.Row - sfrrg.Row + 1
Set srg = sfrrg.Resize(srCount)
sData(nCount) = srg.Value
rData(nCount) = srCount
drCount = drCount + srCount
End If
Next n
If nCount = -1 Then Exit Sub
Dim cCount As Long: cCount = sfrrg.Columns.Count
Dim dData As Variant: ReDim dData(1 To drCount, 1 To cCount)
Dim s As Long, d As Long, c As Long
For n = 0 To nCount
For s = 1 To rData(n)
d = d + 1
For c = 1 To cCount
dData(d, c) = sData(n)(s, c)
Next c
Next s
Next n
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim dfCell As Range: Set dfCell = dws.Range(dFirst)
Dim dfrrg As Range: Set dfrrg = dfCell.Resize(, cCount)
Dim drg As Range: Set drg = dfrrg.Resize(drCount)
drg.Value = dData
Dim dcrg As Range: Set dcrg = dfrrg _
.Resize(dws.Rows.Count - dfrrg.Row - drCount - 1).Offset(drCount)
dcrg.ClearContents
End Sub
If all the data are values then to automate the previous, copy the following into each source module (not the destination (resulting) worksheet).
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Const sFirst As String = "B2:D2"
Dim srg As Range
With Range(sFirst)
Set srg = .Resize(Rows.Count - .Row + 1)
End With
Dim irg As Range
Set irg = Intersect(srg, Target)
If Not srg Is Nothing Then
ConsolidateProducts
End If
End Sub