I have this bit of code run when people close the game to save all their currently selected pets (this is for school don't worry about how I named it "Squirtle", no copyright problems here). The code in question is:
using (StreamWriter sw = File.CreateText(#"..\..\pets.txt"))
{
sw.AutoFlush = true;
foreach (Pet p in petList)
{
sw.Write(p.PetID + ' ');
sw.Write(p.Name + ' ');
sw.Write(p.HP + ' ');
sw.Write(p.Type + ' ');
sw.Write(p.Level + ' ' );
sw.Write(p.Rarity + ' ');
sw.WriteLine(p.Speed);
}
}
the commas were spaces and I just added the autoflush to try and fix the problem, but basically no matter how many times I run it, the first two, next two, and last 3 pieces of data have no spaces between them, example: 32SQUIRTLE 77AQUATIC 41930. this happens every time I run it and am wondering if anyone knows of why it's doing this? I can use any delimiter also if space and comma are notorious with StreamWriter or something.
You are doing Int + Char, The overload for this operation would results in Int + (int) Char which is casting the space into its Unicode code point and doing arithmetic operation
What you want to do is p.PetID.ToString() + " "
Related
I'm having two problems with reading my .csv file with streamreader. What I'm trying to do is get the values, put them into variables which I'll be using later on, inputting the values into a browser via Selenium.
Here's my code (the Console.Writeline at the end is just for debugging):
string[] read;
char[] seperators = { ';' };
StreamReader sr = new StreamReader(#"C:\filename.csv", Encoding.Default, true);
string data = sr.ReadLine();
while((data = sr.ReadLine()) != null)
{
read = data.Split(seperators);
string cpr = read[0];
string ydelsesKode = read[1];
string startDato = read[3];
string stopDato = read[4];
string leverandoer = read[5];
string leverandoerAdd = read[6];
Console.WriteLine(cpr + " " + ydelsesKode + " " + startDato + " " + stopDato + " " + leverandoer + " " + leverandoerAdd);
}
The code in and of itself works just fine - but I have two problems:
The file has values in Danish, which means I get åøæ, but they're showing up as '?' in console. In notepad those characters look fine.
Blank values also show up as '?'. Is there any way I can turn them into a blank space so Selenium won't get "confused"?
Sample output:
1372 1.1 01-10-2013 01-10-2013 Bakkev?nget - dagcenter ?
Bakkev?nget should be Bakkevænget and the final '?' should be blank (or rather, a bank space).
"Fixed" it by going with tab delimited unicode .txt file instead of .csv. For some reason my version of excel doesn't have the option to save in unicode .csv...
Don't quite understand the problem of "rolling my own" parser, but maybe someday someone will take the time to explain it to me better. Still new-ish at this c# stuff...
In my case I create a CSV file using StreamWriter in c# using code below:
[System.Web.Http.HttpPost]
public ActionResult createAllSubscribtionsExcelFile()
{
int ID = Convert.ToInt32(Request.Params["ID"]);
long totalRecords;
var Members = Services.MemberService.GetAll(0, int.MaxValue, out totalRecords);
string baseURL = string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, Url.Content("~"));
string packageName = Umbraco.Content(ID).Name;
string currentPath = Server.MapPath("/") + packageName;
string returnPath = baseURL + "/" + packageName;
string orderNumber = "none"; string price = "none"; string theBillNumber = "none";
List<RootObject> packages = null;
if (!System.IO.File.Exists(currentPath))
{
System.IO.File.Create(currentPath);
}
using (StreamWriter sr = new StreamWriter(currentPath + ".csv", false, Encoding.UTF8))
{
foreach (var member in Members)
{
var NestedPackages = member.GetValue<string>("packages");
if (NestedPackages != null)
{
packages = JsonConvert.DeserializeObject<List<RootObject>>(NestedPackages);
}
if (NestedPackages != null)
{
foreach (var package in packages)
{
var udi = package.package;
var content = Umbraco.Content(udi);
orderNumber = package.orderNumber;
price = package.theAmountPaid.ToString();
theBillNumber = package.theBillNumber;
sr.WriteLine("" + "," + orderNumber.Replace(',', ' ').Replace('/', ' ') + "," + price.Replace(',', ' ').Replace('/', ' ')
+ "," + theBillNumber.Replace(',', ' ').Replace('/', ' '));
}
}
}
sr.Close();
}
return Redirect(returnPath + ".csv");
}
In my case theBillNumber = "16744817032020146676", but the value that shown in the excel sheet like that
"16744817032020100000" (the last 5 digits Equuleus zero).
How can I fix this problem, Please help.
A tiny trick!
Using c# I create a .CSV with the single line:
12/25/2021,James,'1836542348674987512345363,12
Note the single quote at the start of the really big number.
If we do not pre-pend a text character, Excel will treat the number as a super big integer with way more than 15 decimal digits. Excel will automatically convert the trailing numerals into zeros. The single quote tells Excel to leave all the numerals alone.
Once Excel opens the .CSV normally, all the numerals are present, but the cell begins with the single quote. The following VBA will open the .CSV and convert any leading single quote into a PrefixCharacter.
Then using Excel VBA:
Sub dural()
Workbooks.Open Filename:="C:\Users\garys\Desktop\x.csv"
Dim cell As Range
For Each cell In ActiveSheet.UsedRange
v = cell.Value
If Left(v, 1) = "'" Then
cell.Clear
cell.NumberFormat = "#"
cell.Value = v
End If
Next cell
End Sub
I get:
As you see by comparing the value in the Formula Bar to the value in the cell, the single quote is no longer part of the number. It is just a PrefixCharacter.
This kind of handling is useful for:
long phone numbers
USPS tracking numbers
banking account and routing numbers
etc.
I had this issue before, and I hadn't found a solution for it, I had to add an underscore before the number so it would be treated as text
As documented on the Microsoft Learn website, large numbers (lengths greater than 15 digits) are automatically converted to zeroes.
Hence as a workaround, prefix such large digits with a single quote.
Last digits are changed to zeros when you type long numbers in cells of Excel
I am currently making myself a little tool.
Essentially I have this list which goes like this:
NPWR00160_00 LittleBigPlanet
NPWR00163_00 Warhawk
NPWR00179_00 Pure
NPWR00180_00 Midnight Club: Los Angeles
NPWR00181_00 echochrome™
NPWR00187_00 WipEout® HD
This is currently typed into a richTextBox.
I am trying to do this, get the NPWRXXXXXX of the line and save it as a string, and then the Games Name and save that as another string for which I can go ahead and do what I was originially going to do with it. But for each line of the richTextBox which carries on with that formation as above.
Not too sure how to get a line from the richTextBox and save it as a string, in which I can repeat that process for every single line of the richTextBox.
For what I have tried, I gave myself an example that the string was NPWR02727_00 Skydive: Proximity Flight. What I did was this:
string game = "NPWR02727_00 Skydive: Proximity Flight";
string NPWR = game.Substring(0,13);
string gamename = game.Remove(0, 13);
richTextBox2.AppendText("NPWRID: " + NPWR + " Game: " + gamename + Environment.NewLine);
Which actually does successfully save the strings and write it in the second text box as the new form.
Only issue is I'm not sure how to convert a line from the RichTextBox and turn it into a string, and repeat the process for each line in the rich text box
EDIT
So I found out how to turn a string into a line from the richTextBox..
string line = richTextBox1.Lines[0];
So this will get the first line and save it as the string "line"
This now updates the code to
string game = richTextBox1.Lines[0];
string NPWR = game.Substring(0,13);
string gamename = game.Remove(0, 13);
richTextBox2.AppendText("NPWRID: " + NPWR + " Game: " + gamename + Environment.NewLine);
Now how do I get this code to run for every line, I understand I need something to repeat it, and something to change the 0 to count up by 1 everytime it repeats?
EDIT AGAIN
Awesome, forget the above edit, thanks a lot!
I suggest you do something similar to this:
var codes = new List<string>();
var games = new List<string>();
foreach(var s in richTextBox1.Lines)
{
string[] p = s.Split(new char[] { ' ' }, 2);
if (p.Count() == 1) { continue; }
codes.Add(p[0]);
games.Add(p[1]);
}
Basically, we are declaring two Lists of the type string, to store respectively the code and the name of the game. Then we proceed in looping through the Lines property of the RichTextBox, and for each line, we split the line by the first index(space) we find; asking for a maximum of two strings, to avoid splitting any forthcoming elements; in case the name of the game contains spaces.
For the two substrings obtained, we proceed by saving the first part into the List codes, and the second one into the List games.
For further uses(traversing codes/names) we could access the two Lists
for(int c = 0; c < codes.Count; c++)
{
MessageBox.Show(codes[c] + string.Empty + games[c]);
}
I have some vehicle information that I want to send in an email.
I have all code working but spacing out the information is a problem. Each vehicle has a checklist and that checklist then gets emailed. So I loop through the list and get the defect and the comment.
foreach (var item in chkList.CheckItems)
{
if (item.Defect == true)
{
defect += string.Format("{0,-40} {1}\n", item.ItemTitle, item.Comment);
}
}
if (hasDefect == true)
{
Utils.ChecklistSendMail("Checklist", ToAddresses.Split(';'),
"Vehicle Reg: " + reg + "\n" +
"Checklist No: " + chkList.CheckListNo + "\n"+
"Date: " + ChecklistDate.ToShortDateString() + "\n" +
"Defects: Comments: " + "\n" +
defect);
}
Email then looks like this:
Vehicle Reg: XLZ 8194
Checklist No: 0
Date: 22/03/2016
Defects: Comments:
Vehicle Secure comment1
Brakes comment2
I want the defects and the comments to be displayed like this:
Defects: Comments:
Vehicle Secure comment1
Brakes comment2
Since Vehicle Secure is longer than Brakes the comment is being pushed further out. But is there a way to fix the string at a certain position no matter how long first word is?
EDIT
code now looks like this:
string defect = "";
string comment = "";
string aheading = "Defects:";
string bheading = "Comments:";
foreach (var item in chkList.CheckItems)
{
if (item.Defect == true)
{
defect += item.ItemTitle;
comment += item.Comment;
}
}
string result = aheading.PadRight(20, ' ') + bheading.PadRight(20, ' ') + Environment.NewLine +
defect.PadRight(20, ' ') + comment.PadRight(20, ' ') + Environment.NewLine;
But the output looks like this:
Defects: Comments:
Vehicle SecureBrakestest1test2
If you really want to do this with spaces, you need to determine the label with the most characters and how much space you want after that. This creates a total number of characters. From this, you subtract the number of characters of the label to get the number of spaces necessary to line up the value.
However, you could just use a <table> or some other html.
A potential, quick and dirty solution would require you to generate the html as a part of your code. I seriously advise against some homegrown html generator logic. Invariably the data involved in the email becomes more complex. This leads to mixing code that is getting the data for the template and building the html, which is painful to debug. Also there are plenty of html templating solutions out there. You'd really be just reinventing the wheel to take on technical debt and the maintenance of more code.
A better solution would be use something like MvcMailer and build an html template. You then pass the template and a context object to the engine to render the resultant html.
Try and use String padding with ' ' as char
public string PadRight(
int totalWidth,
char paddingChar)
This method would complete the length of the string with the chosen char. by specifying the max length of the string and replacing the remaining length with " " (space). you can always have the strings aligned.
Read more about PadRight or PadLeft
string Defects ="Example"
Defects.PadRight(20," ");
Result: "Example "
Edit : Example Code .Please have a look at this code and check what you are doing wrong
string aheading = "Defects:";
string bheading ="Comments:";
string b = "Vehicle Secure";
string bComment = "My Comment value";
string c = "Brakes";
string cComment = "My Comment value";
string result= aheading.Trim().PadRight(20,' ')+bheading.Trim().PadRight(20,' ')+ Environment.NewLine +
b.Trim().PadRight(20, ' ') + bComment.Trim().PadRight(20, ' ') + Environment.NewLine +
c.Trim().PadRight(20,' ')+cComment.Trim().PadRight(20,' ')+Environment.NewLine ;
Console.WriteLine(result);
Edit:Answer based on the code you Posted
string aheading = "Defects:";
string bheading = "Comments:";
string result = aheading.PadRight(20, ' ') + bheading.PadRight(20, ' ') + Environment.NewLine ;
foreach (var item in chkList.CheckItems)
{
if (item.Defect == true)
{
string result += item.ItemTitle.Trim().PadRight(20,' ') + item.ItemTitle.Trim().PadRight(20,' ') + Environment.NewLine ;
}
}
Console.WriteLine(result);
I'm exporting an Excel.Worksheet in C# like this:
myWorksheet.SaveAs(myPath, Excel.XlFileFormat.xlCSV);
it works almost ok, but I need to force two things:
The "field separator" should be semicolon (;). I'm getting a comma (,)
The "text separator" should always be null. I'm getting double quotes ("")
The documentation is totally unhelpful (what the hell is "xlTextWindows: Specifies a type of text format." supposed to mean?)
Any idea?
The VBA (not C#) solution to replace the commas with semicolons is:
Sub CreateCSV()
Dim rCell As Range
Dim rRow As Range
Dim sOutput As String
Dim sFname As String, lFnum As Long
'Open a text file to write
sFname = "C:\MyCsv.csv"
lFnum = FreeFile
Open sFname For Output As lFnum
'Loop through the rows'
For Each rRow In ActiveSheet.UsedRange.Rows
'Loop through the cells in the rows'
For Each rCell In rRow.Cells
sOutput = sOutput & rCell.Value & ";"
Next rCell
'remove the last comma'
sOutput = Left(sOutput, Len(sOutput) - 1)
'write to the file and reinitialize the variables'
Print #lFnum, sOutput
sOutput = ""
Next rRow
'Close the file'
Close lFnum
End Sub
source tested and works. Now, I'm not sure what text separator you're speaking about being "" but I haven't run into that. If you go the VBA way, let me know if that's still happening and we will alter the code. If this VBA solution is completely useless to you, I apologize!
Thanks guys, but I was looking for something a little less clumsy.
Anyway, since I was just a step away from closing the project, I put together an inelegant but working solution like this:
static public void WorksheetToCSV(Excel.Worksheet origine, string CSVoutPath, string fieldSeparator, string textSeparator)
{
Excel.Range rngCurrentRow;
string lineaDaScrivere;
TextWriter csv = new StreamWriter(CSVoutPath);
for (int i = 1; i <= origine.UsedRange.Rows.Count; i++)
{
rngCurrentRow = origine.UsedRange.get_Range("A" + i, "A" + i).EntireRow;
lineaDaScrivere="";
foreach (Excel.Range cella in rngCurrentRow.Columns)
{
try
{
lineaDaScrivere = lineaDaScrivere + textSeparator + cella.Value.ToString() + textSeparator + fieldSeparator;
}
catch (NullReferenceException ex)
{
break;
}
}
lineaDaScrivere=lineaDaScrivere.Substring(0, (lineaDaScrivere.Length - fieldSeparator.Length));
csv.WriteLine(lineaDaScrivere);
}
csv.Close();
}
There are better solution, but this worked as expected for me.