Excel Macro for data validation modification - list

In cell A5, a list validation is populated ( Cat A, Cat B and Cat C). When the user choose category A, cell C5 is populated by a formula that tells the user to fill in the cell. Once the user goes to Cell C5, there is no formula but a drop down or a list validation of (yes or no).
If the user then goes back to cell A5 and chooses category C, cell C5 will be populated the original formula that cell the user to again the cell. Once the user goes to cell C5, there again no formula but a drop down or a list validation (yes/no)
Is it possible to write a simple macro for this? Anyone please? Thank you so much.
I think I know how but need more thoughts.

This is pretty simple code, but not easy to figure out if you haven't written VBA before. It will require two subroutines. In your VBE double click on the worksheet in the "Project - VBAProject" pane where you want this to live. Mine is being built for workbook "Book1.xls" in the tab "Sheet1"
We are going to use subroutines based on worksheet events. Events are things that happen on the front end (like selecting a cell) that fire code in VBA.
SelectionChange - This worksheet event fires whenever a user changes cell/range selections. We will use it to detect if the user switched to cell C5
Change - This worksheet event fires when someone Changes a cell's value. We use it to see if A5 was changed
In the code editor pane in your VBE, place the following:
Private Sub Worksheet_Change(ByVal Target As Range)
'This subroutine fires when a cell value changes in this worksheet.
'did someone change something specifically in cell A5?
If Not Intersect(Target, Sheet1.Range("A5")) Is Nothing Then
'Is the value A or C?
If Sheet1.Range("A5").Value = "A" Or Sheet1.Range("A5").Value = "C" Then
'Remove any data validation for this cell:
Sheet1.Range("C5").Validation.Delete
'and change the value of C5 to "Fill in this cell"
Sheet1.Range("C5").Value = "Fill in this cell"
End If
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
'This subroutine fires when a user selects a different cell or range.
'So... it fires ALL The time so the next line is super important.
'Did someone change selection specifically to cell C5?
If Not Intersect(Target, Sheet1.Range("C5")) Is Nothing Then
'Is the value currently "Fill in this cell"?
If Sheet1.Range("C5").Value = "Fill in this cell" Then
'Empty the cell
Sheet1.Range("C5").Value = ""
'Add data validation to some list somewhere
With Sheet1.Range("C5").Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:="=$J$1:$J$4" 'This the range that the list exists in
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End If
End If
End Sub
I've noted the important stuff with comments. You'll probably need to monkey a bit with it to fit your needs. Most notably that cell validation code. Currently the data validation for C5 is set to J1:J4. Change that to fit your needs.

Related

Oracle APEX - how to read a cell from interactive grid

The same question once again but with (I hope) better explanation:
I created the most simple case:
An Interactive Grid IG with data source EMP ( table with 14 records contains Ename, Job, HireDate, Salary etc. etc.)
Text field P7_ENAME
After running it looks like below:
What I would like to do is to copy Ename from selected record of IG to P7_ENAME field .
I found several tutorials (text and video) how to do it. Most of them suggest to create dynamic action SelectionChange on IG and when TRUE add a JavaScript code something like below:
var v_ename;
model = this.data.model;
v_ename = model.getValue( this.data.selectedRecords[0], "Ename");
apex.item( "P7_ENAME" ).setValue (v_ename);
and the second step is to create another action: Refresh.
So finally I have a dynamic action with two steps : the first one is a Java script code and the second refresh function on my P7_ENAME field.
Sounds simple and it is simple to repeat/implement. A guy (I suppose) from India published a video on YouTube (https://www.youtube.com/watch?v=XuFz885Yndw) which I followed and in his case it works good. In my case it simple does not work - field P7ENAME is always empty, no errors appears. Any idea why ? Any hints, suggestion ?
thanks for any help
K.
The best way to debug and achieve what you are trying to do is as follows:
create the Dynamic action with the following setup:
-when -> selection change[interactive grid],
-selection type -> region, region -> your IG region,
-client side condition -> javascript expression: ```this.data.selectedRecords[0] != undefined```
First action of the true of the DA with the type: execute javascript code and fire on initialization is turned on, code: console.log(this.data.selectedRecords);
Run your page, and check the browser console. You should see an array of columns when you select a record from that IG as follows:
Find in that array, which sort number of the array contains the data that you want to use for the page item. Let's say I want the 3rd element which is "2694" then I should change my dynamic action's execute javascript code to:
var value = this.data.selectedRecords[0][2];
apex.item( "P7_ENAME" ).setValue (value);
The last thing I should do is add another true action (and the refresh action at the end) to the same dynamic action with type 'SET VALUE' and 'PLSQL EXPRESSION' as type, put :P7_ENAME in the expression, items to submit P7_ENAME and affected element: item / P7_ENAME as follows:

New page of midlevel grouping in Active Reports v7

This has me stumped but then again, I haven't done reports in like 10 years. We are using an old version, AR win 7.
I have groupings by state, Type A, County, Type B. Boss wants it to kick the new county to a new page so I set the NewPage to AfterPrint for the group footer (totals). Problem with that is, when it's the last county of the upper groups (State, Type A), those totals go on a new page but boss wants them on the same page of the last county.
I thought about changing the NewPage setting to BeforePrint on the County Group header, but then the state and type labels print on a page before the first county...want those on the same page too.
So what am I missing?
I guess I figured it out. Seems to work.
Removed the NewPage property setting on the report and set it in code....
Private Sub GroupHeader3_AfterPrint(sender As Object, e As EventArgs) Handles GroupHeader3.AfterPrint
GroupHeader3.NewPage = SectionReportModel.NewPage.Before
End Sub
Then set the GroupKeepTogether = FirstDetail on the two groupings above (State, Type A).
That seems to have done it.

How to check spreadsheet cell value with MATCH without triggering NOW() function?

Trying to create a table that checks if the room key is already taken.
Google spreadsheet link.
An employee selects or enters the value into F2 cell. The formula in the G2 cell =IF(ISERROR(MATCH(F2,C4:C350,0)), "Brīvs", "Paņemts") tests whether the key is taken or not. The formula runs through C column and tests for the value.
While matching, it is also triggering the formula in B4 cell. Formula in B4 being =IF(C4>0, now(), "")
Issue is, every time an employee selects/enters the value, the MATCH function triggers the now() function and overrides the newest time if it matches the search criteria.
Is there a way of testing for the value without invoking the now() function so that the time stays as it was? Limiting recalculation counts in spreadsheet settings does not aid since an employee may not enter the value correctly from the 1st time.
Tried putting the value into another cell by "=" to nearby cell and =cell(contents, cell coordinate), but these refer back to the original values and Spreadsheet would recalculate all the references.
Thanks to cOde for providing the hint.
The code below is modified to the following needs. Since the sheets will be subsequently added, the SHEETNAME variable is taken out. I have also added the isBlank option at the end, so that if there is no value in the cell, the timestamp is erased.
/**
* Creates a Date Stamp if a column is edited.
*/
//CORE VARIABLES
// The column you want to check if something is entered.
var COLUMNTOCHECK = 3;
// Where you want the date time stamp offset from the input location. [row, column]
var DATETIMELOCATION = [0,-1];
function onEdit(e) {
SpreadsheetApp.getActiveSpreadsheet();
var ss= SpreadsheetApp.getActiveSheet();
var selectedCell = ss.getActiveCell();
//checks the column to ensure it is on the one we want to cause the date to appear.
if( selectedCell.getColumn() == COLUMNTOCHECK) {
var dateTimeCell = selectedCell.offset(DATETIMELOCATION[0],DATETIMELOCATION[1]);
dateTimeCell.setValue(new Date());
}
if (selectedCell.isBlank()) {
dateTimeCell.setValue("");
}
}

Using If Statement in Excel to populate when typing in a cell

I'm trying to find out if I can make a formula where I type in any value in a cell and then the next cell autopopulates with the city. Basically it will just be an address field for customers and the city will always remain the same. I just want it to be able to be blank if there is no data in the cell before it and if there is something typed in there it will populate the city in the next cell and the state in the next.
=if("a1"="","","city name") This is an if statement that is checking if the designated cell is blank and if it is then it will show blank, if there is something in there, then it will populate with what you have in "city name"
With “a cell” being in ColumnA (staring in A2), your city in B1 and State in C1 (they may already be labels) then:
=IF($A2="","",IF(ISEVEN(COLUMN()),$B$1,$C$1))
copied across one column and down may suit. If the resulting sequence is the wrong way round then either change EVEN to ODD or switch the contents of B1 and C1.

VBA Validation List Error

I am pretty new to programming in vba. I need some coding help which I am not able to find the solution after I tried Googling for the solution.
Currently I have a self-defined type called category mapping. The type will be used to contain the items which I want to put as the option for the vadliation list. It looked as below:
Public Type categoryMapping
messageKey As Long
description As String
End Type
An example of the categoryMapping is to store gender codes, 6000 stands for Male, 6001 stands for Female.
Display of the Validation List
As I have all stored them in an array, displaying them is not easy. What I have done is as below:
'Validation drop down list for the whole row
If Has_Elements(mapping) Then
Dim code As String
Dim options() As categoryMapping
code = ""
options = mapping
Dim j As Integer
For j = LBound(options) To UBound(options)
code = code & options(j).messageKey & ": " & options(j).description & ","
Next j
With Range(Rows(7).Address).Validation 'TODO: Need to refactor
.Add Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:=code
.InCellDropdown = True
.InputMessage = "Please choose from of the following"
.ShowInput = True
End With
End If
Is there a easier to display them since I have already put all the item to be displayed into a array? Is it possible that I can call the array directly?
Use Cells
From the code above, it can be seen that I have use the address of the whole row to contain validation list, because actually what I want is the whole row, except the header cells to contain the validation list.
With Cells(7,1).Validation 'TODO: Need to refactor
.Add Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:=code
.InCellDropdown = True
.InputMessage = "Please choose from of the following"
.ShowInput = True
End With
I tried using the code above to do, but it fails. Is there any way to go about doing it?
Combine multiple validation delete
Due to the problem mentioned above, I need to put in the code to delete the validation list for some column, as shown below:
'Delete the unneccessary validation
'TODO: refactor the code so that write in 1 line
Range(Columns(1).Address).Validation.Delete
Range(Columns(2).Address).Validation.Delete
Range(Columns(3).Address).Validation.Delete
Range(Columns(4).Address).Validation.Delete
Is there some ways that I can combine all the delete validation into a single statement?
Display part of the option
As you can see from above, when my users select a option from the validation list, the whole string appear.
For example, if I have "6000: Male" & "6001: Female" as the option, and I choose Male, I wished for "6000" to appear instead of "6000: Male". Is there a way to do it?
Validation data not exist after reopen
After I generate the validation list, I close the program and reopen it, there is a error that say "Excel found unreadable content in 'File name.xls'. Do you want to recover the contents of this workbook? If you trust the source of this workbook, click Yes.
When I click Yes, my excel open but all my validation list is gone! And I got the below as a error message.
-
error064240_01.xml
Errors were detected in file 'file_name'
-
Removed Feature: Data validation from /xl/worksheets/sheet2.xml.part
I was guessing that the error occur because the option in the validation list is not stored in the worksheet, but it is stored in the program memory, hence when I closed the program, the memory is loss.
If my guess is correct, is there any way to go around solving this problem? I was thinking of creating another worksheet that contain all the data in the validation list and let my cell validation list refer to them, but is there better ways to store them in the same worksheet?
The unreadable content is because you are storing the validation list in an array in memory. As soon as you close the worksheet, that array goes out of scope and ceases to exist. Rather than storing it in an array, write the list to a worksheet somewhere, I normally create a new sheet called lists.
The actual validation for your cell won't use VBA. Just create a dynamic named range (using offset() and counta() to populate your validation list from the relevant column in the lists sheet. Then use your VBA code to write the array above to that column. (http://chandoo.org/wp/2010/09/13/dynamic-data-validation-excel/)
As far as displaying different text in the validation and the dropdown, that sounds like more trouble than it is worth. Is it possible to just resize your cell so it only shows the first 4 digits?