I have this project on c# windows forms and what I have to do is get some data from a web service and present them to FastRaport.
I have tried display them on a DataGridView first and then fetching the data from it and it works pretty nice. I can download the file and then it gives me a dialog asking me in what format do I want to save it.
But now the requirement is to not use gridview at all, just a button that would convert directly those data into a PDF file.
Here's my code for displaying the data into DataGridView:
var asd1 = dataGridView1.Columns.Add("DrzavaAng", "DrzavaAng");
var asd2 = dataGridView1.Columns.Add("Valuta", "Valuta");
var asd3 = dataGridView1.Columns.Add("Oznaka", "Oznaka");
var asd4 = dataGridView1.Columns.Add("Nomin", "Nomin");
var asd5 = dataGridView1.Columns.Add("Sreden", "Sreden");
for (var i = 0; i<xmlNodes.Count; i++)
{
var node = xmlNodes[i];
var states = new Class();
states.Valuta = node["Valuta"].InnerText;
states.Oznaka = node["Oznaka"].InnerText;
states.Nomin = node["Nomin"].InnerText;
states.Sreden = node["Sreden"].InnerText;
states.DrzavaAng = node["DrzavaAng"].InnerText;
//var asd = dataGridView1.Columns.Add("1", "1");
_ = dataGridView1.Rows.Add();
dataGridView1.Rows[i].Cells["DrzavaAng"].Value=states.DrzavaAng;
dataGridView1.Rows[i].Cells["Valuta"].Value=states.Valuta;
dataGridView1.Rows[i].Cells["Oznaka"].Value=states.Oznaka;
dataGridView1.Rows[i].Cells["Nomin"].Value=states.Nomin;
dataGridView1.Rows[i].Cells["Sreden"].Value=states.Sreden;
}
Here's the part where I pass the data from GridView to the FastReport "database".
using (Report report = new Report())
{
report.Load(ReportPath);
DataTable dt = new DataTable();
foreach (DataGridViewColumn cl in dataGridView1.Columns)
{
dt.Columns.Add();
}
object[] clvl = new object[dataGridView1.Columns.Count];
foreach (DataGridViewRow row in dataGridView1.Rows)
{
for (int i = 0; i<row.Cells.Count; i++)
{ clvl[i] = row.Cells[i].Value; }
dt.Rows.Add(clvl);
}
DataSet ds = new DataSet();
ds.Tables.Add(dt);
report.Dictionary.RegisterData(ds.Tables[0], "test", true);
report.SetParameterValue("date", dateTimePicker1.Value.ToString("dd.MM.yyyy"));
report.Show();
}
Here's my FastReport file before committing anything:
FastReportImage
And here's the output I get : FastReport output
My question is, how can I make it to fetch the data without the gridview, directly from webservice and load it into a FastReport -> PDF file?
Related
so I am working on my project and I want to write datagridview which is from a CSV file into XML file and I have achieved that but what I want to know if there is any way to sort the order view or change the outcome of XML what I want is to sort Alphabetical order from a specific column. this is my code for the saving XML file.
if (saveFileDialogXml.ShowDialog() == DialogResult.OK)
{
//Xml Alphabetical order code goes here
DataTable dst = new DataTable();
dst = (DataTable)Datagridview1.DataSource;
dst.TableName = "Data";
dst.WriteXml(saveFileDialogXml.FileName);
}
}
but the output of this is
<?xml version="1.0" standalone="yes"?>
<Item_x0020_Code>Item Code</Item_x0020_Code>
<Item_x0020_Description>Item Description</Item_x0020_Description>
<Current_x0020_Count>Current Count</Current_x0020_Count>
<On_x0020_Order>On Order</On_x0020_Order>
as you can see it even put the Hexadecimal and it just throws everything there, so I was wondering if i can reformat it the way I want it to display like removing the x0020. So I tried using LINQ to see if there was a problem with file, but I keep getting another error which says
System.Xml.XmlException: 'The ' ' character, hexadecimal value 0x20, cannot be included in a name.'
This is the LINQ code :
var xmlFile = new XElement("root",
from line in File.ReadAllLines(#"C:\\StockFile\stocklist.csv")
.Where(n => !string.IsNullOrWhiteSpace(n))
where !line.StartsWith(",") && line.Length > 0
let parts = line.Split(',')
select new XElement("Item Code",
new XElement("Test1", parts[0]),
new XElement("Test2", parts[1])
)
);
Also, I am new to C# and my first post here so please excuse the messy writing or placements.
Try following :
DataTable dst = new DataTable();
int startColumn = 5;
for(int i = dst.Columns.Count - 1; i >= startColumn; i--)
{
dst = dst.AsEnumerable().OrderBy(x => dst.Columns[i]).CopyToDataTable();
}
Sorry for the late Reply I kinda figured it out so forgot to close or mark an answer anyway if any of you run to the same thing all I did was this
// Save file dialogue XML file.
if (saveFileDialogXml.ShowDialog() == DialogResult.OK)
{
//try block to catch exception and handle it.
try
{
//Changing Data Table name to stock.
string Stock = ((DataTable)Datagridview1.DataSource).TableName;
}
//Catching the exception and handling it.
catch (Exception)
{
string es = "Please Open The File Before Saving it";
string title = "Error";
MessageBox.Show(es, title);
}
// instatiate new DataTable.
DataTable dt = new DataTable
{
TableName = "Stock"
};
for (int i = 0; i < Datagridview1.Columns.Count; i++)
{
//if (dataGridView1.Columns[i].Visible) // Add's only Visible columns.
//{
string headerText = Datagridview1.Columns[i].HeaderText;
headerText = Regex.Replace(headerText, "[-/, ]", "_");
DataColumn column = new DataColumn(headerText);
dt.Columns.Add(column);
//}
}
foreach (DataGridViewRow DataGVRow in Datagridview1.Rows)
{
DataRow dataRow = dt.NewRow();
// Add's only the columns that I need
dataRow[0] = DataGVRow.Cells["Item Code"].Value;
dataRow[1] = DataGVRow.Cells["Item Description"].Value;
dataRow[2] = DataGVRow.Cells["Current Count"].Value;
dataRow[3] = DataGVRow.Cells["On Order"].Value;
dt.Rows.Add(dataRow); //dt.Columns.Add();
}
DataSet ds = new DataSet();
ds.Tables.Add(dt);
//Finally the save part:
XmlTextWriter xmlSave = new XmlTextWriter(saveFileDialogXml.FileName, Encoding.UTF8)
{
Formatting = Formatting.Indented
};
ds.DataSetName = "Data";
ds.WriteXml(xmlSave);
xmlSave.Close();
i am currently working on a small Project and i got stuck with a Problem i currently can not manage to solve...
I have multiple ".CSV" Files i want to read, they all have the same Data just with different Values.
Header1;Value1;Info1
Header2;Value2;Info2
Header3;Value3;Info3
While reading the first File i Need to Create the Headers. The Problem is they are not splited in Columns but in rows (as you can see above Header1-Header3).
Then it Needs to read the Value 1 - Value 3 (they are listed in the 2nd Column) and on top of that i Need to create another Header -> Header4 with the data of "Info2" which is always placed in Column 3 and Row 2 (the other values of Column 3 i can ignore).
So the Outcome after the first File should look like this:
Header1;Header2;Header3;Header4;
Value1;Value2;Value3;Info2;
And after multiple files it sohuld be like this:
Header1;Header2;Header3;Header4;
Value1;Value2;Value3;Value4;
Value1b;Value2b;Value3b;Value4b;
Value1c;Value2c;Value3c;Value4c;
I tried it with OleDB but i get the Error "missing ISAM" which i cant mange to fix. The Code i Used is the following:
public DataTable ReadCsv(string fileName)
{
DataTable dt = new DataTable("Data");
/* using (OleDbConnection cn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"" +
Path.GetDirectoryName(fileName) + "\";Extendet Properties ='text;HDR=yes;FMT=Delimited(,)';"))
*/
using (OleDbConnection cn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
Path.GetDirectoryName(fileName) + ";Extendet Properties ='text;HDR=yes;FMT=Delimited(,)';"))
{
using(OleDbCommand cmd = new OleDbCommand(string.Format("select *from [{0}]", new FileInfo(fileName).Name,cn)))
{
cn.Open();
using(OleDbDataAdapter adapter = new OleDbDataAdapter(cmd))
{
adapter.Fill(dt);
}
}
}
return dt;
}
Another attempt i did was using StreamReader. But the Headers are in the wrong place and i dont know how to Change this + do this for every file. the Code i tried is the following:
public static DataTable ReadCsvFilee(string path)
{
DataTable oDataTable = new DataTable();
var fileNames = Directory.GetFiles(path);
foreach (var fileName in fileNames)
{
//initialising a StreamReader type variable and will pass the file location
StreamReader oStreamReader = new StreamReader(fileName);
// CONTROLS WHETHER WE SKIP A ROW OR NOT
int RowCount = 0;
// CONTROLS WHETHER WE CREATE COLUMNS OR NOT
bool hasColumns = false;
string[] ColumnNames = null;
string[] oStreamDataValues = null;
//using while loop read the stream data till end
while (!oStreamReader.EndOfStream)
{
String oStreamRowData = oStreamReader.ReadLine().Trim();
if (oStreamRowData.Length > 0)
{
oStreamDataValues = oStreamRowData.Split(';');
//Bcoz the first row contains column names, we will poluate
//the column name by
//reading the first row and RowCount-0 will be true only once
// CHANGE TO CHECK FOR COLUMNS CREATED
if (!hasColumns)
{
ColumnNames = oStreamRowData.Split(';');
//using foreach looping through all the column names
foreach (string csvcolumn in ColumnNames)
{
DataColumn oDataColumn = new DataColumn(csvcolumn.ToUpper(), typeof(string));
//setting the default value of empty.string to newly created column
oDataColumn.DefaultValue = string.Empty;
//adding the newly created column to the table
oDataTable.Columns.Add(oDataColumn);
}
// SET COLUMNS CREATED
hasColumns = true;
// SET RowCount TO 0 SO WE KNOW TO SKIP COLUMNS LINE
RowCount = 0;
}
else
{
// IF RowCount IS 0 THEN SKIP COLUMN LINE
if (RowCount++ == 0) continue;
//creates a new DataRow with the same schema as of the oDataTable
DataRow oDataRow = oDataTable.NewRow();
//using foreach looping through all the column names
for (int i = 0; i < ColumnNames.Length; i++)
{
oDataRow[ColumnNames[i]] = oStreamDataValues[i] == null ? string.Empty : oStreamDataValues[i].ToString();
}
//adding the newly created row with data to the oDataTable
oDataTable.Rows.Add(oDataRow);
}
}
}
//close the oStreamReader object
oStreamReader.Close();
//release all the resources used by the oStreamReader object
oStreamReader.Dispose();
}
return oDataTable;
}
I am thankful for everyone who is willing to help. And Thanks for reading this far!
Sincerely yours
If I understood you right, there is a strict parsing there like this:
string OpenAndParse(string filename, bool firstFile=false)
{
var lines = File.ReadAllLines(filename);
var parsed = lines.Select(l => l.Split(';')).ToArray();
var header = $"{parsed[0][0]};{parsed[1][0]};{parsed[2][0]};{parsed[1][0]}\n";
var data = $"{parsed[0][1]};{parsed[1][1]};{parsed[2][1]};{parsed[1][2]}\n";
return firstFile
? $"{header}{data}"
: $"{data}";
}
Where it would return - if first file:
Header1;Header2;Header3;Header2
Value1;Value2;Value3;Value4
if not first file:
Value1;Value2;Value3;Value4
If I am correct, rest is about running this against a list file of files and joining the results in an output file.
EDIT: Against a directory:
void ProcessFiles(string folderName, string outputFileName)
{
bool firstFile = true;
foreach (var f in Directory.GetFiles(folderName))
{
File.AppendAllText(outputFileName, OpenAndParse(f, firstFile));
firstFile = false;
}
}
Note: I missed you want a DataTable and not an output file. Then you could simply create a list and put the results into that list making the list the datasource for your datatable (then why would you use semicolons in there? Probably all you need is to simply attach the array values to a list).
(Adding as another answer just to make it uncluttered)
void ProcessMyFiles(string folderName)
{
List<MyData> d = new List<MyData>();
var files = Directory.GetFiles(folderName);
foreach (var file in files)
{
OpenAndParse(file, d);
}
string[] headers = GetHeaders(files[0]);
DataGridView dgv = new DataGridView {Dock=DockStyle.Fill};
dgv.DataSource = d;
dgv.ColumnAdded += (sender, e) => {e.Column.HeaderText = headers[e.Column.Index];};
Form f = new Form();
f.Controls.Add(dgv);
f.Show();
}
string[] GetHeaders(string filename)
{
var lines = File.ReadAllLines(filename);
var parsed = lines.Select(l => l.Split(';')).ToArray();
return new string[] { parsed[0][0], parsed[1][0], parsed[2][0], parsed[1][0] };
}
void OpenAndParse(string filename, List<MyData> d)
{
var lines = File.ReadAllLines(filename);
var parsed = lines.Select(l => l.Split(';')).ToArray();
var data = new MyData
{
Col1 = parsed[0][1],
Col2 = parsed[1][1],
Col3 = parsed[2][1],
Col4 = parsed[1][2]
};
d.Add(data);
}
public class MyData
{
public string Col1 { get; set; }
public string Col2 { get; set; }
public string Col3 { get; set; }
public string Col4 { get; set; }
}
I don't know if this is the best way to do this. But what i would have done in your case, is to rewrite the CSV's the conventionnal way while reading all the files, then create a stream containing the new CSV created.
It would look like something like this :
var csv = new StringBuilder();
csv.AppendLine("Header1;Header2;Header3;Header4");
foreach (var item in file)
{
var newLine = string.Format("{0},{1},{2},{3}", item.value1, item.value2, item.value3, item.value4);
csv.AppendLine(newLine);
}
//Create Stream
MemoryStream stream = new MemoryStream();
StreamReader reader = new StreamReader(stream);
//Fill your data table here with your values
Hope this will help.
I have a Janus GridEX and I want to add a DropDownList with images and text to a column. When I populate the ValueList of the column I pass a DataView as parameter which contain a DataTable structured in this way:
var dt = new DataTable("asd");
dt.Columns.Add("value");
dt.Columns.Add("text");
dt.Columns.Add("img", typeof(byte[]));
then I add a row which contains one row:
var row2 = dt.NewRow();
row2["value"] = 1;
row2["text"] = "A2";
row["img"] = GetBytesFromImage(resources.Icon1);
this is the GetBytesFromImage routine:
private byte[] GetBytesFromImage(Icon ico)
{
using(var ms = new MemoryStream())
{
ico.Save(ms);
return ms.ToArray()
}
}
then I populate the valuelist:
grid.......PopulateValueList(dataview, "value","text","img",Color.Red, new Size(16,16)
then I get the error. Someone know why?
In my xml file,it has many elements and many child/sub child elements are there so i have decided to load as generic list and display in the DGView and the columns are already created/customed in DGview.
I have to edit the values in the datagridview and serialize back to the file. I would like to know,
how can i get the values from the datagrid view and serialize back to the file.
I tried using this, Dataset ds = new Dataset();ds = (Dataset) (dataGridView2.Datasource);ds.WriteXml("XML_File.xml"); i got a error message, nullRefExceptionError.
As I know the DataSet ds is null, thats why I'm getting this error.
I don't want to use the dataset for binding.I want to bind the xml file directly to the datagridview. IS it possible with my approach???
This approach is good but it's not saving the xml file as like the original xml file:
DataTable dt = new DataTable("Rules");
for (int i = 0; i < dataGridView4.ColumnCount; i++)
{
dt.Columns.Add(dataGridView4.Columns[i].Name, typeof(System.String));
}
DataRow myrow;
int icols = dataGridView4.Columns.Count;
foreach (DataGridViewRow drow in this.dataGridView4.Rows)
{
myrow = dt.NewRow();
for (int i = 0; i <= icols - 1; i++)
{
myrow[i] = drow.Cells[i].Value;
}
dt.Rows.Add(myrow);
}
dt.WriteXml(#"C:\test\items.xml");
Any help for me to serilaize/write the values from datagridview.
I have adapted this approach for my problem & it works.
List<Test>laneConfigs = new List<Test>();//From a class
foreach (DataGridViewRow dr in dataGridView1.Rows)
{
int bbbBorder = 0;
Int32.TryParse(dr.Cells["BBor"].Value.ToString(), out bbbBorder );
int eeee= 0;
Int32.TryParse(dr.Cells["EBor"].Value.ToString(), out eee);
LaneConfig laneConfig = new LaneConfig(
dr.Cells["ID"].Value.ToString(),
(TrafficLaneType)Enum.Parse(typeof(TrafficLaneType), dr.Cells["Type"].Value.ToString()),
new ValueWithUnit<int>(bbbBorder, "mm"),
new ValueWithUnit<int>(eee, "mm"));
laneConfigs.Add(llaneConfig);
}
Would someone kindly assist me with the following? I have two DataGridView objects that each display a DataTable, where the two datatables are related with the following code:
DataSet dSet = new DataSet();
DataTable ParentList = ListToDataTable(_listOfAllAlbumObjects);
DataTable ChildList = ListToDataTable(_listOfAllTrackObjects);
dSet.Tables.AddRange(new DataTable[]{ParentList, ChildList});
DataColumn parentRelationColumn = ParentList.Columns["AlbumId"];
DataColumn childRelationColumn = ChildList.Columns["AlbumId"];
dSet.Relations.Add("ParentToChild", parentRelationColumn, childRelationColumn);
ParentDataGridView.DataSource = dSet;
ParentDataGridView.DataMember = "ParentList";
ChildDataGridView.DataSource = ???;
ChildDataGridView.DataMember = "ParentToChild";
Both DataTables are actually List<> converted to DataTables with the following:`
public static DataTable ListToDataTable<T>( IList<T> data)
{
var props = TypeDescriptor.GetProperties(typeof(T));
var table = new DataTable();
for (var i = 0; i < props.Count; i++)
{
PropertyDescriptor prop = props[i];
table.Columns.Add(prop.Name, prop.PropertyType);
}
var values = new object[props.Count];
foreach (T item in data)
{
for (int i = 0; i < values.Length; i++)
{ values[i] = props[i].GetValue(item); }
table.Rows.Add(values);
}
return table;
}
Initially it appears that the each DataGridView displays the data appropriately; however the child DataGridView does not update with any change of record in the parent DataGridView.
I see that the tables need to be interconnected through the binding-source; however I don't believe there is a true binding-source here.
Could someone please steer me in the right direction? Thanks.
There's an MSDN article showing what you want to do:
How to: Create a Master/Detail Form Using Two Windows Forms DataGridView Controls
Here's how this might work for you:
Either through the designer or through code add two BindingSources to your project: parentBindingSource and childBindingSource. Then try this in place of the code you have.
// Associate your BSs with your DGVs.
ParentDataGridView.DataSource = parentBindingSource;
ChildDataGridView.DataSource = childBindingSource;
// (Most of) your code here:
DataSet dSet = new DataSet();
DataTable ParentList = ListToDataTable(_listOfAllAlbumObjects);
DataTable ChildList = ListToDataTable(_listOfAllTrackObjects);
dSet.Tables.AddRange(new DataTable[]{ParentList, ChildList});
DataColumn parentRelationColumn = ParentList.Columns["AlbumId"];
DataColumn childRelationColumn = ChildList.Columns["AlbumId"];
dSet.Relations.Add("ParentToChild", parentRelationColumn, childRelationColumn);
// Let's name this DT to make clear what we're referencing later on.
ParentList.TableName = "ParentListDT";
// Rather than set the data properties on your DGVs, set them in your BindingSources.
parentBindingSource.DataSource = dSet;
parentBindingSource.DataMember = "ParentListDT";
childBindingSource.DataSource = parentBindingSource;
childBindingSource.DataMember = "ParentToChild";