I have been trying to add code to replace column data that has the word "null" to just a blank. I am not proficient in C#, so have no idea where to add it or how to code it. Below is the snippet of code that reads from the text file. I have no clue if the current code supports adding the replacement logic, so I am open to modifying the code to make it happen.
public override void PreExecute()
{
base.PreExecute();
int columnIndex;
string columnName = string.Empty;
string currentFile = Variables.vCurrentInputFile;
string[] currentRowValues;
string delimiter = Variables.vFileDelimiter;
Type fieldDataType;
string messageText;
DataRow row;
int upperBound;
bool skippedColumn = false;
var skippedColumns = new StringBuilder();
_FormatProvider = CultureInfo.GetCultureInfo(ComponentMetaData.LocaleID);
if (BuildImportBuffer())
{
try
{
using (var fileReader = new TextFieldParser(currentFile))
{
fileReader.SetDelimiters(delimiter);
fileReader.TrimWhiteSpace = false;
var fileColumns = fileReader.ReadFields();
while (!fileReader.EndOfData)
{
currentRowValues = fileReader.ReadFields();
if (currentRowValues != null)
{
upperBound = currentRowValues.GetUpperBound(0);
row = _BufferTable.NewRow();
try
{
var loopTo = upperBound;
for (columnIndex = 0; columnIndex <= loopTo; columnIndex++)
{
columnName = fileColumns[columnIndex];
if (!skippedColumn || skippedColumn && !skippedColumns.ToString().Contains(columnName))
{
fieldDataType = _BufferTable.Columns[columnName].DataType;
row[columnName] = Convert.ChangeType(currentRowValues[columnIndex].Trim(), fieldDataType, _FormatProvider);
}
}
}
I really need help with the code since I don't even know how to modify the current logic.
Related
I have a simple CSV file I need to parse that has variable column lengths. CSV File for reference.
I'm attempting to write some conditions to parse each line and store into a discreet string based off what value the first column contains in each line.
The first issue that I'm running into is that my loop seems to start reading at row 2. Is this because TextFieldParser assumes a header?
The second issue is that my if statements don't seem to be evaluating correctly. If I shift the order of the rows within the file, my first if in the order is supposed to parse the "Lighting" rows (regardless of which rows in the file contain "Lighting").
Just as a note, I am working in a .net 3.5 environment
Here's what I've got so far:
namespace CSV_Handler_Console
{
public class Program
{
public static void Main(string[] args)
{
//Console.WriteLine("Press Enter");
string filePath = "C:\\Users\\chris\\Desktop\\ConfigFile.csv";
string subLight = "Lighting";
string subPin = "PIN";
string subProc = "Processor";
string subFab = "Fabuloso";
string subQuirky = "Quirky";
//string[] fields = csvParser.ReadFields();
string category = string.Empty;
string index = string.Empty;
string load1 = string.Empty;
string load2 = string.Empty;
string load3 = string.Empty;
string load4 = string.Empty;
string value = string.Empty;
string light1 = string.Empty;
string light2 = string.Empty;
string light3 = string.Empty;
string pin = string.Empty;
string processor1 = string.Empty;
string processor2 = string.Empty;
string processor3 = string.Empty;
string processor4 = string.Empty;
string processor5 = string.Empty;
string processor6 = string.Empty;
string processor7 = string.Empty;
string processor8 = string.Empty;
string display1 = string.Empty;
string display2 = string.Empty;
string display3 = string.Empty;
string display4 = string.Empty;
string display5 = string.Empty;
string display6 = string.Empty;
string display7 = string.Empty;
string display8 = string.Empty;
var path = String.Format("{0}", filePath);
using (TextFieldParser csvParser = new TextFieldParser(path))
{
csvParser.SetDelimiters(new string[] { "," });
//csvParser.HasFieldsEnclosedInQuotes = false;
string row = csvParser.ReadLine();
while (!csvParser.EndOfData)
{
if (row.Contains(subLight))
{
string[] fields = csvParser.ReadFields();
category = fields[0];
index = fields[1];
load1 = fields[2];
load2 = fields[3];
load3 = fields[4];
load4 = fields[5];
if(index.Contains("1"))
{
light1 = row;
}
else if (index.Contains("2"))
{
light2 = row;
}
else if (index.Contains("3"))
{
light3 = row;
}
string rowData = string.Format("{0},{1},{2},{3},{4},{5}", category, index, load1, load2, load3, load4);
Console.WriteLine(rowData);
//Console.ReadLine();
}
else if (row.Contains(subPin))
{
string[] fields = csvParser.ReadFields();
category = fields[0];
index = fields[1];
value = fields[2];
string rowData = string.Format("{0},{1},{2}", category, index, value);
Console.WriteLine(rowData);
}
else if (row.Contains(subProc))
{
string[] fields = csvParser.ReadFields();
category = fields[0];
index = fields[1];
value = fields[2];
if (index.Contains("A"))
{
processor1 = row;
}
else if (index.Contains("B"))
{
processor2 = row;
}
else if (index.Contains("C"))
{
processor3 = row;
}
else if (index.Contains("D"))
{
processor4 = row;
}
else if (index.Contains("E"))
{
processor5 = row;
}
else if (index.Contains("F"))
{
processor6 = row;
}
else if (index.Contains("G"))
{
processor7 = row;
}
else if (index.Contains("H"))
{
processor8 = row;
}
string rowData = string.Format("{0},{1},{2}", category, index, value);
Console.WriteLine(rowData);
}
else if (row.Contains(subQuirky) || row.Contains(subFab))
{
string[] fields = csvParser.ReadFields();
category = fields[0];
index = fields[1];
value = fields[2];
if (index.Contains("A"))
{
display1 = row;
}
else if (index.Contains("B"))
{
display2 = row;
}
else if (index.Contains("C"))
{
display3 = row;
}
else if (index.Contains("D"))
{
display4 = row;
}
else if (index.Contains("E"))
{
display5 = row;
}
else if (index.Contains("F"))
{
display6 = row;
}
else if (index.Contains("G"))
{
display7 = row;
}
else if (index.Contains("H"))
{
display8 = row;
}
string rowData = string.Format("{0},{1},{2}", category, index, value);
Console.WriteLine(rowData);
}
else
{
Console.WriteLine("No Match Found");
}
}
Console.ReadLine();
}
}
}
Any guidance would be appreciated.
It's your implementation. You first grab the first row with ReadLine, which advances the cursor to the next line. Then if the row contains your search property, you do a ReadFields, which is the 2nd line of the document.
If your data is always guaranteed to have the category, you could just use ReadFields and compare against the first element. You could look at PeekChars if you want to look at the content of the current row without advancing the cursor.
TextFieldParser.ReadLine: Returns the current line as a string and
advances the cursor to the next line.
TextFieldParser.ReadFields: Reads all fields on the current line,
returns them as an array of strings, and advances the cursor to the
next line containing data.
TextFieldParser.PeekChars: Reads the specified number of characters without advancing the cursor.
i have a problem with visual studio c# listview items that i cant found a solution over googling.
I've made from application with a listview, i can add, remove, update listview items.
I'm saving and loading the listview to/from file correctly with this code:
private void saveListViewItems(string path, ListView lv)
{
var delimeteredListviewData = new List<string>();
string delimeteredItems = string.Empty;
foreach (ListViewItem lvi in lv.Items)
{
foreach (ListViewItem.ListViewSubItem lvsi in lvi.SubItems)
{
delimeteredItems += lvsi.Text + "#";
}
delimeteredListviewData.Add(delimeteredItems);
}
System.IO.File.WriteAllLines(path, delimeteredListviewData.ToArray());
}
private void loadListViewItems(string path, ListView lv)
{
foreach (string line in System.IO.File.ReadAllLines(path))
{
lv.Items.Add(new ListViewItem(line.Split(new char[] { '#' }, StringSplitOptions.RemoveEmptyEntries)));
}
}
the problems is i have activated checkbox next to each item. i cant save listview items with checkbox checked. i want to save listview and load with selected items. thanks
Something like this?:
List<string> delimeteredItems = new List<string>();
foreach (ListViewItem lvi in listView1.CheckedItems)
{
string item= String.Join("#", lvi.SubItems.Cast<ListViewItem.ListViewSubItem>().Select(si=>si.Text));
delimeteredItems.Add(item);
}
System.IO.File.WriteAllLines(#"c:\temp\lines.txt", delimeteredItems);
Instead of only saving the string you need to save more information.
You can added add a IsChecked value together with your string.
You need a small wrapper class that holds both values as a property.
Then you can use serilization, it is a term to describe a way to convert an object to something you can store on disk.
There are many formats to pick from, but Json is a good readable format. You can download the Nuget package NewtonSoft.Json via the nuget package manager.
public class StoreListView
{
public void StoreToDisk(string path, List<ItemDataHolder> list)
{
string theListInJsonFormat = JsonConvert.SerializeObject(list);
File.WriteAllText(path, theListInJsonFormat);
}
}
public class ItemDataHolder
{
public string SomeValuesYouWantToSave { get; set; }
public bool IsChecked { get; set; }
}
I've Managed the program to work.
I was wrong about the way reading/writing the text file.
now I'm using ini-parser nuget.
installed ini parser to project.
then:
using IniParser;
using IniParser.Model;
private void saveListViewItems(string path, ListView lv)
{
int i = 0;
string IPFrom;
string IPFromval;
string IPTO;
string IPTOval;
string Comment;
string Commentval;
string CheckState;
string CheckStateval;
int IPSectioncount;
var parser = new FileIniDataParser();
IniData data = parser.ReadFile(path);
while ( i < lv.Items.Count) {
if ((lv.Items[i].Selected) || (lv.Items[i].Checked))
{
CheckStateval = "1";
}
else
{
CheckStateval = "0";
}
CheckState = "";
CheckState = "CheckState";
CheckState += String.Join(CheckState, i);
IPFromval = lv.Items[i].SubItems[0].Text;
IPFromval = "";
IPFrom = "IPFrom";
IPFrom += String.Join(IPFrom, i);
IPFromval = lv.Items[i].SubItems[0].Text;
IPTOval = "";
IPTO = "IPTO";
IPTO += String.Join(IPTO, i);
IPTOval = lv.Items[i].SubItems[1].Text;
Commentval = "";
Comment = "Comment";
Comment += String.Join(Comment, i);
Commentval = lv.Items[i].SubItems[2].Text;
data["IP"][CheckState] = CheckStateval;
data["IP"][IPFrom] = IPFromval;
data["IP"][IPTO] = IPTOval;
data["IP"][Comment] = Commentval;
i++;
}
IPSectioncount = lv.Items.Count;
data["IP"]["IPSectionCount"] = IPSectioncount.ToString();
parser.WriteFile(path, data);
}
private void loadListViewItems(string path, ListView lv)
{
string IPFrom;
string IPTO;
string Comment;
string CheckState;
string IPSectioncount;
string row="";
var parser = new FileIniDataParser();
IniData data = parser.ReadFile(path);
IPSectioncount = data["IP"]["IPSectionCount"];
int m = Int32.Parse(IPSectioncount);
int i = 0;
while ( i < m )
{
IPFrom = "";
IPTO = "";
Comment = "";
row = "";
IPFrom = "IPFrom";
IPFrom += String.Join(IPFrom, i);
IPFrom = data["IP"][IPFrom];
IPTO = "IPTO";
IPTO += String.Join(IPTO, i);
IPTO = data["IP"][IPTO];
Comment = "Comment";
Comment += String.Join(Comment, i);
Comment = data["IP"][Comment];
CheckState = "CheckState";
CheckState += String.Join(CheckState, i);
CheckState = data["IP"][CheckState];
row = String.Join(",",IPFrom,IPTO,Comment);
lv.Items.Add(new ListViewItem(row.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)));
if (CheckState == "1")
{
lv.Items[i].Checked = true;
}
i++;
}
}
I have a large csv file which has millions of rows. The sample csv lines are
CODE,COMPANY NAME, DATE, ACTION
A,My Name , LLC,2018-01-28,BUY
B,Your Name , LLC,2018-01-25,SELL
C,
All Name , LLC,2018-01-21,SELL
D,World Name , LLC,2018-01-20,BUY
Row C has new line, but actually this is same record. I want to remove new line character from the csv line within cell\field\column.
I tired \r\n, Envirnment.NewLine and many other things, but could not make it work.
Here is my code..
private DataTable CSToDataTable(string csvfile)
{
Int64 row = 0;
try
{
string CSVFilePathName = csvfile; //#"C:\test.csv";
string[] Lines = File.ReadAllLines(CSVFilePathName.Replace(Environment.NewLine, ""));
string[] Fields;
Fields = Lines[0].Split(new char[] { ',' });
int Cols = Fields.GetLength(0);
DataTable dt = new DataTable();
//1st row must be column names; force lower case to ensure matching later on.
for (int i = 0; i < Cols; i++)
dt.Columns.Add(Fields[i].ToLower(), typeof(string));
DataRow Row;
for (row = 1; row < Lines.GetLength(0); row++)
{
Fields = Lines[row].Split(new char[] { ',' });
Row = dt.NewRow();
//Console.WriteLine(row);
for (int f = 0; f < Cols; f++)
{
Row[f] = Fields[f];
}
dt.Rows.Add(Row);
if (row == 190063)
{
}
}
return dt;
}
catch (Exception ex)
{
throw ex;
}
}
How can I remove new line character and read the row correctly? I don't want to skip the such rows as per the business requirement.
You CSV file is not in valid format. In order to parse and load them successfully, you will have to sanitize them. Couple of issues
COMPANY NAME column contains field separator in it. Fix them by
surrounding quotes.
New line in CSV value - This can be fixed by combining adjacent rows as one.
With Cinchoo ETL, you can sanitize and load your large file as below
string csv = #"CODE,COMPANY NAME, DATE, ACTION
A,My Name , LLC,2018-01-28,BUY
B,Your Name , LLC,2018-01-25,SELL
C,
All Name , LLC,2018-01-21,SELL
D,World Name , LLC,2018-01-20,BUY";
string bufferLine = null;
var reader = ChoCSVReader.LoadText(csv)
.WithFirstLineHeader()
.Setup(s => s.BeforeRecordLoad += (o, e) =>
{
string line = (string)e.Source;
string[] tokens = line.Split(",");
if (tokens.Length == 5)
{
//Fix the second and third value with quotes
e.Source = #"{0},""{1},{2}"",{3}, {4}".FormatString(tokens[0], tokens[1], tokens[2], tokens[3], tokens[4]);
}
else
{
//Fix the breaking lines, assume that some csv lines broken into max 2 lines
if (bufferLine == null)
{
bufferLine = line;
e.Skip = true;
}
else
{
line = bufferLine + line;
tokens = line.Split(",");
e.Source = #"{0},""{1},{2}"",{3}, {4}".FormatString(tokens[0], tokens[1], tokens[2], tokens[3], tokens[4]);
line = null;
}
}
});
foreach (var rec in reader)
Console.WriteLine(rec.Dump());
//Careful to load millions rows into DataTable
//var dt = reader.AsDataTable();
Hope it helps.
You haven't made it clear what are the possible criteria an unwanted new line could appear in the file. So assuming that a 'proper' line in the CSV file does NOT end with a comma, and if one ends with a comma that means that it's not a properly formatted line, you could do something like this:
static void Main(string[] args)
{
string path = #"CSVFile.csv";
List<CSVData> data = new List<CSVData>();
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
using (StreamReader sr = new StreamReader(fs))
{
sr.ReadLine(); // Header
while (!sr.EndOfStream)
{
var line = sr.ReadLine();
while (line.EndsWith(","))
{
line += sr.ReadLine();
}
var items = line.Split(new string[] { "," }, StringSplitOptions.None);
data.Add(new CSVData() { CODE = items[0], NAME = items[1], COMPANY = items[2], DATE = items[3], ACTION = items[4] });
}
}
}
Console.ReadLine();
}
public class CSVData
{
public string CODE { get; set; }
public string NAME { get; set; }
public string COMPANY { get; set; }
public string DATE { get; set; }
public string ACTION { get; set; }
}
Obviously there's a lot of error handling to be done here (for example, when creating a new CSVData object make sure your items contain all the data you want), but I think this is the start you need.
I'm trying to make an app for work where I enter some data into some controls (start date and end date wage week ) and then the user picks a csv extract from our wage program. The app then merges the data from the controls and the csv file into a datatable which is then set as the datacontxct of the wpf datagrid view.
this.dgCSVData.DataContext = oDS.Tables[0].DefaultView;
So as I under stand it the datagrid is now bound (that is a question not a statement) Here is a screen shot
The datagrid is in the "shape" of the datatable in the sql database I want to append the data to. However the datatable was created in a private event handler CSV_Load_Click, code block below.
What I had hoped to do is set another button event handler up call "Upload Data" and pass the datatable (oDS.Tables[0].DefaultView) to the DAL layer to be read and appended to sql database table, the problem is how do I make the datatable available, should I have created a class to match my data row and then created a public list of the rows?
private void CSV_Load_Click(object sender, RoutedEventArgs e)
{
//Turn on upload button
btUpload.IsEnabled = true;
//To load and display CSV data
//string filename = txFilePath.Text;
string delimStr = ",,";
char[] delimiter = delimStr.ToCharArray();
string strFilePath = txFilePath.Text;
DataSet oDS = new DataSet();
string strFields = null;
DataTable oTable = new DataTable();
DataRow oRows = null;
Int32 intCounter = 0;
oDS.Tables.Add("Property");
StreamReader oSR = new StreamReader(strFilePath);
//Go to the top of the file
oSR.BaseStream.Seek(0, SeekOrigin.Begin);
string File = fileTest;
//System.Windows.MessageBox.Show(File.ToString());
//Add in the Header Columns check if headers in first row
if (rbYes.IsChecked==true)
// action for headers in row 1
{
foreach (string strFields_loopVariable in oSR.ReadLine().Split(delimiter))
{
strFields = strFields_loopVariable;
oDS.Tables[0].Columns.Add(strFields);
}
}
else
{
if (File==#"CHHOURS.CSV")
{
string TitleHeaders = "Wage_Year,Wage_Start_Date,Wage_End_Date,Tax Week,Wk_No,Clock,Surname,Initial,Dept,Dept_Hours,Other_Hours,Total_Hours,OT_Hours,";
foreach (string strFields_loopVariable in TitleHeaders.Split(delimiter))
{
strFields = strFields_loopVariable;
oDS.Tables[0].Columns.Add(strFields);
}
}
else
{
Int32 i = 0;
foreach (string strFields_loopVariable in oSR.ReadLine().Split(delimiter))
{
string ColumLetter = "abcdefghijklmnopqrstuvwxyz";
strFields = ColumLetter[i].ToString();
oDS.Tables[0].Columns.Add(strFields);
i += 1;
}
}
}
//String request = oSR.ReadToEnd();
//Now add in the Rows
oTable = oDS.Tables[0];
while ((oSR.Peek() > -1))
{
oRows = oTable.NewRow();
if (File == #"CHHOURS.CSV")
{
oRows[intCounter] = cbWageYear.Text;
intCounter = intCounter + 1;
oRows[intCounter] = dpStartDate.SelectedDate;
intCounter = intCounter + 1;
oRows[intCounter] = dpEndDate.SelectedDate;
intCounter = intCounter + 1;
oRows[intCounter] = cBTaxWeek.SelectedIndex;
intCounter = intCounter + 1;
}
foreach (string strFields_loopVariable in oSR.ReadLine().Split(delimiter))
{
strFields = Convert.ToString(strFields_loopVariable);
if (intCounter < 20)
{
oRows[intCounter] = strFields;
intCounter = intCounter + 1;
}
else
{
}
}
intCounter = 0;
oTable.Rows.Add(oRows);
}
this.dgCSVData.DataContext = oDS.Tables[0].DefaultView;
}
Ok so I woke up this morning with an idea and It worked .wow!
All I did was declare my dataset as public before the constructor of my class. Now there might be a "better" way but that worked for me. Ii have been able to call my update method from my DAL and create a datareader, so now just the update to sql to do, then bug fixing.
I am almost happy :)
here is the code
public partial class MainWindow : Window
{
public List<TaxWeek> LTaxWeeks { get; set; }
public TaxWeek SelectedTaxWeek { get; set; }
**public DataSet oDS = new DataSet();**
public MainWindow()
{
InitializeComponent();
}
I need to modify a dataset before binding it to a gridview.
When I walk through the complete code block, and hover over dsEmployeeOrg, that records
dont appear modified. What am I missing here?
My code is:
DataSet dsEmployeeOrg = eCorporateStaffMgr.GetEmployeeAccessLevel(oEmp);
DataTable dt = dsEmployeeOrg[0];
string sManagerID = "";
string sSupervisorID = "";
string sEmployeeID = "";
for (int i = 0; i < dsEmployeeOrg.Tables[0].Rows.Count; i++)
{
sManagerID = dt.Rows[i].ItemArray[3].ToString().Trim();
sSupervisorID = dt.Rows[i].ItemArray[4].ToString().Trim();
sEmployeeID = dt.Rows[i].ItemArray[5].ToString().Trim();
if ((sManagerID.ToString().Trim() != sSupervisorID.ToString().Trim()) && (sManagerID.ToString().Trim() != sEmployeeID.ToString().Trim()))
{
if (sSupervisorID.ToString().Trim() == sEmployeeID.ToString().Trim())
{
// This is a Supervisor record
dt.Rows[i].ItemArray[2] = "1111";
}
else if (sSupervisorID.ToString().Trim() != sEmployeeID.ToString().Trim())
{
//This is a Employee record
dt.Rows[i].ItemArray[2] = "0000";
}
}
}
Please modify your code as below
DataSet dsEmployeeOrg = eCorporateStaffMgr.GetEmployeeAccessLevel(oEmp);
DataTable dt = dsEmployeeOrg[0];
string sManagerID = "";
string sSupervisorID = "";
string sEmployeeID = "";
for (int i = 0; i < dsEmployeeOrg.Tables[0].Rows.Count; i++)
{
sManagerID = dt.Rows[i].ItemArray[3].ToString().Trim();
sSupervisorID = dt.Rows[i].ItemArray[4].ToString().Trim();
sEmployeeID = dt.Rows[i].ItemArray[5].ToString().Trim();
if ((sManagerID.ToString().Trim() != sSupervisorID.ToString().Trim()) && (sManagerID.ToString().Trim() != sEmployeeID.ToString().Trim()))
{
if (sSupervisorID.ToString().Trim() == sEmployeeID.ToString().Trim())
{
// This is a Supervisor record
dt.Rows[i][2] = "1111";
}
else if (sSupervisorID.ToString().Trim() != sEmployeeID.ToString().Trim())
{
//This is a Employee record
dt.Rows[i][2] = "0000";
}
}
}