Unassigned local variables - c#

I bet these types of questions are the most common, however after trying what it said in a few other questions and still getting errors, I came here. I'm getting the following errors:
Use of unassigned local variable 'nodeRss'
Use of unassigned local variable 'nodeChannel'
class Program
{
static void Main(string[] args)
{
XmlTextReader rssReader;
XmlDocument rssDoc;
XmlNode nodeRss;
XmlNode nodeChannel;
String title;
String text;
HttpWebRequest http = WebRequest.Create("http://www.aerolitegaming.com/login/login") as HttpWebRequest;
http.KeepAlive = true;
http.Method = "POST";
http.AllowAutoRedirect = true;
http.ContentType = "application/x-www-form-urlencoded";
string postData="login=SNIP&register=0&password=SNIP&remember=1&cookie_check=0&redirect=forum%2F&_xfToken=";
byte[] dataBytes = UTF8Encoding.UTF8.GetBytes(postData);
http.ContentLength = dataBytes.Length;
using (Stream postStream = http.GetRequestStream())
{
postStream.Write(dataBytes, 0, dataBytes.Length);
}
HttpWebResponse httpResponse = http.GetResponse() as HttpWebResponse;
int y = (int)httpResponse.StatusCode;
http = WebRequest.Create("http://www.aerolitegaming.com/forum") as HttpWebRequest;
http.CookieContainer = new CookieContainer();
http.CookieContainer.Add(httpResponse.Cookies);
http.AllowAutoRedirect=false;
HttpWebResponse httpResponse2 = http.GetResponse() as HttpWebResponse;
rssReader = new XmlTextReader("http://aerolitegaming.com/forums/in-game-reports.132/index.rss");
rssDoc = new XmlDocument();
rssDoc.Load(rssReader);
// Loop for the <rss> tag
for (int i = 0; i < rssDoc.ChildNodes.Count; i++)
{
// If it is the rss tag
if (rssDoc.ChildNodes[i].Name == "rss")
{
// <rss> tag found
nodeRss = rssDoc.ChildNodes[i];
}
}
// Loop for the <channel> tag
for (int i = 0; i < nodeRss.ChildNodes.Count; i++)
{
// If it is the channel tag
if (nodeRss.ChildNodes[i].Name == "channel")
{
// <channel> tag found
nodeChannel = nodeRss.ChildNodes[i];
}
}
// Set the labels with information from inside the nodes
title = "Title: " + nodeChannel["title"].InnerText;
text = "Description: " + nodeChannel["description"].InnerText;
Console.WriteLine(title);
Console.WriteLine(text);
}
}

The nodeRss variable is an assigned in an if statement here:
if (rssDoc.ChildNodes[i].Name == "rss")
{
// <rss> tag found
nodeRss = rssDoc.ChildNodes[i];
}
I'm sure that you never fail to get into that if statement, and so you aren't worried about the lack of initialization. However, the compiler doesn't know that, and so is complaining that nodeRss is never assigned (because it isn't guaranteed to be).
In reality, I highly doubt you are actually guaranteed to get into that if statement, and so you should assign it a default value (null is ok) and check against that value before using the variable.
nodeChannel is running into the same problem.

Because you assign these variables values in a different scope { }.
To prevent the messages, simply give them values.
XmlNode nodeRss = null;
XmlNode nodeChannel = null;

It looks like the you are only assigning values to the two variables under certain conditions, which would lead to them not being set if those conditions have not been met.

Related

Unnecessary NullReferenceException? [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 3 years ago.
Why do I get a NullReferenceException in the following code?
private string FileR ( string name )
{
string[] content = ReadSite(name, Protocol.read, url);
Request_Template newCon;
string[] final = new string[content.Length];
for (int i = 0; i < content.Length; i++)
{
if (content[i].Equals(null))
{
return "content [" + i + "] returns null";
}
newCon = JsonSerializer.Deserialize<Request_Template>(content[i]);
if (newCon.Sender.Contains(myAccount.Username))
{
newCon.Sender = "Me";
}
string sender = newCon.Sender;
string message = newCon.Message;
final[i] = sender + ":\t" + message;
}
string nFinal = string.Concat(final);
Thread.Sleep(10);
return nFinal;
}
string[] ReadSite(string filename, Protocol p, string uri)
{
Read_Template temp = new Read_Template
{
Chat = filename,
Code = key1
};
string myUrl = JsonSerializer.Serialize(temp);
WebClient web = new WebClient();
Stream stream = web.OpenRead(uri + "/" + myUrl);
int length = 0;
while (new StreamReader(stream).ReadLine() != null)
{
length++;
}
string[] content = new string[length];
using (StreamReader reader = new StreamReader(stream))
{
for (int i = 0; i < length; i++)
{
content[i] = reader.ReadLine();
}
}
return content;
}
I've tried using the debugging tools with no avail. When I ran the code, it said that the error came from string [] final = new string [content.Length];
and for (int i = 0; i < content.Length; i++).That lead me to assume that content was null. But when I used the watch window and it said that the variable content cannot be determined. How do I fix this?
I strongly suspect that the problem is actually here:
if (content[i].Equals(null))
If content[i] is genuinely null, then calling content[i].Equals will throw a NullReferenceException. That test should be written as:
if (content[i] is null)`
Or (for C# 6 or older):
if (content[i] == null)`
Now if ReadSite didn't have a bug in, you shouldn't need that check at all - because ReadSite should return an array of non-null string references. However, the way that you're populating the array is broken. You're currently:
Creating a StreamReader around the stream
Reading from the reader until you run out of data
Creating a new array of the "right" length
Creating another StreamReader around the same stream - which is by now at the end
Reading from the reader however many times you read a line originally
Because the stream is already at the end, ReadLine() is going to return null on every iteration.
Instead, you should just read once, populating a list as you go, like this:
List<string> content = new List<string>();
using (var stream = web.OpenRead(uri + "/" + myUrl))
{
using (var reader = new StreamReader(stream))
{
string line;
while ((line = reader.ReadLine()) is object)
{
content.Add(line);
}
}
}
return content;
That's returning a List<string>, so you'd want to change your ReadSite return type to List<string> or perhaps IReadOnlyList<string>. If you really need it to return an array, you could return content.ToArray() instead.
(Ideally, move to using HttpClient as well, but that's a different story.)
private string FileR ( string name )
{
// ReadSite always returns a content that has length 0 or more. string[] content will never equals null.
// TEST: string[] test = new string[0]; test == null -> False
string[] content = ReadSite(name, Protocol.read, url);
Request_Template newCon;
string[] final = new string[content.Length];
// if content.Length == 0, this loop will never occur and you wont get any NREs.
for (int i = 0; i < content.Length; i++)
{
// It is highly unlikely that a reader.ReadLine() would generate a null but
// just in case it does, use == null instead of .Equals() method. When content[i] == null, you cannot use .Equals() method since nulls dont have Equals method.
if (content[i].Equals(null))
{
return "content [" + i + "] returns null";
}
// If you have checked that content[i] is Not empty space or null, you might
//end up with newCon == null if Deserialization fails. Cover this around try / catch.
newCon = JsonSerializer.Deserialize<Request_Template>(content[i]);
// If deserialization fails, this will throw NRE because nulls wont have
// Sender as a property or array. Check if newCon == null or not. Also,
// check if Sender was correctly initialized as an array/list.. as it could
// be null. nulls wont have Contains as a method.
if (newCon.Sender.Contains(myAccount.Username))
{
newCon.Sender = "Me";
}
string sender = newCon.Sender;
string message = newCon.Message;
// This should work correctly as its dependent on content.length. If the
// loop is happening, then there is at least one final element that can be updated.
final[i] = sender + ":\t" + message;
}
string nFinal = string.Concat(final);
Thread.Sleep(10);
return nFinal;
}

Web Scraping with c# and HTMLAgilityPack

Screenshot of the code and error message+variable values So, the goal is to take a word and get the part of speech of the word from its google definition.
I've tried a few different approaches but I'm getting a null reference error every time. Is my code failing to access the webpage? Is it a firewall issue, a logic issue, an {insert-issue-here} problem? I really wish i had a vague idea of what is wrong.
Thanks for your time.
Addendum: I've tried "//[#id=\"source - luna\"]//div" and "//[#id=\"source - luna\"]/div1" as XPath values.
//attempt 1////////////////////////////////////////////////////////////////////////
var term = "Hello";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.urbandictionary.com/define.php?term=" + term);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader stream = new StreamReader(response.GetResponseStream());
string final_response = stream.ReadToEnd();
MessageBox.Show(final_response); //doesn't execute
//attempt 2////////////////////////////////////////////////////////////////////////
var url = "https://www.google.co.za/search?q=define+position";
var content = new System.Net.WebClient().DownloadString(url);
var webGet = new HtmlWeb();
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(content);
//doc is null at runtime
HtmlNode ourNode = doc.DocumentNode.SelectSingleNode("//*[#id=\"uid_0\"]/div[1]/div/div[1]/div[2]/div[2]/div[1]/i/span");
if (ourNode != null)
{
richTextBox1.AppendText(ourNode.InnerText);
}
else
richTextBox1.AppendText("null");
//attempt 3////////////////////////////////////////////////////////////////////////
var webGet = new HtmlWeb();
var doc = webGet.Load("https://www.google.co.za/search?q=define+position");
//doc is null at runtime
HtmlNode ourNode = doc.DocumentNode.SelectSingleNode("//*[#id=\"uid_0\"]/div[1]/div/div[1]/div[2]/div[2]/div[1]/i/span");
if (ourNode != null)
{
richTextBox1.AppendText(ourNode.InnerText);
}
else
richTextBox1.AppendText("null");
//attempt 4////////////////////////////////////////////////////////////////////////
string Url = "http://www.metacritic.com/game/pc/halo-spartan-assault";
HtmlWeb web = new HtmlWeb();
HtmlAgilityPack.HtmlDocument doc = web.Load(Url);
//doc is null at runtime
string metascore = doc.DocumentNode.SelectNodes("//*[#id=\"main\"]/div[3]/div/div[2]/div[1]/div[1]/div/div/div[2]/a/span[1]")[0].InnerText;
string userscore = doc.DocumentNode.SelectNodes("//*[#id=\"main\"]/div[3]/div/div[2]/div[1]/div[2]/div[1]/div/div[2]/a/span[1]")[0].InnerText;
string summary = doc.DocumentNode.SelectNodes("//*[#id=\"main\"]/div[3]/div/div[2]/div[2]/div[1]/ul/li/span[2]/span/span[1]")[0].InnerText;
richTextBox1.AppendText(metascore + " " + userscore + " " + summary);
//attempt 5////////////////////////////////////////////////////////////////////////
HtmlWeb web = new HtmlWeb();
HtmlAgilityPack.HtmlDocument html = web.Load("https://www.google.co.za/search?q=define+position");
//html is null
var div = html.DocumentNode.SelectNodes("//*[#id=\"uid_0\"]/div[1]/div/div[1]/div[2]/div[2]/div[1]/i/span");
richTextBox1.AppendText(Convert.ToString(div));
You are getting null because your XPATHs aren't correct or it couldn't find any node based on those XPATHs. What are you trying to achieve here?

Accessing xmlNodeList with partial namespaces(Xpath)

I have been digging through every example I can find related to Xpath and XML parsing. I can't find a close enough example to the XML I have to deal with that makes any sense to me. I am having an extremely difficult time wrapping my head around Xpath in particular but also XML parsing in a more general sense. The complexity of the file I'm working with is not making it easier to understand.
I have an XML file coming from a remote source which I have no control over.
The file is:
<AssetWarrantyDTO xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Dell.Support.AssetsExternalAPI.Web.Models.V1.Response">
<AdditionalInformation i:nil="true"/>
<AssetWarrantyResponse>
<AssetWarrantyResponse>
<AssetEntitlementData>
<AssetEntitlement>
<EndDate>2010-12-20T23:59:59</EndDate>
<EntitlementType>EXTENDED</EntitlementType>
<ItemNumber>983-4252</ItemNumber>
<ServiceLevelCode>ND</ServiceLevelCode>
<ServiceLevelDescription>Next Business Day Onsite</ServiceLevelDescription>
<ServiceLevelGroup>5</ServiceLevelGroup>
<ServiceProvider>UNY</ServiceProvider>
<StartDate>2008-12-21T00:00:00</StartDate>
</AssetEntitlement>
<AssetEntitlement>
<EndDate>2010-12-20T23:59:59</EndDate>
<EntitlementType>EXTENDED</EntitlementType>
<ItemNumber>987-1139</ItemNumber>
<ServiceLevelCode>TS</ServiceLevelCode>
<ServiceLevelDescription>ProSupport</ServiceLevelDescription>
<ServiceLevelGroup>8</ServiceLevelGroup>
<ServiceProvider>DELL</ServiceProvider>
<StartDate>2008-12-21T00:00:00</StartDate>
</AssetEntitlement>
<AssetEntitlement>
<EndDate>2008-12-20T23:59:59</EndDate>
<EntitlementType>INITIAL</EntitlementType>
<ItemNumber>984-0210</ItemNumber>
<ServiceLevelCode>ND</ServiceLevelCode>
<ServiceLevelDescription>Next Business Day Onsite</ServiceLevelDescription>
<ServiceLevelGroup>5</ServiceLevelGroup>
<ServiceProvider>UNY</ServiceProvider>
<StartDate>2007-12-20T00:00:00</StartDate>
</AssetEntitlement>
<AssetEntitlement>
<EndDate>2008-12-20T23:59:59</EndDate>
<EntitlementType>INITIAL</EntitlementType>
<ItemNumber>987-1308</ItemNumber>
<ServiceLevelCode>TS</ServiceLevelCode>
<ServiceLevelDescription>ProSupport</ServiceLevelDescription>
<ServiceLevelGroup>8</ServiceLevelGroup>
<ServiceProvider>DELL</ServiceProvider>
<StartDate>2007-12-20T00:00:00</StartDate>
</AssetEntitlement>
</AssetEntitlementData>
<AssetHeaderData>
<BUID>11</BUID>
<CountryLookupCode>US</CountryLookupCode>
<CustomerNumber>64724056</CustomerNumber>
<IsDuplicate>false</IsDuplicate>
<ItemClassCode>`U060</ItemClassCode>
<LocalChannel>17</LocalChannel>
<MachineDescription>Precision T3400</MachineDescription>
<OrderNumber>979857987</OrderNumber>
<ParentServiceTag i:nil="true"/>
<ServiceTag>7P3VBU1</ServiceTag>
<ShipDate>2007-12-20T00:00:00</ShipDate>
</AssetHeaderData>
<ProductHeaderData>
<LOB>Dell Precision WorkStation</LOB>
<LOBFriendlyName>Precision WorkStation</LOBFriendlyName>
<ProductFamily>Desktops & All-in-Ones</ProductFamily>
<ProductId>precision-t3400</ProductId>
<SystemDescription>Precision T3400</SystemDescription>
</ProductHeaderData>
</AssetWarrantyResponse>
</AssetWarrantyResponse>
<ExcessTags>
<BadAssets xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
</ExcessTags>
<InvalidBILAssets>
<BadAssets xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
</InvalidBILAssets>
<InvalidFormatAssets>
<BadAssets xmlns:d3p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
</InvalidFormatAssets>
</AssetWarrantyDTO>
Here is the Final code not including the setting of the URI variable for the API URL.
protected void Unnamed1_Click(object sender, EventArgs e)
{
string Serial = TextBox1.Text.ToUpper();
URI = String.Format(URI, Serial);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URI);
request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3";
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
CookieContainer aCookie = new CookieContainer();
request.CookieContainer = aCookie;
WebResponse pageResponse = request.GetResponse();
Stream responseStream = pageResponse.GetResponseStream();
string xml = string.Empty;
using (StreamReader streamRead = new StreamReader(responseStream))
{
xml = streamRead.ReadToEnd();
}
XmlDocument doc1 = new XmlDocument();
doc1.LoadXml(xml);
string _byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
if (xml.StartsWith(_byteOrderMarkUtf8))
{
var lastIndexOfUtf8 = _byteOrderMarkUtf8.Length - 1;
xml = xml.Remove(0, lastIndexOfUtf8);
//Label2.Text = "BOM found.";
}
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc1.NameTable);
nsmgr.AddNamespace("j", "http://schemas.datacontract.org/2004/07/Dell.Support.AssetsExternalAPI.Web.Models.V1.Response");
XmlNodeList nodes = doc1.SelectNodes(".//j:AssetWarrantyResponse/j:AssetWarrantyResponse/j:AssetEntitlementData", nsmgr);
//Make a list to hold the start dates
System.Collections.ArrayList startDates = new System.Collections.ArrayList();
//Make a list to hold the end dates
System.Collections.ArrayList endDates = new System.Collections.ArrayList();
//Create a regex for finding just the date and discarding the time value which can alter tha date if the time is 24:00 (euro standard)
Regex r = new Regex(#"\d{4}-\d{1,2}-\d{1,2}", RegexOptions.IgnoreCase);
//Set the culture to format the date as US region
CultureInfo dtFormat = new CultureInfo("en-US", false);
foreach (XmlNode node in nodes)
{
foreach (XmlNode childNode in node.ChildNodes)
{
string startDate = childNode["StartDate"].InnerText;
if (startDate != null)
{
MatchCollection mcl1 = r.Matches(startDate);
startDates.Add(DateTime.Parse(mcl1[0].ToString(), dtFormat));
}
string endDate = childNode["EndDate"].InnerText;
if (endDate != null)
{
MatchCollection mcl2 = r.Matches(endDate);
endDates.Add(DateTime.Parse(mcl2[0].ToString(), dtFormat));
}
}
startDates.Sort();
endDates.Sort();
DateTime wStartDate = new DateTime();
DateTime wEndDate = new DateTime();
//if (dates.Count > 1) wStartDate = (DateTime)dates[dates.Count - 1];
if (startDates.Count >= 1) wStartDate = (DateTime)startDates[0];
Label1.Text = wStartDate.ToString("MM/dd/yyyy");
if (endDates.Count >= 1) wEndDate = (DateTime)endDates[endDates.Count - 1];
Label2.Text = wEndDate.ToString("MM/dd/yyyy");
//Label2.Text = tempc;
//Label3.Text = feels;
}
nodes = doc1.SelectNodes(".//j:AssetWarrantyResponse/j:AssetWarrantyResponse/j:AssetHeaderData", nsmgr);
foreach (XmlNode node in nodes)
{
try
{
string custNumber = node["CustomerNumber"].InnerText;
string model = node["MachineDescription"].InnerText;
string orderNumber = node["OrderNumber"].InnerText;
string serialNumber = node["ServiceTag"].InnerText;
Label3.Text = custNumber;
Label4.Text = model;
Label5.Text = orderNumber;
Label6.Text = serialNumber;
}
catch (Exception ex)
{
dbgLabel.Text = ex.Message;
}
}
}
You are looking for AssetWarrantyResponse in namespace http://www.w3.org/2001/XMLSchema-instance (the namespace you have bound to prefix "i") but it is actually in namespace http://schemas.datacontract.org/2004/07/Dell.Support.AssetsExternalAPI.Web.Models.V1.Response. Bind a prefix to that namespace (anything will do, e.g "p") and use that prefix in your query, e.g. p:AssetWarrantyResponse, and similarly for other element names.
I wonder if you are spending too much time trying to look for example code that exactly matches what you want to do, and not enough time studying the underlying concepts of the language so that you can apply them to your own problems. Get some good XML books and read them.
There's another problem with your XPath, which is the "/" at the end of the path. That's invalid syntax. If that's the cause of the error then I'm not very impressed with your XPath processor's diagnostics.

How do i get all the text from the string in a loop and not only once?

I have this code:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
WebRequest request = WebRequest.Create(url);
request.Method = "GET";
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
string content = reader.ReadToEnd();
reader.Close();
response.Close();
}
Now i have two functions:
private void GetProfileNames(string text)
{
string startTag = "<a href='/profile/";
string endTag = "'>";
int startTagWidth = startTag.Length;
int endTagWidth = endTag.Length;
index = 0;
while (true)
{
index = text.IndexOf(startTag, index);
if (index == -1)
{
break;
}
// else more to do - index now is positioned at first character of startTag
int start = index + startTagWidth;
index = text.IndexOf(endTag, start + 1);
if (index == -1)
{
break;
}
// found the endTag
profileName = text.Substring(start, index - start);
}
return profileName;
}
private void GetTextFromProfile(string text)
{
string str = "<span class=\"message-text\">";
string startTag = str;
string endTag = "<";
int startTagWidth = startTag.Length;
int endTagWidth = endTag.Length;
index = 0;
while (true)
{
index = text.IndexOf(startTag, index);
if (index == -1)
{
break;
}
// else more to do - index now is positioned at first character of startTag
int start = index + startTagWidth;
index = text.IndexOf(endTag, start + 1);
if (index == -1)
{
break;
}
// found the endTag
profileNameText = text.Substring(start, index - start);
}
return profileNameText;
}
Now after the string content line in the DoWork event i called the function: GetProfileNames but when im using a breakpoint on the line: profileNameText = text.Substring(start, index - start); im getting the same profile name all the time i need to close the program run it again.
What i want it to do is when im calling the function in the Dowork event it will make the GetProFileNames function to the end and get all the profile names from the current content that have been downloaded.
Somehow i need to call the both functions: GetProfileNames and GetTextFromProfile and i need to create a string of each profile and the text that belong to him.
For example i have this line in the content variable:
<span class="message-profile-name" ><a href='/profile/LipazD'>LipazD</a></span>: <span class="message-text">hello world</span>
So I need that the both functions will loop over the content and each time there was itertion i will get a string like string t = "LipazD hello world"
Next itertion will be: "Daniel how are you ?"
The functions work they get the profile name and the second one get the text but i dont know how ot make itertion loop and to get it all to work.
Then when it finish to loop over the content and get all profile names and text for each profile name i need to delete the content and download again a new content and then do it again with the functions finished delete content or just download a new content and so on over and over again.
HtmlDocument doc = new HtmlDocument();
WebClient wc = new WebClient();
doc.Load(wc.DownloadString("http://yourUri.com"));
foreach(HtmlNode link in doc.DocumentElement.SelectNodes("//span[#class='message-profile-name'"])
{
// etc.
}
but i think that message-profile-name and message-text are wrapped in a parent element. I recommend looping over that element and then get the child profilename and comment span content
var wc = new WebClient();
wc.DownloadStringCompleted += (s, e) =>
{
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(e.Result);
var link = doc.DocumentNode
.SelectSingleNode("//span[#class='message-profile-name']")
.Element("a")
.Attributes["href"].Value;
};
wc.DownloadStringAsync(new Uri("http://chatroll.com/rotternet"));

null reference on excel doc C#

Hi I keep getting this error from the below code, was wondering if anyone can help.
error processing excel file: cannot perform runtime binding on a null reference
Code:
private void Import_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
// Open document
string filename = dlg.FileName;
Microsoft.Office.Interop.Excel.Application vExcelObj = new Microsoft.Office.Interop.Excel.Application();
try
{
Microsoft.Office.Interop.Excel.Workbook theWorkbook = vExcelObj.Workbooks.Open(filename, Type.Missing, true);
Microsoft.Office.Interop.Excel.Worksheet sheet = theWorkbook.Worksheets[1];
string vFirstName = "temp";
string vLastName = "temp";
int vIndex = 1;
while (vFirstName != "")
{
// Change the letters of the appropriate columns here!
// In my example, 'A' is first name, 'B' last name
vFirstName = sheet.get_Range("A" + vIndex.ToString()).Value.ToString(); // if i take out the exception handling the error is on this line
vLastName = sheet.get_Range("B" + vIndex.ToString()).Value.ToString();
this.SaveNewCustomer(vFirstName, vLastName);
vIndex++;
}
}
catch (Exception ex)
{
MessageBox.Show("Error processing excel file : " + ex.Message);
}
finally
{
vExcelObj.Quit();
}
}
}
private void SaveNewCustomer(string firstName, string lastName)
{
string uri = "http://localhost:8002/Service/Customer";
StringBuilder sb = new StringBuilder();
sb.Append("<Customers>");
sb.AppendLine("<FirstName>" + firstName + "</FirstName>");
sb.AppendLine("<LastName>" + lastName + "</LastName>");
sb.AppendLine("</Customers>");
string NewStudent = sb.ToString();
byte[] arr = Encoding.UTF8.GetBytes(NewStudent);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
req.Method = "POST";
req.ContentType = "application/xml";
req.ContentLength = arr.Length;
Stream reqStrm = req.GetRequestStream();
reqStrm.Write(arr, 0, arr.Length);
reqStrm.Close();
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
reqStrm.Close();
resp.Close();
}
}
The code just takes a excel document and trys to send the data to my web service.
So I tryed using the below method but it freezes the application :S no error just hangs.
Edit attempt:
while (vFirstName != "")
{
var columnACell = sheet.get_Range("A" + vIndex.ToString());
var columnBCell = sheet.get_Range("B" + vIndex.ToString());
var columnACellValue = columnACell.Value;
var columnBCellValue = columnBCell.Value;
if (columnACellValue != null && columnBCellValue != null)
{
vFirstName = columnACellValue.ToString();
vLastName = columnBCellValue.ToString();
this.SaveNewStaff(vFirstName, vLastName); //, vPassword
vIndex++;
}
}
}
EDIT 2
Just took the code, and stepped through it. Found the problem. I think I misunderstood what was happening originally.
What's happening is that the loop while (vFirstName != "") will keep going until vFirstName is an empty string. But this will never happen! Here's why:
Everything will be fine as long as columns A and B will have values. The code will behave as expected.
When the code gets to an Excel row that doesn't have a value, it hits an empty cell, which will have .Value set to null. This causes the exception.
So the real solution here is to have the loop keep going until it hits a cell with a null value, and then exit. Kind of like this:
while (true) {
// Split the satements
var columnACell = sheet.get_Range("A" + vIndex.ToString());
var columnBCell = sheet.get_Range("B" + vIndex.ToString());
var columnACellValue = columnACell.Value;
var columnBCellValue = columnBCell.Value;
if (columnACellValue != null && columnBCellValue != null) {
vFirstName = columnACellValue.ToString();
vLastName = columnBCellValue.ToString();
} else {
break;
}
this.SaveNewCustomer(vFirstName, vLastName);
vIndex++;
};
Just tested this on my end, and it seems to work.
On a separate note, make sure that you're fully quitting Excel, because calling Excel.Quit() is often not enough. Open Task Manager and check whether there are any extra instances of EXCEL.exe floating around. To prevent those I usually kill Excel after I'm done with it (easier than properly releasing Excel's COM objects), as described in this post.
ORIGINAL POST
It sounds like there are a few options here:
The cell is empty, which means that it's .Value will be null.
The sheet is null,
get_Range() returns null -- that sounds unlikely.
Split the line into separate statements and see which one of them throws an error. That will tell you where to look further.
Judging by what you're doing -- searching the column until you find first name -- it sounds like you're running into nulls inside the cells' Values. To deal with that, I usually add a quick if-statement to test Value for null.
EDIT
Here's an example (may not compile) that will hopefully fix null values inside the cells and help to pinpoint other null-related problems. Replace the offending lines with something like this:
var columnACell = sheet.get_Range("A" + vIndex.ToString());
var columnBCell = sheet.get_Range("B" + vIndex.ToString())
var columnACellValue = columnACell.Value;
var columnBCellValue = columnBCell.Value;
if (columnACellValue != null && columnBCellValue != null) {
vFirstName = columnACellValue.ToString();
vLastName = columnBCellValue.ToString();
}
Note that I assume that your C# compiler supports implicit static typing through var.
Sheet is null. Perhaps there is only 1 worksheet? You're using Worksheets[1] which returns the second one, of course.. :)
Try to split the code that reads the value and test if it is null.
object oName = sheet.get_Range("A" + vIndex.ToString()).Value;
vFirstName = (oName == null ? string.Empty : oName.ToString();
object oLast = sheet.get_Range("B" + vIndex.ToString()).Value;
vLastName = (oLast == null ? string.Empty : oLast.ToString());
if(vFirstName.Length > 0 && vLastName.Length > 0)
this.SaveNewCustomer(vFirstName, vLastName);
And noticed that in your SaveNewStaff/Customer(....) you close the RequestStream two times.
Perhaps the second close freeze your code.
reqStrm.Close();
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
reqStrm.Close(); // <= Already closed before?

Categories