Get bookmark coordinates in PDF - c#

I'm working in placing signature image to PDF at exact place. In PDF I add with report tool bookmark so I could know where to place signature image. Problem is I don't know how to get bookmark coordinates. Is it with ITextsharp possible?
------>EDIT
Picture of bookmark
----->EDIT
Solution is:
PdfReader pdfReader = new PdfReader(GlobalVars.PdfFile);
IList<Dictionary<string, object>> bookmarks = SimpleBookmark.GetBookmark(pdfReader);
string BookmarkID = "";
for (int j = 0; j < bookmarks.Count; j++)
{
//MessageBox.Show(bookmarks[i].Values.ToArray().GetValue(0).ToString());
string s = bookmarks[j].Values.ToArray().GetValue(0).ToString();
if (bookmarks[j].Values.ToArray().GetValue(0).ToString() == "##PODPIS##")
{
BookmarkID = bookmarks[j].Values.ToArray().GetValue(1).ToString();
}
}
var map = SimpleNamedDestination.GetNamedDestination(pdfReader, true);
foreach (KeyValuePair<string, string> entry in map)
{
if (entry.Key.ToString() == BookmarkID)
{
string[] LocationArray = entry.Value.Split(null);
GlobalVars.SignatuePageNumber = Convert.ToInt32(LocationArray[0]);
GlobalVars.SignatureX = float.Parse(LocationArray[2], CultureInfo.InvariantCulture.NumberFormat);
GlobalVars.SignatureY = float.Parse(LocationArray[3], CultureInfo.InvariantCulture.NumberFormat);
}
}

Solution is:
PdfReader pdfReader = new PdfReader(GlobalVars.PdfFile);
IList<Dictionary<string, object>> bookmarks = SimpleBookmark.GetBookmark(pdfReader);
string BookmarkID = "";
for (int j = 0; j < bookmarks.Count; j++)
{
//MessageBox.Show(bookmarks[i].Values.ToArray().GetValue(0).ToString());
string s = bookmarks[j].Values.ToArray().GetValue(0).ToString();
if (bookmarks[j].Values.ToArray().GetValue(0).ToString() == "##PODPIS##")
{
BookmarkID = bookmarks[j].Values.ToArray().GetValue(1).ToString();
}
}
var map = SimpleNamedDestination.GetNamedDestination(pdfReader, true);
foreach (KeyValuePair<string, string> entry in map)
{
if (entry.Key.ToString() == BookmarkID)
{
string[] LocationArray = entry.Value.Split(null);
GlobalVars.SignatuePageNumber = Convert.ToInt32(LocationArray[0]);
GlobalVars.SignatureX = float.Parse(LocationArray[2], CultureInfo.InvariantCulture.NumberFormat);
GlobalVars.SignatureY = float.Parse(LocationArray[3], CultureInfo.InvariantCulture.NumberFormat);
}
}

Related

CSharp Generate polygons from a set of intersecting lines

https://gis.stackexchange.com/questions/58245/generate-polygons-from-a-set-of-intersecting-lines
https://i.stack.imgur.com/UUyHF.png
https://i.stack.imgur.com/3ClRI.png
I want to find the bounding polygon like this link.
I'm using C# nettopologysuite like the jts library shown in this link, but the polygon I want doesn't come out.
How can I extract polygons?
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptEntityOptions pEntOpt1 = new PromptEntityOptions("Outter Boundary");
pEntOpt1.SetRejectMessage("is Not Polyline");
pEntOpt1.AddAllowedClass(typeof(Polyline), true);
PromptEntityResult pEntRes1 = ed.GetEntity(pEntOpt1);
string typeName = RXObject.GetClass(typeof(Polyline)).DxfName;
TypedValue[] tv = new TypedValue[1] { new TypedValue((int)DxfCode.Start, typeName) };
SelectionFilter sf = new SelectionFilter(tv);
PromptSelectionResult pSelectRes = ed.GetSelection(sf);
if (pSelectRes.Status != PromptStatus.OK)
return;
ObjectId boudaryPlineId = pEntRes1.ObjectId;
ObjectId[] innerPlineids = pSelectRes.Value.GetObjectIds();
ObjectIdCollection innerBoundaries = new ObjectIdCollection(innerPlineids);
try
{
using (doc.LockDocument())
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Polygonizer polygonizer = new Polygonizer();
GeometryFactory gf = new GeometryFactory();
Polyline boundaryPline = tr.GetObject(boudaryPlineId, OpenMode.ForWrite) as Polyline;
Coordinate[] coords = new Coordinate[boundaryPline.NumberOfVertices + 1];
for (int j = 0; j < boundaryPline.NumberOfVertices; j++)
{
Point3d pos = boundaryPline.GetPoint3dAt(j);
coords[j] = new Coordinate(pos.X, pos.Y);
}
coords[boundaryPline.NumberOfVertices] = new Coordinate(boundaryPline.StartPoint.X, boundaryPline.StartPoint.Y);
Polygon pg = gf.CreatePolygon(coords);
List<Geometry> plines = new List<Geometry>();
foreach (ObjectId indexid in innerBoundaries)
{
Polyline indexPline = tr.GetObject(indexid, OpenMode.ForWrite) as Polyline;
Coordinate[] coords2 = new Coordinate[indexPline.NumberOfVertices];
for (int i = 0; i < indexPline.NumberOfVertices; i++)
{
Point3d pos = indexPline.GetPoint3dAt(i);
coords2[i] = new Coordinate(pos.X, pos.Y);
}
LineString ls1 = new LineString(coords2);
polygonizer.Add(ls1);
}
ICollection<Geometry> test = polygonizer.GetPolygons();
foreach (Geometry polygon in test)
{
// to do
}
tr.Commit();
}
}
}
catch
{
}
outter Boundary
inner Boundary
The Red Polygon I want to find
This is my second question in English, so please understand the lack of expression.
-------------- After applying the answer below --------------
private List<NetGeometry> GetPolygons(Transaction tr, List<LineString> lineStrings)
{
List<NetGeometry> polygons = new List<NetGeometry>();
Polygonizer polygonizer = new Polygonizer(false);
GeometryFactory gf = new GeometryFactory(new PrecisionModel(10000));
var noder = new SnapRoundingNoder(new PrecisionModel(10000)); // adjust PrecisionModel to your needs, must be fixed.
noder.ComputeNodes(lineStrings.Select(s => (ISegmentString)new NodedSegmentString(s.Coordinates, s)).ToList());
var noded = noder.GetNodedSubstrings();
polygonizer.Add(noded.Select(n => (Geometry)gf.CreateLineString(n.Coordinates)).ToList());
//for ( int i = 0; i < lineStrings.Count; i++)
//{
// polygonizer.Add(lineStrings[i]);
//}
ICollection<NetGeometry> result = polygonizer.GetPolygons();
foreach (NetGeometry index in result)
{
if ( index is Polygon pg)
{
polygons.Add(pg);
}
}
return polygons;
}
Results after application
All input geometries to Polygonizer should be LineStrings.
The whole input set of LineStrings must be fully noded:
var noder = new SnapRoundingNoder(new PrecisionModel(1000)); // adjust PrecisionModel to your needs, must be fixed.
noder.ComputeNodes(lines.Select(s => (ISegmentString)new NodedSegmentString(s.Coordinates, s)).ToList());
var noded = noder.GetNodedSubstrings();
polygonizer.Add(noded.Select(n => (Geometry)gf.CreateLineString(n.Coordinates)).ToList());

using Aspose Words to replace page numbers with barcodes

this may be a silly question but I cannot work out an answer to it and after a day I am turning to the community at large for help...
I am using Aspose for Word (C# or .Net) and I am trying to replace the generated page numbering for barcode images of my own creation. I can use fonts to do it currently but I have found they are less reliable with my barcode reader and thus need to be able to read the value from the page numbering and replace it with an image of my own creation.
So really I need to find the numbering container, read the value in it and replace it. Once I have that creating the barcode and inserting it is easy.
Can anyone help?
The current method (sorry its messy but i keep trying new things):
internal static void SetFooters(ref Document doc)
{
doc.FirstSection.HeadersFooters.LinkToPrevious(false);
var builder = new DocumentBuilder(doc);
builder.MoveToDocumentStart();
Section currentSection = builder.CurrentSection;
PageSetup pageSetup = currentSection.PageSetup;
int totalPages = doc.PageCount;
int j = 1;
foreach (Section sect in doc.Sections)
{
//Loop through all headers/footers
foreach (HeaderFooter hf in sect.HeadersFooters)
{
if (
hf.HeaderFooterType == HeaderFooterType.FooterPrimary || hf.HeaderFooterType == HeaderFooterType.FooterEven || hf.HeaderFooterType == HeaderFooterType.FooterFirst)
{
builder.MoveToHeaderFooter(hf.HeaderFooterType);
Field page = builder.InsertField("PAGE");
builder.Document.UpdatePageLayout();
try
{
page.Update();
}
catch { }
int pageNumber = j;
if (int.TryParse(page.Result, out pageNumber))
{ j++; }
// Remove PAGE field.
page.Remove();
builder.Write(string.Format("{0}/{1}", pageNumber, totalPages));
}
}
}
}
HeaderFooter is a section-level node and can only be a child of Section. The page field inside the header/footer returns the latest updated value and it will be same value for all pages of a section.
In your case, I suggest you to insert text-box at the top/bottom of each page and inset the desired contents in it. Following code example inserts the text-box on each page of document and insert page field and some text in it. Hope this helps you.
public static void InsertTextBoxAtEachPage()
{
string filePathIn = MyDir + #"input.docx";
string filePathOut = MyDir + #"output.docx";
Document doc = new Document(filePathIn);
DocumentBuilder builder = new DocumentBuilder(doc);
LayoutCollector collector = new LayoutCollector(doc);
int pageIndex = 1;
foreach (Section section in doc.Sections)
{
NodeCollection paragraphs = section.Body.GetChildNodes(NodeType.Paragraph, true);
foreach (Paragraph para in paragraphs)
{
if (collector.GetStartPageIndex(para) == pageIndex)
{
builder.MoveToParagraph(paragraphs.IndexOf(para), 0);
builder.StartBookmark("BM_Page" + pageIndex);
builder.EndBookmark("BM_Page" + pageIndex);
pageIndex++;
}
}
}
collector = new LayoutCollector(doc);
LayoutEnumerator layoutEnumerator = new LayoutEnumerator(doc);
const int PageRelativeY = 0;
const int PageRelativeX = 0;
foreach (Bookmark bookmark in doc.Range.Bookmarks)
{
if (bookmark.Name.StartsWith("BM_"))
{
Paragraph para = (Paragraph)bookmark.BookmarkStart.ParentNode;
Shape textbox = new Shape(doc, Aspose.Words.Drawing.ShapeType.TextBox);
textbox.Top = PageRelativeY;
textbox.Left = PageRelativeX;
int currentPageNumber = collector.GetStartPageIndex(para);
string barcodeString = string.Format("page {0} of {1}", currentPageNumber, doc.PageCount);
string barcodeEncodedString = "some barcode string";
Paragraph paragraph = new Paragraph(doc);
ParagraphFormat paragraphFormat = paragraph.ParagraphFormat;
paragraphFormat.Alignment = ParagraphAlignment.Center;
Aspose.Words.Style paragraphStyle = paragraphFormat.Style;
Aspose.Words.Font font = paragraphStyle.Font;
font.Name = "Tahoma";
font.Size = 12;
paragraph.AppendChild(new Run(doc, barcodeEncodedString));
textbox.AppendChild(paragraph);
paragraph = new Paragraph(doc);
paragraphFormat = paragraph.ParagraphFormat;
paragraphFormat.Alignment = ParagraphAlignment.Center;
paragraphStyle = paragraphFormat.Style;
font = paragraphStyle.Font;
font.Name = "Arial";
font.Size = 10;
paragraph.AppendChild(new Run(doc, barcodeString));
textbox.AppendChild(paragraph);
//Set the width height according to your requirements
textbox.Width = doc.FirstSection.PageSetup.PageWidth;
textbox.Height = 50;
textbox.BehindText = false;
para.AppendChild(textbox);
textbox.RelativeHorizontalPosition = Aspose.Words.Drawing.RelativeHorizontalPosition.Page;
textbox.RelativeVerticalPosition = Aspose.Words.Drawing.RelativeVerticalPosition.Page;
bool isInCell = bookmark.BookmarkStart.GetAncestor(NodeType.Cell) != null;
if (isInCell)
{
var renderObject = collector.GetEntity(bookmark.BookmarkStart);
layoutEnumerator.Current = renderObject;
layoutEnumerator.MoveParent(LayoutEntityType.Cell);
RectangleF location = layoutEnumerator.Rectangle;
textbox.Top = PageRelativeY - location.Y;
textbox.Left = PageRelativeX - location.X;
}
}
}
doc.Save(filePathOut, SaveFormat.Docx);
}
I work with Aspose as Developer evangelist.

Strike through a word in a string PowerPoint interop

I have 2 PowerPoints one original and one edited. I each PowerPoint I have a textbox that contains a number of words. The idea is to find any words added or deleted from the original PowerPoint in the edited and put them in a list. I then want to put a strike though these words that have been added or deleted but I can't access any of the properties I need as I have a string and not a TextFrame. Any ideas how I could strike through the words? E.g original "This Text" edited "This New Text" outcome "This New Text".
My code is as fallows
List<int> originalShapesListID = new List<int>();
List<int> editedShapesListID = new List<int>();
List<int> originalListID = new List<int>();
List<int> editedListID = new List<int>();
List<Microsoft.Office.Interop.PowerPoint.Shape> originalList = new List<Microsoft.Office.Interop.PowerPoint.Shape>();
List<Microsoft.Office.Interop.PowerPoint.Shape> editList = new List<Microsoft.Office.Interop.PowerPoint.Shape>();
Microsoft.Office.Interop.PowerPoint.Shape editedShpID;
List<Microsoft.Office.Interop.PowerPoint.Shape> originalListWords = new List<Microsoft.Office.Interop.PowerPoint.Shape>();
List<char> editListWords = new List<char>();
editedShpID = null;
Microsoft.Office.Interop.PowerPoint.Shape originalShpID;
long editedShapeID;
long originalShapeID;
editedShapeID = 0;
originalShapeID = 0;
originalShpID = null;
originalShp = null;
editShp = null;
Microsoft.Office.Interop.PowerPoint.TextFrame txtFrame;
char delimiter = Convert.ToChar(" ");
List<string> one = new List<string>();
List<string> two = new List<string>();
int indexOfWord = 0;
Getting all Text
String pps = "";
foreach (Microsoft.Office.Interop.PowerPoint.Slide slide in Originalslides)
{
foreach (Microsoft.Office.Interop.PowerPoint.Shape originalShape in slide.Shapes)
{
originalShp = originalShape;
if (originalShape.HasTextFrame == Microsoft.Office.Core.MsoTriState.msoTrue)
{
var textFrame = originalShape.TextFrame;
if (textFrame.HasText == Microsoft.Office.Core.MsoTriState.msoTrue)
{
var textRange = textFrame.TextRange;
pps += originalShape.TextFrame.TextRange.Text;
foreach (char word in pps)
{
l.Add(word);
Debug.WriteLine(word);
}
}
}
originalShapesListID.Add(originalShape.Id);
originalShapeID = originalShape.Id;
originalList.Add(originalShape);
}
originalListID.Add(slide.SlideID);
}
foreach (Microsoft.Office.Interop.PowerPoint.Slide slide in EditedSlides)
{
foreach (Microsoft.Office.Interop.PowerPoint.Shape editShape in slide.Shapes)
{
editShp = editShape;
if (editShape.HasTextFrame == Microsoft.Office.Core.MsoTriState.msoTrue)
{
var textFrame = editShape.TextFrame;
if (textFrame.HasText == Microsoft.Office.Core.MsoTriState.msoTrue)
{
var textRange = textFrame.TextRange;
pps += editShape.TextFrame.TextRange.Text;
foreach (char word in pps)
{
l.Add(word);
Debug.WriteLine(word);
}
}
}
editedShapesListID.Add(editShape.Id);
editedShapeID = editShape.Id;
editList.Add(editShape);
}
editedListID.Add(slide.SlideID);
}
Checking if there is an added or deleted word
var q = from original in originalList
join editedTmp in editList on original.Id equals editedTmp.Id into g
from edited in g.DefaultIfEmpty()
select new
{
original,
edited
};
//foreach through both lists
foreach (var item in q)
{
List<string> diff;
var originalString = item.original.TextFrame.TextRange.Text;
var editString = item.edited.TextFrame.TextRange.Text;
var firstStringList = originalString.Split(delimiter).ToList();
var secondStringList = editString.Split(delimiter).ToList();
if (secondStringList.Count() > firstStringList.Count())
{
diff = secondStringList.Except(firstStringList).ToList();
//change to blue for added word
}
else
{
diff = firstStringList.Except(secondStringList).ToList();
// change to red for deleted word
}
}
Updates section
foreach (var word in firstStringList)
{
//check if word matches
if (secondStringList.IndexOf(word, indexOfWord) == -1)
{
// add word to second string in the correct position
secondStringList.Insert(indexOfWord + indexOfWord, word);
}
indexOfWord++;
}
indexOfWord=0;
// Join the secondStringList to make 1 string separated by the space character
item.edited.TextFrame.TextRange.Text = string.Join(" ", secondStringList);

Get the positions of unique elements in a string[]

I have an xml file that I am accessing to create a report of time spent on a project. I'm returning the unique dates to a label created dynamically on a winform and would like to compile the time spent on a project for each unique date. I have been able to return all of the projects under each date or only one project. Currently I'm stuck on only returning one project. Can anyone please help me?? This is what the data should look like if it's correct.
04/11/15
26820 2.25
27111 8.00
04/12/15
26820 8.00
04/13/15
01det 4.33
26820 1.33
27225 4.25
etc.
This is how I'm retrieving the data
string[] weekDateString = elementDateWeekstring();
string[] uniqueDates = null;
string[] weeklyJobNumber = elementJobNumWeek();
string[] weeklyTicks = elementTicksWeek();
This is how I'm getting the unique dates.
IEnumerable<string> distinctWeekDateIE = weekDateString.Distinct();
foreach (string d in distinctWeekDateIE)
{
uniqueDates = distinctWeekDateIE.ToArray();
}
And this is how I'm creating the labels.
try
{
int dateCount;
dateCount = uniqueDates.Length;
Label[] lblDate = new Label[dateCount];
int htDate = 1;
int padDate = 10;
for (int i = 0; i < dateCount; i++ )
{
lblDate[i] = new Label();
lblDate[i].Name = uniqueDates[i].Trim('\r');
lblDate[i].Text = uniqueDates[i];
lblDate[i].TabIndex = i;
lblDate[i].Bounds = new Rectangle(18, 275 + padDate + htDate, 75, 22);
targetForm.Controls.Add(lblDate[i]);
htDate += 22;
foreach (string x in uniqueDates)
{
int[] posJobNumber;
posJobNumber = weekDateString.Select((b, a) => b == uniqueDates[i].ToString() ? a : -1).Where(a => a != -1).ToArray();
for (int pjn = 0; pjn < posJobNumber.Length; pjn++)
{
if (x.Equals(lblDate[i].Text))
{
Label lblJobNum = new Label();
int htJobNum = 1;
int padJobNum = 10;
lblJobNum.Name = weeklyJobNumber[i];
lblJobNum.Text = weeklyJobNumber[i];
lblJobNum.Bounds = new Rectangle(100, 295 + padJobNum + htJobNum, 75, 22);
targetForm.Controls.Add(lblJobNum);
htJobNum += 22;
htDate += 22;
padJobNum += 22;
}
}
}
}
}
I've been stuck on this for about 3 months. Is there anyone that can describe to me why I'm not able to properly retrieve the job numbers that are associated with a particular date. I don't believe that these are specifically being returned as dates. Just a string that looks like a date.
I really appreciate any help I can get. I'm just completely baffled. Thank you for any responses in advance. I truly appreciate the assistance.
EDIT: #Sayka - Here is the xml sample.
<?xml version="1.0" encoding="utf-8"?>
<Form1>
<Name Key="4/21/2014 6:51:17 AM">
<Date>4/21/2014</Date>
<JobNum>26820</JobNum>
<RevNum>00000</RevNum>
<Task>Modeling Secondary</Task>
<Start>06:51 AM</Start>
<End>04:27 PM</End>
<TotalTime>345945089017</TotalTime>
</Name>
<Name Key="4/22/2014 5:44:22 AM">
<Date>4/22/2014</Date>
<JobNum>26820</JobNum>
<RevNum>00000</RevNum>
<Task>Modeling Secondary</Task>
<Start>05:44 AM</Start>
<End>06:56 AM</End>
<TotalTime>43514201221</TotalTime>
</Name>
<Name Key="4/22/2014 6:57:02 AM">
<Date>4/22/2014</Date>
<JobNum>02e-n-g</JobNum>
<RevNum>00000</RevNum>
<Task>NET Eng</Task>
<Start>06:57 AM</Start>
<End>07:16 AM</End>
<TotalTime>11706118875</TotalTime>
</Name>
....
</Form1>
This is how I'm getting the information out of the xml file and returning a string[].
public static string[] elementDateWeekstring()
{
//string datetxtWeek = "";
XmlDocument xmldoc = new XmlDocument();
fileExistsWeek(xmldoc);
XmlNodeList nodeDate = xmldoc.GetElementsByTagName("Date");
int countTicks = 0;
string[] dateTxtWeek = new string[nodeDate.Count];
for (int i = 0; i < nodeDate.Count; i++)
{
dateTxtWeek[i] = nodeDate[i].InnerText;
countTicks++;
}
return dateTxtWeek;
}
Job number and Ticks are returned in a similar fashion. I've been able to reuse these snippets throught out the code. This is a one dimensional xml file?? It will always return a position for a jobnumber that equates to a date or Ticks. I will never have more or less of any one element.
You can use Linq-to-XML to parse the XML file, and then use Linq-to-objects to group (and order) the data by job date and order each group by job name.
The code to parse the XML file is like so:
var doc = XDocument.Load(filename);
var jobs = doc.Descendants("Name");
// Extract the date, job number, and total time from each "Name" element.:
var data = jobs.Select(job => new
{
Date = (DateTime)job.Element("Date"),
Number = (string)job.Element("JobNum"),
Duration = TimeSpan.FromTicks((long)job.Element("TotalTime"))
});
The code to group and order the jobs by date and order the groups by job name is:
var result =
data.GroupBy(job => job.Date).OrderBy(g => g.Key)
.Select(g => new
{
Date = g.Key,
Jobs = g.OrderBy(item => item.Number)
});
Then you can access the data by iterating over each group in result and then iterate over each job in the group, like so:
foreach (var jobsOnDate in result)
{
Console.WriteLine("{0:d}", jobsOnDate.Date);
foreach (var job in jobsOnDate.Jobs)
Console.WriteLine(" {0} {1:hh\\:mm}", job.Number, job.Duration);
}
Putting this all together in a sample compilable console application (substitute the filename for the XML file as appropriate):
using System;
using System.Linq;
using System.Xml.Linq;
namespace ConsoleApplication2
{
class Program
{
private static void Main()
{
string filename = #"d:\test\test.xml"; // Substitute your own filename here.
// Open XML file and get a collection of each "Name" element.
var doc = XDocument.Load(filename);
var jobs = doc.Descendants("Name");
// Extract the date, job number, and total time from each "Name" element.:
var data = jobs.Select(job => new
{
Date = (DateTime)job.Element("Date"),
Number = (string)job.Element("JobNum"),
Duration = TimeSpan.FromTicks((long)job.Element("TotalTime"))
});
// Group the jobs by date, and order the groups by job name:
var result =
data.GroupBy(job => job.Date).OrderBy(g => g.Key)
.Select(g => new
{
Date = g.Key,
Jobs = g.OrderBy(item => item.Number)
});
// Print out the results:
foreach (var jobsOnDate in result)
{
Console.WriteLine("{0:d}", jobsOnDate.Date);
foreach (var job in jobsOnDate.Jobs)
Console.WriteLine(" {0} {1:hh\\:mm}", job.Number, job.Duration);
}
}
}
}
The output is like this
Create a new project
Set form size bigger.
Apply these codes.
Set the location for your XML file.
Namespaces
using System.Xml;
using System.IO;
Form Code
public partial class Form1 : Form
{
const string XML_FILE_NAME = "D:\\emps.txt";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
prepareDataGrid();
List<JOBS> jobsList = prepareXML(XML_FILE_NAME);
for (int i = 0; i < jobsList.Count; i++)
{
addDateRow(jobsList[i].jobDate.ToString("M'/'d'/'yyyy"));
for (int j = 0; j < jobsList[i].jobDetailsList.Count; j++)
dgv.Rows.Add(new string[] {
jobsList[i].jobDetailsList[j].JobNumber,
jobsList[i].jobDetailsList[j].JobHours
});
}
}
DataGridView dgv;
void prepareDataGrid()
{
dgv = new DataGridView();
dgv.BackgroundColor = Color.White;
dgv.GridColor = Color.White;
dgv.DefaultCellStyle.SelectionBackColor = Color.White;
dgv.DefaultCellStyle.SelectionForeColor = Color.Black;
dgv.DefaultCellStyle.ForeColor = Color.Black;
dgv.DefaultCellStyle.BackColor = Color.White;
dgv.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
dgv.Width = 600;
dgv.Dock = DockStyle.Left;
this.BackColor = Color.White;
dgv.Columns.Add("Col1", "Col1");
dgv.Columns.Add("Col2", "Col2");
dgv.Columns[0].Width = 110;
dgv.Columns[1].Width = 40;
dgv.DefaultCellStyle.Font = new System.Drawing.Font("Segoe UI", 10);
dgv.RowHeadersVisible = dgv.ColumnHeadersVisible = false;
dgv.AllowUserToAddRows =
dgv.AllowUserToDeleteRows =
dgv.AllowUserToOrderColumns =
dgv.AllowUserToResizeColumns =
dgv.AllowUserToResizeRows =
!(dgv.ReadOnly = true);
Controls.Add(dgv);
}
void addJobRow(string jobNum, string jobHours)
{
dgv.Rows.Add(new string[] {jobNum, jobHours });
}
void addDateRow(string date)
{
dgv.Rows.Add(new string[] { date, ""});
dgv.Rows[dgv.Rows.Count - 1].DefaultCellStyle.SelectionForeColor =
dgv.Rows[dgv.Rows.Count - 1].DefaultCellStyle.ForeColor = Color.Firebrick;
dgv.Rows[dgv.Rows.Count - 1].DefaultCellStyle.Font = new Font("Segoe UI Light", 13.5F);
dgv.Rows[dgv.Rows.Count - 1].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
dgv.Rows[dgv.Rows.Count - 1].Height = 25;
}
List<JOBS> prepareXML(string fileName)
{
string xmlContent = "";
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
using (StreamReader sr = new StreamReader(fs)) xmlContent = sr.ReadToEnd();
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlContent);
List<JOBS> jobsList = new List<JOBS>();
XmlNode form1Node = doc.ChildNodes[1];
for (int i = 0; i < form1Node.ChildNodes.Count; i++)
{
XmlNode dateNode = form1Node.ChildNodes[i].ChildNodes[0].ChildNodes[0],
jobNumNode = form1Node.ChildNodes[i].ChildNodes[1].ChildNodes[0],
timeTicksNode = form1Node.ChildNodes[i].ChildNodes[6].ChildNodes[0];
bool foundDate = false;
for (int j = 0; j < jobsList.Count; j++) if (jobsList[j].compareDate(dateNode.Value))
{
jobsList[j].addJob(jobNumNode.Value, Math.Round(TimeSpan.FromTicks(
(long)Convert.ToDouble(timeTicksNode.Value)).TotalHours, 2).ToString());
foundDate = true;
break;
}
if (!foundDate)
{
JOBS job = new JOBS(dateNode.Value);
string jbnum = jobNumNode.Value;
string tbtck = timeTicksNode.Value;
long tktk = Convert.ToInt64(tbtck);
double tkdb = TimeSpan.FromTicks(tktk).TotalHours;
job.addJob(jobNumNode.Value, Math.Round(TimeSpan.FromTicks(
Convert.ToInt64(timeTicksNode.Value)).TotalHours, 2).ToString());
jobsList.Add(job);
}
}
jobsList.OrderByDescending(x => x.jobDate);
return jobsList;
}
class JOBS
{
public DateTime jobDate;
public List<JobDetails> jobDetailsList = new List<JobDetails>();
public void addJob(string jobNumber, string jobHours)
{
jobDetailsList.Add(new JobDetails() { JobHours = jobHours, JobNumber = jobNumber });
}
public JOBS(string dateString)
{
jobDate = getDateFromString(dateString);
}
public JOBS() { }
public bool compareDate(string dateString)
{
return getDateFromString(dateString) == jobDate;
}
private DateTime getDateFromString(string dateString)
{
string[] vals = dateString.Split('/');
return new DateTime(Convert.ToInt32(vals[2]), Convert.ToInt32(vals[0]), Convert.ToInt32(vals[1]));
}
}
class JobDetails
{
public string JobNumber { get; set; }
public string JobHours { get; set; }
}
}

"Object reference not set to an instance of an object" error during the compilation

I get the "Object reference not set to an instance of an object" error when i compile the code at string[] values = lineuser.Split(' '); . Any idea?
namespace function
{
public partial class Form1 : Form
{
float userscore,itemscore,result;
string lineitem, lineuser;
//float[][] a = new float[89395][100];
//float[][] b = new float[1143600][100];
float[][] a = Enumerable.Range(0, 89395).Select(i => new float[100]).ToArray();
float[][] b = Enumerable.Range(0, 1143600).Select(j => new float[100]).ToArray();
//float[,] c = new float[89395, 100];
StreamReader fileitem = new StreamReader("c:\\ITEM_SVD_FULL.txt");
StreamReader fileuser = new StreamReader("c:\\USER_SVD_FULL.txt");
public Form1()
{
InitializeComponent();
for (int x = 0; x <= 8939500; x++)
{
lineuser = fileuser.ReadLine();
string[] values = lineuser.Split(' '); //<------the line's error
int userid, factoriduser;
foreach (string value in values)
{
userid = Convert.ToInt32(values[0]);
factoriduser = Convert.ToInt32(values[1]);
userscore = Convert.ToSingle(values[2]);
a[userid][factoriduser] = userscore;
}
}
for (int y = 0; y <= 114360000; y++)
{
lineitem = fileitem.ReadLine();
string[] valuesi = lineitem.Split(' ');
int itemid, factoriditem;
foreach (string value in valuesi)
{
itemid = Convert.ToInt32(valuesi[0]);
factoriditem = Convert.ToInt32(valuesi[1]);
itemscore = Convert.ToSingle(valuesi[2]);
b[itemid][factoriditem] = itemscore;
}
}
}
public float dotproduct(int userid,int itemid)
{
//get the score of 100 from user and item to dotproduct
float[] u_f = a[userid];
float[] i_f = b[itemid];
for (int i = 0; i <u_f.GetLength(1); i++)
{
result += u_f[userid] * i_f[itemid];
}
return result;
}
private void btn_recomm_Click(object sender, EventArgs e)
{
if(txtbx_id.Text==null)
{
MessageBox.Show("please insert user id");
}
if (txtbx_id.Text != null && txtbx_itemid==null)
{
int sc = Convert.ToInt32(txtbx_id.Text);
if (sc>=0 &&sc<=89395)
{
for (int z=0;z<=1143600;z++)
{
dotproduct(sc,z);
}
//Hashtable hashtable = new Hashtable();
//put the result in hashtable
//foreach (DictionaryEntry entry in hashtable)
//{
//Console.WriteLine("{0}, {1}", entry.Key, entry.Value);
// }
}
}
if (txtbx_id!=null &&txtbx_itemid!=null)
{
int uid = Convert.ToInt32(txtbx_id.Text);
int iid = Convert.ToInt32(txtbx_itemid.Text);
{
if (uid>=0 && uid<=89395 && iid>=0 && iid<=1143600)
{
dotproduct(uid,iid);
MessageBox.Show("The Score of user id "+uid+" is "+result);
}
}
Please check you lineuser variable is null
public Form1()
{
InitializeComponent();
for (int x = 0; x <= 8939500; x++)
{
if(!string.IsNullorEmpty(lineuser) //<--- check the string is empty
{
string[] values = lineuser.Split(' '); //<------the line's error
int userid, factoriduser;
foreach (string value in values)
{
userid = Convert.ToInt32(values[0]);
factoriduser = Convert.ToInt32(values[1]);
userscore = Convert.ToSingle(values[2]);
a[userid][factoriduser] = userscore;
}
}
}
for (int y = 0; y <= 114360000; y++)
{
lineitem = fileitem.ReadLine();
if(!string.IsNullorEmpty(lineitem) //<--- check the string is empty
{
string[] valuesi = lineitem.Split(' ');
int itemid, factoriditem;
foreach (string value in valuesi)
{
itemid = Convert.ToInt32(valuesi[0]);
factoriditem = Convert.ToInt32(valuesi[1]);
itemscore = Convert.ToSingle(valuesi[2]);
b[itemid][factoriditem] = itemscore;
}
}
}
}
Now you can avoid the error.
You haven't opened the Stream fileuser so it is still null.
It is really a bad practice to open the file while you define the global variable in your class.
But as part from this, when you call ReadLine the result could be a null because there are no more lines to read and you don't check for this case.
Looking at the code shown above, there is no need to have a global variable for the filestream, so, the usual pattern when handling resources (OPEN/USE/CLOSE) should be followed for both files
public Form1()
{
InitializeComponent();
string lineuser;
// OPEN
using(StreamReader fileuser = new StreamReader("c:\\USER_SVD_FULL.txt"))
{
// USE
while((lineuser = fileuser.ReadLine()) != null)
{
string[] values = lineuser.Split(' ');
....
}
} //CLOSE & DISPOSE
....
string lineitem;
using(StreamReader fileitem = new StreamReader("c:\\ITEM_SVD_FULL.txt"))
{
while((lineitem = fileitem.ReadLine()) != null)
{
string[] valuesi = lineitem.Split(' ');
....
}
}

Categories