// Script Requested By: function guid() { function _p8(s) { var p = (Math.random().toString(16) + "000000000").substr(2, 8); return s ? p.substr(0, 4) + p.substr(4, 4) : p; } return _p8() + _p8(true) + _p8(true) + _p8(); } function xmlSanitize(val) { if (typeof val === "string") { if (val.length > 19) { if (pickRDLType(val) == "Date") { if (!window.navigator.msSaveOrOpenBlob) { val = new Date(val.replace(/:\d\d\d/,"")); val = val.getFullYear() + '-' + (val.getMonth() > 8 ? val.getMonth() + 1: "0" + (val.getMonth() + 1)) + '-' + (val.getDate() > 9 ? val.getDate() : "0" + val.getDate()) + 'T' + val.toTimeString().substr(0,8); } else { val = val.substr(0,19); } } } val = val.replace(/[^\u0009\u000a\u000d\u0020-\uD7FF\uE000-\uFFFD]/g,''); val = val.replace(/&/g,'&amp;'); val = val.replace(//g,'&gt;'); return val; } else if (val == null) {return '';} else {return val;} } function fieldNameSanitize(fld) { if (fld.substr(0, 3) == "DE:") { return fieldNameSanitize(fld.substr(3)); } else { fld = fld.replace(/^[0-9]/g,'fld$&'); // Append 'fld' before any field that starts as a number fld = fld.replace(/%/g,'Pct'); // Change % to "Pct" fld = fld.replace(/&/g,'and'); // Change & to "and" fld = fld.replace(/\-/g,'_'); // Change dashes to underscores fld = fld.replace(/[^a-zA-Z0-9-_~]/g,''); // Remove all other non-alphanumerics return fld; } } var dataDictionary = []; var uniqueFields = {}; var uniqueTables = {}; function buildDataDictionary (objName,field,fsan) { if (!uniqueTables[objName]) { uniqueTables[objName] = true; dataDictionary.push({"table":objName,"fields":[]}); } if (!uniqueFields[objName + ':' + field]) { uniqueFields[objName + ':' + field] = true; dataDictionary.filter(function(fld) {return (fld.table == objName);})[0].fields.push({"jsonName" : field,"rdlName" : fsan}); } } function isDate(val) { var dCheck = /[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/.test(val); dCheck = (dCheck && (! /[a-z]/.test(val))); var d = new Date(val); return (dCheck && !isNaN(d.valueOf())); } function pickRDLType(fld) { var retType = "String"; if (fld != null) { if (typeof fld === "boolean") { retType = "Boolean"; } else if (typeof fld === "number") { retType = "Decimal"; } else if (!isNaN(fld) ) { retType = "Decimal"; } else if (fld.length > 20) { if (isDate(fld.substr(0, 19))) retType = "Date"; } else if (isDate(fld)) { retType= "Date"; } } return retType; } function sortType (val0, val1) { if (val0 == null) { return 1; } else { return evaluateRDLType (pickRDLType(val0),pickRDLType(val1)); } } function evaluateRDLType (type0, type1) { if (type0 == type1) return 1; if (type0 == "String") return 0; if (type1 == "String") return 1; if (type0 == "Boolean") return 1; if (type1 == "Boolean") return 0; if (type0 == "Decimal") return 1; if (type1 == "Decimal") return 0; return 0; } function convertJsonObjectToRdlData(jsonObj, prefix, childDataSets, moveSubObjectsToRoot) { var rdl = ""; if (typeof jsonObj === "object") { for (var key in jsonObj) { fsan = fieldNameSanitize(key); if (key != '$$hashKey') { if (typeof jsonObj[key] === "object" && jsonObj[key] != null) { if (Object.prototype.toString.call(jsonObj[key]) == '[object Array]' && jsonObj[key].length > 0) { var subObj = fsan; if (typeof jsonObj[key][0] === "object") { /* rdl += '<' + prefix + subObj + '_items>' + jsonObj[key].map( function(itm) { return '<' + prefix + subObj + '>' + convertJsonObjectToRdlData(itm, prefix + subObj + "_") + '</' + prefix + subObj + '>\r\n';}).join(" ") + '</' + prefix + subObj + '_items>'; CODE TO BUILD IN-LINE SUB OBJECT */ appendChildObject(jsonObj[key],prefix + subObj); // childDataSets.childData += createRDLDataSet( jsonObj[key],prefix + ( } else { rdl += '<' + prefix + subObj + '>' + xmlSanitize(jsonObj[key].join(", ")) + '</' + prefix + subObj + '>\r\n' ; } } else { if (moveSubObjectsToRoot && !(jsonObj[key] == null) && (jsonObj[key].length != 0)) { appendChildObject(jsonObj[key],fsan); // childDataSets.childData += createRDLDataSet( [jsonObj[key]],fsan, childDataSets , moveSubObjectsToRoot); } else { rdl += convertJsonObjectToRdlData(jsonObj[key], prefix + fsan + "_" , childDataSets, moveSubObjectsToRoot); } } } else { rdl += '<' + prefix + fsan + ' >' + xmlSanitize(jsonObj[key]) + '</' + prefix + fsan + '>\r\n'; } } } } else { rdl += '<' + prefix + ' >' + xmlSanitize(jsonObj) + '</' + prefix + '>\r\n'; } return rdl; } function getMaxJsonObjArray(jsonArr,subObj) { var result = {}; if (typeof subObj != 'undefined') { result = subObj; } for (i = 0; i < jsonArr.length; i++) { obj = jsonArr[i]; for (var x in obj) { if (Object.prototype.toString.call(obj[x]) == '[object Array]') { if (!result.hasOwnProperty(x)) { result[x] = obj[x]; } else if ( result[x] == null || obj[x].length > result[x].length) { result[x] = obj[x]; } } else if (Object.prototype.toString.call(obj[x]) == '[object Object]') { if (!result.hasOwnProperty(x) || result[x] == null) { result[x] = {}; } if (obj[x] != null && !(typeof obj[x] === 'undefined')) { for (var y in obj[x]) { if (!result[x].hasOwnProperty(y)) { result[x][y] = obj[x][y]; } else if (obj[x][y] > result[x][y] && sortType(obj[x][y],result[x][y]) < 1 ) { result[x][y] = obj[x][y]; } } } } else if ( !result.hasOwnProperty(x) || result[x] == null || sortType(obj[x],result[x]) < 1 || (obj[x] > result[x] && sortType(result[x],obj[x]) == 1)) { result[x] = obj[x]; } } }; return result; } function appendChildObject(jsonObj,dataSetName) { if (childObjects.hasOwnProperty(dataSetName)) { Array.prototype.push.apply(childObjects[dataSetName],jsonObj); } else { childObjects[dataSetName]= jsonObj; } } function createRDLDataSet(jsonObj,dataSetName,childDataSets, moveSubObjectsToRoot) { var rdl = ""; if (jsonObj.length > 0) { var maxObj = getMaxJsonObjArray(jsonObj); rdl = '\r\n\r\nEmbeddedDataSource\r\n <Query>\r\n'; rdl += '<ElementPath>\r\nJsonTable{}/JsonRow{' + convertJSONtoRDLElementPath(maxObj, '', moveSubObjectsToRoot).substr(1) + '}\r\n</ElementPath>\r\n'; rdl += '<XmlData>\r\n<JsonTable>'; rdl += jsonObj.map(function (jObj, i, jArr) { return '<JsonRow>\r\n' + convertJsonObjectToRdlData(jObj, '', childDataSets, moveSubObjectsToRoot) + '</JsonRow>\r\n'; }).join(" "); rdl += '</JsonTable>\r\n</XmlData>\r\n'; rdl += '</Query>\r\n\r\n \r\n'; rdl += '\r\n' + convertJSONtoRDLFieldList(maxObj, '', dataSetName, moveSubObjectsToRoot) + '\r\n'; rdl += ""; } return rdl; } function getJsonFieldsFromRDL(xml) { var fields = xml.match(/Fields!\w+(?=\.Value)|\w+(?="\)<\/Value>)|\w+(?=<\/DataSetName>)|<\/Tablix>/g); var tbl = ""; if (fields != null) { fields = fields.map(function (itm) { if (itm.substr(0, 7) != "Fields!" && itm != "") { tbl = itm; } if (itm == "") { return tbl; } else { return itm; } }); tbl = ""; fields.reverse(); var uniqueSet = {}; var uniqueFields = []; fields.map(function (itm) { if (itm.substr(0, 7) == "Fields!") { fld = itm.substr(7); fval = tbl + "." + fld; if (!uniqueSet[fval]) { uniqueSet[fval] = true; uniqueFields.push({ "table": tbl, "field": fld }); } } else { tbl = itm; } return itm; }); uniqueFields.sort(function (a, b) { return ((a.table + '.' + a.field).toUpperCase() >= (b.table + '.' + b.field).toUpperCase() ? 1 : -1) }); var tblSet = {}; var lastSet; uniqueFields.map(function (itm, i, arr) { if (i == 0 || arr[i - 1].table != itm.table) { tblSet[itm.table] = {}; } tblSet[itm.table][itm.field] = false; }); return tblSet; } else { return {}; } } var rptGUID; var dataGUID; var rdlFieldsUsed; var childObjects = {}; function resetGlobals() { dataDictionary = []; uniqueFields = {}; uniqueTables = {}; rptGUID = guid(); dataGUID = guid(); rdlFieldsUsed; childObjects = {}; } function convertJSONArraytoRDLDataSet(jsonObj, dataSetName, rdlTemplate, moveSubObjectsToRoot ) { resetGlobals(); var rdl = ""; var childDataSets = {childData:""}; rdlFieldsUsed = getJsonFieldsFromRDL(rdlTemplate); rdl = createRDLDataSet(jsonObj,dataSetName,childDataSets, moveSubObjectsToRoot); // rdl += childDataSets.childData; for (var obj in childObjects) { rdl += createRDLDataSet(childObjects[obj],obj,{},moveSubObjectsToRoot); } rdl = rdlTemplate.replace("{REPORTGUID}", rptGUID).replace("{DATASOURCEGUID}", dataGUID).replace("{"+ dataSetName +"}", function() { return rdl}); return rdl; } function convertJSONtoRDLElementPath(jsonObj, prefix, moveSubObjectsToRoot) { var rdl = ''; for (var field in jsonObj) { var fsan = fieldNameSanitize(field); if (field != "$$hashKey") { if (typeof jsonObj[field] === "object" && jsonObj[field] != null) { if (Object.prototype.toString.call(jsonObj[field]) == '[object Array]' && jsonObj[field].length > 0) { if(typeof jsonObj[field][0] === "object" && jsonObj[field][0].hasOwnProperty("ID")) { // rdl += ',' + convertJSONtoRDLElementPath(jsonObj[field][0], prefix + fsan + '_').substr(1) ; } else { rdl += ',' + prefix + fsan + '(string)\r\n'; } } else { if (!moveSubObjectsToRoot) {rdl += convertJSONtoRDLElementPath(jsonObj[field], prefix + fsan + '_', moveSubObjectsToRoot);} } } else { rdl += ',' + prefix + fsan + '(' + pickRDLType(jsonObj[field]) + ')\r\n'; } } } return rdl; } function convertJSONtoRDLFieldList(jsonObj, prefix, objName, moveSubObjectsToRoot) { var rdl = ''; if (typeof rdlFieldsUsed[objName.split(":")[0]] === 'undefined') { rdlFieldsUsed[objName.split(":")[0]] = {}; } if (typeof jsonObj === "object") { for (var field in jsonObj) { var fsan = fieldNameSanitize(field); if (field != "$$hashKey") { if (typeof jsonObj[field] === "object" && jsonObj[field] != null) { if (Object.prototype.toString.call(jsonObj[field]) == '[object Array]' && jsonObj[field].length > 0) { if (typeof jsonObj[field][0] === "object" ) { // Is a sub-object and will contain its own field definititions: do nothing } else { // Value array case, is converted to string of items fsan = (prefix != '' ? prefix : '') + fsan; rdl += '\r\n'; rdl += '' + fsan + '\r\n'; rdl += 'System.string'; rdl += '\r\n\r\n'; } } else { if (!moveSubObjectsToRoot) { //Sub object is not an array, will prefix it with field name and append properties with '_' rdl += convertJSONtoRDLFieldList(jsonObj[field], prefix + fsan + '_', objName + ':' + field ,moveSubObjectsToRoot); } } } else { fsan = prefix + fsan; rdl += '\r\n'; rdl += '' + fsan + '\r\n'; rdl += 'System.' + pickRDLType(jsonObj[field]); rdl += '\r\n\r\n'; } } rdlFieldsUsed[objName.split(":")[0]][fsan] = true; buildDataDictionary (objName,field,fsan); } // for loop } else { rdl += '\r\n'; rdl += '' + prefix + '\r\n'; rdl += 'System.' + pickRDLType(jsonObj); rdl += '\r\n\r\n'; rdlFieldsUsed[objName.split(":")[0]][prefix] = true; buildDataDictionary (objName,field,prefix); } if (objName.indexOf(":")==-1) { for (fld in rdlFieldsUsed[objName]) { if (!rdlFieldsUsed[objName][fld]) { rdl += '\r\n'; rdl += '' + fld + '\r\n'; rdl += 'System.string'; rdl += '\r\n\r\n'; } } } return rdl; } function resizeTablix(rdl, tablixName, colWidths, prorateToWidth) { var wFactor = 1; if (prorateToWidth != null) { /* Supports normalized % Widths based on prorated master width */ var colSum = colWidths.reduce(function(a, b) { return a + b; }, 0); wFactor = prorateToWidth / colSum; } /* Use reduce function to concatenate a new XML block based on the new table sizes */ var newXML = colWidths.reduce(function(cumulative, itm) { return cumulative + "" + ((itm * wFactor).toFixed(5)) + "in"; }, ""); /* Use a RegEx to swap in the tablesize block in the RDL code for the provided Tablix Name */ re = new RegExp('([\r\n| ]+[\r\n| ]+)[\r\n|<| |TablixColumn|>|Width|0-9|.|\/]+()'); return rdl.replace(re, '$1' + newXML + '$2'); }