Link to home
Start Free TrialLog in
Avatar of QPR
QPRFlag for New Zealand

asked on

read values into array

HI,
I have the following code which draws a chart to the screen and plots co-ordinates onto it. (finally spat out as a jpg to the browser).
At the moment for dev/testing purposes I am hard coding the x,y values but I need to be able to read them from an external datasource... be it a DB or xml or text file.

(code snippet)
void Page_Load(Object sender, EventArgs e) {
LineChart c = new LineChart(840, 580, Page);
c.Title="";
c.OpenFooter = "Opens";
c.CloseFooter = "Closes";
c.MidFooter = " <-------- voting days --------> ";
c.Xorigin=0; c.ScaleX=21; c.Xdivs=21;
c.Yorigin=0; c.ScaleY=25000; c.Ydivs=10;
c.AddValue(0,0);
c.AddValue(1,800);
c.AddValue(2,1100);
c.AddValue(3,2200);
c.AddValue(4,3600);
c.AddValue(5,4000);
c.AddValue(6,4105);
c.AddValue(7,5251);
c.AddValue(8,5299);
c.AddValue(9,6099);
c.AddValue(10,9090);
c.AddValue(11,12071);
c.AddValue(12,14500);
c.AddValue(13,16559);
c.AddValue(14,18222);
c.AddValue(15,18755);
c.AddValue(16,19444);
c.AddValue(17,20051);
c.AddValue(18,21222);
c.AddValue(19,21259);
c.AddValue(20,23451);
c.AddValue(21,23499);
c.Draw();
}
(/snippet)


Any ideas? I fairly new to C# so go easy on me please  :)
Cheers
ASKER CERTIFIED SOLUTION
Avatar of ruff_ryder
ruff_ryder
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
(MS Access DB access via OleDB)

using System.Data.OleDb;

System.Data.OleDb.OleDbConnection DBconnection;  //connection to database
System.Data.OleDb.OleDbCommand    DbSelect;      // command to send to DB

DBconnection = new OleDbConnection();
DBconnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Password=\"\";User ID=Admin;Data Source=C:\\Database.mdb;Mode=Share Deny None;Extended Properties=\"\";Jet OLEDB:System database=\"\";Jet OLEDB:Registry Path=\"\";Jet OLEDB:Database Password=\"\";Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password=\"\";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False";
try                              
{
      DBconnection.Open();
}
catch (Exception ex)
{
      Console.WriteLine(ex.Message);
}

listBox1.Items.Clear();
string Sql = "SELECT field1 FROM table1";    //SQL select statement
DbSelect = new OleDbCommand(Sql, DBconnection);  //create my command using the sql string connection using the db connection
DbSelect.Prepare();   // tell the sql server to prepare the statement
OleDbDataReader myReader = DbSelect.ExecuteReader();  // create a "datareader" which will read rows from the results
try
{
      while (myReader.Read())   // while there is data in the returned rows
      {
            listBox1.Items.Add(myReader.GetString(0));  // reader get column 0 as a string, add it to the listbox
      }
}
finally
{
      myReader.Close();
}

(note i created my connection string by dropping a OleDbConnection onto the form, created the connectionString using the IDE, copied the string to memory and deleted the non-visual component.  You could do the same by droping components onto your application)
Avatar of QPR

ASKER

Hi Ruff Rider.
This looks to be along the lines of what I need.
The X,Y values will be added on a daily basis... is basically a voting thing.
Each day a (non-web/tech) person will add a number via an admin page which will then cause the xml file to be opened and a new <point x=, y= /> tag to be added.... (no idea how to achieve this step but I guess that's a new question for another group!  :o) where X = day numberX and Y being the number of voting papers returned as at that date (X)

Would you recommend having the required number of tags (21) with the future days being blank
Example:
<LinePoints>
     <point x="1" y="100" />
     <point x="2" y="450" />
     <point x="3" y="612" />
     <point x= y= />
     <point x= y= />
   ...etc
</LinePoints>

or add a new line <point x= y= /> each time/day the user uses the admin page?
I see problems converting null to int32 but then I also see problems having less tags than the specified chart set-up. This probably makes little sense without seeing the code in it's entirity so I'll paste it all here in case it helps.
Continued thanks!


<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Drawing2D" %>
<%@ Import Namespace="System.Drawing.Imaging" %>


<script language="C#" runat="server">

class LineChart
{
public Bitmap b;
public string Title="Default Title";
public string OpenFooter = "Default Footer";
public string CloseFooter="Default Footer";
public string MidFooter="Default Footer";
public ArrayList chartValues = new ArrayList();
public float Xorigin=0, Yorigin=0;
public float ScaleX, ScaleY;
public float Xdivs=2, Ydivs=2;

private int Width, Height;
private Graphics g;
private Page p;

struct datapoint {
public float x;
public float y;
public bool valid;
}

//initialize
public LineChart(int myWidth, int myHeight, Page myPage) {
Width = myWidth; Height = myHeight;
ScaleX = myWidth; ScaleY = myHeight;
b = new Bitmap(myWidth, myHeight);
g = Graphics.FromImage(b);
p = myPage;
}

public void AddValue(int x, int y) {
datapoint myPoint;
myPoint.x=x;
myPoint.y=y;
myPoint.valid=true;
chartValues.Add(myPoint);
}

public void Draw() {
int i;
float x, y, x0, y0;
string myLabel;
Pen blackPen = new Pen(Color.Blue,1);
Brush blackBrush = new SolidBrush(Color.Black);
Font axesFont = new Font("arial",10);

//first establish working area
p.Response.ContentType="image/Gif";
g.FillRectangle(new
SolidBrush(Color.LightYellow),0,0,Width,Height);
int ChartInset = 50;
int ChartWidth = Width-(2*ChartInset);
int ChartHeight = Height-(2*ChartInset);
g.DrawRectangle(new
Pen(Color.Black,2),ChartInset,ChartInset,ChartWidth,ChartHeight);

//must draw all text items before doing the rotate below
g.DrawString(Title, new Font("verdana",16), blackBrush, Width/2 - 290, 10);
g.DrawString(OpenFooter, new Font("Arial",8), blackBrush,Width/Width + 30, Height - 20);
g.DrawString(MidFooter,new Font("Arial",10), blackBrush,Width/2 - 50, Height - 25);
g.DrawString(CloseFooter,new Font("Arial",8), blackBrush,Width-65, Height - 20);

//draw X axis labels
for(i=0; i<=Xdivs; i++) {
      x=ChartInset+(i*ChartWidth)/Xdivs;
      y=ChartHeight+ChartInset;
      myLabel = (Xorigin + (ScaleX*i/Xdivs)).ToString();
      g.DrawString(myLabel, axesFont, blackBrush, x-4, y+10);
      g.DrawLine(blackPen, x, y+2, x, y-2);
}
//draw Y axis labels
for(i=0; i<=Ydivs; i++) {
      x=ChartInset;
      y=ChartHeight+ChartInset-(i*ChartHeight/Ydivs);
      myLabel = (Yorigin + (ScaleY*i/Ydivs)).ToString();
      g.DrawString(myLabel, axesFont, blackBrush, 5, y-6);
      g.DrawLine(blackPen, x+2, y, x-2, y);
}

//transform drawing coords to lower-left (0,0)
g.RotateTransform(180);
g.TranslateTransform(0,-Height);
g.TranslateTransform(-ChartInset,ChartInset);
g.ScaleTransform(-1, 1);

//draw chart data
datapoint prevPoint = new datapoint();
prevPoint.valid=false;
foreach(datapoint myPoint in chartValues) {
if(prevPoint.valid==true) {
      x0=ChartWidth*(prevPoint.x-Xorigin)/ScaleX;
      y0=ChartHeight*(prevPoint.y-Yorigin)/ScaleY;
      x=ChartWidth*(myPoint.x-Xorigin)/ScaleX;
      y=ChartHeight*(myPoint.y-Yorigin)/ScaleY;
      g.DrawLine(blackPen,x0,y0,x,y);
      g.FillEllipse(blackBrush,x0-2,y0-2,4,4);
      g.FillEllipse(blackBrush,x-2,y-2,4,4);
}
prevPoint = myPoint;
}

//finally send graphics to browser
b.Save(p.Response.OutputStream, ImageFormat.Gif);
}

~LineChart() {
g.Dispose();
b.Dispose();
}
}


void Page_Load(Object sender, EventArgs e) {
LineChart c = new LineChart(840, 580, Page);
c.Title="Number of returned voting papers as at " + System.DateTime.Today.ToString("dd/MM/yyyy");
c.OpenFooter = "Opens";
c.CloseFooter = "Closes";
c.MidFooter = " <-------- voting days --------> ";
c.Xorigin=0; c.ScaleX=21; c.Xdivs=21;
c.Yorigin=0; c.ScaleY=25000; c.Ydivs=10;
c.AddValue(0,0);
c.AddValue(1,800);
c.AddValue(2,1100);
c.AddValue(3,2200);
c.AddValue(4,3600);
c.AddValue(5,4000);
c.AddValue(6,4105);
c.AddValue(7,5251);
c.AddValue(8,5299);
c.AddValue(9,6099);
c.AddValue(10,9090);
c.AddValue(11,12071);
c.AddValue(12,14500);
c.AddValue(13,16559);
c.AddValue(14,18222);
c.AddValue(15,18755);
c.AddValue(16,19444);
c.AddValue(17,20051);
c.AddValue(18,21222);
c.AddValue(19,21259);
c.AddValue(20,23451);
c.AddValue(21,23499);
c.Draw();
}

</script>

Hey,

Either way will work actually. Generating new nodes for the XML is pretty simple in .NET. However, since you say that the chart cannot deal with less than 21 days then it is better to code to suit the chart behaviour. It will mean less ahssles for you in functionality. There are a few approaches you could take:

1) Add points as they are entered.

In this case, the only points that would exist in your XML file are actual points input to the system. This would continue to work as you have it.

2) Pre-Allocate the 21 points and default their values

This approach accomodates the chart's operations. In this case, though, when adding a new entry you would have to index into the points and set teh corresponding data values.

Either way can work. Personally I would take approach one. I don't like having unused data in my system for perofrmance and resource issues. I don't know how this affects your chart though so the call is really yours :)

To help you out, have a look at the System.Xml namespace in the .NET documentation. You will find all classes you need to manipulate your xml file at runtime.
Avatar of QPR

ASKER

Getting there!
Man C# is picky when you come from a VB background (not a bad thing tho) XML != Xml

ok "Could not find file "C:\WINNT\system32\GraphData.xml""
The xml file is in the same folder as the aspx
In ASP classic (VBScript) I would use server.mapPath. How can I achieve this in C#.
Hopefully, after 2 forgotten ; and 10 upper/lower case errors :)

Also.... how can I paste text as plain text into VS.Net? When I paste from here I get font declarations etc... I see no paste special on the menu.
And.... Why is there no Intellisense? Is this because I am doing aspx as opposed to a vb.net file?
Avatar of QPR

ASKER

works like a charm and I learnt stuff into the bargain (always a bonus!)
I've used the absolute file path to the xml file and doubled up on the backslashes but would still like a relative path to it if possible?

Now to learn how to open/append the xml file/child tags

Many thanks
Jay
Hey QPR,

For the MapPath, have a look at the System.Web.UI.Page object. It has a method called MapPath() that may be what you are looking for.

As for the text pasting, I'm not sure why that happens. Try pasting in notepad text file then paste from there. You should have intellisense when you are editing code. I don't think IntelliSense operates on the actual aspx page editor. You should have it when editing the code behind the aspx page though.
Avatar of QPR

ASKER

Thanks I'll have a look at MapPath() thanks.
Yep I'll revert to that, starnge that the IDE doesn't offer paste options though.

From memory this page/code was originally an aspx example I d/l as a zip file which I then just opened in VS.NET... as a result I can't find any code behind etc.
Only ever opened as a single file as opposed to a project/solution. Maybe that explains the lack of intellisense.

Many thanks for all the help RR.