I am having a problem working out how to chain syncs in Office JS - I think I have to do one sync to read the values then another sync to write them back - must be simple but I can't find a chaining example.
Basically I am trying to code the equivalent of this VBA code which does a read and a write via an array
Application.ScreenUpdating = False
d1 = MicroTimer
Set rng1 = Worksheets("Sheet1").Range("A1:A1000")
Set rng2 = Worksheets("Sheet1").Range("D1:D1000")
var = rng1.Value2
rng2.Value2 = var
d2 = (MicroTimer - d1) * 1000
MsgBox d2
or even simpler
Worksheets("Sheet1").Range("D1:D1000").Value2=Worksheets("Sheet1").Range("A1:A1000").Value2
To copy the values from one range to another, you can use the following code:
Excel.run(function(context) {
var range1 = context.workbook.worksheets.getItem("Sheet1").getRange("A1:A1000").load('values');
return context.sync()
.then(() => {
var range2 = context.workbook.worksheets.getItem("Sheet1").getRange("D1:D1000");
range2.values = range1.values;
return context.sync();
});
});
You can use the Range-Class OfficeJS gives you.
Here is the full doc: https://dev.office.com/reference/add-ins/excel/range (Also have a look at the examples given there)
To copy the Range, you need to create both ranges and copy the .values[][] from the source to the dest.
For how to copy a two-dimensional array (in this case: values[][]), you should use google.
To Determine the time, you can use the Date()-Class Java gives you.
Related
I am receiving JSON that includes a time pair in the format:
"_changed": "2020-01-26T00:32:16.282Z"
How do I create a corresponding structure property that parses this into something I can display nicely in a view? Right now I simply have:
property (_changed){
type (core.Text)...
But this string is unwieldy and not suitable for display to users. I tried time.DateTimeExpression but that seems to be NL-oriented. How do I manipulate this into something I can display to users in a result view?
The easiest (and possible only) way is to do it in Java Script. There is not any NL training in viv.time can handle that.
Bixby has JS library that could parse this format, just do the following. Read more about dates library here
var dates = require('dates')
var console = require('console')
module.exports.function = function getToday () {
var res = dates.ZonedDateTime.parseDateTime("2020-01-26T00:32:16.282Z")
console.log('res', res)
return 'works!'
}
And check the debugger would see the result.
The following may not be the best Javascript code, but would get the job done for some non-supported format.
var str = "2020-01-26T00:32:16.282Z";
var res = str.split("T")[0].split("-");
var year = parseInt(res[0]);
var month = parseInt(res[1]);
var date = parseInt(res[2]);
You can do the same with hour/minute/second then create and return viv.time object in JS.
I am using IBM BPM 8.6
I have an input string as follows:
"\"RECORD_CONTACT\":\"Maram\" , \"DRUG\":\"Panadol\"
In a script on server side, I want to dynamically create a business object like this:
tw.local.recordContact = Maram;
tw.local.drug = Panadol;
How can I dynamically create the business object?
There are a few problems with your request. The first is that you are not creating a business object, you are creating variables. In IBM BPM the variables have to be declared at design time or you will get an error, so invoking attempting to call something like -
tw.local.myVariable = 'Bob';
Will throw an exception if tw.local.myVariable has not been declared. Base on your other question you asked here (link), I'm going to assume you actually have an ANY variable declared called "return" so that
tw.local.return.myVariable = 'Bob'
will work. Given that I based on Sven's answer I think something like the following will work (you will need to validate)
var str = "\"RECORD_CONTACT\":\"Maram\" , \"DRUG\":\"Panadol\"";
var jsonStr = "{" + str.replace(/\\\"/g,'\"') + "}";
var tempValue = JSON.parse(jsonStr);
var keyArray = Object.keys(tempValue);
var valueArray = Object.values(tempValue);
for(var keyCount=0; keyCount<keyArray.length; keyCount++{
var evalString = "tw.local.return."+keyArray[keyCount]+"="+valueArray[keyCount];
eval(evalString);
}
I'll note that doing this is a very bad idea as it would be very brittle code and that using eval() in this manner opens you up to all sorts of possible exploits. It will also fail badly if the value for one of the keys is not a simple type.
-Andrew Paier
One should know what you are going to do with dynamically created Business Objects (BO) to answer you better. Like a very generic way would be - creating JSON object instead of BO.
But if you want to stick with BO then this is only possible when you know all the BO structure (schema) beforehand during design time.
var str = "\"RECORD_CONTACT\":\"Maram\" , \"DRUG\":\"Panadol\"";
vat objArray = str.split("reg ex to split each object string")
foreach (obj in objArray ){
if(obj.indexOf( "RECORD_CONTACT")!=-1)
tw.local.recordContact = new tw.object.RECORD_CONTACT();
//below goes code get value of each attribute of BPM from string
}
else if(obj.indexOf( "DRUG")!=-1){
//similar code to create BO DRUG
}
Don't forget to create BO before using those :)
The following code is working but extremely slow. Up till the search function all goes well. First, the search function returns a sequence and not an array (why?!). Second, the array consists of nodes and I need URI's for the delete. And third, the deleteDocument function takes a string and not an array of URI's.
What would be the better way to do this? I need to delete year+ old documents.
Here I use xdmp.log in stead of document.delete just te be safe.
var now = new Date();
var yearBack = now.setDate(now.getDate() - 365);
var date = new Date(yearBack);
var b = cts.jsonPropertyRangeQuery("Dtm", "<", date);
var c = cts.search(b, ['unfiltered']).toArray();
for (i=0; i<fn.count(c); i++) {
xdmp.log(fn.documentUri(c[i]), "info");
};
Doing the same with cts.uris:
var now = new Date();
var yearBack = now.setDate(now.getDate() - 365);
var date = new Date(yearBack);
var b = cts.jsonPropertyRangeQuery("Dtm", "<", date);
var c = cts.uris("", [], b);
while (true) {
var uri = c.next();
if (uri.done == true){
break;
}
xdmp.log(uri.value, "info");
}
HTH!
Using toArray will work but is most likely were your slowness is. The cts.search() function returns an iterator. So All you have to do is loop over it and do your deleting until there is no more items in it. Also You might want to limit your search to 1,000 items. A transaction with a large number of deletes will take a while and might time out.
Here is an example of looping over the iterator
var now = new Date();
var yearBack = now.setDate(now.getDate() - 365);
var date = new Date(yearBack);
var b = cts.jsonPropertyRangeQuery("Dtm", "<", date);
var c = cts.search(b, ['unfiltered']);
while (true) {
var doc = c.next();
if (doc.done == true){
break;
}
xdmp.log(fn.documentUri(doc), "info");
}
here is an example if you wanted to limit to the first 1,000.
fn.subsequence(cts.search(b, ['unfiltered']), 1, 1000);
Several things to consider.
1) If you are searching for the purpose of deleting or anything that doesnt require the document body, using a search that returns URIs instead of nodes can be much faster. If that isnt convenient then getting the URI as close to the search expression can achieve similar results. You want to avoid having the server have to fetch and expand the document just to get the URI to delete it.
2) While there is full coverage in the JavaScript API's for all MarkLogic features, the JavaScript API's are based on the same underlying functions that the XQuery API's use. Its useful to understand that, and take a look at the equivalent XQuery API docs to get the big picture. For example Arrays vs Iterators - If the JS search API's returned Arrays it could be a huge performance problem because the underlying code is based on 'lazy evaluation' of sequences. For example a search could return 1 million rows but if you only look at the first one the server can often avoid accessing the remaining 999,999,999 documents. Similarly, as you iterate only the in scope referenced data needs to be in available. If they had to be put into an array then all results would have to be pre-fetched and put put in memory upfront.
3) Always keep in mind that operations which return lists of things may only be bounded by how big your database is. That is why cts.search() and other functions have built in 'pagination'. You should code for that from the start.
By reading the users guides you can get a better understanding of not only how to do something, but how to do it efficiently - or even at all - once your database becomes larger than memory. In general its a good idea to always code for paginated results - it is a lot more efficient and your code will still work just as well after you add 100 docs or a million.
4) take a look at xdmp.nodeUrl https://docs.marklogic.com/xdmp.nodeUri,
This function, unlike fn.documentUri(), will work on any node even if its not document node. If you can put this right next to the search instead of next to the delete then the system can optimize much better. The examples in the JavaScript guide are a good start https://docs.marklogic.com/guide/getting-started/javascript#chapter
In your case I suggest something like this to experiment with both pagination and extracting the URIs without having to expand the documents ..
var uris = []
for (var result of fn.subsequence(cts.search( ... ), 1 , 100 )
uris.push(xdmp.nodeUri(result))
for( i in uris )
xdmp.log( uris[i] )
I have a directed graph where paths are stored in JSON array like. It is in the form of source and destination .
Var pathDirection = [{"Source":2,"Destination":3},
{"Source":3,"Destination":4},
{"Source":5,"Destination":4},
{"Source":2,"Destination":5},
{"Source":4,"Destination":6}];
Using above it forms graph like below structure .
My problem is I don’t know the starting point and I have to find all possible path to reach 6 from any node
Like for above graph different path to reach 6 is
Output:
[4 ->6]
[3->4 ->6]
[5->4 ->6]
[2->5->4 ->6]
[2->3->4 ->6]
I have tried to write below algo using backtracking which is working fine but looking for some best algo to find. Please suggest any other possible way to do same and how can i optimize below programe.
// BackTrack From End Node Destination 6
var getAllSource = function(destId){
var sourceForsameDist = [];
pathDirection.forEach(function(eachDirection){
if(eachDirection.Destination == destId){
sourceForsameDist.push(eachDirection.Source);
}
});
return sourceForsameDist;
};
var diffPath = [];
var init = function(destination){
var sourceId = getAllSource(destination[destination.length - 1]);
if(sourceId.length === 0){
diffPath.push(destination);
}
for(var i=0;i<sourceId.length;i++){
var copy = destination.slice(0);
copy.push(sourceId[i]);
init(copy);
}
};
init([6]);
console.log(diffPath); // [[6,4,3,2],[6,4,5,2]]
I have tried to do using backtracking which is working fine but looking for some best algo to find.
I'd call it Depth-First-Search instead of backtracking, but yes the algorithm is fine.
However, I'd have some suggestions on the implementation:
make diffPath a local variable and return it from the init function
If you omit the if(sourceId.length === 0) condition then you will get the expected output, not only the the paths from the sources
instead of looping through the whole pathDirections in your getAllSource function, I'd use a lookup table that is filled before starting the traversal
rename init to something more meaningful
I have a question about how to use the distribution functions within the jstat library. Specifically, I am focused on studentt.
I've tried this:
var alphaLevel = 0.05;
var degreesOfFreedom = 18;
// the answer I want to get is 2.100922
tStat = jStat.studentt(alphaLevel,degreesOfFreedom);
// but all that is returned is an object with
// members _a,_b,_c (_a=alphaLevel, _b=degreesOfFreedom,_c=undefined).
As explained on the jstat github site, there is a difference between static and instance functions. However, it is above my experience with javascript as to how to do this.
Can anyone explain how to properly call the studentt function and get the proper result?
Thank you!
The usage follows this documentation: http://jstat.github.io/distributions.html#jStat.studentt
So in your example you have two options. Either you can get the result immediately:
var tStat = jStat.studentt.pdf(alphaLevel, degreesOfFreedom);
Or you can return an instance that allows you to pass in multiple values of alpha:
var tStat = jStat.studentt(degreesOfFreedom);
var a1 = tStat.pdf(alpha1);
var a2 = tStat.pdf(alpha2);