This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 5 years ago.
I am using the ExcelDataReader extension to import excel files to C# datagridview. I am able to open the file and get it's sheets, but whenever I try to click on the sheet, My program breaks and says it's datatable is null. Please help me.
I am not sure if it's the var that is causing the problem, or that I didn't update the excel data into the datatable
namespace Dashboard {
public partial class Import_Excel : Form {
public Import_Excel() {
InitializeComponent();
}
DataSet result;
private void btnLoad_Click(object sender, EventArgs e) {
using (OpenFileDialog ofd = new OpenFileDialog()) {
if (ofd.ShowDialog() == DialogResult.OK) {
using (var stream = File.Open(ofd.FileName, FileMode.Open, FileAccess.Read)) {
using (var reader = ExcelReaderFactory.CreateReader(stream)) {
var result = reader.AsDataSet(new ExcelDataSetConfiguration() {
UseColumnDataType = true,
ConfigureDataTable = (data) => new ExcelDataTableConfiguration() {
UseHeaderRow = true
}
});
cboSheet.Items.Clear();
DataTableCollection table = result.Tables;
foreach (DataTable dt in result.Tables) {
cboSheet.Items.Add(dt.TableName);
}
reader.Close();
}
}
}
}
}
private void cboSheet_SelectedIndexChanged(object sender, EventArgs e) {
dataGridView1.DataSource = result.Tables[cboSheet.SelectedIndex];
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) {
}
}
}
If method cboSheet_SelectedIndexChanged happens before btnLoad_Click() than result will be null thus result.Tables throws NullReferenceException
private void cboSheet_SelectedIndexChanged(object sender, EventArgs e)
{
if(result != null) {
dataGridView1.DataSource = result.Tables[cboSheet.SelectedIndex];
}
}
Or just use: dataGridView1.DataSource = result?.Tables[cboSheet.SelectedIndex]; (will set it to null)
Related
I am trying to get the cell value in a string from the selected cell in the "Document Number" column in a DataGridView. My code to retrieve data from SharePoint and populate the DataGridView works fine, but I seem to be caught in a loop there? I cannot execute any other methods after populating the DataGridView . I can select a new search term and execute the Button1_Click event again successfully, but I cannot get any other methods to execute?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.SharePoint.Client;
using SP = Microsoft.SharePoint.Client;
namespace BuyersForeverFriend
{
public partial class Form1 : System.Windows.Forms.Form
{
public Form1()
{
InitializeComponent();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
string userSearch = textBox1.Text;
button1.Enabled = true;
}
private void button1_Click(object sender, EventArgs e)
{
using (ClientContext ctx = new ClientContext("https://teamsites.nafta.fcagroup.com/sites/PSOAPPS/iws/"))
{
var userInput = textBox1.Text;
Web web = ctx.Web;
List list = web.Lists.GetById(new Guid("61ef6657-eff7-42cb-99e1-8afd590334ec"));
var q = new CamlQuery() { ViewXml = "<View><Query><Where><Contains><FieldRef Name='Item_x0020_Description' /><Value Type='Note'>" + userInput + "</Value></Contains></Where></Query><ViewFields><FieldRef Name='Title' /><FieldRef Name='Topic_x002d_' /><FieldRef Name='Item_x0020_Description' /></ViewFields><QueryOptions /></View>" };
var r = list.GetItems(q);
ctx.Load(r);
ctx.ExecuteQuery();
if (r.Count != 0)
{
var searchResults = new DataTable();
searchResults.Columns.AddRange(new[]
{
new DataColumn("ID"), new DataColumn("Document Number"), new DataColumn("Item Description"), new DataColumn("Topic")});
foreach (var oListItem in r)
{
searchResults.Rows.Add(oListItem["ID"], oListItem["Title"], oListItem["Item_x0020_Description"],
oListItem["Topic_x002d_"]);
}
if (dataGridView1 != null)
{
dataGridView1.DataSource = searchResults;
dataGridView1.Refresh();
dataGridView1.Columns[2].DefaultCellStyle.Format = "dd'/'MM'/'yyyy";
var dataGridViewColumn = dataGridView1.Columns["ID"];
if (dataGridViewColumn != null)
dataGridViewColumn.Visible = false;
}
else
MessageBox.Show("after else statement");
}
}
MessageBox.Show("after sharepoint if statement");
return;
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
MessageBox.Show("a cell was clicked");
}
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
MessageBox.Show("starting routine");
if (dataGridView1.SelectedCells.Count > 0)
{
int selectedrowindex = dataGridView1.SelectedCells[0].RowIndex;
DataGridViewRow selectedRow = dataGridView1.Rows[selectedrowindex];
string a = Convert.ToString(selectedRow.Cells["Document Number"].Value);
MessageBox.Show(a);
textBox2.Text = ("The var =" + a);
}
else MessageBox.Show("if did not end up true");
}
}
}
I failed to initialize these, after adding them to the form method...poof everything works! :
public Form1()
{
InitializeComponent();
dataGridView1.CellClick += dataGridView1_CellClick;
dataGridView1.SelectionChanged += dataGridView1_SelectionChanged;
}
I already got most of the help I needed in order to create a working button to save my scraped proxies to a .txt file, but I still run into one issue. This is the code that I have gotten so far, it works perfectly fine:
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;
using System.Windows.Forms;
using System.IO;
namespace CyberScraper
{
public partial class Base_Scraper : Form
{
WebClient _WC = new WebClient();
Defaults _DF = new Defaults();
public Base_Scraper()
{
CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
}
private void Base_Scraper_Load(object sender, EventArgs e)
{
MessageBox.Show("twitch.tv/CyberLost same YT Name");
}
private void ScrapeTheProxies()
{
try
{
foreach (string Source in ScrapeSources.Lines)
{
string UnparsedWebSource = _WC.DownloadString(Source);
MatchCollection _MC = _DF.REGEX.Matches(UnparsedWebSource);
foreach (Match Proxy in _MC)
{
GatheredProxies.Items.Add(Proxy);
}
}
}
catch (Exception)
{
}
}
private void SaveProxyResults_Click(object sender, System.EventArgs e)
{
Stream myStream;
SaveFileDialog dlg = new SaveFileDialog();
dlg.Title = "";
dlg.InitialDirectory = #"C:\Users\username\Desktop";
dlg.Filter = "txt files (*.txt)|*.txt";
dlg.FilterIndex = 1;
if (dlg.ShowDialog() == DialogResult.OK)
{
if ((myStream = dlg.OpenFile()) != null)
{
myStream.Close();
StreamWriter writer = new StreamWriter(dlg.FileName);
for (int i = 0; i < GatheredProxies.Items.Count; i++)
{
writer.WriteLine((string)GatheredProxies.Items[i]);
}
writer.Close();
}
}
dlg.Dispose();
}
private void BackgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
ScrapeTheProxies();
}
private void ScrapeButton_Click(object sender, EventArgs e)
{
BackgroundWorker.RunWorkerAsync();
}
}
}
When I click on "Save Results" it works before I scraped the proxies, if I do it after finishing scraping the proxies it outputs this error and saves it on the desktop as an empty .txt file instead of a .txt file containing the scraped proxies:
System.InvalidCastException: 'Unable to cast object of type 'System.Text.RegularExpressions.Match' to type 'System.String'.'
in:
writer.WriteLine((string)GatheredProxies.Items[i]);
I am trying to add a feature into my application where users can choose the sheets from the comboBox. But I am hitting some bumps, I need some help! I was able to read the the excel file previously as I already sheet the default sheetname. But now I am able to get the sheetname into my comboBox, but I can't seem to read the excel file now? Please help me
public static DataTable ExcelToDataTable (string fileName)
{
using (var stream = File.Open(fileName, FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
var result = reader.AsDataSet(new ExcelDataSetConfiguration()
{
UseColumnDataType = true,
ConfigureDataTable = (data) => new ExcelDataTableConfiguration()
{
UseHeaderRow = true
}
});
DataTableCollection table = result.Tables;
DataTable resultTable = table["Sheet1"];
return resultTable;
}
}
}
private void btnOpen_Click(object sender, EventArgs e)
{
try
{
using (OpenFileDialog ofd = new OpenFileDialog() { Filter = "Excel 2003 Worksheet|*.xls|Excel 2007 Worksheet|*.xlsx", ValidateNames = true, Multiselect = false })
{
if (ofd.ShowDialog() == DialogResult.OK)
{
dataGridView1.DataSource = ExcelToDataTable(ofd.FileName);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
And Now
public static DataSet ExcelToDataTable (string fileName)
{
using (var stream = File.Open(fileName, FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
var result = reader.AsDataSet(new ExcelDataSetConfiguration()
{
UseColumnDataType = true,
ConfigureDataTable = (data) => new ExcelDataTableConfiguration()
{
UseHeaderRow = true
}
});
return result;
}
}
}
private void btnOpen_Click(object sender, EventArgs e)
{
try
{
using (OpenFileDialog ofd = new OpenFileDialog() { Filter = "Excel 2003 Worksheet|*.xls|Excel 2007 Worksheet|*.xlsx", ValidateNames = true, Multiselect = false })
{
if (ofd.ShowDialog() == DialogResult.OK)
{
comboBox1.Items.Clear();
foreach (DataTable dt in ExcelToDataTable(ofd.FileName).Tables)
{
comboBox1.Items.Add(dt.TableName);
}
DataTableCollection table = ExcelToDataTable(ofd.FileName).Tables;
DataTable resultTable = ExcelToDataTable(ofd.FileName).Tables[comboBox1.SelectedIndex];
dataGridView1.DataSource = resultTable
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
May I know what went wrong? I am getting an error of Cannot find table -1 but I can see the sheetname in the excel just not the content
At first use a DataSet property in your form:
private DataSet ExcelDateSet { get; set; }
And add a method to read a table from it like this:
private DataTable GetExcelDataTable(string sheetName)
{
if (string.IsNullOrEmpty(sheetName) || !ExcelDateSet.Tables.Contains(sheetName))
{
// Notify user to select a sheet-name from your ComboBox!
// or you can return first-sheet info as default like this:
// return ExcelDateSet.Tables[0];
}
return ExcelDateSet.Tables[sheetName];
}
then set its value in your btnOpen_Click like this:
ExcelDataSet = ExcelToDataTable(ofd.FileName);
dataGridView1.DataSource = GetExcelDataTable(comboBox1.SelectedText);
dataGridView1.DataBind();
I'm working on a Windows Form Application. Textbox index can be saved and shown as in ListBox with this code:
private List<FunctionData> funcParamList = new List<FunctionData>();
...
private void addFuncButton_Click(object sender, EventArgs e)
{
FunctionData funcParams = new FunctionData();
funcParams.blabla1name = blabla1.Text;
funcParams.blabla2name = blabla2.Text;
...
if (funcParams.isValid())
{
funcParamList.Add(funcParams);
functionListBox.Items.Add(functionNameBox.Text);
}
Also I collect objects to TextBox again to edit (by clicking ListBox item) with the following code :
private void getParams(FunctionData data)
{
blabla1.Text = data.blabla1name;
blabla2.Text = data.blabla2name;
functionNameBox.Text = data.functionName;
return;
}
private void functionListBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (functionListBox.SelectedItem == null) { return; }
foreach (var obj in funcParamList)
{
if (obj.functionName == functionListBox.SelectedItem.ToString())
{
getParams(obj);
}
}
}
And save them to file as JSON with:
private void saveFileButton_Click(object sender, EventArgs e)
{
fileName = fileNameBox.Text;
string jsonFunc = JsonConvert.SerializeObject(funcParamList);
System.IO.File.WriteAllText(#"<blablapath>\" + fileName + ".txt", jsonFunc);
}
There's 'functionName' object in JSON file that I can use it for showing on ListBox.
My question is: How can I load this file buy Native Load/Open File Dialog and show the objects in ListBox and can edit them again?
And here how I've tried to make it with the following code, but it doesn't work:
private void loadFileButton_Click(object sender, EventArgs e)
{
OpenFileDialog loadFileDialog = new OpenFileDialog();
...
if (loadFileDialog.ShowDialog() == DialogResult.OK)
{
string jsonFileName = loadFileDialog.FileName;
string jsonFile = File.ReadAllText(jsonFileName);
dynamic loadedFile = JsonConvert.DeserializeObject(jsonFile);
//if (functionListBox.SelectedItem == null) { return; }
foreach (var obj in loadedFile)
{
if (obj.functionName != null)
{
functionListBox.Items.Add(obj.functionName);
getParams(obj); // I get exception here
funcParamList.Add(loadedFile);
functionListBox.Refresh();
}
}
}
I've solved the problem by casting 'DeserializeObject' as List and it's done. Here the changes:
...
var loadedFile = JsonConvert.DeserializeObject<List<FunctionData>>(jsonFile);
So I'm accessing a DB through a stored procedure and am able to pull the data I wanted into a popup box. The problem now is that no matter what row I click on, the SAME data keeps populating my fields. How the heck can I choose a particular row, and have that specific row's data pulled from the DB? Thanks for any help
Form1
public partial class DSC_Mon : Form
{
DSCU_SvcConsumer.MTCaller Caller;
DataSet dsZA;
DataSet dsOut;
public DSC_Mon()
{
InitializeComponent();
Caller = new DSCU_SvcConsumer.MTCaller();
dsZA = new DataSet();
dsOut = new DataSet();
}
private void DSC_Mon_Load(object sender, EventArgs e)
{
timer1.Enabled = true;
}
private void LoadData()
{
if (!dsZA.Tables.Contains("Query"))
{
DataTable dtZA = dsZA.Tables.Add("Query");
dtZA.Columns.Add("str");
dtZA.Rows.Add(string.Format(#"exec MON_GetStatus"));
}
//dtZA.Rows.Add(string.Format(#"select * from am_company"));
dsOut.Clear();
dsOut.Merge(Caller.CallRequest("ZuluAction", dsZA));
if (gridEXMon.DataSource == null)
{
gridEXMon.DataSource = dsOut;
gridEXMon.DataMember = "Table";
}
//gridEXMon.RetrieveStructure();
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Enabled = false;
LoadData();
timer1.Enabled = true;
}
private void gridEXMon_DoubleClick(object sender, EventArgs e)
{
ReportInfo report = new ReportInfo();
report.ShowDialog();
}
}
I replaced the private void gridEXMon_DoubleClick with:
private void gridEXMon_RowDoubleClick(object sender, Janus.Windows.GridEX.RowActionEventArgs e)
{
if (e.Row.RowIndex < 0)
return;
int rowIndex = Convert.ToInt32(e.Row.RowIndex);
ReportInfo report = new ReportInfo(rowIndex);
report.ShowDialog();
}
Popup Dialog
public partial class ReportInfo : Form
{
public ReportInfo()
{
InitializeComponent();
DSCU_SvcConsumer.MTCaller caller = new DSCU_SvcConsumer.MTCaller();
DataSet dsZA = new DataSet();
DataSet dsOut = new DataSet();
if (!dsZA.Tables.Contains("Query"))
{
DataTable dtZA = dsZA.Tables.Add("Query");
dtZA.Columns.Add("str");
dtZA.Rows.Add(string.Format(#"MON_ReportInfo"));
}
dsOut.Clear();
dsOut.Merge(caller.CallRequest("ZuluAction", dsZA));
DataTable dt = dsOut.Tables["Table"];
DataRow dr = dt.Rows[0];
if (dt != null)
{
systemNameTextBox.Text = dr["System"].ToString();
contactName1TextBox.Text = dr["Manager"].ToString();
functionNameTextBox.Text = dr["Function"].ToString();
durationMSTextBox.Text = dr["Speed"].ToString();
}
}
I then sent the rowIndex to the popup:
DataTable dt = dsOut.Tables["Table"];
DataRow dr = dt.Rows[rowIndex];
systemNameTextBox.Text = dr["System"].ToString();
contactName1TextBox.Text = dr["Manager"].ToString();
functionNameTextBox.Text = dr["Function"].ToString();
durationMSTextBox.Text = dr["Speed"].ToString();
}
Better to get the data from the grid to save the extra call to the database in your ReportInfo class.
Here is the code:
private void gridEXMon_DoubleClick(object sender, EventArgs e)
{
if (e.Row.RowIndex < 0)
return;
ReportInfo report = new ReportInfo();
String System = Convert.ToInt32(e.Row.Cells["System"].Value);
String Manager = Convert.ToString(e.Row.Cells["Manager"].Value);
String Function = Convert.ToDecimal(e.Row.Cells["Function"].Value);
String Speed = Convert.ToInt32(e.Row.Cells["Speed"].Value);
report.ShowDialog(System, Manager, Function, Speed);
}
Then your ReportInfo class ctor should be:
public partial class ReportInfo : Form
{
public ReportInfo(String System, String Manager, String Function, String Speed)
{
InitializeComponent();
systemNameTextBox.Text = System;
contactName1TextBox.Text = Manager;
functionNameTextBox.Text = Function;
durationMSTextBox.Text = Speed;
}
}
Have you tried with:
gridEXMon.DataSource = dsOut.Tables[0];
// next line is not required if you've already defined proper grid structure
gridEXMon.RetrieveStructure();
Janus has also his own forum available here. You can find there a lot of useful information. For browsing I will use IE. Janus forum works good only with IE...
Edited:
How ReportInfo class can know what record have you selected? Especially that you have fallowing code:
DataTable dt = dsOut.Tables["Table"];
DataRow dr = dt.Rows[0]; // always first record is taken!
Probably you should define ctor with row index:
public ReportInfo(int rowIndex)
{
...
DataTable dt = dsOut.Tables["Table"];
DataRow dr = dt.Rows[rowIndex];
....
}