I've got a code that generates a workbook by copying and moving selected worksheets into a new workbook.
The first page of this new workbook is a summary page. On this i want to pull data from the subsequent worksheets by using the range.value method.
However can I use this when referencing the worksheet location for example
Dim wb As Workbook, wbAll As Workbook
Dim ws As Worksheet
Set wbAll = Workbooks.Add
On Error Resume Next
For t = 1 To 100
Set wb = Workbooks("Book" & t)
For Each ws In wb.Sheets
ws.Move after:=wbAll.Sheets(Sheets.Count)
Next
Next
Workbooks("Book" & t).Activate
ActiveWorkbook.Sheets("Sheet1").Select
'compile worksheets into list
Dim wss As Worksheet
Dim x As Integer
On Error Resume Next
x = 17
Sheets("Sheet1").Range("c17:E46").ClearContents
For Each wss In ActiveWorkbook.Worksheets
If wss.Name <> "Sheet1" Then
Sheets("Sheet1").Cells(x, 3) = wss.Name
x = x + 1
End If
Next wss
'COMPILE COSTS
ActiveWorkbook.Sheet1.Range("C17").Value = ActiveWorkbook.Worksheet(2).Range("Q118").Value
ActiveWorkbook.Sheet1.Range("C18").Value = ActiveWorkbook.Worksheet(3).Range("Q118").Value
.
.
ActiveWorkbook.Sheet1.Range("C45").Value = ActiveWorkbook.Worksheet(30).Range("Q118").Value
ActiveWorkbook.Sheet1.Range("C46").Value = ActiveWorkbook.Worksheet(31).Range("Q118").Value
'Compile WBS
ActiveWorkbook.Sheet1.Range("D17").Value = ActiveWorkbook.Worksheet(2).Range("D10").Value
ActiveWorkbook.Sheet1.Range("D18").Value = ActiveWorkbook.Worksheet(3).Range("D10").Value
.
.
ActiveWorkbook.Sheet1.Range("D45").Value = ActiveWorkbook.Worksheet(30).Range("D10").Value
ActiveWorkbook.Sheet1.Range("D46").Value = ActiveWorkbook.Worksheet(31).Range("D10").Value
'Week Number name
ActiveWorkbook.Sheet1.Range("C10").Value = ActiveWorkbook.Worksheet(2).Range("D4").Value
'Supplier Name
ActiveWorkbook.Sheet1.Range("C12").Value = ActiveWorkbook.Worksheet(2).Range("D5").Value
This however gives me an error message of object defined error
This may help:
EDIT: updated to show using links instead of copying the values from the sheet.
Sub Tester()
Dim wb As Workbook, wbAll As Workbook
Dim ws As Worksheet
Dim wss As Worksheet
Dim x As Integer, wsSummary, t As Long
Set wbAll = Workbooks.Add
For t = 1 To 100
Set wb = Nothing
On Error Resume Next 'ignore any error
Set wb = Workbooks("Book" & t)
On Error GoTo 0 'cancel OERN as soon as possible
If Not wb Is Nothing Then
For Each ws In wb.Sheets
ws.Move after:=wbAll.Sheets(wbAll.Sheets.Count)
Next
End If
Next
'Workbooks("Book" & t).Activate 'not sure what this is for?
'ActiveWorkbook.Sheets("Sheet1").Select
'compile worksheets into list
x = 17
Set wsSummary = wbAll.Sheets("Sheet1")
wsSummary.Range("C17:E46").ClearContents
For Each wss In wbAll.Worksheets
If wss.Name <> wsSummary.Name Then
With wsSummary.Rows(x)
'.Cells(3).Value = wss.Name
InsertLink .Cells(5), wss.Range("A1"), "=SheetName({1})"
'.Cells(4).Value = wss.Range("Q118").Value
InsertLink .Cells(4), wss.Range("Q118") 'create a link
'.Cells(5).Value = wss.Range("D10").Value
InsertLink .Cells(5), wss.Range("D10")
'etc etc
End With
x = x + 1
End If
Next wss
End Sub
'UDF to return the sheet name
Function SheetName(c As Range)
Application.Volatile
SheetName = c.Parent.Name
End Function
'Insert a worksheet formula into a cell (rngDest), where the precedents
' are either a single cell/range or an array of cells/ranges (SourceRange)
' sTemplate is an optional string template for the formula
' eg. "=SUM({1},{2})" where {1} and {2} are ranges in SourceRange
' Empty template defaults to "={1}"
'Useage:
' InsertLink sht1.Range("A1"), Array(sht1.Range("B1"), sht1.Range("C1")), "=SUM({1},{2})"
Sub InsertLink(rngDest As Range, SourceRange As Variant, Optional sTemplate As String)
Dim i As Long, sAddress As String, arrTmp As Variant
If sTemplate = "" Then sTemplate = "={1}" 'default is a simple linking formula
'got a single range, or an array of ranges?
If TypeName(SourceRange) = "Range" Then
arrTmp = Array(SourceRange) 'make an array from the single range
Else
arrTmp = SourceRange 'use as-is
End If
'loop over the input range(s) and build the formula
For i = LBound(arrTmp) To UBound(arrTmp)
sAddress = ""
If rngDest.Parent.Name <> arrTmp(i).Parent.Name Then
sAddress = "'" & arrTmp(i).Parent.Name & "'!"
End If
sAddress = sAddress & arrTmp(i).Address(False, False)
sTemplate = Replace(sTemplate, "{" & CStr(i + 1) & "}", sAddress)
Next i
rngDest.Formula = sTemplate 'assign the formula
End Sub
Related
I have the situation presented below in the image (Workbook 1):
and below (Workbook 2)
I want to copy my record from workbook 1 to workbook 2 if
in the Workbook 1 column A the string "surveyor" appears
the value from column B, which is exactly in the same row, where the string "suveyor" was found.
Then I would like to copy this value to my workbook 2.
I have prepared the code like this:
Sub FrontsheetAdd3()
Dim x As Worksheet, y As Worksheet, sPath As String
Dim i As Long
sPath = ThisWorkbook.Path & "\Survey_form.csv"
Set x = Workbooks.Open(sPath)
Set y = ActiveWorkbook.Sheets("Frontsheet") 'set to current worksheet name
'Name of the sheet is the same as Name of the workbook 1
If x.Sheets("Survey_form").Range("A" & i).Value = "surveyor" Then
x.Sheets("Survey_form").Rage("B" & i).Value = ("A" & i)
y.Sheets("Frontsheet").Range("D34").PasteSpecial
End If
Next i
End Sub
I have an error:
Method or data member not found
at the line
If x.Sheets("Survey_form").Range("A" & i).Value = "surveyor" Then
UPDATE:
After changing my code, which now looks like this:
Sub FrontsheetAdd3()
Dim x As Workbook, y As Workbook, sPath As String
Dim i As Long
sPath = ThisWorkbook.Path & "\Survey_form.csv"
Set x = Workbooks.Open(sPath)
Set y = ActiveWorkbook.Sheets("Frontsheet") 'set to current worksheet name
'Name of the sheet is the same as Name of the workbook 1
For i = 1 To 40
If x.Sheets("Survey_form").Range("A" & i).Value = "surveyor"
Then
x.Sheets("Survey_form").Rage("B" & i).Value = ("A" & i)
y.Sheets("Frontsheet").Range("D34").PasteSpecial
End If
Next i
End Sub
At the line:
Set y = ActiveWorkbook.Sheets("Frontsheet") 'set to current worksheet name
my active workbook (Workbook2), where the macro is meant to be is closing down and error Subscript out of range emerges.
What is missig then?
Please, try the next adapted code. It will copy from the csv file in the active one and exit loop:
Sub FrontsheetAdd3()
Dim x As Workbook, y As Worksheet, ws As Worksheet, sPath As String, i As Long
sPath = ThisWorkbook.path & "\Survey_form.csv"
Set y = ActiveWorkbook.Sheets("Frontsheet") 'set to current worksheet name
Set x = Workbooks.Open(sPath): Set ws = x.Sheets(1)
For i = 1 To 40
If ws.Range("A" & i).value = "surveyor" Then
y.Range("D34").value = ws.Rage("B" & i).value: Exit For
End If
Next i
End Sub
A VBA Lookup
Use Option Explicit which forces you to declare all variables.
Use variables (more of them) to make the code more readable.
Use meaningful variable names: sPath is a great name while x and y used for workbooks are terrible.
Instead of the loop, use Application.Match.
You can basically copy in three ways: Copy, Copy with PasteSpecial or Copy by Assignment (dCell.Value = sCell.Value) the latter being the most efficient when copying only values.
Option Explicit
Sub FrontsheetAdd3()
Dim dwb As Workbook: Set dwb = ThisWorkbook ' workbook containing this code
Dim dws As Worksheet: Set dws = dwb.Worksheets("Frontsheet")
Dim dCell As Range: Set dCell = dws.Range("D34")
Dim sPath As String: sPath = dwb.Path & "\Survey_form.csv"
Dim swb As Workbook: Set swb = Workbooks.Open(sPath)
Dim sws As Worksheet: Set sws = wb.Worksheets("Survey_form")
' Determine the position of the first occurence of "surveyor" in column 'A'.
Dim sIndex As Variant
sIndex = Application.Match("surveyor", sws.Columns("A"), 0)
If IsNumeric(sIndex) Then ' "suveyor" was found
Dim sCell As Range: Set sCell = sws.Rows(sIndex).Columns("B")
dCell.Value = sCell.Value
Else ' "surveyor" was not found
dCell.Value = ""
End If
swb.Close SaveChanges:=False
'dwb.Save
End Sub
I have the below macro which lists all the worksheet names in the current(host) workbook.
I would like to adapt this code so it targets an active/open workbook, which has its workbook name & extension referenced in cell C1.
range("C1").value
Please can someone let me know how I adapt the below code.
Sub ListSheets()
Dim ws As Worksheet
Dim x As Integer
x = 1
Sheets("Sheet1").Range("A:A").Clear
For Each ws In Worksheets
Sheets("Sheet1").Cells(x, 1) = ws.Name
x = x + 1
Next ws
End Sub
This should do the job but you don't need the extension of the workbook just the name.
Sub ListSheets()
Dim ws As Worksheet
Dim x As Integer
Dim wbk As Workbook
Dim wbkName As String
x = 1
wbkName = ThisWorkbook.Sheets("Sheet1").Range("C1").Value
ThisWorkbook.Sheets("Sheet1").Range("A:A").Clear
Set wbk = Application.Workbooks(wbkName)
For Each ws In wbk.Worksheets
ThisWorkbook.Sheets("Sheet1").Cells(x, 1) = ws.Name
x = x + 1
Next ws
End Sub
Sub ListSheets()
Dim inputwb As Workbook
Dim ws As Worksheet, source As Worksheet
Dim LRow As Long
' Change source sheet if it is NOT always the active worksheet
' or activate the source sheet first with Workbooks("NAME").Sheets(INDEX).Activate (not preferable)
Set source = ActiveSheet
On Error Resume Next
Set inputwb = Workbooks(Cells(1, 1).Value)
If err.Number <> 0 Then
MsgBox "Could not find workbook " & Cells(1, 1).Value & ". Subroutine execution stopped."
Exit Sub
End If
On Error GoTo 0
ThisWorkbook.Sheets("Sheet1").Range("A:A").Clear
LRow = 1
For Each ws In inputwb.Worksheets
ThisWorkbook.Sheets("Sheet1").Cells(LRow, 1) = ws.Name
LRow = LRow + 1
Next ws
End Sub
I am pretty new to VBA and am having an issue with my code. I have different hotel names from cell B4 to B27. My goal is to create new worksheets and name each one with the hotel names (going down the list). I tried running the sub procedure below but I am getting an error. The error says:
"Run-time error '1004': Application-defined or object-defined error"
It refers to the line below my comment. Any thoughts on why this is occurring and how I can fix this?
Sub sheetnamefromlist()
Dim count, i As Integer
count = WorksheetFunction.CountA(Range("B4", Range("B4").End(xlDown)))
i = 4
Do While i <= count
' next line errors
Sheets.Add(after:=Sheets(Sheets.count)).Name = Sheets("LocalList").Cells(i, 2).Text
i = i + 1
Loop
Sheets("LocalList").Activate
End Sub
Here is something that I quickly wrote
Few things
Do not find last row like that. You may want to see THIS
Do not use .Text to read the value of the cell. You may want to see What is the difference between .text, .value, and .value2?
Check if the sheet exists before trying to create one else you will get an error.
Is this what you are trying?
Option Explicit
Sub sheetnamefromlist()
Dim ws As Worksheet, wsNew As Worksheet
Dim lRow As Long, i As Long
Dim NewSheetName As String
'~~> Set this to the relevant worksheet
'~~> which has the range
Set ws = ThisWorkbook.Sheets("LocalList")
With ws
'~~> Find last row
lRow = .Range("B" & .Rows.Count).End(xlUp).Row
'~~> Loop through the range
For i = 4 To lRow
NewSheetName = .Cells(i, 2).Value2
'~~> Check if there is already a worksheet with that name
If Not SheetExists(NewSheetName) Then
'~~> Create the worksheet and name it
With ThisWorkbook
.Sheets.Add(After:=.Sheets(.Sheets.Count)).Name = NewSheetName
End With
End If
Next i
End With
End Sub
'~~> Function to check if the worksheet exists
Private Function SheetExists(shName As String) As Boolean
Dim shNew As Worksheet
On Error Resume Next
Set shNew = ThisWorkbook.Sheets(shName)
On Error GoTo 0
If Not shNew Is Nothing Then SheetExists = True
End Function
My assumptions
All cells have valid values i.e which can be used for sheet names. If not, then you will have to handle that error as well.
Workbook (not worksheet) is unprotected
Try,
Sub test()
Dim vDB As Variant
Dim rngDB As Range
Dim Ws As Worksheet, newWS As Worksheet
Dim i As Integer
Set Ws = Sheets("LocalList")
With Ws
Set rngDB = .Range("b4", .Range("b4").End(xlDown))
End With
vDB = rngDB 'Bring the contents of the range into a 2D array.
For i = 1 To UBound(vDB, 1)
Set newWS = Sheets.Add(after:=Sheets(Sheets.Count))
newWS.Name = vDB(i, 1)
Next i
End Sub
Create Worksheets from List
The following will create (and count) only worksheets with valid names.
When the worksheet is already added and the name is invalid, it will be deleted (poorly handled, but it works.)
It is assumed that the list is contiguous (no empty cells).
The Code
Option Explicit
Sub SheetNameFromList()
Const wsName As String = "LocalList"
Const FirstCell As String = "B4"
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
Dim ListCount As Long
ListCount = WorksheetFunction.CountA(ws.Range(FirstCell, _
ws.Range(FirstCell).End(xlDown)))
Dim fRow As Long: fRow = ws.Range(FirstCell).Row
Dim fCol As Long: fCol = ws.Range(FirstCell).Column
Dim i As Long, wsCount As Long
Do While i < ListCount
If addSheetAfterLast(wb, ws.Cells(fRow + i, fCol).Value) = True Then
wsCount = wsCount + 1
End If
i = i + 1
Loop
ws.Activate
MsgBox "Created " & wsCount & " new worksheet(s).", vbInformation
End Sub
Function addSheetAfterLast(WorkbookObject As Workbook, _
SheetName As String) _
As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = WorkbookObject.Worksheets(SheetName)
If Err.Number = 0 Then Exit Function
Err.Clear
WorkbookObject.Sheets.Add After:=WorkbookObject.Sheets(Sheets.count)
If Err.Number <> 0 Then Exit Function
Err.Clear
WorkbookObject.ActiveSheet.Name = SheetName
If Err.Number <> 0 Then
Application.DisplayAlerts = False
WorkbookObject.Sheets(WorkbookObject.Sheets.count).Delete
Application.DisplayAlerts = False
Exit Function
End If
addSheetAfterLast = True
End Function
I have search and search for an answer to my code issue but I cant find any. I will be very grateful if someone can take a look at my code. At the moment, I have several large workbooks for data for each country. Each workbook has more that 5 work sheets. I want to consolidate the workbooks into a master file. First, I wan to copy and paste all worksheets under one work sheet in the master workbook and name it all by the country. Right now, my code is only able to consolidate one country at a time which makes it very slow. also the loop worksheet seems to the failing. It creates only one country worksheet. If I put in multiple country names, only the last country workbook gets consolidated. Something is missing but I cant seem to figure it out. Thank you so much!!!! Below is my code:
Sub consolidate()
Application.EnableCancelKey = xlDisabled
Dim folderPath As String
Dim Filename As String
Dim wb As Workbook
Dim Masterwb As Workbook
Dim sh As Worksheet
Dim NewSht As Worksheet
Dim FindRng As Range
Dim PasteRow As Long
Dim countryname As String
Dim LastRow, Rowlast, Rowlast2 As Long
Const fr As Long = 2
Dim i As Long
Dim cell As Range
Dim wx As Worksheet
Set wx = ThisWorkbook.Sheets("Countryname")
Rowlast = wx.Range("B" & Rows.Count).End(xlDown).row 'selects list of country workbook I want to consolidate. e.g I could have Germany, usa, china
Rowlast2 = wx.Range("C" & Rows.Count).End(xlDown).row 'selects list of tabs for each country workbook I want to consolidate, e.g I want for every country listed above, that sheet names 1, 2, 3, 4 be consolidated and put in new worksheets in the masterfile
With wx
For LastRow = fr To Rowlast
If .Cells(LastRow, "B").Value <> "" Then
countryname = .Cells(LastRow, "B").Value
' set master workbook
Set Masterwb = Workbooks("ebele_test.xlsm")
folderPath = Application.InputBox(Prompt:= _
"Please enter only folder path in this format as C:\Users\... Exclude the file name", _
Title:="InputBox Method", Type:=2) 'Type:=2 = text
If folderPath = "False" Or IsError(folderPath) Then 'If Cancel is clicked on Input Box exit sub
MsgBox "Incorrect Input, Please paste correct folder path"
Exit Sub
'On Error GoTo 0
End If
If Right(folderPath, 1) <> "\" Then folderPath = folderPath & "\"
Application.ScreenUpdating = False
Dim str As String
str = "Screener_User_Template-"
Filename = Dir(folderPath & str & countryname & "*.xlsx")
Do While Filename <> ""
Set wb = Workbooks.Open(folderPath & Filename)
If Len(wb.Name) > 253 Then
MsgBox "Sheet's name can be up to 253 characters long, shorten the Excel file name"
wb.Close False
GoTo Exit_Loop
Else
' add a new sheet with the file's name (remove the extension)
With Masterwb
Dim isLastSheet As Boolean
Dim ci, rows1 As Integer
Dim row As Long
rows1 = ThisWorkbook.Worksheets.Count
For ci = rows1 To 1 Step (-1)
If (isLastSheet) = False Then
Set NewSht = Masterwb.Worksheets.Add(After:=Worksheets(ci)) 'Place sheet at the end.
NewSht.Cells(1, 1) = "Identifier"
NewSht.Cells(1, 2) = "Company Name"
NewSht.Cells(1, 3) = "Country of Incorporation"
NewSht.Name = countryname
End If
Next ci
End With
End If
' loop through all sheets in opened wb
For Each sh In wb.Worksheets
For i = 2 To Rowlast2
If sh.Name = wx.Cells(i, "C").Value And NewSht.Name = countryname Then
' get the first empty row in the new sheet
Set FindRng = NewSht.Cells.Find(What:="*", Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False)
If Not FindRng Is Nothing Then ' If find is successful
PasteRow = FindRng.row + 1
Else ' find was unsuccessfull > new empty sheet, should paste at the second row
PasteRow = 2
End If
Dim rng As Range
Set rng = sh.Range(sh.Cells(3, "A"), sh.Cells(150000, "M"))
rng.Copy
NewSht.Range("A" & PasteRow).PasteSpecial xlPasteValues
End If
Application.CutCopyMode = False 'Clears the clipboard
Next i
Next sh
wb.Close False
Exit_Loop:
Set wb = Nothing
Filename = Dir
Loop
End If
Next LastRow
End With
'0: Exit Sub
Application.ScreenUpdating = True
End Sub
It's a Mess
This is not a solution, just a work in progress which I cannot continue due to lack of information and knowledge. It could help you to finish what you started. It would be a shame to quit after you have invested so much time in it. If you provide some answers from the questions in the code someone else might help you finish it. The questions are by no means ironic, they're serious questions that I cannot answer for sure.
The code should be safe, but just don't save anything not to lose data.
I would suggest you somehow split such a code into several and ask several questions to get answers in the future.
Option Explicit
Sub Consolidate()
Application.EnableCancelKey = xlDisabled
' ThisWorkbook
Const cStrCountry As String = "CountryName"
Const cLngRow1 As Long = 2
' Tip: To use columns either as string or as integer declare them as Variant.
Const cVntColCountries As Variant = "B"
Const cVntColTabs As Variant = "C"
Const cStrTemplate = "Screener_User_Template-"
Const cStrMaster As String = "ebele_test.xlsm"
Const cStrExt = ".xlsx"
' New Worksheet in Master Workbook
Const cStrNewHeader1 = "Identifier"
Const cStrNewHeader2 = "Company Name"
Const cStrNewHeader3 = "Country of Incorporation"
' Each Worksheet in Each Workbook
Const cLngFirstRow As Long = 3
Const cLngLastRow As Long = 150000
' Tip: To use columns either as string or as integer declare them as Variant.
Const cVntFirstCol As Variant = "A"
Const cVntLastCol As Variant = "M"
' MsgBox
Dim strMsg1 As String
strMsg1 = "Please enter only folder path in this format as " _
& "C:\Users\... Exclude the file name"
Dim strMsg2 As String
strMsg2 = "Incorrect Input. Please paste correct folder path."
Dim strMsg3 As String
strMsg3 = "Sheet's name can only be up to 253 characters long. " _
& "Shorten the Excel file name."
' Workbooks
' ThisWorkbook
Dim ojbWbEach As Workbook ' Workbook Looper
Dim objWbMaster As Workbook ' Master Workbook
' Worksheets
' ThisWorkbook.Worksheets (cStrCountry)
Dim objWsEach As Worksheet ' Worksheet Looper
Dim objWsNew As Worksheet ' New Worksheet
' Arrays Pasted From Ranges
Dim vntCountries As Variant ' List of Countries
Dim vntTabs As Variant ' List of Tabs
' Ranges
Dim objRngEmpty As Range ' New Sheet Paste Cell
' Rows
Dim lngPasteRow As Long ' New Sheet Paste Row
Dim lngCountries As Long ' Countries Counter
Dim lngTabs As Long ' Tabs Counter
' Strings
Dim strPath As String
Dim strFile As String
Dim strCountry As String
With ThisWorkbook.Worksheets(cStrCountry)
' Paste list of countries from column cVntColCountries into array
vntCountries = .Range(.Cells(cLngRow1, cVntColCountries), _
.Cells(Rows.Count, cVntColCountries).End(xlUp)).Value2
' Paste list of tabs from column cVntColTabs into array
vntTabs = .Range(.Cells(cLngRow1, cVntColTabs), _
.Cells(Rows.Count, cVntColTabs).End(xlUp)).Value2
End With
' The data is in arrays instead of ranges.
' 1. According to the following line the workbook objWbMaster is already open.
' Is that true?
Set objWbMaster = Workbooks(cStrMaster)
For lngCountries = LBound(vntCountries) To UBound(vntCountries)
If vntCountries(lngCountries, 1) <> "" Then
strCountry = vntCountries(lngCountries, 1)
' Determine the path to search for files in.
strPath = Application.InputBox(Prompt:=strMsg1, _
Title:="InputBox Method", Type:=2) ' Type:=2 = text
' When Cancel is clicked in Input Box ... Exit Sub
If strPath = "False" Or IsError(strPath) Then
MsgBox strMsg2
Exit Sub
End If
If Right(strPath, 1) <> "\" Then strPath = strPath & "\"
Application.ScreenUpdating = False
strFile = Dir(strPath & cStrTemplate & strCountry & "*" & cStrExt)
' VBA Help: Dir returns the first file name that matches pathname. To
' get any additional file names that match pathname, call Dir
' again with no arguments. When no more file names match, Dir
' returns a zero-length string ("").
' i.e. The approach is correct!
Do While strFile <> ""
Set ojbWbEach = Workbooks.Open(strPath & strFile)
' 2. When would this ever happen?
If Len(ojbWbEach.Name) <= 253 Then
' Add a new sheet with the file's name (remove the extension)
With objWbMaster
' 3. Isn't the blnLastSheet always False. What should it be doing?
Dim blnLastSheet As Boolean
Dim intSheetsCounter As Integer
Dim intSheets As Integer
intSheets = .Worksheets.Count
' 4. Why parentheses in ... Step (-1)?
For intSheetsCounter = intSheets To 1 Step -1
' 5. Why parentheses in (blnLastSheet)?
If (blnLastSheet) = False Then
' Place sheet at the end.
Set objWsNew = .Worksheets _
.Add(After:=.Worksheets(intSheetsCounter))
With objWsNew
.Cells(1, 1) = cStrNewHeader1
.Cells(1, 2) = cStrNewHeader2
.Cells(1, 3) = cStrNewHeader3
.Name = strCountry
End With
End If
Next
End With
Else
MsgBox strMsg3
ojbWbEach.Close False
GoTo Exit_Loop
End If
' Loop through all worksheets in ojbWbEach.
For Each objWsEach In ojbWbEach.Worksheets
With objWsEach
For lngTabs = LBound(vntTabs) To UBound(vntTabs)
If .Name = vntTabs(lngTabs) _
And objWsNew.Name = strCountry Then
' Get the first empty row in the new sheet
Set objRngEmpty = objWsNew.Cells.Find(What:="*", _
Lookat:=xlPart, LookIn:=xlFormulas, _
SearchOrder:=xlByRows, SearchDirection:=xlPrevious)
' 6. I don't think that this is necessary because you added
' the headers to the New sheet so it will find the first
' row. Or am I missing something?
If Not objRngEmpty Is Nothing Then
' If find is successful.
lngPasteRow = objRngEmpty.row + 1
Else
' Find was unsuccessfull > new empty sheet.
' Should paste at the second row.
lngPasteRow = cLngRow1
End If
' if I'm right, delete all starting from "Set objRngEmpty ..."
' and delete "Dim objRngEmpty as Range" and use the following
' line:
' lngPasteRow = objWsNew.Cells.Find(What:="*", Lookat:=xlPart, _
LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious).row + 1
' Pasting a range into a same sized range is much faster than
' looping or copy/pasting.
objWsNew.Range(.Cells(lngPasteRow, cVntFirstCol), _
.Cells(cLngLastRow + lngPasteRow - cLngFirstRow, _
cVntLastCol)) = _
.Range(.Cells(cLngFirstRow, cVntFirstCol), _
.Cells(cLngLastRow, cVntLastCol)).Value2
End If
Next
.Close False
End With
Next
Exit_Loop:
Set ojbWbEach = Nothing
strFile = Dir
Loop
End If
Next lngCountries
Set objWsEach = Nothing
Set objWsNew = Nothing
Set objWbEach = Nothing
Set objWbMaster = Nothing
Application.ScreenUpdating = True
End Sub
Thank you again for the clean up. I made some modifications to your code and corrected some error but for some reason, it is only able to consolidate 7 countries after which excel crashes. See the code I am running below: Do you think you can find the issue?
Option Explicit
Sub Consolidate()
Application.EnableCancelKey = xlDisabled
' ThisWorkbook
Const cStrCountry As String = "CountryName"
Const cLngRow1 As Long = 2
' Tip: To use columns either as string or as integer declare them as Variant.
Const cVntColCountries As Variant = "B"
Const cVntColTabs As Variant = "C"
Const cStrTemplate = "Screener_User_Template-"
Const cStrMaster As String = "ebele_test.xlsm"
Const cStrExt = ".xlsx"
' New Worksheet in Master Workbook
Const cStrNewHeader1 = "Identifier"
Const cStrNewHeader2 = "Company Name"
Const cStrNewHeader3 = "Country of Incorporation"
' Each Worksheet in Each Workbook
Const cLngFirstRow As Long = 3
Const cLngLastRow As Long = 150000
' Tip: To use columns either as string or as integer declare them as Variant.
Const cVntFirstCol As Variant = "A"
Const cVntLastCol As Variant = "M"
' MsgBox
Dim strMsg1 As String
strMsg1 = "Please enter only folder path in this format as " _
& "C:\Users\... Exclude the file name"
Dim strMsg2 As String
strMsg2 = "Incorrect Input. Please paste correct folder path."
Dim strMsg3 As String
strMsg3 = "Sheet's name can only be up to 253 characters long. " _
& "Shorten the Excel file name."
' Workbooks
' ThisWorkbook
Dim ojbWbEach As Workbook ' Workbook Looper
Dim objWbMaster As Workbook ' Master Workbook
' Worksheets
' ThisWorkbook.Worksheets (cStrCountry)
Dim objWsEach As Worksheet ' Worksheet Looper
Dim objWsNew As Worksheet ' New Worksheet
' Arrays Pasted From Ranges
Dim vntCountries As Variant ' List of Countries
Dim vntTabs As Variant ' List of Tabs
' Ranges
Dim objRngEmpty As Range ' New Sheet Paste Cell
' Rows
Dim lngPasteRow As Long ' New Sheet Paste Row
Dim lngCountries As Long ' Countries Counter
Dim lngTabs As Long ' Tabs Counter
' Strings
Dim strPath As String
Dim strFile As String
Dim strCountry As String
With ThisWorkbook.Worksheets(cStrCountry)
' Paste list of countries from column cVntColCountries into array
vntCountries = .Range(.Cells(cLngRow1, cVntColCountries), _
.Cells(Rows.Count, cVntColCountries).End(xlUp)).Value2
' Paste list of tabs from column cVntColTabs into array
vntTabs = .Range(.Cells(cLngRow1, cVntColTabs), _
.Cells(Rows.Count, cVntColTabs).End(xlUp)).Value2
End With
' The data is in arrays instead of ranges.
' 1. According to the following line the workbook objWbMaster is already open.
' Is that true? yeah, but I moved the strpath up because I want it to be inputed once
Set objWbMaster = Workbooks(cStrMaster)
' Determine the path to search for files in.
strPath = Application.InputBox(Prompt:=strMsg1, _
Title:="InputBox Method", Type:=2) ' Type:=2 = text
'
For lngCountries = LBound(vntCountries) To UBound(vntCountries)
If vntCountries(lngCountries, 1) <> "" And strPath <> "" Then
strCountry = vntCountries(lngCountries, 1)
' When Cancel is clicked in Input Box ... Exit Sub
If strPath = "False" Or IsError(strPath) Then
MsgBox strMsg2
Exit Sub
End If
If Right(strPath, 1) <> "\" Then strPath = strPath & "\"
Application.ScreenUpdating = False
strFile = Dir(strPath & cStrTemplate & strCountry & "*" & cStrExt)
' VBA Help: Dir returns the first file name that matches pathname. To
' get any additional file names that match pathname, call Dir
' again with no arguments. When no more file names match, Dir
' returns a zero-length string ("").
' i.e. The approach is correct!
Do While strFile <> ""
Set ojbWbEach = Workbooks.Open(strPath & strFile)
' 2. When would this ever happen?
If Len(ojbWbEach.Name) <= 253 Then
' Add a new sheet with the file's name (remove the extension)
With objWbMaster
' 3. Isn't the blnLastSheet always False. What should it be doing?
Dim blnLastSheet As Boolean
Dim intSheetsCounter As Integer
Dim intSheets As Integer
intSheets = .Worksheets.Count
' 4. Why parentheses in ... Step (-1)?
For intSheetsCounter = intSheets To 1 Step -1
' 5. Why parentheses in (blnLastSheet)?
If blnLastSheet = False Then
' Place sheet at the end.
Set objWsNew = .Worksheets _
.Add(After:=.Worksheets(intSheetsCounter))
With objWsNew
.Cells(1, 1) = cStrNewHeader1
.Cells(1, 2) = cStrNewHeader2
.Cells(1, 3) = cStrNewHeader3
End With
End If
Next
End With
Else
MsgBox strMsg3
ojbWbEach.Close False
GoTo Exit_Loop
End If
' Loop through all worksheets in ojbWbEach.
For Each objWsEach In ojbWbEach.Worksheets
With objWsEach
For lngTabs = LBound(vntTabs) To UBound(vntTabs)
If .Name = vntTabs(lngTabs, 1) Then
' _
'And objWsNew.Name = strCountry
'
' Get the first empty row in the new sheet
lngPasteRow = objWsNew.Cells.Find(What:="*", Lookat:=xlPart, _
LookIn:=xlFormulas, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious).row + 1
' Pasting a range into a same sized range is much faster than
' looping or copy/pasting.
objWsNew.Range(objWsNew.Cells(lngPasteRow, cVntFirstCol), _
objWsNew.Cells(cLngLastRow + lngPasteRow - cLngFirstRow, _
cVntLastCol)) = _
.Range(.Cells(cLngFirstRow, cVntFirstCol), _
.Cells(cLngLastRow, cVntLastCol)).Value2
objWsNew.Name = strCountry
End If
Next
End With
Next
ojbWbEach.Close False
Exit_Loop:
Set ojbWbEach = Nothing
strFile = Dir
Loop
End If
Next lngCountries
Set objWsEach = Nothing
Set objWsNew = Nothing
Set ojbWbEach = Nothing
Set objWbMaster = Nothing
Call Module2.clean
Application.ScreenUpdating = True
End Sub
What it does is that it also creates extra blank worksheets which I have to clean up with the sub clean.
This is a code from my consolidator maybe you can get an idea.
Dim lRow As Long
Dim LastRow As Long
lRow = Sheets("Sheet1").Cells(Rows.Count, "E").End(xlUp).Row
lRow = lRow + 100
LastRow = WorksheetFunction.Max(Sheets("Sheet1").Cells(Rows.Count, "E").End(xlUp).Row, 9)
LastRow = LastRow + 1
sht1.Range("A10:Q" & lRow).Copy
sht2.Range("A" & LastRow).PasteSpecial
Dim rowL As Long
rowL = sht1.Range("E65536").End(xlUp).Row
sht1.Range("B7").Copy Destination:=sht2.Range("R" & LastRow)
sht1.Range("D7").Copy Destination:=sht2.Range("S" & LastRow)
I'm new to VBA and trying to put together a macro to copy in data from another workbook and then hyperlink values on an existing sheet to the sheets i've copied in based on a string value in a cell. For the most part the script works however i'm getting a type mismatch error. Hoping someone can help identify what i'm doing wrong.
Sub CopyTitleDetailData()
'Copy all sheets from Key New Release Detail sheet, overrides existing sheets, copys in new sheets
Dim wb As Workbook, ws As Worksheet, wbTarget As Workbook, wsTarget As Worksheet
Application.ScreenUpdating = False
Set wb = ActiveWorkbook 'Main workbook
Dim pth As String
pth = wb.Path
Dim titleDetailPth As String
titleDetailPth = Left(pth, InStrRev(pth, "\") - 1)
Dim filePthName As String
filePthName = titleDetailPth & "\Files for Pre-Order Report (Macro & Alteryx)\" & "Key New Release Accounts Details.xlsx"
Set wbTarget = Workbooks.Open(filePthName, UpdateLinks = False, ReadOnly = True)
For Each wsTarget In wbTarget.Worksheets 'A loop for each worksheet in the Key New Release Detail workbook
For Each ws In wb.Worksheets 'A loop for each worksheet in the Pre-Order (i.e. active workbook)
If wsTarget.Name = ws.Name Then 'If the sheet I am importing exists, it will be deleted
Application.DisplayAlerts = False
ws.Delete
Application.DisplayAlerts = True
End If
Next ws
wsTarget.Copy After:=wb.Sheets(wb.Sheets.Count) 'Copies it into the last sheet
wb.Sheets(wsTarget.Name).Visible = 0 'Hides the copied sheets
Next wsTarget
wbTarget.Close SaveChanges:=False
Application.ScreenUpdating = True
'Loops through a specified column and when a specified value is found, puts a hyperlink in the cell below
Const cWsName As String = "Title Detail"
Const cSearch As String = "Title"
Const cRow1 As Integer = 1
Const cRow2 As Integer = 800
Const cCol As String = "D"
Dim oWb As Workbook
Dim oWs As Worksheet
Dim rCell1 As Range
Dim rCell2 As Range
Dim iR As Integer
Dim strText As String
Dim strAddr As String
Set oWb = ActiveWorkbook
Set oWs = oWb.Worksheets(cWsName)
For iR = cRow1 To cRow2
Set rCell1 = oWs.Range(cCol & iR)
Set rCell2 = oWs.Range(cCol & iR + 1)
strText = rCell2.Text 'What's written in the cell.
strAddr = rCell2.Address 'The address e.g. B1, B13 ...
If rCell1 = cSearch Then
If strText <> "" Then
'Anchor is the place where i'm placing the hyperlink.
'SubAddress is where the hyperlink will take you
rCell2.Hyperlinks.Add _
Anchor:=rCell2, _
Address:="", _
SubAddress:="'" & rCell2 & "'!" & "A1", _
TextToDisplay:=strText 'The same text that orginally lived in the cell
Else
'What im doing if the cell is empty (i.e. nothing)
End If
End If
Next
Dim beginRow As Long
Dim endRow As Long
Dim chkCol As Long
Dim rowCnt As Long
Dim rngResult As Range
beginRow = 1
endRow = 800
chkCol = 1
With oWs
.Cells.EntireRow.Hidden = False 'Unhides all rows, remove line if that's not desired
For rowCnt = beginRow To endRow
If .Cells(rowCnt, chkCol) = "X" Then
If rngResult Is Nothing Then
Set rngResult = .Cells(rowCnt, 1)
Else
Set rngResult = Union(rngResult, .Cells(rowCnt, 1))
End If
End If
Next rowCnt
End With
If Not rngResult Is Nothing Then rngResult.EntireRow.Hidden = True
End Sub
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Dim oWs As Workbook
Dim targetString As String, targetSheet As Worksheet
Set oWs = ActiveWorkbook
targetString = Cells(Target.Range.Row, Target.Range.Column).Value
Set targetSheet = oWs.Sheets(targetString)
If targetSheet.Visible = False Then
targetSheet.Visible = True
End If
'End on Title Detail Sheet
targetSheet.Select
End Sub
Per this documentation, you have to provide an Address when adding a hyperlink. you seem to be setting Address = ""
https://learn.microsoft.com/en-us/office/vba/api/excel.hyperlinks.add