EDIT:
Below is the format of my XML. It contains data for my IconSheet. I just put only one icon Hex Value for sample.
<Item>
<ItemInfo>
<Value>uE101</Value>
<Name>1</Name>
</ItemInfo>
</Item>
Here is a snippet from my Code
private void OnLoaded(object sender, RoutedEventArgs e)
{
data = (from query in XElement.Load("Data.xml").Descendants("ItemInfo")
select new ItemInfo
{
value = (int)(query.Element("Value").Value),
name = (string)query.Element("Name")
}).ToList();
int itemcount = data.length;
while (itemcount-- > 0)
{
TextBlock t = new TextBlock()
{
Width = 75,
Height = 75,
Text = #"\" + data[itemcount].value,
FontFamily = new FontFamily("Segoe UI Symbol")
};
wrapPanel.Children.Add(t);
}
}
in the Snippet Above data[itemcount].value contains data as "uE101". This does not work.
Below code works.
Text = "\uE101"
Any Help would be greatly appreciated.
UPDATE:
With Help from har07 and mishan comments i now have a clear cut idea as to how to handle HEX codes in C#. Thanks for the help. But i Updated the Question what I am trying with and this is what is causing the problem for me.
You can't separate backslash from next characters in this case. This code :
#"\" + "uE101"
is equal to this :
"\\uE101"
which will output this string instead of special character :
\uE101
They need to be written as single string expression :
"\uE101"
UPDATE :
You can either go with #mishan's second solution by storing only hexadecimal part of the character in xml (<Value>E101</Value>), then parse it to int -> convert int to char -> convert char back to string (following is the example to clarify what I mean) :
.....
TextBlock t = new TextBlock()
{
Width = 75,
Height = 75,
Text = ((char)int.Parse(data[itemcount].value, NumberStyles.HexNumber)).ToString(),
FontFamily = new FontFamily("Segoe UI Symbol")
};
.....
Or to write the exact character to xml and specify xml encoding to a format that support your special characters. You didn't show the codes to create that xml, so I can't help with exact sample that close to yours. But you can search for this topic by keyword "c# write xml document with specific encoding" and will find many examples.
Well, har07 answered your problem in his reply, so I'll just add some possible solutions that come to mind.
1.STORE THE WHOLE CHARACTERS
add the backslash to the data - then it will work
When creating the data, add the backslash to it immediately so it's already complete
2. STORE CHARACTERS AS (HEXADECIMAL) NUMBERS
or store them as characters right away, that would be the best option
when you need to assemble them for some reason, you just do conversion from numbers to characters and voila....
EXAMPLE:
while (itemcount-- > 0)
{
//can be achieved if data[].value is integer
//for testing purposes
//I used integer with value 0xE101
//int a = 0xe101;
TextBlock t = new TextBlock()
{
Width = 75,
Height = 75,
Text = ((char)data[itemcount].value).ToString(),
//Text = ((char)a).Tostring(),
FontFamily = new FontFamily("Segoe UI Symbol")
};
wrapPanel.Children.Add(t);
}
THE UPDATE TO MY ANSWER
the easiest solution to this would be if you could save the whole code in xml.
and by this I mean if you could add the backslash (\) before the uE101
<Item>
<ItemInfo>
<Value>\uE101</Value> //see the added "\" character?
<Name>1</Name>
</ItemInfo>
</Item>
And the C# code:
data = (from query in XElement.Load("Data.xml").Descendants("ItemInfo")
select new ItemInfo
{
value = query.Element("Value").Value, //provided value is of string type
name = query.Element("Name").Value
}).ToList();
store just the HEX values, without the "u" in front like E101, not uE101, and translate them to ints....
//the conversion from STRING CONTAINING HEXADECIMAL CHARACTERS to INTEGER
//can be done by standard methods included in basic interger...
//YOUR'S doesn't work because you didn't remove the `u` in front of the HEX VALUE
//in string - and i'm also not sure about the implicit conversion between
//hexadecimal string and integer....
//so, the improved version of your code using the stuff you have now
private void OnLoaded(object sender, RoutedEventArgs e)
{
//this should work for values stored as integer
data = (from query in XElement.Load("Data.xml").Descendants("ItemInfo")
select new ItemInfo
{
value = int.Parse(query.Element("Value").Value.ToString().Substring(1),NumberStyles.HexNumber),
name = query.Element("Name").Value
}).ToList();
int itemcount = data.length;
while (itemcount-- > 0)
{
TextBlock t = new TextBlock()
{
Width = 75,
Height = 75,
Text = #"\" + data[itemcount].value,
FontFamily = new FontFamily("Segoe UI Symbol")
};
wrapPanel.Children.Add(t);
}
}
CONCLUSION
IMHO the best solution I can think of top of my head is to store the XML with the backslash in the value and when reading, having the ItemInfo class contain two strings - value and name
Related
I need to be able to pull sub strings out of a large string based on data identifiers. What is the proper method to pull specific strings of data?
I'll start with the fact I am a co-op student/ intern so go easy on me.
I am writing a program for a stand alone hand held computer scanner that will store the scanned data internally and transfer it to a computer when docked. (No RF or wireless on this particular site). I can scan a bar code and see the complete string of data no problem, its when I attempt to separate the data string into its variable parts (Part #, vender ID, Date, etc) that I cant get past. I can split the string based on each of the identifiers into a string array but im not sure how to call on the specific data sets based on the prefix data identifier so i can place the needed information into a data grid or export to excel properly.
Ultimately I would like to be able to define all of the different data identifiers( and there are a lot) and have my program go through each scan and pick out the needed information. Since this is a learning experience for me, Im not asking for someone to write it for me but point me in the right direction :)
If the identifiers are always the same between scans, I'd use string.Split
string[] stringArray = scannedString.Split(new string[]{"identifier1", "identifier2"}, StringSplitOptions.RemoveEmptyEntries);
Ive found that using regex has been the best solution.
The only problem I have now is that the my expressions can contain overlapping values. such as in the following code matching to:
[)>6P24274885Q641JUN631170227A0000027L20LA6-98721L54321 ZESKG11556D5-13-19 7:48 AM0366D190513MAY05-13-19011BKLT32147Q76GT2SDELNOTEPUSINV
The quantity is only 64 but my expression is adding the "1" from the 1JUN expression to its value, which is no good. So if anyone has any advice for preventing overlapping expressions? Otherwise Ill be getting learneded on regex methods.
//Define "Showmatch" and what to do when matches found
public void showMatch(string text, string expr, TextBox tb, Label lbl)
{
Regex regex = new Regex(expr);
Match match = regex.Match(text);
if (match.Success)
{
tb.Text = match.Value;
}
else
{
tb.Text = "No Data Found";
}
}
//Set Regular Expression Parameters
DateTime scan_Date = DateTime.Today;
string part_Param = "(P)[0-9-]+";
string serial_Param = "S[0-9-]+";
string duns_Param = "(1JUN)[0-9]+";
string quant_Param = "Q[0-9]+";
string unknown_Param = "20L-B[a-zA-Z0-9]";
public void button1_Click(object sender, EventArgs e)
{
//Pop up window to select data source document
using (OpenFileDialog ofd = new OpenFileDialog() { Filter = "Text Documents(*.txt)|*.txt", ValidateNames = true, Multiselect = true })
if (ofd.ShowDialog() == DialogResult.OK)
{
//Read Text Document From scanner
string[] raw_data = System.IO.File.ReadAllLines(ofd.FileName);
string mod_data = string.Join("", raw_data);
textBox1.Text = (mod_data);
tbScanDate.Text = scan_Date.ToString("dd.MM.yyyy");
showMatch(mod_data, part_Param, tbPartNumber, lblPartNumber);
showMatch(mod_data, serial_Param, tbSerialNumber, lblSerialNumber);
showMatch(mod_data, duns_Param, tbDunsNumber, lblDunsNumber);
showMatch(mod_data, quant_Param, tbQuantity, lblQuantity);
showMatch(mod_data, unknown_Param, tbOther, lblOther);
}
I'm using a RichTextBox for coloured text. Let's assume I want to use different colours for different portions of the text. This is working fine so far.
I'm currently having a problem with the SelectionStart property of the RichTextBox. I've set some text to the Text property of the RichTextBox. If the text contains \r\n\r\n the SelectionStart Position won't match the position of characters with the assigned String.
Small example (WinformsApplication. Form with a RichTextBox):
public Form1()
{
InitializeComponent();
String sentence1 = "This is the first sentence.";
String sentence2 = "This is the second sentence";
String text = sentence1 + "\r\n\r\n" + sentence2;
int start1 = text.IndexOf(sentence1);
int start2 = text.IndexOf(sentence2);
this.richTextBox1.Text = text;
String subString1 = text.Substring(start1, sentence1.Length);
String subString2 = text.Substring(start2, sentence2.Length);
bool match1 = (sentence1 == subString1); // true
bool match2 = (sentence2 == subString2); // true
this.richTextBox1.SelectionStart = start1;
this.richTextBox1.SelectionLength = sentence1.Length;
this.richTextBox1.SelectionColor = Color.Red;
this.richTextBox1.SelectionStart = start2;
this.richTextBox1.SelectionLength = sentence2.Length;
this.richTextBox1.SelectionColor = Color.Blue;
}
The RichTextBox looks like this:
As you can see, the first two characters of the second sentence are not coloured. This is the result of an offset produced by \r\n\r\n.
What is the reason for this? Should I use another control for colouring text?
How do I fix the problem in a reliable way? I've tried replacing the "\r\n\r\n"with a String.Empty, but that produces other offset problem.
Related question:
Inconsistent behaviour between in RichTextBox.Select with SubString method
It seems that the sequence \r\n counts for one character only when doing selections. You can do the measurements in a copy of the string where all \r\n are replaced by \n.
Just for completeness (I'll stick to linepogls answer for now):
I've found another way to get indices for the SelectionStart property. The RichTextBox offers a Find method, that can be used to retrieve index positions based on a specified string.
Be aware of the fact, that the text you want to highlight might not be unique and occur multiple times. You can use an overload to specify a start position for the search.
I have converted an asp.net c# project to framework 3.5 using VS 2008. Purpose of app is to parse a text file containing many rows of like information then inserting the data into a database.
I didn't write original app but developer used substring() to fetch individual fields because they always begin at the same position.
My question is:
What is best way to find the index of substring in text file without having to manually count the position? Does someone have preferred method they use to find position of characters in a text file?
I would say IndexOf() / IndexOfAny() together with Substring(). Alternatively, regular expressions. It the file has an XML-like structure, this.
If the files are delimited eg with commas you can use string.Split
If data is: string[] text = { "1, apple", "2, orange", "3, lemon" };
private void button1_Click(object sender, EventArgs e)
{
string[] lines = this.textBoxIn.Lines;
List<Fruit> fields = new List<Fruit>();
foreach(string s in lines)
{
char[] delim = {','};
string[] fruitData = s.Split(delim);
Fruit f = new Fruit();
int tmpid = 0;
Int32.TryParse(fruitData[0], out tmpid);
f.id = tmpid;
f.name = fruitData[1];
fields.Add(f);
}
this.textBoxOut.Clear();
string text=string.Empty;
foreach(Fruit item in fields)
{
text += item.ToString() + " \n";
}
this.textBoxOut.Text = text;
}
}
The text file I'm reading does not contain delimiters - sometimes there spaces between fields and sometimes they run together. In either case, every line is formatted the same. When I asked the question I was looking at the file in notepad.
Question was: how do you find the position in a file so that position (a number) could be specified as the startIndex of my substring function?
Answer: I've found that opening the text file in notepad++ will display the column # and line count of any position where the curser is in the file and makes this job easier.
You can use indexOf() and then use Length() as the second substring parameter
substr = str.substring(str.IndexOf("."), str.Length - str.IndexOf("."));
I've been trying to figure out how to insert 2 different formats into the same paragraph using interop.word in c# like this:
hello planet earth here's what I want to do
Assuming you have your document defined as oDoc, the following code should get you the desired result:
Word.Paragraph oPara = oDoc.Content.Paragraphs.Add(ref oMissing);
oPara.Range.Text = "hello planet earth here's what I want to do";
object oStart = oPara.Range.Start + 13;
object oEnd = oPara.Range.Start + 18;
Word.Range rBold = oDoc.Range(ref oStart, ref oEnd);
rBold.Bold = 1;
I had to modify Dennis' answer a little to get it to work for me.
What I'm doing it totally automated, so I have to only work with variables.
private void InsertMultiFormatParagraph(string text, int size, int spaceAfter = 10) {
var para = docWord.Content.Paragraphs.Add(ref objMissing);
para.Range.Text = text;
// Explicitly set this to "not bold"
para.Range.Font.Bold = 0;
para.Range.Font.Size = size;
para.Format.SpaceAfter = spaceAfter;
var start = para.Range.Start;
var end = para.Range.Start + text.IndexOf(":");
var rngBold = docWord.Range(ref objStart, ref objEnd);
rngBold.Bold = 1;
para.Range.InsertParagraphAfter();
}
The main difference that made me want to make this post was that the Paragraph should be inserted AFTER the font is changed. My initial thought was to insert it after setting the SpaceAfter property, but then the objStart and objEnd values were tossing "OutOfRange" Exceptions. It was a little counter-intuitive, so I wanted to make sure everyone knew.
The following code seemed to work the best for me when formatting a particular selection within a paragraph. Using Word's built in "find" function to make a selection, then formatting only the selected text. This approach would only work well if the text to select is a unique string within the selection. But for most situations I have run across, this seems to work.
oWord.Selection.Find.Text = Variable_Containing_Text_to_Select; // sets the variable for find and select
oWord.Selection.Find.Execute(); // Executes find and select
oWord.Selection.Font.Bold = 1; // Modifies selection
oWord.Selection.Collapse(); // Clears selection
Hope this helps someone!
I know this post is old, but it came out in almost all my searches. The answer below is in case someone, like me, wants to do this for more than one word in a sentence. In this case, I loop through a string array of variables that contain strings and change that text to bold--modifing #joshman1019
string[] makeBold = new string[4] {a, b, c, d};
foreach (string s in makeBold)
{
wApp.Selection.Find.Text = s; //changes with each iteration
wApp.Selection.Find.Execute();
wApp.Selection.Font.Bold = 1;
wApp.Selection.Collapse(); //used to 'clear' the selection
wApp.Selection.Find.ClearFormatting();
}
So, each string represented by the variable will be bold. So if a = "hello world", then Hello World is made bold in the Word doc. Hope it saves someone some time.
I know this is an old thread, but I thought I'd post here anyway for those that come across it via Google (like I did). I got most of the way to a solution with krillgar's approach, but I had trouble because some of my text contains newlines. Accordingly, this modification worked best for me:
private void WriteText(string text)
{
var para = doc.Content.Paragraphs.Add();
var start = para.Range.Start;
var end = para.Range.Start + text.IndexOf(":");
para.Range.Text = text;
para.Range.Font.Bold = 0;
para.Range.InsertParagraphAfter();
if(text.Contains(":")){
var rngBold = doc.Range(start, end);
rngBold.Bold = 1;
}
}
The key difference is that I calculate start and end earlier in the function. I can't quite put my finger on it, but I think if your new text has newlines in it, the later calculation of start/end messes something up.
And obviously my solution is intended for text with the format:
Label: Data
where Label is to be bolded.
Consider usage of Range.Collapse eventually with Microsoft.Office.Interop.Word.WdCollapseDirection.wdCollapseEnd as parameter.
That would allow next text to have formatting different than previous text (and next text formatting will not affect formatting of previous one).
well, the title pretty much says it all.
here's a little info:
i have a text file, and inside that textfile contains:
Label
"this text will be associated with the Text property of the label once the label has been added to the Panel Control at runtime."
20, 45
Trebuchet MS
14.0
explanation of the above
the above file may have only one label-info, or it may have a thousand of them. here's how it works:
Control
Text Property
Locatoin
Font Name
Font Size
...Now, all is well if i leave out the font information from the file. but as soon as i modified my regex to suit for the font name and font size, my program no longer adds the control to the Panel at runtime. there are no debugging errors or ugly squigly lines either. It just doesn't show anything.
So, my guess is the last part of the regex that tries to match font information/ can somebody please help me understand/solve this problem?
the code i have is:
public partial class Form1 : Form
{
private void FillCanvas()
{
canvas.Controls.Clear();
canvas.Visible = true;
canvas.BringToFront();
txt.Visible = false;
MatchCollection lines = Regex.Matches(File.ReadAllText(Path), #"(.+?)\r\n""([^""]+)""\r\n(\d+), (\d+)\r\n""(\w*)\r\n" +
#"(\d+)");
foreach (Match match in lines)
{
string control = match.Groups[1].Value;
string text = match.Groups[2].Value;
int x = Int32.Parse(match.Groups[3].Value);
int y = Int32.Parse(match.Groups[4].Value);
string fname = match.Groups[6].Value;
float fsize = float.Parse(match.Groups[7].Value);
switch (control)
{
case "Label":
Label label = new Label();
label.Text = text;
label.AutoSize = true;
label.IsAccessible = true;
label.Font = new Font(fname, fsize);
label.MouseMove += new MouseEventHandler(label_MouseMove);
label.MouseDown += new MouseEventHandler(label_MouseDown);
label.MouseUp += new MouseEventHandler(label_MouseUp);
label.Click += new EventHandler(label_Click);
label.DoubleClick += new EventHandler(label_DoubleClick);
canvas.Controls.Add(label);
ControlCount++;
label.Name = ControlCount.ToString();
label.Location = new Point(x, y);
SelectedControl = label.Name;
break;
Your regex pattern is incorrect. Change it to this:
#"(.+?)\r\n""([^""]+)""\r\n(\d+),\s(\d+)\r\n([\w\s]*)\r\n(\d+)"
Your original pattern has 2 problems when it attempts to match the font name. First, it has unnecessary quotation marks, but there are none for the font name section. Second, the font name can have a space in it, and your pattern didn't account for it.
Your pattern:
#"(.+?)\r\n""([^""]+)""\r\n(\d+), (\d+)\r\n""(\w*)\r\n(\d+)"
^ ^
| |
1st problem ___| |
2nd problem ___|
BTW, the current pattern does not correctly capture the "14.0" font size. It will capture "14" only. If you need to capture the rest of it, consider using (\d+(?:\.\d+)?) instead if it's an optional format. If you always expect it to be in that format then use (\d+\.\d+).
EDIT: if it's within your control I suggest switching the text file / regex approach to an XML format instead. Some nice LINQ to XML will make this simpler to maintain.
Have you set a breakpoint inside the foreach and debugged? Since you are iterating over the results of a MatchCollection, the first place I'd check is to see if you have zero matches.