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

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();
}
}

Related

MalformedInputException: Input length = 1 while reading text file with Files.readAllLines(Path.get("file").get(0);

Why am I getting this error? I'm trying to extract information from a bank statement PDF and tally different bills for the month. I write the data from a PDF to a text file so I can get specific data from the file (e.g. ASPEN HOME IMPRO, then iterate down to what the dollar amount is, then read that text line to a string)
When the Files.readAllLines(Path.get("bankData").get(0) code is run, I get the error. Any thoughts why? Encoding issue?
Here is the code:
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\wmsai\\Desktop\\BankStatement.pdf");
PDFTextStripper stripper = new PDFTextStripper();
BufferedWriter bw = new BufferedWriter(new FileWriter("bankData"));
BufferedReader br = new BufferedReader(new FileReader("bankData"));
String pdfText = stripper.getText(Loader.loadPDF(file)).toUpperCase();
bw.write(pdfText);
bw.flush();
bw.close();
LineNumberReader lineNum = new LineNumberReader(new FileReader("bankData"));
String aspenHomeImpro = "PAYMENT: ACH: ASPEN HOME IMPRO";
String line;
while ((line = lineNum.readLine()) != null) {
if (line.contains(aspenHomeImpro)) {
int lineNumber = lineNum.getLineNumber();
int newLineNumber = lineNumber + 4;
String aspenData = Files.readAllLines(Paths.get("bankData")).get(0); //This is the code with the error
System.out.println(newLineNumber);
break;
} else if (!line.contains(aspenHomeImpro)) {
continue;
}
}
}
So I figured it out. I had to check the properties of the text file in question (I'm using Eclipse) to figure out what the actual encoding of the text file was.
Then, when creating the file in the program, encode the text file to UTF-8 so that Files.readAllLines could read and grab the data I wanted to get.

Insert multiple lines of text into a Rich Text content control with OpenXML

I'm having difficulty getting a content control to follow multi-line formatting. It seems to interpret everything I'm giving it literally. I am new to OpenXML and I feel like I must be missing something simple.
I am converting my multi-line string using this function.
private static void parseTextForOpenXML(Run run, string text)
{
string[] newLineArray = { Environment.NewLine, "<br/>", "<br />", "\r\n" };
string[] textArray = text.Split(newLineArray, StringSplitOptions.None);
bool first = true;
foreach (string line in textArray)
{
if (!first)
{
run.Append(new Break());
}
first = false;
Text txt = new Text { Text = line };
run.Append(txt);
}
}
I insert it into the control with this
public static WordprocessingDocument InsertText(this WordprocessingDocument doc, string contentControlTag, string text)
{
SdtElement element = doc.MainDocumentPart.Document.Body.Descendants<SdtElement>().FirstOrDefault(sdt => sdt.SdtProperties.GetFirstChild<Tag>().Val == contentControlTag);
if (element == null)
throw new ArgumentException("ContentControlTag " + contentControlTag + " doesn't exist.");
element.Descendants<Text>().First().Text = text;
element.Descendants<Text>().Skip(1).ToList().ForEach(t => t.Remove());
return doc;
}
I call it with something like...
doc.InsertText("Primary", primaryRun.InnerText);
Although I've tried InnerXML and OuterXML as well. The results look something like
Example AttnExample CompanyExample AddressNew York, NY 12345 or
<w:r xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:t>Example Attn</w:t><w:br /><w:t>Example Company</w:t><w:br /><w:t>Example Address</w:t><w:br /><w:t>New York, NY 12345</w:t></w:r>
The method works fine for simple text insertion. It's just when I need it to interpret the XML that it doesn't work for me.
I feel like I must be super close to getting what I need, but my fiddling is getting me nowhere. Any thoughts? Thank you.
I believe the way I was trying to do it was doomed to fail. Setting the Text attribute of an element is always going to be interpreted as text to be displayed it seems. I ended up having to take a slightly different tack. I created a new insert method.
public static WordprocessingDocument InsertText(this WordprocessingDocument doc, string contentControlTag, Paragraph paragraph)
{
SdtElement element = doc.MainDocumentPart.Document.Body.Descendants<SdtElement>().FirstOrDefault(sdt => sdt.SdtProperties.GetFirstChild<Tag>().Val == contentControlTag);
if (element == null)
throw new ArgumentException("ContentControlTag " + contentControlTag + " doesn't exist.");
OpenXmlElement cc = element.Descendants<Text>().First().Parent;
cc.RemoveAllChildren();
cc.Append(paragraph);
return doc;
}
It starts the same, and gets the Content Control by searching for it's Tag. But then I get it's parent, remove the Content Control elements that were there and just replace them with a paragraph element.
It's not exactly what I had envisioned, but it seems to work for my needs.

LibTiff.net isn't setting the Subject tag

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);

Remove Content controls after adding text using open xml

By the help of some very kind community members here I managed to programatically create a function to replace text inside content controls in a Word document using open xml. After the document is generated it removes the formatting of the text after I replace the text.
Any ideas on how I can still keep the formatting in word and remove the content control tags ?
This is my code:
using (var wordDoc = WordprocessingDocument.Open(mem, true))
{
var mainPart = wordDoc.MainDocumentPart;
ReplaceTags(mainPart, "FirstName", _firstName);
ReplaceTags(mainPart, "LastName", _lastName);
ReplaceTags(mainPart, "WorkPhoe", _workPhone);
ReplaceTags(mainPart, "JobTitle", _jobTitle);
mainPart.Document.Save();
SaveFile(mem);
}
private static void ReplaceTags(MainDocumentPart mainPart, string tagName, string tagValue)
{
//grab all the tag fields
IEnumerable<SdtBlock> tagFields = mainPart.Document.Body.Descendants<SdtBlock>().Where
(r => r.SdtProperties.GetFirstChild<Tag>().Val == tagName);
foreach (var field in tagFields)
{
//remove all paragraphs from the content block
field.SdtContentBlock.RemoveAllChildren<Paragraph>();
//create a new paragraph containing a run and a text element
Paragraph newParagraph = new Paragraph();
Run newRun = new Run();
Text newText = new Text(tagValue);
newRun.Append(newText);
newParagraph.Append(newRun);
//add the new paragraph to the content block
field.SdtContentBlock.Append(newParagraph);
}
}
Keeping the style is a tricky problem as there could be more than one style applied to the text you are trying to replace. What should you do in that scenario?
Assuming a simple case of one style (but potentially over many Paragraphs, Runs and Texts) you could keep the first Text element you come across per SdtBlock and place your required value in that element then delete any further Text elements from the SdtBlock. The formatting from the first Text element will then be maintained. Obviously you can apply this theory to any of the Text blocks; you don't have to necessarily use the first. The following code should show what I mean:
private static void ReplaceTags(MainDocumentPart mainPart, string tagName, string tagValue)
{
IEnumerable<SdtBlock> tagFields = mainPart.Document.Body.Descendants<SdtBlock>().Where
(r => r.SdtProperties.GetFirstChild<Tag>().Val == tagName);
foreach (var field in tagFields)
{
IEnumerable<Text> texts = field.SdtContentBlock.Descendants<Text>();
for (int i = 0; i < texts.Count(); i++)
{
Text text = texts.ElementAt(i);
if (i == 0)
{
text.Text = tagValue;
}
else
{
text.Remove();
}
}
}
}

How to filter datagridview using text inputted from a rich text box?

I have a datagridview that I want to display a data from a database. But I don't want it to display all of the data. I want it to display the data for a specific ID only. Meaning if the user enters 3 ID, it will display the info for that 3 ID. Hence I want to use a rich text box as a filter so that the user can enter multiple ID for each line in the rich text box. The user can enter the ID No. within the rich text box and the data will be used as a filter to display the data for that particular ID. But I cannot make it read beyond the first line of the rich text box. If I enter just one ID in the first line, it works perfectly, but if I enter a second ID in the second line, or in the third line, then it will not display anything at all. I tried using for loop to read each line of the rich text box but it doesn't work. Any advice or solution??
here is my code :
namespace TrackCon
{
public partial class trackInput : Form
{
public trackInput()
{
InitializeComponent();
}
/*private void trackInput_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'trackingBMSDATADataSet.BRDATA' table. You can move, or remove it, as needed.
this.bRDATATableAdapter.Fill(this.trackingBMSDATADataSet.BRDATA);
}*/
private void trackBtn_Click(object sender, EventArgs e)
{
RichTextBox dynamicRichTextBox = new RichTextBox();
DataTable dt = null;
string connoInput = richTextBox1.Text;
string conString = Properties.Settings.Default.BMSDATAConnectionString;
//string[] RichTextBoxLines = dynamicRichTextBox.Lines;
foreach (char line in richTextBox1.Text)
{
using (SqlCeConnection con = new SqlCeConnection(#"Data Source=C:\Documents and Settings\Administrator\My Documents\Visual Studio 2008\Projects\TrackCon\TrackCon\BMSDATA.sdf;Persist Security Info = True;Password=xxxx"))
{
con.Open();
SqlCeCommand com = new SqlCeCommand("SELECT conno,cmpsno,ctrx,dsysdate,cstnno,corigin FROM BRDATA WHERE conno = '" + richTextBox1.Text + "'OR cmpsno = '" + richTextBox1.Text + "'", con);
SqlCeDataAdapter adap = new SqlCeDataAdapter(com);
DataSet set = new DataSet();
adap.Fill(set);
if (set.Tables.Count > 0)
{
dt = set.Tables[0];
}
dataGridView1.DataSource = dt;
con.Close();
}
}
}
}
}
I suggest to use a TextBox and set MultiLine to true.
Then you can read all the ids like this:
string[] ids = myTextBox.Text.Split('\n');
EDIT:
You can use SQL's IN to find all elements:
string sql = "SELECT conno, etc FROM BRDATA WHERE conno IN (" + String.Join(", ", ids) + ")";