If dropdown value is selected add formatting and values to cells to the right - vba

Ok so I am making a sheet where a user would select a value from a dropdown and then needs to see the required parameters based on the selection.
Example:
If i select X from the drop down then three new input fields would be created and formatted as input cells with the parameter as the default value (so the yellowish orange input format with default text explaining what the parameter is -- like start date for one then the next end date)
My start:
Sub test()
If ActiveCell = "setEnrollnet" Then
ActiveCell.Offset(0, 1) = startDate
ActiveCell.Offset(1).EntireRow.Insert
ActiveCell.Offset(1, 1) = 0
ActiveCell.Offset(0, 2) = endDate
ActiveCell.Offset(1).EntireRow.Insert
ActiveCell.Offset(1, 2) = 0
End If
End Sub
This does not work well and it does not apply formatting. I need help figuring out how to do both format and input the correct text based on selection in another cell.

I suggest - for each value in the drop down list - you define the input fields in a seperate sheet, together with field labels and formats. After selection from the drodown, you scan the parameter table and copy whatever is listed for that parameter to your input sheet.
Example (range named InputParams):
ParamVal InputLabel InputField
X StartDate (empty but formatted)
X EndDate (empty but formatted)
Y Foo default_Foo
Y Bar default_Bar
Upon selecting "X" from the dropdown list you walk through InputParams and,
If InputParams(Idx, 1) = DropDownValue Then copy cells InputParams(Index,2) and InputParams(Index,3) to your input range - by default formats are copied along with content.
It is desireable to define a named range also for Input, giving it a size of maximum parameters expected, so that you can clear content and formats with one single statement prior to re-populating this range when walking through the InputParams list.

Related

Use python to pull variable sized range of cells between 2 known fields from Excel file

I want to pull data from an Excel file that matches certain fields. See sample worksheet below:
The fields I need are the dispatch and arrival times but I also need the values in between the two cells in the first column marked "Incident Notes:" and "Event log" (highlighted in bold).
For instance, in the first event, the cells I need are:
08/02/2022 4:02:29
08/02/2022 4:04:22
Pizza with cheese
Did not tip
So there are 2 cells in that range between "Incident Notes" and "Event log" in the first call. In the second call however, there is only a single cell:
"Italian sub". In the third call there are 3 cells:
"Hot wings"
"Rude"
"No street parking".
This is the code I have so far but I am stuck on how to pull a range of cells that vary in number between 2 known fields.
wb = openpyxl.load_workbook('TestSpreadsheet.xlsx')
sheet = wb['Sheet1']
for row in range(1, sheet.max_row):
myrow = sheet[row]
callstatus = sheet['C' + str(row)].value
if callstatus == 'Dispatch:':
calltime =sheet['C' + str(row+1)].value
print(f" Status: {callstatus} at {calltime}")
# TODO: figure out how to pull range of cells between
# Incident Notes: and Event log: cells
I know I want some kind of while loop that does something like
while after 'incident notes:' cell and before 'event log' cell
print cells in between
but am stuck on this.
You can search for the known word(s) that delineate each section then use offsets to find the data from that position since it seems this is consistent in your example data.
Offset allows you to select another cell at row and column from the current cell.
Below is an example code for your sample;
import openpyxl
def fill_list(row_cell):
# Get the cell values by offset positions
data_list = []
corrent_row = 0
search_term2 = 'incident notes:'
search_term3 = 'event log:'
data_list.append(row_cell.offset(column=2, row=2).value)
data_list.append(row_cell.offset(column=4, row=2).value)
while row_cell.offset(row=corrent_row).value.lower() != search_term2:
corrent_row += 1
corrent_row += 1
while row_cell.offset(row=corrent_row).value.lower() != search_term3:
data_list.append(row_cell.offset(row=corrent_row).value)
corrent_row += 1
return data_list, row_cell.row + corrent_row
filename = 'foo.xlsx'
search_term1 = 'event no:'
wb = openpyxl.load_workbook(filename)
ws = wb['Sheet1']
row_next = 0
for row_cell in (ws['A']):
cur_cell_val = row_cell.value
# Jump down to the next row after the last processed data
if row_cell.row < row_next:
continue
if cur_cell_val.lower() == search_term1:
event_list, row_next = fill_list(row_cell)
print(event_list)
['08/02/2022 4:02:29', '08/02/2022 4:04:22', 'Pizza with cheese', 'Did not tip']
['08/02/2022 5:01:12', '08/02/2022 5:14:18', 'Italian sub']
['08/02/2022 6:12:37', '08/02/2022 6:14:50', 'Hotwings', 'Rude', 'No street parking']
---------Additional answers-------
For the offset method both column and row are optional. As you can see from the code extract from the module below both are set to 0 by default
def offset(self, row=0, column=0):
"""Returns a cell location relative to this cell.
:param row: number of rows to offset
:type row: int
Not setting either will mean of course that you are referencing the same cell as your current. However referencing a cell in the same plane as your current cell there is no need to set that attribute to 0.
The dates are down to the Excel formatting used on the cell. I don't know what formatting you have on any of the cells so for the test output I set the date cells as text. Your sheet appears is using a custom format for these date/time cells. If that format was like 'dd-mmm-yy hh:mm:ss' it would display as shown in Excel however its probably using forward slashes so python is interpreting as datetime.datetime(2022, 8, 2, 4, 2, 29). If you can/do not want to change the cell formatting then just convert in python. The exact conversion will probably depend on what you want to do with the dates. If its just for display you can do the following. The default will display with hyphens the second line will change the hyphens to forward slashes.
import datetime
print(datetime.datetime(2022, 2, 8, 5, 1, 12))
print(str(datetime.datetime(2022, 2, 8, 5, 1, 12)).replace('-', '/'))
Output
2022-02-08 05:01:12
2022/02/08 05:01:12

VBA: filter data based on cell value and fill in to another sheet

enter image description hereI Have two Excel Sheets ("Record") & ("Register"), " Register" is the database. from this database I need to create Records of each employees based on their employee ID (cell value). i am searching for a VBA code that should give me the training Record a each employee once i have enter their ID in the cell and click "a command button". Attached the Excel screen short for reference.
Steps 1: Enter Employee ID in the "Record" sheet
Step 2: Click command button "Filter" in the Record sheet
Step 3: VBA code to run and filter data from "Register" and fill "Record".
IF i Type another Employee ID in the sheet "Record" , it should ClearContents of the previous query. and produce the data.
Please help me, i am not good in VBA .attached the Excel screen short for reference ( UPDATE on 29/07/2018-Question Solved : sharing the code below; thank you Mr.ComradeMicha for your valuable feedback)
Sub Button2_Click()
'Declare the variables
Dim RegisterSh As Worksheet
Dim RecordSh As Worksheet
Dim EmployeeRange As Range
Dim rCell As Range
Dim i As Long
'Set the variables
Set RegisterSh = ThisWorkbook.Sheets("Register")
Set RecordSh = ThisWorkbook.Sheets("Record")
'Clear old data Record Sheet
RecordSh.Range("A8:F107").ClearContents
Set EmployeeRange = RegisterSh.Range(RegisterSh.Cells(6, 4), RegisterSh.Cells(Rows.Count, 6).End(xlUp))
'I went from the cell row6/column4 (or D6) and go down until the last non empty cell
i = 7
For Each rCell In EmployeeRange 'loop through each cell in the range
If rCell = RecordSh.Cells(4, 2) Then 'check if the cell is equal to "Record"
i = i + 1 'Row number (+1 everytime I found another "Record")
RecordSh.Cells(i, 1) = i - 7 'S No.
RecordSh.Cells(i, 2) = rCell.Offset(0, 2) 'Training name
RecordSh.Cells(i, 3) = rCell.Offset(0, -2) 'End date
RecordSh.Cells(i, 4) = rCell.Offset(0, 6) 'Validity
RecordSh.Cells(i, 5) = rCell.Offset(0, 7) 'Remarks
RecordSh.Cells(i, 6) = rCell.Offset(0, 5) 'Minimal requirement
End If
Next rCell
End Sub
Your code is missing a few essential parts you may want to look into:
It seems to require the user to select a specific row before the macro is started, even though there is a command button to trigger the macro. If the layout stays the same, just use constants to store the row where certain input or lookup fields are located.
ra is used both on the input form and on the lookup sheet. That's asking for trouble... Again, use constants or at least "StartingRow=3" or something similar.
You are correcting your employee number to a format that doesn't fit the data provided in the screenshot. Hopefully just a dummy data issue, but in case you are wondering why you don't find anything ;)
You are typecasting all fields individually. If your layout is always the same, it's much easier to just use the "variant" type for all cell values and make sure you already formatted all columns correctly.
ru is never initialized? It's supposed to be "the next row", why not simply use "ra+1" then instead of ru? Also, TRNRow and RTRNRow are never initialized either.
When you "search" your records, you actually only copy the same row into your results, then "copy next row until employee number is wrong". So this only works for exactly one employee, and even then you only catch the first few trainings. Use the Find function on the employee number cell in the records sheet to find the next row with that id, then copy the row's contents and find next.
I think if you get yourself aquainted with the Find function, you will easily finish this macro on your own. Here's a good guide: https://excelmacromastery.com/excel-vba-find
Good luck!

VBA: Finding the row number by looking up a user defined value (date)

I am trying to use VBA to look up the row value that corresponds to a user defined date on one of my work sheets so that I am able to edit all data on that row.
As a bit of context:
I have several time series data sets that all have different start and end dates with a good portion of overlap in the middle. I want to chart these using user defined date parameters, however, because of non-uniform start dates, the chart is impossible to dynamically rebase.
I was hoping to use a macro to clone the data on one sheet, overwrite the line of values that corresponds to the user defined start date, and then calculate return values based on percentage change figures (I already have in a different sheet).
If I can dynamically o/w the row that corresponds to the UD start date of the date range, I can replace it with a one and all my calculations will effectively rebase.
Any and all feedback would be great!
EDIT
Lucas,
I am having two issues; firstly, what I have inexpertly cobbled together doesn't work when I protect the sheets (not insurmountable); secondly, it doesn't work :). Here is my work:
Sub Rebase()
Dim UDStartVal
Dim UDStartLoc As Range
Dim UDRow As Integer
'
' Rebase Macro
' A macro to rebase the chart to the user defined start date.
'
'
Sheets("Cumulative Monthly Returns").Select
Cells.Select
Selection.Copy
Sheets("Chart Numbers").Select
Range("A1").Select
ActiveSheet.Paste
' Lookup to change the value of the cells corresponding to the user defined start date to 0, effectivley rebasing the portfolo.
Worksheets("Cumulative Period Returns").Activate
UDStartVal = Cells(4, 2).Value
Set UDStartLoc = Range("A:A").SpecialCells(xlCellTypeVisible).Find(UDStartVal)
Set UDRow = UDStartLoc.Row
Stop
End Sub
Here's some code that I use to find the row of an entry based on quote numbers on a sheet that gets resorted and re-filtered constantly.
Private Sub FindQuote(partNum as String)
Dim quoteRow as Range
Set quoteRow = Range("A:A").SpecialCells(xlCellTypeVisible).Find(partNum)
then when I want to do something that uses the range of that row I use quoteRow.Row
If Not quoteRow Is Nothing Then
quoteNum = Cells(quoteRow.Row, "P").Value
Cells(quoteRow.Row, "Q").Value = "Found"
Else
MsgBox "No quote was found"
End If
End Sub
Did you need help with the part where you clone your sheet?

Data Validation of a Filtered table

I have a Data table with an Auto Filter (shown Below).
Sub Tariff_Filter()
Dim columnNumber, tableRow, tableColumn, tableWidth As Integer
Dim tableName, columnName As String
tableName = "Tariff_Table"
columnName = ActiveSheet.Range("A1").Value
'This clears the existing filter
ActiveSheet.ListObjects(tableName).Range.AutoFilter
'Assign some numbers we need to know about the table to check the headers
tableRow = ActiveSheet.ListObjects(tableName).Range.Row
tableColumn = ActiveSheet.ListObjects(tableName).Range.Column
tableWidth = ActiveSheet.ListObjects(tableName).Range.Columns.Count
'If a column title with the specified value does not exist VBA throws an error which we need to catch
On Error GoTo ErrorHandler
'Search through the table column header row to find the specified column and assign the number to columnNumber
columnNumber = Application.WorksheetFunction.Match(columnName, Range(Cells(tableRow, tableColumn), Cells(tableRow, tableColumn + tableWidth)), 0)
'Apply the filter "1" to the found columnNumber
ActiveSheet.ListObjects(tableName).Range.AutoFilter field:=columnNumber, Criteria1:="1"
'Exit the sub otherwise the "error handling" will be provoked
Exit Sub
ErrorHandler:
MsgBox columnName & "Please Specify Required Channel"
End Sub
As i cant seem to figure out how to get my combo-box's to show only the visible cells after filtering the table i was wondering if there is a way i can create a a validation box to show the visible cells or copy the visible data into a seperate table underneath. I can then use the validation box/ secondary table as a focus point for the combo-box's on the user-form.
Thanks in advance
If I'm understanding your question correctly, you would like to have a data-validation drop-down list that updates as the table is filtered and only displays visible items for a given column.
You can do this by using the following formula in Data Validation (I'm assuming your table header row starts in A1 and it's col A you need to display):
=OFFSET($A$2,,,SUBTOTAL(103,TableName[column name]))
This formula expands from the starting cell (A2) by a specified height in number of rows. We are defining the height using SUBTOTAL with function number 103 - this means that the height is defined using COUNTA, but only on visible cells, so it will expand and collapse as the table is filtered.
Be aware: since the height is defined using a counta function, it will only count cells containing data, therefore if you have blanks in your table, the range will not be defined correctly. Also if you have any repeated data, these will be repeated in your drop-down box, this method will not condense them into a neat, unique list.
Hope this is helpful.
D

Macro query spread over multiple-sheets

Wording my question is slightly tricky so I've included screen-shots to make this easier. I have 2 separate spreadsheets which are currently not linked together in anyway. What I've been asked to do is:
For the drop-downs which have a * next to them, have this * drop-down get converted into a acronym (I.e. If it's Home Visit *, then this will be converted to HV), and have it automatically entered into Cell Position X. Please refer to Image 1 then Image 2)
So the user would click on Sheet one, select the relevant drop-down field and then assign how much time that task took. The second sheet would then update itself with this information - it would insert the users name, program and activities. This is where it gets very tricky. Based off the drop-down selection, if it is asterisked (*), then based off the field-type it will convert it into a set acronym which would then be placed in one of the data fields based off the entry date that has been provided.
I designed both spread-sheets and they have macros in the background, but I can't seem to work out how to best perform this. Would you suggest a transpose function which checks firstly the date criteria and then an INDEX(MATCH) function to match the criteria against a pre-defined name-range which converts Home Visit etc. to HV automatically? I'm also unsure of how to insert delimiters for each new entry that is read. If anyone can provide help I would be very grateful.
I'm not 100% sure I understand your question, but here goes:
What about adding a Worksheet_Change event to look for changes in the drop-down's cell, and then converting it to an acronym?
Place the following code inside the sheet of interest:
Private Sub Worksheet_Change(ByVal Target As Range)
'If Cell A1 is changed, put the acronym into A2
If Target.Row = 1 And Target.Column = 1 Then
Cells(2, 1) = GetAcronym(Target.Value)
End If
End Sub
Function GetAcronym(TheText As String) As String
Dim result As String
Dim x As Long
'Always grab the first letter
result = Mid(TheText, 1, 1)
'Get the other letters
For x = 2 To Len(TheText) - 1
If Mid(TheText, x, 1) = " " Then result = result & Mid(TheText, x + 1, 1)
Next x
GetAcronym = UCase(result)
End Function