Finding Table Start Location Index using Google Docs API - javascript

I want to make a InsertTableRow Request via Docs API and it requires a TableStartLocation.
I used
var tableName = table[0];
foreach (var element in document.Body.Content)
if (element.Table != null)
{
var checkTable = element.Table.TableRows[0].TableCells[0].Content[0].Paragraph.Elements[0]
.TextRun.Content.TrimEnd('\n'); //Get Text Value in first cell of the table
if (tableName.Equals(checkTable)) // Check if the table is the table that I want to add rows
{
Console.WriteLine("Add Table Row");
TableUpdateRequest(ref requests, table, element.StartIndex); // Using element(StructuralElement) to get StartIndex
break;
}
}
To find all table in a document and tried to use the element.StartIndex as Table Start Location but i got: Google.GoogleApiException : Google.Apis.Requests.RequestError Invalid requests[5].insertTableRow: Invalid table start location. Must specify the start index of the table. [400]
What is a suitable index for Table Start Location?

The tableStartLocation is necessary to identify the correct table
A way to retrieve it is e.g. with documents.get. To narrow down the results you can specify fields, e.g. body/content(startIndex,table).
This will return you a resource of the type
{
"body": {
"content": [
{},
{
"startIndex": 1
},
{
"startIndex": 2,
"table": {
"rows": 4,
"columns": 3,
"tableRows": [
{
...
In other words: You know now that your tableStartLocation is 2 - same as the table's startIndex.
Sample
var resource = { "requests": [
{
"insertTableRow": {
"tableCellLocation": {
"tableStartLocation": {
"index": 2
}
},
"insertBelow": false
}
}
]
}
Docs.Documents.batchUpdate(resource, documentId);
Now, depending on your document, you might have several tables and might want to compare names etc. before deciding which is the start index of the correct able.

Related

Exporting model to csv

I'm trying to make an export of my model which consists out of employees, some properties and a Date.
Visualisation of my model
var myModel= {
employees: [{
pentagram: oMyData.Pentagram,
records: [{
Date: oMyData.Date,
GC: oMyData.Lunch,
CheckIn: oMyData.CheckedIn,
CheckOut: oMyData.CheckedOut
}]
}]
};
Purpose of my application
My app is used to log which employee is in the building by letting them check in and out at the front door. This is registered to a HanaXS database. Each day when an employee checks in, a record is created with the corresponding properties. So if the decide not to eat at the office, they will click on the GC button (which stands for 'no consumption' in dutch).
So in a nutshell. Each employee has their own record per date in the database.
What do I want to do
I want to make an excel sheet which will cover a month.
The most left column will cover the names of the employee's (Pentagram). After that all the columns will be a day in the corresponding month in chronological order.
The content should be an X when they pressed the GC button. Otherwise the cell should be empty.
My problem
I have no clue how to get the dates as columns while keeping the binding with the employees. I've already searched a lot on exporting of the model and of tables but nothing is actually near to what I need.
If anyone has some experience or done this before I would be really gratefull for some help.
Thanks in advance
Hi you can use the following libraries
'sap/ui/core/util/Export',
'sap/ui/core/util/ExportTypeCSV',
This is the sample code you can refer to suit your needs
generateExcel: function(oData, that) {
var oModel = new JSONModel();
oModel.setData(oData); //oData is the model data which is binding to the table
var oTable = this.getViewById("yourTableName").getTable();
var aColumns = oTable.getColumns();
var aItems = oTable.getItems();
var aTemplate = [];
for (var i = 0; i < aColumns.length; i++) {
var oColumn = {
name: aColumns[i].getHeader().getText(),
template: {
content: {
path: null
}
}
};
if (aItems.length > 0) {
oColumn.template.content.path = aItems[0].getCells()[i].getBinding("text").getPath();
}
aTemplate.push(oColumn);
}
var oExport = new Export({
// Type that will be used to generate the content. Own ExportType’s can be created to support other formats
exportType: new ExportTypeCSV({
separatorChar: ",",
charset: "utf-8"
}),
// Pass in the model created above
models: oModel,
// binding information for the rows aggregation
rows: {
path: "/results"
},
// column definitions with column name and binding info for the content
columns: aTemplate
});
oExport.saveFile().always(function() {
this.destroy();
});
}
Hi you can use custom formatter for columns depending on types like below an example
var oColumn = {
name: aColumns[i].getHeader().getText(),
template: {
content: {
path: null,
formatter: function(value) {
if (value instanceof(Date)) {
//Convert to user date format
var oFormat = DateFormat.getDateInstance({
style: "short"
});
value = oFormat.format(value);
} else {
value = (value === null) ? "" : value;
}
return value;
}
}
}
};

Finding a row with specific column value in jqxGrid

I am trying to get the data for a row by matching a column value. For example if we have the following data in the grid, I want to get the data of the row which has a CombinedID = 2015-01-02-0222.
[
{"Name":"Test 1", "CombinedID":"2015-01-02-0111", "Description":"Testing"},
{"Name":"Test 2", "CombinedID":"2015-01-02-0222", "Description":"Testing 2"},
{"Name":"Test 2", "CombinedID":"2015-01-02-0333", "Description":"Testing 3"}
]
Cannot find a straight forward method in jqxGrid documentation.
Was looking for something like this (but cannot find any such method yet):
var rowData = $(grid).jqxGrid('getRowByColumnValue','CombinedID',"2015-01-02-0222");
I created a function myself to get the rows which matches the column value:
function getItemsByColumnValue(grid, field, value, selectField) {
var rows = $(grid).jqxGrid('getboundrows');
var output = [];
rows.forEach(function(row) {
if(row[field] == value) {
if(selectField) {
//if selectField is specified, put only that field value to array
output.push(row[selectField]);
} else {
output.push(row);
}
}
});
return output;
}

Loop Through JSON, Insert Key/Value Between Objects?

UPDATE - Thanks for all the great answers and incredibly fast response. I've learned a great deal from the suggested solutions. I ultimately chose the answer I did because the outcome was exactly as I asked, and I was able to get it working in my application with minimal effort - including the search function. This site is an invaluable resource for developers.
Probably a simple task, but I can't seem to get this working nor find anything on Google. I am a Javascript novice and complex JSON confuses the hell out of me. What I am trying to do is make a PhoneGap Application (Phone Directory) for our company. I'll try to explain my reasoning and illustrate my attempts below.
I have JSON data of all of our employees in the following format:
[
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer"
},
{
"id":"2",
"firstname":"Mark",
"lastname":"Banana",
"jobtitle":"Artist"
},
... and so on
]
The mobile framework (Framework 7) that I am using offers a "Virtual List" solution which I need to take advantage of as our directory is fairly large. The virtual list requires you to know the exact height of each list item, however, you can use a function to set a dynamic height.
What I am trying to do is create "headers" for the alphabetical listing based on their last name. The JSON data would have to be restructured as such:
[
{
"title":"A"
},
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer"
},
{
"title":"B"
},
{
"id":"2",
"firstname":"Mark",
"lastname":"Banana",
"jobtitle":"Artist"
},
... and so on
]
I've been able to add key/value pairs to existing objects in the data using a for loop:
var letter, newLetter;
for(var i = 0; i < data.length; i++) {
newLetter = data[i].lastname.charAt(0);
if(letter != newLetter) {
letter = newLetter
data[i].title = letter;
}
}
This solution changes the JSON, thus outputting a title bar that is connected to the list item (the virtual list only accepts ONE <li></li> so the header bar is a div inside that bar):
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer",
"title":"A"
},
{
"id":"1",
"firstname":"Mike",
"lastname":"Apricot",
"jobtitle":"Engineer",
"title":""
}
This solution worked until I tried implementing a search function to the listing. When I search, it works as expected but looks broken as the header titles ("A", "B", etc...) are connected to the list items that start the particular alphabetical section. For this reason, I need to be able to separate the titles from the existing elements and use them for the dynamic height / exclude from search results.
The question: How can I do a for loop that inserts [prepends] a NEW object (title:letter) at the start of a new letter grouping? If there is a better way, please enlighten me. As I mentioned, I am a JS novice and I'd love to become more efficient programming web applications.
var items = [
{ "lastname":"Apple" },
{ "lastname":"Banana" },
{ "lastname":"Box" },
{ "lastname":"Bump" },
{ "lastname":"Can" },
{ "lastname":"Switch" }
];
var lastC = null; //holds current title
var updated = []; //where the updated array will live
for( var i=0;i<items.length;i++) {
var val = items[i]; //get current item
var firstLetter = val.lastname.substr(0,1); //grab first letter
if (firstLetter!==lastC) { //if current title does not match first letter than add new title
updated.push({title:firstLetter}); //push title
lastC = firstLetter; //update heading
}
updated.push(val); //push current index
}
console.log(updated);
Well right now you have an array of objects - prefixing the title as its own object may be a bit confusing - a better structure may be:
[
{
title: "A",
contacts: [
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer",
"title":"A"
}
]
Given your current structure, you could loop and push:
var nameIndexMap = {};
var newContactStructure = [];
for (var i = 0; i < data.length; i++) {
var letter = data[i].lastname.charAt(0);
if (nameIndexMap.hasOwnProperty(letter)) {
//push to existing
newContactStructure[nameIndexMap[letter]].contacts.push(data[i])
} else {
//Create new
nameIndexMap[letter] = newContactStructure.length;
newContactStructure.push({
title: letter,
contacts: [
data[i]
]
});
}
}
newContactStructure will now contain your sorted data.
Demo: http://jsfiddle.net/7s50k104/
Simple for loop with Array.prototype.splice will do the trick:
for (var i = 0; i < data.length; i++) {
if (i == 0 || data[i-1].lastname[0] !== data[i].lastname[0]) {
data.splice(i, 0, {title: data[i].lastname[0]});
i++;
}
}
Demo. Check the demo below.
var data = [
{"lastname":"Apple"},
{"lastname":"Banana"},
{"lastname":"Bob"},
{"lastname":"Car"},
{"lastname":"Christ"},
{"lastname":"Dart"},
{"lastname":"Dog"}
];
for (var i = 0; i < data.length; i++) {
if (i == 0 || data[i-1].lastname[0] !== data[i].lastname[0]) {
data.splice(i, 0, {title: data[i].lastname[0]});
i++;
}
}
alert(JSON.stringify( data, null, 4 ));

Update multiple documents / add keys and its values in to a new array

I have collection named inventory where I have multiple documents that has values for each doc
{ "apples": 2 ,"oranges": 3, "carrots": 5 }
{ "apples": 4, "oranges": 6, "carrots": 9 }
How do I update push all fruits in to a single array on multiple documents like so:
{ "fruits": { "apples":2 ,"oranges":3 }, "carrots": 5 }
First thing to note here is that the example you give is not an array but just a sub-document for "fruits" that has different keys. An "array" in MongoDB would look like this:
{ "fruits": [{ "apples":2 } , { "orange":3 }], "carrot": 5 }
Also, aside from the term "fruits" being subjective, as with no other identifier you would have to specify a "list" of things that qualify as fruits, the other thing to consider is that there is no actual way in MongoDB at present to refer to the existing value of a field when processing an update.
What that means is you need to .find() each document to retrieve the data in order to be able to work with the sort of "re-structure" that you want. This essentially means looping the results an performing an .update() operation for each document.
The Bulk API for MongoDB 2.6 and greater can be of some help here, where at least the "write" operations to the database can be sent in batches, rather than one at a time:
var bulk = db.collection.initializeOrderedBulkOp();
var count = 0;
var fruits = ["apples","oranges"];
var unset = {};
fruits.forEach(function(fruit) {
unset[fruit] = 1;
});
db.collection.find({}).forEach(function(doc) {
var fields = [];
fruits.forEach(function(fruit) {
if ( doc.hasOwnProperty(fruit) ) {
var subDoc = {};
subDoc[fruit] = doc[fruit];
fields.push(subDoc);
}
});
bulk.find({ "_id": doc._id }).updateOne({
"$unset": unset, "$push": { "fruits": { "$each": fields } }
});
count++;
if ( count % 1000 == 0 ) {
bulk.execute();
var bulk = db.collection.initializeOrderedBulkOp();
}
});
if ( count % 1000 != 0 )
bulk.execute();
That also uses the $each modifier for $push in order to add multiple array entries at once. The $unset operator can be safely called for fields that don't exist in the document so there is no need to check for their presence in the document as is otherwise required when constructing the array of elements to $push.
Of course if you actually want a document like what you gave an example of that is not actually an array, then you construct differently with the $set operator:
var fields = {};
fruits.forEach(function(fruit) {
if ( doc.hasOwnProperty(fruit) )
fields[fruit] = doc[fruit];
});
bulk.find({ "_id": doc._id }).updateOne({
"$unset": unset, "$set": { "fruits": fields }
});
Whatever the case is you need to loop the existing collection. There is no operation that allows you to "take" an existing value in a document and "use it" in order to set a new value from a server side perspective.

How to access nested object in JSON returned by Wikipedia API

From this query to the Wikipedia API:
http://en.wikipedia.org/w/api.php?action=query&prop=links&format=json&plnamespace=0& pllimit=10&titles=List%20of%20television%20programs%20by%20name
I get a JSON structure, e.g.:
var data = {
"query": {
"pages": {
"1536715": {
"pageid": 1536715,
"ns": 0,
"title": "List of television programs by name",
"links": [
{
"ns": 0,
"title": "$1.98 Beauty Show"
},
{
"ns": 0,
"title": "''Dance Academy''"
}
]
}
}
},
"query-continue": {
"links": {
"plcontinue": "1536715|0|15\/Love"
}
}
}
I want to work with the elements of the "links" array. However, based on the existence of the element "pageid": 1536715, I suspect the name of the nested object "1536715" is a dynamic value that may change. I am reluctant to use this name to access the "links" array, e.g. query.pages.1536715.links.
Is there any way to "step" past this object, i.e. with a wild card query.pages.*.links? Failing that, can I iterate the children of pages to get this object? I am using jQuery 1.7.2 for this project, in case you can suggest any helpful methods from there.
Yes, you will need to loop over it. See also the very similiar question parse json string from wikimedia using jquery. You could also receive a list of result pageids using the indexpageids parameter.
if (data && data.query && data.query.pages)
var pages = data.query.pages;
else
// error: No pages returned / other problems!
for (var id in pages) { // in your case a loop over one property
var links = pages[id].links
if (links)
for (i=0; i<links.length; i++) {
// do what you want with links[i]
}
else
// error: No links array returned for whatever reasons!
}
This should get you there...
var links, i, pageID;
for (pageID in query.pages) {
links = query.pages[pageID].links;
for (i=0; i<links.length; i++) {
link = links[i];
link.ns; link.title // handle link obj here.
}
}

Categories

Resources