Open XML document ContentControls problem with signed id's - ms-word

I have an application that generates Open XML documents with Content Controls.
To create a new Content Control I use Interop and the method ContentControls.Add. This method returns an instance of the added Content Control.
I have some logic that saves the id of the Content Control to reference it later, but in some computers I've been having a weird problem.
When I access the ID property of the Content Control I just created, it returns a string with the numeric id, the problem is that when this value is too big, after I save the document, if I look through the document.xml in the generated document, the <w:id/> element of the <w:sdtPr/> element has a negative value, that is the signed equivalent of the value I got from the Id property of the generated control.
For example:
var contentControl = ContentControls.Add(...);
var contentControlId = contentControl.ID;
// the value of contentControlId is "3440157266"
If I save the document and open it in the Package Explorer, the Id of the Content Control is "-854810030" instead of "3440157266".
What have I figured out is this:
((int)uint.Parse("3440157266")).ToString() returns "-854810030"
Any idea of why this happens? This issue is hard to replicate because I don't control the Id of the generated controls, the Id is automatically generated by the Interop libraries.

When displayed in 32-bit binary format, -854810030 and 3440157266 are just the same!

This problem is mentioned in the MSDN documentation of the ContentControl.ID Property:
When you get the ID property value at runtime, it is returned as an unsigned value. However, when saved into the Office Open XML file format, it is saved as a signed value. If your solution attempts to map programmatically returned values to values saved in the file format, you must check for both the unsigned and signed version of the value obtained from this property.
As Claude Martel mentioned, -854810030 and 3440157266 are ident. You can easily check this by casting the signed Int32 to a unsigned UInt32:
var id = Convert.ToInt32("-854810030 ");
UInt32 uId = (uint) id;
Assert.AreEqual(3440157266, uId);

I've had the very same type of issue in the past. The ID is unreliable as it doesn't seem to perpeturate. What I did instead is stored a name of the Content Control's .Tag so I could access it later.

Related

Word VSTO - Why paraId is sometimes missing

I'm retrieving paragraph stylenames from openXML and using paraID property to get the right one.
During testing i noticed that depending on the word document the attribute might not be present on any of the paragraphs.
I do know that this is a internal runtime paragraph id for Word.
So the question is: What generates the paraId properties on the paragraphs, can't seem to figure this out.
ps. I don't want to use get_style() since that is waay too slooooow...
edit: added code example
This is in some documents "0" and in some documents a valid hex id
string sParaId = range.Paragraphs.First.ParaID.ToString("x").ToUpper();
This open xml document sometimes have valid w14:paraId-attribute and sometimes it is missing:
activeDocument = Globals.ThisAddIn.Application.ActiveDocument;
wordXML = XElement.Parse(activeDocument.WordOpenXML);
... I would like to get the styleName something like this from the WordOpenXML but for now it seems i might go for some other option since I don't know when paraId is added in the XML.
paraEl = ooXMLElementList.Descendants().Where(x => x.Name.LocalName ==
"p").FirstOrDefault(x => x.Attribute(w14 + "paraId")?.Value == sParaId);
styleName = paraEl.Descendants().FirstOrDefault(x => x.Name.LocalName ==
"pStyle") != null ? paraEl.Descendants().FirstOrDefault(x =>
x.Name.LocalName == "pStyle").Attribute(w + "val").Value : "Normal";
From the Word Language Reference for Paragraph.ID:
Returns or sets the identifying label for the specified object when
the current document is saved as a Web page.
Since the document is not saved as HTML the property has no meaning.
The ParaId property is not exposed for developers to use. It's not visible in the VBA object model, but due to the way the PIA (primary interop assemblies) are generated the .NET developer will see it. From the language reference:
Reserved for internal use.
Not sure what it is you're really trying to do, but you can use Word's Range.Find capability to search formatting (styles).

How to Send a Glympse from the Automate App

From the app Automate, I would like to send a Glympse. Automate's App Start block takes the following inputs. I assume not all of them have to be specified.
Package
Activity Class
Action
Data URI
Mime Type
Category
Extras
Flags
What should I set for the above values?
I am reading some code and looking at some documentation. I figured out that the Package should be com.glympse.android.glympse and the Activity Class should be com.glympse.android.intent.Create. The extras input should be set to a dictionary object. The dictionary should have a message key with a string value. The duration key has a long value which holds the number of milliseconds to share the location. I haven't figured out the rest of the keys or their formats.
Here are the steps...
Create a dictionary named recipient with these keys:
type with a string value of sms
address with a string value of 5425551212 // replace with the actual phone number
Create another dictionary named options with these keys:
recipients with a string value of jsonEncode(recipient) // this will convert the recipient dictionary into a JSON string
message with a string value of whatever you want to say
duration with a long value of the number of milliseconds to share the Glympse location (e.g. 1800000 for 30 minutes)
Use the App Start block with the following inputs:
Package is set to com.glympse.android.glympse
Activity Class is set to com.glympse.android.intent.Create
Action is set to Run
Extras is set to options // the dictionary created above
This will cause the Glympse screen to show up so that the user only has to hit the Create button.

Realm: imported data are shown as String type not Int

I have a problem with builded realm. When I am importing CSV or XLSX file to realm browser, it will generate a "default.realm" file and mark the columns with Integer values as String, but i need it as Int type, because a need to perform .max() function on it.
When i define in object class like this
let price = RealmOptional<Int>()
.. it will crash.
There is an issue in current version of Realm Browser unfortunately :( I've created https://github.com/realm/realm-browser-osx/issues/210 to track it.

embeddedmap of strings not working after 2.2

I had been developing some base queries for about 6 months prior to the release of 2.2
CREATE CLASS Flag_Definitions EXTENDS V
CREATE PROPERTY Flag_Definitions.V_status EMBEDDEDMAP STRING
CREATE PROPERTY Flag_Definitions.V_branding EMBEDDEDMAP STRING
CREATE PROPERTY Flag_Definitions.Block_type EMBEDDEDMAP STRING
CREATE VERTEX Flag_Definitions SET title = "developer reference for all data flags", V_status = {"ACTIVE":"Normal active record", "SUSPENDED":"Currently inactive record","DELETED":"Discontinued record maintained for archiving"}, Block_type = {"Prop":"Holds text from a data object property","HTML":"Holds basic HTML for content","Container":"Holds other blocks"}
but now I'm getting this error in studio
{"errors":[{"code":400,"reason":400,"content":"Map found but entries are not defined as :\r\n\tDB name=\"TestDB\""}]}
From console, the phrasing is slightly different
Map found but entries are not defined as <key>:<value>
Either way, the format 'SET mapfield = {"key":"val"}' no longer seems to be working, and I can't find an explanation. I even looked into the orient code on github (line 118), but, having 2 parts, the format should be passing the check on line 117.
Solved this one, it has nothing to do with the Flag_Definitions object, but I had a default status flag being applied to all created vertices
CREATE PROPERTY V.flags EMBEDDEDMAP STRING
ALTER PROPERTY V.flags DEFAULT {"status":"ACTIVE"}
The issue is the DEFAULT, which needs to be
DEFAULT '{"status":"ACTIVE"}'
Similarly, I had to change
DEFAULT sysdate() to DEFAULT "sysdate()"

Get statuscode text in C#

I'm using a plugin and want to perform an action based on the records statuscode value. I've seen online that you can use entity.FormattedValues["statuscode"] to get values from option sets but when try it I get an error saying "The given key was not present in the dictionary".
I know this can happen when the plugin cant find the change for the field you're looking for, but i've already checked that this does exist using entity.Contains("statuscode") and it passes by that fine but still hits this error.
Can anyone help me figure out why its failing?
Thanks
I've not seen the entity.FormattedValues before.
I usually use the entity.Attributes, e.g. entity.Attributes["statuscode"].
MSDN
Edit
Crm wraps many of the values in objects which hold additional information, in this case statuscode uses the OptionSetValue, so to get the value you need to:
((OptionSetValue)entity.Attributes["statuscode"]).Value
This will return a number, as this is the underlying value in Crm.
If you open up the customisation options in Crm, you will usually (some system fields are locked down) be able to see the label and value for each option.
If you need the label, you could either do some hardcoding based on the information in Crm.
Or you could retrieve it from the metadata services as described here.
To avoid your error, you need to check the collection you wish to use (rather than the Attributes collection):
if (entity.FormattedValues.Contains("statuscode")){
var myStatusCode = entity.FormattedValues["statuscode"];
}
However although the SDK fails to confirm this, I suspect that FormattedValues are only ever present for numeric or currency attributes. (Part-speculation on my part though).
entity.FormattedValues work only for string display value.
For example you have an optionset with display names as 1, 2, 3,
The above statement do not recognize these values because those are integers. If You have seen the exact defintion of formatted values in the below link
http://msdn.microsoft.com/en-in/library/microsoft.xrm.sdk.formattedvaluecollection.aspx
you will find this statement is valid for only string display values. If you try to use this statement with Integer values it will throw key not found in dictionary exception.
So try to avoid this statement for retrieving integer display name optionset in your code.
Try this
string Title = (bool)entity.Attributes.Contains("title") ? entity.FormattedValues["title"].ToString() : "";
When you are talking about Option set, you have value and label. What this will give you is the label. '?' will make sure that the null value is never passed.