VBA Excel autopopulate new sheets based on the cell value for incrementing cells - excel

I would like to auto-populate new sheets in Excel with their names based on the cell value. However, it won't be the value from one cell but from the list of cells in the row. The name of the first worksheet will be fetched from the 1st cell value, the name of the second worksheet from the 2nd cell value, and so on...
I defined the maximum range of these cells - 20 in the row, but not all of them will have the values. I want the new sheets to be created only from these cells, where value is provided.
I used the following code:
Sub Namedsheetsadding()
Dim wsr As Worksheet, wso As Worksheet
Dim i As Long, xCount As Long
Dim SheetName As String
Set wsr = ThisWorkbook.Sheets("Vetro Area Map 1")
SheetName = ThisWorkbook.Sheets("Frontsheet").Range("D122:D142") 'including empty cells either, but
not creating new sheets for them
For i = 1 To ActiveWorkbook.Sheets.Count
If InStr(1, Sheets(i).name, "Vetro") > 0 Then xCount = xCount + 1
Next
wsr.Copy After:=ActiveWorkbook.Sheets(wsr.Index - 1 + xCount)
ActiveSheet.name = "Vetro Area Map " & SheetName & xCount + 1
End Sub
Based on some solutions here:
VBA rename sheet based on cell value
http://excelexperts.com/vba-code-adding-new-sheet-based-cell-value
https://www.mrexcel.com/board/threads/vba-create-new-sheet-based-on-cell-data.740895
EXCEL VBA Dynamic Sheet Name according to a cell value - Not working when formula in the cell
which apply to one cell only
Possibly this is the reason, why I am getting:
Error: Type mismatch
for the following line:
SheetName = ThisWorkbook.Sheets("Frontsheet").Range("D122:D142") 'including empty cells either, but not creating new sheets for them
Is there any chance to make the sheet auto-population with names based on the cell range?

This should do what you are looking for,it gets an array from the range, converts it into a 1d array and then makes the sheets.
Sub Namedsheetsadding()
Dim wsr As Worksheet, wso As Worksheet
Dim i As Long, xCount As Long
Dim SheetNames As Variant 'This needs to be variant
Dim sheetname As Variant
Dim newsheet As Worksheet
Dim lr As Long
Set wsr = ThisWorkbook.Sheets("Vetro Area Map 1")
lr = ThisWorkbook.Sheets("Frontsheet").Cells(Rows.Count, 4).End(xlUp).Row 'Get last row
SheetNames = ThisWorkbook.Sheets("Frontsheet").Range("D122:D" & lr) 'including empty cells either, but not creating new sheets for them
SheetNames = Application.Transpose(Application.Index(SheetNames, , 1)) 'Converts the 2d array into a 1d array
For i = 1 To ActiveWorkbook.Sheets.Count
If InStr(1, Sheets(i).Name, "Vetro") > 0 Then xCount = xCount + 1
Next
For Each sheetname In SheetNames
wsr.Copy After:=ActiveWorkbook.Sheets(wsr.Index - 1 + xCount)
Set newsheet = Sheets(wsr.Index + xCount)
newsheet.Name = "Vetro Area Map " & sheetname
xCount = xCount + 1 'Preserve order of sheets from range
Next
End Sub

In answer to your question, YES, you can make sheets automatically named, but you'll need to handle your rules better. You're getting an error because you're trying to reference an array to a single string. I would recommend learning about arrays (Paul Kelly has some great stuff here), but there might be other ways to approach your specific issue.
If you're more familiar with Excel than VBA, you should try to make a cell formula rule that populates a SINGLE cell that should be the next name of a worksheet. If you can have a cell that will always have the proper name, then you can always have your code reference the same value.
Alternatively, you might want to use the VBA offset function, which is pretty easier for newer coders to comprehend.
See below as an example.
Sub makeNewWorksheets()
Dim wsr As Worksheet, wso As Worksheet
Dim i As Long, xCount As Long
Dim SheetName As String
Dim startTingCell As Range
Set startTingCell = Range("D122")
For i = 1 To ActiveWorkbook.Sheets.Count
If InStr(1, Sheets(i).Name, "Vetro") > 0 Then xCount = xCount + 1
Next
'Changes the cell being referenced by xCount
Set startTingCell = startTingCell.Offset(xCount, 0)
'helps explain what is happening. Delete after you've grasped what's up.
MsgBox "The cell that will be set to the name is " & startTingCell.Address & _
"with a value of " & startTingCell.Value
wsr.Copy After:=ActiveWorkbook.Sheets(wsr.Index - 1 + xCount)
ActiveSheet.Name = "Vetro Area Map " & startTingCell.Value
End Sub

Related

Distribute rows to individual sheets based on cell value vs sheet name

I have this vba code that appends/distributes records from a Data mastersheet to individual named sheets. This is done based on column E's value. It works fine but ends in an error whenever it encounters a value on column E that's not one of the sheets in the file. Can you please help me so as to allow it to just skip those records and proceed with the processing? Thanks!
Sub CopyDataToSheets()
Dim copyfromws As Worksheet
Dim copytows As Worksheet
Dim cfrng As Range
Dim ctrng As Range
Dim cflr As Long
Dim ctlr As Long
Dim i As Long
Dim currval As String
Set copyfromws = Sheets("Data")
cflr = copyfromws.Cells(Rows.Count, "B").End(xlUp).Row
' Copy Row of Data to Specific Worksheet based on value in Column E
' Existing Formulas in Columns F through H or J are automatically extended to the new row of data
For i = 2 To cflr
currval = copyfromws.Cells(i, 1).Value
Set copytows = Sheets(currval)
ctlr = copytows.Cells(Rows.Count, "B").End(xlUp).Row + 1
Set cfrng = copyfromws.Range("A" & i & ":N" & i)
Set ctrng = copytows.Range("A" & ctlr & ":N" & ctlr)
ctrng.Value = cfrng.Value
Next
End Sub
I would make a small helper function that can test if the worksheet exists. That way you can control the logic of your loop.
Function SheetExists(sheetName As String, Optional wb As Workbook) As Boolean
If wb Is Nothing Then Set wb = ThisWorkbook
Dim ws As Worksheet
On Error Resume Next
Set ws = wb.Sheets(sheetName)
SheetExists = Err = 0
End Function

Sum Values in different worksheets (same cell)

I have a workbook with multiple sheets ,the number of sheets can change for each project but they all end with PAF. The table is the same across all sheets as well as the cells.
I have a summary tab with the exact same table, I just need to sum it all up there, the table has at least 6 columns and 20 rows so each cell would need the same formula (basically) so I came up with the following but I'm getting an error. Any suggestions?
Sub SumPAF
Dim ws as Worksheet
Sheets("Summary PAF").Activate
For Each ws In ActiveWorkbook.Worksheets
If ws.Name Like "PAF" Then
Range("E10") = WorksheetFunction.Sum(Range("E10"))
End If
Next
End Sub
It's getting stuck in "For Each" saying that an Object is required...
I have commented the code so you should not have a problem understanding it.
Option Explicit
Sub SumPAF()
Dim ws As Worksheet
'~~> This will store the cell addresses
Dim sumFormula As String
'~~> Loop though each worksheet and check if it ends with PAF
'~~> and also to ingore summary worksheet
For Each ws In ActiveWorkbook.Worksheets
If UCase(ws.Name) Like "*PAF" And _
InStr(1, ws.Name, "Summary", vbTextCompare) = 0 Then _
sumFormula = sumFormula & "," & "'" & ws.Name & "'!E10"
'~~> or simply
'sumFormula = sumFormula & ",'" & ws.Name & "'!E10"
Next
'~~> Remove the intital ","
sumFormula = Mid(sumFormula, 2)
'~~> Insert the sum formula
If sumFormula <> "" Then _
Sheets("Summary PAF").Range("E10").Formula = "=SUM(" & sumFormula & ")"
End Sub
Here's a very simple and easy to understand program to illustrate how VBA can be used for loops over ranges. If you have any questions, feel free to ask:
Sub SumPAF()
'Save a reference to the Summary Sheet
Dim SummarySheet As Worksheet
Set SummarySheet = Sheets("Summary PAF")
'Save a reference to the Summary Table and decide the table dimensions
Dim SummaryTable As Range
Set SummaryTable = SummarySheet.Range("A1:F20")
'Create an array to save the sum values
Dim SumValues() As Double
ReDim SumValues(1 To SummaryTable.Rows.Count, 1 To SummaryTable.Columns.Count)
'Loop through the workbook sheets
Dim ws As Worksheet, TableRange As Range
For Each ws In ActiveWorkbook.Worksheets
'Find sheets ending in PAF other than the summary PAF
If ws.Name Like "*PAF" And Not ws.Name = SummarySheet.Name Then
'create a reference to a range on the sheet in the same place and dimensions as the summary table
Set TableRange = ws.Range(SummaryTable.Address)
'loop through the range, cell by cell
Dim i As Long, j As Long
For i = 1 To TableRange.Rows.Count
For j = 1 To TableRange.Columns.Count
'Sum each cell value into the array, where its cell address is the array coordinates.
SumValues(i, j) = SumValues(i, j) + TableRange.Cells(i, j).Value
Next j
Next i
End If
Next
'Output the array into the summary table
SummaryTable.Value = SumValues
End Sub

Excel Auto Change Sheet Name Based On Cells VBA

We have a workbook that needed to have the sheets change names every month and I decided to automate it for other employees. So after some research I found the best way to do it was to reference the names of cells. I needed it to start running on the 4th sheet and run through the second last sheet. I found some VBA code and edited it until I got to this point:
Sub RenameSheet()
Dim ShCnt As Integer 'count of sheets in workbook
Dim myarray() As String 'array of new worksheet names
Dim Month() As String 'mystery variable -- not used in this code
Dim i As Integer 'loop counter
Dim Lrow As Integer 'number of new worksheet names.
ThisWorkbook.Sheets("SETUP").Select 'select the sheet that has the list of new names
Lrow = Range("T1").End(xlDown).Row 'get range that contains new worksheet names
ShCnt = ThisWorkbook.Sheets.Count 'get number of worksheets in the workbook
ReDim myarray(1 To Lrow) 'resize array to match the number of new worksheet names
For i = 1 To UBound(myarray) 'loop through array of new sheet names
myarray(i) = Range("T" & i).Value 'insert new sheet name into array
Debug.Print Range("T" & i).Value 'show the new worksheet name in 'the Immediate window to be able to check that we're getting what we want
Next i 'end of loop
For i = 4 To ShCnt - 1 'loop through array of existing worksheets
Sheets(i).Name = myarray(i) 'rename each worksheet with the matching name from myarray
Next i 'end of loop
MsgBox "Sheets name has changed successfully" 'report success
End Sub
My issue is that I need the 4th sheet to start with the value in cell "T2". I have figured out that this section of code changed the starting point:
For i = 1 To UBound(myarray)
myarray(i) = Range("T" & i).Value
Debug.Print Range("T" & i).Value
Next i
When I replaced myarray(i) = Range("T" & i).Value with myarray(i) = Range("T2" & i).Value it started on cell T24 for some reason (which may have to do with the placement of my button?) and myarray(i) = Range("T" + 1 & i).Value doesn't work.
I also tried changing the For i = 1 To UBound(myarray) to For i = 2 To UBound(myarray) and that didn't work either.
Can someone please help me figure out how to get it so that the information in cell T2 ends up on the 4th sheet and goes from there? Thank you very much in advance.
I would suggest loop through worksheets in the workbook and use the loop counter to index into the range of names in column T:
Sub RenameSheet()
Dim ShCnt As Integer
Dim i As Integer
Dim ws_setup As Worksheet
Set ws_setup = ThisWorkbook.Worksheets("SETUP")
ShCnt = ThisWorkbook.Worksheets.Count
Const start_ws_index = 4
For i = start_ws_index To ShCnt - 1
ThisWorkbook.Worksheets(i).Name = _
ws_setup.Range("t2").Offset(i - start_ws_index, 0).Value
Next i
End Sub
Rename Sheets From List
In the current setup, it is assumed that the list is contiguous (no blanks), has at least two entries, and starts in cell T2, and that the 4th sheet is the first to be renamed.
The Code
Option Explicit
Sub renameSheets()
' Constants
Const wsName As String = "SETUP"
Const FirstCell As String = "T2"
Const FirstSheetIndex As Long = 4
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Array (at least two names)
Dim SheetNames As Variant
With wb.Worksheets(wsName)
SheetNames = .Range(FirstCell, .Range(FirstCell).End(xlDown))
End With
' Rename
Dim shOffset As Long: shOffset = FirstSheetIndex - 1
Dim i As Long
For i = 1 To UBound(SheetNames, 1)
wb.Sheets(i + shOffset).Name = SheetNames(i, 1)
Next i
' Inform
MsgBox "Sheet names changed successfully", vbInformation
End Sub

copy selected columns in a row to another sheet if a cell meets a condition

(not in a range, not adjacent columns)
(in given order)
I have many rows on Sheet1. I would like to copy some columns of a row (not the entire row and not a range of columns) to Sheet2 (to the first empty row of Sheet2) if a cell satisfies a condition (the cell in the current row and A column has a value of y)
I would like to copy not the entire row from Sheet1 only the row with those columns that are given on Sheet3 (Column A), and the new column number (on Sheet2) is also given on Sheet3 (column B)
It would be simple if my task would be to copy the entire row, or the selected column would be in a range...but i would need to copy those columns that are specialized on Sheet3. I would be grateful for any help. Thanks in advance.
Sheet1 shows an example data sheet. The criteria is if Cells(Rows, 1).Value = "y"
Sheet2 shows the desired result.
Sheet3 shows the selected column number on Sheet1 and the new column number on Sheet2
Whilst this probably should be done using arrays more, here's some basic VBA code that loops the first sheet checking for "y" in the first column. When it finds it, it then loops the column mappings in the third sheet that have been saved into arrays to set the values on the second sheet:
Sub sTranasferData()
On Error GoTo E_Handle
Dim aOld() As Variant
Dim aNew() As Variant
Dim wsIn As Worksheet
Dim wsOut As Worksheet
Dim wsTrack As Worksheet
Dim lngLastRow As Long
Dim lngLoop1 As Long
Dim lngLoop2 As Long
Dim lngRow As Long
Dim lngTrack As Long
Set wsIn = Worksheets("Sheet1")
Set wsOut = Worksheets("Sheet2")
Set wsTrack = Worksheets("Sheet3")
lngLastRow = wsIn.Cells(wsIn.Rows.Count, "A").End(xlUp).Row
lngTrack = wsTrack.Cells(wsTrack.Rows.Count, "A").End(xlUp).Row
aOld() = wsTrack.Range("A2:A" & lngTrack).Value
aNew() = wsTrack.Range("B2:B" & lngTrack).Value
lngRow = 1
For lngLoop1 = 2 To lngLastRow
If wsIn.Cells(lngLoop1, 1) = "y" Then
For lngLoop2 = LBound(aOld) To UBound(aOld)
wsOut.Cells(lngRow, aNew(lngLoop2, 1)) = wsIn.Cells(lngLoop1, aOld(lngLoop2, 1))
Next lngLoop2
lngRow = lngRow + 1
End If
Next lngLoop1
sExit:
On Error Resume Next
Set wsIn = Nothing
Set wsOut = Nothing
Set wsTrack = Nothing
Exit Sub
E_Handle:
MsgBox Err.Description & vbCrLf & vbCrLf & "sTransferData", vbOKOnly + vbCritical, "Error: " & Err.Number
Resume sExit
End Sub
Regards,

Excel VBA Range for all relevant cells

My macro creates a large text file by writing all the data from all sheets in the active workbook.
In each worksheet, it is necessary to determine a certain rectangular range of cells that would be saved in the text file. It's upper left corner would always be A1, but the lower right corner should be chosen so that the range includes all cells with any content (formatting does not matter).
I thought ws.Range("A1").CurrentRegion would do the trick, but it does not work when A1 and the nearby cells are empty. If the only cell with data in the sheet is Q10, then the range should be A1:Q10.
Of course, I could loop over the ws.Cells range to discover the range of interest, but that's quite time consuming, I hope there's more effective way. If I select all cells in a sheet and do a copy-paste to notepad, I do not end up with hundreds of empty columns and thousands of empty rows, only the relevant data are copied. The question is how to replicate that with VBA.
This is my code so far:
Sub CreateTxt()
'This macro copies the contents from all sheets in one text file
'Each sheet contents are prefixed by the sheet name in square brackets
Dim pth As String
Dim fs As Object
Dim rng As Range
pth = ThisWorkbook.Path
Set fs = CreateObject("Scripting.FileSystemObject")
Dim outputFile As Object
Set outputFile = fs.CreateTextFile(pth & "\Output.txt", True)
Dim WS_Count As Integer
Dim ws As Worksheet
Dim I As Integer
WS_Count = ActiveWorkbook.Worksheets.Count
For I = 1 To WS_Count
Set ws = ActiveWorkbook.Worksheets(I)
outputFile.WriteLine ("[" & ws.Name & "]")
Debug.Print ws.Name
Set rng = ws.Range("A1").CurrentRegion
outputFile.WriteLine (GetTextFromRangeText(rng, vbTab, vbCrLf))
Next I
outputFile.Close
End Sub
Function GetTextFromRangeText(ByVal poRange As Range, colSeparator As String, rowSeparator As String) As String
Dim vRange As Variant
Dim sRow As String
Dim sRet As String
Dim I As Integer
Dim j As Integer
If Not poRange Is Nothing Then
vRange = poRange
Debug.Print TypeName(vRange)
For I = LBound(vRange) To UBound(vRange)
sRow = ""
For j = LBound(vRange, 2) To UBound(vRange, 2)
If j > LBound(vRange, 2) Then
sRow = sRow & colSeparator
End If
sRow = sRow & vRange(I, j)
Next j
If sRet <> "" Then
sRet = sRet & rowSeparator
End If
sRet = sRet & sRow
Next I
End If
GetTextFromRangeText = sRet
End Function
if there is anything in A1:B2 cells, this macro works. It breaks when the A1:B2 is empty and the CurrentRegion property returns Empty.
I think you should use these functions to find the last Row/Column
lastRow = Sheets("Sheetname").Cells(Rows.Count, 1).End(xlUp).Row
lastCol = Sheets("Sheetname").Cells(1, Columns.Count).End(xlToLeft).Column
You specify the name of the sheet and the row/columb-number that you want to find the last cell with information, and it return the number of it.
(In the example the last row in first column, and last column in first row are find)
lastCol will give you an Long as an asnwer. If you want to convert this number into the column letter you can use the next function
Function Col_Letter(lngCol As Long) As String
Dim vArr
vArr = Split(Cells(1, lngCol).Address(True, False), "$")
Col_Letter = vArr(0)
End Function
I hope you find this useful
Thanks to user Rosetta, I've come up with this expression for the sought range:
ws.Range("A1:" & ws.Cells.SpecialCells(xlLastCell).Address)

Resources