Rename tabs based on cell value on different tab - excel

I have a workbook that has 14 tabs. I want to rename 4 of the tabs. The tabs to be renamed will use cell values on a different tab that contain no illegal characters or length restrictions.
I researched but only found where the cell values are in the same spot on each workbook.
If the cell value is blank or 0, I want to hide the tab.
Worksheets to be renamed:
Summary 1
Summary (2)
Summary (3)
Summary (4)
Worksheet with cell values for renaming:
Overall Summary
cell A24 for Summary 1
cell A25 for Summary (2)
cell A26 for Summary (3)
cell A27 for Summary (4)

Sheets("Summary 1").Name = Sheets("Overall Summary").Range("A24").Value
Etc...
For the cells that have blanks, you'll have to be careful with hide because you might have more than one.
Example:
If Sheets("Overall Summary").Range("A24").Value = <> then
For Each ws In ThisWorkbook.Worksheets
If InStr(1, ws.Name, "Hide_", vbTextCompare) Then
i = i + 1
End If
Next ws
Sheets("OldName").Name = "Hide_" & i
End If

This one will hopefully do what you're looking for.
It looks through each sheet in the ActiveWorkbook and if the name contains "Summary" it will move down into column A of the "Overall Summary" sheet and attempt to grab the new name you want to add.
If the cell it’s looking at in "Overall Summary" is 0 or blank, it will rename that summary sheet to "Hide X" but note that it could just hide the sheets for you instead :)
Sub RenameSummary()
Dim objRegex
Set objRegex = CreateObject("vbscript.regexp")
Dim offset As Long
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
If InStr(LCase$(ws.name), "summary") > 0 Then
With objRegex
.Global = True
.Pattern = "[^\d]+"
offset = CLng(.Replace(ws.name, vbNullString))
End With
With sheets("Overall Summary").Range("A" & (23 + offset))
If Len(.Value2) = 0 Or .Value2 = 0 Then
ws.name = "HIDE " & .row
'ws.Visible = xlSheetHidden 'can directly hide sheet
Else
ws.name = .Value2
End If
End With
End If
Next ws
End Sub

You could try this
Sub Trythis()
Dim cell As Range
For Each cell in Worksheets("Overall Summary").Range("A24:A27") ‘ loop through relevant range of “Overall Summary” sheet
If Not IsEmpty(cell) And cell.Value <> 0 Then ‘ if current cell isn’t neither empty nor zero
Select Case cell.Row ‘check for current cell value and act accordingly
Case 24
Sheets("Summary 1").Name = cell.Value
Case 25
Sheets("Summary (2)").Name = cell.Value
Case 26
Smeets("Summary (3)").Name = cell.Value
Case 27
Sheets("Summary (4)").Name = cell.Value
End Select
End If
Next
End Sub

Related

Is there a way to identify if a worksheet has a highlighted cell at a worksheet level, without checking all the cells?

Is there a way to identify if a worksheet has a highlighted cell at a worksheet level, without checking all the cells?
Further context:
I have a WorkBook with a number of Worksheets(ws).
some of the worksheets have cells that are highlighted.
I want to be able to take out the worksheets that have a cell highlighted and put them in another workbook.
But the way I do it is, I go through each cell in each worksheet to find a highlighted cell, and when I find one, I copy this worksheet to another workbook and move on to the next work sheet.
But the more ws there are the longer this takes and because I have to go through individual cells.
So my questions is, Is there a way to identify if a worksheet has a highlighted cell at a worksheet level? Or do I have to go through each cell range in each worksheet?
Code
' copy the path from cell a1 to the master in a1, a2, a3.....
' want to add to copy the WS if it has a highlighted area
' added copy ws with highlight to new WB and exit for loop for checking more highlighted areas
' this works C:\Samsung\Macros\test_macro_test3.xlsm, see cloumn A in master sheet and have Summary.xlsm WB open
Sub test3()
Dim startTime, endTime As Date
startTime = Now
Dim ws As Worksheet, MainWs As Worksheet, cell As Range
Set MainWs = Sheets("master") '<-- change name as needed
Dim i As Integer
i = 1
For Each ws In Sheets
If ws.Name <> MainWs.Name Then
For Each cell In ws.UsedRange
Debug.Print "ws.Name:" & ws.Name
Debug.Print "cell.Address:" & cell.Address
Debug.Print "cell.Value:" & cell.Value
Debug.Print "i:" & i
'if your cells are colored through conditional formatting, delete/comment below line & uncomment the line after
If cell.Interior.Color = vbYellow Then
MainWs.Range("A" & i) = ws.Range("A1").Value
MainWs.Range("B" & i) = ws.Name
ws.Copy After:=Workbooks("Summary.xlsm").Sheets(Workbooks("Summary.xlsm").Sheets.Count)
Exit For
'If cell.DisplayFormat.Interior.Color = vbYellow Then MainWs.Range(cell.Address) = cell.Value
Debug.Print "cell.Address:" & cell.Address
Debug.Print "cell.Value:" & cell.Value
Debug.Print "i:" & i
Exit For
End If
Next
End If
i = i + 1
Next 'next worksheet
endTime = Now
Debug.Print "startTime:" & startTime
Debug.Print "endTime: " & endTime
Debug.Print "Total(hh:mm:ss)" & Format((DateDiff("s", startTime, endTime)) / 86400, "hh:mm:ss")
End Sub
WB examples
https://www.dropbox.com/scl/fi/7x91vwbvv62nn15loczpy/test_macro_test3.xlsm?dl=0&rlkey=k8b53wizejaf4jqwjzilthvg2
https://www.dropbox.com/scl/fi/8c5uatqyhlwlv5pzcude7/Summary.xlsm?dl=0&rlkey=fodf1j7ic7ac5pl9coehnlhab
You can use the following function to check if a worksheet has cells with a certain background color:
Public Function hasSheetHighlightedCells(ws As Worksheet, _
Optional lngColor As Long = vbYellow) As Boolean
Application.FindFormat.Clear
Application.FindFormat.Interior.color = lngColor
Dim rgFound As Range
On Error Resume Next 'in case nothing can be found
Set rgFound = ws.UsedRange.Find("*", searchFormat:=True)
On Error GoTo 0
If Not rgFound Is Nothing Then
hasSheetHighlightedCells = True
End If
Application.FindFormat.Clear
End Function
You will call that function within your For each ws in Sheets loop:
If hasSheetHighlightedCells(ws) = true then
This will check for the default color vbYellow.
If you want to check for a different color you can use e.g.
If hasSheetHighlightedCells(ws, vbRed) = true then

Create a Do While loop to scan a column until no value is found in VBA

I worked on the top portion of this last week and that doesn't need anything aside from some formatting on my end. The bottom portion with the block style comments are where I am stuck. (below wks.Activate is new)
I am trying to set a do while loop that sequentially reads through a given column until no value is present, then copy the row above and paste the formatting into the blank row.
There are a couple other problems, but I'm just concerned with base functionality at the moment.
The code I have put together so far is as follows:
Public Sub AddNewPage()
Sheets(Sheets.Count).Select 'references last sheet in workbook
Dim wks As Worksheet 'establish static variable wks to reference worksheets
Dim nullVal As Boolean 'set a boolean variable for value check
Dim i As Integer 'set variable as integer for coming loop
Set wks = ActiveSheet 'set wks to be the given, activated sheet (dynamic variable)
ActiveSheet.Copy After:=Worksheets(Sheets.Count) 'sets the last sheet in the workbook as the active sheet and copies it
Range("H9").Value = Range("H9").Value + 1 'sets value of cell H9 in new worksheets to sequentially increase by 1
If wks.Range("H9").Value <> "" Then 'If cell "H9" in activated worksheet has a value then...
On Error Resume Next 'Proceed even if I beak stuff
wks = Sheets(Sheets.Count).Select 'sets wks to reference last sheet in given workbook
ActiveSheet.Name = wks.Range("H9").Value + 1 'sets page title to sequentially increase by 1 with each iteration
End If
wks.Activate
Application.Worksheets("Log").Activate 'redirect to primary sheet used for tracking workbook data
Do While nullVal = False 'establishing a do while loop to scan cells until no value is found
For i = 1 To 1000 '*************************
If Cells(i, 1).Value <> "" Then '*This is my problem
nullVal = False '*area, I think.
i = i + 1 '*
Else: nullVal = True '*The goal is to create
End If '*a do while loop that
Next i '*scans cells in the given
'*column until no value
If nullVal = True Then Exit Do '*is found and copy the
If nullVal = True Then Exit Sub '*above row's formatting
'*into the blank row.
Loop '*(see below)
'*************************
If nullVal = True Then
wks.Cells(i, 1).End(xlUp).Offset(1, 0).Select '**********************************
Rows(Selection.Row - 1).Copy '*Another minor bug in here as it
Rows(Selection.Row).Insert Shift:=xlDown '*won't necessarily select the last
Rows(Selection.Row).ClearContents '*row if the user is in the sheet
Application.CutCopyMode = False
End If
End Sub
It's somewhat functional at this point, with bugs.
Any other sets of eyes and any depth of knowledge would be appreciated as I just started learning this... thing (VBA) and I've been working on and off with this for days now.
I am curious as to whether an array or table might serve me well here.
I'm not sure by saying copy the format to the empty [row] means the entire row or just the empty cell?
For you loop struct
Dim vItem As Variant
For Each vItem In Selection
If vItem.Value = "" Then
vItem.Activate
ActiveCell.Offset(-1, 0).Copy
ActiveCell.PasteSpecial xlPasteFormats
Exit Sub
End If
Next vItem
This will format the empty cell by the format of the cell immediately above it.
Is this what you want?
Public Sub AddNewPage()
Sheets(Sheets.Count).Select 'references last sheet in workbook
Dim wks As Worksheet 'establish static variable wks to reference worksheets
Dim nullVal As Boolean 'set a boolean variable for value check
Dim i As Integer 'set variable as integer for coming loop
Set wks = ActiveSheet 'set wks to be the given, activated sheet (dynamic variable)
Dim iRange As Range
Dim iCells As Range
ActiveSheet.Copy After:=Worksheets(Sheets.Count) 'sets the last sheet in the workbook as the active sheet and copies it
Range("H9").Value = Range("H9").Value + 1 'sets value of cell H9 in new worksheets to sequentially increase by 1
If wks.Range("H9").Value <> "" Then 'If cell "H9" in activated worksheet has a value then...
On Error Resume Next 'Proceed even if I beak stuff
wks = Sheets(Sheets.Count).Select 'sets wks to reference last sheet in given workbook
ActiveSheet.Name = wks.Range("H9").Value + 1 'sets page title to sequentially increase by 1 with each iteration
End If
wks.Activate
Application.Worksheets("Log").Activate 'redirect to primary sheet used for tracking workbook data
Do While nullVal = False 'establishing a do while loop to scan cells until no value is found
For i = 1 To Sheets(Sheet.Count).Value 'Makes the book functional, but because I have an index page and a master template I have compensate with "- 2" in the subsequent code
If Cells(i, 1).Value > "" Then 'If cells in defined column have positive value, adhere to the following
nullVal = False
Else: nullVal = True
End If
Next i 'Psuedo ++ style operator
If nullVal = True Then
Cells(i - 1, 1) = i - 2 'Floating variable which sets numeric value of a given cell to coincide with page count
End If
Loop
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'The following makes use of the floating variable "i - 2" to
'define the page number for the given formulas
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Cells(i - 1, 1).Select 'Creates a hyperlink to sheets as they are being created
ActiveCell.Formula = "=('" & i - 2 & "'!H9)"
Sheets("Log").Cells(i - 1, 1).Hyperlinks.Add Selection, Address:="", SubAddress:="'" & Sheets(Sheets.Count).Name & "'!H9", TextToDisplay:=""
Cells(1, 1).Select 'Solves the issue of replacing descriptor in cell (1, 1)
Sheets("Log").Cells(1, 1).Hyperlinks.Add Selection, Address:="", SubAddress:="", TextToDisplay:="EWA #"
Cells(i - 1, 2).Select
ActiveCell.Formula = "=('" & i - 2 & "'!A12)"
Cells(i - 1, 3).Select
ActiveCell.Formula = "=('" & i - 2 & "'!H24)"
Cells(i - 1, 4).Select
ActiveCell.Formula = "=('" & i - 2 & "'!H25)"
Cells(i - 1, 5).Select
ActiveCell.Formula = "=('" & i - 2 & "'!D29)"
Cells(i - 1, 6).Select
ActiveCell.Formula = "=('" & i - 2 & "'!E29)"
Cells(i - 1, 7).Select
ActiveCell.Formula = "=('" & i - 2 & "'!H42)"
Cells(i - 1, 1).EntireRow.RowHeight = 50 'Row width formatting for new data
Cells(i - 1, 1).Select 'Moving back to the top of the page
End Sub
That is what I was trying to get to, took a bit and I'm still not completely familiarized with VBA. If anyone has any insightts on how to clean it up a bit I'm all ears.
I would like to find a way to create a page from the base master template, called "master," have the created page populate with the name "1" and populate the index page with a 1 as well while no values are present.

Replacing formulas in multiple sheets with the different values based on a different sheet VBA

My current code creates 9 copies of a sheet called "MasterCalculator". It decides the amount of copies to be named by counting the number of cells filled in Row 1 (starting at column C) in the other sheet Called 'LLP Disc Sheet'. Each of the 9 sheets created are then named. Sheet 1's name comes from C1 in the 'LLP Disc Sheet', Sheet 2's name comes from D1 in the 'LLP Disc Sheet', Sheet 3's names comes from E1 in the 'LLP Disc Sheet', and so on.
Option Explicit
Public Sub NewSheets()
Dim shCol As Integer
Dim i As Integer
Dim ws As Worksheet
Dim sh As Worksheet
Set ws = Sheets("MasterCalculator")
Set sh = Sheets("LLP Disc Sheet")
Application.ScreenUpdating = 0
Application.EnableEvents = 0
shCol = 2
sh.Activate
For i = 2 To sh.Range("A1:Z1").Cells.SpecialCells(xlCellTypeConstants).Count
shCol = shCol + 1
Application.StatusBar = "Processing " & sh.Cells(1, shCol).Text & Format(i / sh.Range("A1:Z1").Cells.SpecialCells(xlCellTypeConstants).Count, " #0.0 %")
Select Case shCol
Case Is = 3
ws.Copy After:=sh
Case Else
ws.Copy After:=Sheets(sh.Cells(1, shCol - 1).Text)
End Select
ActiveSheet.Name = sh.Cells(1, shCol).Text
Application.CutCopyMode = False
Next i
sh.Activate
Application.StatusBar = 0
Application.EnableEvents = 1
Application.ScreenUpdating = 1
Application.CalculateFull
End Sub
So now that all the sheets are created and named... I now want to update the formulas in each since they're copies of the sheet called 'MasterCalculator'. There are 2 cells in each sheet I need to update - cell B1 and cell M4. Cell B1 contains the formula "=+'LLP Disc Sheet'!C1". The sheet that was created based on C1 in the 'LLP Disc Sheet' can keep this formula. However, the next sheet (sheet 2) that was created and named based off of D1 in the "LLP Disc Sheet" needs to be updated to "=+'LLP Disc Sheet'!D1". This goes on with the rest of the sheets. The next has to change to =+'LLP Disc Sheet'!E1 and so on. How do I create a code to replace that cell in each of the newly created sheet with an updated formula that only changes it to cell referenced one cell after in the 'LLP Disc Sheet'?
ActiveSheet.Range(“B1:M4”).Replace_
What: ="LLP Disc Sheet'!C1", Replacement:="LLP Disc Sheet'!D1”,_ ‘but I want it to continue to the next sheet to replace D1 with E1 and so on until all of the B1 cells match their sheet names (it also allow all the data to be filled in). All of these will be found in cell B1 in the MasterCalculator copies
What: ="LLP Disc Sheet'!$C$1:$C$", Replacement:=" LLP Disc Sheet'!$D$1:$D$”,_ ‘but I want it to continue to the next sheet to replace $D$1 with E$1$ and $D$ with $E$ and so on until all of the M4 cells are set to 0.
SearchOrder:=xlByRows, MatchCase:=True
Use formulaR1C1
Option Explicit
Public Sub NewSheets()
Dim wb As Workbook, ws As Worksheet, wsMaster As Worksheet
Dim iLastCol As Integer, iCol As Integer
Dim s As String, n As Integer
Set wb = ThisWorkbook
Set wsMaster = wb.Sheets("MasterCalculator")
Set ws = wb.Sheets("LLP Disc Sheet")
iLastCol = ws.Cells(1, Columns.Count).End(xlToLeft).Column
n = wb.Sheets.Count
For iCol = 3 To iLastCol
s = ws.Cells(1, iCol) ' sheet name
If Len(s) > 0 Then
wsMaster.Copy After:=Sheets(n)
n = n + 1
wb.Sheets(n).Name = s
wb.Sheets(n).Range("B1,M4").FormulaR1C1 = "='" & ws.Name & "'!R1C" & iCol
End If
Next
MsgBox iLastCol - 2 & " sheets added", vbInformation
End Sub

Using VBA in Excel to share cell vales between sheets to populate data in cells

Updated Question
I have a VBA script attached to sheet 1 that uses the B5:B50 cell values to populate the adjacent column with pre-defined text. If I want to use this script in another sheet, but still use the B5:B50 cell values of the previous sheet. How to I do that?
For Example:
In sheet 1, If I enter the value of 2 in the cell B5, it will populate D5 and E5 with the text value attached to CONST TXT. I want to do the same thing in sheet 2, but instead of the user entering the value again into B5 of sheet 2, it just gets the value of B5 from the previous sheet and then populate D5 and E5.
Sheet 2 B values will need to update as soon as the B values are updated in Sheet 1.
Private Sub Worksheet_Change(ByVal Target As Range)
Const NUM_COLS As Long = 5
Const TXT = "• Course Name:" & vbNewLine & _
"• No. Of Slides Affected:" & vbNewLine & _
"• No. of Activities Affected:"
Dim rng As Range, i As Long, v
If Target.CountLarge <> 1 Then Exit Sub
If Not Intersect(Target, Me.Range("B5:B50")) Is Nothing Then
Set rng = Target.Offset(0, 2).Resize(1, NUM_COLS) 'range to check
v = Target.Value
If IsNumeric(v) And v >= 1 And v <= NUM_COLS Then
For i = 1 To rng.Cells.Count
With rng.Cells(i)
If i <= v Then
'Populate if not already populated
If .Value = "" Then .Value = TXT
Else
'Clear any existing value
.Value = ""
End If
End With
Next i
Else
rng.Value = "" 'clear any existing content
End If
End If
End Sub
As I understand you, you want something like an equivalent of offset which returns a range on a different sheet. There are a couple of options.
You can use Range.AddressLocal, which returns the address of Range without any worksheet or workbook qualifiers, and then apply this to the other worksheet:
'returns a cell 1 to the right of rng, but on Sheet2
Worksheets("Sheet2").Range(rng.Offset(0, 1).AddressLocal)
Or you can get the Row and Column properties of your range and use them in Cells in the other worksheet:
'returns a cell 1 to the right of rng, but on Sheet2
Worksheets("Sheet2").Cells(rng.Row, rng.Column + 1)
To use it in your code, I think it's just a case of replacing
If .Value = "" Then .Value = TXT
with
If Worksheets("Sheet2").Range(.Offset(0, 1).AddressLocal).Value = "" Then Worksheets("Sheet2").Range(.Offset(0, 1).AddressLocal).Value = TXT
and replacing
.Value = ""
with
Worksheets("Sheet2").Range(.Offset(0, 1).AddressLocal).Value = ""
(or the same using the Cells construction).
The below will copy the Target.Value into the same cell in Sheet2
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ws1 As Worksheet, ws2 As Worksheet
Set ws2 = ThisWorkbook.Worksheets("Sheet2")
If Not Intersect(Target, Me.Range("B5:B50")) Is Nothing And Target.Count = 1 Then
With Target
ws2.Cells(.Row, .Column).Value = .Value
End With
End If
End Sub

Get start range and end range of a vertically merged cell with Excel using VBA

I need to find out the first cell and the last cell of a vertically merged cell..
Let's say I merge Cells B2 down to B50.
How can I get in VBA the start cell(=B2) and the end cell(=B50)?
Sub MergedAreaStartAndEnd()
Dim rng As Range
Dim rngStart As Range
Dim rngEnd As Range
Set rng = Range("B2")
If rng.MergeCells Then
Set rng = rng.MergeArea
Set rngStart = rng.Cells(1, 1)
Set rngEnd = rng.Cells(rng.Rows.Count, rng.Columns.Count)
MsgBox "First Cell " & rngStart.Address & vbNewLine & "Last Cell " & rngEnd.Address
Else
MsgBox "Not merged area"
End If
End Sub
Below macro goes through all sheets in a workbook and finds merged cells, unmerge them and put original value to all merged cells.
This is frequently needed for DB applications, so I wanted to share with you.
Sub BirlesenHucreleriAyirDegerleriGeriYaz()
Dim Hucre As Range
Dim Aralik
Dim icerik
Dim mySheet As Worksheet
For Each mySheet In Worksheets
mySheet.Activate
MsgBox mySheet.Name & “ yapılacak…”
For Each Hucre In mySheet.UsedRange
If Hucre.MergeCells Then
Hucre.Orientation = xlHorizontal
Aralik = Hucre.MergeArea.Address
icerik = Hucre
Hucre.MergeCells = False
Range(Aralik) = icerik
End If
Next
MsgBox mySheet.Name & " Bitti!!"
Next mySheet
End Sub
Suppose you merged B2 down to B50.
Then, start cell address will be:
MsgBox Range("B2").MergeArea.Cells(1, 1).Address
End cell address will be:
With Range("B2").MergeArea
MsgBox .Cells(.Rows.Count, .Columns.Count).Address
End With
You can put address of any cell of merged area in place of B2 in above code.
Well, assuming you know the address of one of the cells in the merged range, you could just select the offset from that range and get the row/column:
Sub GetMergedRows()
Range("A7").Select 'this assumes you know at least one cell in a merged range.
ActiveCell.Offset(-1, 0).Select
iStartRow = ActiveCell.Row + 1
Range("A7").Select
ActiveCell.Offset(1, 0).Select
iEndRow = ActiveCell.Row - 1
MsgBox iStartRow & ":" & iEndRow
End Sub
The code above will throw errors if the offset row cannot be selected (i.e. if the merged rows are A1 through whatever) so you will want to add error handling that tells the code if it can't offset up, the top rows must be 1 and if it can't go down, the bottom row must be 65,536. This code is also just one dimensional so you might want to add the x-axis as well.
If you want the cell references as strings, you can use something like this, where Location, StartCell, and EndCell are string variables.
Location = Selection.Address(False, False)
Colon = InStr(Location, ":")
If Colon <> 0 Then
StartCell = Left(Location, Colon - 1)
EndCell = Mid(Location, Colon + 1)
End If
If you want to set them as ranges, you could add this, where StartRange and EndRange are Range objects.
set StartRange = Range(StartCell)
set EndRange = Range (EndCell)
If you intend to loop through the merged cells, try this.
Sub LoopThroughMergedArea()
Dim rng As Range, c As Range
Set rng = [F5]
For Each c In rng.MergeArea
'Your code goes here
Debug.Print c.Address'<-Sample code
Next c
End Sub

Resources