Sprache auswählen

Snippets für Cognos 11

Cognos 11 Tipps und Tricks

In diesem Abschnitt erfahren Sie mehr über Tipps und Tricks zu Cognos 11. Beispiele, wie man Berichte oder Dashboards um Zusatzfunktionen erweitern kann oder bestimmte Funktionalitäten mit JavaScript in Cognos 11 einbauen kann.

Bei Cognos 11 ist das Design teilweise etwas unschön. Anstatt dies mühevoll über Themes oder eigene Klassen zu steuern oder, noch mühevoller, manuell in allen Objekten zusammen zu klicken, kann man einfach etwas CSS dem Kopf der Seite hinzufügen.

Dazu bietet es sich an, im Seitenkopf ein HTML-Element hinzuzufügen, und dort Änderungen vorzunehmen. Alternativ kann man die CSS-Formatierung auch als CSS-Datei speichern und diese über <link> auf der Seite verlinken.

<style>
a {
text-decoration: none !important;
}

button {
cursor:hand;
}

select.pv, div.pv, input.pt {
  padding: 4px;
  border-radius: 4px;
  border: 1px solid #111;
  outline: none;
  font-family: Arial, helvetica;
  font-size: 11pt;
  background: white;
}

a.pl {
  font-size: 7pt;
  font-family: Arial, helvetica;
  color: #222;
}

button.bp {
  border-radius: 4px;
  outline: none;
  border: 1px solid #111;
  padding: 5px;
  color: black;
  background-color: #d0d0d0;
  background-image: none;
  width: 150px;
  height: 40px;
  font-family: Arial, helvetica;
  font-size: 11pt;
}

input.clsSelectDateEditBox {
  font-family: Arial, helvetica;
  font-size: 11pt;
  padding: 4px;
  border-radius: 4px;
  border: 1px solid #111;
  outline: none;
}

table.clsSelectDateCalendarDialog {
    font-family: Arial, helvetica;
    font-size: 9pt;
}

input.clsSelectDateYearEditBox {
    font-family: Arial, helvetica;
    font-size: 9pt;
}

.clsCheckBoxRow label {
    font-family: Arial, helvetica;
    color: #333;
    font-size: 11pt;
    padding: 3px;
    /* line-height: 32px; */
}

.clsCheckBoxRow {
    height: 18px;
}

div#targetgroup span {
    font-family: Arial, helvetica;
    font-size: 9pt;
}

div#input_tg {
    font-family: Arial, helvetica;
    font-size: 9pt;
}

div#input_tg ul {
    padding-left: 30px;
}

div#input_tg li {
    line-height: 13pt;
}

.clsTextWidgetParseError select {
    border: none;
}

.clsTextWidgetParseError {
    border: 1px dotted red;
    border-radius: 4px;
}

.dijitCheckBox input {
    opacity: 1 !important;
    border: 1px solid #333;
    border-radius: 2px;
    width: 15px;
    filter: none !important;
}

.dijitCheckBox {
    border: none;
    /* border-radius: 3px; */
    background: none !important;
}
</style>

Die Auswahlboxen auf Cognos Eingabeaufforderungsseiten sind nicht sehr interaktiv. Das "Suche-Element" von Cognos ist allerdings sehr unhandlich und verursacht bei jeder Suche neue Datenbankabfragen.

Daher ist ein kleines Eingabefeld, um eine Auswahlliste schnell und einfach zu filtern, sehr praktisch.

Vor einer normalen Auswahlliste wird mit etwas HTML-Code ein Eingabefeld hinzugefügt. Und mit etwas JS-Code kann man dann die Auswahlliste filtern. Hierbei funktionieren auch Regular Expressions (z.B. mit ^ nach einem Text am Anfang oder mit $ am Ende suchen).

Vor dem Listenelement ein HTML-Element mit folgender Code-Zeile einfügen

<input type="text" id="client_search_field"></input>

Direkt nach dem Listenelement ein HTML-Element mit diesem Code-Snippet einfügen

<script>
var elem = findControl("P_LST_KUNDE1")
var options = elem.options
var clientids = [];
var clientnames = [];
var clientelems = [];
for (let x = 0, x_len = options.length; x < x_len; x++) {
  if (options[x].getAttribute("dv") != null) {
    clientids.push(options[x].value);
    clientnames.push(options[x].getAttribute("dv"));
    clientelems.push(options[x]);
  }
}
document.getElementById("client_search_field").addEventListener("input", function (evt) {
  findControl("P_LST_KUNDE1").value = "";
  clientelems.forEach(elem => elem.style.display = "none");
  clientelems.filter(function (elem, search) {
    var exp = new RegExp(this.toUpperCase().replace(/ /g, ".*"));
    if (elem.getAttribute("dv").toUpperCase().match(exp)) {
      elem.style.display = "";
      return true;
    } else {
      return false;
    }
  }, evt.target.value)
});
</script>

Definition auf der Cognos-Promptpage
Definition der Element auf der Prompt-Page

Standardsuche nach allen Vorkommen eines Suchbegriffs
Filtereingabe für eine Listbox

Suche nach Texten, die auf 73 enden ($ am Ende des Suchtextes)
Filtereingabe für eine Listbox mit RegEx $

Suche nach Texten, die mit B beginnen (^ am Anfang des Suchtextes)
Filtereingabe für eine Listbox mit RegEx ^

In einigen Bereichen werden Perioden häufig über Kalenderwochen definiert. Diese lassen sich über das Kalenderwidget von Cognos natürlich einstellen (Montag bis Sonntag), aber es fehlt eine Anzeige der Kalenderwochen, so dass man wissen muss, wann z.B. KW 14 beginnt. Dafür ist dann eine Auswahlliste der Kalenderwochen hilfreich, so dass man nur "KW 14" auswählen muss und das Datumswidget direkt auf den richtigen Tag eingestellt wird.

Um diese Funktionalität zu erreichen, ist nicht viel erforderlich:

Man benötigt zwei Auswahllisten mit statischen Werten für die möglichen Kalenderwochen eines Jahres. Und natürlich zwei Kalenderwidgets ("Von" und "Bis").

Definitionen für die Kalenderwochenauswahl per Dropdown

Weiter unten auf der Eingabeaufforderungsseite fügt man ein HTML-Element hinzu, das folgenden Code enthält:

<script language="JavaScript">
var isoweek = (kou) => {
var year = parseInt(kou.substring(0, 4), 10);
var week = parseInt(kou.substring(4, 6), 10);
// JavaScript weekdays: Sun=0..Sat=6
var jan10 = new Date(year, 0, 10, 12, 0, 0);
var jan4 = new Date(year, 0, 4, 12, 0, 0);
var wk1mon = new Date(jan4.getTime() - (jan10.getDay()) * 86400000);
var startdate = new Date(wk1mon.getTime() + (week - 1) * 604800000);
var enddate = new Date(startdate.getTime() + 518400000);
var datesout = new Array();
datesout[0] = dmyformat(startdate);
datesout[1] = dmyformat(enddate);
return datesout;
}

 var dmyformat = (kou) => {
    return (kou.getFullYear() + '-'
      + (kou.getMonth() + 101).toString().substring(1, 3) + '-' + (kou.getDate() + 100).toString().substring(1, 3));
  }

var __week_from;
var __week_till;
var __year_from;
var __year_till;

  pmTitanHelper.findControl("P_LST_WEEK_FROM").addEventListener('change', function (e) {
    __year_from = parseInt(pickerControlP_DATEPICKER_FROM.sGetValue().substr(0, 4));
    __week_from = (__year_from * 100 + parseInt(e.srcElement.value)).toString();
  pickerControlP_DATEPICKER_FROM.setValue(isoweek(__week_from)[0]);
  });
  pmTitanHelper.findControl("P_LST_WEEK_TILL").addEventListener('change', function (e) {
    __year_till = parseInt(pickerControlP_DATEPICKER_TILL.sGetValue().substr(0, 4));
    __week_till = (__year_from * 100 + parseInt(e.srcElement.value)).toString();
  pickerControlP_DATEPICKER_TILL.setValue(isoweek(__week_till)[1]);
  });
</script>

Code enthält eine Funktion zur Berechnung des Wochenstart- bzw. -endedatums anhand eines Index und fügt Eventhandler zu den Drop-Downs hinzu. Sobald eine andere KW-Auswahl getroffen wird, wird das Wochenstart- bzw. -endedatum errechnet und das jeweilige Datumswidget gesetzt und der Wert im Parameter gespeichert.

Auswahl einer Kalenderwoche per Dropdown

Für einen Bericht/Dashboard mit einer Liste als HTML-Ausgabe kann es praktisch sein, diese Liste in eine interaktive dataTable mit Filterfunktion und direktem Excel-Export (z.B. auch mit echten Excel-Formeln) umzuwandeln.

Datenliste als jQuery-dataTable

Dies ist mit wenigen Schritten möglich.

Erst müssen die entsprechenden jQuery und dataTables JS-sourcen im Kopf der Berichtsseite geladen werden.

jQuery und dataTables Sourcen laden

<link rel="stylesheet" href="/../js/jquery/datatables.min.css" type="text/css" media="all" /> 
<script src="/../js/jquery/jquery-2.1.3.min.js" type="text/javascript"></script>
<script src="/../js/jquery/datatables.min.js" type="text/javascript"></script>

Dann muss ein DIV-Element um die Datentabelle herum eingefügt werden, damit die Tabelle per JS angesprochen werden kann.

Hinter der Tabelle braucht es dann noch ein HTML-Element mit etwas Code, um die Cognos-Datentabelle in eine jQuery-dataTable umzuwandeln.

Um das deutsche Zahlenformat korrekt im Excel-Export zu erhalten, müssen die Zahlen vor dem Export formatiert werden. Dazu wird beim Laden der dataTable ein Array mit den Dimensionsspalten ermittelt. Dieses geschieht hier über die Spaltentitelhintergrundfarbe, kann aber auch über Namen etc. elegant gelöst werden.

Datentabelle über ein DIV ansprechbar machen und dataTables-Initialisierung

<div tableWrapper>

<div id="dataTable_wrapper">

</div>

</div>

<datatable>

<script>
$('#dataTable_wrapper table').append("<thead>");
$('#dataTable_wrapper table thead').append($('#dataTable_wrapper table tbody').children()[0]);
let hdr = $('#dataTable_wrapper table thead').html();
hdr = hdr.replace(/<td /g,"<th ").replace(/<\/td>/g,"</th>");
$('#dataTable_wrapper table thead').html(hdr);
let dimColumns=[];

$('#dataTable_wrapper table thead th').each((id,elem)=>{
if($(elem).css("backgroundColor")=="rgb(224, 224, 224)") {
  dimColumns.push(id);
}
});

var dt = $("#dataTable_wrapper table").dataTable({
    scrollY: false,
    scrollX: false,
    scrollCollapse: true,
    paging: false,
   search: {
     regex: true,
    smart: false
   },
    ordering: true,
    order: [
    ],
    dom: 'Bfrtsp',
    buttons: [{
      extend: 'excelHtml5',
      exportOptions: {
        columns: ':visible',
        format: {
          body: (data, row, column, node) => {
           if(dimColumns.includes(column)) {
            return node.innerText;
          }else{
       return node.innerText.replace(/\./g,"").replace(",",".");
          }
          }
        }
      },
      customize: (xlsx) => {
        let sheet = xlsx.xl.worksheets['sheet1.xml'];
        //$('c[r^="A"]', sheet).attr('s', '50');
        $('c[r=A1]', sheet).attr('s', '7');
        $('c[r=A3]', sheet).attr('s', '4');
      },
      text: 'Save as Excel',
      messageTop: 'Commercials Analysis',
      sheetName: 'Commercials Analysis',
      title: 'Commercials Analysis',
      extension: '.xlsx',
    }]
  })
</script>

Wenn man eine lange Auswahlliste mit 100en Einträge hat, kann es sehr mühsam sein, hieraus den richtigen Eintrag zu finden. Oder, wenn die User an die Eingabe von Nummern gewöhnt sind, aber der Bezeichner der Eintrags dennoch zur Anzeige benötigt wird, kann man sich mit einem Such-Pop-up behelfen.

Hierzu muss man erst ein DIV in der Eingabeaufforderungsseite definieren.

<div id="targetgroup"></div>

Zusätzlich benötigt man ein weiteres DIV, das als Pop-up fungiert und den JS-Code enthält, der die möglichen Einträge aus einer versteckten Cognos-Auswahlliste ausliest und dann die Suchfunktion bereitstellt. Dies wird im zweiten HTML-Element eingefügt.

<div id="input_tg"
  style="display:none;position:absolute;z-index:100;width:250px;margin-top:-40px;margin-left:10px;background-color:#eee;border:1px solid #333;">
</div>

<script>

  var checkTG = (id) => {
    var __tg_fil = [];
    var __tg_sel = [];
    var __tg_item = [];
    var __id_len = id.length;
    var __div_tg = document.getElementById("input_tg");
    var __li;
    var __ul;
    var __tx;

    if (__div_tg.firstChild) {
      __div_tg.removeChild(__div_tg.firstChild);
    }
    if (__div_tg.style.display == "block") {
      __div_tg.style.display = "none";
    }

    if (__id_len < 1) return false;

    for (var y = 0; y < _tg_list.length; y++) {
      var __fil_id = _tg_list[y][0].substr(0, __id_len);
      if (__fil_id == id) {
        __tg_sel.push(_tg_list[y][0] + ' - ' + _tg_list[y][1]);
      }
    }
    if (__tg_sel.length == 0) {
      __tx = document.createTextNode("Keine Treffer!");
      __div_tg.appendChild(__tx);
      __div_tg.style.display = "block";
      document.getElementById("targetgroup").innerHTML = '<span style="color:red;">Keine Treffer!</span>';
      return false;
    }
    var __ul = document.createElement("ul");
    for (let z1 = 0, z_len = __tg_sel.length; z1 < z_len; z1++) {
      var __li = document.createElement("li");
      __li.style.listStyleType = "none";
      __li.style.marginLeft = "-10px";
      var __tx = document.createTextNode(__tg_sel[z1]);
      __li.appendChild(__tx);
      __ul.appendChild(__li);
    }
    __div_tg.appendChild(__ul);
    __div_tg.style.display = "block";
    __tg_fil = new Array();
    __tg_sel = new Array();
    __tg_name = "Keine eindeutigen Treffer!";
    for (let y = 0, y_len = _tg_list.length; y < y_len; y++) {
      if (_tg_list[y][0] == id) {
        __tg_name = _tg_list[y][1];
      }
    }
    document.getElementById("targetgroup").innerHTML = '<span style="color:green;">' + __tg_name + '</span>';
  setParamValue("P_TXT_TARGETGROUP_MANUELL_TXT", __tg_name);
    return false;
  }

findControl("P_TXT_TARGETGROUP_MANUELL").addEventListener("keyup", function (e) { checkTG(e.srcElement.value); return false; });
findControl("P_TXT_TARGETGROUP_MANUELL").addEventListener("blur", function (e) { document.getElementById('input_tg').style.display = 'none'; return false; });
</script>

Hinweis: Der obige Code setzt das Vorhandensein der cognosHelper-Klasse voraus, um die Funktionen "findControl" und "setParamValue" verwenden zu können.

Im Bericht sieht das dann folgendermaßen aus

Pop-up-Definition im Bericht

Das fertige Widget sieht dann so aus. Im Eingabefeld kann man Ziffern eintragen und bekommt im Popup alle passenden Einträge angezeigt. Wenn nur ein Eintrag übrig ist, wird dieser Wert in den Parameter übernommen.

Fertiges Auswahl-Pop-up im Bericht

Free Joomla templates by L.THEME