Consolidate Master sheet with specific columns - vba

I need a VBA code that can select common columns from different worksheet and paste the same in the summary sheet.
For example, consider am having 3 sheets in a work book.
Sheet1 has column IP,Tag,Host,service
Sheet2 has column IP,Tag,REASON,source
Sheet3 has column IP,Tag,protocol,port.
I need to fetch the common columns(IP,Tag) in a summary sheet one after another.
Can anyone please help me on this.
Note: The Common columns will not be always in the same (A and B cell range) it may vary as of reports.
Dim myInSht As Worksheet
Dim myOutSht As Worksheet
Dim aRow As Range
Dim aCol As Range
Dim myInCol As Range
Dim myOutCol As Range
Dim cell As Range
Dim iLoop As Long, jLoop As Long
jLoop = 2
' loop through the worksheets
For Each myInSht In ActiveWorkbook.Worksheets
' pick only the worksheets of interest
If myInSht.Name = "PrjA" Or myInSht.Name = "PrjB" Or myInSht.Name = "PrjC" Then
' find the columns of interest in the worksheet
For Each aCol In myInSht.UsedRange.Columns
Set myOutCol = Nothing
If aCol.Cells(1, 1).Value = "ip" Then Set myOutCol = Sheets("Consolidated").Range("A:A")
If aCol.Cells(1, 1).Value = "protocol" Then Set myOutCol = Sheets("Consolidated").Range("B:B")
If aCol.Cells(1, 1).Value = "port" Then Set myOutCol = Sheets("Consolidated").Range("C:C")
If aCol.Cells(1, 1).Value = "hostname" Then Set myOutCol = Sheets("Consolidated").Range("D:D")
If aCol.Cells(1, 1).Value = "tag" Then Set myOutCol = Sheets("Consolidated").Range("E:E")
If Not myOutCol Is Nothing Then
' don't move the top line, it contains the headers - no data
Set myInCol = aCol
Set myInCol = myInCol.Offset(1, 0).Resize(myInCol.Rows.Count - 1, myInCol.Columns.Count)
' transfer data from the project tab to the consolidated tab
iLoop = jLoop
For Each aRow In myInCol.Rows
myOutCol.Cells(iLoop, 1).Value = aRow.Cells(1, 1).Value
iLoop = iLoop + 1
Next aRow
End If
Next aCol
End If
If iLoop > jLoop Then jLoop = iLoop
Next myInSht

Try this.
Sub Consolidate()
Dim FindCol As String
L1 = Sheets(1).Range("XFD2").End(xlToLeft).Column
FindCol = InputBox("Type in header of Column to be searched")
For k = 2 To Sheets.Count
Sheets(k).Select
l = Range("XFD1").End(xlToLeft).Column
For i = 1 To l
x = Range("A65536").End(xlUp).Row
If Cells(1, i).Value = FindCol Then
Range(Cells(1, i), Cells(x, i)).Copy
Sheets(1).Activate
L2 = Range("XFD1").End(xlToLeft).Column
Sheets(1).Cells(1, L2 + 1).Select
ActiveSheet.Paste
End If
Next
Next
Sheets(1).Activate
End Sub

a somewhat general approach could be the following:
Option Explicit
Sub Collect()
Dim sheetsNames As Variant, sharedColumns As Variant
Dim sheetName As Variant, sharedColumn As Variant
Dim summarySheet As Worksheet
sheetsNames = Array("PrjA", "PrjB", "PrjC") '<--| list your sheets names
If FindSharedColumns(sheetsNames, sharedColumns) Then '<--| if any shared columns between ALL listed sheets
Set summarySheet = GetOrCreateSheet("Consolidated") '<--| set or create "Consolidated" sheet: if already there it'll be cleared
With summarySheet
.Range("A1").Resize(, UBound(sharedColumns) + 1).Value = sharedColumns '<--| write headers as the names found in first cell of "shared" columns
End With
For Each sheetName In sheetsNames '<--| loop through sheets ALL sharing the same columns
With Worksheets(sheetName) '<--| reference current sheet in loop
For Each sharedColumn In sharedColumns '<--| loop through shared columns names
With .Rows(1).SpecialCells(xlCellTypeConstants, xlTextValues).Find(what:=sharedColumn, LookIn:=xlValues, lookat:=xlWhole).EntireColumn '<--| reference column corresponding to current shared column in current sheet
With .Resize(WorksheetFunction.CountA(.cells) - 1).Offset(1) '<--| reference its cells from row 2 down to last not empty one (WARNING: it's assumed there are not blank cells in between)
summarySheet.Rows(1).SpecialCells(xlCellTypeConstants, xlTextValues).Find(what:=sharedColumn, LookIn:=xlValues, lookat:=xlWhole).End(xlDown).End(xlDown).End(xlUp).Offset(1).Resize(.Rows.Count).Value = .Value '<--| update 'summarySheet' appending current values at the bottom of its corresponding column
End With
End With
Next
End With
Next
End If
End Sub
Function GetOrCreateSheet(shtName As String) As Worksheet
If Not GetSheet(shtName, GetOrCreateSheet) Then
Set GetOrCreateSheet = Worksheets.Add(after:=Worksheets(Worksheets.Count))
GetOrCreateSheet.Name = shtName
Else
GetOrCreateSheet.UsedRange.ClearContents
End If
End Function
Function GetSheet(sheetName As Variant, sht As Worksheet) As Boolean
On Error Resume Next
Set sht = Worksheets(sheetName)
GetSheet = Not sht Is Nothing
End Function
Function FindSharedColumns(sheetsNames As Variant, sharedColumns As Variant) As Boolean
Dim sheetName As Variant
Dim sht As Worksheet
Dim col As Range
Dim key As Variant
With CreateObject("Scripting.Dictionary")
For Each sheetName In sheetsNames
If GetSheet(sheetName, sht) Then
For Each col In sht.Rows(1).SpecialCells(xlCellTypeConstants, xlTextValues)
.Item(col.Value) = .Item(col.Value) + 1
Next
End If
Next
For Each key In .keys
If .Item(key) < UBound(sheetsNames) + 1 Then .Remove key
Next
If .Count > 0 Then
sharedColumns = .keys
FindSharedColumns = True
End If
End With
End Function
if sheets names differs every time then you have to loop through all worksheets
the changes in the above code are minimal, here's the complete code
Option Explicit
Sub Collect()
Dim sheetsNames As Variant, sharedColumns As Variant
Dim sht As Worksheet, sharedColumn As Variant
Dim summarySheet As Worksheet
If FindSharedColumns(sharedColumns) Then '<--| if any shared columns between ALL worksheets
Set summarySheet = GetOrCreateSheet("Consolidated") '<--| set or create "Consolidated" sheet: if already there it'll be cleared
With summarySheet
.Range("A1").Resize(, UBound(sharedColumns) + 1).Value = sharedColumns '<--| write headers as the names found in first cell of "shared" columns
End With
For Each sht In Worksheets '<--| loop through all worksheets
With sht '<--| reference current sheet in loop
For Each sharedColumn In sharedColumns '<--| loop through shared columns names
With .Rows(1).SpecialCells(xlCellTypeConstants, xlTextValues).Find(what:=sharedColumn, LookIn:=xlValues, lookat:=xlWhole).EntireColumn '<--| reference column corresponding to current shared column in current sheet
With .Resize(WorksheetFunction.CountA(.cells) - 1).Offset(1) '<--| reference its cells from row 2 down to last not empty one (WARNING: it's assumed there are not blank cells in between)
summarySheet.Rows(1).SpecialCells(xlCellTypeConstants, xlTextValues).Find(what:=sharedColumn, LookIn:=xlValues, lookat:=xlWhole).End(xlDown).End(xlDown).End(xlUp).Offset(1).Resize(.Rows.Count).Value = .Value '<--| update 'summarySheet' appending current values at the bottom of its corresponding column
End With
End With
Next
End With
Next
End If
End Sub
Function GetOrCreateSheet(shtName As String) As Worksheet
If Not GetSheet(shtName, GetOrCreateSheet) Then
Set GetOrCreateSheet = Worksheets.Add(after:=Worksheets(Worksheets.Count))
GetOrCreateSheet.Name = shtName
Else
GetOrCreateSheet.UsedRange.ClearContents
End If
End Function
Function GetSheet(sheetName As Variant, sht As Worksheet) As Boolean
On Error Resume Next
Set sht = Worksheets(sheetName)
GetSheet = Not sht Is Nothing
End Function
Function FindSharedColumns(sharedColumns As Variant) As Boolean
Dim sheetName As Variant
Dim sht As Worksheet
Dim col As Range
Dim key As Variant
With CreateObject("Scripting.Dictionary")
For Each sht In Worksheets
For Each col In sht.Rows(1).SpecialCells(xlCellTypeConstants, xlTextValues)
.Item(col.Value) = .Item(col.Value) + 1
Next
Next
For Each key In .keys
If .Item(key) < Worksheets.Count Then .Remove key
Next
If .Count > 0 Then
sharedColumns = .keys
FindSharedColumns = True
End If
End With
End Function

The below code works well the requirement
Sub Collect()
Dim myInSht As Worksheet
Dim myOutSht As Worksheet
Dim aRow As Range
Dim aCol As Range
Dim myInCol As Range
Dim myOutCol As Range
Dim calcState As Long
Dim scrUpdateState As Long
Dim cell As Range
Dim iLoop As Long, jLoop As Long
jLoop = 2
' loop through the worksheets
For Each myInSht In ActiveWorkbook.Worksheets
' pick only the worksheets of interest
'If myInSht.Name = "a" Or myInSht.Name = "aa" Or myInSht.Name = "aaa" Then
' find the columns of interest in the worksheet
For Each aCol In myInSht.UsedRange.Columns
Set myOutCol = Nothing
If aCol.Cells(1, 1).Value = "timestamp" Then Set myOutCol = Sheets("Summary").Range("B2:B1000")
If aCol.Cells(1, 1).Value = "ip" Then Set myOutCol = Sheets("Summary").Range("C2:C1000")
If aCol.Cells(1, 1).Value = "protocol" Then Set myOutCol = Sheets("Summary").Range("D2:D1000")
If aCol.Cells(1, 1).Value = "port" Then Set myOutCol = Sheets("Summary").Range("E2:E1000")
If aCol.Cells(1, 1).Value = "hostname" Then Set myOutCol = Sheets("Summary").Range("F2:F1000")
If aCol.Cells(1, 1).Value = "tag" Then Set myOutCol = Sheets("Summary").Range("G2:G1000")
If aCol.Cells(1, 1).Value = "asn" Then Set myOutCol = Sheets("Summary").Range("I2:I1000")
If aCol.Cells(1, 1).Value = "geo" Then Set myOutCol = Sheets("Summary").Range("J2:J1000")
If aCol.Cells(1, 1).Value = "region" Then Set myOutCol = Sheets("Summary").Range("K2:K1000")
If aCol.Cells(1, 1).Value = "naics" Then Set myOutCol = Sheets("Summary").Range("L2:L1000")
If aCol.Cells(1, 1).Value = "sic" Then Set myOutCol = Sheets("Summary").Range("M2:M1000")
If aCol.Cells(1, 1).Value = "server_name" Then Set myOutCol = Sheets("Summary").Range("H2:H1000")
If Not myOutCol Is Nothing Then
' don't move the top line, it contains the headers - no data
Set myInCol = aCol
Set myInCol = myInCol.Offset(1, 0).Resize(myInCol.Rows.Count, myInCol.Columns.Count)
' transfer data from the project tab to the consolidated tab
iLoop = jLoop
For Each aRow In myInCol.Rows
myOutCol.Cells(iLoop, 1).Value = aRow.Cells(1, 1).Value
iLoop = iLoop + 1
Next aRow
End If
Next aCol
'End If
If iLoop > jLoop Then jLoop = iLoop
Next myInSht
End Sub

Related

Trying to Copy column and paste into another sheet based on another cells value VBA

I am trying to copy the content of a column only if another cell equals "Yes". If the cell equals "Yes", I want to paste the selected columns range into another workbook. Then loop to the next "Yes".
If M2 = "Yes" then copy AD2:AD200 if "NO" go to the next "if"
If M3 = "Yes" then copy AE2:AE200 if "NO" go to the next "if"
If M4 = "Yes" then copy AF2:AF200 if "NO" go to the next "if"
and so on....
The last one i will look for is M11.
Then paste the copy range to last blank cell in sheet "Cases in QA Status",
range("AL200",range("al200").end(xlUp).select
This is what I have so far:
Sheets("Sheet1").Select
If Range("M8").Value = True Then
Range("aj2:aj200").Select
Selection.Copy
Sheets("Cases in QA Status").Select
End If
End Sub
Can you try the following?
If Sheets("Sheet1").Range("M8").Value = True Then
Sheets("Sheet1").Range("aj2:aj200").Copy
ActiveSheet.Paste Destination:=Sheets("Cases in QA Status").Range("A1")
End If
And repeat for other columns :).
Naturally if you have "Yes" in the column, then replace True with "Yes".
1. Copy Method
Sub test()
Dim Ws As Worksheet, toWs As Worksheet
Dim vDB As Variant, rngDB As Range
Dim Target As Range
Dim i As Long
Set Ws = Sheets("Sheet1")
Set toWs = Sheets("Cases in QA Status")
With Ws
vDB = .Range("m2", .Range("m" & Rows.Count).End(xlUp))
End With
For i = 1 To UBound(vDB, 1)
If vDB(i, 1) = "Yes" Then 'vDB(i, 1) = True then
Set rngDB = Ws.Range("ad2").Resize(199).Offset(, i - 1)
Set Target = toWs.Range("al" & Rows.Count).End(xlUp).Offset(1, 0)
rngDB.Copy Target
End If
Next i
End Sub
2. Using Array
Sub test2()
Dim Ws As Worksheet, toWs As Worksheet
Dim vDB As Variant, vData As Variant
Dim Target As Range
Dim i As Long
Set Ws = Sheets("Sheet1")
Set toWs = Sheets("Cases in QA Status")
With Ws
vDB = .Range("m2", .Range("m" & Rows.Count).End(xlUp))
End With
For i = 1 To UBound(vDB, 1)
If vDB(i, 1) = "Yes" Then 'vDB(i, 1) = True then
vData = Ws.Range("ad2").Resize(199).Offset(, i - 1)
Set Target = toWs.Range("al" & Rows.Count).End(xlUp).Offset(1, 0)
Target.Resize(199) = vData
End If
Next i
End Sub

Adding Unique Sheets From Range Values

I am attempting to write code that runs through column G, and adds a new sheet for every unique value with out creating duplicates; However from what I have so so it creates duplicates
Public Sub AddSheet()
Worksheets("Dataset").Select
Range("A1", Range("A1").End(xlToRight)).Name = "Title"
Range("A2", Range("G1").End(xlDown)).Name = "Data"
Range("H2", Range("H1").End(xlDown)).Name = "Physician"
Dim i As Integer, lastrow As Integer
lastrow = Worksheets("Dataset").Cells(Worksheets("Dataset").Rows.Count, "H").End(xlUp).Row
With Range("Physician")
For i = 1 To lastrow
If i.Value = Worksheetexists = False Then
Sheet.Add
ActiveSheet.Name = Worksheets("Dataset").Cells(i, 1).Value
Else
GoTo NextStep:
End If
Next
End With
End Sub
something like this will iterate and create a new sheet for every unique value in Column A.
Public Sub AddSheet()
With Worksheets("Dataset")
Dim lastrow As Long
lastrow = .Cells(.Rows.Count, "H").End(xlUp).Row
Dim i As Long
For i = 1 To lastrow
If IsError(Application.Evaluate("'" & .Cells(i, 1).Value & "'!A1")) And .Cells(i, 1) <> "" Then
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets.Add
ws.Name = .Cells(i, 1).Value
End If
Next i
End With
End Sub
Something like this should work and be a bit safer as you may need to check the edge case that a sheet you are adding already exists. I'm using a dictionary to keep track of unique sheet names first, then adding to that based on the unique values in column H.
Sub SOExample()
Dim DataSheet As Excel.Worksheet
Dim ws As Excel.Worksheet
Dim lastRow As Long
Dim i As Long
Dim dict As Object
Dim SheetName As String
Set dict = CreateObject("Scripting.Dictionary")
Set DataSheet = ThisWorkbook.Worksheets("Dataset")
lastRow = DataSheet.Cells(DataSheet.Rows.Count, "H").End(xlUp).Row
'Add existing sheets into the dictionary first
'in case a sheet already exists with that name
For Each ws In ThisWorkbook.Worksheets
dict.Add ws.Name, ws.Name
Next
'Loop the range and add new sheets
For i = 1 To lastRow
SheetName = DataSheet.Cells(i, 8).Value 'Column H is index 8
If Not dict.exists(SheetName) Then
dict.Add SheetName, SheetName
Set ws = ThisWorkbook.Worksheets.Add
ws.Name = SheetName
End If
Next
End Sub

vba code to paste value in open workbooks which have similar name to a range value

I got stuck in the below-mentioned code, what I want to do is to get the value from Range("C4:C" & LastRow) in worksheets X2 that will b changing every time and compare each value with all open workbooks name. If match found then search that value in A column of worksheet X1 and copy all those rows.
The final objective is to paste those rows into those open workbooks which have the same value. For eg: Range C4 has TW00 then the code will search workbooks which have name "TW00.xlsx" and copy all the rows from worksheet X1 which have TW00 value in column A in the worksheet named TW00.xlsx.
Dim BookNames()
ReDim BookNames(Windows.Count)
n = 1
For n = 1 To Windows.Count
BookNames(n) = Workbooks(n).Name
If Workbooks(n).Name = Workbooks("A.xlsx").Worksheets("X2").Range("C4:C" & LastRow).Value Then
Set Rng = Workbooks("A.xlsx").Worksheets("X1").Range("A2:A50000")
For Each c In Rng.Cells
If c.Value = Workbooks("A.xlsx").Worksheets("X2").Range("C4").Value Then
If Not CopyRng Is Nothing Then
Set CopyRng = Application.Union(CopyRng,
Workbooks("A.xlsx").Worksheets("X1").Rows(c))
Else
Set CopyRng = Workbooks("A.xlsx").Worksheets("X1").Rows(c)
End If
End If
Next c
CopyRng.Copy
Workbooks(n).Activate
Worksheets.Add
ActiveSheet.Name = "X1"
ActiveSheet.Paste
End If
Next n
is that code help you?
Sub test()
Dim lastRow As Long
dim sheetName as string
Dim sourceDataSheet As worksheet
Dim sourceSheetsName as worksheet
dim targetDataSheet as worksheet
Dim wkb As Variant
set sourceDataSheet = ActiveWorkbook.Worksheets("X2")
set sourceSheetsName = ActiveWorkbook.Worksheets("X1")
With sourceSheetsName
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
sheetName = .Cells(lastRow, "A")
For Each wkb In Application.Workbooks
If wkb.Name <> .Name And wkb.Name = sheetName Then
set targetDataSheet = wkb.Worksheets.Add
with sourceDataSheet
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
for i = 1 to lastRow
if .Cells(i, "A").Value = sheetName then
.Cells(i, "A").EntireRow.Copy
targetDataSheet.Cells(i, "A").PasteSpecial Paste:=xlPasteValues
end if
next i
end with
End If
Next wkb
End With
End Sub

Hyperlink cell to the source Sheet

I've below code which will create a consolidated sheet. I need a cell value to be hyperlinked that can route to the source sheet. Please find the below code.
Sub Collect()
Dim myInSht As Worksheet
Dim myOutSht As Worksheet
Dim aRow As Range
Dim aCol As Range
Dim myInCol As Range
Dim myOutCol As Range
Dim calcState As Long
Dim scrUpdateState As Long
Dim cell As Range
Dim iLoop As Long, jLoop As Long
jLoop = 2
' loop through the worksheets
For Each myInSht In ActiveWorkbook.Worksheets
' pick only the worksheets of interest
'If myInSht.Name = "a" Or myInSht.Name = "aa" Or myInSht.Name = "aaa" Then
' find the columns of interest in the worksheet
For Each aCol In myInSht.UsedRange.Columns
Set myOutCol = Nothing
If aCol.Cells(1, 1).Value = "timestamp" Then Set myOutCol = Sheets("Summary").Range("B2:B1000")
If aCol.Cells(1, 1).Value = "ip" Then Set myOutCol = Sheets("Summary").Range("C2:C1000")
If aCol.Cells(1, 1).Value = "protocol" Then Set myOutCol = Sheets("Summary").Range("D2:D1000")
If aCol.Cells(1, 1).Value = "port" Then Set myOutCol = Sheets("Summary").Range("E2:E1000")
If aCol.Cells(1, 1).Value = "hostname" Then Set myOutCol = Sheets("Summary").Range("F2:F1000")
If aCol.Cells(1, 1).Value = "tag" Then Set myOutCol = Sheets("Summary").Range("G2:G1000")
If aCol.Cells(1, 1).Value = "asn" Then Set myOutCol = Sheets("Summary").Range("I2:I1000")
If aCol.Cells(1, 1).Value = "geo" Then Set myOutCol = Sheets("Summary").Range("J2:J1000")
If aCol.Cells(1, 1).Value = "region" Then Set myOutCol = Sheets("Summary").Range("K2:K1000")
If aCol.Cells(1, 1).Value = "naics" Then Set myOutCol = Sheets("Summary").Range("L2:L1000")
If aCol.Cells(1, 1).Value = "sic" Then Set myOutCol = Sheets("Summary").Range("M2:M1000")
If aCol.Cells(1, 1).Value = "server_name" Then Set myOutCol = Sheets("Summary").Range("H2:H1000")
If Not myOutCol Is Nothing Then
' don't move the top line, it contains the headers - no data
Set myInCol = aCol
Set myInCol = myInCol.Offset(1, 0).Resize(myInCol.Rows.Count, myInCol.Columns.Count)
' transfer data from the project tab to the consolidated tab
iLoop = jLoop
For Each aRow In myInCol.Rows
myOutCol.Cells(iLoop, 1).Value = aRow.Cells(1, 1).Value
iLoop = iLoop + 1
Next aRow
End If
Next aCol
'End If
If iLoop > jLoop Then jLoop = iLoop
Next myInSht
End Sub
I would like to create a hyperlink cells on column tag. so i click it should take me to the source sheet from the summary sheet.
I'm rusty with hyperlinks so this is a bit clunky looking, but the code below should point you in the right direction.
If Not MyOutCol Is Nothing Then
' don't move the top line, it contains the headers - no data
Set MyInCol = aCol
Set MyInCol = MyInCol.Offset(1, 0).Resize(MyInCol.Rows.Count, MyInCol.Columns.Count)
' transfer data from the project tab to the consolidated tab
iLoop = jLoop
For Each aRow In MyInCol.Rows
MyOutCol.Cells(iLoop, 1).Value = aRow.Cells(1, 1).Value
iLoop = iLoop + 1
Next aRow
MyOutCol.Parent.Hyperlinks.Add _
Anchor:=MyOutCol.Cells(jLoop, 1), _
Address:="", _
SubAddress:=MyInCol.Parent.Name & "!" & MyInCol.Address, _
TextToDisplay:=MyInCol.Cells(1, 1).Value
End If
Edits: replaced aCol with MyIncol, changed 1 to jLoop, moved hyperlink code to after range has been populated
You could use this
Sub LinkToSheet()
Dim SheetName As String
Sheets(SheetName).Select
EndSub
and then insert a button or a link to run this Sub. Of course you have to parametrize the value of "SheetName".

Dynamic Sheet naming and copying data

I have been a silent reader on here for a few months but have been struggling with this code for a week now, so thought i would see if anyone can help.
I have a worksheet where sheet 1 contains information for users to input data.
Column A ask a question, column C is where the user will type in an answer.
Row 4 asks how many configurations there will be. depending on what number they input depends on how many cells light up to the right ie if 1 then D4 goes yellow, if 2 then D4 and E4 go yellow (using conditional formatting)
The user will then enter the title into the highlighted cell (D4,E4 ,F4 etc)
I want to create a new sheet at the end of the sheet for each configuration.
then NAME the new sheet by the text entered in D4, E4 etc.
the code I have so far is:
Option Explicit
Sub InsertSupplierSheet()
Dim ws As Worksheet
Dim tmpSht As Worksheet
Dim Lastcol As Integer, i As Integer, j As Integer
Dim DESCRANGE As Range
'~~> Change Sheet1 to the sheet which has all the data
Set ws = ThisWorkbook.Worksheets(1)
With ws
Lastcol = ActiveSheet.Cells(4, Columns.Count).End(xlToLeft).Column
If Lastcol < 4 Then Exit Sub
For i = 3 To Lastcol
If DoesSheetExist(ActiveSheet.Cells(4 & i).Value) Then
Set tmpSht = ActiveSheet.Cells(4 & i).Value
Else
Sheets.Add After:=Sheets(Sheets.Count)
Set tmpSht = ActiveSheet
tmpSht.Name = "NEWSHEET"
End If
.Rows("1:3").Copy tmpSht.Rows(1)
For j = 1 To 4
tmpSht.Columns(j).ColumnWidth = .Columns(j).ColumnWidth
Next j
.Rows(i).Copy tmpSht.Rows(4)
Next
End With
End Sub
Function DoesSheetExist(Sht As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = Sheets(ws)
On Error GoTo 0
If Not ws Is Nothing Then DoesSheetExist = True
End Function
I put in "NEWSHEET" to see if even creates a new sheet, but it still fails. I just cant see where I am going wrong.
Any help /advise is welcomed.
EDIT .
I cant work out why though.
The last col will be H4 so lastcol would be "8" .
Then for i = 4 to 8 run the loop. there are descriptions in each of the cells in row 4 so i don't see why it would work for 2 instantness and then fail ?
I dont know if this would make it easier but I have the number of sheets i want to create in cell C4 so i could use this rather than looking up populated cells. so if C4 is 2 then I want to add 2 sheets named as the content of D4, E4. if C4 is 3 then I want to add 3 sheets names as content of D3,E3,F3. Am I making this harder than I need too ?
UPDATE
I figured out the copying over of info is affecting this loop. and amended the code to this.
Sub InsertSupplierSheet()
Dim ws As Worksheet
Dim tmpSht As Worksheet
Dim Lastcol As Integer, i As Integer, j As Integer
Dim DESCRANGE As Range
Dim sShtName As String 'Dimension sheet name variable
'~~> Change Sheet1 to the sheet which has all the data
Set ws = ThisWorkbook.Worksheets(1)
With ws
Lastcol = ActiveSheet.Cells(4, Columns.Count).End(xlToLeft).Column
If Lastcol < 4 Then Exit Sub
For i = 4 To Lastcol
sShtName = ActiveSheet.Cells(4, i).Value2 'Set sShtName to cell value within loop
If DoesSheetExist(sShtName) Then 'Use sShtName to call "Exists" function
Set tmpSht = Sheets(sShtName)
Else
Sheets.Add After:=Sheets(Sheets.Count)
Set tmpSht = ActiveSheet
tmpSht.Name = sShtName 'Change name to sShtName
End If
.Rows("1:3").Copy tmpSht.Rows(1)
.Rows(13).Copy tmpSht.Rows(4)
Next
End With
End Sub
Function DoesSheetExist(Sht As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = Sheets(Sht)
On Error GoTo 0
If Not ws Is Nothing Then DoesSheetExist = True
End Function
this is doing what i want it to do with a couple of small exceptions.
the Sheets are being named by the cells in D1 , then E13,F13,G13,H13 So i need to figure out where that info is coming from.
the final bit is that due to my conditional formatting in the First sheet, I am getting text on black backgrounds in the copy cells, but that is the very least of my worries !
UPDATE
Found the error -
sShtName = ActiveSheet.Cells(4, i).Value2
should be
sShtName = Worksheets(1).Cells(4, i).Value2
You are calling your cells incorrectly. Use (4, i) instead of (4 & i).
The way you were calling it concatenated it to 43, which resulted in you checking cell AQ1 (AQ being the 43rd column) for the sheet reference.
Edit: I just walked through it a bit and found a couple of other errors. You need to set the sheet name to sht in your 'exists' function, and I'm assuming you want to set tmpSht to a sheet, so you need to encase it in sheets(). Try this:
Sub InsertSupplierSheet()
Dim ws As Worksheet
Dim tmpSht As Worksheet
Dim Lastcol As Integer, i As Integer, j As Integer
Dim DESCRANGE As Range
Dim sShtName As String 'Dimension sheet name variable
'~~> Change Sheet1 to the sheet which has all the data
Set ws = ThisWorkbook.Worksheets(1)
With ws
Lastcol = ActiveSheet.Cells(4, Columns.Count).End(xlToLeft).Column
If Lastcol < 4 Then Exit Sub
For i = 4 To Lastcol
sShtName = ActiveSheet.Cells(4, i).Value2 'Set sShtName to cell value within loop
If DoesSheetExist(sShtName) Then 'Use sShtName to call "Exists" function
Set tmpSht = Sheets(sShtName)
Else
Sheets.Add After:=Sheets(Sheets.Count)
Set tmpSht = ActiveSheet
tmpSht.Name = sShtName 'Change name to sShtName
End If
.Rows("1:3").Copy tmpSht.Rows(1)
For j = 1 To 4
tmpSht.Columns(j).ColumnWidth = .Columns(j).ColumnWidth
Next j
.Rows(i).Copy tmpSht.Rows(4)
Next
End With
End Sub
Function DoesSheetExist(Sht As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = Sheets(Sht)
On Error GoTo 0
If Not ws Is Nothing Then DoesSheetExist = True
End Function
Instead of adding the new sheet and then setting the activesheet to the tmpsht you could use a shorter way (see below). And why did you set the ws if you don't use it....
Sub InsertSupplierSheet()
Dim ws As Worksheet
Dim tmpSht As Worksheet
Dim Lastcol As Integer, i As Integer, j As Integer
Dim DESCRANGE As Range
Set ws = ThisWorkbook.Worksheets(1)
With ws
Lastcol = .Cells(4, .Columns.Count).End(xlToLeft).Column
If (Lastcol < 4) Then
Exit Sub
End If
For i = 4 To Lastcol
If (DoesSheetExist(.Cells(4, i).Value2) = True) Then
Set tmpSht = Sheets(.Cells(4, i).Value)
Else
Set tmpSht = Sheets.Add After:=Sheets(Sheets.Count)
tmpSht.Name = "NEWSHEET"
End If
.Rows("1:3").Copy tmpSht.Rows(1)
For j = 1 To 4
tmpSht.Columns(j).ColumnWidth = .Columns(j).ColumnWidth
Next j
.Rows(i).Copy tmpSht.Rows(4)
Next i
End With
End Sub
Function DoesSheetExist(Sht As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = Sheets(Sht)
On Error GoTo 0
If Not ws Is Nothing Then
DoesSheetExist = True
Else
DoesSheetExist = False
End If
End Function
This was my final code. There were a few tweaks, Firstly I added a formula in row 6 to shorten the name of row 4 to a 10 character name as I found the tab names were too long (hence the code for the naming refers to row 6. I also added some custom text to add into each sheet and some formatting
Option Explicit
Sub InsertSupplierSheet()
Dim ws As Worksheet
Dim tmpSht As Worksheet
Dim Lastcol As Integer
Dim i As Integer
Dim j As Integer
Dim DESCRANGE As Range
Dim sShtName As String 'Dimension sheet name variable
'~~> Change Sheet1 to the sheet which has all the data
Set ws = ThisWorkbook.Worksheets(1)
With ws
Lastcol = ActiveSheet.Cells(4, Columns.Count).End(xlToLeft).Column ' work with the template sheet
If Lastcol = 3 Then Exit Sub 'repeat these steps from the first config to the last
For i = 4 To Lastcol
sShtName = Worksheets(1).Cells(6, i).Value2 'Set sShtName to cell value within loop
If DoesSheetExist(sShtName) Then 'Use sShtName to call "Exists" function
Set tmpSht = Sheets(sShtName)
Else
Sheets.Add After:=Sheets(Sheets.Count)
Set tmpSht = ActiveSheet
tmpSht.Name = sShtName 'Change name to sShtName tmpSht.Name = sShtName
End If
.Rows("1:3").Copy tmpSht.Rows(1) ' Format the cell width in the new sheet
.Rows(13).Copy tmpSht.Rows(4)
tmpSht.Range("A1").Value = Worksheets(1).Cells(4, i).Value2
Range("A1").ColumnWidth = 30
Range("B1").ColumnWidth = 0
Range("C1").ColumnWidth = 30
Range("D1:K1").ColumnWidth = 10
Range("D4:J4").Font.Color = vbWhite ' format the colour of the text in the new sheet
Range("C1") = " " ' Negate info in cell C1
With Range("A1:M5") ' add borders
'Clear existing
.Borders.LineStyle = xlNone
'Apply new borders
.BorderAround xlContinuous
.Borders(xlInsideHorizontal).LineStyle = xlContinuous
.Borders(xlInsideVertical).LineStyle = xlContinuous
End With
With Range("A1:C4") ' set colours for the new sheet
.Font.Color = vbBlack
.Interior.Color = vbWhite
End With
Range("D4:J4").Font.Color = vbWhite ' set colour of the numbers to white to show on black background
Range("A5") = "Unit cost in " & Worksheets(1).Cells(17, 3).Value2
Range("A6") = "CUSTOM TEXT ONE."
Range("A7") = "NOTE if quantity " & Range("D4").Value2 + 5 & " is ordered then total cost will be your unit cost for " & Range("D4").Value2 & " multiplied by " & Range("D4").Value2 + 5 & " .This applies up to the quantity of " & Range("E4").Value2 - 1
Range("A8") = "CUSTOM TEXT 2"
Next i
End With
End Sub
Function DoesSheetExist(Sht As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = Sheets(Sht)
On Error GoTo 0
If Not ws Is Nothing Then DoesSheetExist = True
End Function