Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Definir un TChart (https://www.clubdelphi.com/foros/showthread.php?t=94290)

Angel.Matilla 06-11-2019 17:55:34

Definir un TChart
 
Buenas a todos. A partir del código encontrado aquí y otro de este foro estoy montando un TChart en base a los resultados de, por ejemplo, este Query:
Código:

SELECT B.Sigla, B.Color, C.Fecha, SUM(A.Votos) Votos
  FROM Resultados A, Partidos B, Elecciones C
 WHERE A.CodPrv = (SELECT Literal FROM Instalacion WHERE Etiqueta = 'Provincia')
  AND A.CodPrv = C.CodPrv AND C.Proceso = 4 AND C.Fecha BETWEEN 1993 AND 2019
  AND A.Proceso = C.Codigo
  AND A.Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv)
  AND B.CodPrv = A.CodPrv AND A.Partido = B.Codigo
  AND A.Partido IN (22, 4, 2, 3, 17, 16)
 GROUP BY A.Partido, B.Sigla, B.Color, C.Fecha ORDER BY A.Partido, B.Sigla, C.Fecha

Con el resultado del mismo genero esta pantalla que tiene un TListView y un TChart.

Para crear el TChart hago esto:
Código:

if (Chart1->SeriesCount() > 0)
    Chart1->RemoveAllSeries();

Chart1->Title->Font->Style = TFontStyles();
Chart1->BottomAxis->Title->Caption    = "Años";
Chart1->BottomAxis->Title->Font->Style = TFontStyles() << fsBold;
Chart1->LeftAxis->Title->Caption      = "Votos";
Chart1->LeftAxis->Title->Font->Style  = TFontStyles() << fsBold;

AnsiString cAux = "";
fMenu->Auxiliar->First();
for (; !fMenu->Auxiliar->Eof; fMenu->Auxiliar->Next())
{
    if (fMenu->Auxiliar->FieldByName("Sigla")->AsString != cAux)
    {
          cAux = fMenu->Auxiliar->FieldByName("Sigla")->AsString;
          Chart1->AddSeries(&TLineSeries(this));
    }

    Chart1->Series[Chart1->SeriesCount() - 1]->Add(fMenu->Auxiliar->FieldByName("Votos")->AsInteger, fMenu->Auxiliar->FieldByName("Fecha")->AsInteger, (TColor)fMenu->Auxiliar->FieldByName("Color")->AsInteger);
}

Pero me surgen algunos problemas:
  1. En el eje horizontal deberían mostrarse los años y en el mismo orden que se ven en el TListView, pero como veis se muestra el "orden" dentro del ListView.
  2. En la leyenda quiero mostrar la primera columna del TListView (las siglas del partido).
¿Alguna idea de como resolver estos problemas? Porque llevo un par de días dando vueltas al problema y no se me ocurre nada.

Angel.Matilla 07-11-2019 10:51:18

Bueno. He resuelto todos los problemas menos uno. El código ha quedado así partiendo de este query:
Código:

SELECT A.Partido, B.Sigla, B.Color, C.Fecha, SUM(A.Votos) Votos
  FROM Resultados A, Partidos B, Elecciones C
 WHERE C.Proceso = :Proceso
  AND C.Fecha BETWEEN :Desde AND :Hasta AND A.Proceso = C.Codigo
  AND A.Mesa IN (SELECT Codigo FROM Mesas)
  AND A.Partido = B.Codigo
  AND A.Partido IN (22, 4, 2, 3, 17, 16)
 GROUP BY A.Partido, B.Sigla, B.Color, C.Fecha ORDER BY A.Partido, C.Fecha

y con este código:
Código:

Chart1->Chart3DPercent                = 10;
Chart1->Title->Font->Style            = TFontStyles() << fsBold;
Chart1->BottomAxis->Title->Caption    = "Años";
Chart1->BottomAxis->Title->Font->Style = TFontStyles() << fsBold;
Chart1->BottomAxis->Labels            = fMenu->Auxiliar->FieldByName("Fecha")->AsInteger;
Chart1->LeftAxis->Title->Caption      = "Votos";
Chart1->LeftAxis->Title->Font->Style  = TFontStyles() << fsBold;

cAux = "";
for (; !fMenu->Auxiliar->Eof; fMenu->Auxiliar->Next())
{
    if (fMenu->Auxiliar->FieldByName("Sigla")->AsString != cAux)
    {
          pItem = Evolucion->Items->Add();
          pItem->Caption = (cAux = fMenu->Auxiliar->FieldByName("Sigla")->AsString);
          for (nItem = 1; nItem < Evolucion->Columns->Count; nItem ++)
              pItem->SubItems->Add("");

          Chart1->AddSeries(&TLineSeries(Chart1));
          Chart1->Series[Chart1->SeriesCount() - 1]->Title = cAux;
          Chart1->Series[Chart1->SeriesCount() - 1]->SeriesColor = (TColor)fMenu->Auxiliar->FieldByName("Color")->AsInteger;
    }

    nVotos[0] = 0;
    for (nItem = 1; nItem < Evolucion->Columns->Count; nItem ++)
          if (Evolucion->Columns->Items[nItem]->Caption == IntToStr(fMenu->Auxiliar->FieldByName("Fecha")->AsInteger))
          {
              nVotos[0] = fMenu->Auxiliar->FieldByName("Votos")->AsInteger;
              pItem->SubItems->Strings[nItem - 1] = FormatFloat("###,##0", nVotos[0]);
              break;
          }

          Chart1->Series[Chart1->SeriesCount() - 1]->Add(nVotos[0], fMenu->Auxiliar->FieldByName("Fecha")->AsInteger,
                                                              (TColor)fMenu->Auxiliar->FieldByName("Color")->AsInteger);
}
Chart1->Series[0]->XLabelsSource = "FECHA";

Obtengo este resultado:

Sin embargo, como podéis ver, las últimas bandas no se inician donde debieran a pesar de añadir valores al definir la serie donde así sea, y esto no se me ocurre como resolverlo.

Casimiro Notevi 07-11-2019 11:02:57

¿Y si le pones valor cero en lugar de dejarlo en blanco?

Angel.Matilla 07-11-2019 11:11:28

Cita:

Empezado por Casimiro Notevi (Mensaje 534329)
¿Y si le pones valor cero en lugar de dejarlo en blanco?

Si te fijas estoy poniendo cero.
Código:

cAux = "";
for (; !fMenu->Auxiliar->Eof; fMenu->Auxiliar->Next())
{
[...]
    nVotos[0] = 0;    // <--- AQUÍ INICIALIZO LA VARIABLE
    for (nItem = 1; nItem < Evolucion->Columns->Count; nItem ++)
    if (Evolucion->Columns->Items[nItem]->Caption == IntToStr(fMenu->Auxiliar->FieldByName("Fecha")->AsInteger))
    {
          // Si hay un valor, lo asigno
          nVotos[0] = fMenu->Auxiliar->FieldByName("Votos")->AsInteger;

          pItem->SubItems->Strings[nItem - 1] = FormatFloat("###,##0", nVotos[0]);
          break;
    }

    Chart1->Series[Chart1->SeriesCount() - 1]->Add(nVotos[0], fMenu->Auxiliar->FieldByName("Fecha")->AsInteger,
                                                              (TColor)fMenu->Auxiliar->FieldByName("Color")->AsInteger);
}


Casimiro Notevi 07-11-2019 11:19:20

¿Y si pones 1 tampoco?

Angel.Matilla 07-11-2019 11:52:16

Cita:

Empezado por Casimiro Notevi (Mensaje 534332)
¿Y si pones 1 tampoco?

Tampoco. Y creo que ya me he dado cuenta de por qué: Porque no todos los partidos tiene votos en todos los años y al hacer el Add en TChart va añadiendo lo que encuentra; es decir que:
Cita:

Para PP va añadiendo 120124 y 2000 (índice 0); 110322 y 2004 (índice 1); 115991 y 2008 (índice 2)...
Cuando llega a PD hace esto:
Cita:

36011 y 2015 (índice 0); 36677 y 2016 (índice 1) y 26770 y 2019 (índice 2)
Por eso hace lo que hace. Tengo que ver como rellenar el año aunque no tenga datos para ese partido.

Casimiro Notevi 07-11-2019 12:12:02

Cita:

Empezado por Angel.Matilla (Mensaje 534333)
Por eso hace lo que hace. Tengo que ver como rellenar el año aunque no tenga datos para ese partido.

Eso quería decirte con lo de que pusieras ceros.

Angel.Matilla 07-11-2019 12:19:14

Cita:

Empezado por Casimiro Notevi (Mensaje 534334)
Eso quería decirte con lo de que pusieras ceros.

No, el año nunca lo puedo poner a cero; tengo que rellenar todos los campos para todas las líneas. Voy a darle un vuelta.

Angel.Matilla 07-11-2019 12:25:20

Dicho de otra forma: Tengo que sacar todos los años para todos los partidos, independientemente de si tienen o no votos registrados.

Angel.Matilla 07-11-2019 19:48:10

Como vía query no se me ocurre como sacar todos los años para todos los partidos, al margen de si tiene o nom votos registrados, lo h hecho de una forma un poco más pedestre, pero funciona.
Código:

Chart1->Chart3DPercent                = 10;
Chart1->Title->Font->Style            = TFontStyles() << fsBold;
Chart1->BottomAxis->Title->Caption    = "Años";
Chart1->BottomAxis->Title->Font->Style = TFontStyles() << fsBold;
Chart1->BottomAxis->Labels            = fMenu->Auxiliar->FieldByName("Fecha")->AsInteger;
Chart1->LeftAxis->Title->Caption      = "Votos";
Chart1->LeftAxis->Title->Font->Style  = TFontStyles() << fsBold;

cAux = "";
for (; !fMenu->Auxiliar->Eof; fMenu->Auxiliar->Next())
{
    if (fMenu->Auxiliar->FieldByName("Sigla")->AsString != cAux)
    {
          pItem = Evolucion->Items->Add();
          pItem->Caption = (cAux = fMenu->Auxiliar->FieldByName("Sigla")->AsString);
          for (nItem = 1; nItem < Evolucion->Columns->Count; nItem ++)
              pItem->SubItems->Add("");
    }

    for (nItem = 1; nItem < Evolucion->Columns->Count; nItem ++)
          if (Evolucion->Columns->Items[nItem]->Caption == IntToStr(fMenu->Auxiliar->FieldByName("Fecha")->AsInteger))
              pItem->SubItems->Strings[nItem - 1] = FormatFloat("###,##0", fMenu->Auxiliar->FieldByName("Votos")->AsInteger);
}

for (int nRow = 0; nRow < Evolucion->Items->Count; nRow ++)
{
    fMenu->Auxiliar->First();
    for (; !fMenu->Auxiliar->Eof; fMenu->Auxiliar->Next())
    {
          if (Evolucion->Items->Item[nRow]->Caption == fMenu->Auxiliar->FieldByName("Sigla")->AsString)
          {
              Chart1->AddSeries(&TLineSeries(Chart1));
              Chart1->Series[Chart1->SeriesCount() - 1]->Title      = fMenu->Auxiliar->FieldByName("Sigla")->AsString;
              Chart1->Series[Chart1->SeriesCount() - 1]->SeriesColor = (TColor)fMenu->Auxiliar->FieldByName("Color")->AsInteger;
              break;
          }
    }

    for (int nCol = 1; nCol < Evolucion->Columns->Count; nCol ++)
          Chart1->Series[Chart1->SeriesCount() - 1]->Add(StrToIntDef(StringReplace(Evolucion->Items->Item[nRow]->SubItems->Strings[nCol - 1], ".", "", oReplace), 0),
                                                        StrToInt(Evolucion->Columns->Items[nCol]->Caption),
                                                        (TColor)fMenu->Auxiliar->FieldByName("Color")->AsInteger);
}

No es la forma más elegante, pero funciona-

Casimiro Notevi 07-11-2019 21:20:43

En el select, si la suma es null puedes hacer que devuelva cero:
Código SQL [-]
 coalesce(sum(a.votos),0) votos

Angel.Matilla 08-11-2019 09:36:00

Cita:

Empezado por Casimiro Notevi (Mensaje 534345)
En el select, si la suma es null puedes hacer que devuelva cero:
Código SQL [-]
 coalesce(sum(a.votos),0) votos

El problema no es que la suma sea cero, el problema es que no todos tiene resultados todos los años. Por ejemplo:

Si te fijas hay partidos que como no se presentaron en unos años no pueden tener resultados y haría falta que aparecieran aunque no tengan resultado.


La franja horaria es GMT +2. Ahora son las 03:40:19.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi