I am running a loop through all my worksheets to collcet data on the first worksheet. Now I want to exclude a list of worksheets that is defines by their namees in a list on the first worksheet.
I could exclude them one by one like this:
dim ws as worksheet
For each ws in ThisWorkbook.Worksheets
If ws.Name <> "Sheet1" and ws.name <> "Sheet2"
and so on.
BUT
Since the data will change in the future I dont want to edit this code everytime the "exclude-list" changes.
UPDATE
I have tried the solution from "CLR" because it seemed like an easy way to fix it and it worked for my case. Just a reminder: You also have to include the name of the worksheet you want to diaplay your data on in the list and you are used to the If ws.Name <> "Sheet1" and ws.name <> "Sheet2" method. All the other solutions might work too, when I have the time I might test them, too.
Process worksheets of active workbook, excluding those on a list in a specified range:
Modify the A1:A6 address to the location of your exclusion list. Modify the Sheet1 part if your list is on another named sheet.
Sub ProcessWorksheets()
'declarations
Dim ws As Worksheet
Dim exceptionlist As Range
'define range that contains exceptions
Set exceptionlist = ActiveWorkbook.Worksheets("Sheet1").Range("A1:A6")
'cycle through each worksheet
For Each ws In ThisWorkbook.Worksheets
'if ws.name does not exist in the range
If Application.CountIf(exceptionlist, ws.Name) = 0 Then
'do something with ws
Debug.Print ws.Name
Else
'ignore it, do nothing
End If
Next
End Sub
What you can do is create a sheet named Exclude.
On column A write Exclude on first line.
Your other sheets to exclude after. Finally, use code below..
Dim Lastrow As Integer
Lastrow = ws.Cells(Rows.Count, 1).End(xlUp).Row
Set rs = ws.Range("A1:A1" & Lastrow)
For Each ws In ThisWorkbook.Worksheets
If Not rs.Find(ws.Name) Is Nothing Then
'Your code
End If
Next
Loop Through Worksheets Excluding the Ones in a List
Test this code as-is before adding your processing code assuring yourself that it works correctly i.e. that it includes the correct worksheets.
Option Explicit
Sub CollectData()
' Define constants.
Const LIST_WORKSHEET_ID = 1 ' rather use the (tab name), e.g. "Sheet1"
Const LIST_FIRST_CELL As String = "Z2"
' Reference the workbook.
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Reference the list range.
Dim lws As Worksheet: Set lws = wb.Sheets(LIST_WORKSHEET_ID)
Dim lfCell As Range: Set lfCell = lws.Range(LIST_FIRST_CELL)
Dim llCell As Range
Set llCell = lws.Cells(lws.Rows.Count, lfCell.Column).End(xlUp)
Dim lrg As Range: Set lrg = lws.Range(lfCell, llCell)
Dim sws As Worksheet
' Loop through all worksheets...
For Each sws In wb.Worksheets
' ... excluding the ones from the list:
If IsError(Application.Match(sws.Name, lrg, 0)) Then
' Continue using the 'sws' variable , e.g.:
Debug.Print sws.Name
'Else ' it's one from the list; do nothing
End If
Next sws
MsgBox "Data collected.", vbInformation
End Sub
Related
So I have a workbook with multiple sheets. All contain the same columns but just different categorical data. I want to grab all the data from those sheets and display/populate to a master sheet in the workbook.
I have tried different methods, but none of them are dynamic. The amount of data can be changed (+/-, either more rows or less rows) in each sheet. Each method I have found seems to be a static solution.
One example is to use the Consolidate option under the data tab, and add the respective reference/range for each sheet you would like to add (not dynamic).
Another option I found was a VBA macro, which populates the headers over and over, which I do not want to happen either, I want them all under the same header (Since the columns are already the same)
Sub Combine()
'UpdatebyExtendoffice20180205
Dim I As Long
Dim xRg As Range
Worksheets.Add Sheets(1)
ActiveSheet.Name = "Combined"
For I = 2 To Sheets.Count
Set xRg = Sheets(1).UsedRange
If I > 2 Then
Set xRg = Sheets(1).Cells(xRg.Rows.Count + 1, 1)
End If
Sheets(I).Activate
ActiveSheet.UsedRange.Copy xRg
Next
End Sub
Is this achievable?
Sheet 1
Sheet 2
Master Sheet Should Be:
But actually returns the following:
Will this constantly run each time the workbook is closed/opened/updated if it is a macro enabled workbook?
Consolidate All Worksheets
It is assumed that the Combined worksheet already exists with at least the headers which will stay intact.
To make it more efficient, only values are copied (no formats or formulas).
It will utilize the Worksheet Activate event: each time you activate (select) the combined worksheet, the data will automatically be updated.
Sheet Module of the Combined worksheet e.g. Sheet10(Combined)
Option Explicit
Private Sub Worksheet_Activate()
CombineToMaster
End Sub
Standard Module e.g. Module1
Option Explicit
Sub CombineToMaster()
Const dName As String = "Combined"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim drrg As Range
With dws.UsedRange
If .Rows.Count = 1 Then
Set drrg = .Offset(1)
Else
.Resize(.Rows.Count - 1).Offset(1).Clear
Set drrg = .Resize(1).Offset(1)
End If
End With
Dim sws As Worksheet
Dim srg As Range
Dim drg As Range
Dim rCount As Long
For Each sws In wb.Worksheets
If sws.Name <> dName Then
With sws.UsedRange
rCount = .Rows.Count - 1
If rCount > 0 Then
Set srg = .Resize(rCount).Offset(1)
drrg.Resize(rCount).Value = srg.Value
Set drrg = drrg.Offset(rCount)
End If
End With
End If
Next sws
End Sub
VBA Solution
Sub Combine()
Dim wsCombine As Worksheet: Set wsCombine = GetSheetCombine
Dim dataSheets As Collection: Set dataSheets = GetDataSheets
' Copy Header
dataSheets.Item(1).UsedRange.Rows(1).Copy
wsCombine.Range("A1").PasteSpecial xlPasteAll
wsCombine.Range("A1").PasteSpecial xlPasteColumnWidths
Application.CutCopyMode = False
' Copy data
Dim rngDest As Range: Set rngDest = wsCombine.Range("A2")
Dim srcRng As Range
Dim ws As Worksheet
For Each ws In dataSheets
' Drop header row
With ws.UsedRange
Set srcRng = .Offset(1, 0).Resize(.Rows.Count - 1)
End With
srcRng.Copy rngDest
Set rngDest = rngDest.Offset(srcRng.Rows.Count)
Next ws
Application.CutCopyMode = False
MsgBox "Done!", vbInformation
End Sub
Private Function GetSheetCombine() As Worksheet
Dim ws As Worksheet
With Worksheets
On Error Resume Next
Set ws = .Item("Combine")
On Error GoTo 0
If ws Is Nothing Then
Set ws = .Add(Before:=.Item(1))
ws.Name = "Combine"
Else
ws.Cells.Clear ' clear any existing data
End If
End With
Set GetSheetCombine = ws
End Function
Private Function GetDataSheets() As Collection
Dim Result As New Collection
Dim ws As Worksheet
For Each ws In Worksheets
If ws.Name <> "Combine" Then Result.Add ws
Next ws
Set GetDataSheets = Result
End Function
As to your question "Will this run every time macro enabled workbook is open?".
No. You will need to put this in a VBA module and run it every time you need, via the Macro dialog (View->Macros), or link a button to it.
my code aims to copy the same range from multiple sheets and paste the data from each sheet into the next empty column in a Combined sheet. My code copies from each sheet correctly, but pastes into the same column and overwrites the preceding paste.
Could someone please point out my error?
Many thanks!
Sub CopyToNextCol()
Dim Sh As Worksheet
Dim NextCol As Long
For Each Sh In ThisWorkbook.Worksheets
If Sh.Name <> "Master" And Sh.Name <> "Lists" And Sh.Name <> "Combined" Then
NextCol = Sheets("Combined").Cells(, Columns.Count).End(xlToLeft).Column + 1
Sh.Range("B2:B44").Copy Sheets("Combined").Cells(, NextCol)
End If
Next Sh
End Sub
Copy Same Ranges From Multiple Worksheets
The following example will copy the worksheet names ("I am planning to use a different column header" in the comments) in the first row and each range below it.
s - Source, d - Destination.
A Quick Fix
Option Explicit
Sub CopyToNextCol()
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim dws As Worksheet: Set dws = wb.Worksheets("Combined")
Dim dCell As Range
Set dCell = dws.Cells(1, dws.Columns.Count).End(xlToLeft).Offset(, 1)
Dim sws As Worksheet
Dim srg As Range
For Each sws In wb.Worksheets
Select Case sws.Name
Case "Master", "Lists", "Combined"
' Skip (do nothing)
Case Else
Set srg = sws.Range("B2:B44")
dCell.Value = sws.Name
srg.Copy dCell.Offset(1)
Set dCell = dCell.Offset(, 1)
End Select
Next sws
'wb.Save
End Sub
I am trying to write a macro that will look through all sheets in the workbook, and if a sheet name contains "blank", to rename that sheet with the value in cell C1.
Here is what I have so far:
Sub Rename()
Dim ws As Worksheet
Dim sheetBlank As Worksheet
Set sheetBlank = ActiveWorkbook.ActiveSheet
Dim nameCell As Range
Set nameCell = ActiveSheet.Range("C1")
For Each ws In Sheets
If sheetBlank.Name Like "*blank*" Then
sheetBlank.Name = nameCell.Value
End If
Next ws
End Sub
Now, this does rename the first active sheet, but it is not making any changes to the rest of them. What am I doing wrong?
You're referring to the wrong worksheet:
Sub Rename()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
If ws.Name Like "*blank*" Then
ws.Name = ws.Range("C1").Value
End If
Next ws
End Sub
You set your objects outside the loop and never touch them again.
If you're going to use "ActiveSheet" you need to .Activate each sheet in order to work, but that's not a good approach since your iterator (ws) represents the sheet object.
Public Sub Rename()
Dim Ws As Worksheet
For Each Ws In Worksheets
If InStr(1, Ws.Name, "blank", vbTextCompare) > 0 Then _
Ws.Name = Ws.Range("C1").Value2
Next Ws
End Sub
I would like to copy a range to an another worksheet and to insert before it 2 columns on the new worksheet. It doesn't copy the original range.
It works, if I copy to the same worksheet.
Set ws = ThisWorkbook.Sheets("Sh2")
Set ws2 = ThisWorkbook.Sheets("Sh3")
Set wb = ThisWorkbook
rowNum = ws.UsedRange.Rows.Count
For Each row In ws.Range("A1:A" & rowNum)
ws2.Range("A1:A" & rowNum).Offset(0, 0).Value2 = wb.Name
ws2.Range("A1:A" & rowNum).Offset(0, 1).Value2 = ws.Name
Next row
For Each cell In ws.UsedRange
cell.Offset(10, 2).Value2 = cell.Value2
Next cell
I expect the column "A" contains the name of active workbook, the "B" the name of active worksheet, the other rows comes the original content. Now, the filename and worksheet's name copied to the new worksheet, but the content not.
The direction you're headed with your code is close, hopefully this example can help. But first, please always use Option Explicit in your code.
In setting up your initial variables for the worksheets, using more descriptive variable names makes it more clear exactly which variable is intended to hold certain data. My example set up then is
Dim wb As Workbook
Dim srcWS As Worksheet
Dim dstWS As Worksheet
Set wb = ThisWorkbook
Set srcWS = wb.Sheets("Sh2")
Set dstWS = wb.Sheets("Sh3")
Next, you can create a variable to determine the range area of your source data:
Dim srcRange As Range
Set srcRange = srcWS.UsedRange
In the case where you want to create your first two columns to contain the workbook and worksheet names, you don't actually need a loop. By creating a Range of the size you need, a single statement will place the same value in all of the cells in that range. Therefore you can create your name columns in two statements using
dstWS.Range("A1").Resize(srcRange.Rows.Count, 1) = wb.Name
dstWS.Range("B1").Resize(srcRange.Rows.Count, 1) = srcWS.Name
I'll establish a destination range that starts in the third column, just to the right of the two name columns:
Dim dstRange As Range
Set dstRange = dstWS.Range("C1").Resize(srcRange.Rows.Count, _
srcRange.Columns.Count)
Then with the same idea, you can also copy the entire source range to your destination in a single statement as well:
dstRange.Value = srcRange.Value
And you're done.
Here is the whole example in a single block:
Option Explicit
Sub CopyMyRange()
Dim wb As Workbook
Dim srcWS As Worksheet
Dim dstWS As Worksheet
Set wb = ThisWorkbook
Set srcWS = wb.Sheets("Sh2")
Set dstWS = wb.Sheets("Sh3")
Dim srcRange As Range
Set srcRange = srcWS.UsedRange
dstWS.Range("A1").Resize(srcRange.Rows.Count, 1) = wb.Name
dstWS.Range("B1").Resize(srcRange.Rows.Count, 1) = srcWS.Name
Dim dstRange As Range
Set dstRange = dstWS.Range("C1").Resize(srcRange.Rows.Count, _
srcRange.Columns.Count)
dstRange.Value = srcRange.Value
End Sub
I need help with the code. I want to merge all rows from few sheets except header in one sheet in Excel.
Here is the code:
Dim ws As Worksheet
Dim sh As Worksheet
Set sh = Sheets("P&L_consolidation")
For Each ws In Sheets
If ws.Name <> "Zero's" Then
ws.Range("A2", ws.Range("U"& Rows.Count).End(xlUp)).Copy sh.Range("A"& Rows.Count).ENd(xlUp)(2)
End if
Next ws
This code works if the sheet has some data in it, but the problem is if some sheet contains only header then this code copy that header and paste it to the merged sheet. In that case I just want to skip that sheet.
Please, can somebody help me?
Something like this should work for you:
Sub tgr()
Dim wb As Workbook
Dim ws As Worksheet
Dim wsDest As Worksheet
Set wb = ActiveWorkbook
Set wsDest = wb.Worksheets("P&L_consolidation")
For Each ws In wb.Worksheets
If ws.Name <> "Zero's" Then
With ws.Range("A2", ws.Cells(ws.Rows.Count, "U").End(xlUp))
If .Row >= 2 Then .Copy wsDest.Cells(ws.Rows.Count, "A").End(xlUp).Offset(1)
End With
End If
Next ws
End Sub