LibTiff.net isn't setting the Subject tag - tags

I'm trying to mimic some production code to generate Tiffs with a subject for testing purposes (IE in windows, right click, go to properties and the details tab there is a subject). We place some text we need to reference later in the subject field. The field we use is 0x9c9f which as far as I can find is (Subject tag used by Windows, encoded in UCS2)
Here's the code I'm using to generate the tag
public static void TagExtender(Tiff tif)
{
TiffFieldInfo[] tiffFieldInfo =
{
new TiffFieldInfo(TIFFTAG_SUBJECT, 256, 256, TiffType.BYTE, FieldBit.Custom, true, false, "XPSubject"),
};
tif.MergeFieldInfo(tiffFieldInfo, tiffFieldInfo.Length);
//if (m_parentExtender != null)
// m_parentExtender(tif);
}
public static void GenerateTiff(string filename, int pages = 1, bool encrypt = false, string tag = null)
{
// Register the custom tag handler
if (m_parentExtender == null)
{
Tiff.TiffExtendProc extender = TagExtender;
m_parentExtender = Tiff.SetTagExtender(extender);
}
// Open the output image
using (Tiff output = Tiff.Open(filename, "w"))
{
//...other code to generate tiff
if (tag != null)
{
byte[] bytes = UnicodeStr2HexStr(tag);
output.SetField(TIFFTAG_SUBJECT, bytes.Length-1, bytes);
}
// Code to actually write the image ....
output.WriteDirectory();
}
output.Close();
}
Basically, the tag (code wise) appears to be in the tiff but the windows properties dialog never shows it. Anything special needed to get this in place?

You are passing a bytecount, but set the passCount flag to false.
If you want to pass the count, use these lines at their correct positions:
// Your FieldInfo
new TiffFieldInfo((TiffTag)40095, -1, -1, TiffType.BYTE, FieldBit.Custom, true, true, "XPSubject")
// Your Input
byte[] test = Encoding.Unicode.GetBytes("Test3");
tiff.SetField((TiffTag)40095, test.Length, test);

Related

How to catch *all* characters sent to Text field from a HID barcode scanner?

I need to capture input from a barcode scanner. Up until now the input has been just simple alphanum text which I have captured in one Text field. I added a ModifyListener to the Text field and am able to see the input arrive. That has worked fine.
I now need to handle a more complex matrix code which contains values for multiple fields. The values are separated by non-printable characters such as RS, GS and EOT (0x1E, 0x1D, 0x04). The complete data stream has a well-defined header and an EOT at the end, so I am hoping that I can detect barcode input as opposed to manual input.
When a barcode is detected, I can use the record separators RS to split the message and insert the values into the relevant Text fields.
However, the standard key handler on the Text controls ignore these non-printable characters and they do not appear in the controls text. This makes it impossible to proceed as planned.
How could I modify these Text fields to accept and store all characters? Or is there an alternative approach I could use?
This is the code I used to handle the barcode stream.
public class Main
{
static StringBuilder sb = new StringBuilder();
public static void main(String[] args)
{
Display d = new Display();
Shell shell = new Shell(d);
shell.setLayout(new FillLayout());
Text text = new Text(shell, 0);
text.addListener(SWT.KeyDown, new Listener()
{
#Override
public void handleEvent(Event e)
{
// only accept real characters
if (e.character != 0 && e.keyCode < 0x1000000)
{
sb.append(e.character);
String s = sb.toString();
// have start and end idents in buffer?
int i = s.indexOf("[)>");
if (i > -1)
{
int eot = s.indexOf("\u0004", i);
if (eot > -1)
{
String message = s.substring(i, eot + 1);
handleMessageHere(message);
// get ready for next message
sb = new StringBuilder();
}
}
}
}
});
shell.open();
while (!shell.isDisposed())
{
if (!d.readAndDispatch())
d.sleep();
}
}

Setting URL in UploadCollectionItem in UI5 1.38.4

What parameters are mandatory for an UploadCollectionItem with the URL parameter set will show the file when the filename is clicked.
I am using a factory to handle files coming from different locations.
attachmentFactory(sId, context) {
const modelObj = context.getModel().getProperty(context.getPath());
const uploadListItem = new SAPUploadCollectionItem();
// If __metadata exists, attachment entry is from odata, if not then it's a FileEntry object.
if (modelObj.__metadata) {
uploadListItem.setFileName(modelObj.FILE_NAME);
uploadListItem.setMimeType(modelObj.MIME_CODE);
uploadListItem.setUrl("https://upload.wikimedia.org/wikipedia/commons/4/49/Koala_climbing_tree.jpg");
}
else {
uploadListItem.setFileName(modelObj.name);
uploadListItem.setMimeType(modelObj.type);
uploadListItem.setUrl("https://upload.wikimedia.org/wikipedia/commons/4/49/Koala_climbing_tree.jpg");
}
return uploadListItem;
}
I get an exception in UI5 when I press the link in the function
UploadCollection.prototype._triggerLink = function(oEvent, oContext) {
var iLine = null;
var aId;
if (oContext.editModeItem) {
//In case there is a list item in edit mode, the edit mode has to be finished first.
sap.m.UploadCollection.prototype._handleOk(oEvent, oContext, oContext.editModeItem, true);
if (oContext.sErrorState === "Error") {
//If there is an error, the link of the list item must not be triggered.
return this;
}
oContext.sFocusId = oEvent.getParameter("id");
}
aId = oEvent.oSource.getId().split("-");
iLine = aId[aId.length - 2];
sap.m.URLHelper.redirect(oContext.aItems[iLine].getProperty("url"), true);
};
oContext.aItems is an array but the source.getId() value is "__item9-ta_filenameHL" so __item9 is not found in oContext.aItems
I'm not sure if this is a bug or I'm setting up my UploadCollectionItem incorrectly
I had to set the sId of the UploadCollectionItem to be the sId that was passed into the factory.

Switch Statement for Field Value

I am trying to set up a customization that will dynamically display values in a series of fields using a switch statement.
If we focus on one field I have a String List
public static class SMSPlans
{
public const string A = "A";
public const string B = "B";
public const string C = "C";
public const string Z = "Z";
}
[PXDBString(2, IsUnicode = true)]
[PXDefault(SMSPlans.Z)]
[PXUIField(DisplayName = "SMS Plan Selected")]
[PXStringList(
new string[]
{
SMSPlans.A,
SMSPlans.B,
SMSPlans.C,
SMSPlans.Z
},
new string[]
{
"Plan A",
"Plan B",
"Plan C",
"No Text Plan"
})]
I would like to when this field is set to any one of the allowable values populate a series of fields with corresponding fixed values as shown in the image below (0 is default value currently would show up if any plan is selected)
I planned on using the formula functions and using a switch statement to set my desired value that would look like
[PXFormula(null,typeof(Switch<Case<Where<Current<UsrMPSMSPlanSelected, Equal<SMSPlans.A>>,0>))]
I am stuck however on:
How I need to use the _RowSelect() or other event handlers
What if any value would be stored in the database for these fields assigned by the switch statment
finally is this switch structured correctly as it is not currently working
From what I can tell you have a few ways to handle this.
1) With PXFormula attribute tags - your Switch definition is mostly correct in the sample above but depending on where you have it the PXFormula definition itself is incorrect. What I would do is put the PXFormula tag on the fields that need to be updated.
For example, if your field is UsrMinText use the following:
[PXFormula(typeof(Switch<Case<Where<UsrMPSMSPlanSelected,Equal<SMSPlans.A>>,{value if true},{value if false or more case statements}))]
2) Personally for this type of customization I would use an actual event method in the BLC to do this. A good example of this is in the help guide for the events.
protected void Batch_ManualStatus_FieldUpdating(PXCache sender, PXFieldUpdatingEventArgs e)
{
Batch batch = (Batch)e.Row;
if (batch != null && e.NewValue != null)
{
switch ((string)e.NewValue)
{
case "H":
batch.Hold = true;
batch.Released = false;
batch.Posted = false;
break;
case "B":
batch.Hold = false;
batch.Released = false;
batch.Posted = false;
break;
case "U":
batch.Hold = false;
batch.Released = true;
batch.Posted = false;
break;
case "P":
batch.Hold = false;
batch.Released = true;
batch.Posted = true;
break;
}
}
}
In either method, the value that will be stored in the database is whatever you specify in either the {True}/{False} values for PXFormula or the values specified in the actual switch methods.
One thing to remember is field order in the DACS is important. I'd read through the training information and help guides for more information on this.

Change Sheet tab color of excel file using Open XML

I want to change the sheet tab color of an excel Xlsx document. I am using the following code but it does not set the sheet color. I get object reference exception when I set the sheet tab color.
public static string filepath = #"C:\Test\Book1.xlsx";
private static void ChangeSheetcolor()
{
try
{
using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(filepath, false))
{
WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
IEnumerable<Sheet> sheets = spreadSheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();
//my code
WorksheetPart worksheetPart =
GetWorksheetPartByName(spreadSheetDocument, "Sheet1");
if (worksheetPart != null)
{
// worksheetPart.Worksheet.SheetProperties.TabColor.Rgb = DocumentFormat.OpenXml.HexBinaryValue.FromString("Red");
worksheetPart.Worksheet.SheetProperties.TabColor.Rgb = DocumentFormat.OpenXml.HexBinaryValue.FromString("#CCCCCC");
// Save the worksheet.
worksheetPart.Worksheet.Save();
}
}
}
catch (Exception ex)
{
}
}
private static WorksheetPart
GetWorksheetPartByName(SpreadsheetDocument document,
string sheetName)
{
IEnumerable<Sheet> sheets =
document.WorkbookPart.Workbook.GetFirstChild<Sheets>().
Elements<Sheet>().Where(s => s.Name == sheetName);
if (sheets.Count() == 0)
{
//does not exist
return null;
}
string relationshipId = sheets.First().Id.Value;
WorksheetPart worksheetPart = (WorksheetPart)
document.WorkbookPart.GetPartById(relationshipId);
return worksheetPart;
}
How to change the sheet tab color using Open XML dlls?
You seem to have 3 issues as far as I can tell. Firstly, the second parameter to the Open method you are calling denotes whether or not the file is editable. You need to pass true here if you wish to edit the file otherwise you'll hit the following exception upon saving the worksheet:
System.IO.IOException: Cannot get stream with FileMode.Create, FileMode.CreateNew, FileMode.Truncate, FileMode.Append when access is FileAccess.Read.
Secondly, SheetProperties or TabColor could be null. In the XSD they are defined as
<xsd:element name="sheetPr" type="CT_SheetPr" minOccurs="0" maxOccurs="1"/>
and
<xsd:element name="tabColor" type="CT_Color" minOccurs="0" maxOccurs="1"/>
Note both have minOccurs="0" so either could be null. If they are, you can just create new instances and assign them to the Worksheet.
Finally, the Rgb property is arguably badly named as the documentation states (emphasis mine):
Standard Alpha Red Green Blue color value (ARGB).
The possible values for this attribute are defined by the ST_UnsignedIntHex simple type
(ยง18.18.86).
18.18.86 goes on to say (again, emphasis mine):
This simple type's contents have a length of exactly 8 hexadecimal digit(s).
Assuming you want a solid color you can set the alpha channel to FF. You also shouldn't include the leading # so for a solid red for example you should use "FFFF0000". More details on ARGB values can be found on this question.
Putting that all together your code becomes something like this:
public static string filepath = #"C:\Test\Book1.xlsx";
private static void ChangeSheetcolor()
{
try
{
using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(filepath, false))
{
WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
IEnumerable<Sheet> sheets = spreadSheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();
//my code
WorksheetPart worksheetPart =
GetWorksheetPartByName(spreadSheetDocument, "Sheet1");
if (worksheetPart != null)
{
//create the SheetProperties if it doesn't exist
if (worksheetPart.Worksheet.SheetProperties == null)
worksheetPart.Worksheet.SheetProperties = new SheetProperties();
//create the TabColor if it doesn't exist
if (worksheetPart.Worksheet.SheetProperties.TabColor == null)
worksheetPart.Worksheet.SheetProperties.TabColor = new TabColor();
//this will set the tab color to Red
//note the value is an ARGB not an RGB
worksheetPart.Worksheet.SheetProperties.TabColor.Rgb = DocumentFormat.OpenXml.HexBinaryValue.FromString("FFFF0000");
// Save the worksheet.
worksheetPart.Worksheet.Save();
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}

Syncfusion DocIO -- how to insert image (local file) at bookmark using BookmarksNavigator

I have been using Syncfusion DocIO for generating MS Word documents from my .net applications (winforms). So far I have dealt with plain text and it is fairly straightforward to insert text in a word document template where bookmarks serve as reference points for text insertion.
I am navigating the bookmarks using BookmarksNavigator.MoveToBookmark() . Now I need to insert an image at a bookmark but I am at a loss at how to go about it.
Please help...
Thanks.
Specifically for adding it to a bookmark :
//Move to the specified bookmark
bk.MoveToBookmark(bookmark);
//Insert the picture into the specified bookmark location
bk.DeleteBookmarkContent(true);
// we assume the text is a full pathname for an image file
// get the image file
System.Drawing.Image image = System.Drawing.Image.FromFile(sText);
IWParagraph paragraph = new WParagraph(document);
paragraph.AppendPicture(image);
bk.InsertParagraph(paragraph);
private System.Drawing.Image LoadSignature(string sFileName)
{
string sImagePath = sFileName;
System.Drawing.Image image = System.Drawing.Image.FromFile(sImagePath);
return image;
}
private void MergeSignature(WordDocument doc, string sFile, string sBalise)
{
System.Drawing.Image iSignature = LoadSignature(sFile);
WordDocument ImgDoc = new WordDocument();
ImgDoc.AddSection();
ImgDoc.Sections[0].AddParagraph().AppendPicture(iSignature);
if (iSignature != null)
{
TextSelection ts = null ;
Regex pattern = new Regex(sBalise);
ts = doc.Find(pattern);
if (ts != null)
{
doc.ReplaceFirst = true;
doc.Replace(pattern, ImgDoc, false);
}
}
iSignature.Dispose();
}
See here: https://help.syncfusion.com/file-formats/docio/working-with-mailmerge
1) You should create docx file with name "Template.docx". This file will use as template.
In your docx file create Field of type MergeField.
2) Create MergeFiled with name Image:Krishna
3)
using Syncfusion.DocIO.DLS;
using System.Drawing;
public class Source
{
public Image Krishna { get; set; } = Image.FromFile(#"C:\1.png");
}
and generating code:
public static void Generate()
{
WordDocument doc = new WordDocument("Template.docx");
Source data = new Source();
var dataTable = new MailMergeDataTable("", new Source[] { data });
doc.MailMerge.ExecuteGroup(dataTable);
doc.Save("result.docx");
doc.Close();
}