V předchozím článku o grafech v ASP.NET jsem vám ukázal jak lze vytvořit čárové grafy. Dnes se dozvíte jak podobným způsobem vytvořit graf koláčový.

Pro příklad (zdrojový kód) jsem zvolil jako datový zdroj ankety na Intervalu, které se pravidelně obměňují na hlavní stránce. Jak udělat takovouto anketu (ovšem pouze v klasickém ASP) jste si měli možnost přečíst v seriálu článků Anketa krok za krokem (1, 2, 3,). Jak si můžete všimnout, je v příkladu zobrazeno pomocí jednoho ASPX několik grafů. Údaje pro grafy jsou vybírány z databáze na základě parametru idankety. Vstupní parametr je ošetřen tak, aby nemohl obsahovat nic jiného než číslo.

Povšimněte si také způsobu předání parametru do SQL dotazu. Tento způsob je přehledný a minimalizuje možnost podvržení nesprávných parametrů. Pokud chcete použít v SQL dotazu parametr, záleží na tom, zda použijete OleDbCommand nebo SqlCommand. Bohužel každý z těchto zprostředkovatelů dat vyžaduje jiný způsob zápisu parametrů. Zatímco OleDbCommand vyžaduje pro označení parametru ? (otazník), SqlCommand používá pojmenované parametry, kde jméno parametru začíná znakem @ (zavináč). Zápis parametrů pro SQLCommand bude vypadat takto:

SqlCommand cmd=new SqlCommand(„SELECT SUM(redaction_anketa_odpovedi.hlasy)
         AS celkem, redaction_anketa_otazky.Otazka FROM redaction_anketa_odpovedi
         INNER JOIN redaction_anketa_otazky ON redaction_anketa_odpovedi.idankety =
         redaction_anketa_otazky.id GROUP BY redaction_anketa_otazky.id, redaction_anketa_otazky.Otazka
         HAVING (redaction_anketa_otazky.id = @idanketa) SELECT odpoved, hlasy FROM
         redaction_anketa_odpovedi
         WHERE (idankety = @idanketa) ORDER BY hlasy DESC“,conn);
cmd.Parameters.Add(„@idanketa“,idankety);
SqlDataReader rdr=cmd.ExecuteReader();
rdr.Read();

A pro OleDbCommand provedeme zápis tímto způsobem:

OleDbCommand cmd=new OleDbCommand(„SELECT SUM(redaction_anketa_odpovedi.hlasy)
         AS celkem, redaction_anketa_otazky.Otazka FROM redaction_anketa_odpovedi
         INNER JOIN redaction_anketa_otazky ON redaction_anketa_odpovedi.idankety =
         redaction_anketa_otazky.id GROUP BY redaction_anketa_otazky.id, redaction_anketa_otazky.Otazka
         HAVING (redaction_anketa_otazky.id = ?) SELECT odpoved, hlasy FROM redaction_anketa_odpovedi
         WHERE (idankety = ?) ORDER BY hlasy DESC“,conn);
cmd.Parameters.Add(„redaction_anketa_otazky.id“,idankety);
cmd.Parameters.Add(„idankety“,idankety);
OleDbDataReader rdr=cmd.ExecuteReader();

Stejně jako v minulém článku používám dva SQL dotazy, pomocí kterých dostanu dvě sady záznamů. Všimněte si, že ačkoliv používám jen jeden parametr idankety, v zápise pro OleDbCommand mám použity dva parametry jiného jména, kdežto v zápise pro SqlCommand si parametr pojmenuji a nadále pak používám jeden jediný.

Po „malém výletu“ do ADO.NET se vrátíme opět k tvorbě grafu. Základním „stavebním“ kamenem bude metoda FillPie třídy Graphics (vyplněná kruhová výseč). Metoda FillPie má tři různé způsoby zápisu parametrů a v příkladě je použit tento:

public void FillPie(
   Brush brush,
   float x,
   float y,
   float width,
   float height,
   float startAngle,
   float sweepAngle
);

Parametr Brush určuje typ výplně, která bude použita pro vyplnění výseče – x,y určuje souřadnice levého horního rohu čtverce (či obélníku) opsaného útvaru, ze kterého se vykresluje výseč, width,height určuje velikost objektu (pokud nejsou shodné, bude se vykreslovat výseč elipsy), startAngle určuje počáteční úhel vykreslované výseče (úhel se bere od osy x – „tři hodiny“ – ve směru hodinových ručiček), sweepAngle určuje úhel vykreslované výseče (opět ve směru hodinových ručiček). Úhly se zadávají ve stupních a při výpočtu doporučuji počítat s datovým typem float a nepoužít metodu FillPie s parametry typu int, nýbrž s typem float. Důvodem je skutečnost, že by při výpočtu v oboru čísel int došlo k velké nepřesnosti a vykreslené výseče by neuzavřely kruh.

private void Page_Load(object sender, System.EventArgs e)
{
   int idankety=0;
   string ErrorText=““;
   try
   {
      idankety=Convert.ToInt16(Request.QueryString.GetValues(„idankety“)[0]);
   }
   catch
   {
      ErrorText=“Chybný parametr“;
   }
   // vytvoření „obrázku“
   const int width = 400, height = 400;
   Bitmap objBitmap = new Bitmap(width, height);
   Graphics objGraphics = Graphics.FromImage(objBitmap);
   // ramecek kolem grafu
   objGraphics.FillRectangle(new LinearGradientBrush(new Point(10,10),
      new Point(100,100),Color.Red,Color.Blue), 0, 0, width, height);
   // pozadi grafu
   objGraphics.FillRectangle(new SolidBrush(Color.White), 2, 2, width – 4, height – 4);
   // Nastavíme font pro popis
   Font fontPopis = new Font(„Times New Roman“, 12, FontStyle.Bold);
   // Nastavíme formátování textu
   StringFormat stringFormat = new StringFormat();
   stringFormat.Alignment = StringAlignment.Center;
   stringFormat.LineAlignment = StringAlignment.Center;
   try
   {
      // připojovací řetězec do SQL serveru
      const string sqlConnectionString=“Data Source=localhost;User ID=sa;Password=asdf;Initial Catalog=INTERVAL;“;
      // Vytvoření spojení do databáze
      SqlConnection conn=new SqlConnection(sqlConnectionString);
      conn.Open();
      // provedení výběru da
      SqlCommand cmd=new SqlCommand(„SELECT SUM(redaction_anketa_odpovedi.hlasy)
         AS celkem,redaction_anketa_otazky.Otazka FROM redaction_anketa_odpovedi
         INNER JOIN redaction_anketa_otazky ON redaction_anketa_odpovedi.idankety =
         redaction_anketa_otazky.id GROUP BY redaction_anketa_otazky.id, redaction_anketa_otazky.Otazka
         HAVING (redaction_anketa_otazky.id = @idanketa) SELECT odpoved, hlasy FROM
         redaction_anketa_odpovedi
         WHERE (idankety = @idanketa) ORDER BY hlasy DESC“,conn);
      cmd.Parameters.Add(„@idanketa“,idankety);
      SqlDataReader rdr=cmd.ExecuteReader();
      rdr.Read();
      objGraphics.DrawString(rdr[„Otazka“].ToString(), fontPopis, new SolidBrush(Color.Black),
         new Rectangle(5,5,390,40),stringFormat);
      float jedenstupen= 360.0F/float.Parse(rdr[„celkem“].ToString());
      rdr.NextResult();
      float celkovyuhel=0.0F;
      float uheldilku;
      int polozka=0;
      Font fontPopisOdpoved = new Font(„Times New Roman“, 10, FontStyle.Bold);
      // Nastavíme formátování textu
      StringFormat stringFormatOdpoved = new StringFormat();
      stringFormatOdpoved.Alignment = StringAlignment.Near;
      stringFormatOdpoved.LineAlignment = StringAlignment.Far;
      Color Barva;
      int posunx,posuny;
      while(rdr.Read())
      {
         uheldilku= float.Parse(rdr[„hlasy“].ToString())*jedenstupen;
         // predvoleni barvy vyplne
         switch(polozka)
         {
            case 0: Barva=Color.FromArgb(153,51,102);break;
            case 1: Barva=Color.FromArgb(102,0,102);break;
            case 2: Barva=Color.FromArgb(0,102,204);break;
            case 3: Barva=Color.FromArgb(153,153,255);break;
            case 4: Barva=Color.FromArgb(0,204,45);break;
            default: Barva=Color.Black;break;
         }
         // prvni vysec bude posuna ven ze stredu
         if (polozka==0)
         {
            posunx=10;
            posuny=10;
         }
            else
         {
            posunx=0;
            posuny=0;
         }
         objGraphics.FillPie(new SolidBrush(Barva),60+posunx,50+posuny,220,220,celkovyuhel,uheldilku);
         celkovyuhel=celkovyuhel+uheldilku;
         // vypis legendy
         objGraphics.DrawString(rdr[„hlasy“].ToString(), fontPopisOdpoved, new SolidBrush(Barva),
            new Rectangle(5, 280+(15*polozka),390,20),stringFormatOdpoved);
         objGraphics.DrawString(rdr[„odpoved“].ToString(), fontPopisOdpoved, new SolidBrush(Barva),
            new Rectangle(35, 280+(15*polozka),390,20),stringFormatOdpoved);
         polozka++;
      }
      // zavření spojení do databáze a uvolneni nepotrebnych objektu z pameti
      cmd.Dispose();
      rdr.Close();
      conn.Close();
      stringFormatOdpoved.Dispose();
      fontPopisOdpoved.Dispose();
   }
   catch
   {
      if (idankety>0)
      {
         ErrorText=“Nejsou k dispozici žádná data“;
      }
   }
   // pokud doslo v prubehu prace k chybě vypsat hlášení
   if (ErrorText.Length>0)
   {
      objGraphics.DrawString(ErrorText, fontPopis, new SolidBrush(Color.Black),
         new Rectangle(5,5,390,40),stringFormat);
      objGraphics.FillEllipse(new SolidBrush(Color.Red),60,60,280,280);
   }
   // odeslaní výsledku na klienta
   Response.ContentType = („image/gif“);
   objBitmap.Save (Response.OutputStream,ImageFormat.Gif);
   // uvolnění paměti
   fontPopis.Dispose();
   stringFormat.Dispose();
   objGraphics.Dispose();
   objBitmap.Dispose();
}

Užitečným doplněním grafu by bylo zamezení zobrazení grafu z jiného serveru způsobem, který popsal Pavel Růžička v článku Dynamické obrázkové nadpisy v ASP.NET. Toto ošetření nemá vliv na funkčnost příkladu, a proto jsem je z důvodu přehlednosti do kódu nezahrnul.

Žádný příspěvek v diskuzi

Odpovědět