My problem is how to populate the cmbSelProp ComboBox with propIDs from a workbook scoped Named Range called PropLocs. The columns of interest Column "A" which contains the list of propIDs and Column "K" which contains the ActiveStatus of each propID. I also have Named Ranges for both columns of interest, propIDs and actStatus respectively. The actStatus, Column "K", portion of the range are set to True/False when the properties are added and subsequently initialized and annual worksheets are automatically generated.
I only want cmbRptPrpID populated with propIDs having an actStatus = True.
I have spent many hours over the past few weeks going blind doing Web Searches, looking at links, and trying suggestions from the various links without success. I,m as "Lost as a blind man in a snow storm!"
There are broader issues associated with the problem I am dealing with and understanding how to solve, and understand, the issue at hand will help me in the future development of my application.
UPDATE
the 2 mentioned additional ranges are in columns "A" and "K"
Update 2
Business Logic
The application I am developing utilizes a multipage object and there are pairs of dynamic comboboxes, cmbSelProp and cmbYears for example, used to select the active worksheet and enter Monthly expenses, view/generate Reports, etc. cbmSelPropselects the property ID, and the cbmSplProp_Change() event configures cmbYears list values based on the variable wsStartYr in column "K" and wbCurYear which is the Current Calendar Year. the annual worksheets have a Worksheet TabName of propId_Year and are selected using a variable wsA = pID & "_" & wsYr. I do not want propIDs with an Inactive status to appear as a part of the cmbSelProp list values.
This is a link to My First Question here on StakOverflow which is related to this question.
I really need some help figuring this out!
Thanks in advance for your assistance.
here is the code I have been trying to work with.
selectedRow = cmbSelProp.ListIndex + 3
For Each cPart In wsCntrl.Range(Range("propIDs"), Range("A" & Rows.Count).End(xlUp))
pAct = wsCntrl.Cells(selectedRow, "K").Value
With Me.cmbSelProp
If pAct = "True" And cPart.Value <> "" Then cmbSelProp.AddItem cPart.Value
End With
Next cPart
There are a number of issues in your code. Rather than breaking down all the errors/issues, I'll show you how I would do it.
From your previous Q, I take it that your Combo Box is on a Userform.
I've created a Userform with a combo box and a button to load it. You can change how you call the load function to suit your needs.
The UserForm code
Option Explicit
Private Sub btnTest_Click()
Load_cmbSelProp
End Sub
Private Sub Load_cmbSelProp()
Dim propIDs As Range
Dim actStatus As Range
Dim rw As Long
Set propIDs = ThisWorkbook.Names("propIDs").RefersToRange
Set actStatus = ThisWorkbook.Names("actStatus").RefersToRange
Me.cmbSelProp.Clear
For rw = 1 To propIDs.Count
If propIDs.Cells(rw, 1).Value2 <> vbNullString Then
If actStatus.Cells(rw, 1).Value2 = True Then
Me.cmbSelProp.AddItem propIDs.Cells(rw, 1).Value2
End If
End If
Next
End Sub
The Named ranges
The result
Related
Okay, so don't mind the title, I had trouble summarizing my current issue. But first here is what I am trying to do :
I have three sheets, first one is containing a list of Attributes, the second a list of Categories and the third a cross table associating Attributes and Categories.
The code i'm working on is quite straightforward : when selecting one or many attributes (or categories) using checkboxes and executing the macro, the code will look for ticked checkboxes, get the ID associated to the selected attributes (or categories), then delete the line in the attribute (or category) worksheet and also in the cross table.
The sheets looks like that :
*Attribute Sheet*
*Category Sheet*
*Cross Table*
And here is my code :
Sub Delete_Selection()
Dim Wb As Workbook: Set Wb = Workbooks("DataBase WIP.xlsm")
Dim Sws As Worksheet: Set Sws = ActiveSheet
Dim CrossWs As Worksheet: Set CrossWs = Sheet6
Dim Cb As CheckBox
Dim Checking As Range
Dim LastRow As Long: LastRow = Sws.Cells(Sws.Rows.Count, "B").End(xlUp).Row
Dim CRow As Long, IDColumn As Long, IDRow As Long
Dim CID As String
IDColumn = Sws.Cells.Find(What:="ID", LookAt:=xlWhole).Column 'Look for the ID column in the current sheet
MsgBox (IDColumn) 'Debug purpose
For Each Cb In Sws.Checkboxes
If (Cb.Value = 1) Then 'If checkbox is ticked, proceed
CRow = Range(Cb.LinkedCell).Row 'Get the row number of the checkbox
MsgBox (CRow) 'Debug purpose
CID = Cells(CRow, IDColumn).Value 'Get the ID value
Rows(CRow).Delete Shift:=xlUp 'Delete the row
Cb.Delete 'Delete the checkbox
If (ActiveSheet.CodeName = "Sheet2") Then 'If attributes are being deleted, proceed
MsgBox (CID) 'Debug Purpose
IDRow = CrossWs.Cells.Find(What:=CID, LookAt:=xlWhole).Row 'Find the corresponding row in the cross table
CrossWs.Rows(IDRow).Delete Shift:=xlUp 'Delete it
End If
If (ActiveSheet.CodeName = "Sheet5") Then 'If categories are being deleted, proceed
MsgBox (CID) 'Debug Purpose
IDColumn = CrossWs.Cells.Find(What:=CID, LookAt:=xlWhole).Column 'Find the corresponding column in the cross table
CrossWs.Columns(IDColumn).Delete Shift:=xlToLeft 'Delete it
End If
End If
Next
End Sub
The issue :
The code works perfectly fine when selecting and deleting multiple attributes
The code works when selecting and deleting one category
BUT : when selecting multiple categories and running the deletion code, it deletes them all in the category sheet but it only delete one corresponding column in the cross table.
Example : if I want to delete the beef and beans category, I select them using the checkboxes then press the button, in the category sheet they're all successfully deleted (yay !) but only the beef column will be deleted in the crosstable.
So to figure out why, I decided to print the relevant variables, what is happening in the previous example is the following :
IDColumn = 1 which is normal
CRow = 10 fine too
CID = DOC9 expected
Then
IDColumn = 1 Wasn't supposed to change
Crow = 10 The rows have been shifted up to fill the gap so totally normal
CID = "" And that's where my issue is.
Despite looking at the right cell, CID don't get the value contained in it and I don't understand why at all.
Important precision, the attribute sheet is perfectly normal while the category sheet contains a Table ! I think that's where the issue lies but I couldn't find anything useful on the Internet.
And I don't understand why the program would be able the read the value of a cell the first time and then doesn't. I may have missed something obvious so I apologize if its the case but any help would be greatly appreciated !
Edit 1 : It has nothing to do with the Categories being in a table, I wrote a similar code but I ran into the exact same issue even without looking at a Table. I still don't know what's happening.
I found a workaround by first reading all my ID's and storing them into an array and then looping through my array to modify my cross table. I will probably do the same for my current issue.
Okay, I found the problem.
Once again I wasted a lot of time because of a stupid mistake.
When I was deleting a category, I needed to find the column linked to that category in my cross table, and I stupidly used the same variable referring to the ID column of my Category sheet (i.e. "IDColumn"), changing its value and therefore when reading the next ID, my code was looking in the wrong cell.
Thanks to anyone who have tried to help me ! I will hopefully not make a fool of myself next time ahah.
I have a file in excel. For each line, I have to create a unique identifier. It must be created permanently. The problem is for example: I have the same files on computers A and B. I'm filling same lines in each file. But the identifiers of those lines should be different. Please help me. If you know how to do that please give me an example of macro or formula
Try this.
=CONCATENATE(DEC2HEX(RANDBETWEEN(0,4294967295),8),"-",DEC2HEX(RANDBETWEEN(0,65535),4),"-",DEC2HEX(RANDBETWEEN(16384,20479),4),"-",DEC2HEX(RANDBETWEEN(32768,49151),4),"-",DEC2HEX(RANDBETWEEN(0,65535),4),DEC2HEX(RANDBETWEEN(0,4294967295),8))
This a copy of How can I generate GUIDs in Excel? with the semi colons replaced with commas. What you are looking for is a Global Unique Identifier or GUID. If you search for excel and GUID you can get a lot more options.
If you want to be able to get a reference of the row and/or columns out of this so you can compare the two files, you can append
& "-" & ROW()&COLUMN()
to the end of the above. This will effectively give you and address of the row and column being referenced.
Not the most elegant way of doing things, but I believe this somewhat answers your question.
If you can make sure that both files are Macro enabled, the user doesn't need to know how to prefix them, simply use something like below to add the ID to whatever column you want as new data is entered in column B in my example below:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ws As Worksheet: Set ws = Sheets("Sheet1")
'declare and set your worksheet, amend as required
LastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
'get the last row with data on Column A
If Target.Address = "$B$" & LastRow Then
For i = 2 To LastRow
ws.Cells(i, 1).Value = "A" & Format(i, "000")
Next i
End If
End Sub
Do the same in the other file, just change the "A" to "B"
I'm building a project management spreadsheet where multiple teams are going to have a copy. I want to create a simple address book. I have the names of the teams in a table and using VBA, I create the Master Table.
In the range B4:D5 there is a simple table with three column names:
Name
Telephone
Email
I have named this table (in Name Manager) as ContactTeam1
I want to copy and paste this exact 3x2 table to be below each corresponding team such as the image Here and change each Named Table as ContactTeam2, ContactTeam3 and so on.
The reason I want to use VBA is because, we have many different projects, so I want to automate the process as much as I can, for future projects as well.
I will fill in the tables with all the necessary information (Names,Phones,Emails) - by hand. The reason I want to use tables is that it has the benefit to auto-expand to include any new lines below the last.
As a bonus functionality, when somebody clicks the cell on top that contains the name of the Team. (Team Blue, Team Red etc.) all the emails of the corresponding range will be copied to clipboard, to be used in an email client. (This can be done easier with tables - one more reason I want to use them).
I hope this helps
Sub Bouton()
Dim cell As Range
Dim rng As Range
Dim cnt As Integer
Dim RangeName As String
Dim CellAdd1, CellAdd2 As String
For cnt = 2 To ActiveSheet.Range("NumberTimes")
Set rng = Range("ContactTeam" & (cnt - 1))
RangeName = "ContactTeam" & cnt
CellAdd1 = Cells(rng.Row, rng.Column + 3).Address
CellAdd2 = Cells(rng.Row + 1, rng.Column + 5).Address
'+ 1 in the row so the named range goes from B4 to D5
Set cell = ActiveSheet.Range(CellAdd1, CellAdd2)
ThisWorkbook.Names.Add Name:=RangeName, RefersTo:=cell
Range("ContactTeam1").Copy Range("ContactTeam" & cnt)
Next cnt
End Sub
I'm not the best in VBA, but what this does is that it creates a new range each 3 cells and names it from ContactTeam2 to whatever your limit is. I created a named range called NumberTimes. Basically, you tell it how many new ranges you want to be created.
easiest of all, i guess we can use dictionary here. would be faster but here he what i tested/tried , EXACTLY on your data and works.
Sub d()
Sheet1.Select
Range("b3").Select
Do
Range("b3:d4").Name = "mainteam"
ActiveCell.Offset(0, 3).Select
Range("mainteam").Copy ActiveCell
Range(ActiveCell, ActiveCell.End(xlDown).End(xlToRight)).Select
Range(ActiveCell, ActiveCell.End(xlDown).End(xlToRight)).Name = "team" & i
i = i + 1
Loop While i <> 5
End Sub
I have a spreadsheet which is acessed by a team of 5 members, put in a shared folder. Tracking the changes over the spreadsheet becomes difficult over time.
I would like to achieve the following. The Excel has around 8 columns (Only Sheet 1) with more than 250 rows. I would like to add another 2 columns, say Owner (Column 9) and Last Update (column 10) to Sheet1.
Owner - Column 9 - Team Member Name, whoever make the change to that row
Date - Column10 - Current Date and time whenever the last update made to that row.
Please suggest me the VBA code to automatically populate the Column 9 and Column 10.
EDIT - Changed row = ActiveCell.row to row = Target.row (allows for if you are no longer on the same row)
Something like this should work. Obviously you may want to consider adding some error handling and perhaps further validation if you only want to do the update if certain fields are changed etc. but this certainly covers the basics:
Private Sub Worksheet_Change(ByVal Target As Range)
' declare constants and variables
Const owner_col As String = "I"
Const date_col As String = "J"
Dim row As Double
Dim owner_addr As Range
Dim date_addr As Range
' initialise
row = Target.row
Set owner_addr = Range(owner_col & row)
Set date_addr = Range(date_col & row)
' check that the update is not to the fields you want to update to avoid infinite loop
If Target.Address <> owner_addr.Address And Target.Address <> date_addr.Address Then
' set values
owner_addr.Value = Environ("username")
date_addr.Value = Now()
End If
' free up the memory
Set owner_addr = Nothing
Set date_addr = Nothing
End Sub
This needs to be added to the sheet that you want the changes to be tracked in (i.e. not a module or the whole workbook). Let me know if you have any questions.
The Environ("username") gets the username from the Windows environment variable.
Started with a data validation list and I like that it is in the cell where I want the data to appear. Tried combo box and active X combo box and don't like that they do not reside in the cell. This is very different than Access. This is what I am trying to accomplish:
My named range (Employee) is A4:C100, 3 columns, with headings Title, MI, and LN on a sheet named "Emp".
My form location is C6. I wanted to be able to show 3 columns and end up with data from the three columns. For example, Officer J. Doe.
Currently I am using data validation list entering data into one column as Doe, J., Officer and it works. The list can be long and I will need it to be in alphabetical order.
Is this the best way or am I confused with combo box and active X combo box?
The only way to show a combination of all 3 columns in a dropdown list is to concatenate the data in a 4th column e.g. use the following formula in Cell D4
=A4&" "&B4&" "&C4
...then you can name the range D4:D100. You may wish to hide this column for presentational reasons
Actually, you will probably want to avoid naming the whole range as the bottom cells may be blank/make scrolling more awkward than strictly necessary. I would recommend dynamic ranges
The next extension exercise might be to develop your formula to allow for e.g. a missing middlename e.g.
=A4&" "&IF(B4<>"",B4&" ","")&C4
The above assumes you can sort the data manually. If the data is not being sorted manually, you will need to use VBA e.g. ensure Column D gets completed and the named range created each time a user moves off Sheet("Emp"). You can embed the following code in the Emp sheet...
Private Sub Worksheet_Deactivate
For n = 4 to 100
If Cells(n, 1) <> "" Then
Cells(n, 4) = Cells(n, 1) & " " & Cells(n, 2) & " " & Cells(n, 3)
End If
Next n
Range(Cells(4,4),Cells(100,4)).Sort Key1:=Cells(4,4), Order1:=xlAscending, Header:=xlNo
LastRow = 4
Do Until Cells(LastRow + 1, 4) = ""
LastRow = LastRow + 1
Loop
ActiveWorkbook.Names.Add Name:="Employee", RefersTo:=Range(Cells(4,4),Cells(LastRow,4))
End Sub
The expressions for sorting/adding range names can be found by recording macros and eliminating code as in this expert Excel support video. Your data validation would refer to 'Employee' which is the range name created in the 4th column
There are a number of assumptions made above such as the idea that all employees have data in the first column and you would need to add logical tests if you do not always have data in all three columns
It may also be that you would prefer to create the Employee range when a user clicks in cell C6 of your form, as this may be more robust. My assumption in using Worksheet_Deactivate is that 'Employee' may be used elsewhere in your spreadsheet
Something like this. Put this code in your worksheet where the comboBox is
Private Sub Worksheet_Change(ByVal Target As Range)
Dim topY As Integer, leftX As Integer
topY = ComboBox1.top
leftX = ComboBox1.left
Dim c As Range
Set c = Cells(5, 5)
c.Left = topY
c.Top = leftX
c.Width = ComboBox1.Width
c.Height = ComboBox1.Height
End Sub
It should keep it locked in place if you move things around. Or you could try it in your Private Sub Worksheet_SelectionChange(ByVal Target As Range) event.