// info  nam="SAMPLE04C"  tit="備品管理レポート"  dsc="説明用サンプル"  pro=3

  // リース等データ
typedef struct {
  char  lid[10];
  BYTE  ltp, ofc;
  char  dsc[40];
  int   ter;
  int   bdt, edt;
  int   mnp;
  int   amp;
  char  ven[24];
  char  len[24];
  char  lcd[40];
  char  rem[40];
  char  fil[12];
} LEADAT;

  // 保守契約データ
typedef struct {
  char  mid[10];
  BYTE  mtp, ofc;
  char  dsc[40];
  int   ter;
  int   bdt, edt;
  int   mnp;
  char  ven[24];
  char  mcd[40];
  char  rem[40];
  char  fil[12];
} MNTDAT;

void MonthlyCost(REAL *mc, int ym, int ofc)
{ // 月間コスト
  HTBL tb;
  LEADAT *p0, *p0e;
  MNTDAT *p1, *p1e;

  mc[0] = mc[1] = mc[2] = 0.0;
  tb = DBHTBL("LEADAT");
  for (p0 = (LEADAT *)TablePtr(tb), p0e = p0 + NTableRows(tb); p0 < p0e; p0++) {
    if (ofc == 0 || p0->ofc == ofc) {
      switch (p0->ltp) {
      case 0:
        if (ym >= p0->bdt) {
          if (ym <= date_serial(year(p0->bdt), month(p0->bdt) + p0->ter, 0)) {
            mc[0] += p0->mnp;
          } else if (ym <= p0->edt) {
            mc[0] += iround(p0->mnp / 10.0);
          }
        }
        break;
      case 1:
        if (ym >= p0->bdt && ym <= p0->edt) {
          mc[0] += p0->mnp;
        }
        break;
      case 2:
        if (ym == date_serial(year(p0->bdt), month(p0->bdt), 1)) {
          mc[2] += p0->amp;
        }
        break;
      }
    }
  }
  tb = DBHTBL("MNTDAT");
  for (p1 = (MNTDAT *)TablePtr(tb), p1e = p1 + NTableRows(tb); p1 < p1e; p1++) {
    if (ofc == 0 || p1->ofc == ofc) {
      if (ym >= p1->bdt && ym <= p1->edt) {
        mc[1] += p1->mnp;
      }
    }
  }
}

  // 系列数
#define  NSE   3
  // 項目数(計算年数)
#define  NYR  10

  // グラフの系列データ
typedef struct {
  PCSTR nam; // 系列名
  BGRC  col; // 色
} SERI;

  // グラフの項目データ
typedef struct {
  char  nam[8]; // 項目名
  REAL  val[NSE];// 値の配列
} ITMI;

  // グラフ作成情報
typedef struct {
  PCSTR grp; // 項目軸タイトル
  PCSTR unt; // 数値軸単位名称
  REAL  max; // 数値軸最大値
  REAL  div; // 数値軸目盛間隔
  SERI  ser[NSE]; // 系列データ
  ITMI  itm[NYR]; // 項目データ
} GRFI;

void CalcCost(GRFI *pd, int fy0, int ofc)
{ // 計算
  int i, j, k;
  REAL mc[NSE];

  for (i = 0; i < NYR; i++) {
    sprintf(pd->itm[i].nam, "%d年度", fy0 + i);
    for (k = 0; k < NSE; k++) {
      pd->itm[i].val[k] = 0.0;
    }
    for (j = 0; j < 12; j++) {
      MonthlyCost(mc, date_serial(fy0 + i, FYearMonth() + j, 1), ofc);
      for (k = 0; k < NSE; k++) {
        pd->itm[i].val[k] += mc[k];
      }
    }
  }
}

void DrawDataTable(HREP rp, PCCELL pc, GRFI *pd)
{ // グラフ作成情報を表として描画
  int i, j, nr, nc, dt;
  REAL rh, va, vs;
  char bf[32];
  GRID grd;

  nr = NYR + 1;
  nc = NSE + 2;
  rh = (pc->y2 - pc->y1) / nr;
  SetGrid0(&grd, pc->x1, pc->y1, nc, nr, (pc->x2 - pc->x1) / nc, rh);
  SetTextFont(rp, NULL, rh / 2, 0, 0);
  SetCellMargin(rp, rh / 8, 0.0);
  for (i = 0; i < nr; i++) {
    for (j = 0; j < nc; j++) {
      if (i == 0) {
        if (j == 0) {
          sprintf(bf, pd->grp);
        } else if (j < nc-1) {
          sprintf(bf, pd->ser[j-1].nam);
        } else {
          sprintf(bf, "合計");
        }
        dt = DT_CEN;
      } else {
        if (j == 0) {
          sprintf(bf, pd->itm[i-1].nam);
          vs = 0.0; dt = DT_CEN;
        } else if (j < nc-1) {
          csprintf(bf, "%.0f", va = pd->itm[i-1].val[j-1]);
          vs += va; dt = DT_RGT;
        } else {
          csprintf(bf, "%.0f", vs);
          dt = DT_RGT;
        }
      }
      GridCellText(rp, &grd, i, j, RST_R_M, bf, dt);
    }
  }
}

void DrawBarChart(HREP rp, PCCELL pc, GRFI *pd)
{ // 積み上げ棒グラフの描画
  int i, j;
  REAL x0, y0, wc, sc, x1, x2, y1, y2;
  CELL cel;

  x0 = pc->x1 + (pc->x2 - pc->x1) * 0.10;
  y0 = pc->y2 - (pc->y2 - pc->y1) * 0.10;
  x1 = pc->x2 - (pc->x2 - pc->x1) * 0.05;
  y1 = pc->y1 + (pc->y2 - pc->y1) * 0.05;
  wc = (pc->x2 - pc->x1) * 0.85 / NYR;
  sc = (pc->y2 - pc->y1) * 0.85 / pd->max;
  SetTextFont(rp, NULL, wc / 5, 0, 0);
  SetCellMargin(rp, wc / 20, 0.0);
  SetLineStyle(rp, LST_THN);
  DrawLine(rp, x0, y0, x0, y1);
  DrawLine(rp, x1, y0, x1, y1);
  for (y2 = y0; y2 > y1; y2 -= pd->div * sc) {
    SetCell(&cel, pc->x1, y2 - wc / 5, x0, y2 + wc / 5);
    CellText(rp, &cel, cformat("%.0f", (y0 - y2) / sc), DT_RGT);
    DrawLine(rp, x0, y2, x1, y2);
  }
  DrawLine(rp, x0, y1, x1, y1);
  x1 = x0 + wc * 0.25;
  for (i = 0; i < NYR; i++) {
    x2 = x1 + wc * 0.5;
    y2 = y0;
    for (j = 0; j < NSE; j++) {
      y1 = y2 - pd->itm[i].val[j] * sc;
      SetCell(&cel, x1, y1, x2, y2);
      FillCell(rp, &cel, RST_NUL, pd->ser[j].col);
      y2 = y1;
    }
    SetCell(&cel, x1 - wc * 0.25, y0, x1 + wc * 0.75, y0 + wc / 2);
    CellText(rp, &cel, pd->itm[i].nam, DT_CEN);
    x1 += wc;
  }
}

  // 事業所
CODI diOFC[7] = {
  { 19, "本社" }, { 20, "仙台" }, { 23, "名古屋" }, { 24, "大阪" },
  { 26, "広島" }, { 27, "九州" }, {  0, "全社" }
};
CODS dsOFC = { diOFC, NELEM(diOFC) };

  // 入力データ
typedef struct {
  int   fy0; // 開始年度
  int   ofc; // 事業所コード
} IMPP;

BOOL ReportMain(HREP rp, int msg, int pg, UINT pa)
{ // ＯＡ機器類レポート
  int i, re;
  HOPN op;
  HBUF rb;
  CELL cel;
  char bf[16];
  static IMPP imp;
  static COLI ci[2] = {
    { TID_I4B, 6, "fy0", "開始年度(&Y)", },
    { TID_C4B, 6, "ofc", "事業所(&O)", NULL, CF_DDL, NULL, NULL, (UINT)&dsOFC, },
  };
  static COLS cs = { ci, NELEM(ci) };
  static TBLI ti = { &cs, };
  static GRFI dat;

  if (msg == REPM_CREATE) {

    dat.grp = "年度";
    dat.unt = "円";
    dat.max = 60000000.0;
    dat.div = 10000000.0;
    dat.ser[0].nam = "リース"; dat.ser[0].col = 0x4444ff;
    dat.ser[1].nam = "保守";   dat.ser[1].col = 0x44ff44;
    dat.ser[2].nam = "買取";   dat.ser[2].col = 0xff4444;

  } if (msg == REPM_SETUP) {

    imp.fy0 = year(today()) - NYR;
    rb = CreateRowBufX(&imp, &ti);
    re = EditRowDlgBox(hWND(rp), rb, "ＯＡ機器類レポート");
    DeleteRowBuf(rb);
    if (!re) return FALSE;
    if (!ConnectDB("SAMPLE04A")) return FALSE;
    op = OpenTables("LEADAT, MNTDAT", OM_RDO);
    if (!op) { DisconnectDB(); return FALSE;}
    CalcCost(&dat, imp.fy0, imp.ofc);
    CloseTables(op, FALSE);
    DisconnectDB();

  } else if (msg == REPM_DRAWPAGE) {

    SetCell(&cel, BodyLeft(rp), BodyTop(rp), BodyRight(rp), BodyTop(rp) + 20.0);
    SetTextFont(rp, NULL, 5.0, 0, 0);
    CellText(rp, &cel, format("ＯＡ機器類コスト推移（%s）", codstr(&dsOFC, imp.ofc)), DT_CEN);
    SetCell(&cel, BodyLeft(rp), BodyTop(rp), BodyRight(rp), BodyTop(rp) + BodyHeight(rp) / 2);
    DrawCell(rp, &cel, RST_THN);
    ResizeCell(MoveCell(&cel, 15.0, 20.0), -30.0, -30.0);
    DrawDataTable(rp, &cel, &dat);
    SetCell(&cel, BodyLeft(rp), BodyTop(rp) + BodyHeight(rp) / 2, BodyRight(rp), BodyBottom(rp));
    DrawCell(rp, &cel, RST_THN);
    DrawBarChart(rp, &cel, &dat);

  }
  return TRUE;
}
