Updating ActiveWorkbook.Names("X").RefersTo and Names.Value in VBA - vba

I have some code that currently looks through the sheet for any cell that I have filled with a light grey, and then adds the value within that cell to a Names list. The goal being that somewhere else in the workbook I can reference this list as a drop down.
Here's my current code:
Sub Add_Food_To_List()
i = 1
Application.ScreenUpdating = False
Range("a1:a60").Select
x = "{"
y = ""
first = True
For Each Cell In Selection
If ActiveCell.Interior.ColorIndex = "2" Then
i = i + 1
If first = False Then
x = x & ", " & ActiveCell.Value
y = y & ", " & ActiveCell.Address
End If
If first Then
x = x & ActiveCell.Value
y = y & ActiveCell.Address
first = False
End If
ActiveWorkbook.Names("Foods").RefersTo = y
ActiveWorkbook.Names("Foods").Value = x
End If
ActiveCell.Offset(1, 0).Select
Next Cell
Range("a1").Select
Application.ScreenUpdating = True
End Sub
For some reason these two lines within the For Each Cell In Selection:
ActiveWorkbook.Names("Foods").RefersTo = y
ActiveWorkbook.Names("Foods").Value = x
overwrite each other. Whichever goes last ends up as the value that both RefersTo AND Value are set to in the name.
Bonus: This is my first VBA script. How can I get this script to run on the entire workbook, not just the active sheet? Also, how do I make it run automatically on save, or on workbook update?

Perhaps this will serve you better:
Create a Worksheet in your Workbook with the name Reference.
Type Foods in cell A1 and put at least one random food in cell A2.
Create a defined name of Foods with the following formula: =offset(A2,0,0,counta(A:A)-1,1) This is a Dynamic Named Ranges that will expand or contract as rows are added or deleted (just be sure there are no blank rows in between data).
Place the below code in the ThisWorkbook module in the VBE. The below code will run right before the Workbook saves. It will loop through each sheet and add the values of any cells highlighted grey in Range(A1:A60) to the rowset in column A of the Reference Worksheet directly underneath the existing rowset.
Code for Module:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Application.ScreenUpdating = False
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
If ws.Name <> "Reference" Then
With ws
Dim rCell As Range
For Each rCell In .Range("a1:a60")
If rCell.Interior.ColorIndex = "2" Then
Dim wsRef As Worksheet
Set wsRef = Sheets("Reference")
If wsRef.Range("Foods").Find(rCell.Value, lookat:=xlWhole) Is Nothing Then
wsRef.Range("A" & wsRef.Rows.Count).End(xlUp).Offset(1).Value = rCell.Value2
End If
End If
Next
End With
End If
Application.ScreenUpdating = True
End Sub

Related

How to capture data to a specified excel sheet(first workbook) from two different workbooks from the Userform?

I have workbook-1 where the data should be actually captured from the userform when add button is clicked.
In workbook-2 I just have my combobox list inorder to display the excel data when selected from the comobox and textbox automatically in the userform.
But now I am facing a problem, when I fill the userform by selecting all combobox list and filling other data manually then clicked on add button the data is trasferring to my Workbook-2 (below my combobox list).
How to capture the userform data to my workbook-1 on Sheetname "Sheet1".
My Workbook-2 path is "C:\Users\Desktop\Work.xlmx", will I need to include this path also for the commandbutton?
Below is my code of combox and add commandbutton:
Private Sub cboLs_DropButtonClick()
Dim wb As Workbook 'workbook 2 for combobox list
Dim i As Long
Dim ssheet As Worksheet
Set wb = Workbooks.Open("C:\Users\Desktop\Book1.xlsx")
Set ssheet = wb.Worksheets("LS")
If Me.cboLs.ListCount = 0 Then
For i = 2 To ssheet.Range("A" & ssheet.Rows.Count).End(xlUp).Row
Me.cboLs.AddItem Sheets("LS").Cells(i, "A").Value
Next i
End If
End Sub
Private Sub cboLs_Change()
Dim wb As Workbook
Dim ssheet As Worksheet
Dim i As Long
Set wb = Workbooks.Open("C:\Users\Desktop\Book1.xlsx")
Set ssheet = wb.Worksheets("LS")
For i = 2 To ssheet.Range("A" & ssheet.Rows.Count).End(xlUp).Row
If ssheet.Cells(i, "A").Value = (Me.cboLs) Or ssheet.Cells(i, "A").Value = Val(Me.cboLs) Then
Me.txtProject = ssheet.Cells(i, "B").Value
End If
Next i
End Sub
Private Sub cmdadd_Click()
Dim e As Long
Dim Sheet1 As String
Worksheets(Sheet1).Activate 'Workbook-1 here i need to capture my userform data but it is going to workbook-2 on sheetname LS
'position cursor in the correct cell A6.
ActiveSheet.Range("A6").Select
e = 1 'set as the first ID
'if all the above are false (OK) then carry on.
'check to see the next available blank row start at cell A6...
Do Until ActiveCell.Value = Empty
ActiveCell.Offset(1, 0).Select 'move down 1 row
e = e + 1 'keep a count of the ID for later use
Loop
'Populate the new data values into the 'Data' worksheet.
ActiveCell.Value = e 'Next ID number
ActiveCell.Offset(0, 2).Value = Me.txtname.Text 'set col B
ActiveCell.Offset(0, 3).Value = Me.txtbook.Text 'set col C
ActiveCell.Offset(0, 1).Value = Me.cboLs.Text 'set col D
Me.txtname.Text = Empty
Me.txtbook.Text = Empty
Me.cboLs.Text = Empty
End Sub
In your code, I never see you setting the value of the Sheet1 string variable.
Please note it is not required to activate a worksheet in order to work with it. Likewise, it is not required a select a cell. Try something like this...
Private Sub cmdadd_Click()
Dim e As Long
Dim destSheet As Worksheet
Set destSheet = Worksheets("Sheet1")
ActiveSheet.Range("A6").Select
e = 1 'set as the first ID
'if all the above are false (OK) then carry on.
'check to see the next available blank row start at cell A6...
Do Until ActiveCell.Value = Empty
ActiveCell.Offset(1, 0).Select 'move down 1 row
e = e + 1 'keep a count of the ID for later use
Loop
'Populate the new data values into the 'Data' worksheet.
destSheet.Range("A6").Value = e 'Next ID number
destSheet.Range("B6").Value = Me.txtname.Text 'set col B
destSheet.Range("C6").Value = Me.txtbook.Text 'set col C
destSheet.Range("D6").Value = Me.cboLs.Text 'set col D
Me.txtname.Text = Empty
Me.txtbook.Text = Empty
Me.cboLs.Text = Empty
End Sub
Likewise, use the same approach for your loop to get your desired value of e. By the way, if you are just looking for the value of the last populated row in column A, instead of looping (which is inefficient for this purpose), you can do use
destSheet.Cells(destSheet.Rows.Count, "A").End(xlUp).Value
This is the same as going to the last cell at the bottom of column A and pressing CTRL+Up to go to the last populated cell. Then you can just add 1 to that value.
In the sub cmdadd_Click, the second workbook is still active. Therefore before Worksheets(‘Sheet1’).Activate add:
Dim wb As Workbook
Dim ssheet As Worksheet
Set wb = Workbooks.Open("C:\Users\Desktop\Work.xlmx")
Set ssheet = wb.Worksheets("Sheet1")
Like you did in the other subs. Next add the following before worksheets(‘sheet1”):
wb.activate
ssheet.activate
Delete these lines from your sub:
Dim Sheet1 As String
Worksheets(Sheet1).Activate
This should do the trick.

Setting range on different sheet causing error

I am fairly new to VBA and Wondering if someone can help me out.
I have 2 different sheets in a workbook.
Sheet(Raw Data) has a range with Cost Center NameS (Cell BC3 down to empty)
I have to copy Sheet(CC Template) and name it the right 5 characters of Sheet(Raw Data).Range(BC3).Value and change Cell(2,2).value to Sheet(Raw Data).Range(BC3).Value...
Then I want it to go to the next cell in Sheet(Raw Data) ...BC4 and create the second sheet and change the name and Cell(2,2) accordingly until the list in Sheet(Raw Data) ends.
Here is my Code. It creates the first worksheet but then I get run-time Error '1004' at Sheets("Raw Data").Range("BC3").Select in the do until loop. I would like to get rid of X and CCName variable from the code also if possible.
Sub CreateCCTabsinNewPlantFile2()
Dim i As Integer
Dim x As Integer
Dim CCName As String
i = ActiveWorkbook.Worksheets.Count
x = 1
' Select cell BC3, *first line of data*.
Sheets("Raw Data").Range("BC3").Select
' Set Do loop to stop when an empty cell is reached.
Do Until IsEmpty(ActiveCell)
CCName = ActiveCell.Value
' Code to make worksheets
Worksheets("CC Template").Copy after:=Worksheets(i)
ActiveSheet.Name = Right(CCName, 5)
ActiveSheet.Cells(2, 2).Value = CCName
' Step down 1 row from present location.
Sheets("Raw Data").Range("BC3").Select
ActiveCell.Offset(x, 0).Select
x = x + 1
Loop
End Sub
Sub CreateCCTabsinNewPlantFile2()
Dim i As Integer
Dim X As Integer
X = 3 'Starting row in Sheet("Raw Data")
With ThisWorkbook.Sheets("Raw Data")
Do Until .Cells(X, 55).Value = "" 'cells(x,55)= BC3. First time x= 3 so Cells(3,55)=BC3
i = ThisWorkbook.Worksheets.Count 'we update count everytime, because we are adding new sheets
ThisWorkbook.Worksheets("CC Template").Copy after:=ThisWorkbook.Worksheets(i)
ThisWorkbook.ActiveSheet.Name = Right(.Cells(X, 55).Value, 5)
ThisWorkbook.ActiveSheet.Cells(2, 2).Value = .Cells(X, 55).Value
' We increade X. That makes check a lower rower in next loop.
X = X + 1
Loop
End With
End Sub
Hope this helps.
You get error1004 because you can use Range.Select only in Active Sheet. If you want to Select a Range in different Sheet, first you must Activate that sheet with Sheets("Whatever").Activate.
Also, I Updated your code so you can execute it from any sheet. Your code forces user to have Sheets ("Raw Data") as the ActiveSheet.
Try not use too much Select if you can avoid it. And also , try to get used to Thisworkbook instead of ActiveWorkbook. If you work always in same workbook, is not a problem, but if your macros operate several workbooks, you'll need to difference when to use each one.
Try this code
Sub Test()
Dim rng As Range
Dim cel As Range
With Sheets("Raw Data")
Set rng = .Range("BC3:BC" & .Cells(Rows.Count, "BC").End(xlUp).Row)
End With
Application.ScreenUpdating = False
For Each cel In rng
If Not SheetExists(cel.Value) Then
Sheets("CC Template").Copy After:=Sheets(Sheets.Count)
With ActiveSheet
.Name = Right(cel.Value, 5)
.Range("B2").Value = cel.Value
End With
End If
Next cel
Sheets("Raw Data").Activate
Application.ScreenUpdating = True
End Sub
Function SheetExists(sheetName As String) As Boolean
On Error Resume Next
SheetExists = (LCase(Sheets(sheetName).Name) = LCase(sheetName))
On Error GoTo 0
End Function

(Excel) How Can I Add Worksheet Name as Prefix for Each Column Header?

I have a header that starts in Column E and might go on for 100+ columns.
I am trying to change each column header to add a prefix (the name of the "tab" aka. worksheet) (ie. if Worksheet is called 'Beverage', I'd like each column header to be prefixed with "Beverage -")
I will be running script across multiple sheets, so am trying to find a way to reference the current sheet name.
Before: (For Worksheet "Beverage")
After: (For Worksheet "Beverage". Note: Columns don't need to be resized, just did it to demonstrate)
I've tried adapting code from this thread, however I can't get it to work.
Here is the code I have so far (non-working):
Sub Worksheet_Name_Prefix()
Dim columnNumber As Long, x As Integer
Dim myTab As ListObject
Set myTab = ActiveSheet.ListObjects(rows.Count, 1)
For x = 5 To rows.Count ' For Columns E through last header cell with value
columnNumber = x
myTab.HeaderRowRange(1, columnNumber) = ActiveSheet.Name
Next x
End Sub
Any suggestions on what's wrong with my code? Any help would be greatly appreciated.
I hope this help you...
Sub Worksheet_Name_Prefix_v2()
Dim h 'to store the last columns/header
Dim rngHeaders As Range 'the whole range with the headers from E1 to x1
Dim i 'just and index
Dim sht As Worksheet 'the sheet where you want the job done
h = Range("E1").End(xlToRight).Column 'find the last column with the data/header
Set rngHeaders = Range(Cells(1, 5), Cells(1, h)) 'the range with the headers E = column 5
'Cells 1 5 = E1
'Cells 1 h = x1 where x is the last column with data
Set sht = ActiveSheet 'the sheet with the data, _
'and we take the name of that sheet to do the job
For Each i In rngHeaders 'for each cell in the headers (every cells in row 1)
i.Value = sht.Name & " - " & i.Value
'set the value "sheet_name - cell_value" in every cell
Next i
End Sub
If you need any emprovement please tell me... I'm not sure if I get the real idea of what you need.
Edit #1
Use this in a regular module:
Option Explicit
Sub goForEverySheet()
Dim noSht01 As Worksheet 'store the first sheet
Dim noSht02 As Worksheet 'store the second sheet
Dim sht 'just a tmp var
Set noSht01 = Sheets("AA") 'the first sheet
Set noSht02 = Sheets("Word Frequency") 'the second sheet
appTGGL bTGGL:=False
For Each sht In Worksheets ' for each sheet inside the worksheets of the workbook
If sht.Name <> noSht01.Name And sht.Name <> noSht02.Name Then
'IF sht.name is different to AA AND sht.name is diffent to WordFrecuency THEN
'TIP:
'If Not sht.Name = noSht01.Name And Not sht.Name = noSht02.name Then 'This equal
'IF (NOT => negate the sentence) sht.name is NOT equal to noSht01 AND
' sht.name is NOT equal to noSht02 THEN
sht.Activate 'go to that Sheet!
Worksheet_Name_Prefix_v3 'run the code
End If '
Next sht 'next one please!
appTGGL
End Sub
Sub Worksheet_Name_Prefix_v3()
Dim h 'to store the last columns/header
Dim rngHeaders As Range 'the whole range with the headers from E1 to x1
Dim i 'just and index
Dim sht As Worksheet 'the sheet where you want the job done
h = Range("E1").End(xlToRight).Column 'find the last column with the data/header
Set rngHeaders = Range(Cells(1, 5), Cells(1, h)) 'the range with the headers E = column 5
'Cells 1 5 = E1
'Cells 1 h = x1 where x is the last column with data
Set sht = ActiveSheet 'the sheet with the data, _
'and we take the name of that sheet to do the job
For Each i In rngHeaders 'for each cell in the headers (every cells in row 1)
i.Value = sht.Name & " - " & i.Value
'set the value "sheet_name - cell_value" in every cell
Next i
End Sub
Public Sub appTGGL(Optional bTGGL As Boolean = True)
Debug.Print Timer
Application.ScreenUpdating = bTGGL
Application.EnableEvents = bTGGL
Application.DisplayAlerts = bTGGL
Application.Calculation = IIf(bTGGL, xlCalculationAutomatic, xlCalculationManual)
End Sub
Your code was not running because, you do not use this line sht.Activate you say, for every sheet in the workbook do this, but you not say to go to every sheet, and the the code run n times in the same sheet (as many sheets there in the workbook less two). But if you say, for every sheet do this, AND got to each of one of that sheets and do this (less that two sheets) you will get whay you want

type mismatch VBA checking cell value

I am trying to understand why I get Type mismatch error:
This is the function I have, basically it is copying from a worksheet to another and afterwards deleting the first character of the copied cells:
Sub copyBackFormulas()
Application.ScreenUpdating = False
Application.EnableEvents = False
'iterate through all worksheets
Dim WS_Count As Integer
WS_Count = ActiveWorkbook.Worksheets.Count
Dim I As Integer
For I = 1 To WS_Count
Dim ws1 As Worksheet
Set ws1 = ThisWorkbook.Worksheets(I)
'if sheet contains evdre
Set d = ws1.Cells.Find("EVDRE:OK")
If Not d Is Nothing Then
'copy back all formulas except from current view
Dim wsTarget As Worksheet
Set wsTarget = ws1
nameHidden = ActiveSheet.Name & "_BPCOffline"
Sheets(nameHidden).Visible = True
Dim wsSource As Worksheet
Set wsSource = Sheets(nameHidden)
For Each c In wsSource.UsedRange.Cells
If Left(c.Value, 1) = "_" Then
If Left(c.Value, 7) = "_=EVCVW" Then
Else
c.Copy wsTarget.Range(c.Address)
End If
End If
Next
'Remove underscore
For Each c In wsTarget.UsedRange.Cells
If Left(c.Value, 1) = "_" Then
c.Formula = Right(c.Value, Len(c.Value) - 1)
End If
Next
wsSource.Visible = xlSheetHidden
End If
Range("A1").Select
Next I
Application.CutCopyMode = False
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
I have several sheets that may need to be copied. The point is that I get type mismatch error on the line: If Left(c.Value, 1) = "_" Then
However, if I run the macro starting from other sheet it just works perfectly or it is only doing the right operations on one of the sheets and not the others.
I don't understand what makes it work at some point and what not.
Any input is highly appreciated
EDIT: I think the issue has to do with the fact that the macro may not find the first condition If Left(c.Value, 1) = "_" Then
You CAN'T copy paste formulas which have an error value
If you want to skip cells with errors you need another If...End if block:
If Not Iserror(c.Value) Then
...
End if
As explained by Rory in the comments

How to do cell copy- paste and value substitution in VBA?

I have a table with 2 columns.
A B
A2 B2 nn
A3 B3 nn
.....
An Bn nn
I need to copy the content of B2 cell and paste it to all the other B column cells, where A column has a value.
Then to find a certain value (nn) in B column and substitute it with A column value.
In order to copy B2 content I do this:
Sub CopyTest()
'ActiveSheet.Range("A1").End(xlDown).Offset(1, 0).Select
Range("B3:B1048576").Select
Selection.ClearContents
Range("B2").Copy
Range("B2:B7").PasteSpecial (xlPasteAll)
Application.CutCopyMode = False
End Sub
1.The problem is that I don't know how to do a paste not till certain cell (B7), but for all the table (so till A column contains value).
Similar problem I have substituting certain B column value with a value from column A.
Sub ReplaceExample()
Dim OriginalText As String
Dim CorrectedText As String
OriginalText = Range("B2").Value
CorrectedText = Replace(OriginalText, "E_ONBAL", Range("A2").Value)
Range("B2").Offset(, 1).Value = CorrectedText
End Sub
2.How to do the same action for all the A column, so to do kind of loop?
Thanks!
The first part is managed, so I publish the answer, in case it will be useful for someone:
Sub CopyTest()
Range("B3:B1048576").Select
Selection.ClearContents
Set currentsheet = ThisWorkbook.Worksheets("Sheet1")
LastRow = currentsheet.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
Range("B2").Copy
Range("B3" & ":" & "B" & LastRow).PasteSpecial (xlPasteAll)
Application.CutCopyMode = False
End Sub
I just still did not manage how to modify second part of the script with substitution in order to do the same action for all the A column, so to do kind of loop.
This example how to copy from activesheet to another sheet.
Sub Test1()
Dim SuccessSheet As String
Application.ScreenUpdating = False
SuccessSheet = ActiveSheet.Name
WS_Count = ActiveWorkbook.Worksheets.Count
' Generate new sheet if it does not exist
If Not sheetExists(SuccessSheet & " Log") Then
Set WS = Sheets.Add(After:=Worksheets(WS_Count))
Worksheets(SuccessSheet).Columns(2).Copy Destination:=Worksheets(WS.Name).Columns(2)
Worksheets(SuccessSheet).Columns(4).Copy Destination:=Worksheets(WS.Name).Columns(1)
WS.Name = SuccessSheet & " Log"
End if
Application.ScreenUpdating = True
End Sub