So I have a C# program that collects a list of customers. The list displays Customer ID, Customer Name, and Customer Phone Number. The list is shown in a multi-line text box. My issue is, a customer is allowed to either use first and last name, or first middle and last name, and when the list is displayed, if one of the customers only put a first and last name, the phone number is literally right next to the name instead of tabbed like the others. I will demonstrate what I mean below.
Notice how Bob Anthony's phone number is off compared to Mary and John? What would I use to make sure that every line has the same space in the tabs?
While some type of a data grid or list view would probably be more appropriate, if you want to keep it in string form you can use some of the composite formatting features in String.Format - notably the alignment flag:
string.Format("{0,-8} {1,-20} {2}", stuff)
The negative/positive indicates left/right alignment. Note that strings aren't truncated for you, you'll have to do that if you don't already know the max width.
You should get length of the longest item and add space after other items so that all of them be equal. By the way, I suggest you to use DataGridView for your application. Something like this:
dataGridView1.Rows.Add(3);
dataGridView1.Rows[0].Cells[0].Value = customer.ID;
dataGridView1.Rows[0].Cells[1].Value = customer.Name;
dataGridView1.Rows[0].Cells[2].Value = customer.Phone;
As everyone has said a DataGridView is recomendable and easy to use, instead of truncating the information or padding it the user can resize the columns. If you still want to do it that way then you have to get each customer and format it accordingly:
var text = new StringBuilder();
foreach (var customer in Customers)
{
var format = String.Format("{0} {1} {2}\n",
FormatField(customer.Id,6),
FormatField(customer.Name,20),
FormatField(customer.Phone,10) // Might need extra formating
);
text.Append(format);
}
And to format it:
private string FormatField(object field, int size)
{
var value = field.ToString();
if (value.Length == size)
return value;
return value.Length > size
? value.Substring(0,size)
: value.PadRight(size, ' ');
}
Depending on where you display it you will see some inconsistencies, like its not the same "view width" the characters "iii" and "MMM" even that they have the same length.
Related
I have a richtextbox named rtbDisclaimer. It's set to limit user input to 500 characters. I have been trying to figure out a way to take whatever the user types into the rtb, and break it into an array of strings with each string element limited to a certain character length, such as 100 for example, however if the 100th character is in the middle of a word I don't want it to include that word, but rather to put it in the next element so that words are not cut in half. Basically, if a user types in 500 characters, the whole thing would be broken into 5 or 6 string array elements with each element limited to 100 characters maximum without cutting any words in half. I've searched around and haven't been able to find anything that would work, and can't quite figure out how to tackle this problem. Also, the user input can be any length up to 500, so this would need to be flexible to allow for a input ranging anywhere from 0 - 500 characters.
Ex:
Not this:
[0]This is the user input typed into the ri
[1]chtextbox as it would appear in the ar
[2]ray elements
~~~~~~~~~~~~~~~~~~~~~~~~
This:
[0]This is the user input typed into the
[1]richtextbox as it would appear in the
[2]array elements
Something like this maybe?
var longText = "this morning, bla blabla";
var words = longText.split(' '); // split on space
var sentences = new List<string>();
var currentSentence = string.Empty();
foreach(var word in words){
if((sentence.Length + word.Length + 1) < 100){
currentSentence += word + " ";
}
else{
sentences.Add(currentSentence);
currentSentence = word;
}
}
I am building a report using StringBuilder and the details of it to be properly intended and aligned
for which i will be using
private static int paperWidth = 55; //it defines the size of paper
private static readonly string singleLine = string.Empty.PadLeft(paperWidth, '-');
StringBuilder reportLayout;
reportLayout.AppendLine("\t" + "Store Name");
I want Store Name in center and many such more feilds by use of \t
Thanks in Advance.
EDIT
I want to print like. Store Name in center
If you're simulating what tabs look like at a terminal you should
stick with 8 spaces per tab. A Tab character shifts over to the next
tab stop. By default, there is one every 8 spaces. But in most shells
you can easily edit it to be whatever number of spaces you want
You can realize this through the following Code:
string tab = "\t";
string space = new string(' ', 8);
StringBuilder str = new StringBuilder();
str.AppendLine(tab + "A");
str.AppendLine(space + "B");
string outPut = str.ToString(); // will give two lines of equal length
int lengthOfOP = outPut.Length; //will give you 15
From the above example we can say that in .Net the length of \t is
calculated as 1
A Tab is a Tab and its meaning is created by the application that renders it.
Think of a word processor where a Tab means:
Go to the next tab stop.
You can define the tab stops!
To center output do not use Tabs, use the correct StringFormat :
StringFormat fmt = new StringFormat()
{ Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
This centers the text inside a rectanlge in both directions:
e.Graphics.DrawString(someText, someFont, someBrush, layoutRectangle, fmt);
or something like it..
But it looks as if you want to embed the centering inside a text.
This will only work if you really know everything about the output process, i.e. the device, the Font and Size as well as the margins etc..
So it will probably not be reliable at all, no matter what you do.
The best alternative may be to either give up on plain text or use a fixed number of spaces to 'mean' 'centered' and then watch for this number when you render.
If you don't have control over the rendering, it will not work.
Ok I have an autocomplete/string matching problem to solve. I have an expression string typed in by a user into a text box, e.g.
More detail:
Expression textbox has string
"Buy some Al"
and client has a list of suggestions given by a server after a fuzzy match which populate a listbox
All Bran, Almonds, Alphabetti Spaghetti
now on the GUI I have a nice intellisense style autocomplete, but I need to wire up the "TAB" action to perform the complete. So if the user presses TAB and "All Bran" was the top suggestion, the string becomes
"Buy some All Bran"
e.g. the string "Al" was substituted for the top match "All Bran"
It's more than a simple string split on the expression to match the suggestions, as the expression text could be this
"Buy some All Bran and Al"
with suggestions
Alphabetti Spaghetti
In which case I'd expect the final Al to be substituted with the top match so the result becomes
"Buy some All Bran and Alphabetti Spaghetti"
I'm wondering how to do this simply in C# (Just the C# string manipulation, not GUI code) without going back to the server and asking for a substitution to be made.
You could do this with regex, but it doesn't seem necessary. The following solution assumes that the suggestion will always be preceded by a space (or start at the beginning of the sentence). If that's not the case then you'll need to share more examples to get the rules down.
string sentence = "Buy some Al";
string selection = "All Bran";
Console.WriteLine(AutoComplete(sentence, selection));
sentence = "Al";
Console.WriteLine(AutoComplete(sentence, selection));
sentence = "Buy some All Bran and Al";
selection = "Alphabetti Spaghetti";
Console.WriteLine(AutoComplete(sentence, selection));
Here is the AutoComplete method:
public string AutoComplete(string sentence, string selection)
{
if (String.IsNullOrWhiteSpace(sentence))
{
throw new ArgumentException("sentence");
}
if (String.IsNullOrWhiteSpace(selection))
{
// alternately, we could return the original sentence
throw new ArgumentException("selection");
}
// TrimEnd might not be needed depending on how your UI / suggestion works
// but in case the user can add a space at the end, and still have suggestions listed
// you would want to get the last index of a space prior to any trailing spaces
int index = sentence.TrimEnd().LastIndexOf(' ');
if (index == -1)
{
return selection;
}
return sentence.Substring(0, index + 1) + selection;
}
Use string.Join(" and ", suggestions) to create your replacement string and then string.Replace() to do substitution.
You can add the listbox items in the array and while traversing through array, once a match is found, break the loop and get out of it and display the output.
Does there is any library or algorithm that can do auto detection of tags in a text (ignoring the usual words of the chosen language)?
Something like this:
string[] keywords = GetKeyword("Your order is num #0123456789")
and keywords[] would contain "order" and "#0123456789" ...?
Does it exist? Or the user will select by himself all the tags of every document all the time? :?
foreach(string keyword in keywords) { // where keywords is a List<string>
if ("Your order is num #0123456789".Contains(keyword)) {
keywordsPresent.Add(keyword); // where keywordsPresent is a List<string>
}
}
return keywordsPresent;
What the above does is not cater for your #0123456789, for that add some more logic to find the index of the # or something...
Sorry, I misunderstood the question. If you want to look for specific words, the algorithm will depend on you strings. For example, you can use string.Split() to generate an array of words from one string, and then work with that, like this:
string[] words = string.Split("Your order is num #0123456789");
string orderNumber = "";
if(words.Contains("order") && w.StartsWith("#").Count > 0)
{
orderNumber = words.Where(w=>w.StartsWith("#").FirstOrDefault();
}
This will first generate an array of words from "Your order is num #0123456789" , then if it contains the word "order" it will wind a word that starts with "#" and select that;
I think that a lot of different algorithms can be used. Some of them are simple another are super complex. I can suggest you the next basic way:
Split all text into array of words.
Remove stop words from the array. (Goole "stop words list" to get full list of stop words.)
Walk through the array and calculate count of each word.
Sort words in accordance with their 'weight' in the array.
Choose necessary amount of tags.
I have strings with space seperated values and I would like to pick up from a certain index to another and save it in a variable. The strings are as follows:
John Doe Villa Grazia 323334I
I managed to store the id card (3rd column) by using:
if (line.length > 39)
{
idCard = line.Substring(39, 46);
}
However, if I store the name and address (1st and 2nd columns) with Substring there will be empty spaces since they are not of the same length (unlike the id cards). How can I store these 2 values and removing the unneccasry spaces BUT allowing the spaces between name and surname?
Try this:
string line = " John Doe Villa Grazia 323334I";
string name = line.Substring(02, 16).Trim();
string address = line.Substring(18, 23).Trim();
string id = line.Substring(41, 07).Trim();
var values = line.Split(' ');
string name = values[0] + " " + values[1];
string idCard = values[4];
It will be impossible to do without database lookups on names if there aren't spaces for sure in the previous columns.
Are these actually space separated or are they really fix width columns?
By that I mean do the "columns" start at the same index into the string in each case - from the way you're describing the data is sounds like the later i.e. the ID column is always column 39 for 7 characters.
In which case you need to a) pull the columns using the appropriate substring calls as you're already doing and then, use "string ".Trim() to cut off the spaces.
If the rows, are, as it seems fixed with then you don't want to use Split at all.
How can you even get the ID like that, when everything in front of it is of variable length? If that was used for my name, "David Hedlund 323334I", the ID would start at pos 14, not 39.
Try this more dynamic approach:
var name = str.Substring(0, str.LastIndexOf(" "));
var id = str.Substring(str.LastIndexOf(" ")+1);
Looks like your parsing strategy will cause you a lot of trouble. You shouldn't count on the string's size in order to parse it.
Why not save the data in CSV format (John Doe, Villa Grazia, 323334I)?
that way, you can assume that each "column" will be separated by a comma which will make your parsing efforts easier.
Possible "DOH!" question but are you sure they are spaces and not Tabs? Looks like it "could" be a tab seperated file?
Also for browie points you should use String.Empty instead of ' ' for comparisons, its more localisation and memory friendly apparently.
The first approach would be - as already mentioned - a CSV-like structure with a defined token as the field separator.
The second one would be fixed field lengths so you know the first column goes from char 1 to char 20, the second column from char 21 to char 30, and so on.
There is nothing bad about this concept besides that the human readability may be poor if the columns are filled up to their maximum so no spaces remain between them.
You could write a helper function or class which knows about the field lengths and provides an index-based, fault-tolerant access to the particular column. This function would extract the particular string parts and remove the leading and trailing spaces but leave the spaces in between as they are.
If your values have fixed width, best not split it but use the right indexes in your array.
const string input = "John Doe Villa Grazia 323334I";
var name = input.Substring(0, 15).TrimEnd();
var place = input.Substring(16, 38).TrimEnd();
var cardId = input.Substring(39).TrimEnd();
Assuming your values cannot contain two sequential spaces in them we can maybe use " " (double space" as a separator?
The following code will split your string based on the double space
const string input = "John Doe Villa Grazia 323334I";
var entries = input.Split(new[]{" "}, StringSplitOptions.RemoveEmptyEntries)
.Select(s=>s.Trim()).ToArray();
string name = entries[0];
string place = entries[1];
string idCard = entries[2];