Using Find to find a user property in Outlook/Redemption - outlook

I'm trying to return a single calendaritem from Outlook from our C# windows desktop application. It keeps returning this error:
Redemption.RDOItems
Assertion failed: Number of fields == 1.
I use similar code in an Outlook addin I created and it works fine. The main difference is the filterprefix.
In the AddIn I use:
string filterprefix = "[" + OurCustomProperty.OurItemId + "] = '";
var filter1 = filterprefix + parentItem.NeedlesId + "'";
var findItem = folder.Items.Find(filter1);
but this code does not work from our desktop app.
Here is the code from the desktop App which is returning the error:
The appointment.Id contains a valid value which we set when we create the item.
string Filterprefix = "#SQL="+"http://schemas.microsoft.com/mapi/string/{00020329-0000-0000-C000-000000000046}/OurCustomProperty.OurItemId/0x0000001f = '";
RDOSession rdoSession = new RDOSession();
rdoSession.Logon("", "", false, false, null, false);
RDOFolder folderRDO = rdoSession.GetDefaultFolder(rdoDefaultFolders.olFolderCalendar);
var filter1 = filterprefix + appointment.Id + "'";
string ls_find = Filterprefix + appointment.Id + "'" ;
var findItem = folderRDO.Items.Find(ls_find);
I've tried several variations of the syntax but can't seem to get it right.
I also tried using Sort then Restrict but no luck with that either.
Thanks, Rick

RDOItems.Find takes a SQL statement, please do not use the #SQL= prefix - it is OOM specific. Also do not forget to doublequote the DASL property name:
"http://schemas.microsoft.com/mapi/string/{00020329-0000-0000-C000-000000000046}/OurCustomProperty.OurItemId/0x0000001f" = '<some value>'

Related

cypress use value outside .then() block

i have a case where i enter a searchTerm to a search field. Then I want to count the results shown to randomly select one of the entries. But I cannot realize it with cypress
let countOfElements = "";
cy.get(this.SEARCH_RESULT + ' > a').then($elements => {
countOfElements = $elements.length;
cy.log(countOfElements)
cy.log("Found " + countOfElements + " results for search term + " + searchTerm)
});
cy.get(this.SEARCH_RESULT + ' > a').invoke('val').as('searchEntries')
//This is obviosly not working, but I don't get how to fix this.
let randomNumber = this.getRandomNumberBetweenTwoValues(0, cy.get('#searchEntries')));
cy.get(this.SEARCH_RESULT + ' > a').eq(randomNumber).click()
I tried different things, like storing the value with .as() but I never seem to have access to the value outside a .then() block. So how I can use the value in my "getRandomNumber..." function to decide with entry in the result list shall be selected?
Pls help. thx
let countOfElements = "";
cy.get(this.SEARCH_RESULT + ' > a').then($elements => {
countOfElements = $elements.length;
cy.log(countOfElements)
cy.log("Found " + countOfElements + " results for search term + " + searchTerm)
});
cy.get(this.SEARCH_RESULT + ' > a').invoke('val').as('searchEntries')
//This is obviosly not working, but I don't get how to fix this.
let randomNumber = getRandomNumberBetweenTwoValues(0, this.searchEntries);
cy.get(this.SEARCH_RESULT + ' > a').eq(randomNumber).click()
Something like this could work. If this.searchEntries give undefined error then make the block function(){} instead of ()=>{}

How to query ARCGIS REST Service via ajax with street address

Not very familiar with the necessary GIS concepts so this is a beginner question. From my web app I am querying a GIS REST Service using this query:
require([
"dojo/dom", "dojo/on",
"esri/tasks/query", "esri/tasks/QueryTask", "dojo/domReady!"
], function (dom, on, Query, QueryTask) {
var queryTask = new QueryTask("http://gis.something.org/arcgis/rest/services/XXXX/Operational/MapServer/6");
var query = new Query();
query.returnGeometry = false;
query.outFields = [
"DISTRICTID "
];
query.where = "SUBID = '" + SUBJID + "'";
queryTask.execute(query, showResults);
In this scenario I had a subject ID (SUBID) which I used for the query to return which district the subject falls in (i.e. the respective DistrictID). I now want to query the service by street address, rather than by SUBID. Any pointers how to structure the query in this case?
thank you!
in query.where, just add ' AND ' or ' OR ' to concatenate the where attribute with other conditions...
example:
query.where = "SUBID = '" + SUBJID + "'" + ' AND ' + "otherAttr = " + otherVar;
Any pointers query in this case
var q = new Query();
var query = "SUBID = '" + SUBJID + "'";
query = query + " and " + "attr = " + attrValue
q.where = query;

Servicenow script infinite recursion

I have the following ServiceNow script which inserts the record into live_message table.
(function executeRule(current, previous/*null when async*/) {
var requestBody;
var responseBody;
var status;
var request;
var response;
try {
request = new sn_ws.RESTMessageV2("LiveMessageWebhook", "post");
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var parameters = "&chat_message=" + current.chat_message.toString();
parameters = parameters + "&context=" + current.context.toString();
parameters = parameters + "&formatted_message=" + current.formatted_message.toString();
parameters = parameters + "&has_attachments=" + current.has_attachments.toString();
parameters = parameters + "&has_links=" + current.has_links.toString();
parameters = parameters + "&has_tags=" + current.has_tags.toString();
parameters = parameters + "&ID=" + current.id.toString();
parameters = parameters + "&in_reply_to=" + current.in_reply_to.toString();
parameters = parameters + "&isLiked=" + current.is_liked.toString();
parameters = parameters + "&lastActivity=" + current.last_activity.toString();
parameters = parameters + "&lastMessage=" + current.last_message.toString();
parameters = parameters + "&likeCount=" + current.like_count.toString();
parameters = parameters + "&message=" + current.message.toString();
parameters = parameters + "&next_reply_order_chunk=" + current.next_reply_order_chunk.toString();
parameters = parameters + "&order=" + current.order.toString();
parameters = parameters + "&poll=" + current.poll.toString();
parameters = parameters + "&private=" + current.private_message.toString();
parameters = parameters + "&profile=" + current.profile.toString();
parameters = parameters + "&reflected_field=" + current.reflected_field.toString();
parameters = parameters + "&reply_to=" + current.reply_to.toString();
parameters = parameters + "&state=" + current.state.toString();
parameters = parameters + "&group_type=" + current.sys_class_name.toString();
parameters = parameters + "&created_by=" + current.sys_created_by.toString();
parameters = parameters + "&created_on=" + current.sys_created_on.toString();
parameters = parameters + "&domain=" + current.sys_domain.toString();
parameters = parameters + "&domain_path=" + current.sys_domain_path.toString();
parameters = parameters + "&sys_ID=" + current.sys_id.toString();
parameters = parameters + "&to_profile=" + current.sys_domain.toString();
parameters = parameters + "&updates=" + current.sys_mod_count.toString();
parameters = parameters + "&updated_by=" + current.sys_updated_by.toString();
parameters = parameters + "&updated_on=" + current.sys_updated_on.toString();
request.setRequestBody(encodeURI(parameters));
var l = request.getRequestBody();
response = request.execute();
responseBody = response.haveError()
? response.getErrorMessage()
: response.getBody();
status = response.getStatusCode();
{
var gr = new GlideRecord('live_message');
gr.initialize();
gr.chat_message = current.chat_message;
gr.context = current.context.toString();
gr.formatted_message = "abc";
gr.group = current.group;
gr.has_attachments = current.has_attachments;
gr.has_links = current.has_links;
gr.has_tags = current.has_tags;
gr.id = current.id;
gr.in_reply_to = "admin";
gr.is_liked = current.is_liked;
gr.last_activity = current.last_activity;
gr.last_message = current.last_message;
gr.like_count = current.like_count;
gr.message = "abc";
gr.next_reply_order_chunk = current.next_reply_order_chunk;
gr.order = current.order;
gr.poll = current.poll;
gr.private_message = current.private_message;
gr.profile = current.profile;
gr.reflected_field = current.reflected_field;
gr.reply_to = current.reply_to;
gr.state = current.state;
gr.sys_class_name = current.sys_class_name;
gr.sys_created_by = current.sys_created_by;
gr.sys_created_on = current.sys_created_on;
gr.sys_domain = current.sys_domain;
gr.sys_domain_path = current.sys_domain_path;
gr.sys_mod_count = current.sys_mod_count;
gr.sys_updated_by = current.sys_updated_by;
gr.sys_updated_on = current.sys_updated_on;
gr.to_profile = current.to_profile;
gr.insertWithReferences();
}
} catch (ex) {
responseBody = 'Exception: ' + ex;
status = '900';
requestBody = request
? request.getRequestBody()
: null;
} finally {
gs.info("Final: Request Body: " + requestBody);
gs.info("Final: Response: " + responseBody);
gs.info("Final: HTTP Status: " + status);
gs.addInfoMessage('Final: Finished');
}
})(current, previous);
But after inserting the record it again goes back to the try block again and does the whole thing again and now with the inserted record
How is this business rule configured?
Is it possible that the changes made by this script, could also trigger the script to run?
Here's an example of what I mean:
Imagine I have a business rule that executes whenever a record in the table "u_arbitrary_counter" is updated.
Imagine that the function of this business rule is that whenever such a record is updated, we increase the value of the "u_counter" field by one, like so:
current.setValue('u_counter', parseInt(current.getValue('u_counter')) + 1);
current.update();
By using .update(), I'm forcing an update to the database, EVEN if this is a "before" business rule.
Pro Tip: Note that "before" business rules run on the data that's about to be
saved to the database, BEFORE the actual database operation has taken
place. Any changes to the "current" object in a "before" business rule
will be saved even without using current.update, because you're
modifying the data that's about to be sent to the database anyway, in
the natural course of this operation.
So using current.update() in a BEFORE business rule isn't a great idea. For the same reason though, performing any other operation which necessarily leads to a database update which could trigger this same business rule is a bad idea. It doesn't have to be current.update() -- Instead, imagine if rather than updating the current record, I did something like...
var gr = new GlideRecord('u_arbitrary_counter'); //the same table this BR is running on
gr.initialize();
gr.setValue('u_counter', parseInt(current.getValue('u_counter')) + 1);
gr.insert(); //This triggers a database action!
This is no good for the same reason.
Ditto for any REST calls which would trigger a DB action on this table which may trigger this business rule.
The solution
If this is indeed the cause of your issue (and without knowing the configuration of your business rule, I can't be sure if it is or not), there is actually a way to tell the system not to run any further business rules as a result of the operation your script performs. Right before your gr.insertWithReferences(); line (line 91), IF that block of code is the issue (which I'm fairly confident it is), add:
gr.setWorkflow(false);
This prevents business rules from running.
Unfortunately, since you're placing the record into the live_message table, that may not be a good idea either, since the messenger may require some business rule to propagate or present that information once inserted; I'm not sure.
If that is the case, I would recommend adding a condition to your business rule so that it only runs under certain circumstances, and then craft your inserted record to not meet those criteria.
Pro Tip: PS - I notice you access a table field using current.field_name.toString() in some places, and directly access
current.field_name in others. While the former is acceptable (not
that I recommend it in most cases), the latter should almost never be
used -- except in the case of journal fields. Instead, I strongly
recommend using the appropriate getter/setter methods, to avoid
pass-by-reference issues and confusion, and to ensure you're not
relying on JavaScript's coersion, which doesn't always play nice with
Mozilla Rhino, which ServiceNow runs on the back-end. Example issue
here. For more info, please see my article on using getValue()
and setValue() in ServiceNow.

How to query from URL "Line" Format to VBA variable

I'm trying to make an application that will display user data through api on command... I have assembled the URL generator and everything. it's just beyond me to find a simple way to assign THIS: "http://api.bf4stats.com/api/playerInfo?plat=xbox&name=charlie%20is%20tftc&output=lines" data to specific variables with my parameters. (Lines / Text format)
This is my code so far, I just want to be able to assign data like 'player.id' to playerid and display it. (Player.id is the first value in the data linked above)
//the code below will be changed to user input, I don't need help with that this was just for theory
Public Class Form1
Public Sub URL_Player_Info(ByVal Address As String)
'Assign all data figures for constructing the "URL"...
Dim url, plat, player, webprefix, domain, paramsym, ext, preplat, preplayer, andsym, lineparam, format As String
'Variables for "Plat"
plat = "xbox"
'Input for "Player"
player = "Charlie Is TFTC"
'Structure for "URL"
webprefix = "http://"
domain = "api.bf4stats"
ext = ".com/api/playerInfo"
paramsym = "?"
preplat = "plat="
andsym = "&"
preplayer = "name="
format = "output="
lineparam = "lines"
'Generate Final "URL"
url = webprefix + domain + ext + paramsym + preplat + plat + andsym + preplayer + player + andsym + format + lineparam
'Getting Data / Assigning Data for "Plat. Player: Params"
End Sub
Thanks in advanced!

iteration through outlook appointments

I know how to iterate through non-recurring appointments in Outlook.
My question is, how to I iterate through Outlook appointments including the recurring appointments?
Thank you.
If you are open to using 3rd party libraries, I'd suggest using "Redemption" library (http://www.dimastr.com/redemption/). This library has useful RDOFolder2 interface with GetActivitiesForTimeRange method.
Here you can find more information about usage of this interface:
(http://www.dimastr.com/redemption/rdo/rdofolder.htm)
If you don't want to use 3rd party library and need to stick to Outlook API, the trick is to set IncludeRecurrences flag to true before iterating appointments. The following article should provide enough information on how to do that:
(http://www.outlookcode.com/article.aspx?id=30)
Actually there is no need to use third party tools. There is the option IncludeRecurrences which takes care of this:
Set myNameSpace = myOlApp.GetNamespace("MAPI")
Set MyFolder = myNameSpace.GetDefaultFolder(olFolderCalendar)
Set oItems = MyFolder.Items
' Restrict Date
strFilter = "[Start] >= " + "'" + ourStart + "'"
Set oItems = oItems.Restrict(strFilter)
strFilter = "[End] <= " + "'" + ourEnd + "'"
Set oItems = oItems.Restrict(strFilter)
' Restrict Category
strFilter = "[Categories] = " + "'" + ourCategory + "'"
Set oItems = oItems.Restrict(strFilter)
oItems.Sort "[Start]"
' We want recurring, too (http://www.pcreview.co.uk/forums/get-recurring-appointment-dates-vba-t799214.html)
oItems.IncludeRecurrences = True

Resources