Starting Point
In one of our customer projects the business users wanted the possibility to copy single values out of (pivot-) tables within the Oracle BI Suite. This is not possible within the standard implementation as using copy+paste on a pivot-table entry copies the whole table, not the value inside the table-cell. The copied content is not appropriate for any further processing.

copypaste_01

standard table within Oracle BI

Using the context menu does not provide a solution as well. Oracle BI overwrites the browser context menu. The following screenshots shows the standard firefox content menu (left) in comparison to the menu overwritten by Oracle BI (right).

copypaste_06

comparison of context menus

However as Oracle BI overwrites the context menu we should be able to change the way it does that and extend the menu with an entry for copying the table cell content. To configure the Oracle BI frontend we have to make changes within the files that render the webpages. These files reside in the folder “b_mozilla” which can be found here:

[MIDDLEWARE_HOME]/Oracle_BI1/bifoundation/web/app/res/b_mozilla.

As the changes made in these files affect the frontend only after redeploying the analytics application it is necessary to change the temporary files within the weblogic server. These files reside in the following folder:

[MIDDLEWARE_HOME]/user_projects/domains/[DOMAIN]/servers/[SERVER bzw. INSTANZ]/tmp/_WL_user/analytics_11.1.1/7dezjl/war/res/b_mozilla

The following steps describe all necessary code changes. Please make sure you backup all the files prior to changing.
Code Modifications
Please note that the following changes are made in existing files. Therefore make sure the naming of functions and variables does not affect the functionality of the application. You should also contemplate a regression testing after applying the changes.
File: “viewrightclickmenu.js”
After these lines within the file “viewrightclickmenu.js” (around line 52)

var D="";
var j=f.isLayerHierarchical(g,F);
var t=obips.ViewRightClickMenu.isRuntimeMode();

insert the code:

// Changed - start

labelText = 'Kopieren mittels \'Strg + c\'';
buttonEvent = obips.ViewModel.EventType.CUSTOM_COPY_CELL_VALUE;
var p = obips.ViewRightClickMenu.CreateContextMenuOption(labelText, labelText, null, null, buttonEvent, e);
f.push(p);

// Changed – end

The lines above produce a new context menu entry with the label ‘Kopieren mittels Strg + C’. In addition an indentifier “obips.ViewModel.EventType.CUSTOM_COPY_CELL_VALUE” is assigned to the new entry.
File: “obips.viewmodel.js”
All the menu entry identifiers link to corresponding entries in the file “obips.viewmodel.js”. As we have introduced a new identifier we have to add it to the identifier list.

After the existing list of identifiers

obips.ViewModel.EventType.SHOW_GRANDTOTAL_MENU_EVENT = 49;
obips.ViewModel.EventType.SELN_REMOVE_ALL_STEPS = 50;
obips.ViewModel.EventType.HIDE_COLUMN = 51;

add the new one:

// Changed - start
obips.ViewModel.EventType.CUSTOM_COPY_CELL_VALUE = 100;
// Changed - end

Now we have to define which action should be performed if the menu entry is selected. This is defined around line 1868 in the same file:

obips.ViewModel.ptCurrentEvent.eventType = a;
obips.ViewModel.ptCurrentEvent.eventData = c;
switch (a) {

The switch instruction selects the event type which is the uniform identifier for a menu entry. Therefore we have to add the newly created case “obips.ViewModel.EventType.CUSTOM_COPY_CELL_VALUE”:

// Changed - start
        case obips.ViewModel.EventType.CUSTOM_COPY_CELL_VALUE :  
            var b = obips.EdgeCoords.findCoords(d.getElement());
            var a = b.getId();
            var f = b.getEdge();
            var d = b.getLayer();
            var g = b.getSlice();
            if (g == -1) {
                var eId = "hl_" + a + "_" + f + "_" + d;
            } else {
                var eId = "e_" + a + "_" + f + "_" + d + "_" + g;}
            var cell = document.getElementById(eId);
            var cellValue = cell.innerHTML;
            if (cellValue) {
                cellValue = cellValue.toString().replace(/\s*\<.*?\>\s*/g, '');
                cellValue = cellValue.toString().replace(/&lt;/g, '<');
                cellValue = cellValue.toString().replace(/&gt;/g, '>');
                cellValue = cellValue.toString().replace(/&quot;/g, '"');
                cellValue = cellValue.toString().replace(/&nbsp;/g, ' ');
            }
            window.prompt('Kopieren mittels \'Strg + c\'', cellValue );
            break;
// Changed – end

The code inside the case clause selects the content of the current table cell

var cellValue = cell.innerHTML

and displays the content within a modal prompt window.

window.prompt('Kopieren mittels \'Strg + c\'', cellValue )

Datei “pivot\pivotview.js”
This file is responsible for rendering pivot tables. The same changes we made within the “obips.viewmodel.js” have to be applied to this file to change the context menu of pivot tables. Change the content of the “obips.PivotTable.onContextMenuItemSelected” to handle the context menu event:

obips.PivotTable.ptCurrentEvent.eventType = a;
obips.PivotTable.ptCurrentEvent.eventData = c;
switch (a) {

The processing logic is identical to the logic within the “obips.viewmodel.js” except the calculation of the element id (“eid”).

// Changed - start
        case obips.ViewModel.EventType.CUSTOM_COPY_CELL_VALUE :
            var a = c.getId();
            var e = c.getRow();
            var h = c.getCol();
            var eId = "db_" + a + "_" + e + "_" + h;
            var cell = document.getElementById(eId);
            var cellValue = cell.innerHTML;
            if (cellValue) {
                cellValue = cellValue.toString().replace(/\s*\<.*?\>\s*/g, '');
                cellValue = cellValue.toString().replace(/&lt;/g, '<');
                cellValue = cellValue.toString().replace(/&gt;/g, '>');
                cellValue = cellValue.toString().replace(/&quot;/g, '"');
                cellValue = cellValue.toString().replace(/&nbsp;/g, ' ');
            }
            window.prompt('Kopieren mittels \'Strg + c\'', cellValue );
            break;
// Changed - end

After the following lines

p.setDataValue(v, u);
var a = new ActionLinksRenderer(p, G);

you have to change the definition of the “obips.PivotTable.onDatabodyContextMenu” function:

// Changed - start
linkText = "Kopieren mittels 'Strg + c'";
k = obips.ViewModel.EventType.CUSTOM_COPY_CELL_VALUE;
var l = obips.PivotTable.CreateContextMenuOption(linkText, linkText, null, null, k, f);
i.push(l);
// Changed - end

This inserts the new context menu entry to the pivot table context menu. We do not have to define a new event type as we used the one created for the table context menu.
Restarting the system
After applying the changes restart the opmn components and every running instance. After the competed restart the new functionality should be available in the Oracle BI frontend.
Result
After the system restart the context menu of a (pivot-) table should look like this:

copypaste_04

modified context menu

A click on the new menu entry opens a modal prompt window that provides the possibility to copy the cell value using Copy+Paste.

copypaste_05

modal prompt window of the modified context menu

Note that this method only applies for copying single values. For copying multiple cells Oracle BI provides a CSV-export functionality.

Code source: http://obi2ru.blogspot.de/2012/11/biee11g-copy-paste.html

Note: This example was tested using Oracle BI Suite 11.1.1.7.141014. Please note that we cannot ensure that the following code snippets work for all further versions of Oracle BI.