Oracle APEX - Conditionally Changing Text Color in a cell on an Interactive Report based on Contained Value? - date

Ok... So. I have an interactive report in APEX that displays data about documents in our system. Our documents are supposed to be reviewed every two years and there is a column in the table that contains the date that the document should be next reviewed by. We want to visually indicate either in the cell that contains the date, or another cell in the row, when the date reaches certain benchmarks (i.e. When the date is within 6 months of the current date, 3 months, 2, 1 etc.)
What I need to hopefully do is to change the color of the text (or background) of a specific cell based on either the value of that cell or the value of another cell in the same row. There would need to be a process or some function that does some computation to determine the span between the sysdate and the date contained in the cell... It does not necessarily need to calculate when the page is loaded but a daily or weekly process or something would be good.
Is it possible to set up processes or triggers that execute daily without human interaction? I also have a need to use the same functionality for sending reminder emails about these upcoming deadlines. (i.e. when a document is 6 months out from needing to be reviewed an email would be sent out, at 3 months, 2, 1 etc.)

Example with hiredate on emp: i'm about to colour the cells that are > 11000. (sysdate-hiredate ranges from about 10k to 12k). You could use a field you calculate in the query, or one you filled in through some procedure, doesn't matter :)
select empno, ename, job, mgr, hiredate, sal, comm, deptno,
trunc((trunc(sysdate)-hiredate)) to_colour_or_not
from emp
You will need 2 dynamic actions to colour rows in reports: an onload action, and an after refresh. If you skip the after refresh, rows won't be coloured after for example pagination, due to partial page refreshing.
Dynamic action one: After refresh on the region:
True action:
$("td[headers='TO_COLOUR_OR_NOT']").each(function(){
alert($(this).text());
if(parseInt($(this).text()) > 11000){
$(this).css({"background-color":"red"});
};
});
Example of using one column as a condition to colour another column. Always be carefull with what you test and what you test it for! For example, the hiredate column is a date, be sure to treat it as such if necessary! Further caution too: if your date format is set as DD-MON-YYYY, then you'd have to do the mapping for month to number (JAN = 1, DEC = 12)! Maybe it is an option to change the date format for this column even...
$("td[headers='HIREDATE']").each(function(){
var i_date = $(this).text();
//date format = MM/DD/YYYY
//be carefull with date formats.
//in my case, i know my date format and know it won't change
//my code is far from a complete parse of possible date values!
var dMonth = i_date.substring(0, 2),
dDay = i_date.substring(3, 5),
dYear = i_date.substring(6);
var d = new Date(dYear, dMonth, dDay, 0, 0, 0, 0);
if(d.getFullYear() <= 1981){
//we are looping over TD elements. I want to colour the
//column ENAME in red when the condition is true for this row.
//so, $(this) = TD element we loop with. parent = TR element,
//then back to the children of the row
$(this).parent().children("td[headers='ENAME']").css({"background-color":"red"});
};
});
The second dynamic action: on load
As true action, use the same code as the true action for the refresh.
With the JS you can do whatever you want: you just need to know which cells you wish to paint. Use the [headers=''] to target the cells you'd like (jquery selectors).
Instead of the css(), you can use addClass for example, if that is more what you'd like.
Do mind: IRs come with built-in mouseover actions. This causes your painted cells not to show in their colour when there is a mouseover action. If you don't want this, you'd need another dynamic action for the mouseover/mouseleave events, and target those cells necessary.
As for scheduled jobs: check out DBMS_JOBS.

In an Interactive Report, you also can define REPORTS ( with HIGHLIGHTS), which will do the trick for you.
Choose button ACTIONS, Then FORMAT (on Pop-up) and the HIGHLIGHT
In HighLight you can give a Name, Type (Row or Cell), Background and Text Colour, and the COLUMN on which you want an OPERATOR and an EXPRESSION.
You Apply the Highlight (Make Several Highlights /other-name when you need more than one colour-highlight depending on your EXPRESSION-s).
Together with the most important Filters then SAVE it as a Report (First Primary).
After having defined the Primary Report you can take this as the basis-report. Make some other Reports (and save them) with other filters, but with the same Highlights as the Primary Report).
Have FUN with it.

Related

In sheets, duplicating responses into specific tab(s)

In forms collection, users provide me data. Most importantly in the data given is the date(s) they select (or sign up for, in my instance). I've created new tabs in the spreadsheet that are associated with the dates. I'm copying and pasting the exact information that they provide into the correct date(s) tab. Sometimes they select multiple dates. However, at this rate, I'm moving so slow and making many mistakes.
Is there a code that can duplicate what I'm doing to avoid the simple mistakes I'm making and save time?
Updated: here is the link to a mock sheet (I hope I did it right): Mock Sheet
(quick pic of what I'm working with)
https://imgur.com/a/NErREzU
Thank you for sharing your spreadsheet. Here is what I recommend:
1.) In your existing individual date sheets, select and delete whichever columns you will not be using; likewise, select and delete all rows beyond the maximum number of rows you might ever need per sheet. Keeping sheets trim is the professional standard, makes it easier to focus on the important information, and assures maximum processing speed.
2.) Delete everything from your existing individual date sheets, including the headers.
3.) Place the following formula into cell A1 of each sheet:
=FILTER({Sheet1!A:D,Sheet1!F:F},(ROW(Sheet1!A:A)=1)+(REGEXMATCH(Sheet1!E:E,"December 17, 2021")))
Adjust the date in quotation marks to match the sheet. It seems that all of your events may be happening from 5:00 - 9:00, so you don't need to include that if my assumption is correct. However, if there are different times on the same day (and will therefore be two different sheets for that day), you will need to include the start time in the formula's quotes as well, exactly as it will come in from the form (e.g., "December 17, 2021 Friday, 5:00pm"). The hyphen and end time seems it would be superfluous and can be left off.
4.) To create a new individual date sheet, simply duplicate an existing individual date sheet, rename the copy, color your header row as desired, and change the formula section between those quotes in the A1 formula (which will already be in place from the duplicate sheet.
5.) Since you will be adding further notes or other information in additional columns within each individual date sheet, be sure that you never delete information from Sheet1; otherwise, the formula-produces row information will collapse to eliminate deleted rows, and your manually entered data will not match up. For this reason, I recommend simply Hide-ing Sheet1 entirely, as this will cut down on the chance that someone may accidentally tamper with the data coming into that sheet. There is not reason to have Sheet1 showing, since all data will be included in some other sheet due to the formulas there.
The formula FILTERs in only the five target columns, which are included in the opening virtual array formed between the curly brackets { }; and it will include rows that match either one of two conditions (shown between sets of parentheses, where the plus symbol means 'OR'): either A.) the row is Row 1 (i.e., the header row information) or B.) the part in quotes can be found in Sheet1!E:E.

setFormulaArray too slow

I'm trying to write a python wrapper which is designed to read multiple records from csv(or mysql) and update values of a predefined range of a sheet, the range is consisted of value cells and formula cells, my purpose is to update value cells only and keep formula cells in the range unchanged.
In order to do this, I first tried setting cell values one by one, using if to skip formula cells, but it was to slow because there were more than 10 thousand cells, then I tried setDataArray which was fast enough but formulas were overrode by values, then I created an array and set values and formulas into the array and used setFormulaArray to put the values and formulas into the range, the function was what I needed, by it took more than one minutes to finish
I know the setFormulaArray will update the formulas but I don't need this to happen, however as there is no option in the API to skip formulas I can only use the same formula to update the original formula in a certain cell.
Is there any solution to improve the performance when using setFormulaArry, or is there any solution to update only value cells and skip formula cells in a range?
bellow is my code
import uno
import time
#to open the libreoffice calc file
local_ctx = uno.getComponentContext()
smgr_local = local_ctx.ServiceManager
resolver = smgr_local.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", local_ctx)
url = "uno:socket,host=localhost,port=2083,tcpNoDalay=1;urp;StarOffice.ComponentContext"
uno_ctx = resolver.resolve(url)
uno_smgr = uno_ctx.ServiceManager
desktop = uno_smgr.createInstanceWithContext("com.sun.star.frame.Desktop", uno_ctx )
PropertyValue = uno.getClass('com.sun.star.beans.PropertyValue')
inProps = PropertyValue( "Hidden" , 0 , True, 0 )
document = desktop.loadComponentFromURL("file:///D:/salse.ods", "_blank", 0, inProps )
# get the sheet and read original data and formula from the sheet
sheets = document.getSheets()
xs = sheets["salse"]
cursor=xs.createCursor()
cursor.gotoStartOfUsedArea(False)
cursor.gotoEndOfUsedArea(True)
cra=cursor.getRangeAddress()
rng=xs.getCellRangeByPosition(cra.StartColumn,cra.StartRow,cra.EndColumn,cra.EndRow)
ft=rng.getFormulaArray()
#some code here to change values in ft....
# bellow took more than one minutes
rng.setFormulaArray(ft)
it is only a test of setFormulaArray performance
update1:
I still can't find the ideal solution,however, my solution is to create an identical sheet for each of the sheets in the workbook and add ,in the original sheets, references to the newly created sheets on the precisely same cells, for example:
example
sheetA is the original sheet
sheetA-1 is newly created one
then modify data cells in sheetA to reference to sheetA-1
then setDataArray to update the entire range in sheetA-1, data will automatically change in corresponding cells in sheetA

Show calculated measure in row?

I'm using Tableau Desktop 9.0 on OSX. I have data (loaded from a local CSV file) that looks like this:
code,org,items
0212000AA,142,10
0212000AA,143,15
0313000AA,142,90
0314000AA,143,85
I want a chart that shows the number of items beginning with 0212 as a percentage of all items, for each organisation. (I mean as a percentage of the organisation's items - for example, in the above, I would like to show 0.1 (10/(10+90)) for organisation 142.)
I have been able to get part way there, by adding org to Columns, and SUM(items) to Rows. Then by adding a Wildcard filter on code, for starts with 0212.
This shows me the number of items starting with 0212, by organisation.
But what I don't know how to do is show this divided by the value of all items for the organisation.
Is this possible in Tableau, or do I need to pre-calculate it before loading my data source?
One way is to define a calculated field called matches_code_prefix as:
left(code, 4) = "0212"
You can also define a parameter called, say, code_prefix to avoid hard coding the prefix string:
left(code, 4) = code_prefix
And then show the parameter control for code_prefix to allow the user to interact with it.
If you use this new field as a dimension to separate SUM(items) according to those that match the prefix and those that don't, you can then use a quick table calculation to get the percent of total.
For example, you can place org on the Rows shelf and matches_code_prefix on the Columns shelf, and SUM(items) on the Text shelf to make a table. Then under the analysis menu, turn on grand totals for both rows and columns to see the behavior. Next, right click on SUM(items) and choose Quick Table Calc->Percent of Total. Tableau will display the percents of total in the table.
If you want the percent of total defined differently than the default, then right click on the measure again and set Compute Using to a different value such as matches_code_prefix in your case. It's usually better to set compute using to a specific field.
If you only want to display the value for the matching case, select the column header you don't want to see and choose hide. You can also turn off the grand totals from the analysis menu when you are done.
When you are confident in the values in your table, you can turn it into a bar chart for example by moving matches_code_prefix to the detail shelf and the measure to the Columns shelf.
--
The above is the drag and drop approach. If you prefer to hard code everything in a single calculated field that is calculated on the database side, you could instead define a calculation such as:
zn(sum(if matches_code_prefix then items end)) / sum(items)
Then set the default number format for that field to display as a percentage

Background Color Not Filling in Entire Row Based off Expression in SSRS

I was hoping I could get some help on this issue. Got a report that displays data for events; of which we have two types: fixed and mobile.
To fill in the row based off what type the event is, I used this expression:
=IIF(Fields!OwnerType.Value = "Fixed", "LightSteelBlue", "#FFFFFF")
But here is what the result actually look like:
The rows with the light blue background color are fixed sites are often not assigned incentives/promotions. And if they aren't, I would still like the entire row to have a background color of light blue.
My issue like in the fact that the incentive columns (Sam's Club, T-Shirts, Wal-Mart, etc) are created dynamically through a column grouping - I have no which values might appear here or how many.
The way I have it configured currently is to put an expression on the cell itself:
But it leaves me with my reason for posting, I can't get the entire row to be back filled with this column grouping.
And if I apply the expression =IIF(Fields!OwnerType.Value = "Fixed", "LightSteelBlue", "#FFFFFF") to the column grouping the same way I did for the row, it will only change the colors of the individual cells where the incentive is and the header.
Under Group Columns -> Incentives Properties, can I change the visibility to also include the background color fill?
Added this expression for the row:
=Iif(
Max(
Iif( Fields!OwnerType.Value = "Fixed", 1, 0 )
, "Row_Group_Name"
) = 0
,"White"
,"LightSteelBlue")
Which filled in the entire row.

Excel - Insert "day" on a cell and format it to date with current month and year

I am working on a home accounting template (and could not find any good one :-/), so I am creating one for each month. Both in my expenses and my incomes, I would like to have a date column where I just have to insert the "day" (e.g.: 22) and it automatically fills the rest with the current month and year (or I could set them in another cell).
For example: 22 + ENTER would return: 22/12/2014
If I do this, I automatically get a default date: 22/01/1900
I do not know if it is possible to change this defaul date depending on the current one or any other value.
I have tried with a different strategy: if the amount column is not empty, fill in with today's date: =IF(A3="";"";TODAY())
The problem is that I do not always register today's expenses, so I need to change it manually. I was just wondering if this is possible and there is a better way (maybe a macro?).
You need Excel to modify the cell contents after you press ENTER. The only option seems to be a Macro using the Worksheet_Change event.
Please check out this other question. I think that will help.
This can be achieved with simple formatting and use of controls that are available in Excel. VBA will give you drastically more flexibility, however the request above can be accomplished without learning VBA.
I have included a sample file here.
Steps to recreate:
Create a range of months. I created a range including the current month through 12/2014
Insert a combo box from the developer tab. Right click and select Format Control. On the Control tab, input the range you just created and then select a "linked cell". This will insert an integer to indicate which item you picked in the list, starting at 1.
Use the attached formula to add the DAY that you enter in the first column and VLOOKUP the month and year from the value chosen in the combo box.
Enhancements: I used conditional formatting to change the text color of the days you enter to WHITE. This way you won't see them. I also included some checking in the VLOOKUP formula: the day you enter must be a number and must be non-blank for a date to populate.