I have just recentely used AngularJS to "convert" a data structure I had in pure SVG format into JSON format.
Now, I want to store such a structure in a MongoDB database to start finally connecting some components of the MEAN stack together and start seeing some things working! Basically, I have the following code inside a Webstorm AngularJS project:
JS:
var app = angular.module('app', []);
var RectangleDim=30;
app.controller('MainCtrl', function($scope) {
$scope.graph = {'width': 5000, 'height': 5000};
$scope.circles = [
/* JSON.parse("{\"x\": 85, \"y\": 20, \"r\":15}"),
{"x": 20, "y": 60, "r":20},
{"x": 18, "y": 10, "r":40} */
];
$scope.draw=function(val)
{
// val = document.getElementById("NumQuest").value;
return JSON.parse('{\"cx\":'+val+', "cy": 20, "r":30}');
// $scope.circles.push(JSON.parse('{\"x\":'+val+', "y": 220, "r":30}'));
};
$scope.rectangles = [
// {'x':220, 'y':220, 'width' : 300, 'height' : 100},
// {'x':520, 'y':220, 'width' : 10, 'height' : 10},
];
$scope.DrawRect=function(xpos,ypos) {
return JSON.parse('{\"x\":' + xpos + ', \"y\":' + ypos + ', \"width\":' + RectangleDim + ', \"height\":' + RectangleDim+ '}');
};
$scope.Debug=function(desiredNo){
desiredNo=document.getElementById("NumQuest").value;
for(var i = 0;i < RectangleDim*desiredNo+desiredNo;i++){
$scope.rectangles.push($scope.DrawRect(i+RectangleDim+1,40));
}
};
$scope.DrawLineOdd=function(desiredNo,lineNo,pozY){
var pozX = lineNo*RectangleDim;
var aux = 2*Math.floor(Math.sqrt(desiredNo))-1-2*lineNo;
for (var j = 0; j < aux; j++) {
$scope.rectangles.push($scope.DrawRect(pozX, pozY));//$scope.DrawRect(pozX, pozY);
pozX += RectangleDim;
}
//return aux;
};
$scope.DrawMatrixPerfectProgression=function(desiredNo) {
desiredNo=document.getElementById("NumQuest").value;
var line=0;
var pozy=0;
while(line<Math.floor(Math.sqrt(desiredNo))) {
$scope.DrawLineOdd(desiredNo, line, pozy);
//document.getElementById("val").innerHTML = teste;
line += 1;
pozy+=RectangleDim;
}
//document.getElementById('tablePrint').innerHTML = finalTable;
};
$scope.DrawLineEven=function(desiredNo, lineNo, pozY){
var pozX = lineNo*RectangleDim;
//var pozY = lineno*20;
var aux = 2*Math.floor(Math.sqrt(desiredNo))-2*lineNo;
for (var j = 0; j < aux; j++) {
$scope.rectangles.push($scope.DrawRect(pozX, pozY));
pozX += RectangleDim;
}
//return aux;
};
$scope.DrawMatrixEvenProgression=function(desiredNo) {
desiredNo=document.getElementById("NumQuest").value;
var line=0;
var pozy=0;
while(line<Math.floor((Math.sqrt(4*desiredNo+1)-1)/2)) {
$scope.DrawLineEven(desiredNo, line, pozy);
//document.getElementById("val").innerHTML = teste;
line += 1;
pozy+=RectangleDim;
}
//document.getElementById('tablePrint').innerHTML = finalTable;
};
$scope.AddExtraRectangles=function(desiredNo) {
desiredNo = document.getElementById("NumQuest").value;
var arg1 = desiredNo - ( Math.floor(Math.sqrt(desiredNo))*Math.floor(Math.sqrt(desiredNo)));
var arg2 = desiredNo-(Math.floor((Math.sqrt(4*desiredNo+1)-1)/2)*Math.floor((Math.sqrt(4*desiredNo+1)-1)/2))-Math.floor((Math.sqrt(4*desiredNo+1)-1)/2);
var OptimalLeftOver = Math.min( arg1 ,arg2 );
//We add two rectangles per row: one at the beginning one at the end
//we start with the row below the first one
var line;
var pozy;
var pozx1, pozx2;
var nRectLine_i;
if(OptimalLeftOver===arg1){
line=1;//1st line is skipped
pozy=RectangleDim;
pozx1 = 0;
while(OptimalLeftOver>0) {
nRectLine_i = 2* Math.floor(Math.sqrt(desiredNo))-1-2*line;
pozx2 = (line-1)*RectangleDim+RectangleDim*(nRectLine_i+1);//pozx1+nRectLine_i+2*RectangleDim;
$scope.rectangles.push($scope.DrawRect(pozx1,pozy));
OptimalLeftOver-=1;
if(OptimalLeftOver>0) {
$scope.rectangles.push($scope.DrawRect(pozx2, pozy));
OptimalLeftOver -= 1;
}
//document.getElementById("val").innerHTML = teste;
line += 1;
pozy+=RectangleDim;
pozx1=RectangleDim*line - RectangleDim;
}
//document.getElementById('tablePrint').innerHTML = finalTable;
}
else {
line=1;//1st line is skipped
pozy=RectangleDim;
pozx1 = 0;
while(OptimalLeftOver>0) {
nRectLine_i = 2* Math.floor(Math.sqrt(desiredNo))-2*line;
pozx2 = RectangleDim*(line-1)+RectangleDim*(nRectLine_i+1);//pozx1+nRectLine_i+2*RectangleDim;
$scope.rectangles.push($scope.DrawRect(pozx1,pozy));
OptimalLeftOver-=1;
if(OptimalLeftOver>0) {
$scope.rectangles.push($scope.DrawRect(pozx2, pozy));
OptimalLeftOver -= 1;
}
//document.getElementById("val").innerHTML = teste;
line += 1;
pozy+=RectangleDim;
pozx1=RectangleDim*line - RectangleDim;
}
//document.getElementById('tablePrint').innerHTML = finalTable;
}
};
/* $scope.DrawMatrix=function(desiredNo)
{
/* Chooses optimal leftover number based on the progression formulas.
Attempts to minimize the work of the designer of the response form without
making too much assumptions
desiredNo = document.getElementById("NumQuest").value;
var arg1 = desiredNo - ( Math.floor(Math.sqrt(desiredNo))*Math.floor(Math.sqrt(desiredNo)));
var arg2 = desiredNo - (Math.floor((Math.sqrt(4*desiredNo+1)-1)/2)*Math.floor((Math.sqrt(4*desiredNo+1)-1)/2))-Math.floor((Math.sqrt(4*desiredNo+1)-1)/2);
var OptimalLeftOver = Math.min( arg1 ,arg2 );
document.getElementById("val").innerHTML = 'There are '+OptimalLeftOver+' questions missing!'+ arg1+ '___'+arg2;
console.log(arg1);
if(OptimalLeftOver===arg1){
DrawMatrixPerfectProgression(desiredNo);
AddExtraRectangles(desiredNo);
}
else {
DrawMatrixEvenProgression(desiredNo);
AddExtraRectangles(desiredNo);
}
}; */
}
);
angular.bootstrap(document.getElementById('body'), ["app"]);
The relevant part of the code is the $scope.rectangles array which contains the JSON.parse of the strings representing my data structure on the html side and that structure in JSON (or JSON parsed or whatever) is what I want to save in the MongoDB database...How can I do that? The HTML relevant part is just like this:
HTML:
<p><button ng-click="DrawMatrixEvenProgression(NumQuest)">Draw</button></p>
<svg ng-attr-height="{{graph.height}}" ng-attr-width="{{graph.width}}">
<rect ng-repeat="rect in rectangles"
ng-attr-x="{{rect.x}}"
ng-attr-y="{{rect.y}}"
ng-attr-width="{{rect.width}}"
ng-attr-height="{{rect.height}}">
</rect>
</svg>
Any help will be appreciated... Can I start by adding more files to that project to handle the database and then things will be linked together?
Like adding stuff to handle the mongoose and the connections?
Thanks in advance!
Because Angular is a front-end framework. So to communicate with database (in this case MongoDB) you need to have application on the server-side to handle this and I suggest you to use Node.js and Mongoose as a MongoDB driver.
Node.js
Mongoose
Come back to Angular, you can create Angular service or factory and let the them talk to your server with service like $http or $resource.
Angular service documentation
Example for angular service
angular.module('app')
.factory('RectangleService', function($http){
return {
create: create
}
function create(rectangle){
// make http request to the server
return $http({
url: 'API_URL',
method: 'GET',
params: rectangle
});
}
});
After you create your service you have to inject it to your controller and
you may create some function to your $scope to talk with service like this
app.controller('MainCtrl', function($scope, RectangleService) { // <-- Inject service to controller
// your controller code
$scope.createRectangle = function(rectangle){
RectangleService.create(rectangle);
}
});
You can map createRectangle function to directive like ng-click and pass your json data as a parameter
Because I don't know what server-side language you can use, so I don't come with an example for Node.js & Mongoose
Hope this can help :)
Related
I am using script.google.com to create a custom connector that can read CSV data from drive.google.com and send the data to Googles data studio.
When running the connector and inserting a simple table inside the data studio, I receive a simple that the request could not be processed because of an server error. The error id is changing every time I "re-publish" the script.
This is
function getData(request) {
var dataSchema = [];
request.fields.forEach(function(field) {
for (var i = 0; i < csvDataSchema.length; i++) {
if (csvDataSchema[i].name === field.name) {
dataSchema.push(csvDataSchema[i]);
break;
}
}
});
csvFile = UrlFetchApp.fetch("https://drive.google.com/uc?export=download&id=" + request.configParams.documentId);
var csvData = Utilities.parseCsv(csvFile);
var data = [];
csvData.forEach(function(row) {
data.push({
values: row
});
});
console.log( {
schema: dataSchema,
rows: data
} );
return {
schema: dataSchema,
rows: data
};
};
This is the csvDataSchema:
var csvDataSchema = [
{
name: 'date',
label: 'Date',
dataType: 'STRING',
semantics: {
conceptType: 'DIMENSION'
}
},
{
name: 'nanoseconds',
label: 'nanoseconds',
dataType: 'NUMBER',
semantics: {
"isReaggregatable": true,
conceptType: 'METRIC'
}
},{
name: 'size',
label: 'Size of Testfile in MByte',
dataType: 'STRING',
semantics: {
"isReaggregatable": false,
conceptType: 'DIMENSION'
}
}
];
And this is the result of the getData function, stringified:
{"schema":[{"name":"date","label":"Date","dataType":"STRING","semantics":{"conceptType":"DIMENSION"}},{"name":"size","label":"Size of Testfile in MByte","dataType":"STRING","semantics":{"isReaggregatable":false,"conceptType":"DIMENSION"}}],"rows":[{"values":["2017-05-23",123,"1"]},{"values":["2017-05-23",123,"1"]}]}
It perfectly fits to the reference. I am providing more information, but following the tutorial it should work, anyways.
Those are the fields provided in request:
And this is what getDate returns:
So, what I am wondering first is: Why is there a random error id? And what could be wrong with my script?
You should only return fields/columns included in request. Currently, data contains all fields that are in csvFile. Depending on your chart element in your dashboard, request will most likely contain only a subset of your full schema. See example implementation at the Data Studio Open Source repo.
If this does not solve the problem, you should setup error handing and check if the error is occurring at any specific line.
#Minhaz Kazi gave the missing hint:
As I did not "dynamically" filled the response object in getData, I always returned all three columns.
With my code above the only thing I had to do is adding the third column as a dimension or a metric.
So I changed my code to dynamically return the columns so it will fit to the response. For this I had to implement an function that will transform the CSV-data into an object.
This is the getData() function now:
function getData(request) {
var url = "https://drive.google.com/uc?export=download&id="
+ request.configParams.documentId;
var csvFile = UrlFetchApp.fetch(url);
var csvData = Utilities.parseCsv(csvFile);
var sourceData = csvToObject(csvData);
var data = [];
sourceData.forEach(function(row) {
var values = [];
dataSchema.forEach(function(field) {
switch(field.name) {
case 'date':
values.push(row.date);
break;
case 'nanoseconds':
values.push(row.nanoseconds);
break;
case 'size':
values.push(row.size);
break;
default:
values.push('');
}
});
data.push({
values: values
});
});
return {
schema: dataSchema,
rows: data
};
};}
And this is the function to convert the CSV data to an object:
function csvToObject(array) {
var headers = array[0];
var jsonData = [];
for ( var i = 1, length = array.length; i < length; i++ )
{
var row = array[i];
var data = {};
for ( var x = 0; x < row.length; x++ )
{
data[headers[x]] = row[x];
}
jsonData.push(data);
}
return jsonData;
}
(it's based on a so-solution from here, I modified it to fit my source CSV data)
I have an ajax request which helps me to get a JSON-object from a webserver!
function _loadModel(filename) {
var request = new XMLHttpRequest();
request.open("GET", filename);//open(method, url, async)
request.onreadystatechange = function() {
console.info(request.readyState +' - '+request.status);
if (request.readyState == 4) {//4 == finished download
if(request.status == 200) { //OK -> bezogen auf http Spezifikation
handleLoadedGeometry(filename,JSON.parse(request.responseText));
}
else if (document.domain.length == 0 && request.status == 0){ //OK but local, no web server
handleLoadedGeometry(filename,JSON.parse(request.responseText));
}
else{
alert ('There was a problem loading the file :' + filename);
alert ('HTML error code: ' + request.status);
}
}
}
request.send();// send request to the server (used for GET)
}
_loadModel('http://localhost:8080/bbox?XMIN=3500060&YMIN=5392691&XMAX=3500277&YMAX=5393413')
JSON file:
[{"building_nr": 5, "geometry": "{\"type\":\"Polygon\",\"coordinates\":[[[3500267.16,5392933.95,456.904],[3500259.19,5392933.01,456.904],[3500258.586,5392938.152,456.904],[3500258.02,5392942.97,456.904],[3500265.98,5392943.94,456.904],[3500266.552,5392939.097,456.904],[3500267.16,5392933.95,456.904]]]}", "polygon_typ": "BuildingGroundSurface"}, ...]
This is one object and I have a lot of them in this array.
Now I want to create a mesh!
I think this can be done inside the function handleLoadedGeometry()
//Callback funktion
function handleLoadedGeometry(filename, model) {
var geom = new THREE.BufferGeometry();
for (var i=0;i<10;i++)
{
var vertex = new THREE.Vector3();
vertex.x = model.geometry[i].coordinates[0];
vertex.y = model.geometry[i].coordinates[1];
vertex.z = model.geometry[i].coordinates[2];
geometry.vertices.push( vertex );
}
geom.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
var material = new THREE.MeshBasicMaterial( { color: 0xff00f0 } );
var mesh = new THREE.Mesh( geom, material );
Scene.scene.add(mesh);
}
At the end I get this error in the browser: Cannot read property '0' of undefined
How can I refer to geometry coordinates inside the JSON?
from what you provided it seems the loaded JSON contains an array of multiple objects that is why you get the error
try something like this
function handleLoadedGeometry(filename, models) {
for (var i=0; i<models.length; i++)
{
var model = models[i];
var coordinates = model.geometry.coordinates;
var positions = [];
for (var j=0; j<coordinates.length; j++){
positions.push(coordinates[j][0]);
positions.push(coordinates[j][1]);
positions.push(coordinates[j][2]);
}
var geometry = new THREE.BufferGeometry();
// buffer attributes contain an array not vectors
var positionAttribute = new THREE.BufferAttribute(new Float32Array(positions),3);
geometry.addAttribute("position", positionAttribute);
var material = new THREE.MeshBasicMaterial( { color: 0xff00f0 } );
var mesh = new THREE.Mesh( geom, material );
Scene.scene.add(mesh);
}
}
or remove the first loop if you call it for each object in the JSON array
I did it in another way...I just created instead of BufferGeometry the default Geometry in three.js:
function handleLoadedGeometry(filename) {
var material = new THREE.MeshBasicMaterial({color: 0xFF0000});
for (var i=0; i<filename.length; i++)
{
var model = filename[i]; // erstes Objekt
var coordinates = JSON.parse(model.geometry);
var geometry = new THREE.Geometry();
var coordinates_updated = _transformCoordinates(coordinates.coordinates[0]);
for (var j = 0; j<coordinates_updated.vertices.length; j++){
geometry.vertices.push(
//new THREE.Vector3(coordinates.coordinates[0][j][0], coordinates.coordinates[0][j][1], coordinates.coordinates[0][j][2])//x,y,z Koordinatenpunkte für Surface 1
new THREE.Vector3(coordinates_updated.vertices[j][0],coordinates_updated.vertices[j][1],coordinates_updated.vertices[j][2])
);
geometry.faces.push(
new THREE.Face3(0,1,2),
new THREE.Face3(0,3,2)
geometry.computeBoundingSphere();
}
var mesh = new THREE.Mesh(geometry, material);
Scene.scene.add(mesh);
}
};
And now it works!
I think BufferGeometry is more for more complex surfaces.
I've scavenged the inter web for answers and though I found some, they were mostly incomplete or not working.
What I'm trying to do is: I have a info page which displays information about a customer or server (or something else), this information is displayed in a table, sometimes multiple tables (I sometimes create my own table for some of the data and use Html.Grid(Model.list) to create tables for the rest of the data stored in lists, all on 1 page).
I found this website which is an awesome: http://www.excelmashup.com/ and does exactly what I want for 1 table, though I need this for multiple tables (they must all be in the same Excel file). I know I can create multiple files (1 for each table) but this is not the desired output.
So I kept on searching and I found a post on stackoverflow: Export multiple HTML tables to Excel with JavaScript function
This seemed promising so I tried using it but the code had some minor errors which I tried to fix:
var tableToExcel = (function () {
var uri = 'data:application/vnd.ms-excel;base64,'
, template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>'
, base64 = function (s) { return window.btoa(unescape(encodeURIComponent(s))) }
, format = function (s, c) { return s.replace(/{(\w+)}/g, function (m, p) { return c[p]; }) }
return function (table, name) {
if (!table.nodeType) table = document.getElementById(table)
var ctx = { worksheet: name || 'Worksheet', table: table.innerHTML }
window.location.href = uri + base64(format(template, ctx))
}
})()
The button I use to trigger it:
<input type="button" onclick="tableToExcel('InformatieTable', 'W3C Example Table')" value="Export to Excel">
but alas to no avail (I did not know what to do with the if (!table.nodeType) table = table line so I just commented it since it seemed to do nothing special).
Now I get an error, or well not really an error but this is what it says when I try to run this code:
Resource interpreted as Document but transferred with MIME type application/vnd.ms-excel: "data:application/vnd.ms-excel;base64,PGh0bWwgeG1sbnM6bz0idXJuOnNjaGVtYXMtbW…JzZXQ9VVRGLTgiLz48L2hlYWQ+PGJvZHk+PHRhYmxlPjwvdGFibGU+PC9ib2R5PjwvaHRtbD4=".
And I get an Excel file as download in my browser but when I try to open it I get an error about the content and file extension not matching and if I would still like to open it. So if I click ok it opens a empty Excel sheet and that's it.
I am currently trying to fix that error, though i don't think it will make any difference to the content of the Excel file.
Is there anyone that can help me fix this? Or provide an other way of doing this?
I do prefer it to be run client side (so jQuery/java) instead of server side to minimize server load.
EDIT
I've found a better example of the jQuery (one that does work) on http://www.codeproject.com/Tips/755203/Export-HTML-table-to-Excel-With-CSS
This converts 1 table into an excel file which is obviously not good enough. But now I have the code to do this so I should be able to adapt it to loop trough all tables on the web page.
Also updated the code in this example to the correct version I'm using now.
I also still get the same error yet when I click on ok when trying to open the Excel file it does show me the content of the table, so I'm just ignoring that for now. anyone who has a solution for this please share.
Thanks to #Axel Richter I got my answer, he reffered me to the following question
I have adapted the code a bit so it would Take all the tables on the web page so it now looks like this:
<script type="text/javascript">
var tablesToExcel = (function () {
var uri = 'data:application/vnd.ms-excel;base64,'
, tmplWorkbookXML = '<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?><Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">'
+ '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"><Author>Axel Richter</Author><Created>{created}</Created></DocumentProperties>'
+ '<Styles>'
+ '<Style ss:ID="Currency"><NumberFormat ss:Format="Currency"></NumberFormat></Style>'
+ '<Style ss:ID="Date"><NumberFormat ss:Format="Medium Date"></NumberFormat></Style>'
+ '</Styles>'
+ '{worksheets}</Workbook>'
, tmplWorksheetXML = '<Worksheet ss:Name="{nameWS}"><Table>{rows}</Table></Worksheet>'
, tmplCellXML = '<Cell{attributeStyleID}{attributeFormula}><Data ss:Type="{nameType}">{data}</Data></Cell>'
, base64 = function (s) { return window.btoa(unescape(encodeURIComponent(s))) }
, format = function (s, c) { return s.replace(/{(\w+)}/g, function (m, p) { return c[p]; }) }
return function (wsnames, wbname, appname) {
var ctx = "";
var workbookXML = "";
var worksheetsXML = "";
var rowsXML = "";
var tables = $('table');
for (var i = 0; i < tables.length; i++) {
for (var j = 0; j < tables[i].rows.length; j++) {
rowsXML += '<Row>'
for (var k = 0; k < tables[i].rows[j].cells.length; k++) {
var dataType = tables[i].rows[j].cells[k].getAttribute("data-type");
var dataStyle = tables[i].rows[j].cells[k].getAttribute("data-style");
var dataValue = tables[i].rows[j].cells[k].getAttribute("data-value");
dataValue = (dataValue) ? dataValue : tables[i].rows[j].cells[k].innerHTML;
var dataFormula = tables[i].rows[j].cells[k].getAttribute("data-formula");
dataFormula = (dataFormula) ? dataFormula : (appname == 'Calc' && dataType == 'DateTime') ? dataValue : null;
ctx = {
attributeStyleID: (dataStyle == 'Currency' || dataStyle == 'Date') ? ' ss:StyleID="' + dataStyle + '"' : ''
, nameType: (dataType == 'Number' || dataType == 'DateTime' || dataType == 'Boolean' || dataType == 'Error') ? dataType : 'String'
, data: (dataFormula) ? '' : dataValue.replace('<br>', '')
, attributeFormula: (dataFormula) ? ' ss:Formula="' + dataFormula + '"' : ''
};
rowsXML += format(tmplCellXML, ctx);
}
rowsXML += '</Row>'
}
ctx = { rows: rowsXML, nameWS: wsnames[i] || 'Sheet' + i };
worksheetsXML += format(tmplWorksheetXML, ctx);
rowsXML = "";
}
ctx = { created: (new Date()).getTime(), worksheets: worksheetsXML };
workbookXML = format(tmplWorkbookXML, ctx);
console.log(workbookXML);
var link = document.createElement("A");
link.href = uri + base64(workbookXML);
link.download = wbname || 'Workbook.xls';
link.target = '_blank';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
})();
</script>
so now when ever I want a page to have an option to be exported to excel i add a refference to that script and i add the following button to my page:
<button onclick="tablesToExcel(['ServerInformatie', 'Relaties'], 'VirtueleMachineInfo.xls', 'Excel')">Export to Excel</button>
so the method:
tablesToExcel(WorksheetNames, fileName, 'Excel')
Where worksheetNames is an array which needs to contain as much names (or more) as there are tables on the page. You could ofcourse chose to create the worksheet names in a different way.
And where fileName is ofcourse the name of the file you'll be downloading.
Not having it all in 1 worksheet is a shame but at least this will do for now.
Here is the code that I used to put multiple HTML tables in the same Excel sheet:
import TableExport from 'tableexport';
const tbOptions = {
formats: ["xlsx"], // (String[]), filetype(s) for the export, (default: ['xlsx', 'csv', 'txt'])
bootstrap: true, // (Boolean), style buttons using bootstrap, (default: true)
exportButtons: false, // (Boolean), automatically generate the built-in export buttons for each of the specified formats (default: true)
position: "bottom", // (top, bottom), position of the caption element relative to table, (default: 'bottom')
}
DowlandExcel = (key) => {
const table = TableExport(document.getElementById(key), tbOptions);
var exportData = table.getExportData();
var xlsxData = exportData[key].xlsx;
console.log(xlsxData); // Replace with the kind of file you want from the exportData
table.export2file(xlsxData.data, xlsxData.mimeType, xlsxData.filename, xlsxData.fileExtension, xlsxData.merges, xlsxData.RTL, xlsxData.sheetname)
}
DowlandExcelMultiTable = (keys) => {
const tables = []
const xlsxDatas = []
keys.forEach(key => {
const selector = document.getElementById(key);
if (selector) {
const table = TableExport(selector, tbOptions);
tables.push(table);
xlsxDatas.push(table.getExportData()[key].xlsx)
}
});
const mergeXlsxData = {
RTL: false,
data: [],
fileExtension: ".xlsx",
filename: 'rapor',
merges: [],
mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
sheetname: "Rapor"
}
for (let i = 0; i < xlsxDatas.length; i++) {
const xlsxData = xlsxDatas[i];
mergeXlsxData.data.push(...xlsxData.data)
xlsxData.merges = xlsxData.merges.map(merge => {
const diff = mergeXlsxData.data.length - xlsxData.data.length;
merge.e.r += diff;
merge.s.r += diff;
return merge
});
mergeXlsxData.merges.push(...xlsxData.merges)
mergeXlsxData.data.push([null]);
}
console.log(mergeXlsxData);
tables[0].export2file(mergeXlsxData.data, mergeXlsxData.mimeType, mergeXlsxData.filename, mergeXlsxData.fileExtension, mergeXlsxData.merges, mergeXlsxData.RTL, mergeXlsxData.sheetname)
}
I want to make a dynamic graph based on a json file. I have seen many examples with tsv but I donot how to convert it to json.
That is the part that I want to change from tsv to json but I donot know how!
d3.tsv("data/data.tsv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
when I use
d3.json("data/data.json", function(data) {
data.forEach(function d) {
d.date = parseDate(d.date);
d.close = +d.close;
}
});
it gives this error: Uncaught type error: cannot call method 'forEach' of undefined!
Thanks for your suggestions :)
try to do something like this
d3.json("data/data.json", function(data) {
data.forEach(function d) {
d.date = parseDate(d.date);
d.close = +d.close;
}
});
d3.js have support for json, https://github.com/mbostock/d3/wiki/Requests
The syntax around your forEach is a little off; try this instead:
d3.json("data/data.json", function(data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
});
(As Felix points out, this will only work if your JSON object is defined and is an array)
Here a small code where you'll be able to convert tsv to json. It could help you...
ps : here is typescript, but you can easily convert it to vanilla javascript ;)
// Set bunch of datas into format object
tsvToJson(datas: string): Array<Object>{
// Separate each lines
let array_datas = datas.split(/\r\n|\r|\n/g);
// Separate each values into each lines
var detailed_datas = [];
for(var i = 0; i < array_datas.length; i++){
detailed_datas.push(array_datas[i].split("\t"));
}
// Create index
var index = [];
var last_index = ""; // If the index we're reading is equal to "", it mean it might be an array so we take the last index
for(var i = 0; i < detailed_datas[0].length; i++){
if(detailed_datas[0][i] == "") index.push(last_index);
else {
index.push(detailed_datas[0][i]);
last_index = detailed_datas[0][i];
}
}
// Separate data from index
detailed_datas.splice(0, 1);
// Format data
var formated_datas = [];
for(var i = 0; i < detailed_datas.length; i++){
var row = {};
for(var j = 0; j < detailed_datas[i].length; j++){
// Check if value is empty
if(detailed_datas[i][j] != ""){
if(typeof row[index[j]] == "object"){
// it's already set as an array
row[index[j]].push(detailed_datas[i][j]);
} else if(row[index[j]] != undefined){
// Already have a value, so it might be an array
row[index[j]] = [row[index[j]], detailed_datas[i][j]];
} else {
// It's empty for now, so let's say first that it's a string
row[index[j]] = detailed_datas[i][j];
}
}
}
formated_datas.push(row);
}
console.log(formated_datas); // #TODO : remove this
return formated_datas;
}
I transpile and resume Wetteren's code:
convertTSVtoJSON(tsvData) {
const formattedData = tsvData.split(/\r\n|\r|\n/g).filter(e => !!e).map((parsedEntry) => parsedEntry.split("\t"));
const tsvHeaders = formattedData.shift();
return formattedData.map(formattedEntry => {
{
return tsvHeaders.reduce((jsonObject, heading, position) => {
jsonObject[heading] = formattedEntry[position];
return jsonObject;
}, {});
}
});
}
I have trouble to parse and show events from Bands in Town´s API in my appcelerator mobile app. (iOS)
This is my bands event that i want to show in a table.
http://api.bandsintown.com/artists/Lucy%20Seven/events.json?api_version=2.0&app_id=LucySeven
And this is the code that i have for showing it
var win = Ti.UI.currentWindow;
win.hideNavBar();
Ti.UI.backgroundColor = '#050505';
var url = "http://api.bandsintown.com/artists/Lucy%20Seven/events.json? api_version=2.0&app_id=LucySeven"
var table = Ti.UI.createTableView({
backgroundColor: '#050505',
separatorColor:'#110000',
});
var tableData = [];
var json, artists, name, picture, title, description;
var xhr = Ti.Network.createHTTPClient({
onload: function() {
// Ti.API.debug(this.responseText);
json = JSON.parse(this.responseText);
for (i = 0; i < json.data.length; i++) {
data = json.data[i];
row = Ti.UI.createTableViewRow({
height:'100dp',
backgroundColor: '#050505',
separatorColor:'#110000',
});
var name = Ti.UI.createLabel({
text: title,
font:{
fontSize:'17dp',
fontWeight:'bold'
},
height:'auto',
left:'90dp',
top:'20dp',
color:'#eee',
touchEnabled:true
});
row.add(name);
var start = Ti.UI.createLabel({
text: description,
font:{
fontSize:'12dp'
},
height:'auto',
left:'90dp',
bottom:'20dp',
color:'#eee',
touchEnabled:true
});
row.add(start);
// Avatar
var img = Ti.UI.createImageView({
image : thumb_url ,
width : 70,
height : 70,
top : 5,
bottom : 5,
borderRadius: 5,
borderColor: '#eee',
left : 5
});
row.add(img);
tableData.push(row);
}
table.setData(tableData);
},
onerror: function(e) {
Ti.API.debug("STATUS: " + this.status);
Ti.API.debug("TEXT: " + this.responseText);
Ti.API.debug("ERROR: " + e.error);
alert('There was an error retrieving the remote data. Try again.');
},
timeout:5000
});
xhr.open("GET", url);
xhr.send();
There is a API responses for json here:
http://www.bandsintown.com/api/responses#events-json
I really cant see what is wrong... Maybe im to blind to see what i have missed?
I would appreciate if someone could point me in the right direction on this.
i have tried with: data.title data.artists.title title artists.titel and so on but nothing have shown up in my tableview.....
Thanx
//R
What's the value of this.responseText and what's the value of json after JSON.parse? In the JSON response I don't see a data property so I'm not sure what json.data is supposed to be. Also in Ti.UI.createLabel you give test: title but title is never given a value.
I suspect what you really want in your for loop is this:
json = JSON.parse( this.responseText ); // `json` will be an array of objects
for (i = 0; i < json.length; i++) {
data = json[ i ];
// ...
var name = Ti.UI.createLabel( {
text: data.title,
// ...
} );
}
The key to debugging this is the same as debugging many things—find out what data you have at each step (I've never used Titanium but it must have something like console.log at the very least) and figure out how it differs from what you expect.