I have an excel workbook that contains multiple sheets. In this workbook sheets occasionally are removed, renamed, or added. This workbook features a sheet (Sheet1) that is supposed to be used as a command center for printing copies of the other sheets in the workbook. Unfortunately, this printing command center does not work as intended.
The command center has only two columns. In column A is a list with the names of the other Sheets. In column B the user can specify how many copies to print of the respective sheet in column A.
This is the current code:
Sub PrintSheets()
Dim mysheets As Range
For Each mySheets In Sheet1.Range("A2:A100")
If mySheets.Offset(0, 1).Value <> "" Then Sheets(mySheets.Value).PrintOut Copies:=mySheets.Offset(0, 1).Value
Next mySheets
End Sub
The first two sheets are printed as intended and then I get a "Run-time error '9': Subscript out of range"
1) How can I fix the error?
2) Can the list with the sheet names be generated automatically and sorted by their position (i.e., left to right in the sheet tab -> top to bottom in the column)?
If you rename, add and remove sheets, you will have to update your list before printing. This sub will clear Range("A2:A100") and it will insert all sheets names in your first sheet. Make sure your "command center" sheet is the first one (or change the index reference to the name of that special sheet).
Sub LIST_SHEETS()
Application.ScreenUpdating = False
Dim ws As Worksheet
Dim i As Byte
ThisWorkbook.Sheets(1).Range("A2:A100").Clear
i = 2
For Each ws In ThisWorkbook.Sheets
ThisWorkbook.Sheets(1).Range("A" & i).Value = ws.Name
i = i + 1
Next ws
Application.ScreenUpdating = True
End Sub
I'm afraid you will have to figure out where to put the code. I don't know your needs, so maybe after renaming/adding/deleting all sheets, or maybe when Workbook opens or something like that. Try it!.
It appears that a name in the list of sheets, does not exactly match the actual name. You can use either of the two options below, to loop through each sheet
For Each sht in ThisWorkbook.Sheets
'Do Something
Next
Or
Dim sht as Worksheet
For i= 0 to ThisWorkbook.Sheets.Count
Set sht=ThisWorkbook.Sheets(i)
'Do something
Next
The second option is not reliable when the sheets are deleted (their integer index may not be sequential then) so I would prefer the first option.
Related
I have a template file, whereby multiple copies of the template (5 to 20) are completed, then consolidated into one master file. This file contains multiple sheets (18) and hundreds of entries in each sheet.
Not every cell is a number requiring consolidation, i.e there are titles and dates etc which are repeated, with no clear structure. Re-organising the template is not an option. The best way is to calculate only cells with a "Currency" type.
Here is the code I have so far. I have pieced it together from a number of searches, but will admit that I don't fully understand vba so I know I'm missing something obvious.
To make this a bit simpler, I have closed everything else and opened the target files manually before running this, then called upon the open excel files. Improving this bit of the code so that I can just put the target files into a sub folder and then use that path would be nice but not necessary.
I do not need to change the cell colour at the end, but I just did that as a quick visual reference to see whether it had ran.
The script in this format does not throw up any errors, but simply runs without actually calculating and populating the total value into each cell. I would guess that my approach of trying to extract the sheet and cell reference for every loop is wrong, but I cannot find the answer anywhere, so any help would be greatly appreciated.
totalValue = totalValue + Worksheets(sht).Cells(R, C)
is completely the wrong syntax, and the crux of the issue, but I simply don't know how to fix this within the context of the two existing For Each loops.
Sub ConsolidatedFigures()
Application.ScreenUpdating = False
'Declare variable types
Dim ws As Worksheet
Dim totalValue As Double
Dim C As Integer
Dim R As Integer
Dim wb As Workbook
Dim sht As String
Dim myRange As Range
Dim cell As Range
'Start to loop through each sheet in the workbook
For Each ws In ThisWorkbook.Worksheets
'get the current sheet name to later search for the same sheet in other workbooks
sht = ws.Name
'set the range in the current sheet
Set myRange = ws.UsedRange
'Now loop though every cell in the range
For Each cell In myRange
'Only target cells with an "currency" style so we're not trying to sum text
If cell.Style = "Currency" Then
'get the current cell references to later search for the same cell in other workbooks
C = cell.Column
R = cell.Row
'Within the current cell, go through open workbooks (except this one) to create a total of all the corresponding cells
For Each wb In Application.Workbooks
'the target workbooks will be open already, and nothing else. Disregard this open workbook and personal book
If wb.Name <> "PERSONAL.xlsb" AND wb.Name <> "consolidation.xlsm" Then
totalValue = totalValue + Worksheets(sht).Cells(R, C)
End If
Next wb
'populate the cell with the total of the corresponding cells
cell.Value = totalValue
'change cell colour to show the above step worked
cell.Interior.ColorIndex = 5
End If
'move on to next cell in worksheet
Next cell
'move on to next sheet in the workbook
Next ws
Application.ScreenUpdating = True
End Sub
I have 200 worksheets (named 1, 2, 3 and so on) that i need to loop through and copy and paste varying ranges of data from each one into a master worksheet. How can i do this?
I have a list of all the sheets in an array in the VB Editor and have tried to loop through it.
I have a list of the sheet names in a table in another worksheet and have tried to loop through it as well.
Can someone provide a simple example of how one of these methods can be done?
Example code shown below.
Dim i As Integer
i = 11
Dim SheetList As String
Dim element As Variant
SheetList = Array("Sheet24", "Sheet25")
'Simplified example of Do While loop being used
Do While Sheet1.Cells(i, 2).Value <> ""
For Each element In SheetList
If element.Range("C3") = "" Then
GoTo Next Iteration
Else
'copy and paste data in master worksheet
End If
NextIteration:
i = i +1
Next element
Loop
Expected result: ranges of data from a number of worksheets to be copy and pasted into one combined range on the master worksheet.
You can easily loop through all the worksheets in a workbook, without needing their names, using:
Dim sht As Worksheet
For Each sht In ThisWorkbook.Worksheets
'do something
Next sht
If the range you need to copy is different in every worksheet, then you could search for the headers of the columns you want to copy for example, get the range you need and paste it's contents to your master worksheet.
If there are specific sheets you want to use, then you could still loop through all the sheets and check if some condition is true for a specific sheet like so:
For Each sht In ThisWorkbook.Worksheets
If sht.Name = "something" Then
'do something
End If
If Condition Then
'do something
End If
Next sht
For example the sheets from which you want to copy some data, could have a "flag" cell with a specific value assigned to it, like TRUE or 1. The code would check for the contents of this cell and act accordingly.
Now if you want to save time by not looping through all the sheets (which shouldn't take too much time anyway..) and to avoid checking a condition for each sheet, then you could create a custom collection of worksheets, consisting of only those sheets you are interested in.
Dim sht As Worksheet
Dim shtcol As New Collection
shtcol.Add ThisWorkbook.Worksheets(1)
shtcol.Add ThisWorkbook.Worksheets(2)
shtcol.Add ThisWorkbook.Worksheets(3)
For Each sht In shtcol
'do something
Next sht
I have set up a VBA macro that is running a VBA operation consecutively in each spreadsheet of a given Excel file. Given that there are numerous sheets in the file, which leads to occasional interruptions with the server, I have to restart the request every once in a while.
So here comes the question: I am looking to modify the code element below in a way that the VBA macro starts running on the currently selected sheet/tab. It shall then consecutively cover all remaining sheets/tabs to the right of the active sheet, but not those to the left which have already been populated.
The code below restarts the each run of the macro with the very first sheet/tab of the file, which is not necessary. Is there any smart tweak to the code?
Dim xsheet As Worksheet
For Each xsheet In ThisWorkbook.Worksheets
xsheet.Select
There are three sheet-specific collections: Worksheets, Charts and DialogSheets. The Index property of these collections returns Sheets's collection index - not the actual index in sheet-specific collection.
Say, you have four sheets:
Worksheet ("Sheet1")
Worksheet ("Sheet2")
Chart ("Chart1")
Worksheet ("Sheet3").
In this case Worksheets("Sheet3").Index returns 4 when the real index is 3. The bottom line is never rely on Index property of sheet-specific collection when it comes to processing all the sheets.
To solve you problem you just need to use Sheets collection:
Sub FFF()
Dim x%, sheet As Variant
For x = ActiveSheet.Index + 1 To Sheets.Count
Set sheet = Sheets(x)
'// Do something with sheet
Next
End Sub
Continue Through Worksheets
If you want to continue with the ActiveSheet, just remove ' + 1'.
Warning: These codes are valid if you only have worksheets in the workbook, and not charts, dialogs or whatever.
I almost always use only worksheets in my workbooks so I never learned about the Index issue that JohnyL is referring to in his answer to this question.
The Idea
Sub ContinueThroughWorksheets()
Dim i As Long
With ThisWorkbook
For i = .ActiveSheet.Index + 1 To .Worksheets.Count
Debug.Print .Worksheets(i).Name
Next
End With
End Sub
The Implementation
Sub ContinueThroughWorksheets2()
Dim i As Long
Dim j As Long
With ThisWorkbook
Select Case .ActiveSheet.Index
Case 1
j = 1
Case .Worksheets.Count
Exit Sub
Case Else
j = .ActiveSheet.Index + 1
End Select
For i = j To .Worksheets.Count
Debug.Print .Worksheets(i).Name
Next
End With
End Sub
You can do it thus, but note that it's generally not advisable to base code on the active sheet or active cells as they can easily be changed and your code may not run correctly.
A better method would be to store the (code)names of the sheets processed elsewhere and loop through your sheets excluding those names.
Sub x()
Dim i As Long
For i = ActiveSheet.Index To Worksheets.Count
MsgBox Worksheets(i).Name
Next i
End Sub
I have the following simple Excel spreadsheet:
A
1 Sheet1 =MID(CELL("filename",Sheet1!K1),FIND("]",CELL("filename",Sheet1!K1))+1,255)
2 Sheet2 =MID(CELL("filename",Sheet2!K1),FIND("]",CELL("filename",Sheet2!K1))+1,255)
3 Sheet3 =MID(CELL("filename",Sheet3!K1),FIND("]",CELL("filename",Sheet3!K1))+1,255)
4 Sheet4 =MID(CELL("filename",Sheet4!K1),FIND("]",CELL("filename",Sheet4!K1))+1,255)
5 Sheet5 =MID(CELL("filename",Sheet5!K1),FIND("]",CELL("filename",Sheet5!K1))+1,255)
6
7
In Column A there is a list of all sheets in the Excel file. I list the sheets using the formula that you can see next to it.
All this works fine so far.
Now it can happen that some sheets in my spreadsheet are invisible (hidden). In this case I want that those sheets do not appear in the list above. Therefore, I wonder if there is a formula that can identify if a sheet is visible or not. Something like this:
IF MID(CELL("filename",Sheet1!K1),FIND("]",CELL("filename",Sheet1!K1))+1,255) = Invisible THEN ""
Do you have any idea how to solve this issue?
I don't really understand the purpose of this list... it seems like you're just duplicating the list of worksheet "tabs" shown at the bottom of the screen.
I sense something being made more complicated than necessary; either an XY Problem, or some duplicate data that you're trying to manage without reorganizing it. :-)
Regardless, based on my understanding of your question, there are no built-in functions to do what you need, but these VBA examples should give you some ideas:
This procedure lists all visible worksheets, in the Immediate Window (Hit Ctrl+G from VBA to view it):
Sub ListSheets() 'list in immediate window
Dim sht As Worksheet
For Each sht In Worksheets
If sht.Visible = xlSheetVisible Then Debug.Print sht.Name
Next sht
End Sub
This procedure is similar excep lists them on the active worksheet, leaving blanks for hidden sheets (like your example would imply):
Sub ListSheets() 'list on worksheet
Dim sht As Worksheet
For Each sht In Worksheets
If sht.Visible = xlSheetVisible Then Range("A" & sht.Index) = sht.Name
Next sht
End Sub
This function can be called from a worksheet formula and lists the name of the worksheet you specify by index number. It returns "" (empty string/nothing) if the worksheet is not set to Visible, or if it doesn't exist.
Function listSheet(shtNum As Long) As String
On Error Resume Next
If Sheets(shtNum).Visible = xlSheetVisible Then listSheet = Sheets(shtNum).Name
End Function
Related note:
There are three types of worksheet visibility.
More Info:
MSDN: Worksheet.Visible Property (Excel)
Is it possible to let Excel automatically select the first empty cell in column A, whenever I open the document?
I have got the following to find the the first empty line:
ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Value + 1.Count, 1).End(xlUp).Value + 1
In order to get Excel to select the first empty cell in column A when you open your workbook, you need to place the following code in the ThisWorkbook module.
Private Sub Workbook_Open()
Dim ws As Worksheet
Set ws = ActiveSheet
ws.Cells(ws.Rows.Count, 1).End(xlUp).Offset(1, 0).Select
End Sub
This will select the first empty cell in the ActiveSheet. If you got multiple sheets in your workbook and you want to select the first empty row in a specific sheet, say Sheet1, you should change the second line of code to:
Set ws = ActiveWorkbook.Sheets("Sheet1")
You can do that.
You need write VBA(macro) program to realize.
Code you need is as follow
Private Sub Workbook_Open()
ActiveWindow.Range("A65536").End(xlUp).Offset(1,0).Select
End Sub
Meaning of code is:
"Private Sub Workbook_Open()" is predefined name subroutine which will be executed when the workbook be opened.
"ActiveWindow.Range("A65536").End(xlUp)" will find last cell with data in A column ("last cell")
"ActiveWindow.Range("A65536").End(xlUp).Offset(1,0)" will move to cell next to "last cell", that will be first blank cell.
ActiveWindow.Range("A65536").End(xlUp).Offset(1,0).Select will select tha first blank cell.
I assumed that you use Excel 2003 or older, OR number of rows with data in your worksheet is less than 65536.
If you use Excel 2007 or newer and you have rows with data in your worksheet more than 65536, please modify 65536 to the value large enough to cover rows in your worksheet.