Write Specific SubItems to .txt while looping through ListView Control? - c#

My below code first writes an exclamation point (!) delimited Header to a .txt file and then loops through each item and subItem in a ListView Control, placing each record value onto a new line in my .txt file. All the values are needed for user review while in the ListBox, but when writing to the file, I need to only write the fields that are used in the next step, using the .txt file as datasource for MS Word MailMerge document.
Instead of looping through and appending every record field value to my StringBuilder, I need a way to get only the values where the ListView Column Header is the following:
memno
name
address1
address2
address3
sal
fuldate
sys
private void btnMerge_Click(object sender, EventArgs e)
{
try
{
string docLoc = "";
string docSource = "";
StringBuilder sb;
// Change this to the DataSource FilePath
StreamWriter sw = new StreamWriter("C:\\Users\\NAME\\Desktop\\Test2.txt");
string fileHeaderTxt = "memno!name!address1!address2!city!state!zip!old_addr1!old_addr2!old_city!old_state!old_zip!sys!fuldate!sex!lname!sal!address3";
sb = new StringBuilder();
sb.Append(fileHeaderTxt);
sw.WriteLine(sb.ToString());
sb.Clear();
if (lvData.Items.Count > 0)
{
foreach (ListViewItem lvI in lvData.Items)
{
sb = new StringBuilder();
foreach (ListViewItem.ListViewSubItem lvSI in lvI.SubItems)
{
sb.Append(string.Format("{0}!", lvSI.Text));
}
sw.WriteLine(sb.ToString());
}
sw.WriteLine();
}
//sb.Clear();
sw.Close();
MessageBox.Show("Complete");
if (rbPrint.Checked)
{
Print(docLoc, docSource);
}
if (rbCommit.Checked)
{
Commit_NetFYI();
}
}
catch (Exception ex)
{
MessageBox.Show("Source:\t" + ex.Source + "\nMessage: \t" + ex.Message + "\nData:\t" + ex.Data);
}
finally
{
//
}
}
I've been hammering away at this for last couple hours and just can't seem to get it. Anyone have some ideas?
EDIT:
I modified my code using Grammarian's solution, but it seems I am missing something. Each loop iteration writes a line containing all previous looped values, plus the new value.
Rough Example:
Header1!Header2!Header3!Header4
1!2!3!4
1!2!3!4!5!6!7!8
1!2!3!4!5!6!7!8!9!10!11!12
1!2!3!4!5!6!7!8!9!10!11!12!13!14!15!16
etc.
Here is my current code:
private void btnMerge_Click(object sender, EventArgs e)
{
try
{
string docLoc = "";
string docSource = "";
StringBuilder sb;
// Change this to the DataSource FilePath
StreamWriter sw = new StreamWriter("C:\\Users\\NAME\\Desktop\\Test2.txt");
string fileHeaderTxt = "memno!name!address1!address2!city!state!zip!old_addr1!old_addr2!old_city!old_state!old_zip!sys!fuldate!sex!lname!sal!address3";
sb = new StringBuilder();
sb.Append(fileHeaderTxt);
sw.WriteLine(sb.ToString());
sb.Clear();
if (lvData.Items.Count > 0)
{
foreach (ListViewItem lvI in lvData.Items)
{
var indices = new int[] { 0, 1, 2, 3, 12, 13, 16, 17 };
foreach (int i in indices)
{
sb.Append(string.Format("{0}!", lvI.SubItems[i].Text));
}
sw.WriteLine(sb.ToString());
sb.Clear();
}
sw.WriteLine();
}
}
}
EDIT2:
Got it, wasn't clearing out my stringBuilder object after each time through my first loop. Edited code above to reflect working code.

Rather than always just iterating all subitems, make an array of subitem indices in the order you want, and iterate the indices.
var indices = new [] { 0, 1, 2, 4, 9 }; // whatever you want
foreach (int i in indices)
{
sb.Append(string.Format("{0}!", lvI.SubItems[i].Text));
}

Related

Listarray overflow

I have a problem reading data from a CSV file. As in the following example I try to read in the list information from two different columns. With the query "EndOfStream" or with a count variable larger than about 6000 I get the error: "The index was out of range". However, with a count variable of 4000, the code works exactly as it should. I do not understand my mistake.
List<string> gpsGGA = new List<string>();
List<string> gpsRMC = new List<string>();
public Form1()
{
InitializeComponent();
}
private void btn_file_Click(object sender, EventArgs e)
{
string path;
OpenFileDialog file = new OpenFileDialog();
if (file.ShowDialog() == DialogResult.OK)
{
try {
path = file.FileName;
StreamReader data = new StreamReader(path);
data.ReadLine(); //Header verwerfen
gpsGGA.Clear();
gpsRMC.Clear();
for(int i=0; i<8000; i++)//while (!data.EndOfStream)
{
string[] substring = data.ReadLine().Split(';');
gpsGGA.Add(substring[11]);
gpsRMC.Add(substring[12]);
}
data.Close();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
Not sure why this is commented out:
for(int i=0; i<8000; i++)//while (!data.EndOfStream)
The while loop that is commented out intended to only read data while exists.
I added a using statement to ensure the file gets closed. I added an IsNullOrEmpty check in case there's a blank line at the end of the file, so you don't get an error with that.
using (StreamReader data = new StreamReader(path))
{
data.ReadLine(); //Header verwerfen
gpsGGA.Clear();
gpsRMC.Clear();
int counter = 0;
while (!data.EndOfStream)
{
string line = data.ReadLine();
if (! String.IsNullOrEmpty(line))
{
string[] substring = line.Split(';');
if ( substring.Length < 13 )
throw new ApplicationException("Malformated Data At Line " + counter.ToString());
gpsGGA.Add(substring[11]);
gpsRMC.Add(substring[12]);
}
counter += 1;
}
}
Your codes makes it hard to guess wheter the error is coming from reading the file or the file content itself.
You can use File.ReadAllLines which takes the file path and returns its lines as an array, regardless of the number of lines that you specify in the foor loop, which by the way can cause errors if the number of lines is is not equal to 8000.
if (file.ShowDialog() == DialogResult.OK)
{
try
{
gpsGGA.Clear();
gpsRMC.Clear();
string[] lines= File.ReadAllLines(file.FileName);
foreach(String line in lines)
{
string[] substring = line.Split(';');
gpsGGA.Add(substring[11]);
gpsRMC.Add(substring[12]);
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The index was out of range is probably caused by some lines which have invalid data
For example this is line 6000 : sdd;dfdf;dfdf;00;dfdf;555
When you try to get element at index 11 or 12, it doesn't exist because this line has only 6 elements

In c#, how to show specific searched paragraph numbers and docx file name in listview without repeating same file name?

I am creating an application in which user search word in docx file and get paragraph number which is contained that word. Almost my application work fine but the problem which I was facing is that I get repeating file name and get each paragraph in new listview row. Lets see the image for more understanding.
Image.
I just want searched file names and all paragraphs in one row of listview by separate with ','comma. Lets see the desire image.
See Below code which I try
private void button2_Click(object sender, EventArgs e)
{
this.listView1.Items.Clear();
try
{
foreach (var filePath in Search(this.textBox1.Text, this.textBox2.Text, this.checkBox1.Checked, this.checkBox2.Checked, this.radioButton2.Checked))
{
var file = new FileInfo(filePath);
this.listView1.Items.Add(new ListViewItem(new string[] { file.Name, string.Format("{0:0.0}", file.Length / 1024d), file.FullName, toDisplay }));
}
}
catch (Exception ex)
{
MessageBox.Show(this, string.Format("Exception details:\n{0}", ex), string.Format("Exception '{0}' occurred.", ex.GetType()), MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private static IEnumerable<string> Search(string directory, string searchString, bool searchSubdirectories, bool caseSensitive, bool useRegex)
{
/*
* Below is the list where we insert all paragraph of docx file.
*/
var paragph = new List<string>();
/*
* Below I am using foreach loop by using this I get all docx files from a selected directory.
*/
foreach (var filePath in Directory.GetFiles(directory, "*.docx", searchSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
{
string docxText;
int counter = 0;
using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
docxText = new DocxToStringConverter(stream).Convert();
string[] lines = docxText.Split(new string[] { Environment.NewLine },StringSplitOptions.RemoveEmptyEntries);
foreach (string line in lines)
{
if (line.IndexOf(searchString, StringComparison.OrdinalIgnoreCase) >= 0)
{
//MessageBox.Show((counter + 1).ToString() + ": " + line);
paragph.Add((counter + 1).ToString());
arrparagh = paragph.ToArray();
toDisplay = string.Join(",", arrparagh);
//MessageBox.Show(toDisplay);
yield return filePath;
}
counter++;
}
}
}
I believe you need to move your yield return out of the inner foreach loop. Like:
paragph.Clear();
foreach (string line in lines)
{
if (line.IndexOf(searchString, StringComparison.OrdinalIgnoreCase) >= 0)
{
//MessageBox.Show((counter + 1).ToString() + ": " + line);
paragph.Add((counter + 1).ToString());
arrparagh = paragph.ToArray();
toDisplay = string.Join(",", arrparagh);
//MessageBox.Show(toDisplay);
}
counter++;
}
yield return filePath;
With your yield return where it is now, it returns out of the function and gets displayed after every line that matches. Moving the yield return out of that inner loop should make it return only after each file has been fully searched.

Ordering a comboBox by the int value

having a lot of problems ordering my combobox by value any help is greatly appreacitated
private void Form1_Load(object sender, EventArgs e)
{
//text to hold the conbo box, text is grabed from the AS2W14data.csv file from c:\temp\...
String variable;
variable = "";
//filll in the combo box , create a reader
System.IO.StreamReader sr = System.IO.File.OpenText(#"c:\temp\AS2W14data.csv");
//use a while loop to read the entire file line by line, using the current line to populate the comboBox
while (!sr.EndOfStream)
{
variable = sr.ReadLine();
string[] currentLineIndex = variable.Split(',');
//customer ID is indexed at the string array postion 1
//Customer name is indexed at the string array position 0
cboCustomer.Items.Add(currentLineIndex[1].Trim() + " " + currentLineIndex[0].Trim());
}
//close the file to prevent errors...
sr.Close();
}
this is my code so far and i cant seem to find a way to order it.. help
I would suggest ordering them before adding them to the combo. Also here's a little shortcut for reading a text file. First, you want to read lines by streaming them (ReadLines() returns IEnumerable<string>) into a projection (Select()) where you create an anonymous object with two properties - Id and Name. At the end, you order a collection of these anonymous objects by the Id.
var lines = File.ReadLines(#"c:\temp\AS2W14data.csv")
.Select(l => new
{
Id = int.Parse(l.Split(',')[1].Trim()),
Name = l.Split(',')[0].Trim()
}).OrderBy(i => i.Id);
foreach (var l in lines)
cboCustomer.Items.Add(l.Id + " " + l.Name);
try this code hope it will work alternatively you can use Sorted Property of ComboBox
private void Form1_Load(object sender, EventArgs e)
{
//text to hold the conbo box, text is grabed from the AS2W14data.csv file from c:\temp\...
String variable;
variable = "";
ArrayList Indexs = new ArrayList();
//filll in the combo box , create a reader
System.IO.StreamReader sr = System.IO.File.OpenText(#"c:\temp\AS2W14data.csv");
//use a while loop to read the entire file line by line, using the current line to populate the comboBox
while (!sr.EndOfStream)
{
variable = sr.ReadLine();
string[] currentLineIndex = variable.Split(',');
//customer ID is indexed at the string array postion 1
//Customer name is indexed at the string array position 0
Indexs.Add(new AddIndexValues(currentLineIndex[1].Trim() + " " + currentLineIndex[0].Trim());
}
//close the file to prevent errors...
cboCustomer.DataSource = DataBaseBuilds.Indexs;
sr.Close();
}
public class AddIndexValues
{
private int i_index;
public AddIndexValues(int Index)
{
i_index = Index;
}
public int Index
{
get { return i_index; }
}
}

File contents filtering

I'm trying to develop an application which will take the data from a datagrid and based on a drop down menu choice return a csv file with only the selected client . My code is shown below , This links to a previous question I posted howeever I am still getting no values back and I really need to sort this out so I'm wondering if anyone can either see were i'm going wrong or else provide alternatives
//Master inventory export
private void ExportClass_Click(object sender, EventArgs e)
{
StringBuilder str = new StringBuilder();
objSqlCommands2 = new SqlCommands("MasterInventory", "ClientName");
string strString = str.ToString();
string Filepath = txtSaveShareClass.Text.ToString();
str.Append("ISIN ,FundName,Status,Share CCY,Benchmark,NAV Freq,CLASSCODE,SIMULATION,HEDGED,FUNDCCY");
StringManipulation sm = new StringManipulation();
foreach (DataRow dr in this.CalcDataSet.MasterInventory)
{
foreach (object field in dr.ItemArray)
{
str.Append(field.ToString() + ",");
}
str.Replace(",", "\n", str.Length - 1, 1);
}
try
{
System.IO.File.WriteAllText(Filepath, str.ToString());
}
catch (Exception ex)
{
MessageBox.Show("Write Error :" + ex.Message);
}
List<string[]> lsClientList = objStringManipulation.parseCSV(Filepath,cmbClientList .Text.ToCharArray());
foreach (string[] laClient in lsClientList)
{
sm.parseCSV2(Filepath, cmbClientList.Text.ToCharArray());
List<string[]> newFoo = lsClientList.Where(x => x.Contains(cmbClientList.Text)).ToList();
List<string[]> Results = sm.parseCSV2(Filepath, cmbClientList.Text.ToCharArray()).Where(x => x.Contains(cmbClientList.Text)).ToList();
//Refreshs the Client table on display from the
System.IO.File.WriteAllText(Filepath, Results.ToString());
}
this.TableAdapter.Fill(this.CalcDataSet.MasterInventory);
dataGridView2.Update();
}
If all of your variables are filling properly and your Results list contains the data that you expect, then the problem is with your WriteAllText call. You have:
System.IO.File.WriteAllText(Filepath, Results.ToString());
That is not going to produce the output that you seem to expect. It will likely just give you the class name.
Results is a List<string[]>. If you want to output that as a CSV, then you have to enumerate it:
using (var outfile = new StreamWriter(Filepath))
{
foreach (var line in Results)
{
StringBuilder sb = new StringBuilder();
foreach (var field in line)
{
sb.Append(field + ",");
}
sb.Length = sb.Length -1;
outfile.WriteLine(sb.ToString());
}
}

Logical error in writing data in a text file in one column

My Usecase is to read data from a textfile by browsing to the location of the file containing the data to be quoted.the data from the file is save in a list. i use arraylist to get the data and loop through the arraylist and concatenate each string then create output file to store the data in single column as demostrated below
Example of a string:
20050000
40223120
40006523
sample out put:
'20050000',
'40223120',
'40006523'
But my code is currently displaying the output in the format:
'20050000'20050000,
'40223120'20050000,
'40006523'40006523
Pls help.
public List<string> list()
{
List<string> Get_Receiptlist = new List<string>();
String ReceiptNo;
openFileDialog1.ShowDialog();
string name_of_Textfile = openFileDialog1.FileName;
try
{
StreamReader sr = new StreamReader(name_of_Textfile);
{
while ((ReceiptNo = sr.ReadLine()) != null)
{
Get_Receiptlist.Add(ReceiptNo);
} // end while
MessageBox.Show("Record saved in the Data list");// just for testing purpose.
}// end StreamReader
}
catch (Exception err)
{
MessageBox.Show("Cannot read data from file");
}
return Get_Receiptlist;
}
private void button2_Click(object sender, EventArgs e)
{
string single_quotation = "'";
string comma = ",";
string paths = #"C:\Users\sample\Desktop\FileStream\Output.txt";
if (!File.Exists(paths))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(paths))
{
string[] receipt = list().ToArray();
foreach (string rec in receipt)
{
string quoted_receipt = single_quotation + rec + single_quotation + rec + comma;
sw.WriteLine(quoted_receipt);
sw.WriteLine(Environment.NewLine);
}//foreach
sw.Close();
MessageBox.Show("Finish processing File");
}//end using
}// end if
}
In your method button2_Click you have bad loop:
string[] receipt = list().ToArray();
foreach (string rec in receipt)
{
string quoted_receipt = single_quotation + rec + single_quotation + rec + comma;
sw.WriteLine(quoted_receipt);
sw.WriteLine(Environment.NewLine);
}//foreach
First I'm not even sure its Java ... but if it was Java, then I would replace this fragment with this:
List<String> values = list();
for (int i = 0; i < values.size(); i++)
{
String rec = values.get(i);
StringBuilder quoted_receipt = new StringBuilder();
if (i > 0)
{
// add comma only if the first iteration already passed
quoted_receipt.append(comma);
}
quoted_receipt.append(single_quotation).append(rec).append(single_quotation);
sw.WriteLine(quoted_receipt.toString());
sw.WriteLine(Environment.NewLine);
}

Categories