Excel VBA: Merge worksheets by search/mapping headers? - vba

Looking to up my manual mapping solution of merging worksheets, to a search-map header solution. The basics are this
Dest_Worksheet: This has the only headers that are needed post merge (up to 50 columns)
Source_Worksheet1: This has a list of items with some headers that match Dest_Worksheet (up to 100 columns - different than Source_Worksheet2)
Source_Worksheet2: This has a list of items with some headers that match Dest_Worksheet (up to 100 columns - different than Source_Worksheet1)
Total row count unknown at the time of run. Currently built out a manual mapping (see below).
ASKING: Move beyond manual mapping of each worksheet to a solution which reviews the Dest_Worksheet and references those headers, move through remaining or identified list of Source worksheets and copy all rows with only columns that match Dest_Worksheet.
See sample worksheet for working manual mapping code below
'******Manual Mapping of Source_Data1*******
Sub Source_Data1()
Dim sht As Worksheet
Dim colname As String
Dim Lastrow As Integer, rowcount As Integer
colname = 1
For Each sht In ActiveWorkbook.Worksheets
If sht.Name = "Source_Worksheet1" And sht.Range("A3").Value <> "" Then
Sheets("Source_Worksheet1").Select
Lastrow = Range("A9000").End(xlUp).Row
Sheets("Dest_Worksheet").Select
rowcount = Range("A9000").End(xlUp).Row + 1
sht.Select
Sheets("Dest_Worksheet").Range("A" & rowcount & ":A" & rowcount + Lastrow - 3).Value = sht.Range("A3:A" & Lastrow).Value
Sheets("Dest_Worksheet").Range("B" & rowcount & ":B" & rowcount + Lastrow - 3).Value = sht.Range("B3:B" & Lastrow).Value
Sheets("Dest_Worksheet").Range("C" & rowcount & ":C" & rowcount + Lastrow - 3).Value = sht.Range("C3:C" & Lastrow).Value
Sheets("Dest_Worksheet").Range("D" & rowcount & ":D" & rowcount + Lastrow - 3).Value = sht.Range("D3:D" & Lastrow).Value
End If
Next sht
Worksheets("Dest_Worksheet").Select
End Sub
'******Manual Mapping of Source_Data2*******
Sub Source_Data2()
Dim sht As Worksheet
Dim colname As String
Dim Lastrow As Integer, rowcount As Integer
colname = 1
For Each sht In ActiveWorkbook.Worksheets
If sht.Name = "Source_Worksheet2" And sht.Range("A3").Value <> "" Then
Sheets("Source_Worksheet2").Select
Lastrow = Range("A9000").End(xlUp).Row
Sheets("Dest_Worksheet").Select
rowcount = Range("A9000").End(xlUp).Row + 1
sht.Select
Sheets("Dest_Worksheet").Range("A" & rowcount & ":A" & rowcount + Lastrow - 3).Value = sht.Range("A3:A" & Lastrow).Value
Sheets("Dest_Worksheet").Range("E" & rowcount & ":E" & rowcount + Lastrow - 3).Value = sht.Range("B3:B" & Lastrow).Value
Sheets("Dest_Worksheet").Range("F" & rowcount & ":F" & rowcount + Lastrow - 3).Value = sht.Range("C3:C" & Lastrow).Value
Sheets("Dest_Worksheet").Range("C" & rowcount & ":C" & rowcount + Lastrow - 3).Value = sht.Range("E3:E" & Lastrow).Value
End If
Next sht
Worksheets("Dest_Worksheet").Select
End Sub

After lots of trial and error I got Find() working to return the column letter I'm looking for. Here's the code I ended up using and the associated function call:
Sub LookupText()
Dim DestLetter As String
DestLetter = TextLookup("Search Text")
MsgBox DestLetter
End Sub
'***********
Function TextLookup(TheText As String) As String
Set Cell = Worksheets("Destination_Worksheet").Cells.range("A1:DA1").Find(TheText, , xlValues, xlPart, , , False)
If Not Cell Is Nothing Then
ColLetter = Split(Cell.Address, "$")(1)
TextLookup = ColLetter
End If
End Function

Related

VBA to populate names

I need help to create one VBA for below issue -
column C should be updated based on column A and B values.
in below example if column A=Unit1 and column B=IND then Person 1 and so on.. it should loop till end.
Thank you in adv. please refer picture for sample data
enter image description here
Here you go. Just change the sheet name since I don't know what you're working with.
Sub AddPerson()
Dim i As Long, ws As Worksheet, lRow As Long
Set ws = Sheets("Sheet1") 'Change to your sheet name
lRow = ws.Range("A" & Rows.Count).End(xlUp).Row
With ws
.Range("C2:C" & lRow + 1).ClearContents
For i = 2 To lRow
If .Range("B" & i) = "IND" Then
.Range("C" & i) = "Person1"
ElseIf .Range("A" & i) = "Unit5" And .Range("B" & i) = "OTR" Then
.Range("C" & i) = "Person3"
Else
.Range("C" & i) = "Person2"
End If
Next i
End With
End Sub

Excel/VBA - Combine rows and columns from worksheets into one, with varying source columns

I am working on combining multiple Excel worksheets into a single Master worksheet. The following code works for when all worksheets have identical columns:
Sub CombineData()
Dim Sht As Worksheet
'This If will clear Master before combining
Worksheets("Master").Range("A2:ZZ9000").ClearContents
For Each Sht In ActiveWorkbook.Worksheets
If Sht.Name <> "Master" And Sht.Range("A2").Value <> "" Then
Sht.Select
LastRow = Range("A9000").End(xlUp).Row
Range("A2", Cells(LastRow, "ZZ")).Copy
Sheets("Master").Select
Range("A9000").End(xlUp).Offset(1, 0).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Else
End If
Next Sht
End Sub
However, I now need to go one step further and merge worksheets when the columns differ from the source worksheets, into a master which has all coluns listed.
This shows the layout of the worksheets I'm testing with, to keep things simple.
I'm open to either mapping all source to destination columns (e.g.
-Source1, Column A to Master, Column A
-Source2, Column B to Master, Column D
-Etc
Or simply recreating Master with all columns from source worksheets - which is preferable in case source worksheets change.
Cheers-
I have made some changes to your code, to make it suitable for mapping any column from master to sheet1. You have to hard code the mapping inside the code
Sub CombineData()
Dim Sht As Worksheet
Dim colname As String
Dim Lastrow As Integer, rowcount As Integer
'This If will clear Master before combining
Worksheets("Master").Range("A2:ZZ9000").ClearContents
colname = 1
For Each Sht In ActiveWorkbook.Worksheets
If Sht.Name = "Sheet2" And Sht.Range("A2").Value <> "" Then
Lastrow = Range("A9000").End(xlUp).Row
Sheets("Master").Select
rowcount = Range("A9000").End(xlUp).Row
Sht.Select
'Map the columns of sheet2 to master
Sheets("Master").Range("A" & rowcount & ":A" & rowcount + Lastrow - 2).Value = Sht.Range("A2:A" & Lastrow).Value
Sheets("Master").Range("B" & rowcount & ":B" & rowcount + Lastrow - 2).Value = Sht.Range("C2:C" & Lastrow).Value
ElseIf Sht.Name = "Sheet3" And Sht.Range("A2").Value <> "" Then
Lastrow = Range("A9000").End(xlUp).Row
Sheets("Master").Select
rowcount = Range("A9000").End(xlUp).Row
Sht.Select
'Map the columns of sheet3 to master
Sheets("Master").Range("A" & rowcount & ":A" & rowcount + Lastrow - 2).Value = Sht.Range("A2:A" & Lastrow).Value
Sheets("Master").Range("B" & rowcount & ":B" & rowcount + Lastrow - 2).Value = Sht.Range("B2:B" & Lastrow).Value
End If
Next Sht
End Sub
**************Edited********************
Sub CombineData()
Dim Sht As Worksheet
Dim colname As String
Dim Lastrow As Integer, rowcount As Integer
'This If will clear Master before combining
Worksheets("Master").Range("A2:ZZ9000").ClearContents
colname = 1
For Each Sht In ActiveWorkbook.Worksheets
If Sht.Name = "Sheet1" And Sht.Range("A2").Value <> "" Then
Sheets("Sheet1").Select
Lastrow = Range("A9000").End(xlUp).Row
Sheets("Master").Select
rowcount = Range("A9000").End(xlUp).Row + 1
Sht.Select
'Map the columns of sheet2 to master
Sheets("Master").Range("A" & rowcount & ":A" & rowcount + Lastrow - 2).Value = Sht.Range("A2:A" & Lastrow).Value
Sheets("Master").Range("B" & rowcount & ":B" & rowcount + Lastrow - 2).Value = Sht.Range("B2:B" & Lastrow).Value
Sheets("Master").Range("C" & rowcount & ":C" & rowcount + Lastrow - 2).Value = Sht.Range("C2:C" & Lastrow).Value
Sheets("Master").Range("D" & rowcount & ":D" & rowcount + Lastrow - 2).Value = Sht.Range("D2:D" & Lastrow).Value
ElseIf Sht.Name = "Sheet2" And Sht.Range("A2").Value <> "" Then
Sheets("Sheet2").Select
Lastrow = Range("A9000").End(xlUp).Row
Sheets("Master").Select
rowcount = Range("A9000").End(xlUp).Row + 1
Sht.Select
'Map the columns of sheet3 to master
Sheets("Master").Range("A" & rowcount & ":A" & rowcount + Lastrow - 2).Value = Sht.Range("A2:A" & Lastrow).Value
Sheets("Master").Range("E" & rowcount & ":E" & rowcount + Lastrow - 2).Value = Sht.Range("B2:B" & Lastrow).Value
Sheets("Master").Range("F" & rowcount & ":F" & rowcount + Lastrow - 2).Value = Sht.Range("C2:C" & Lastrow).Value
Sheets("Master").Range("G" & rowcount & ":G" & rowcount + Lastrow - 2).Value = Sht.Range("D2:D" & Lastrow).Value
Sheets("Master").Range("C" & rowcount & ":C" & rowcount + Lastrow - 2).Value = Sht.Range("E2:E" & Lastrow).Value
End If
Next Sht
End Sub

copy lastrow of masterfile to multiple created worksheets then perform a Subtotal formula in a column lastrow

I have a master file which is (JV501) where I filter through column AB (currency) then copy those to createdsheets, my problem now is the lastrow from master file which I need to include to every created worksheets since it starts in column R and from there under column AD (which is all null) lastrow is where I shall perform a subtotal of AC2 up to lastrow so the subtotal shall inline with the lastrow copied.
Option Explicit
Sub SortCurrency()
Dim currRng As Range, dataRng As Range, currCell As Range
Dim LastCol As Long, lastRow As Long, lastrow2 As Long, TheLastRow As Long
Call DeleteSheets
With Worksheets("JV501")
Set currRng = .Range("AB1", .Cells(.Rows.Count, "AB").End(xlUp))
Set dataRng = Intersect(.UsedRange, currRng.EntireRow)
LastCol = Range("A1").End(xlToRight).Column
TheLastRow = Range("A1").End(xlDown).Row
lastRow = Range("AB2").End(xlDown).Row
Range("AB2:AB" & lastRow).sort key1:=Range("AB2" & lastRow), _
order1:=xlAscending, Header:=xlNo
Range("AF:XFD").EntireColumn.Delete
With .UsedRange
With .Resize(1, 1).Offset(, .Columns.Count)
With .Resize(currRng.Rows.Count)
.Value = currRng.Value
.RemoveDuplicates Array(1), Header:=xlYes
For Each currCell In .SpecialCells(xlCellTypeConstants)
currRng.AutoFilter field:=1, Criteria1:=currCell.Value
If Application.WorksheetFunction.Subtotal(103, currRng) - 1 > 0 Then
dataRng.SpecialCells(xlCellTypeVisible).Copy Destination:=GetOrCreateWorksheet(currCell.Value).Range("A1")
Range("J:Q").EntireColumn.Delete
Range("A:A").EntireColumn.Delete
Columns("A:AE").Select
Selection.EntireColumn.AutoFit
End If
Next currCell
.ClearContents
End With
End With
End With
.AutoFilterMode = False
End With
Call checklist
End Sub
Function GetOrCreateWorksheet(shtName As String) As Worksheet
On Error Resume Next
Set GetOrCreateWorksheet = Worksheets(shtName)
If GetOrCreateWorksheet Is Nothing Then
Set GetOrCreateWorksheet = Worksheets.Add(After:=Sheets(Sheets.Count))
GetOrCreateWorksheet.Name = shtName
End If
End Function
this is my code so far. I'm confused if how I shall do this.
Every help is appreciated!
In trying to compute for a a column range i've come up and got it working by adding this in my loop in creating sheets.
'subtotal of debit
lastrowSrc = Range("AC" & Rows.Count).End(xlUp).Row + 1
Range("AC" & lastrowSrc & ":AC" & lastrowSrc).Formula = "=SUBTOTAL(9,AC2:AC" & lastrowSrc - 1 & ")"
'copy ac to ad
Range("AC" & lastrowSrc & ":AC" & lastrowSrc).Cut Destination:=Range("AC" & lastrowSrc).Offset(0, 1)
in column AC is where I will compute the subtotal of debit then copy it to another column which is AD which is null I've pasted it by column AC then offset
For copying the columns not included in criteria of extracting I've done it one by one
dim internalS as long, 'and so on
internalR = Range("R" & Rows.Count).End(xlUp).Row + 1
copyR.Copy Destination:=Range("R" & internalR)
internalS = Range("S" & Rows.Count).End(xlUp).Row + 1
copyS.Copy Destination:=Range("S" & internalS)
internalT = Range("T" & Rows.Count).End(xlUp).Row + 1
copyT.Copy Destination:=Range("T" & internalT)
internalU = Range("U" & Rows.Count).End(xlUp).Row + 1
copyU.Copy Destination:=Range("U" & internalU)
internalV = Range("V" & Rows.Count).End(xlUp).Row + 1
copyV.Copy Destination:=Range("V" & internalV)
internalW = Range("W" & Rows.Count).End(xlUp).Row + 1
copyW.Copy Destination:=Range("W" & internalW)
internalX = Range("X" & Rows.Count).End(xlUp).Row + 1
copyX.Copy Destination:=Range("X" & internalX)
internalY = Range("Y" & Rows.Count).End(xlUp).Row + 1
copyY.Copy Destination:=Range("Y" & internalY)
internalZ = Range("Z" & Rows.Count).End(xlUp).Row + 1
copyZ.Copy Destination:=Range("Z" & internalZ)
internalAE = Range("AE" & Rows.Count).End(xlUp).Row + 1
copyAE.Copy Destination:=Range("AE" & internalAE)
also inserted this in my loop in creating new worksheets

How to sum values in variable range in VBA?

I have a table as shown below.
In column C I would like to Sum values from column A if they have the same index (column B). I would like to put sum result for all the rows if they have same index (as shown in column D).
Unfortunately the range of values with same index is variable and my macro can sum values just with 2 indexes. Can anyone help with it, please? Thanks!
Sub example()
Dim ws As Worksheet
Dim LastRow As Long
Dim n, i As Integer
Set ws = ActiveWorkbook.Sheets("Sheet2")
ws.Select
LastRow = Sheets("Sheet2").Range("A" & Sheets("Sheet2").Rows.Count).End(xlUp).Row
Range("C3:C" & LastRow).Select
Selection.ClearContents
For i = 3 To LastRow
If Range("B" & i + 1) - Range("B" & i) = 0 Then
Range("C" & i) = Range("A" & i + 1) + Range("A" & i)
Else
Range("C" & i) = Range("C" & i - 1)
End If
Next i
End Sub
Here's one way:
Sub example()
Dim ws As Worksheet
Dim LastRow As Long
Set ws = ActiveWorkbook.Sheets("Sheet2")
LastRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
With ws.Range("C3:C" & LastRow)
.ClearContents
.Value = ws.Evaluate("INDEX(SUMIF(B3:B" & LastRow & ",B3:B" & LastRow & ",A3:A" & LastRow & "),)")
End With
End Sub

How to create excel VBA change log

I am trying to write a change log for excel VBA. I want it to iterate through so that the each additional response is populated in the workbook as the additional rows. Please let me know if you have any insight into what is wrong with my code
Dim streply As String
Dim Today As Date
Dim myrange As Range
Dim inglastrow As Long
CurrentDate = Date
With Sheets("Sheet1")
lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
nextrow = lastrow + 1
MsgBox lastrow
MsgBox nextrow
End With
MsgBox lastrow
streply = InputBox(Prompt:="Please type description of changes", Title:="Change Log", Default:="Brief Desc.")
If streply <> " " Then
Range("A" & nextrow).Value = Application.UserName
Range("B" & nextrow).Value = streply
Range("C" & nextrow).Value = ActiveWorkbook.Name
Range("D" & nextrow).Value = Date
End If
Set lastrow = Nothing
Set nextrow = Nothing
End Sub
EDIT: silly mistake on my part, fixed now
Instead of:
lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
Try:
lastrow = .UsedRange.Rows.Count