Extracting string from a longer string - c#

I'm creating an app in C# that uses EConnect to import information into Great Plains. EConnect has it own set of exceptions which are really great to know if you are passing the app the wrong information. I want to display an error message if an EConnectException is thrown. My problem is the EConnect exception is very long so I want to extract a particular part from it.
The exception string look like the following example:
Microsoft.Dynamics.GP.eConnect.eConnectException: Sql procedure error codes returned:
Error Number = 714 Stored Procedure= taPMTransactionInsert Error Description = You can not enter a 1099 value (TEN99AMNT) > than the Purchase Amount (PRCHAMNT) minus the Trade Discount Amount (TRDISAMT)Node Identifier Parameters: taPMTransactionInsert
All I really want for my error messages is the Error Description part. Its easy enough to cut out the part before Error Description because that portion is always the same length. The Error Description can vary in length so thats where I'm having trouble figuring out how to extract it. In the end what I would want it the starting at Error Description and ending before Node Identifier Parameters (which always comes after the Error Description)
Here is how I catch my exception right now and cut off the first part of the error message. setStatusErrorLogs is just a function I use to display my errors to my app.
catch (eConnectException exc)
{
setStatusErrorLogs((exc.ToString()).Substring(85), xInvoiceNumber + ": ", "CreateInvoice");
}
Any ideas how I can extract this string?

Use string.IndexOf method
var error = exc.ToString();
var startIndex = error.IndexOf("Error Description = ") + "Error Description = ".Length;
var endIndex = error.LastIndexOf("Node Identifier Parameters:");
var desc = error.Substring(startIndex, endIndex - startIndex);
setStatusErrorLogs(desc, xInvoiceNumber + ": ", "CreateInvoice");
This approach is very error prone! If you are not sure about the exact format and content of the excetpion then you should do checks not to get junk data!

Use string.IndexOf to find the index of the string "Node Identifier". then use string.SubString to get everything between the 85th character and the index returned by IndexOf.

Here's a simple Regex that captures what you want:
.*Error Description(.*)Node Identifier.*
Here's code that uses this:
string text = "Error Number = 714 Stored Procedure= taPMTransactionInsert Error Description = You can not enter a 1099 value (TEN99AMNT) > than the Purchase Amount (PRCHAMNT) minus the Trade Discount Amount (TRDISAMT)Node Identifier Parameters: taPMTransactionInsert";
var desc = Regex.Replace(text, ".*Error Description(.*)Node Identifier.*", "$1");
Console.WriteLine(desc);
This regex uses greedy matching to ensure that if the description contains the phrase "Error Description" or "Node Identifier", it'll still match as you expect.
Test out the regex here

Find the index of Node identifier with String.IndexOf()
Solution would be like this
string exception = exc.ToString();
int nodeIndex = exception.IndexOf("Node identifier");
string errorDescription = exception.Substring(85, nodeIndex);
setStatusErrorLogs(errorDescription, xInvoiceNumber + ": ", "CreateInvoice");

This can be achieved like this:
var lookUpString = "Error Description =";
var lookUpStringEnd = "Node Identifier";
var stringToLookIn ="Microsoft.Dynamics.GP.eConnect.eConnectException: Sql procedure error codes returned: Error Number = 714 Stored Procedure= taPMTransactionInsert Error Description = You can not enter a 1099 value (TEN99AMNT) > than the Purchase Amount (PRCHAMNT) minus the Trade Discount Amount (TRDISAMT)Node Identifier Parameters: taPMTransactionInsert";
var indexOfLookUpString = stringToLookIn.IndexOf(lookUpString);
var indexOfLookUpStringEnd = stringToLookIn.IndexOf(lookUpStringEnd);
var stringWithLookUpStringIncluded= stringToLookIn.Substring(indexOfLookUpString,indexOfLookUpStringEnd-indexOfLookUpString);
var stringWithoutLookUpStringIncluded = stringToLookIn.Substring(indexOfLookUpString+lookUpString.Length,indexOfLookUpStringEnd -(indexOfLookUpString+lookUpString.Length));
Console.WriteLine(stringWithLookUpStringIncluded);
// output: Error Description = You can not enter a 1099 value (TEN99AMNT) > than the Purchase Amount (PRCHAMNT) minus the Trade Discount Amount (TRDISAMT)
Console.WriteLine(stringWithoutLookUpStringIncluded);
//output: You can not enter a 1099 value (TEN99AMNT) > than the Purchase Amount (PRCHAMNT) minus the Trade Discount Amount (TRDISAMT)
Read more about String.Substring and String.IndexOf

Related

How to use substring to get the value after fifth space until sixth space

My problem is that I want to extract the first number in a string.
The format of the string is as such
string text = "Board the DT line, go 1 stops toward Test";
What I want is the value 1. This is how I tried to do it
int digit1 = int.Parse(text.Substring(text.IndexOf("go")+1, text.IndexOf("stops")-1));
The error that I got was An unhandled exception of type 'System.FormatException' occurred in mscorlib.dll
Additional information: Input string was not in a correct format.
If you are new to programming you may want to break this down into smaller tasks.
For instance you can start by hardcoding the substring values to ensure you get the correct result
var str = "Board the DT line, go 1 stops toward Test";
var number = str.Substring(22, 1);
when you know you have the correct number you can look at how to get those values programmatically.
var index = str.IndexOf("go "); //gives you 19
var index = str.IndexOf("go ") + 3 //add 3 to get the start index
then you substitute the hard coded value for the code
var number = str.Substring(str.IndexOf("go ") + 3, 1);
You could also use regex: [0-9]+. This pattern extracts all of the numbers in the string.
var matches = Regex.Matches("Board the DT line, go 1 stops toward Test", "[0-9]+");
foreach(Match match in matches)
{
int number = int.Parse(match.Value);
Console.WriteLine(number);
}

Isolating values from a listbox line

I have got a line in a lisbox that i need so i can print out my receipt for the end of my 12 grade project im doing.
Example of my line :"cha1 Adidas Stan Smith White 1 2" (its padded).
Now what i want to do is isolate like cha1, Adidas stan Smith White,1,2 to add to my Microsoft Access Database, i somehow managed to do it with substring but i screwed up my code and now i cant do it , can somebody help me please ?
My code ,that used to work , looks like this :
foreach (string item in lstpreview.Items)
{
//create the string to print on the reciept
string nomeproduto = item;
float quantidade = float.Parse(item.Substring(item.Length -5, 5));
float precounitario = float.Parse(item.Substring(item.Length - 5, 5));
string totalproduto = item.Substring(item.Length - 6, 6);
txt1.Text = Convert.ToString(quantidade);
txt2.Text = Convert.ToString(precounitario);
//MessageBox.Show(item.Substring(item.Length - 5, 5) + "PROD TOTAL: " + totalproduto);
//float totalprice = 0.00f;
}
You say that the line is padded, but do not give any details. If you know that the first field is always the first 4 characters of the line, you can isolate it with string.Substring:
string field1 = line.Substring(0, 4);
and similarly for the other fields.
P.S. Please edit your post and remove the swear word.
Edit after parsing code added
I don't understand your comment, what is "your negative value"? Run the code in the debugger and find which line causes the error. Please post the exact error message.
Is there a reason for converting the substring to a float and then back to a string? I can imagine that you might want to validate that the field is numeric, but then you would be better to use TryParse.
Your second comment is helpful. The last 5 characters of the line are not all numeric, that's the problem.
Done it with this snippet of code together with a for each loop.
string[] caracteresnastring = item.Split(new char[] { ',' }.ToArray());
string code = caracteresnastring[0];
string name = caracteresnastring[1];
string price = caracteresnastring[2];
string quantity = caracteresnastring[3];

How do I Split string only at last occurrence of special character and use both sides after split

I want to split a string only at last occurrence of special character.
I try to parse a name of a tab from browser, so my initial string looks for example like this:
Untitled - Google Chrome
That is easy to solve as there is a Split function. Here is my implementation:
var pageparts= Regex.Split(inputWindow.ToString(), " - ");
InsertWindowName(pageparts[0].ToString(), pageparts[1].ToString());//method to save string into separate columns in DB
This works, but problem occurs, when I get a page like this:
SQL injection - Wikipedia, the free encyclopedia - Mozilla Firefox
Here are two dashes, which means, that after split is done, there are 3 separate strings in array and if I would continue normally, database would contain in first column value "SQL injection" and in second column value "Wikipedia, the free encyclopedia". Last value will be completely left out.
What I want is that first column in database will have value:
SQL injection - Wikipedia, the free encyclopedia" and second column will have:
"Mozilla Firefox". Is that somehow possible?
I tried to use a Split(" - ").Last() function (even LastOrDefault() too), but then I only got a last string. I need to get both side of the original string. Just separated by last dash.
You can use String.Substring with String.LastIndexOf:
string str = "SQL injection - Wikipedia, the free encyclopedia - Mozilla Firefox";
int lastIndex = str.LastIndexOf('-');
if (lastIndex + 1 < str.Length)
{
string firstPart = str.Substring(0, lastIndex);
string secondPart = str.Substring(lastIndex + 1);
}
Create a extension method (or a simple method) to perform that operation and also add some error checking for lastIndex.
EDIT:
If you want to split on " - " (space-space) then use following to calculate lastIndex
string str = "FirstPart - Mozzila Firefox-somethingWithoutSpace";
string delimiter = " - ";
int lastIndex = str.LastIndexOf(delimiter);
if (lastIndex + delimiter.Length < str.Length)
{
string firstPart = str.Substring(0, lastIndex);
string secondPart = str.Substring(lastIndex + delimiter.Length);
}
So for string like:
"FirstPart - Mozzila Firefox-somethingWithoutSpace"
Output would be:
FirstPart
Mozzila Firefox-somethingWithoutSpace
Please forgive me for my laziness ins this solution i'm sure there is a better approach but i will give you one solution proposal i'm assuming you are codding in C#.
First of all correct me if I get wrongly the question no matter what you just want to columns returned the first (all text even of it includes dashes but the last one) and last column (all the text after last dash) if it's ok. let's do it.
// I Only use split function when I want all data in separate variable (array position) in you case I assumed that you just want 2 values (if possible), so you can use substring.
static void Main(string[] args)
{
string firstname = "";
string lastName = "";
string variablewithdata = "SQL injection - Wikipedia, -the free encyclopedia - Mozilla Firefox";
// variablewithdata.LastIndexOf('-') = returns Integer corresponding to the last position of that character.
//I suggest you validate if variablewithdata.LastIndexOf('-') is equal to -1 or not because if it don't found your character it returns -1 so if the value isn't -1 you can substring
firstname = variablewithdata.Substring(0, (variablewithdata.LastIndexOf('-') - 1));
lastName = variablewithdata.Substring(variablewithdata.LastIndexOf('-') + 1);
Console.WriteLine("FirstColumn: {0} \nLastColumn:{1}",firstname,lastName);
Console.ReadLine();
}
If it's not what you want can you explain me for example for "SQL injection - Wikipedia,- the free - encyclopedia - Mozilla Firefox" what's suppose to be returned?
Forgive me for unclean code i'm bored today.
If you don't care about reassembling strings, you could use something like :
var pageparts= Regex.Split(inputWindow.ToString(), " - ");
var firstPart = string.Join(" - ", pageparts.Take(pageparts.Length - 1));
var secondPart = pageparts.Last()
InsertWindowName(firstPart, secondPart);

Get data from file and split into an array

I have information formatted on a webpage which looks like the following:
Key=submission_id, Value=300348811884547965
Key=formID, Value=50514289063151
Key=ip, Value=xxxxx
Key=editimage, Value=Yes
Key=openimage5, Value=Yes
Key=copyimage, Value=Yes
How would I go about getting the value of each line, I was thinking of doing some sort of next() while getting all data after the 2nd equal sign of each line however I am unsure on how to do it in c#. I am sure there is a better solution then what I have in mind. Please let me know your thoughts.
A regex works nicely for parsing data structured in this way.
Regex splitter = new Regex(#"Key=([\w]+), Value=([\w]+)");
string path = "TextFile1.txt";
string[] lines = System.IO.File.ReadAllLines(path);
lines.ToList().ForEach((s) =>
{
Match match = splitter.Match(s);
if (match.Success)
{
Console.WriteLine("The Key is " + match.Groups[1] + " and the value is " + match.Groups[2]);
}
});

C#: How to extract values from a predefined format of string efficiently?

I have collection of similar strings
for example :
string 1: Customer's first Name is john, his last name is glueck,his company name is abc def technolgies llc, he has a balance of 60 dollars.His spending rate is +3.45%
string 2: Customer's first Name is steve, his last name is johnston,his company name is xyz corporation, he has a balance of 800 dollars.His spending rate is -212.86%
Now I have to extract the values like john,glueck,abc def technolgies llc,60,+3.45 from the string 1 and steve,johnston,xyz corporation,800,-212.86 from the string 2.
In our production environment each string is quite large and I have around 83 fields to extract from each string. What is the best way to extract these values?
Is there any method that does opposite of string.format, which takes the reference string & the actual string and returns back the extracted values?
A regular expressions will do the trick.
namespace ConsoleApplication
{
using System;
using System.Text.RegularExpressions;
internal static class Program
{
private static void Main()
{
var expression = new Regex(
#"Customer's first Name is (?<FirstName>[^,]+), " +
#"his last name is (?<LastName>[^,]+), " +
#"his company name is (?<CompanyName>[^,]+), " +
#"he has a balance of (?<Balance>[0-9]+) dollars\. " +
#"His spending rate is (?<SpendingRate>[^%]+)%");
var line = #"Customer's first Name is john, his last name is glueck, his company name is abc def technolgies llc, he has a balance of 60 dollars. His spending rate is +3.45%";
var match = expression.Match(line);
Console.WriteLine("First name......{0}", match.Groups["FirstName"]);
Console.WriteLine("Last name.......{0}", match.Groups["LastName"]);
Console.WriteLine("Balance.........{0}", match.Groups["Balance"]);
Console.WriteLine("Spending rate...{0}", match.Groups["SpendingRate"]);
Console.ReadLine();
}
}
}
OUTPUT
First name......john
Last name.......glueck
Balance.........60
Spending rate...+3.45
After that you can perform some simple string parsing to get numeric values from the strings. Further you will probably have to write a more robust regular expression if there are some variations in the format of the inputs.
(question: You actual input string is the full wordy text: "Customer's first Name is xxxx, his last name is xxxx, his company name is xxxx" etc. Correct?)
The is probably a good case for a Regex. If you use the compile option, you should get a reasonalbe speed out of it. The is essencially the "reverse string.format" you asked about (with a whole bunch more options).
UPDATE:
// NOTE: pattern assumes a comma after spending rate
Regex regex = new Regex("Customer's first Name is (\w+), his last name is (\w+),his company name is ([\w\s]+), he has a balance of (\d+) dollars.His spending rate is ([^,]+)");
string[] values = regex.Split(string1);

Categories