Saiku默认给数据类型的数据添加小数点问题处理(三十一)

Saiku默认给数据类型的数据添加小数点问题处理

不知道大家有没有遇到过saiku定义的维度信息,数据类型时 展示出来的数据会自动加上 .0的后缀。

比如我定义了一个维度为 年, 在数据库中为 int类型,值为2018 ,结果在saiku中展示就自动变成了 2018.0  ,这个好像还是个概率性事件...  一模一样的配置,有些会自动带上小数点 有些正常显示。

对于此问题,我看了看后台接口 execute,接口的返回结果集中就添加了小数点,所以我目前的应对处理方案是在table渲染页面更改值。

SaikuTableRenderer.js 文件中,在此代码前  for (var col = 0, colLen = table[row].length; col < colLen; col++) {      添加如下代码    ,文章末尾处会提供完整的js文件信息 大概是400多行的位置

//循環遍歷data 將帶小數的年、月去掉小數位; 例如 2018.0 轉換為 2018
for (var col = 0, colLen = table[row].length; col < colLen; col++) {
	var tmpRow = data[row][col];
	if(tmpRow.properties.hierarchy=="[年].[年]" || tmpRow.properties.hierarchy=="[月].[月]"){ //判断是否为年和月维度
		var tmpValue = tmpRow.value;
		if(tmpValue != null && tmpValue.indexOf('.')>-1){ //判断是否有小数点信息
			tmpValue = tmpValue.substr(0,tmpValue.indexOf('.'));//去掉小數位
			data[row][col].value = tmpValue; //重新给data的value赋值(新值中已经去掉了小数点)
		}
	}
}

  

在schame的cube中关于维度 年, 月的定义如下:

    <Dimension name="年" foreignKey="ID" >
		<Hierarchy  hasAll="true" primaryKey="ID" allMemberName="年" >
			 <Level name="年" column="statisyear"  uniqueMembers="false" />
		</Hierarchy>
        </Dimension> 
		
	<Dimension name="月" foreignKey="ID" >
		<Hierarchy  hasAll="true" primaryKey="ID" allMemberName="月" >
			 <Level name="月" column="statismonth"  uniqueMembers="false" />
		</Hierarchy>
        </Dimension> 

  

针对去除不必要的小数点其实还有其他方案可行

>>1 更改数据库中年,月的数据类型为 char类型,不使用数据类型(int)

>>2 通过定义参数来处理,就不用走这么多for循环了... 但是这样子的话 不带参数访问saiku数据时 是没有达到去除的效果的,而且参数过多可能请求会被拦截...  所以我没有用参数去做。

因为改动的是js文件,所以不需要重新编译saiku哦,直接到saiku-server下更改文件,然后刷新浏览器即可看到效果~

最后提供一下更改后的完整的SaikuTableRenderer.js文件

function SaikuTableRenderer(data, options) {
    this._data = data;
    this._options = _.extend({}, SaikuRendererOptions, options);
}

function getAxisLevelsName(data, axisName) {
    var queryData = data.query.queryModel.axes[axisName].hierarchies;
    var len = queryData.length;
    var arrLevels = [];

    for (var i = 0; i < len; i++) {
        for (var level in queryData[i].levels) {
            if (queryData[i].levels.hasOwnProperty(level)) {
                if (Settings.COLUMN_TITLE_TABLE_USE_LEVEL_CAPTION_NAME) {
                    arrLevels.push(queryData[i].levels[level].caption);
                }
                else {
                    arrLevels.push(level);
                }
            }
        }
    }

    return arrLevels;
}

function setStyleNegativeNumber(value) {
    var className = '';

    if (Settings.STYLE_NEGATIVE_NUMBER && parseFloat(value) < 0) {
        className = ' style_negative_number ';
    }

    return className;
}

function getAxisSize(data, axisName) {
    var queryData = data.query.queryModel.axes[axisName].hierarchies;
    var len = queryData.length;
    var axisSize = 0;

    for (var i = 0; i < len; i++) {
        axisSize += _.size(queryData[i].levels);
    }

    return axisSize;
}

function getDomColumnsLevelsName(htmlObject) {
    var $htmlObject = $(htmlObject.closest('.workspace')
                           .find('.workspace_fields')
                           .find('.columns.axis_fields')
                           .find('.hierarchy')
                           .find('.d_level'));
    var arrLevels = [];

    $.each($htmlObject, function(key, level) {
        if ($(level).attr('style') === 'display: list-item;') {
            if (Settings.COLUMN_TITLE_TABLE_USE_LEVEL_CAPTION_NAME) {
                arrLevels.push($(level).find('.level').attr('title'));
            }
            else {
                arrLevels.push($(level).find('.level').attr('level'));
            }
        }
    });

    return arrLevels;
}

/*table render method*/
SaikuTableRenderer.prototype.render = function(data, options) {
        var self = this;
        if (data) {
            this._data = data;
        }
        if (options) {
            this._options = _.extend({}, SaikuRendererOptions, options);
        }

        if (typeof this._data == "undefined") {
            return;
        }

        if (this._data != null && this._data.error != null) {
            return;
        }
        if (this._data == null || (this._data.cellset && this._data.cellset.length === 0)) {
            return;
        }

        this.hideEmpty = this._options.hideEmpty;

        if (this._options.htmlObject) {
//            $(this._options.htmlObject).stickyTableHeaders("destroy");

            // in case we have some left over scrollers
            if (self._options.hasOwnProperty('batch')) {
                $(self._options.htmlObject).parent().parent().unbind('scroll');
            }

            _.defer(function(that) {
                if (self._options.hasOwnProperty('batch') && !self._options.hasOwnProperty('batchSize')) {
                    self._options['batchSize'] = 1000;
                }
				
				// the key method to render data by table form. 20190423
                var html =  self.internalRender(self._data, self._options);
                $(self._options.htmlObject).html(html);
                // Render the totals summary
                $('#totals_summary').remove(); // Remove one previous totals div, if present
                $(self._options.htmlObject).after(self.renderSummary(data)); // Render the new summary

//                $(self._options.htmlObject).stickyTableHeaders( { container: self._options.htmlObject.parent().parent(), fixedOffset: self._options.htmlObject.parent().parent().offset().top });

                _.defer(function(that) {
                    if (self._options.hasOwnProperty('batch') && self._options.hasBatchResult) {
                        var batchRow = 0;
                        var batchIsRunning = false;
                        var batchIntervalSize = self._options.hasOwnProperty('batchIntervalSize') ? self._options.batchIntervalSize : 20;
                        var batchIntervalTime = self._options.hasOwnProperty('batchIntervalTime') ? self._options.batchIntervalTime : 20;

                        var len = self._options.batchResult.length;

                        var batchInsert = function() {
                            // maybe add check for reach table bottom - ($('.workspace_results').scrollTop() , $('.workspace_results table').height()
                            if (!batchIsRunning && len > 0 && batchRow < len) {
                                batchIsRunning = true;
                                var batchContent = "";
                                var startb = batchRow;
                                for (var i = 0;  batchRow < len && i < batchIntervalSize ; i++, batchRow++) {
                                    batchContent += self._options.batchResult[batchRow];
                                }
                                if (batchRow > startb) {
                                    $(self._options.htmlObject).append( $(batchContent));
                                }
                                batchIsRunning = false;
                            }
                            if (batchRow >= len) {
                                $(self._options.htmlObject).parent().parent().unbind('scroll');
                            }
                        };

                        var lazyBatchInsert = _.debounce(batchInsert, batchIntervalTime);
                        $(self._options.htmlObject).parent().parent().scroll(function () {
                            lazyBatchInsert();
                        });
                    }
                });
                return html;
            });
        } else {
            var html =  this.internalRender(this._data, self._options);
            return html;
        }

};

SaikuTableRenderer.prototype.clear = function(data, options) {
    var self = this;
    if (this._options && this._options.htmlObject && this._options.hasOwnProperty('batch')) {
        $(self._options.htmlObject).parent().parent().unbind('scroll');
    }

};

SaikuTableRenderer.prototype.processData = function(data, options) {
    this._hasProcessed = true;
};

function genTotalDataCells(currentIndex, cellIndex, scanSums, scanIndexes, lists) {
    var contents = '';
    var lists = lists[ROWS];

    for (var i = scanSums.length - 1; i >= 0; i--) {
        if (currentIndex == scanSums[i]) {
            var currentListNode = lists[i][scanIndexes[i]];
            for (var m = 0; m < currentListNode.cells.length; m++) {
                contents += '<td class="data total">' + currentListNode.cells[m][cellIndex].value + '</td>';
            }

            scanIndexes[i]++;
            if (scanIndexes[i] < lists[i].length)
                scanSums[i] += lists[i][scanIndexes[i]].width;
        }
    }

    return contents;
}

function genTotalHeaderCells(currentIndex, bottom, scanSums, scanIndexes, lists, wrapContent) {
    var contents = '';
    for (var i = bottom; i >= 0; i--) {
        if (currentIndex == scanSums[i]) {
            var currentListNode = lists[i][scanIndexes[i]];
            var cssClass;
            if (i == 0 && bottom == 1)
                cssClass = "col";
            else if (i == bottom)
                cssClass = "col_total_corner";
            else if (i == bottom - 1 && currentListNode.captions)
                cssClass = "col_total_first";
            else cssClass = "col_null";

            for (var m = 0; m < currentListNode.cells.length; m++) {
                var text = ' ';
                if (bottom == lists.length - 1) {
                    if (currentListNode.captions) {
                        text = lists[i][scanIndexes[i]].captions[m];
                    }
                    if (i == 0 && scanIndexes[i] == 0) {
                        if (currentListNode.captions)
                            text += " ";
                        else text = "";
                        text += (wrapContent ? "<span class='i18n'>Grand Total</span>" :  "Grand Total");
                    }
                }
                contents += '<th class="' + cssClass + '">'
                  + (wrapContent ? '<div>' + text + '</div>' : text ) + '</th>';
            }
            scanIndexes[i]++;
            if (scanIndexes[i] < lists[i].length)
                scanSums[i] += lists[i][scanIndexes[i]].width;
        }
    }
    return contents;
}

function totalIntersectionCells(currentIndex, bottom, scanSums, scanIndexes, lists) {
    var contents = '';
    for (var i = bottom; i >= 0; i--) {
        if (currentIndex == scanSums[i]) {
            var currentListNode = lists[i][scanIndexes[i]];
            var cssClass = "data total";
            for (var m = 0; m < currentListNode.cells.length; m++) {
                var text = ' ';
                contents += '<td class="' + cssClass + '">' + text + '</td>';
            }
            scanIndexes[i]++;
            if (scanIndexes[i] < lists[i].length)
                scanSums[i] += lists[i][scanIndexes[i]].width;
        }
    }
    return contents;
}

function isNextTotalsRow(currentIndex, scanSums, scanIndexes, totalsLists, wrapContent) {
    var colLists = totalsLists[COLUMNS];
    var colScanSums = scanSums[COLUMNS];
    var colScanIndexes = scanIndexes[COLUMNS];
    var bottom = colLists.length - 2;
    var contents = -1;
    for (var i = bottom; i >= 0; i--) {
        if (currentIndex == colScanSums[i]) {
            for (var m = 0; m < colLists[i][colScanIndexes[i]].cells.length; m++) {
                contents += '<tr>';
                for (var j = 0; j <= bottom; j++) {
                    var cssClass;
                    var text = ' ';
                    if (i == 0 && j == 0)
                        cssClass = 'row';
                    else if (i == j + 1){
                        cssClass = 'row_total_corner';
                        return j;
                    }
                    else if (i == j && colLists[i][colScanIndexes[i]].captions) {
                        cssClass = 'row_total_first';
                    } else if (i < j + 1)
                        cssClass = 'row_total';
                    else
                        cssClass = 'row_null';
                    if (j == bottom ) {
                        if (colLists[i][colScanIndexes[i]].captions) {
                            text = colLists[i][colScanIndexes[i]].captions[m];
                        }
                        if (i == 0 && colScanIndexes[i] == 0) {
                            if (colLists[i][colScanIndexes[i]].captions)
                                text += " ";
                            else text = "";
                            text += (wrapContent ? "<span class='i18n'>Grand Total</span>" :  "Grand Total");
                        }
                    }

                }
            }
        }
    }
    return -1;
}

function genTotalHeaderRowCells(currentIndex, scanSums, scanIndexes, totalsLists, wrapContent) {
    var colLists = totalsLists[COLUMNS];
    var colScanSums = scanSums[COLUMNS];
    var colScanIndexes = scanIndexes[COLUMNS];
    var bottom = colLists.length - 2;
    var contents = '';
    for (var i = bottom; i >= 0; i--) {
        if (currentIndex == colScanSums[i]) {
            for (var m = 0; m < colLists[i][colScanIndexes[i]].cells.length; m++) {
                contents += '<tr>';
                for (var j = 0; j <= bottom; j++) {
                    var cssClass;
                    var text = ' ';
                    if (i == 0 && j == 0)
                        cssClass = 'row';
                    else if (i == j + 1)
                        cssClass = 'row_total_corner';
                    else if (i == j && colLists[i][colScanIndexes[i]].captions) {
                        cssClass = 'row_total_first';
                    } else if (i < j + 1)
                        cssClass = 'row_total';
                    else
                        cssClass = 'row_null';
                    if (j == bottom ) {
                        if (colLists[i][colScanIndexes[i]].captions) {
                            text = colLists[i][colScanIndexes[i]].captions[m];
                        }
                        if (i == 0 && colScanIndexes[i] == 0) {
                            if (colLists[i][colScanIndexes[i]].captions)
                                text += " ";
                            else text = "";
                            text += (wrapContent ? "<span class='i18n'>Grand Total</span>" :  "Grand Total");
                        }
                    }
                    contents += '<th class="' + cssClass + '">'
                                + (wrapContent ? '<div>' + text + '</div>' : text ) + '</th>';

                }

                var scanIndexes = {};
                var scanSums = {};

                if (totalsLists[ROWS]) {
                    for (var z = 0; z < totalsLists[ROWS].length; z++) {
                        scanIndexes[z] = 0;
                        scanSums[z] = totalsLists[ROWS][z][scanIndexes[z]].width;
                    }
                }

                for (var k = 0; k < colLists[i][colScanIndexes[i]].cells[m].length; k++) {
                    contents += '<td class="data total">' + colLists[i][colScanIndexes[i]].cells[m][k].value + '</td>';

                    if (totalsLists[ROWS]) {
                        contents += totalIntersectionCells(k + 1, totalsLists[ROWS].length - 1, scanSums, scanIndexes, totalsLists[ROWS]);
                    }
                }

                contents += '</tr>';
            }

            colScanIndexes[i]++;

            if (colScanIndexes[i] < colLists[i].length) {
                colScanSums[i] += colLists[i][colScanIndexes[i]].width;
            }
        }
    }
    return contents;
}

var ROWS = "ROWS";
var COLUMNS = "COLUMNS";

function nextParentsDiffer(data, row, col) {
    while (row-- > 0) {
        if (data[row][col].properties.uniquename != data[row][col + 1].properties.uniquename)
            return true;
    }
    return false;
}


function topParentsDiffer(data, row, col) {
    while (col-- > 0)
        if (data[row][col].properties.uniquename != data[row - 1][col].properties.uniquename)
            return true;
    return false;
}

/**
 * This function is intended to traverse the totals arrays and cleanup empty
 * totals. This will optimize the query result on screen, displaying just the
 * needed cells.
 * @param dirs The direction array ['ROWS', 'COLUMNS']
 * @param totalsLists The totals from allData.rowTotalsLists and allData.colTotalsLists.
 */
function cleanupTotals(dirs, totalsLists) {
    // For each direction (ROWS/COLUMNS)
    for (var dirIndex = 0; dirIndex < dirs.length; dirIndex++) {
        var dir = dirs[dirIndex];

        // If there are defined totals
        if (totalsLists[dir]) {
            var isEmpty = true; // A flag to indicate if this total is empty
            for (var row = 0; row < totalsLists[dir].length; row++) {
                var totalsInfoArray = totalsLists[dir][row];
                for (var totalIndex = 0; totalIndex < totalsInfoArray.length; totalIndex++) {
                    var cells = totalsLists[dir][row][totalIndex].cells;
                    for (var cellIndex = 0; cellIndex < cells.length; cellIndex++) {
                        var cellArray = cells[cellIndex];
                        // For each total cell
                        for (var i = 0; i < cellArray.length; i++) {
                            var cell = cellArray[i];
                            // If it contains a value different from empty
                            if (cell.value !== '-') {
                                isEmpty = false; // So, this total is not empty
                            }
                        }
                    }
                }
            }

            if (isEmpty) { // If this total is empty
                totalsLists[dir] = null; // Remove it
            }
        }
    }
}

/*the main method to render data by table form. 20190423*/
SaikuTableRenderer.prototype.internalRender = function(allData, options) {
    var tableContent = "";
    var rowContent = "";
    var data = allData.cellset;

    var newRowContent = '';
    var arrRowData = [];
    var objRowData = [];

    var table = data ? data : [];
    var colSpan;
    var colValue;
    var isHeaderLowestLvl;
    var isBody = false;
    var firstColumn;
    var isLastColumn, isLastRow;
    var nextHeader;
    var processedRowHeader = false;
    var lowestRowLvl = 0;
    var rowGroups = [];
    var batchSize = null;
    var batchStarted = false;
    var isColHeader = false, isColHeaderDone = false;
    var resultRows = [];
    var wrapContent = true;
    if (options) {
        batchSize = options.hasOwnProperty('batchSize') ? options.batchSize : null;
        wrapContent = options.hasOwnProperty('wrapContent') ? options.wrapContent : true;
    }
    var totalsLists = {};
    totalsLists[COLUMNS] = allData.rowTotalsLists;
    totalsLists[ROWS] = allData.colTotalsLists;

    var scanSums = {};
    var scanIndexes = {};

    var dirs = [ROWS, COLUMNS];

    var hasMeasures = allData.query && allData.query.queryModel && allData.query.queryModel.details
                   ? allData.query.queryModel.details.measures.length
                   : 0;

    if (typeof this._options.htmlObject === 'object' &&
        Settings.ALLOW_AXIS_COLUMN_TITLE_TABLE &&
        hasMeasures > 0 &&
        allData.query.type === 'QUERYMODEL' &&
        allData.query.queryModel.details.axis === 'COLUMNS' &&
        allData.query.queryModel.details.location === 'BOTTOM') {

        var arrColumnTitleTable = getAxisLevelsName(allData, COLUMNS);
        var arrDomColumnTitleTable = getDomColumnsLevelsName(this._options.htmlObject);
        var colspanColumnTitleTable = getAxisSize(allData, ROWS);
        var auxColumnTitleTable = 0;

        if (arrColumnTitleTable.length === arrDomColumnTitleTable.length) {
            arrColumnTitleTable = arrDomColumnTitleTable;
        }
        else {
            arrColumnTitleTable = _.intersection(arrDomColumnTitleTable, arrColumnTitleTable);
        }
    }

    for (var i = 0; i < dirs.length; i++) {
        scanSums[dirs[i]] = new Array();
        scanIndexes[dirs[i]] = new Array();
    }

    // Here we cleaup the empty totals
    cleanupTotals(dirs, totalsLists);

    if (totalsLists[COLUMNS]) {
        for (var i = 0; i < totalsLists[COLUMNS].length; i++) {
            scanIndexes[COLUMNS][i] = 0;
            scanSums[COLUMNS][i] = totalsLists[COLUMNS][i][scanIndexes[COLUMNS][i]].width;
        }
    }
	
	var headerFlag=true;// add this flag to solve the bug when same data to merge。 20190423
	var cubename = allData.query.cube.name;
    for (var row = 0, rowLen = table.length; row < rowLen; row++) {
        var rowShifted = row - allData.topOffset;
        colSpan = 1;
        colValue = "";
        isHeaderLowestLvl = false;
        isLastColumn = false;
        isLastRow = false;
        isColHeader = false;
        var headerSame = false;
	
        if (totalsLists[ROWS]) {
            for (var i = 0; i < totalsLists[ROWS].length; i++) {
                scanIndexes[ROWS][i] = 0;
                scanSums[ROWS][i] = totalsLists[ROWS][i][scanIndexes[ROWS][i]].width;
            }
        }

        rowWithOnlyEmptyCells = true; //默认行数据为空时不展展示,如果改回来 将此条值置为true即可
        
        //var paramsURI = Saiku.URLParams.paramsURI(); //get the param from url
        //var showEmptyRows = paramsURI.showEmptyRows;
		//if(showEmptyRows != null && showEmptyRows != undefined && showEmptyRows != '' && showEmptyRows=='yes') {
		if(cubename == "SummaryKPI_2018_ext" ||cubename == "SummaryKPI_2019_ext" ||cubename == "SummaryKPI_2019_Dynamic"){
			rowWithOnlyEmptyCells = false; //設置行數據為空的時候也顯示數據! 20190425 for summaryKPI Data
		}
        rowContent = "<tr>";
        var header = null;

        if (row === 0) {
            rowContent = "<thead>" + rowContent;
        }

        if (typeof this._options.htmlObject === 'object' &&
            Settings.ALLOW_AXIS_COLUMN_TITLE_TABLE &&
            hasMeasures > 0 &&
            allData.query.type === 'QUERYMODEL' &&
            allData.query.queryModel.details.axis === 'COLUMNS' &&
            allData.query.queryModel.details.location === 'BOTTOM' &&
            auxColumnTitleTable < arrColumnTitleTable.length) {

            rowContent += '<th class="row_header" style="text-align: right;" colspan="' + colspanColumnTitleTable + '" title="' + arrColumnTitleTable[auxColumnTitleTable] + '">'
                + (wrapContent ? '<div>' + arrColumnTitleTable[auxColumnTitleTable] + '</div>' : arrColumnTitleTable[auxColumnTitleTable])
                + '</th>';

            auxColumnTitleTable += 1;
        }
		
		
		//循環遍歷data 將帶小數的年、月去掉小數位; 例如 2018.0 轉換為 2018
		for (var col = 0, colLen = table[row].length; col < colLen; col++) {
			var tmpRow = data[row][col];
			if(tmpRow.properties.hierarchy=="[年].[年]" || tmpRow.properties.hierarchy=="[月].[月]"){
				var tmpValue = tmpRow.value;
				if(tmpValue != null && tmpValue.indexOf('.')>-1){
					tmpValue = tmpValue.substr(0,tmpValue.indexOf('.'));//去掉小數位
					data[row][col].value = tmpValue;
				}
			}
		}
		
		
		
        for (var col = 0, colLen = table[row].length; col < colLen; col++) {
			
            var colShifted = col - allData.leftOffset;
            header = data[row][col];

            if (header.type === "COLUMN_HEADER") {
                isColHeader = true;
            }

            // If the cell is a column header and is null (top left of table)
            if (header.type === "COLUMN_HEADER" && header.value === "null" && (firstColumn == null || col < firstColumn)) {
                if (((!Settings.ALLOW_AXIS_COLUMN_TITLE_TABLE || (Settings.ALLOW_AXIS_COLUMN_TITLE_TABLE && allData.query.queryModel.details.location !== 'BOTTOM')) || hasMeasures === 0) ||
                    allData.query.type === 'MDX') {
                    rowContent += '<th class="all_null"> </th>';
                }
            } // If the cell is a column header and isn't null (column header of table)
            else if (header.type === "COLUMN_HEADER") {
                if (firstColumn == null) {
                    firstColumn = col;
                }
                if (table[row].length == col+1)
                    isLastColumn = true;
                else
                    nextHeader = data[row][col+1];


                if (isLastColumn) {
                    // Last column in a row...
                    if (header.value == "null") {
                        rowContent += '<th class="col_null"> </th>';
                    } else {
                        if (totalsLists[ROWS])
                            colSpan = totalsLists[ROWS][row + 1][scanIndexes[ROWS][row + 1]].span;
                        rowContent += '<th class="col" style="text-align: center;" colspan="' + colSpan + '" title="' + header.value + '">'
                            + (wrapContent ? '<div rel="' + row + ":" + col +'">' + header.value + '</div>' : header.value)
                            + '</th>';
                    }

                } else {
                    // All the rest...
                    var groupChange = (col > 1 && row > 1 && !isHeaderLowestLvl && col > firstColumn) ?
                        data[row-1][col+1].value != data[row-1][col].value || data[row-1][col+1].properties.uniquename != data[row-1][col].properties.uniquename
                        : false;

                    var maxColspan = colSpan > 999 ? true : false;
                    if (header.value != nextHeader.value || nextParentsDiffer(data, row, col) || isHeaderLowestLvl || groupChange || maxColspan) {
                        if (header.value == "null") {
                            rowContent += '<th class="col_null" colspan="' + colSpan + '"> </th>';
                        } else {
                            if (totalsLists[ROWS])
                                colSpan = totalsLists[ROWS][row + 1][scanIndexes[ROWS][row + 1]].span;
                            rowContent += '<th class="col" style="text-align: center;" colspan="' + (colSpan == 0 ? 1 : colSpan) + '" title="' + header.value + '">'
                            + (wrapContent ? '<div rel="' + row + ":" + col +'">' + header.value + '</div>' : header.value)
                            + '</th>';
                        }
                        colSpan = 1;
                    } else {
                        colSpan++;
                    }
                }
                if (totalsLists[ROWS])
                    rowContent += genTotalHeaderCells(col - allData.leftOffset + 1, row + 1, scanSums[ROWS], scanIndexes[ROWS], totalsLists[ROWS], wrapContent);
            } // If the cell is a row header and is null (grouped row header)
            else if (header.type === "ROW_HEADER" && header.value === "null") {
                rowContent += '<th class="row_null"> </th>';
            } // If the cell is a row header and isn't null (last row header)
            else if (header.type === "ROW_HEADER") {
                if (lowestRowLvl == col)
                    isHeaderLowestLvl = true;
                else
                    nextHeader = data[row][col+1];

                var previousRow = data[row - 1];
                var nextRow = data[row + 1];
				// when  same set fixed value is false ,It means the same data will not merge。table data will  show row by row.20190423
				//var same=false; 
				
				/*judge the current value and previousRow value,
				if equals ,all set comeback,set the headerFlag is true, 
				we can judge the data as usual. 20190423*/
				if(header.value !== previousRow[col].value){
					headerFlag =true;
				}

				/*judge the tableContent include value or not, if include ,
				set the headerFlag value is true to avoid repeat datas showed in table.20190423*/
				if(tableContent.indexOf(header.value) > -1 ){
					headerFlag =true;
				}
	
				/*add headerFlag to judge the data is same ,then control the data merge wheather or not.20190423 */
				var same = !headerSame && !isHeaderLowestLvl && (col == 0 || !topParentsDiffer(data, row, col)) && header.value === previousRow[col].value && headerFlag;
                headerSame = !same;
                var sameAsPrevValue = false;
                if(Settings.ALLOW_TABLE_DATA_COLLAPSE){
                    if (row > 0 && row < rowLen - 1) {
                        if (totalsLists[ROWS] == null || (col <= colLen - totalsLists[ROWS].length - 1)) {
                            var checkOther = true;
                            if (totalsLists[COLUMNS] && rowShifted >= 0 && col <= isNextTotalsRow(rowShifted + 1, scanSums, scanIndexes, totalsLists, wrapContent)) {
                                sameAsPrevValue = true;
                                checkOther = false;
                            }
                            if (checkOther && nextRow[col].value == header.value) {
                                if (col > 0) {
                                    for (var j = 0; j < col; j++) {
                                        if (nextRow[j].value == data[row][j].value) {
                                            sameAsPrevValue = true;
                                        } else {
                                            sameAsPrevValue = false;
                                            break;
                                        }
                                    }
                                } else {
                                    sameAsPrevValue = true;
                                }
                            }
                        }
                    } else if(row > 0 && row == rowLen - 1) {
                        if (totalsLists[COLUMNS] && rowShifted >= 0 && col <= isNextTotalsRow(rowShifted + 1, scanSums, scanIndexes, totalsLists, wrapContent)) {
                            sameAsPrevValue = true;
                        }
                    }
                }
                var value = (same ? "<div> </div>" : '<div rel="' + row + ":" + col + '">'
                            + (sameAsPrevValue && Settings.ALLOW_TABLE_DATA_COLLAPSE ? '<span class="expander expanded" style="cursor: pointer;">▼</span>' : '' ) + header.value + '</div>');
                if (!wrapContent) {
                    value = (same ? " " : header.value );
                }
                var tipsy = "";
                /* var tipsy = ' original-title="';
                if (!same && header.metaproperties) {
                    for (key in header.metaproperties) {
                        if (key.substring(0,1) != "$" && key.substring(1,2).toUpperCase() != key.substring(1,2)) {
                            tipsy += "<b>" + safe_tags_replace(key) + "</b> : " + safe_tags_replace(header.metaproperties[key]) + "<br>";
                        }
                    }
                }
                tipsy += '"';
                */
                var cssclass = (same ? "row_null" : "row");
                var colspan = 0;

                if (!isHeaderLowestLvl && (typeof nextHeader == "undefined" || nextHeader.value === "null")) {
                    colspan = 1;
                    var group = header.properties.dimension;
                    var level = header.properties.level;
                    var groupWidth = (group in rowGroups ? rowGroups[group].length - rowGroups[group].indexOf(level) : 1);
                    for (var k = col + 1; colspan < groupWidth && k <= (lowestRowLvl+1) && data[row][k] !== "null"; k++) {
                        colspan = k - col;
                    }
                    col = col + colspan -1;
                }
				
				/*when the content is to long ,we will set new line to show it.*/
				// eg value: <div rel="3:0">新業務及保單行政部</div>
				if(cssclass == "row" && value.length>0){
					var startPos = value.indexOf('>'); //find  start position of the tag. eg: <div rel="3:0">
					var endPos = value.lastIndexOf('<'); //find  end position of the tag. eg: </div>
					var tmpValue = value.substr( startPos+1 ,endPos-startPos-1); // get the content value. eg: 新業務及保單行政部
					//将value值每隔40个字自动加上换行符
					//each 40 character add one <br> tag to get new line. 
					if(tmpValue.length>120){ 
						tmpValue = tmpValue.substr(0,40)+"<br/>"+tmpValue.substr(40,40)+"<br/>"+tmpValue.substr(80,40)+"<br/>"+tmpValue.substr(120,tmpValue.length-120);
					}else if(tmpValue.length>80){ 
						tmpValue = tmpValue.substr(0,40)+"<br/>"+tmpValue.substr(40,40)+"<br/>"+tmpValue.substr(80,tmpValue.length-80);
					}else if(tmpValue.length>40){
						tmpValue = tmpValue.substr(0,40)+"<br/>"+tmpValue.substr(40,tmpValue.length-40);
					}
					
					// compared with old value, this value only add <br> tag for show data in table more beautiful.
					value = value.substr(0,startPos+1) + tmpValue + value.substr(endPos,value.length-endPos);
				}
                rowContent += '<th class="' + cssclass + '" ' + (colspan > 0 ? ' colspan="' + colspan + '"' : "") + tipsy + '>' + value + '</th>';
            }
            else if (header.type === "ROW_HEADER_HEADER") {
                var hierName = function(data) {
                    var hier = data.properties.hierarchy;
                    var name = hier.replace(/[[]]/gi, '').split('.')[1]
                        ? hier.replace(/[[]]/gi, '').split('.')[1]
                        : hier.replace(/[[]]/gi, '').split('.')[0];

                    return name;
                };
                var arrPosRowData = [];

                if (_.contains(arrRowData, header.value)) {
                    for (var i = 0; i < arrRowData.length; i++) {
                        if (arrRowData[i] === header.value) {
                            arrPosRowData.push(i);
                        }
                    }

                    arrPosRowData.push(col);
                }

                rowContent += '<th class="row_header">' + (wrapContent ? '<div>' + header.value + '</div>' : header.value) + '</th>';

                arrRowData.push(header.value);
                objRowData.push({
                    name: header.value,
                    hierName: hierName(header) + '/' + header.value
                });

                isHeaderLowestLvl = true;
                processedRowHeader = true;
                lowestRowLvl = col;
                if (header.properties.hasOwnProperty("dimension")) {
                    var group = header.properties.dimension;
                    if (!(group in rowGroups)) {
                        rowGroups[group] = [];
                    }
                    rowGroups[group].push(header.properties.level);
                }

                if (arrPosRowData.length > 0) {
                    var aux = 0;

                    rowContent = '<tr>';

                    if (row === 0) {
                        rowContent = '<thead>' + rowContent;
                    }

                    for (var i = 0; i < objRowData.length; i++) {
                        if (arrPosRowData[aux] === i) {
                            newRowContent += '<th class="row_header">' + (wrapContent ? '<div>' + objRowData[i].hierName + '</div>' : objRowData[i].hierName) + '</th>';
                            aux += 1;
                        }
                        else {
                            newRowContent += '<th class="row_header">' + (wrapContent ? '<div>' + objRowData[i].name + '</div>' : objRowData[i].name) + '</th>';
                        }
                    }

                    rowContent += newRowContent;
                }
            } // If the cell is a normal data cell
            else if (header.type === "DATA_CELL") {
                batchStarted = true;
                var color = "";
                var val = _.isEmpty(header.value) ? Settings.EMPTY_VALUE_CHARACTER : header.value;
                var arrow = "";

                if (header.properties.hasOwnProperty('image')) {
                    var img_height = header.properties.hasOwnProperty('image_height') ? " height='" + header.properties.image_height + "'" : "";
                    var img_width = header.properties.hasOwnProperty('image_width') ? " width='" + header.properties.image_width + "'" : "";
                    val = "<img " + img_height + " " + img_width + " style='padding-left: 5px' src='" + header.properties.image + "' border='0'>";
                }

                // Just apply formatting to non-empty cells
                if (val !== '-' && val !== '' && header.properties.hasOwnProperty('style')) {
                    color = " style='background-color: " + header.properties.style + "' ";
                }
                if (header.properties.hasOwnProperty('link')) {
                    val = "<a target='__blank' href='" + header.properties.link + "'>" + val + "</a>";
                }
                if (header.properties.hasOwnProperty('arrow')) {
                    arrow = "<img height='10' width='10' style='padding-left: 5px' src='./images/arrow-" + header.properties.arrow + ".gif' border='0'>";
                }

                if (val !== '-' && val !== '') {
                    rowWithOnlyEmptyCells = false;
                }

                rowContent += '<td class="data" ' + color + '>'
                        + (wrapContent ? '<div class="datadiv '+ setStyleNegativeNumber(header.properties.raw) + '" alt="' + header.properties.raw + '" rel="' + header.properties.position + '">' : "")
                        + val + arrow
                        + (wrapContent ? '</div>' : '') + '</td>';
                if (totalsLists[ROWS])
                    rowContent += genTotalDataCells(colShifted + 1, rowShifted, scanSums[ROWS], scanIndexes[ROWS], totalsLists, wrapContent);
            }
        }
        rowContent += "</tr>";

        // Change it to let hideEmpty true by default
        if (options.hideEmpty && header.type === "DATA_CELL" && rowWithOnlyEmptyCells) {
		   /*when data_cell is null,set the headerFlag is false ,
		   to fix the problem data merge inccrrect.
		   */
		   headerFlag=false;
			rowContent = '';
        }

        var totals = "";
        if (totalsLists[COLUMNS] && rowShifted >= 0) {
            totals += genTotalHeaderRowCells(rowShifted + 1, scanSums, scanIndexes, totalsLists, wrapContent);
        }
        if (batchStarted && batchSize) {
                if (row <= batchSize) {
                    if (!isColHeader && !isColHeaderDone) {
                        tableContent += "</thead><tbody>";
                        isColHeaderDone = true;
                    }
                    tableContent += rowContent;
                    if (totals.length > 0) {
                        tableContent += totals;
                    }

                } else {
                    resultRows.push(rowContent);
                    if (totals.length > 0) {
                        resultRows.push(totals);
                    }

                }
        } else {
            if (!isColHeader && !isColHeaderDone) {
                tableContent += "</thead><tbody>";
                isColHeaderDone = true;
            }
            tableContent += rowContent;
            if (totals.length > 0) {
                tableContent += totals;
            }
        }
    }
    if (options) {
        options['batchResult'] = resultRows;
        options['hasBatchResult'] = resultRows.length > 0;
    }
    return "<table>" + tableContent + "</tbody></table>";
};

SaikuTableRenderer.prototype.renderSummary = function(data) {
    if (data && data.query) {
        var hasSomethingToRender = false;
        var measures = data.query.queryModel.details
                       ? data.query.queryModel.details.measures
                       : [];
        var summaryData = {};

        for (var i = 0; i < measures.length; i++) {
            var m = measures[i];
            if (m.aggregators) {
                for (var j = 0; j < m.aggregators.length; j++) {
                    var a = m.aggregators[j];
                    if (a.indexOf('_') > 0) {
                        var tokens = a.split('_');
                        var aggregator = tokens[0];
                        var axis = tokens[1];

                        if (aggregator !== 'nil' && aggregator !== 'not') {
                            hasSomethingToRender = true;
                            aggregator = aggregator.capitalizeFirstLetter();
                            if (!(axis in summaryData)) summaryData[axis] = [];
                            summaryData[axis].push(m.name + ": " + aggregator);
                        }
                    }
                }
            }
        }
        
        if (hasSomethingToRender) {
            var summary = "<div id='totals_summary'><br/>";

            $.each(summaryData, function(key, aggregators) {
                summary += "<h3>" + key.capitalizeFirstLetter();
                for (var i = 0; i < aggregators.length; i++) {
                    summary += "<br/> " + aggregators[i];
                }
                summary += "</h3>";
            });

            return summary + "</div>";
        }
    }

    return "";
};

String.prototype.capitalizeFirstLetter = function() {
    return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase();
}

  

 ========二次更新,后台导出excel也有默认的小数点 2018.0问题处理=======20190605============start=======

处理方案:

修改saiku后台代码,OlapResultSetUtil.java 类 的 cellSet2Matrix( final CellSet cellSet, ICellSetFormatter formatter )方法中,有给列头信息赋值,我们根据判断[年]、[月]且值是否带小数点来修改value值就行了啦  大概是line60~

最主要的是我们要知道最后导出excel时,填充数据的取值来源是FormattedValue属性(headervalues[ y ][ x ].getFormattedValue(); ,  所以以下我们会根据rowValue的值是否是年 月 维度,且是否带小数点来给formattedValue赋值。

添加的代码如下: 

 for ( int y = 0; y < matrix.getOffset(); y++ ) {
      for ( int x = 0; x < matrix.getMatrixWidth(); x++ ) {
        headervalues[ y ][ x ] = matrix.get( x, y );
        //以下為新增內容:處理導出excel時 年月帶小數點問題
        if(headervalues[ y ][ x ] != null && headervalues[ y ][ x ].getRawValue() != null){ 
        	if( headervalues[ y ][ x ].getRawValue().startsWith("[年].[年]") || headervalues[ y ][ x ].getRawValue().startsWith("[月].[月]") ){
        		
	        	String tmpValue = headervalues[ y ][ x ].getFormattedValue();
	        	if(tmpValue != null && tmpValue.indexOf(".")>-1){//判斷年 月結果是否帶小數點
	        		
	        		tmpValue = tmpValue.substring(0, tmpValue.indexOf("."));//竊取小數點以前的數據
	        		headervalues[ y ][ x ].setFormattedValue(tmpValue);//重新賦值
	        	}
	        	
        	}
        }
        //以上為新增內容:處理導出excel時 年月帶小數點問題
      }
    }

 

最后提供完整的 OlapResultSetUtil.java文件

/*  
 *   Copyright 2012 OSBI Ltd
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
package org.saiku.olap.util;

import org.olap4j.CellSet;
import org.saiku.olap.dto.resultset.AbstractBaseCell;
import org.saiku.olap.dto.resultset.CellDataSet;
import org.saiku.olap.dto.resultset.Matrix;
import org.saiku.olap.util.formatter.HierarchicalCellSetFormatter;
import org.saiku.olap.util.formatter.ICellSetFormatter;

public class OlapResultSetUtil {

  public static CellDataSet cellSet2Matrix( final CellSet cellSet ) {
    final ICellSetFormatter formatter = new HierarchicalCellSetFormatter();
    return cellSet2Matrix( cellSet, formatter );
  }

  public static CellDataSet cellSet2Matrix( final CellSet cellSet, ICellSetFormatter formatter ) {
    if ( cellSet == null ) {
      return new CellDataSet( 0, 0 );
    }

    final Matrix matrix = formatter.format( cellSet );
    final CellDataSet cds = new CellDataSet( matrix.getMatrixWidth(), matrix.getMatrixHeight() );

    int z = 0;
    final AbstractBaseCell[][] bodyvalues =
      new AbstractBaseCell[ matrix.getMatrixHeight() - matrix.getOffset() ]
                          [ matrix.getMatrixWidth() ];

    for ( int y = matrix.getOffset(); y < matrix.getMatrixHeight(); y++ ) {
      for ( int x = 0; x < matrix.getMatrixWidth(); x++ ) {
        bodyvalues[ z ][ x ] = matrix.get( x, y );
      }

      z++;
    }

    cds.setCellSetBody( bodyvalues );

    final AbstractBaseCell[][] headervalues =
        new AbstractBaseCell[ matrix.getOffset() ][ matrix.getMatrixWidth() ];

    for ( int y = 0; y < matrix.getOffset(); y++ ) {
      for ( int x = 0; x < matrix.getMatrixWidth(); x++ ) {
        headervalues[ y ][ x ] = matrix.get( x, y );
        //以下為新增內容:處理導出excel時 年月帶小數點問題
        if(headervalues[ y ][ x ] != null && headervalues[ y ][ x ].getRawValue() != null){ 
        	if( headervalues[ y ][ x ].getRawValue().startsWith("[年].[年]") || headervalues[ y ][ x ].getRawValue().startsWith("[月].[月]") ){
        		
	        	String tmpValue = headervalues[ y ][ x ].getFormattedValue();
	        	if(tmpValue != null && tmpValue.indexOf(".")>-1){//判斷年 月結果是否帶小數點
	        		
	        		tmpValue = tmpValue.substring(0, tmpValue.indexOf("."));//竊取小數點以前的數據
	        		headervalues[ y ][ x ].setFormattedValue(tmpValue);//重新賦值
	        	}
	        	
        	}
        }
        //以上為新增內容:處理導出excel時 年月帶小數點問題
      }
    }

    cds.setCellSetHeaders( headervalues );
    cds.setOffset( matrix.getOffset() );

    return cds;
  }
}

  

 ========二次更新,后台导出excel也有默认的小数点 2018.0问题处理=======20190605============end=======

原文地址:https://www.cnblogs.com/DFX339/p/10899855.html