I read that JSON can be inserted into a datatable. However, its done
in JS on the HTML page (if memory serves right). I am using the GWT-
visualisation driver as given here, and the only methods to add a row are not
designed with JSON in mind. Is there any work-able solution? I am
trying to make a Stacked Column Chart.
Thanks.
I also struggled with this using geomap and data table combined. In my workaround I used the evalJSON() in prototype javascript framework to make the json string an object.
var country_obj = country_data.evalJSON(true);
Then I loop over the object's length :
var data = new google.visualization.DataTable();
data.addRows(country_obj.country.length);
data.addColumn('string', 'Country');
data.addColumn('number', map_context);
var j = country_obj.country.length;
for ( i = 0; i < j; i++ )
{
var num = new Number(country_obj.country[i].geo_mstat_reads);
data.setValue(i, 0, country_obj.country[i].country_name);
data.setValue(i, 1, num.valueOf());
}
// and then the table.draw() with the data
This worked very well for me because it scales to the exact size of the dataset you are trying to show.
Also you can do a whole whack of operations on an object which makes your life and coding easier to read and write.
I hope this helps you with your problem.
same pb, and don't know if it's feasible :
public native DataTable createDataTable(String obj) /*-{
console.log("create Datatable :" + obj);
var dt = new $wnd.google.visualization.DataTable(obj);
console.log("Datatable created");
return dt;
}-*/;
This create an empty dataTable whereas the JSON input is well formatted...
Related
I'm new to stackexchange so my apologies if this question is too extensive or already answered somewhere I couldn't find. You can find the spreadsheet here, the script here and the dashboard (dev version) here.
I have been banging my head on handling dates in the google app script visualization for days.
My ultimate goal is to make a dashboard that includes an annotated timeline as well as other charts based on a data set in a spreadsheet. I have started this process using Mogsdad tutorial on creating a 3-tier google visualization dashboard, where the data is pulled from external spreadsheet and then pulled into the DataTable using arrayToDataTable. Everything worked great out of the box. However, my data contains dates, so I added a date column to the original data, but alas arrayToDataTable doesn't accept date type per this post. So when a Date column is added i get the following result:
ScriptError: The script completed but the returned value is not a
supported return type.
I have tried multiple approaches to ensure even date formatting: options includes putting the values in the date column through new Date(dateColumn[i]), dateColumn[i].toJSON() (renders the dash board, but dates aren't able to be processed), forced date formats in the spreadsheet (yyyy-MM-dd), using the DataView outlined in the post above (dashboards don't get past 'Loading'), and such.
So my question is what is the alternatives to arrayToDataTable that will accept date columns in this 3-tier approach? Or alternatively, what are the errors in the below methods?
For all the cases when I have attempted to add columns I have changed the code from var data = google.visualization.arrayToDataTable(response,false) to var data = google.visualization.DataTable()
I have tried the following:
Manually adding columns and manually adding data (not working)
//Add Columns
data.addColumn('string','Name');
data.addColumn('string','Gender');
data.addColumn('number','Age');
data.addColumn('number','Donuts eaten');
data.addColumn('date','Last Donut Eaten');
//Add Rows
data.addRows([
['Miranda','Female', 22,6,6],
['Jessica','Female',22,6,12],
['Aaron','Male',3,1,13]
]);
Automatically adding the rows without dates (The rows are added, but it only works if there are no date columns)
//Add Rows
for (var i=1; i<response.length; i++) {
data.addRow(response[i]);
}
Manually adding columns and automatically adding rows (not working, combination of 1 and 2)
Automatically adding the columns with loops (not working, neither if dates or not)
for (var i=0; i<response[0].length; i++) {
if (response[1][i] instanceof Date) { //Checks if first value is Date
data.addColumn('date',response[0][i]);
};
else if (response[1][i] instanceof Number) //Checks if first value is Number
data.addColum('number',response[0][i]);
else data.addColumn('string',response[0][i]; //Otherwise assume string
};
Thank you so much for your help!
you can use the Query (google.visualization.Query) class to pull the data from the spreadsheet,
this will convert the date column properly...
google.charts.load('current', {
packages:['table']
}).then(function () {
var queryURL = 'https://docs.google.com/spreadsheets/d/1aaxYNLCuPz3o3TA1jdryenUP01Qbkdaut4AR5eIhe9s/edit#gid=0';
var query = new google.visualization.Query(queryURL).send(function (response) {
var data = response.getDataTable();
// show column types
for (var i = 0; i < data.getNumberOfColumns(); i++) {
console.log(data.getColumnLabel(i), '=', data.getColumnType(i));
}
// draw table chart
var table = new google.visualization.Table(document.getElementById('chart-table'));
table.draw(data);
});
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart-table"></div>
note: the example uses jsapi to load the library,
this library should no longer be used.
according to the release notes...
The version of Google Charts that remains available via the jsapi loader is no longer being updated consistently. Please use the new gstatic loader.js from now on.
this will only change the load statement, see above snippet...
I want to move columns in Grid Panel and save its position in database so that next time when i login I will get same column reordering in Grid Panel. I am using following function to move column in gridpanel.
columnmove: function (container, coulmn, from, to) {
alert('Column Moved From' + from + 'To' + to);
}
You can implement an Ext.state.Provider:
Abstract base class for state provider implementations. The provider
is responsible for setting values and extracting values to/from the
underlying storage source. The storage source can vary and the details
should be implemented in a subclass. For example a provider could use
a server side database or the browser localstorage where supported.
Alternatively you can use the existing Ext.state.LocalStorageProvider class.
Save the order of the columns in comma separated or some other formats in the database . Next time construct the columns dynamically using the values from the backend.
something like this
var selectedColumns = ['Description', 'DateTime', 'Type', 'Status'];
var gridColumns = [];
for (var i = 0; i < selectedColumns.length; i++) {
var col = {
text: selectedColumns[i],
dataIndex: selectedColumns[i],
sortable: true,
hideable: false,
};
gridColumns.push(col);
}
grid.columns= gridColumns
or use
grid.reconfigure(grid.getStore(), gridColumns);
I have implemented a gwt incubator table following the example at http://zenoconsulting.wikidot.com/blog:17
this works great however, the order of rows is not same as it is passed using the list object.
the data in this example is set in the following part of the code:
public long showMessages(ArrayList<Message> list) {
long start = System.currentTimeMillis();
// update the count
countLabel.setText("There are "+ list.size() + " messages.");
// reset the table model data
tableModel.setData(list);
// reset the table model row count
tableModel.setRowCount(list.size());
// clear the cache
cachedTableModel.clearCache();
// reset the cached model row count
cachedTableModel.setRowCount(list.size());
// force to page zero with a reload
pagingScrollTable.gotoPage(0, true);
long end = System.currentTimeMillis();
return end - start;
}
Please provide some solution to fix this issue.
awesome! thank you! somehow i ignored this part and internally down the line code was using a hashMap to manage table data which obviously does not retain the sort order. i changed it to linkedHashMap and it worked
How can one find where are lines located in a document with iText?
Suppose say I have a table in a PDF document, and want to read its contents; I would like to find where exactly the cells are located. In order to do that I thought I might find the intersections of lines.
I think your only option using iText will be to parse the PDF tokens manually. Before doing that I would have a copy of the PDF spec handy.
(I'm a .Net guy so I use iTextSharp but other than some capitalization differences and property declarations they're almost 100% the same.)
You can get the individual tokens using the PRTokeniser object which you feed bytes into from calling getPageContent(pageNum) on your PdfReader.
//Get bytes for page 1
byte[] pageBytes = reader.getPageContent(1);
//Get the tokens for page 1
PRTokeniser tokeniser = new PRTokeniser(pageBytes);
Then just loop through the PRTokeniser:
PRTokeniser.TokType tokenType;
string tokenValue;
while (tokeniser.nextToken()) {
tokenType = tokeniser.tokenType;
tokenValue = tokeniser.stringValue;
//...check tokenValue, do something with it
}
As far a tokenValue, you'd want to probably look for re and l values for rectangle and line. If you see an re then you want to look at the previous 4 values and if you see an l then previous 2 values. This also means that you need to store each tokenValue in an array so you can look back later.
Depending on what you used to create the PDF with you might get some interesting results. For instance, I created a 4 cell table with Microsoft Word and saved as a PDF. For some reason there are two sets of 10 rectangles with many duplicates, but the general idea still works.
Below is C# code targeting iTextSharp 5.1.1.0. You should be able to convert it to Java and iText very easily, I noted the one line that has .Net-specific code that needs to be adjusted from a Generic List (List<string>) to a Java equivalent, probably an ArrayList. You'll also need to adjust some casing, .Net uses Object.Method() whereas Java uses Object.method(). Lastly, .Net accesses properties without gets and sets, so Object.Property is both the getter and setter compared to Java's Object.getProperty and Object.setProperty.
Hopefully this gets you started at least!
//Source file to read from
string sourceFile = "c:\\Hello.pdf";
//Bind a reader to our PDF
PdfReader reader = new PdfReader(sourceFile);
//Create our buffer for previous token values. For Java users, List<string> is a generic list, probably most similar to an ArrayList
List<string> buf = new List<string>();
//Get the raw bytes for the page
byte[] pageBytes = reader.GetPageContent(1);
//Get the raw tokens from the bytes
PRTokeniser tokeniser = new PRTokeniser(pageBytes);
//Create some variables to set later
PRTokeniser.TokType tokenType;
string tokenValue;
//Loop through each token
while (tokeniser.NextToken()) {
//Get the types and value
tokenType = tokeniser.TokenType;
tokenValue = tokeniser.StringValue;
//If the type is a numeric type
if (tokenType == PRTokeniser.TokType.NUMBER) {
//Store it in our buffer for later user
buf.Add(tokenValue);
//Otherwise we only care about raw commands which are categorized as "OTHER"
} else if (tokenType == PRTokeniser.TokType.OTHER) {
//Look for a rectangle token
if (tokenValue == "re") {
//Sanity check, make sure we have enough items in the buffer
if (buf.Count < 4) throw new Exception("Not enough elements in buffer for a rectangle");
//Read and convert the values
float x = float.Parse(buf[buf.Count - 4]);
float y = float.Parse(buf[buf.Count - 3]);
float w = float.Parse(buf[buf.Count - 2]);
float h = float.Parse(buf[buf.Count - 1]);
//..do something with them here
}
}
}
I can send callback param(s) and it works perfectly as long as I am only sending some primitive types like String. But the same thing does not work for even the simplest POJO. PrimeFaces guide says that the RequestContext.addCallbackParam() method can handle POJOs and it coverts them into JSON. I don't know why it's not working in my case.
Has anybody done that?
Solution found! ---------------------------------------------------------------------
I did some research and found the answer to this question.
And the solution was to use some JSON library (right now I am using GSON) to convert Java objects to JSON objects.
new Gson().toJson(someJavaObj)
returns string. Just send the string as the param and on the client side using js' eval or some js library's function to turn that into JSON again.
Actually, it was pretty clean and simple.
Sorry I actually did not post the solution. Below is the my solution -
Action method in the backing bean -
public void retrievePieData() {
List<String> categories = new ArrayList<String>();
categories.add("Electronic");
categories.add("Food");
categories.add("Liguor");
categories.add("Stationary");
categories.add("Mechanical");
List<Integer> itemCounts = new ArrayList<Integer>();
itemCounts.add(5);
itemCounts.add(20);
itemCounts.add(1);
itemCounts.add(50);
itemCounts.add(10);
RequestContext reqCtx = RequestContext.getCurrentInstance();
reqCtx.addCallbackParam("categories", new Gson().toJson(categories));
reqCtx.addCallbackParam("itemCounts", new Gson().toJson(itemCounts));
}
PrimeFaces p:commandButton in the view -
<p:commandLink action="#{pieDataProvider.retrievePieData}" oncomplete="feedPieData(xhr, status, args);" value="Pie chart demo" update="pieData" />
Javascript function -
function feedPieData(xhr, status, args) {
var categories = eval('(' + args.categories + ')');
var itemCounts = eval('(' + args.itemCounts + ')');
options.xAxis.categories = categories;
var series = {
data: []
};
series.name = new Date().toString();
series.data = itemCounts;
options.series = [series];
chart = new Highcharts.Chart(options);
}
I would really appreciate and welcome any suggestion or opinion.
Thank you!