{$IFNDEF UPRINT_VIEJO}
unit uPrint;
{$MODE Delphi}
{$IFDEF APLICACION_CONSOLA}
{xDEFINE SIMRES3SOLOTEXTO}
{$ENDIF}

{$IFDEF LINUX}
{$DEFINE SIM_EXCEL}
{$ENDIF}
{$IFDEF FORM_LIBRO_SIMSEE}
{$DEFINE SIM_EXCEL}
{$ENDIF}
interface

uses
{$IFNDEF SIMRES3SOLOTEXTO}
{$IFDEF WINDOWS}
  Windows,
  XLConst,
  ComObj,
{$ENDIF}
  uExcelFile,
{$IFNDEF SVG_CANVAS}
{$IFDEF FP_CANVAS}
  ucoloresbasicos,
{$ELSE}
Graphics,
{$ENDIF}
{$ENDIF}
{$ENDIF}
  Math, xMatDefs,
//  uFechas,
  ucursorfila,
  SysUtils, uAuxiliares;

type
  TTipoGrafico = (areaApilada, dispersion, linea);   // OJO NO CAMBIAR EL ORDEN
  TDAOfTTipoGrafico = array of TTipoGrafico;
  TTipoEje = (Primario, Secundario);
  TTipoVariableDelEje = (tiempo, PE, CronVar);
  TDAOfTTipoEje = array of TTipoEje;
  TTipoValoresAComparar = (Promedios, DesviacionesEstandar, ProbabilidadesDeExcedencia, ValoresEnRiesgo, TodasLasCronicas );
{$IFNDEF SIMRES3SOLOTEXTO}
  TDAOfTColor = array of TColor;
{$ENDIF}

function nroColToExcelStrCol(nroCol: integer): string;

procedure WriteMatToText(nombreArch: string; idstr: string; mat: TMatOfNReal;
  titulo: string; nPasos: integer; nCronicas: integer; dtFechaPrimerPaso: TDateTime;
  dtPaso: double; digitos, decimales: integer; Print_Todas: boolean;
  Print_promedio: boolean; Pre_Ordenar: boolean; TipoImpresion_PE: boolean;
  Print_probAisladas: TDAofNReal);

{$IFNDEF SIMRES3SOLOTEXTO}
procedure chartMat_SimpleEje_ColoresAuto(xls: TExcelFile; nombreHoja: string;
  titulo, ejeY: string; colIni, colFin, filaIni, filaFin: integer;
  minEjeYAuto, maxEjeYAuto: boolean; minEjeY, MaxEjeY: NReal;
  minEjeX, MaxEjeX: NReal; tipoGrafico: TTipoGrafico; dtPaso: TDateTime);

procedure chartMat_MultiEje_Coloreable(
  xls: TExcelFile; nombreHoja: string;
  titulo: string;
  titulo_eje1: string;
  colIni, colFin, filaIni, filaFin: integer;
  minEjeYAuto_eje1, maxEjeYAuto_eje1: boolean; minEjeY_eje1, MaxEjeY_eje1: NReal;
  minEjeX, MaxEjeX: NReal; tiposDeGrafico: TDAOfTTipoGrafico;
  ejes: TDAOfTTipoEje; colores: TDAOfTColor; dtPaso: TDateTime;
  nCronicas:integer;
  tipoVariableDelEjeX: TTipoVariableDelEje ;
  multi_xy: Boolean;
  titulo_ejeX : string = '';
  titulo_eje2: string = '';
  minEjeYAuto_eje2: boolean = true;
  maxEjeYAuto_eje2: boolean = true;
  minEjeY_eje2: NReal = 0.0;
  MaxEjeY_eje2: NReal = 100.0 );



(* ??? por ahora lo comento
procedure aplicarPropiedadesASeries(xls: TExcelFile; nombreHoja: String;
                                    tipoGraficoPrincipal: TTipoGrafico; tiposGraficos: TDAOfTTipoGrafico;
                                    ejes: TDAOfTTipoEje;
                                    colores: TDAOfTColor);
*)


procedure WriteMatToXLS(xls: TExcelFile; nombreHoja: string;
  mat: TMatOfNReal; titulo, unidades: string; nPasos: integer;
  nCronicas: integer; dtFechaPrimerPaso: TDateTime; dtPaso: double;
  decimales: integer; Print_Todas: boolean; Print_promedio: boolean;
  Pre_Ordenar: boolean; TipoImpresion_PE: boolean; Print_probAisladas: TDAofNReal;
  chart_Mat: boolean; minEjeYAuto, maxEjeYAuto: boolean; minEjeY, MaxEjeY: NReal);

procedure writeHistogramaGlobalToXls(xls: TExcelFile; nombreHoja: string;
  mat: TMatOfNReal; titulo, unidades: string; decimales: integer;
  minX, maxX: NReal; nPuntos: integer{;
                                     chart_Mat: boolean;
                                     minEjeYAuto, maxEjeYAuto: boolean;
                                     minEjeY, MaxEjeY: NReal});



procedure WriteMatToXLS_SinOrdenar(
  xls: TExcelFile; nombreHoja: string;
  mat: TMatOfNReal;
  titulo, unidades: string;
  titulosCols: TDAofString;
  nPasos: integer; nCronicas: integer; dtFechaPrimerPaso: TDateTime;
  dtPaso: double; decimales: integer; Print_promedio: boolean;
  chart_Mat: boolean; minEjeYAuto, maxEjeYAuto: boolean; minEjeY, MaxEjeY: NReal);


procedure WriteValoresToXLS(
  xls: TExcelFile; tipoValores: TTipoValoresAComparar;
  probExcedencia: NReal; Pre_Ordenar: boolean; ProbExcedencia_Sup: NReal;
  nombresVars: TDAofString; mats: array of TMatOfNReal;

  nombreVar_ejex: string;
  mat_ejex: TMatOfNReal;

  nombreHoja: string;
  titulo: string;

  dtFechaPrimerPaso: TDateTime; dtPaso: double;

  graficar: boolean; tiposGraficos: TDAOfTTipoGrafico;
  ejes: TDAOfTTipoEje; colores: TDAOfTColor;

  // Información del eje Y Primario
  titulo_eje1: string;
  digitos_eje1: integer;
  decimales_eje1: integer;
  minEjeYAuto_eje1: boolean;
  maxEjeYAuto_eje1: boolean;
  minEjeY_eje1: NReal;
  MaxEjeY_eje1: NReal;

  // Información del eje Y Secundario
  titulo_eje2: string = '';
  digitos_eje2: integer = 12;
  decimales_eje2: integer = 2;
  minEjeYAuto_eje2: boolean = true;
  maxEjeYAuto_eje2: boolean = true;
  minEjeY_eje2: NReal = 0.0;
  MaxEjeY_eje2: NReal = 100.0;

  TipoVariableDelEjeX: TTipoVariableDelEje = tiempo;
  titulo_ejeX:string='');

function TTipoGraficoToXLConst(tipoGrafico: TTipoGrafico;
  TipoPrincipal: TTipoGrafico = dispersion): integer;

function TTipoGraficoToString(tipoGrafico: TTipoGrafico): string;
function StringToTTipoGrafico(tipoGrafico: string): TTipoGrafico;

function TTipoEjeToXLConst(tipoEje: TTipoEje): integer;
function TTipoEjeToString(tipoEje: TTipoEje): string;
function TEjeToString(Eje: TTipoVariableDelEje): string;
function StringToTTipoEje(tipoEje: string): TTipoEje;
function StringToTEje(Eje: string): TTipoVariableDelEje;

function TTipoValoresACompararToString(tipoValoresAComparar:
  TTipoValoresAComparar): string;

function StringToTTipoValoresAComparar(tipoValoresAComparar: string):
  TTipoValoresAComparar;

function TTipoValoresACompararToShortStringSingular_(tipoValoresAComparar:
  TTipoValoresAComparar; probExcedencia, probExcedencia2: NReal): string;

{$ENDIF}



resourcestring
  RS_DISPERSION = 'Dispersión';
  RS_AREAS_APILADAS = 'Areas Apiladas';
  RS_PROBABILIDAD_ACUMULADA = 'Probabilidad Acumulada';
  RS_XLS_PROMEDIO = 'VE';
  RS_XLS_DESVIACION_ESTANDAR = 'DesvE_';
  RS_XLS_PROBABILIDAD_DE_EXCEDENCIA = 'PE_';
  RS_XLS_VALOR_EN_RIESGO = 'VaR_';
  RS_XLS_TODAS_LAS_CRONICAS = 'Todas las crónicas';



implementation

function promediarProbs(const v: TDAofNReal; kCron1, kCron2: integer): NReal;
var
  a: NReal;
  k: integer;
begin
  a := 0;
  for k := kCron1 to kCron2 do
    a := a + v[k];
  Result := a / (kCron2 - kCron1 + 1);
end;


function nroColToExcelStrCol(nroCol: integer): string;
const
  ExcelCols = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var
  iLetra: integer;
  res: string;
begin
  res := '';

  while nroCol > Length(ExcelCols) do
  begin
    iLetra := nroCol div Length(ExcelCols);
    res := res + ExcelCols[iLetra];
    nroCol := nroCol - iLetra * Length(ExcelCols);
  end;
  res := res + ExcelCols[nroCol];

  Result := res;
end;

procedure WriteMatToText(nombreArch: string; idstr: string; mat: TMatOfNReal;
  titulo: string; nPasos: integer; nCronicas: integer; dtFechaPrimerPaso: TDateTime;
  dtPaso: double; digitos, decimales: integer; Print_Todas: boolean;
  Print_promedio: boolean; Pre_Ordenar: boolean; TipoImpresion_PE: boolean;
  Print_probAisladas: TDAofNReal);

var
  sal: textfile;
  iCronica, iPaso: integer;
  fechaDelPaso: TDateTime;
  iProbAisladas: array of integer;
  aprom: NReal;
  kProb: integer;
  hayAdicionales: boolean;
  aval: NReal;
begin
  setlength(iProbAisladas, length(Print_probAisladas));
  for kProb := 0 to high(Print_probAisladas) do
  begin
    iCronica := round(NCronicas * Print_probAisladas[kProb]) - 1;
    if iCronica < 0 then
      iCronica := 0;
    iProbAisladas[kProb] := iCronica;
  end;

  hayAdicionales := Print_promedio or (length(Print_probAisladas) > 0);

  if pos('.', nombreArch) = 0 then
    assignfile(sal, nombreArch + '_rpex.xlt')
  else
    assignfile(sal, nombreArch);

  rewrite(sal);

  writeln(sal, '# '+titulo+' '+idstr);
  Write(sal, 'paso');

  if Print_Todas then
  begin
    Write(sal, #9);
    for iCronica := 0 to NCronicas - 1 do
      Write(sal, #9, ((iCronica + 1) / NCronicas * 100): 6: 1, '%');
  end;

  if hayAdicionales then
  begin
    Write(sal, #9, #9);
    if Print_Promedio then
      Write(sal, #9, 'Prom');
    if TipoImpresion_PE then
    begin
      for kProb := 0 to high(iProbAisladas) do
        Write(sal, #9, 'PE' + FloatToStrF(Print_ProbAisladas[kProb] *
          100, ffFixed, 6, 1) + '%');
    end
    else
    begin
      for kProb := 0 to high(iProbAisladas) do
        Write(sal, #9, 'VaR' + FloatToStrF(Print_ProbAisladas[kProb] *
          100, ffFixed, 6, 1) + '%');
      Write(sal, #9, 'VaR' + FloatToStrF(100, ffFixed, 6, 1) + '%');
    end;
  end;

  writeln(sal);
  for iPaso := 0 to NPasos - 1 do
  begin
    if Pre_Ordenar then
      QuickSort_Decreciente(mat[iPaso]);
    fechaDelPaso := dtFechaPrimerPaso + dtPaso * iPaso;
    Write(sal, iPaso);

    if Print_Todas then
      Write(sal, #9, DateTimeToStr(fechaDelPaso));

    aProm := 0;
    for iCronica := 0 to NCronicas - 1 do
    begin
      aval := mat[iPaso, iCronica];
      if Print_Todas then
        Write(sal, #9, FloatToStrF(aval, ffFixed, digitos, decimales));
      aProm := aProm + aval;
    end;
    aProm := aProm / NCronicas;

    if hayAdicionales then
    begin
      Write(sal, #9, #9, DateTimeToStr(fechaDelPaso));
      if Print_Promedio then
        Write(sal, #9, FloatToStrF(aProm, ffFixed, digitos, decimales));

      if TipoImpresion_PE then
      begin
        for kProb := 0 to high(iProbAisladas) do
          Write(sal, #9, FloatToStrF(mat[iPaso, iProbAisladas[kProb]]
            , ffFixed, digitos, decimales));
      end
      else
      begin
        aval := promediarProbs(mat[iPaso], 0, iProbAisladas[0]);

        Write(sal, #9, FloatToStrF(aval, ffFixed, digitos, decimales));
        for kProb := 1 to high(iProbAisladas) do
        begin
          aval := promediarProbs(mat[iPaso], iProbAisladas[kProb - 1],
            iProbAisladas[kProb]);
          Write(sal, #9, FloatToStrF(aval, ffFixed, digitos, decimales));
        end;
        aval := promediarProbs(mat[iPaso], iProbAisladas[high(iProbAisladas)],
          NCronicas - 1);
        Write(sal, #9, FloatToStrF(aval, ffFixed, digitos, decimales));
      end;
    end;
    writeln(sal);
  end;
  writeln(sal);
  closefile(sal);
end;

{$IFNDEF SIMRES3SOLOTEXTO}

procedure chartMat_SimpleEje_ColoresAuto(xls: TExcelFile; nombreHoja: string;
  titulo, ejeY: string; colIni, colFin, filaIni, filaFin: integer;
  minEjeYAuto, maxEjeYAuto: boolean; minEjeY, MaxEjeY: NReal;
  minEjeX, MaxEjeX: NReal; tipoGrafico: TTipoGrafico; dtPaso: TDateTime);
var
  nombreHojaGrafico: Shortstring;
  {$IFNDEF SIM_EXCEL}
  hojag: variant;
  {$ENDIF}
begin
  nombreHojaGrafico := xls.graficar(PurificarNombreHoja(nombreHoja),
    colIni, colFin, filaIni, filaFin);

  xls.aplicarPropiedadesAGrafico(nombreHojaGrafico,
    TTipoGraficoToXLConst(TipoGrafico),
    titulo, ejeY, minEjeYAuto, maxEjeYAuto,
    minEjeY, MaxEjeY, minEjeX, MaxEjeX  );

  {$IFNDEF SIM_EXCEL}
  hojag := xls.v.Workbooks[1].Charts[nombreHojaGrafico];
  hojag.Select;
  hojag.Axes(xlCategory).Select;
  hojag.Axes(xlCategory).TickLabels.Orientation := xlHorizontal;
  if xls.version < 12.0 then // Office2007
    hojag.Axes(xlCategory).TickLabels.Orientation := 73
  else
    hojag.Axes(xlCategory).TickLabels.Orientation := -89;

  hojag.Axes(xlCategory).MajorTickMark := xlOutside;
  hojag.Axes(xlCategory).MinorTickMark := xlInside;
  hojag.Axes(xlCategory).TickLabelPosition := xlLow;


  //  hojag.Axes(xlCategory).MajorGridlines.Select;
  if abs( dtPaso - 1.0 / 24.0) < 0.00001 then
  begin
    if tipoGrafico = areaApilada then
    begin
      hojag.Axes(xlCategory).TickLabelSpacing := 24;
      hojag.Axes(xlCategory).TickMarkSpacing := 12;
    end
    else
    begin
      hojag.Axes(xlCategory).MajorUnit := 1;
      hojag.Axes(xlCategory).MinorUnit := 1 / 4;
    end;
  end
  else if dtPaso = 1 then
  begin
    hojag.Axes(xlCategory).HasMinorGridlines := False;
    if tipoGrafico = areaApilada then
    begin
      hojag.Axes(xlCategory).TickLabelSpacing := 7;
      hojag.Axes(xlCategory).TickMarkSpacing := 1;
    end
    else
    begin
      hojag.Axes(xlCategory).MajorUnit := 7;
      hojag.Axes(xlCategory).MinorUnit := 1;
    end;
  end
  else if dtPaso >= 7 then
  begin
    if tipoGrafico = areaApilada then
    begin
      hojag.Axes(xlCategory).TickLabelSpacing := 4;
      hojag.Axes(xlCategory).TickMarkSpacing := 1;
    end
    else
    begin
      hojag.Axes(xlCategory).MajorUnit := 365.2425 / 1.0;
      hojag.Axes(xlCategory).MinorUnit := 365.2425 / 3.0;
    end;
  end;


  hojag.Axes(xlCategory).HasMajorGridlines := True;
  hojag.Axes(xlCategory).HasMinorGridlines := True;

  hojag.Axes(xlCategory).MajorGridlines.Border.ColorIndex := 15;
  //    hojag.Axes(xlCategory).MajorGridlines.Border.Weight:= xlThick;
  hojag.Axes(xlCategory).MajorGridlines.Border.LineStyle := xlDashDot;


  hojag.Axes(xlCategory).MinorGridlines.Border.ColorIndex := 15;
  hojag.Axes(xlCategory).MinorGridlines.Border.Weight := xlHairline;
  hojag.Axes(xlCategory).MinorGridlines.Border.LineStyle := xlDot;

{$ENDIF}
end;

procedure chartMat_MultiEje_Coloreable(
  xls: TExcelFile; nombreHoja: string;
  titulo: string;
  titulo_eje1: string;
  colIni, colFin, filaIni, filaFin: integer;
  minEjeYAuto_eje1, maxEjeYAuto_eje1: boolean; minEjeY_eje1, MaxEjeY_eje1: NReal;
  minEjeX, MaxEjeX: NReal; tiposDeGrafico: TDAOfTTipoGrafico;
  ejes: TDAOfTTipoEje; colores: TDAOfTColor; dtPaso: TDateTime;
  nCronicas:integer;
  tipoVariableDelEjeX: TTipoVariableDelEje ;

  multi_xy: Boolean;

  titulo_ejeX : string = '';
  titulo_eje2: string = '';
  minEjeYAuto_eje2: boolean = true;
  maxEjeYAuto_eje2: boolean = true;
  minEjeY_eje2: NReal = 0.0;
  MaxEjeY_eje2: NReal = 100.0 );

var
  nombreHojaGrafico: WideString;
  iterTipoGrafico, tipoGraficoPrincipal: TTipoGrafico;

  i, max_cnt_TiposGraficos: integer;
  cnt_TiposGraficos: array [TTipoGrafico] of integer;
  tipoPrincipal: integer;
  {$IFNDEF SIM_EXCEL}
  hojag: variant;
  eje_x, plot_area: variant;
  AltoPlotArea: double;
  {$ENDIF}

begin

  // limpiamo los contadores
  for iterTipoGrafico := low(cnt_TiposGraficos) to high(cnt_TiposGraficos) do
    cnt_TiposGraficos[iterTipoGrafico] := 0;

  // recorremos el vector de tipos para contar cuantos hay de cada tipo
  for i := 0 to high(tiposDeGrafico) do
    Inc(cnt_TiposGraficos[tiposDeGrafico[i]]);


  // determinamos el tipo cuyo contador de máximo y lo definimos como el TipoGraficoPrincipal
  max_cnt_TiposGraficos := 0;
  tipoGraficoPrincipal := dispersion;
  for iterTipoGrafico := low(cnt_TiposGraficos) to high(cnt_TiposGraficos) do
    if cnt_TiposGraficos[iterTipoGrafico] > max_cnt_TiposGraficos then
    begin
      max_cnt_TiposGraficos := cnt_TiposGraficos[iterTipoGrafico];
      tipoGraficoPrincipal := iterTipoGrafico;
    end;

  // xls.VisibleOn;

  TipoPrincipal := TTipoGraficoToXLConst(tipoGraficoPrincipal);

  {$IFNDEF SIM_EXCEL}
  nombreHojaGrafico := xls.graficar(PurificarNombreHoja(nombreHoja),
    colIni, colFin, filaIni, filaFin, TipoPrincipal);
  xls.aplicarPropiedadesAGrafico(nombreHojaGrafico,
    TipoPrincipal, titulo,
    titulo_eje1,
    minEjeYAuto_eje1, maxEjeYAuto_eje1,
    minEjeY_eje1, MaxEjeY_eje1,
    minEjeX, MaxEjeX, titulo_ejeX  );
  {$ELSE}

  if (tipoVariableDelEjeX =CronVar) and multi_xy then
    nombreHojaGrafico := xls.graficarXY(PurificarNombreHoja(nombreHoja),
      colIni, colFin, filaIni, filaFin,nCronicas)
  else
     nombreHojaGrafico := xls.graficar(PurificarNombreHoja(nombreHoja),
       colIni, colFin, filaIni, filaFin);

  xls.aplicarPropiedadesAGrafico(nombreHojaGrafico,
    TipoPrincipal, titulo,
    titulo_eje1,
    minEjeYAuto_eje1, maxEjeYAuto_eje1,
    minEjeY_eje1, MaxEjeY_eje1,
    minEjeX, MaxEjeX, titulo_ejeX,
    titulo_eje2,
    minEjeYAuto_eje2, maxEjeYAuto_eje2,
    minEjeY_eje2, MaxEjeY_eje2
    );
  {$ENDIF}



  for i := 0 to high(tiposDeGrafico) do
  begin
    xls.aplicarPropiedadesASerie(nombreHojaGrafico, i + 1,
      TTipoGraficoToXLConst(tipoGraficoPrincipal),
      TTipoGraficoToXLConst(tiposDeGrafico[i], TipoGraficoPrincipal),
      TTipoEjeToXLConst(ejes[i]),
      colores[i], // Color de línea
      clNone );  // color fondo del marcador
  end;

  {$IFNDEF SIM_EXCEL}
  //  if TTipoGraficoToXLConst(tipoGraficoPrincipal) = xlAreaStacked then
  begin
    hojag := xls.v.Workbooks[1].Charts[nombreHojaGrafico];
    hojag.Select;
 (*
    hojag.ChartType := xlAreaStacked;
    for i := 0 to high(tiposDeGrafico) do
      hojag.SeriesCollection(i + 1).ChartType := TTipoGraficoToXLConst(tiposDeGrafico[i]);
   *)
    eje_x := hojag.Axes(xlCategory);
    eje_x.Select;
    eje_x.TickLabels.NumberFormat := WideString('0.00000000');
    if dtPaso >= 1 then
      eje_x.TickLabels.NumberFormat := WideString(ShortDateFormat)
    else
      eje_x.TickLabels.NumberFormat := WideString(ShortDateFormat + ' hh');

    hojag.Axes(xlCategory).Select;
    hojag.Axes(xlCategory).TickLabels.Orientation := xlHorizontal;
    if xls.version < 12.0 then  // Office2007
      hojag.Axes(xlCategory).TickLabels.Orientation := 73
    else
      hojag.Axes(xlCategory).TickLabels.Orientation := -89;

    hojag.Axes(xlCategory).MajorTickMark := xlOutside;
    hojag.Axes(xlCategory).MinorTickMark := xlInside;

    hojag.Axes(xlCategory).TickLabelPosition := xlLow;

    hojag.Axes(xlCategory).HasMajorGridlines := True;
    hojag.Axes(xlCategory).HasMinorGridlines := True;

    hojag.Axes(xlCategory).MajorGridlines.Border.ColorIndex := 15;
    //  hojag.Axes(xlCategory).MajorGridlines.Border.Weight:= xlThick;
    hojag.Axes(xlCategory).MajorGridlines.Border.LineStyle := xlDashDot;

    // hojag.Axes(xlCategory).MinorGridlines.Select;
    hojag.Axes(xlCategory).MinorGridlines.Border.ColorIndex := 15;
    hojag.Axes(xlCategory).MinorGridlines.Border.Weight := xlHairline;
    hojag.Axes(xlCategory).MinorGridlines.Border.LineStyle := xlDot;

     (*** ATENCION, LUEGO DE GRAFICAR; cambio el formato de la serie
    temporal si dt < 1 para que el Excel grafique bien.
    Este cambio hay que hacerlo antes de fijar las líneas de división
    para que las mismas queden ok.
    *****)
   if TipoGraficoPrincipal = areaApilada then
   begin
    if (dtPaso < 1) then
    begin
      xls.SelRango(filaIni + 1, colIni, filaFin, colIni);
      xls.CambiarFormato(xf_formatoStr(8));
    end;
   end;


    //  hojag.Axes(xlCategory).MajorGridlines.Select;
    if abs( dtPaso - 1.0 / 24.0 ) < 0.00001 then
    begin
      if tipoGraficoPrincipal = areaApilada then
      begin
        hojag.Axes(xlCategory).TickLabelSpacing := 24; //24
        hojag.Axes(xlCategory).TickMarkSpacing := 12;  //12
      end
      else
      begin
        hojag.Axes(xlCategory).MajorUnit := 1;
        hojag.Axes(xlCategory).MinorUnit := 1 / 4;
      end;
    end
    else if dtPaso = 1 then
    begin
      hojag.Axes(xlCategory).HasMinorGridlines := False;
      if tipoGraficoPrincipal = areaApilada then
      begin
        hojag.Axes(xlCategory).TickLabelSpacing := 7;
        hojag.Axes(xlCategory).TickMarkSpacing := 1;
        hojag.Axes(xlCategory).MajorUnit := 3;
        hojag.Axes(xlCategory).MajorUnitScale := xlMonths;
        hojag.Axes(xlCategory).MinorUnit := 1;
        hojag.Axes(xlCategory).MinorUnitScale := xlMonths;
      end
      else
      begin
        hojag.Axes(xlCategory).MajorUnit := 7;
        hojag.Axes(xlCategory).MinorUnit := 1;
      end;
    end
    else if dtPaso >= 7 then
    begin
      if tipoGraficoPrincipal = areaApilada then
      begin
        hojag.Axes(xlCategory).TickLabelSpacing := 4;
        hojag.Axes(xlCategory).TickMarkSpacing := 1;
      end
      else
      begin
        hojag.Axes(xlCategory).MajorUnit := 365.2425 / 1.0;
        hojag.Axes(xlCategory).MinorUnit := 365.2425 / 3.0;
      end;
    end;




    plot_area := hojag.PlotArea;
    hojag.ChartArea.Border.LineStyle := xlDash;
    Plot_Area.Border.LineStyle := xlDot;

    plot_area.Select;
    (*
    system.writeln( 'Chart Area TH: (', hojag.chartarea.top, ', ',  hojag.chartarea.height,')' );
    system.writeln( 'Plot Area TH: (', plot_area.top,', ' , plot_area.height,')');
    system.writeln( 'Eje_x TH: ', eje_x.top, ', ', eje_x.height,')' );
    *)
    //    plot_area.height:= hojag.chartarea.height - 88 - plot_area.top; // - eje_x.height;




  end;
  {$ENDIF}

  //  aplicarPropiedadesASeries(xls, nombreHojaGrafico, tipoGraficoPrincipal, tiposGraficos, ejes, colores);
end;

(*

procedure aplicarPropiedadesASeries(xls: TExcelFile; nombreHoja: String;
                                    tipoGraficoPrincipal: TTipoGrafico; tiposGraficos: TDAOfTTipoGrafico;
                                    ejes: TDAOfTTipoEje;
                                    colores: TDAOfTColor);
var
  hojag, serie: Variant;
  i: Integer;
  colorIndexI: Integer;
  versionOffice: NReal;
  aux: TPaletaColoresExcel;
begin
  hojag:= xls.Hoja(nombreHoja);

  versionOffice:= xls.version;
  if versionOffice < versionOffice2007 then
    aux:= xls.getPaletaColores;

  for i:= 0 to High(tiposGraficos) do
  begin
    serie:= hojag.SeriesCollection(i + 1);
    if tiposGraficos[i] <> tipoGraficoPrincipal then
      serie.ChartType:= TTipoGraficoToXLConst(tiposGraficos[i]);
    serie.AxisGroup:= TTipoEjeToXLConst(ejes[i]);

    if colores[i] <> colorAutomatico then
    begin
      if versionOffice < versionOffice2007 then
      begin
        colorIndexI:= getColorIndex(colores[i], aux);

        if tiposGraficos[i] in tiposGraficosConColorInterior then
          serie.Interior.Colorindex:= colorIndexI;
        serie.Border.Colorindex:= colorIndexI;
        if tiposGraficos[i] in tiposGraficosConMarcadores then
        begin
          serie.MarkerStyle:= xlAutomatic;
          serie.MarkerBackgroundColorIndex:= colorIndexI;
          serie.MarkerForegroundColorIndex:= colorIndexI;
        end;
      end
      else
      begin
        if tiposGraficos[i] in tiposGraficosConColorInterior then
          serie.Interior.Color:= colores[i];
        serie.Border.Color:= colores[i];
        if tiposGraficos[i] in tiposGraficosConMarcadores then
        begin
          serie.MarkerStyle:= xlAutomatic;
          serie.MarkerBackgroundColor:= colores[i];
          serie.MarkerForegroundColor:= colores[i];
        end;
      end;
    end;
  end;
end;
*)



procedure WriteMatToXLS(xls: TExcelFile; nombreHoja: string;
  mat: TMatOfNReal; titulo, unidades: string; nPasos: integer;
  nCronicas: integer; dtFechaPrimerPaso: TDateTime; dtPaso: double;
  decimales: integer; Print_Todas: boolean; Print_promedio: boolean;
  Pre_Ordenar: boolean; TipoImpresion_PE: boolean;
  Print_probAisladas: TDAofNReal; chart_Mat: boolean; minEjeYAuto,
  maxEjeYAuto: boolean; minEjeY, MaxEjeY: NReal);
var
  iCronica, iPaso: integer;
  fechaDelPaso: TDateTime;
  iProbAisladas: array of integer;
  aprom: NReal;
  kProb: integer;
  hayAdicionales: boolean;
  aval: NReal;
  colIni, colFin, filaIni, filaFin: integer;
  pe_ant: NReal;

begin

  setlength(iProbAisladas, length(Print_probAisladas));
  for kProb := 0 to high(Print_probAisladas) do
  begin
    iCronica := round(NCronicas * Print_probAisladas[kProb]) - 1;

    // previendo que alguien escriba porbabilidades <0 o > 1 o que
    // por algún redondeo nos vayamos de rango.
    if iCronica < 0 then
      iCronica := 0
    else if iCronica > (NCronicas - 1) then
      iCronica := (NCronicas - 1);

    iProbAisladas[kProb] := iCronica;
  end;

  hayAdicionales := Print_promedio or (length(Print_probAisladas) > 0);

  nombreHoja := PurificarNombreHoja(nombreHoja);
  xls.agregoHoja(nombreHoja);
  xls.go(nombreHoja, 1, 1);

  xls.writeln('# '+titulo + ' ' + unidades+' '+xls.idstr );

  //Para evitar el warning
  colIni := -1;
  colFin := -1;

  filaIni := xls.fila; // fila del encabezado
  filaFin := filaIni + nPasos; // ultima fila de datos


  xls.Writebuffereado('paso');

  if Print_Todas then
  begin
    colIni := xls.columnaBuffereada;
    colFin := colIni + nCronicas;
    xls.Writebuffereado('');
    for iCronica := 0 to NCronicas - 1 do
      xls.Writebuffereado((iCronica + 1) / NCronicas);
  end;

  if hayAdicionales then
  begin
    xls.Writebuffereado('');

    colIni := xls.columnaBuffereada;
    colFin := colIni + Length(Print_ProbAisladas);
    if Print_promedio then
      Inc(colFin);
    filaIni := xls.fila;
    filaFin := filaIni + nPasos;

    xls.Writebuffereado('');
    if Print_Promedio then
      xls.Writebuffereado('Prom');

    if TipoImpresion_PE then
    begin
      for kProb := 0 to high(iProbAisladas) do
        xls.Writebuffereado('Pe' + FloatToStrF(
          Print_ProbAisladas[kProb] * 100, ffFixed, 6, 1) + '%');
    end
    else
    begin
      inc( colFin );
      pe_ant:= 0;
      for kProb := 0 to high(iProbAisladas) do
      begin
        xls.Writebuffereado('VaR(' + FloatToStrF( pe_ant * 100, ffFixed, 6, 1)
          +'-'+ FloatToStrF( Print_ProbAisladas[kProb] * 100, ffFixed, 6, 1)
          + ')%');
         pe_ant:= Print_ProbAisladas[kProb];
      end;
      xls.Writebuffereado('VaR(' + FloatToStrF( pe_ant * 100, ffFixed, 6, 1)
        +'-'+ FloatToStrF( 100, ffFixed, 6, 1)
        + ')%');
    end;
  end;
  xls.writelnBuffer;

  for iPaso := 0 to NPasos - 1 do
  begin
    if Pre_Ordenar then
    QuickSort_Decreciente( mat[iPaso]);


    fechaDelPaso := dtFechaPrimerPaso + dtPaso * iPaso;
    xls.Writebuffereado(IntToStr(iPaso + 1));

    if Print_Todas then
   //   xls.Write_buffereado(DateTimeToIsoStr(fechaDelPaso));
      xls.Writebuffereado(fechaDelPaso);

    aProm := 0;
    if Print_Todas or Print_promedio then
    begin
      for iCronica := 0 to NCronicas - 1 do
      begin
        aval := mat[iPaso, iCronica];
        if Print_Todas then
          xls.Writebuffereado(aval);
        aProm := aProm + aval;
      end;
      aProm := aProm / NCronicas;
    end;

    if hayAdicionales then
    begin
      xls.Writebuffereado('');
 //     xls.Write_buffereado(DateTimeToIsoStr(fechaDelPaso));
      xls.Writebuffereado(fechaDelPaso);
  
      if Print_Promedio then
        xls.Writebuffereado(aProm);

      if TipoImpresion_PE then
      begin
        for kProb := 0 to high(iProbAisladas) do
          xls.Writebuffereado(mat[iPaso, iProbAisladas[kProb]]);
      end
      else
      begin
       aval := promediarProbs(mat[iPaso], 0, iProbAisladas[0]);

        xls.Writebuffereado(aval);
        for kProb := 1 to high(iProbAisladas) do
        begin
          aval := promediarProbs(mat[iPaso], iProbAisladas[kProb - 1],
            iProbAisladas[kProb]);
          xls.Writebuffereado(aval);
        end;
        aval := promediarProbs(mat[iPaso], iProbAisladas[high(iProbAisladas)],
          NCronicas - 1);
        xls.Writebuffereado(aval);
      end;
    end;
    xls.writelnBuffer;
  end;
  xls.writelnBuffer;


  {$IFNDEF SIM_EXCEL}
  // formatedo del área de datos
  xls.SelRango(filaIni + 1, colIni + 1, filaFin, colFin);
  if xls.version = 14 then
    xls.CambiarFormato(xf_formatoStr(decimales))
  else
    xls.CambiarFormato('General');
  {$ENDIF}

  // formatedo de las fechas
  xls.SelRango(filaIni + 1, colIni, filaFin, colIni);

  if (dtPaso < 1) then
    xls.CambiarFormato(SysUtils.ShortDateFormat + ' hh')
  else
    xls.CambiarFormato(SysUtils.ShortDateFormat);


  if chart_Mat then
  begin
    chartMat_SimpleEje_ColoresAuto(xls,
      nombreHoja, titulo, unidades,
      colIni, colFin, filaIni, filaFin,
      minEjeYAuto, maxEjeYAuto,
      minEjeY, MaxEjeY,
      dtFechaPrimerPaso, dtFechaPrimerPaso + (nPasos - 1) * dtPaso,
      dispersion, dtPaso);
  end;
end;


procedure writeHistogramaGlobalToXls(xls: TExcelFile; nombreHoja: string;
  mat: TMatOfNReal; titulo, unidades: string; decimales: integer; minX,
  maxX: NReal; nPuntos: integer);
var
  i, j, idxVal: integer;
  //  min, max: NReal;
  histo, histoAcum: TDAofNReal;
  x, invNPuntosCronicas, deltaMaxMin, invDeltaMaxMin, deltaX: NReal;

  //  filaContenido: TDAOfVariant;
  nFilas, nColumnas: integer;
  filaIni, filaFin, colIni, colFin: integer;
begin
  nombreHoja := PurificarNombreHoja(nombreHoja);

  deltaMaxMin := maxX - minX;
  invDeltaMaxMin := 1 / deltaMaxMin;
  deltaX := deltaMaxMin / (nPuntos - 1);
  nFilas:= length(mat);
  nColumnas:= length(mat[0]);
  invNPuntosCronicas := 1 / ( nFilas * nColumnas );

  SetLength(histo, nPuntos);

  for i := 0 to high(histo) do
    histo[i] := 0;


  for i := 0 to nFilas-1 do
  begin
    for j := 0 to nColumnas-1 do
    begin
      idxVal := trunc(((mat[i, j] - minX) * invDeltaMaxMin) * high(histo));
      if idxVal < 0 then
        idxVal := 0
      else if idxVal > high(histo) then
        idxVal := high(histo);
      histo[idxVal] := histo[idxVal] + invNPuntosCronicas;
    end;
  end;

  SetLength(histoAcum, length(histo));
  histoAcum[0] := histo[0];
  for i := 1 to high(histoAcum) do
    histoAcum[i] := histoAcum[i - 1] + histo[i];

  xls.agregoHoja(nombreHoja);
  xls.go(nombreHoja, 1, 1);

  xls.writeln('# '+titulo + ' ' + unidades+' '+xls.idstr );

  filaIni := xls.fila;   // fila del encabezado
  colIni  := xls.columnaBuffereada; // columna de datos
  filaFin := filaIni + length(histoAcum); // última fila de datos.
  colFin := colIni + 1; // seguna columna con las probabilidades

  xls.WriteBuffereado(titulo);
  xls.WriteBuffereado(RS_PROBABILIDAD_ACUMULADA);
  xls.writelnBuffer;
  x := minX;

  for i := 0 to high(histoAcum) do
  begin
    xls.WriteBuffereado(x);
    xls.WriteBuffereado(histoAcum[i]);
    xls.writelnBuffer;
    x := x + deltaX;
  end;


  // formatedo columna de valores de X
  xls.SelRango(filaIni + 1, colIni, filaFin, colIni);
  {$IFNDEF SIM_EXCEL}
  if xls.version = 14 then
    xls.CambiarFormato(xf_formatoStr(decimales))
  else
    xls.CambiarFormato('General');
  {$ENDIF}
  // formatedo las probabilidades acumuladas;
  xls.SelRango(filaIni + 1, colFin, filaFin, colFin);
  xls.CambiarFormato('0%');

  {
  if chart_Mat then
  begin
    chartMat(xls, nombreHoja, titulo, unidades, colIni, colFin, filaIni, filaFin,
    minEjeYAuto, maxEjeYAuto, minEjeY, MaxEjeY, 1/ Length(histo), 1, dispersion);
  end;
 }
end;

procedure WriteMatToXLS_SinOrdenar(xls: TExcelFile; nombreHoja: string;
  mat: TMatOfNReal; titulo, unidades: string; titulosCols: TDAofString;
  nPasos: integer; nCronicas: integer; dtFechaPrimerPaso: TDateTime;
  dtPaso: double; decimales: integer; Print_promedio: boolean;
  chart_Mat: boolean; minEjeYAuto, maxEjeYAuto: boolean; minEjeY, MaxEjeY: NReal);
var
  iCronica, iPaso: integer;
  fechaDelPaso: TDateTime;
  aprom: NReal;
  aval: NReal;
  colIni, colFin, filaIni, filaFin: integer;

  nHojas, kHoja: integer;
  iCronIni, iCronM, iCronFin: integer;
  sNombreHoja: string;
begin
  nombreHoja := PurificarNombreHoja(nombreHoja);
  //Para sacar el warning
  colIni := -1;
  filaIni := -1;
  ColFin := -1;
  filaFin := -1;

  nHojas := ((nCronicas - 1) div 250) + 1;

  for kHoja := 1 to nHojas do
  begin
    if (nHojas > 1) then
      sNombreHoja := nombreHoja + '_' + IntToStr(kHoja)
    else
      sNombreHoja := nombreHoja;

    xls.agregoHoja(sNombreHoja);

    iCronIni := (kHoja - 1) * 250;
    iCronFin := min((nCronicas - 1), iCronIni + 250 - 1);
    iCronM := max(iCronIni - 1, min(high(titulosCols), iCronFin));

    xls.go(sNombreHoja, 1, 1);
    xls.writeln('# '+titulo + ' ' + unidades+' ' +xls.idstr);

    filaIni := xls.fila;  // fila encabezado
    filaFin := filaIni + nPasos; // ultima fila de datos

    xls.WriteBuffereado('paso');

    colIni := xls.columnaBuffereada; // columna de fechas
    colFin := colIni + iCronFin - iCronIni + 1; // ultima columna de datos

    xls.WriteBuffereado('');


    for iCronica := iCronIni to iCronM do
      xls.WriteBuffereado(titulosCols[iCronica]);
    //Si faltaron titulos de columnas como parametro imprime Columna y su número
    for iCronica := iCronM + 1 to iCronFin do
      xls.WriteBuffereado('Col_' + IntToStr(iCronica + 1));

    if Print_promedio then
    begin
      Inc(colFin);
      xls.WriteBuffereado('Prom');
    end;

    xls.writelnBuffer;
    for iPaso := 0 to NPasos - 1 do
    begin
      fechaDelPaso := dtFechaPrimerPaso + dtPaso * iPaso;
      xls.WriteBuffereado(IntToStr(iPaso + 1));
//      xls.WriteBuffereado(DateTimeToIsoStr(fechaDelPaso));
      xls.WriteBuffereado(fechaDelPaso);

      aProm := 0;
      for iCronica := iCronIni to iCronFin do
      begin
        aval := mat[iPaso, iCronica];
        xls.WriteBuffereado(aval);
        aProm := aProm + aval;
      end;
      aProm := aProm / NCronicas;

      if Print_Promedio then
        xls.WriteBuffereado(aProm);
      xls.writelnBuffer;
    end;
    xls.writelnBuffer;

    // formatedo del área de datos
    xls.SelRango(filaIni + 1, colIni + 1, filaFin, colFin);

{$IFNDEF SIM_EXCEL}
    if xls.version = 14 then
      xls.CambiarFormato(xf_formatoStr(decimales))
    else
      xls.CambiarFormato('General');
{$ENDIF}
    // formatedo de las fechas
    xls.SelRango(filaIni + 1, colIni, filaFin, colIni);
    if (dtPaso < 1) then
      xls.CambiarFormato(SysUtils.ShortDateFormat + ' hh')
    else
      xls.CambiarFormato(SysUtils.ShortDateFormat);
  end;
  xls.writelnBuffer;

  if (nHojas = 1) and chart_Mat then
  begin

    chartMat_SimpleEje_ColoresAuto(xls,
      nombreHoja, titulo, unidades,
      colIni, colFin, filaIni, filaFin,
      minEjeYAuto, maxEjeYAuto,
      minEjeY, MaxEjeY,
      dtFechaPrimerPaso, dtFechaPrimerPaso + (nPasos - 1) * dtPaso, dispersion, dtPaso);
  end;
end;


{$ENDIF}

procedure Cronicas(
  const mats: array of TMatOfNReal;
  const matx: TMatOfNReal;
  iPaso: integer;
  var resultado: TDAofNReal );

var
  iCronVar, iCronica, max_iCronica, kCronica, k, nCronicas: integer;


begin
  k:=0;
  nCronicas:= length( mats[1][iPaso]);

  for iCronVar := 0 to high(mats) do
  begin
    max_iCronica:= high( mats[iCronVar][0] );
    for iCronica := 0 to nCronicas-1 do
    begin
      kCronica:= min( iCronica, max_iCronica );
      if iPaso < length( mats[iCronVar]) then
        resultado[k] := mats[iCronVar][iPaso][kCronica]
      else
        resultado[k] := mats[iCronVar][ high(mats[iCronVar])][ kCronica ];
      inc( k );
    end;
  end;

end;


procedure calcPromedios(const mats: array of TMatOfNReal; iPaso: integer;
  var resultado: TDAofNReal);
var
  i: integer;
begin
  for i := 0 to high(mats) do
    if iPaso < length(mats[i]) then
      resultado[i] := vprom(mats[i][iPaso])
    else
      resultado[i] := vprom(mats[i][high(mats[i])]);
end;


procedure calcDesviacionesEstandar(const mats: array of TMatOfNReal;
  iPaso: integer; var resultado: TDAofNReal);
var
  i, j: integer;
  proms: TDAofNReal;
  filaPaso: TDAofNReal;
begin
  SetLength(proms, length(mats));
  calcPromedios(mats, iPaso, proms);
for i := 0 to high(mats) do
begin
  if iPaso < length(mats[i]) then
    filaPaso := mats[i][iPaso]
  else
    filaPaso := mats[i][high(mats[i])];

  resultado[i] := 0;
  if length(filaPaso) > 1 then
  begin
    for j := 0 to High(filaPaso) do
      resultado[i] := resultado[i] + Sqr(filaPaso[j] - proms[i]);
    resultado[i] := resultado[i] / (Length(filaPaso) - 1);
  end;
end;
  SetLength(proms, 0);
end;

procedure calcProbsExcedencia(const mats: array of TMatOfNReal;
  preOrdenar: boolean; iPaso: integer; probExcedencia: NReal;
  var resultado: TDAofNReal);
var
  i, iProbExcedencia: integer;
  filaPaso: TDAofNReal;
  kPaso: integer;
begin
  for i := 0 to high(mats) do
  begin
    if iPaso < length(mats[i]) then
      kPaso := iPaso
    else
      kPaso := high(mats[i]);

    filaPaso := copy(mats[i][kPaso], 0, length(mats[i][kPaso]));

    if preOrdenar then
      QuickSort_Decreciente(filaPaso);
    iProbExcedencia := round(length(filaPaso) * probExcedencia) - 1;
    iProbExcedencia := max(0, min(high(filaPaso), iProbExcedencia));
    resultado[i] := filaPaso[iProbExcedencia];
    setlength( filaPaso, 0 );
  end;
end;



procedure calcValoresEnRiesgo(const mats: array of TMatOfNReal;
  preOrdenar: boolean; iPaso: integer; probExcedencia1, probExcedencia2: NReal;
  var resultado: TDAofNReal);
var
  i, j, iProbExcedencia1, iProbExcedencia2: integer;
  filaPaso: TDAofNReal;
  aval: NReal;
  kPaso: integer;

begin

  for i := 0 to high(mats) do
  begin

    if iPaso < length(mats[i]) then
      kPaso := iPaso
    else
      kPaso := high(mats[i]);

    filaPaso := copy(mats[i][kPaso], 0, length(mats[i][kPaso]));
    if preOrdenar then
      QuickSort_Decreciente(filaPaso);
    iProbExcedencia1 := trunc(high(filaPaso) * probExcedencia1);
    iProbExcedencia2 := trunc(high(filaPaso) * probExcedencia2);
    aval := 0;
    for j := iProbExcedencia1 to iProbExcedencia2 do
      aval := aval + filaPaso[j];
    resultado[i] := aval / (iProbExcedencia2 - iProbExcedencia1 + 1);
    setlength( filaPaso, 0 );
  end;
end;



{$IFNDEF SIMRES3SOLOTEXTO}
procedure WriteValoresToXLS(
  xls: TExcelFile;
  tipoValores: TTipoValoresAComparar;
  probExcedencia: NReal;
  Pre_Ordenar: boolean;
  ProbExcedencia_Sup: NReal;

  nombresVars: TDAofString;
  mats: array of TMatOfNReal;

  nombreVar_ejex: string;
  mat_ejex: TMatOfNReal;

  nombreHoja: string;

  titulo: string;

  dtFechaPrimerPaso: TDateTime; dtPaso: double;

  graficar: boolean; tiposGraficos: TDAOfTTipoGrafico;
  ejes: TDAOfTTipoEje; colores: TDAOfTColor;

  // Información del eje Y Primario
  titulo_eje1: string;
  digitos_eje1: integer;
  decimales_eje1: integer;
  minEjeYAuto_eje1: boolean;
  maxEjeYAuto_eje1: boolean;
  minEjeY_eje1: NReal;
  MaxEjeY_eje1: NReal;

  // Información del eje Y Secundario
  titulo_eje2: string = '';
  digitos_eje2: integer = 12;
  decimales_eje2: integer = 2;
  minEjeYAuto_eje2: boolean = true;
  maxEjeYAuto_eje2: boolean = true;
  minEjeY_eje2: NReal = 0.0;
  MaxEjeY_eje2: NReal = 100.0;

  TipoVariableDelEjeX: TTipoVariableDelEje = tiempo;
  titulo_ejeX:string=''
  );
var
  iPaso, iMats: integer;
  iVal: integer;
  valores: TDAofNReal;
  descTipoValor: string;
  colIni, colFin, filaIni, filaFin: integer;
  dtUltimoPaso: TDateTime;
  nFilas, nColumnas, nCronicas, TotCron,iCronVar,iCronica: integer;

begin
  nombreHoja := PurificarNombreHoja(nombreHoja);
  xls.agregoHoja(nombreHoja);
  xls.go(nombreHoja, 1, 1);

  if titulo_eje2  = '' then
    xls.writeln('# ' + titulo + ' ' + titulo_eje1+' '+xls.idstr )
  else
    xls.writeln('# '+titulo + ' ' + titulo_eje1+' '+xls.idstr + ' Eje2:' + titulo_eje2);

  xls.WriteBuffereado('paso');

  nCronicas:=length( mats[0][0]);
  nFilas:= Length( mats[0] );

  nColumnas:= length( mats );

  filaIni := xls.fila;
  filaFin := filaIni + nFilas;
  colIni  := xls.columnaBuffereada;

  colFin  := colIni + length(mats); //-1;

  TotCron:= nCronicas * ( nColumnas + 1 );

  if  tipoValores = TodasLasCronicas then
  begin
    SetLength( valores, TotCron );
    case tipoVariableDelEjeX of
      CronVar:
        colFin  := colIni + length(valores)-1;
      PE,tiempo:
        colFin  := colIni + length(valores)-1-(nCronicas - 1);
    end
  end
  else
    SetLength( valores, length( mats ));

  descTipoValor := TTipoValoresACompararToShortStringSingular_(tipoValores, probExcedencia, ProbExcedencia_Sup);


  //Escribo los encabezados de las series

  // PRIMER COLUMNA DEL ENCABEZADO
  case tipoVariableDelEjeX of
    tiempo: xls.WriteBuffereado('fecha');
    PE: xls.WriteBuffereado('PE');
    CronVar:  xls.WriteBuffereado( nombreVar_ejex );
   end;


  for iCronVar := 0 to high( mats) do
       xls.WriteBuffereado(nombresVars[iCronVar] ); // + '_' + descTipoValor);


  xls.writelnBuffer;


  for iPaso := 0 to nFilas -1  do
  begin
    case tipoValores of
      Promedios: calcPromedios( mats, iPaso, valores);
      DesviacionesEstandar: calcDesviacionesEstandar(mats, iPaso, valores);
      ProbabilidadesDeExcedencia: calcProbsExcedencia(mats, pre_Ordenar, iPaso,
          probExcedencia, valores);
      ValoresEnRiesgo: calcValoresEnRiesgo(mats, pre_Ordenar, iPaso,
          probExcedencia, ProbExcedencia_Sup, valores);
    {$IFDEF TODAS_LAS_CRONICAS}
    hay que revisar
      TodasLasCronicas:
          Cronicas(mats, iPaso, valores);   //todas las cronicas de todas las CronVars
    {$ENDIF}
    end; // del case

    xls.WriteBuffereado( iPaso + 1 );
    // xls.WriteBuffereado(DateTimeToIsoStr(dtFechaPrimerPaso + iPaso * dtPaso));

    //Escribo el ejex

    // Primer columna del ejeX
    case tipoVariableDelEjeX of
      tiempo: xls.WriteBuffereado( dtFechaPrimerPaso + iPaso * dtPaso);
      PE: xls.WriteBuffereado( iPaso / nfilas );
      {$IFDEF TODAS_LAS_CRONICAS}
      CronVar: xls.WriteBuffereado( valores[0] );
      {$ENDIF}
    end;

    if tipoValores = TodasLasCronicas  then
    begin
      {$IFDEF TODAS_LAS_CRONICAS}
      case tipoVariableDelEjeX of
        CronVar:
          for iVal := 1 to high(valores) do
            xls.WriteBuffereado(valores[iVal]);
        PE, tiempo:
           //las primeras nCronicas se desechan porque es basura
          for iVal := nCronicas to high(valores) do
            xls.WriteBuffereado(valores[iVal]);
      end;
      {$ENDIF}
    end
    else
    begin
       for iVal := 0 to high(valores) do
        xls.WriteBuffereado(valores[iVal]);
    end;

    xls.writelnBuffer;

  end;


  // formatedo del área de datos
  xls.SelRango(filaIni + 1, colIni + 1, filaFin, colFin);
  {$IFNDEF SIM_EXCEL}
  if xls.version = 14 then
    xls.CambiarFormato(xf_formatoStr(decimales_eje1))
  else
    xls.CambiarFormato('General');
  {$ENDIF}

  // formatedo de las fechas
  if tipoVariableDelEjeX = tiempo then
  begin
    xls.SelRango(filaIni + 1, colIni, filaFin, colIni);
    if (dtPaso < 1) then
      xls.CambiarFormato(SysUtils.ShortDateFormat + ' hh')
    else
      xls.CambiarFormato(SysUtils.ShortDateFormat );
  end;

  if graficar then
  begin
    case tipoVariableDelEjeX of
      tiempo:
        begin
          dtUltimoPaso:= dtFechaPrimerPaso +  high(mats[0]) * dtPaso ;
    //      titulo_ejeX:='';
        end;
      {$IFDEF TODAS_LAS_CRONICAS}
      CronVar:
        begin
          dtUltimoPaso:= valores[0];
          if titulo_ejeX = '' then
            titulo_ejeX:= nombresVars[0];
        end;
      {$ENDIF}
      PE:
        begin
          dtUltimoPaso:= 1.0 ;
          dtFechaPrimerPaso:= 0.0;
          if titulo_ejeX = '' then
            titulo_ejeX:='PE'
        end
    end;

    if descTipoValor <> 'VE' then
      titulo:= titulo +' ('+descTipoValor+')';


    chartMat_MultiEje_Coloreable(xls,
      nombreHoja, titulo, titulo_eje1,
      colIni, colFin, filaIni, filaFin,
      minEjeYAuto_eje1,
      maxEjeYAuto_eje1,
      minEjeY_eje1,
      MaxEjeY_eje1,
      dtFechaPrimerPaso, dtULtimoPaso ,
      tiposGraficos, ejes, colores, dtPaso,nCronicas,
      tipoVariableDelEjeX,
      tipoValores = TodasLasCronicas,
      titulo_ejeX,
      titulo_eje2,
      minEjeYAuto_eje2,
      maxEjeYAuto_eje2,
      minEjeY_eje2,
      MaxEjeY_eje2
      );

  end;

end;



function TTipoGraficoToXLConst(tipoGrafico: TTipoGrafico;
  TipoPrincipal: TTipoGrafico): integer;
begin
  case tipoGrafico of
    linea:
      {$IFDEF SIM_EXCEL}
      result:= xlXYScatterLines;
      {$ELSE}
      Result :=xlLine;
      {$ENDIF}
    dispersion:
      {$IFDEF SIM_EXCEL}
      Result := xlXYScatterLines;
      {$ELSE}
      if tipoPrincipal = dispersion then
        Result := xlXYScatterLines
      else
        Result := xlLineMarkers;
      {$ENDIF}
    areaApilada: Result := xlAreaStacked;
    else
      raise Exception.Create('uPrint.TTipoGraficoToXLConst: TTipoGrafico desconocido ' +
        IntToStr(Ord(tipoGrafico)));
  end;
end;

function TTipoGraficoToString(tipoGrafico: TTipoGrafico): string;
begin
  case tipoGrafico of
    //    linea       : result:= 'Líneas';
    areaApilada: Result := 'are';
    dispersion: Result := 'dis';
    else
      raise Exception.Create('uPrint.TTipoGraficoToString: tipo de grafico desconocido '
        + IntToStr(Ord(tipoGrafico)));
  end;
end;

function StringToTTipoGrafico(tipoGrafico: string): TTipoGrafico;
var
  flg_asignado: boolean;
begin
{  if CompareStr(tipoGrafico, 'Líneas') = 0 then
    result:= linea
  else }
  flg_asignado := False;


  if (pos('Area', tipoGrafico) > 0) or (tipoGrafico = 'are') then
    Result := areaApilada
  else if (pos('Disp', tipoGrafico) > 0) or (tipoGrafico = 'dis') then
    Result := dispersion
  else
    raise Exception.Create('uPrint.StringToTTipoGrafico: tipo de gráfico desconocido ' +
      tipoGrafico);
end;

function TTipoEjeToXLConst(tipoEje: TTipoEje): integer;
begin
  case tipoEje of
    Primario: Result := 1;
    Secundario: Result := 2;
    else
      raise Exception.Create('uPrint.TTipoEjeToXLConst: tipo de eje desconocido ' +
        IntToStr(Ord(tipoEje)));
  end;
end;

function TTipoEjeToString(tipoEje: TTipoEje): string;
begin
  case tipoEje of
    Primario: Result := 'pri';
    Secundario: Result := 'sec';
    else
      raise Exception.Create('uPrint.TTipoEjeToXLConst: tipo de eje desconocido ' +
        IntToStr(Ord(tipoEje)));
  end;
end;

function TEjeToString(Eje: TTipoVariableDelEje): string;
begin
  case Eje of
    tiempo: Result := 'tiempo';
    PE: Result := 'PE';
    CronVar: Result := 'CronVar';
    else
      raise Exception.Create('uPrint.TEjeToXLConst:  eje desconocido ' +
        IntToStr(Ord(Eje)));
  end;
end;

function StringToTTipoEje(tipoEje: string): TTipoEje;
begin
  if (tipoEje = 'Primario') or (tipoEje = 'pri') then
    Result := Primario
  else if (tipoEje = 'Secundario') or (tipoEje = 'sec') then
    Result := Secundario
  else
    raise Exception.Create('StringToTTipoEje: tipo de eje desconocido ' + tipoEje);
end;

function StringToTEje(Eje: string): TTipoVariableDelEje;
begin
  if (Eje = 'tiempo')  then
    Result := tiempo
  else if (Eje = 'PE')  then
    Result := PE
  else if (Eje = 'CronVar')  then
    Result := CronVar
  else
    raise Exception.Create('StringToTEje: tipo de eje desconocido ' + Eje);
end;

function TTipoValoresACompararToString(tipoValoresAComparar:
  TTipoValoresAComparar): string;
begin
  case tipoValoresAComparar of
    Promedios: Result := 'prom';
    DesviacionesEstandar: Result := 'desv';
    ProbabilidadesDeExcedencia: Result := 'pbex';
    ValoresEnRiesgo: Result := 'var';
    TodasLasCronicas: Result:= 'tdlcrs';
    else
      raise Exception.Create(
        'uPrintCronVars.TTipoValoresACompararToString: tipo de grafico desconocido ' +
        IntToStr(Ord(tipoValoresAComparar)));
  end;
end;

function StringToTTipoValoresAComparar(tipoValoresAComparar: string):
TTipoValoresAComparar;
begin
  if (tipoValoresAComparar = 'Promedios') or (tipoValoresAcomparar = 'prom') then
    Result := Promedios
  else if (tipoValoresAComparar = 'Desviaciones Estandar') or
    (tipoValoresAComparar = 'desv') then
    Result := DesviacionesEstandar
  else if (tipoValoresAComparar = 'Probabilidades de Excedencia') or
    (tipoValoresAComparar = 'pbex') then
    Result := ProbabilidadesDeExcedencia
  else if (tipoValoresAComparar = 'Valores en Riesgo') or
    (tipoValoresAComparar = 'var') then
    Result := ValoresEnRiesgo
  else if (tipoValoresAComparar = 'Todas las crónicas') or
      (tipoValoresAComparar = 'tdlcrs') then
      Result := TodasLasCronicas
  else
    raise Exception.Create(
      'uPrintCronVars.StringToTTipoValoresAComparar: tipo de gráfico desconocido ' +
      tipoValoresAComparar);
end;

function TTipoValoresACompararToShortStringSingular_(tipoValoresAComparar:
  TTipoValoresAComparar; probExcedencia, probExcedencia2 : NReal): string;
begin
  case tipoValoresAComparar of
    Promedios: Result := RS_XLS_PROMEDIO;
    DesviacionesEstandar: Result := RS_XLS_DESVIACION_ESTANDAR;
    ProbabilidadesDeExcedencia: Result :=
        RS_XLS_PROBABILIDAD_DE_EXCEDENCIA + ' ' +
        FloatToStrF(probExcedencia * 100, ffFixed, 6, 2) + '%';
    ValoresEnRiesgo: Result :=
        RS_XLS_VALOR_EN_RIESGO + ' ' + FloatToStrF(probExcedencia *
        100, ffFixed, 6, 2) + '-'+ FloatToStrF(probExcedencia2 *
        100, ffFixed, 6, 2) +'%';
    TodasLasCronicas: Result:= RS_XLS_TODAS_LAS_CRONICAS;
    else
      raise Exception.Create(
        'uPrintCronVars.TTipoValoresACompararToShortStringSingular: tipo de grafico desconocido '
        + IntToStr(Ord(tipoValoresAComparar)));
  end;
end;

{$ENDIF}
end.


{$ELSE}


unit uPrint;

{$MODE Delphi}
{$IFDEF APLICACION_CONSOLA}
{xDEFINE SIMRES3SOLOTEXTO}
{$ENDIF}

{$IFDEF LINUX}
{$DEFINE SIM_EXCEL}
{$ENDIF}
{$IFDEF FORM_LIBRO_SIMSEE}
{$DEFINE SIM_EXCEL}
{$ENDIF}
interface

uses
{$IFNDEF SIMRES3SOLOTEXTO}
{$IFDEF WINDOWS}
  Windows,
  XLConst,
  ComObj,
{$ENDIF}
  uExcelFile,
{$IFNDEF SVG_CANVAS}
{$IFDEF FP_CANVAS}
  ucoloresbasicos,
{$ELSE}
Graphics,
{$ENDIF}
{$ENDIF}
{$ENDIF}
  Math, xMatDefs,
  SysUtils, uAuxiliares, uFechas;

type
  TTipoGrafico = (areaApilada, dispersion, linea);   // OJO NO CAMBIAR EL ORDEN
  TDAOfTTipoGrafico = array of TTipoGrafico;
  TTipoEje = (Primario, Secundario);
  TTipoVariableDelEje = (tiempo, PE, CronVar);
  TDAOfTTipoEje = array of TTipoEje;
  TTipoValoresAComparar = (Promedios, DesviacionesEstandar, ProbabilidadesDeExcedencia, ValoresEnRiesgo, TodasLasCronicas );
{$IFNDEF SIMRES3SOLOTEXTO}
  TDAOfTColor = array of TColor;
{$ENDIF}

function nroColToExcelStrCol(nroCol: integer): string;

procedure WriteMatToText(nombreArch: string; idstr: string; mat: TMatOfNReal;
  titulo: string; nPasos: integer; nCronicas: integer; dtFechaPrimerPaso: TDateTime;
  dtPaso: double; digitos, decimales: integer; Print_Todas: boolean;
  Print_promedio: boolean; Pre_Ordenar: boolean; TipoImpresion_PE: boolean;
  Print_probAisladas: TDAofNReal);

{$IFNDEF SIMRES3SOLOTEXTO}
procedure chartMat_SimpleEje_ColoresAuto(xls: TExcelFile; nombreHoja: string;
  titulo, ejeY: string; colIni, colFin, filaIni, filaFin: integer;
  minEjeYAuto, maxEjeYAuto: boolean; minEjeY, MaxEjeY: NReal;
  minEjeX, MaxEjeX: NReal; tipoGrafico: TTipoGrafico; dtPaso: TDateTime);

procedure chartMat_MultiEje_Coloreable(
  xls: TExcelFile; nombreHoja: string;
  titulo: string;
  titulo_eje1: string;
  colIni, colFin, filaIni, filaFin: integer;
  minEjeYAuto_eje1, maxEjeYAuto_eje1: boolean; minEjeY_eje1, MaxEjeY_eje1: NReal;
  minEjeX, MaxEjeX: NReal; tiposDeGrafico: TDAOfTTipoGrafico;
  ejes: TDAOfTTipoEje; colores: TDAOfTColor; dtPaso: TDateTime;
  nCronicas:integer;
  tipoVariableDelEjeX: TTipoVariableDelEje ;
  multi_xy: Boolean;
  titulo_ejeX : string = '';
  titulo_eje2: string = '';
  minEjeYAuto_eje2: boolean = true;
  maxEjeYAuto_eje2: boolean = true;
  minEjeY_eje2: NReal = 0.0;
  MaxEjeY_eje2: NReal = 100.0 );



(* ??? por ahora lo comento
procedure aplicarPropiedadesASeries(xls: TExcelFile; nombreHoja: String;
                                    tipoGraficoPrincipal: TTipoGrafico; tiposGraficos: TDAOfTTipoGrafico;
                                    ejes: TDAOfTTipoEje;
                                    colores: TDAOfTColor);
*)


procedure WriteMatToXLS(xls: TExcelFile; nombreHoja: string;
  mat: TMatOfNReal; titulo, unidades: string; nPasos: integer;
  nCronicas: integer; dtFechaPrimerPaso: TDateTime; dtPaso: double;
  decimales: integer; Print_Todas: boolean; Print_promedio: boolean;
  Pre_Ordenar: boolean; TipoImpresion_PE: boolean; Print_probAisladas: TDAofNReal;
  chart_Mat: boolean; minEjeYAuto, maxEjeYAuto: boolean; minEjeY, MaxEjeY: NReal);

procedure writeHistogramaGlobalToXls(xls: TExcelFile; nombreHoja: string;
  mat: TMatOfNReal; titulo, unidades: string; decimales: integer;
  minX, maxX: NReal; nPuntos: integer{;
                                     chart_Mat: boolean;
                                     minEjeYAuto, maxEjeYAuto: boolean;
                                     minEjeY, MaxEjeY: NReal});



procedure WriteMatToXLS_SinOrdenar(xls: TExcelFile; nombreHoja: string;
  mat: TMatOfNReal; titulo, unidades: string; titulosCols: TDAofString;
  nPasos: integer; nCronicas: integer; dtFechaPrimerPaso: TDateTime;
  dtPaso: double; decimales: integer; Print_promedio: boolean;
  chart_Mat: boolean; minEjeYAuto, maxEjeYAuto: boolean; minEjeY, MaxEjeY: NReal);


procedure WriteValoresToXLS(
  xls: TExcelFile; tipoValores: TTipoValoresAComparar;
  probExcedencia: NReal; Pre_Ordenar: boolean; ProbExcedencia_Sup: NReal;
  nombresVars: TDAofString; mats: array of TMatOfNReal; nombreHoja: string;
  titulo: string;

  dtFechaPrimerPaso: TDateTime; dtPaso: double;

  graficar: boolean; tiposGraficos: TDAOfTTipoGrafico;
  ejes: TDAOfTTipoEje; colores: TDAOfTColor;

  // Información del eje Y Primario
  titulo_eje1: string;
  digitos_eje1: integer;
  decimales_eje1: integer;
  minEjeYAuto_eje1: boolean;
  maxEjeYAuto_eje1: boolean;
  minEjeY_eje1: NReal;
  MaxEjeY_eje1: NReal;

  // Información del eje Y Secundario
  titulo_eje2: string = '';
  digitos_eje2: integer = 12;
  decimales_eje2: integer = 2;
  minEjeYAuto_eje2: boolean = true;
  maxEjeYAuto_eje2: boolean = true;
  minEjeY_eje2: NReal = 0.0;
  MaxEjeY_eje2: NReal = 100.0;

  TipoVariableDelEjeX: TTipoVariableDelEje = tiempo;
  titulo_ejeX:string='');

function TTipoGraficoToXLConst(tipoGrafico: TTipoGrafico;
  TipoPrincipal: TTipoGrafico = dispersion): integer;

function TTipoGraficoToString(tipoGrafico: TTipoGrafico): string;
function StringToTTipoGrafico(tipoGrafico: string): TTipoGrafico;

function TTipoEjeToXLConst(tipoEje: TTipoEje): integer;
function TTipoEjeToString(tipoEje: TTipoEje): string;
function TEjeToString(Eje: TTipoVariableDelEje): string;
function StringToTTipoEje(tipoEje: string): TTipoEje;
function StringToTEje(Eje: string): TTipoVariableDelEje;

function TTipoValoresACompararToString(tipoValoresAComparar:
  TTipoValoresAComparar): string;
function StringToTTipoValoresAComparar(tipoValoresAComparar: string):
  TTipoValoresAComparar;
function TTipoValoresACompararToShortStringSingular_(tipoValoresAComparar:
  TTipoValoresAComparar; probExcedencia: NReal): string;

{$ENDIF}



resourcestring
  RS_DISPERSION = 'Dispersión';
  RS_AREAS_APILADAS = 'Areas Apiladas';
  RS_PROBABILIDAD_ACUMULADA = 'Probabilidad Acumulada';
  RS_XLS_PROMEDIO = 'Prom';
  RS_XLS_DESVIACION_ESTANDAR = 'DesvE';
  RS_XLS_PROBABILIDAD_DE_EXCEDENCIA = 'PE_';
  RS_XLS_VALOR_EN_RIESGO = 'VaR_';
  RS_XLS_TODAS_LAS_CRONICAS = 'Todas las crónicas';



implementation

function promediarProbs(const v: TDAofNReal; kCron1, kCron2: integer): NReal;
var
  a: NReal;
  k: integer;
begin
  a := 0;
  for k := kCron1 to kCron2 do
    a := a + v[k];
  Result := a / (kCron2 - kCron1 + 1);
end;


function nroColToExcelStrCol(nroCol: integer): string;
const
  ExcelCols = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var
  iLetra: integer;
  res: string;
begin
  res := '';

  while nroCol > Length(ExcelCols) do
  begin
    iLetra := nroCol div Length(ExcelCols);
    res := res + ExcelCols[iLetra];
    nroCol := nroCol - iLetra * Length(ExcelCols);
  end;
  res := res + ExcelCols[nroCol];

  Result := res;
end;

procedure WriteMatToText(nombreArch: string; idstr: string; mat: TMatOfNReal;
  titulo: string; nPasos: integer; nCronicas: integer; dtFechaPrimerPaso: TDateTime;
  dtPaso: double; digitos, decimales: integer; Print_Todas: boolean;
  Print_promedio: boolean; Pre_Ordenar: boolean; TipoImpresion_PE: boolean;
  Print_probAisladas: TDAofNReal);

var
  sal: textfile;
  iCronica, iPaso: integer;
  fechaDelPaso: TDateTime;
  iProbAisladas: array of integer;
  aprom: NReal;
  kProb: integer;
  hayAdicionales: boolean;
  aval: NReal;
begin
  setlength(iProbAisladas, length(Print_probAisladas));
  for kProb := 0 to high(Print_probAisladas) do
  begin
    iCronica := round(NCronicas * Print_probAisladas[kProb]) - 1;
    if iCronica < 0 then
      iCronica := 0;
    iProbAisladas[kProb] := iCronica;
  end;

  hayAdicionales := Print_promedio or (length(Print_probAisladas) > 0);

  if pos('.', nombreArch) = 0 then
    assignfile(sal, nombreArch + '_rpex.xlt')
  else
    assignfile(sal, nombreArch);

  rewrite(sal);

  writeln(sal, '# '+titulo+' '+idstr);
  Write(sal, 'paso');

  if Print_Todas then
  begin
    Write(sal, #9);
    for iCronica := 0 to NCronicas - 1 do
      Write(sal, #9, ((iCronica + 1) / NCronicas * 100): 6: 1, '%');
  end;

  if hayAdicionales then
  begin
    Write(sal, #9, #9);
    if Print_Promedio then
      Write(sal, #9, 'Prom');
    if TipoImpresion_PE then
    begin
      for kProb := 0 to high(iProbAisladas) do
        Write(sal, #9, 'PE' + FloatToStrF(Print_ProbAisladas[kProb] *
          100, ffFixed, 6, 1) + '%');
    end
    else
    begin
      for kProb := 0 to high(iProbAisladas) do
        Write(sal, #9, 'VaR' + FloatToStrF(Print_ProbAisladas[kProb] *
          100, ffFixed, 6, 1) + '%');
      Write(sal, #9, 'VaR' + FloatToStrF(100, ffFixed, 6, 1) + '%');
    end;
  end;

  writeln(sal);
  for iPaso := 0 to NPasos - 1 do
  begin
    if Pre_Ordenar then
      QuickSort_Decreciente(mat[iPaso]);
    fechaDelPaso := dtFechaPrimerPaso + dtPaso * iPaso;
    Write(sal, iPaso);

    if Print_Todas then
      Write(sal, #9, DateTimeToStr(fechaDelPaso));

    aProm := 0;
    for iCronica := 0 to NCronicas - 1 do
    begin
      aval := mat[iPaso, iCronica];
      if Print_Todas then
        Write(sal, #9, FloatToStrF(aval, ffFixed, digitos, decimales));
      aProm := aProm + aval;
    end;
    aProm := aProm / NCronicas;

    if hayAdicionales then
    begin
      Write(sal, #9, #9, DateTimeToStr(fechaDelPaso));
      if Print_Promedio then
        Write(sal, #9, FloatToStrF(aProm, ffFixed, digitos, decimales));

      if TipoImpresion_PE then
      begin
        for kProb := 0 to high(iProbAisladas) do
          Write(sal, #9, FloatToStrF(mat[iPaso, iProbAisladas[kProb]]
            , ffFixed, digitos, decimales));
      end
      else
      begin
        aval := promediarProbs(mat[iPaso], 0, iProbAisladas[0]);

        Write(sal, #9, FloatToStrF(aval, ffFixed, digitos, decimales));
        for kProb := 1 to high(iProbAisladas) do
        begin
          aval := promediarProbs(mat[iPaso], iProbAisladas[kProb - 1],
            iProbAisladas[kProb]);
          Write(sal, #9, FloatToStrF(aval, ffFixed, digitos, decimales));
        end;
        aval := promediarProbs(mat[iPaso], iProbAisladas[high(iProbAisladas)],
          NCronicas - 1);
        Write(sal, #9, FloatToStrF(aval, ffFixed, digitos, decimales));
      end;
    end;
    writeln(sal);
  end;
  writeln(sal);
  closefile(sal);
end;

{$IFNDEF SIMRES3SOLOTEXTO}

procedure chartMat_SimpleEje_ColoresAuto(xls: TExcelFile; nombreHoja: string;
  titulo, ejeY: string; colIni, colFin, filaIni, filaFin: integer;
  minEjeYAuto, maxEjeYAuto: boolean; minEjeY, MaxEjeY: NReal;
  minEjeX, MaxEjeX: NReal; tipoGrafico: TTipoGrafico; dtPaso: TDateTime);
var
  nombreHojaGrafico: Shortstring;
  {$IFNDEF SIM_EXCEL}
  hojag: variant;
  {$ENDIF}
begin
  nombreHojaGrafico := xls.graficar(PurificarNombreHoja(nombreHoja),
    colIni, colFin, filaIni, filaFin);

  xls.aplicarPropiedadesAGrafico(nombreHojaGrafico,
    TTipoGraficoToXLConst(TipoGrafico),
    titulo, ejeY, minEjeYAuto, maxEjeYAuto,
    minEjeY, MaxEjeY, minEjeX, MaxEjeX  );

  {$IFNDEF SIM_EXCEL}
  hojag := xls.v.Workbooks[1].Charts[nombreHojaGrafico];
  hojag.Select;
  hojag.Axes(xlCategory).Select;
  hojag.Axes(xlCategory).TickLabels.Orientation := xlHorizontal;
  if xls.version < 12.0 then // Office2007
    hojag.Axes(xlCategory).TickLabels.Orientation := 73
  else
    hojag.Axes(xlCategory).TickLabels.Orientation := -89;

  hojag.Axes(xlCategory).MajorTickMark := xlOutside;
  hojag.Axes(xlCategory).MinorTickMark := xlInside;
  hojag.Axes(xlCategory).TickLabelPosition := xlLow;


  //  hojag.Axes(xlCategory).MajorGridlines.Select;
  if abs( dtPaso - 1.0 / 24.0) < 0.00001 then
  begin
    if tipoGrafico = areaApilada then
    begin
      hojag.Axes(xlCategory).TickLabelSpacing := 24;
      hojag.Axes(xlCategory).TickMarkSpacing := 12;
    end
    else
    begin
      hojag.Axes(xlCategory).MajorUnit := 1;
      hojag.Axes(xlCategory).MinorUnit := 1 / 4;
    end;
  end
  else if dtPaso = 1 then
  begin
    hojag.Axes(xlCategory).HasMinorGridlines := False;
    if tipoGrafico = areaApilada then
    begin
      hojag.Axes(xlCategory).TickLabelSpacing := 7;
      hojag.Axes(xlCategory).TickMarkSpacing := 1;
    end
    else
    begin
      hojag.Axes(xlCategory).MajorUnit := 7;
      hojag.Axes(xlCategory).MinorUnit := 1;
    end;
  end
  else if dtPaso >= 7 then
  begin
    if tipoGrafico = areaApilada then
    begin
      hojag.Axes(xlCategory).TickLabelSpacing := 4;
      hojag.Axes(xlCategory).TickMarkSpacing := 1;
    end
    else
    begin
      hojag.Axes(xlCategory).MajorUnit := 365.2425 / 1.0;
      hojag.Axes(xlCategory).MinorUnit := 365.2425 / 3.0;
    end;
  end;


  hojag.Axes(xlCategory).HasMajorGridlines := True;
  hojag.Axes(xlCategory).HasMinorGridlines := True;

  hojag.Axes(xlCategory).MajorGridlines.Border.ColorIndex := 15;
  //    hojag.Axes(xlCategory).MajorGridlines.Border.Weight:= xlThick;
  hojag.Axes(xlCategory).MajorGridlines.Border.LineStyle := xlDashDot;


  hojag.Axes(xlCategory).MinorGridlines.Border.ColorIndex := 15;
  hojag.Axes(xlCategory).MinorGridlines.Border.Weight := xlHairline;
  hojag.Axes(xlCategory).MinorGridlines.Border.LineStyle := xlDot;

{$ENDIF}
end;

procedure chartMat_MultiEje_Coloreable(
  xls: TExcelFile; nombreHoja: string;
  titulo: string;
  titulo_eje1: string;
  colIni, colFin, filaIni, filaFin: integer;
  minEjeYAuto_eje1, maxEjeYAuto_eje1: boolean; minEjeY_eje1, MaxEjeY_eje1: NReal;
  minEjeX, MaxEjeX: NReal; tiposDeGrafico: TDAOfTTipoGrafico;
  ejes: TDAOfTTipoEje; colores: TDAOfTColor; dtPaso: TDateTime;
  nCronicas:integer;
  tipoVariableDelEjeX: TTipoVariableDelEje ;

  multi_xy: Boolean;

  titulo_ejeX : string = '';
  titulo_eje2: string = '';
  minEjeYAuto_eje2: boolean = true;
  maxEjeYAuto_eje2: boolean = true;
  minEjeY_eje2: NReal = 0.0;
  MaxEjeY_eje2: NReal = 100.0 );

var
  nombreHojaGrafico: WideString;
  iterTipoGrafico, tipoGraficoPrincipal: TTipoGrafico;

  i, max_cnt_TiposGraficos: integer;
  cnt_TiposGraficos: array [TTipoGrafico] of integer;
  tipoPrincipal: integer;
  {$IFNDEF SIM_EXCEL}
  hojag: variant;
  eje_x, plot_area: variant;
  AltoPlotArea: double;
  {$ENDIF}

begin

  // limpiamo los contadores
  for iterTipoGrafico := low(cnt_TiposGraficos) to high(cnt_TiposGraficos) do
    cnt_TiposGraficos[iterTipoGrafico] := 0;

  // recorremos el vector de tipos para contar cuantos hay de cada tipo
  for i := 0 to high(tiposDeGrafico) do
    Inc(cnt_TiposGraficos[tiposDeGrafico[i]]);


  // determinamos el tipo cuyo contador de máximo y lo definimos como el TipoGraficoPrincipal
  max_cnt_TiposGraficos := 0;
  tipoGraficoPrincipal := dispersion;
  for iterTipoGrafico := low(cnt_TiposGraficos) to high(cnt_TiposGraficos) do
    if cnt_TiposGraficos[iterTipoGrafico] > max_cnt_TiposGraficos then
    begin
      max_cnt_TiposGraficos := cnt_TiposGraficos[iterTipoGrafico];
      tipoGraficoPrincipal := iterTipoGrafico;
    end;

  // xls.VisibleOn;

  TipoPrincipal := TTipoGraficoToXLConst(tipoGraficoPrincipal);

  {$IFNDEF SIM_EXCEL}
  nombreHojaGrafico := xls.graficar(PurificarNombreHoja(nombreHoja),
    colIni, colFin, filaIni, filaFin, TipoPrincipal);
  xls.aplicarPropiedadesAGrafico(nombreHojaGrafico,
    TipoPrincipal, titulo,
    titulo_eje1,
    minEjeYAuto_eje1, maxEjeYAuto_eje1,
    minEjeY_eje1, MaxEjeY_eje1,
    minEjeX, MaxEjeX, titulo_ejeX  );
  {$ELSE}

  if (tipoVariableDelEjeX =CronVar) and multi_xy then
    nombreHojaGrafico := xls.graficarXY(PurificarNombreHoja(nombreHoja),
      colIni, colFin, filaIni, filaFin,nCronicas)
  else
     nombreHojaGrafico := xls.graficar(PurificarNombreHoja(nombreHoja),
       colIni, colFin, filaIni, filaFin);


  xls.aplicarPropiedadesAGrafico(nombreHojaGrafico,
    TipoPrincipal, titulo,

    titulo_eje1,
    minEjeYAuto_eje1, maxEjeYAuto_eje1,
    minEjeY_eje1, MaxEjeY_eje1,

    minEjeX, MaxEjeX, titulo_ejeX,

    titulo_eje2,
    minEjeYAuto_eje2, maxEjeYAuto_eje2,
    minEjeY_eje2, MaxEjeY_eje2
    );
  {$ENDIF}



  for i := 0 to high(tiposDeGrafico) do
  begin
    xls.aplicarPropiedadesASerie(nombreHojaGrafico, i + 1,
      TTipoGraficoToXLConst(tipoGraficoPrincipal),
      TTipoGraficoToXLConst(tiposDeGrafico[i], TipoGraficoPrincipal),
      TTipoEjeToXLConst(ejes[i]),
      colores[i], // Color de línea
      clNone );  // color fondo del marcador
  end;

  {$IFNDEF SIM_EXCEL}
  //  if TTipoGraficoToXLConst(tipoGraficoPrincipal) = xlAreaStacked then
  begin
    hojag := xls.v.Workbooks[1].Charts[nombreHojaGrafico];
    hojag.Select;
 (*
    hojag.ChartType := xlAreaStacked;
    for i := 0 to high(tiposDeGrafico) do
      hojag.SeriesCollection(i + 1).ChartType := TTipoGraficoToXLConst(tiposDeGrafico[i]);
   *)
    eje_x := hojag.Axes(xlCategory);
    eje_x.Select;
    eje_x.TickLabels.NumberFormat := WideString('0.00000000');
    if dtPaso >= 1 then
      eje_x.TickLabels.NumberFormat := WideString(ShortDateFormat)
    else
      eje_x.TickLabels.NumberFormat := WideString(ShortDateFormat + ' hh');

    hojag.Axes(xlCategory).Select;
    hojag.Axes(xlCategory).TickLabels.Orientation := xlHorizontal;
    if xls.version < 12.0 then  // Office2007
      hojag.Axes(xlCategory).TickLabels.Orientation := 73
    else
      hojag.Axes(xlCategory).TickLabels.Orientation := -89;

    hojag.Axes(xlCategory).MajorTickMark := xlOutside;
    hojag.Axes(xlCategory).MinorTickMark := xlInside;

    hojag.Axes(xlCategory).TickLabelPosition := xlLow;

    hojag.Axes(xlCategory).HasMajorGridlines := True;
    hojag.Axes(xlCategory).HasMinorGridlines := True;

    hojag.Axes(xlCategory).MajorGridlines.Border.ColorIndex := 15;
    //  hojag.Axes(xlCategory).MajorGridlines.Border.Weight:= xlThick;
    hojag.Axes(xlCategory).MajorGridlines.Border.LineStyle := xlDashDot;

    // hojag.Axes(xlCategory).MinorGridlines.Select;
    hojag.Axes(xlCategory).MinorGridlines.Border.ColorIndex := 15;
    hojag.Axes(xlCategory).MinorGridlines.Border.Weight := xlHairline;
    hojag.Axes(xlCategory).MinorGridlines.Border.LineStyle := xlDot;

     (*** ATENCION, LUEGO DE GRAFICAR; cambio el formato de la serie
    temporal si dt < 1 para que el Excel grafique bien.
    Este cambio hay que hacerlo antes de fijar las líneas de división
    para que las mismas queden ok.
    *****)
   if TipoGraficoPrincipal = areaApilada then
   begin
    if (dtPaso < 1) then
    begin
      xls.SelRango(filaIni + 1, colIni, filaFin, colIni);
      xls.CambiarFormato(xf_formatoStr(8));
    end;
   end;


    //  hojag.Axes(xlCategory).MajorGridlines.Select;
    if abs( dtPaso - 1.0 / 24.0 ) < 0.00001 then
    begin
      if tipoGraficoPrincipal = areaApilada then
      begin
        hojag.Axes(xlCategory).TickLabelSpacing := 24; //24
        hojag.Axes(xlCategory).TickMarkSpacing := 12;  //12
      end
      else
      begin
        hojag.Axes(xlCategory).MajorUnit := 1;
        hojag.Axes(xlCategory).MinorUnit := 1 / 4;
      end;
    end
    else if dtPaso = 1 then
    begin
      hojag.Axes(xlCategory).HasMinorGridlines := False;
      if tipoGraficoPrincipal = areaApilada then
      begin
        hojag.Axes(xlCategory).TickLabelSpacing := 7;
        hojag.Axes(xlCategory).TickMarkSpacing := 1;
        hojag.Axes(xlCategory).MajorUnit := 3;
        hojag.Axes(xlCategory).MajorUnitScale := xlMonths;
        hojag.Axes(xlCategory).MinorUnit := 1;
        hojag.Axes(xlCategory).MinorUnitScale := xlMonths;
      end
      else
      begin
        hojag.Axes(xlCategory).MajorUnit := 7;
        hojag.Axes(xlCategory).MinorUnit := 1;
      end;
    end
    else if dtPaso >= 7 then
    begin
      if tipoGraficoPrincipal = areaApilada then
      begin
        hojag.Axes(xlCategory).TickLabelSpacing := 4;
        hojag.Axes(xlCategory).TickMarkSpacing := 1;
      end
      else
      begin
        hojag.Axes(xlCategory).MajorUnit := 365.2425 / 1.0;
        hojag.Axes(xlCategory).MinorUnit := 365.2425 / 3.0;
      end;
    end;




    plot_area := hojag.PlotArea;
    hojag.ChartArea.Border.LineStyle := xlDash;
    Plot_Area.Border.LineStyle := xlDot;

    plot_area.Select;
    (*
    system.writeln( 'Chart Area TH: (', hojag.chartarea.top, ', ',  hojag.chartarea.height,')' );
    system.writeln( 'Plot Area TH: (', plot_area.top,', ' , plot_area.height,')');
    system.writeln( 'Eje_x TH: ', eje_x.top, ', ', eje_x.height,')' );
    *)
    //    plot_area.height:= hojag.chartarea.height - 88 - plot_area.top; // - eje_x.height;




  end;
  {$ENDIF}

  //  aplicarPropiedadesASeries(xls, nombreHojaGrafico, tipoGraficoPrincipal, tiposGraficos, ejes, colores);
end;

(*

procedure aplicarPropiedadesASeries(xls: TExcelFile; nombreHoja: String;
                                    tipoGraficoPrincipal: TTipoGrafico; tiposGraficos: TDAOfTTipoGrafico;
                                    ejes: TDAOfTTipoEje;
                                    colores: TDAOfTColor);
var
  hojag, serie: Variant;
  i: Integer;
  colorIndexI: Integer;
  versionOffice: NReal;
  aux: TPaletaColoresExcel;
begin
  hojag:= xls.Hoja(nombreHoja);

  versionOffice:= xls.version;
  if versionOffice < versionOffice2007 then
    aux:= xls.getPaletaColores;

  for i:= 0 to High(tiposGraficos) do
  begin
    serie:= hojag.SeriesCollection(i + 1);
    if tiposGraficos[i] <> tipoGraficoPrincipal then
      serie.ChartType:= TTipoGraficoToXLConst(tiposGraficos[i]);
    serie.AxisGroup:= TTipoEjeToXLConst(ejes[i]);

    if colores[i] <> colorAutomatico then
    begin
      if versionOffice < versionOffice2007 then
      begin
        colorIndexI:= getColorIndex(colores[i], aux);

        if tiposGraficos[i] in tiposGraficosConColorInterior then
          serie.Interior.Colorindex:= colorIndexI;
        serie.Border.Colorindex:= colorIndexI;
        if tiposGraficos[i] in tiposGraficosConMarcadores then
        begin
          serie.MarkerStyle:= xlAutomatic;
          serie.MarkerBackgroundColorIndex:= colorIndexI;
          serie.MarkerForegroundColorIndex:= colorIndexI;
        end;
      end
      else
      begin
        if tiposGraficos[i] in tiposGraficosConColorInterior then
          serie.Interior.Color:= colores[i];
        serie.Border.Color:= colores[i];
        if tiposGraficos[i] in tiposGraficosConMarcadores then
        begin
          serie.MarkerStyle:= xlAutomatic;
          serie.MarkerBackgroundColor:= colores[i];
          serie.MarkerForegroundColor:= colores[i];
        end;
      end;
    end;
  end;
end;
*)



procedure WriteMatToXLS(xls: TExcelFile; nombreHoja: string;
  mat: TMatOfNReal; titulo, unidades: string; nPasos: integer;
  nCronicas: integer; dtFechaPrimerPaso: TDateTime; dtPaso: double;
  decimales: integer; Print_Todas: boolean; Print_promedio: boolean;
  Pre_Ordenar: boolean; TipoImpresion_PE: boolean;
  Print_probAisladas: TDAofNReal; chart_Mat: boolean; minEjeYAuto,
  maxEjeYAuto: boolean; minEjeY, MaxEjeY: NReal);
var
  iCronica, iPaso: integer;
  fechaDelPaso: TDateTime;
  iProbAisladas: array of integer;
  aprom: NReal;
  kProb: integer;
  hayAdicionales: boolean;
  aval: NReal;
  colIni, colFin, filaIni, filaFin: integer;
  pe_ant: NReal;

begin

  setlength(iProbAisladas, length(Print_probAisladas));
  for kProb := 0 to high(Print_probAisladas) do
  begin
    iCronica := round(NCronicas * Print_probAisladas[kProb]) - 1;

    // previendo que alguien escriba porbabilidades <0 o > 1 o que
    // por algún redondeo nos vayamos de rango.
    if iCronica < 0 then
      iCronica := 0
    else if iCronica > (NCronicas - 1) then
      iCronica := (NCronicas - 1);

    iProbAisladas[kProb] := iCronica;
  end;

  hayAdicionales := Print_promedio or (length(Print_probAisladas) > 0);

  nombreHoja := PurificarNombreHoja(nombreHoja);
  xls.agregoHoja(nombreHoja);
  xls.go(nombreHoja, 1, 1);

  xls.writeln('# '+titulo + ' ' + unidades+' '+xls.idstr );

  //Para evitar el warning
  colIni := -1;
  colFin := -1;

  filaIni := xls.fila; // fila del encabezado
  filaFin := filaIni + nPasos; // ultima fila de datos


  xls.Writebuffereado('paso');

  if Print_Todas then
  begin
    colIni := xls.columnaBuffereada;
    colFin := colIni + nCronicas;
    xls.Writebuffereado('');
    for iCronica := 0 to NCronicas - 1 do
      xls.Writebuffereado((iCronica + 1) / NCronicas);
  end;

  if hayAdicionales then
  begin
    xls.Writebuffereado('');

    colIni := xls.columnaBuffereada;
    colFin := colIni + Length(Print_ProbAisladas);
    if Print_promedio then
      Inc(colFin);
    filaIni := xls.fila;
    filaFin := filaIni + nPasos;

    xls.Writebuffereado('');
    if Print_Promedio then
      xls.Writebuffereado('Prom');

    if TipoImpresion_PE then
    begin
      for kProb := 0 to high(iProbAisladas) do
        xls.Writebuffereado('Pe' + FloatToStrF(
          Print_ProbAisladas[kProb] * 100, ffFixed, 6, 1) + '%');
    end
    else
    begin
      inc( colFin );
      pe_ant:= 0;
      for kProb := 0 to high(iProbAisladas) do
      begin
        xls.Writebuffereado('VaR(' + FloatToStrF( pe_ant * 100, ffFixed, 6, 1)
          +'-'+ FloatToStrF( Print_ProbAisladas[kProb] * 100, ffFixed, 6, 1)
          + ')%');
         pe_ant:= Print_ProbAisladas[kProb];
      end;
      xls.Writebuffereado('VaR(' + FloatToStrF( pe_ant * 100, ffFixed, 6, 1)
        +'-'+ FloatToStrF( 100, ffFixed, 6, 1)
        + ')%');
    end;
  end;
  xls.writelnBuffer;

  for iPaso := 0 to NPasos - 1 do
  begin
    if Pre_Ordenar then
    QuickSort_Decreciente( mat[iPaso]);


    fechaDelPaso := dtFechaPrimerPaso + dtPaso * iPaso;
    xls.Writebuffereado(IntToStr(iPaso + 1));

    if Print_Todas then
   //   xls.Write_buffereado(DateTimeToIsoStr(fechaDelPaso));
      xls.Writebuffereado(fechaDelPaso);

    aProm := 0;
    if Print_Todas or Print_promedio then
    begin
      for iCronica := 0 to NCronicas - 1 do
      begin
        aval := mat[iPaso, iCronica];
        if Print_Todas then
          xls.Writebuffereado(aval);
        aProm := aProm + aval;
      end;
      aProm := aProm / NCronicas;
    end;

    if hayAdicionales then
    begin
      xls.Writebuffereado('');
 //     xls.Write_buffereado(DateTimeToIsoStr(fechaDelPaso));
      xls.Writebuffereado(fechaDelPaso);

      if Print_Promedio then
        xls.Writebuffereado(aProm);

      if TipoImpresion_PE then
      begin
        for kProb := 0 to high(iProbAisladas) do
          xls.Writebuffereado(mat[iPaso, iProbAisladas[kProb]]);
      end
      else
      begin
       aval := promediarProbs(mat[iPaso], 0, iProbAisladas[0]);

        xls.Writebuffereado(aval);
        for kProb := 1 to high(iProbAisladas) do
        begin
          aval := promediarProbs(mat[iPaso], iProbAisladas[kProb - 1],
            iProbAisladas[kProb]);
          xls.Writebuffereado(aval);
        end;
        aval := promediarProbs(mat[iPaso], iProbAisladas[high(iProbAisladas)],
          NCronicas - 1);
        xls.Writebuffereado(aval);
      end;
    end;
    xls.writelnBuffer;
  end;
  xls.writelnBuffer;


  {$IFNDEF SIM_EXCEL}
  // formatedo del área de datos
  xls.SelRango(filaIni + 1, colIni + 1, filaFin, colFin);
  if xls.version = 14 then
    xls.CambiarFormato(xf_formatoStr(decimales))
  else
    xls.CambiarFormato('General');
  {$ENDIF}

  // formatedo de las fechas
  xls.SelRango(filaIni + 1, colIni, filaFin, colIni);

  if (dtPaso < 1) then
    xls.CambiarFormato(SysUtils.ShortDateFormat + ' hh')
  else
    xls.CambiarFormato(SysUtils.ShortDateFormat);


  if chart_Mat then
  begin
    chartMat_SimpleEje_ColoresAuto(xls,
      nombreHoja, titulo, unidades,
      colIni, colFin, filaIni, filaFin,
      minEjeYAuto, maxEjeYAuto,
      minEjeY, MaxEjeY,
      dtFechaPrimerPaso, dtFechaPrimerPaso + (nPasos - 1) * dtPaso,
      dispersion, dtPaso);
  end;
end;


procedure writeHistogramaGlobalToXls(xls: TExcelFile; nombreHoja: string;
  mat: TMatOfNReal; titulo, unidades: string; decimales: integer; minX,
  maxX: NReal; nPuntos: integer);
var
  i, j, idxVal: integer;
  //  min, max: NReal;
  histo, histoAcum: TDAofNReal;
  x, invNPuntosCronicas, deltaMaxMin, invDeltaMaxMin, deltaX: NReal;

  //  filaContenido: TDAOfVariant;
  nFilas, nColumnas: integer;
  filaIni, filaFin, colIni, colFin: integer;
begin
  nombreHoja := PurificarNombreHoja(nombreHoja);

  deltaMaxMin := maxX - minX;
  invDeltaMaxMin := 1 / deltaMaxMin;
  deltaX := deltaMaxMin / (nPuntos - 1);
  nFilas:= length(mat);
  nColumnas:= length(mat[0]);
  invNPuntosCronicas := 1 / ( nFilas * nColumnas );

  SetLength(histo, nPuntos);

  for i := 0 to high(histo) do
    histo[i] := 0;


  for i := 0 to nFilas-1 do
  begin
    for j := 0 to nColumnas-1 do
    begin
      idxVal := trunc(((mat[i, j] - minX) * invDeltaMaxMin) * high(histo));
      if idxVal < 0 then
        idxVal := 0
      else if idxVal > high(histo) then
        idxVal := high(histo);
      histo[idxVal] := histo[idxVal] + invNPuntosCronicas;
    end;
  end;

  SetLength(histoAcum, length(histo));
  histoAcum[0] := histo[0];
  for i := 1 to high(histoAcum) do
    histoAcum[i] := histoAcum[i - 1] + histo[i];

  xls.agregoHoja(nombreHoja);
  xls.go(nombreHoja, 1, 1);

  xls.writeln('# '+titulo + ' ' + unidades+' '+xls.idstr );

  filaIni := xls.fila;   // fila del encabezado
  colIni  := xls.columnaBuffereada; // columna de datos
  filaFin := filaIni + length(histoAcum); // última fila de datos.
  colFin := colIni + 1; // seguna columna con las probabilidades

  xls.WriteBuffereado(titulo);
  xls.WriteBuffereado(RS_PROBABILIDAD_ACUMULADA);
  xls.writelnBuffer;
  x := minX;

  for i := 0 to high(histoAcum) do
  begin
    xls.WriteBuffereado(x);
    xls.WriteBuffereado(histoAcum[i]);
    xls.writelnBuffer;
    x := x + deltaX;
  end;


  // formatedo columna de valores de X
  xls.SelRango(filaIni + 1, colIni, filaFin, colIni);
  {$IFNDEF SIM_EXCEL}
  if xls.version = 14 then
    xls.CambiarFormato(xf_formatoStr(decimales))
  else
    xls.CambiarFormato('General');
  {$ENDIF}
  // formatedo las probabilidades acumuladas;
  xls.SelRango(filaIni + 1, colFin, filaFin, colFin);
  xls.CambiarFormato('0%');

  {
  if chart_Mat then
  begin
    chartMat(xls, nombreHoja, titulo, unidades, colIni, colFin, filaIni, filaFin,
    minEjeYAuto, maxEjeYAuto, minEjeY, MaxEjeY, 1/ Length(histo), 1, dispersion);
  end;
 }
end;

procedure WriteMatToXLS_SinOrdenar(xls: TExcelFile; nombreHoja: string;
  mat: TMatOfNReal; titulo, unidades: string; titulosCols: TDAofString;
  nPasos: integer; nCronicas: integer; dtFechaPrimerPaso: TDateTime;
  dtPaso: double; decimales: integer; Print_promedio: boolean;
  chart_Mat: boolean; minEjeYAuto, maxEjeYAuto: boolean; minEjeY, MaxEjeY: NReal);
var
  iCronica, iPaso: integer;
  fechaDelPaso: TDateTime;
  aprom: NReal;
  aval: NReal;
  colIni, colFin, filaIni, filaFin: integer;

  nHojas, kHoja: integer;
  iCronIni, iCronM, iCronFin: integer;
  sNombreHoja: string;
begin
  nombreHoja := PurificarNombreHoja(nombreHoja);
  //Para sacar el warning
  colIni := -1;
  filaIni := -1;
  ColFin := -1;
  filaFin := -1;

  nHojas := ((nCronicas - 1) div 250) + 1;

  for kHoja := 1 to nHojas do
  begin
    if (nHojas > 1) then
      sNombreHoja := nombreHoja + '_' + IntToStr(kHoja)
    else
      sNombreHoja := nombreHoja;

    xls.agregoHoja(sNombreHoja);

    iCronIni := (kHoja - 1) * 250;
    iCronFin := min((nCronicas - 1), iCronIni + 250 - 1);
    iCronM := max(iCronIni - 1, min(high(titulosCols), iCronFin));

    xls.go(sNombreHoja, 1, 1);
    xls.writeln('# '+titulo + ' ' + unidades+' ' +xls.idstr);

    filaIni := xls.fila;  // fila encabezado
    filaFin := filaIni + nPasos; // ultima fila de datos

    xls.WriteBuffereado('paso');

    colIni := xls.columnaBuffereada; // columna de fechas
    colFin := colIni + iCronFin - iCronIni + 1; // ultima columna de datos

    xls.WriteBuffereado('');


    for iCronica := iCronIni to iCronM do
      xls.WriteBuffereado(titulosCols[iCronica]);
    //Si faltaron titulos de columnas como parametro imprime Columna y su número
    for iCronica := iCronM + 1 to iCronFin do
      xls.WriteBuffereado('Col_' + IntToStr(iCronica + 1));

    if Print_promedio then
    begin
      Inc(colFin);
      xls.WriteBuffereado('Prom');
    end;

    xls.writelnBuffer;
    for iPaso := 0 to NPasos - 1 do
    begin
      fechaDelPaso := dtFechaPrimerPaso + dtPaso * iPaso;
      xls.WriteBuffereado(IntToStr(iPaso + 1));
//      xls.WriteBuffereado(DateTimeToIsoStr(fechaDelPaso));
      xls.WriteBuffereado(fechaDelPaso);

      aProm := 0;
      for iCronica := iCronIni to iCronFin do
      begin
        aval := mat[iPaso, iCronica];
        xls.WriteBuffereado(aval);
        aProm := aProm + aval;
      end;
      aProm := aProm / NCronicas;

      if Print_Promedio then
        xls.WriteBuffereado(aProm);
      xls.writelnBuffer;
    end;
    xls.writelnBuffer;

    // formatedo del área de datos
    xls.SelRango(filaIni + 1, colIni + 1, filaFin, colFin);

{$IFNDEF SIM_EXCEL}
    if xls.version = 14 then
      xls.CambiarFormato(xf_formatoStr(decimales))
    else
      xls.CambiarFormato('General');
{$ENDIF}
    // formatedo de las fechas
    xls.SelRango(filaIni + 1, colIni, filaFin, colIni);
    if (dtPaso < 1) then
      xls.CambiarFormato(SysUtils.ShortDateFormat + ' hh')
    else
      xls.CambiarFormato(SysUtils.ShortDateFormat);
  end;
  xls.writelnBuffer;

  if (nHojas = 1) and chart_Mat then
  begin

    chartMat_SimpleEje_ColoresAuto(xls,
      nombreHoja, titulo, unidades,
      colIni, colFin, filaIni, filaFin,
      minEjeYAuto, maxEjeYAuto,
      minEjeY, MaxEjeY,
      dtFechaPrimerPaso, dtFechaPrimerPaso + (nPasos - 1) * dtPaso, dispersion, dtPaso);
  end;
end;


{$ENDIF}

procedure Cronicas( const mats: array of TMatOfNReal; iPaso: integer;
  var resultado: TDAofNReal );
var
  iCronVar, iCronica, max_iCronica, kCronica, k, nCronicas: integer;
begin
  k:=0;
  nCronicas:= length( mats[1][iPaso]);
  for iCronVar := 0 to high(mats) do
  begin
    max_iCronica:= high( mats[iCronVar][0] );
    for iCronica := 0 to nCronicas-1 do
    begin
      kCronica:= min( iCronica, max_iCronica );
      if iPaso < length( mats[iCronVar]) then
        resultado[k] := mats[iCronVar][iPaso][kCronica]
      else
        resultado[k] := mats[iCronVar][ high(mats[iCronVar])][ kCronica ];
      inc( k );
    end;
  end;
end;

procedure calcPromedios(const mats: array of TMatOfNReal; iPaso: integer;
  var resultado: TDAofNReal);
var
  i: integer;
begin
  for i := 0 to high(mats) do
    if iPaso < length(mats[i]) then
      resultado[i] := vprom(mats[i][iPaso])
    else
      resultado[i] := vprom(mats[i][high(mats[i])]);
end;


procedure calcDesviacionesEstandar(const mats: array of TMatOfNReal;
  iPaso: integer; var resultado: TDAofNReal);
var
  i, j: integer;
  proms: TDAofNReal;
  filaPaso: TDAofNReal;
begin
  SetLength(proms, length(mats));
  calcPromedios(mats, iPaso, proms);
for i := 0 to high(mats) do
begin
  if iPaso < length(mats[i]) then
    filaPaso := mats[i][iPaso]
  else
    filaPaso := mats[i][high(mats[i])];

  resultado[i] := 0;
  if length(filaPaso) > 1 then
  begin
    for j := 0 to High(filaPaso) do
      resultado[i] := resultado[i] + Sqr(filaPaso[j] - proms[i]);
    resultado[i] := resultado[i] / (Length(filaPaso) - 1);
  end;
end;
  SetLength(proms, 0);
end;

procedure calcProbsExcedencia(const mats: array of TMatOfNReal;
  preOrdenar: boolean; iPaso: integer; probExcedencia: NReal;
  var resultado: TDAofNReal);
var
  i, iProbExcedencia: integer;
  filaPaso: TDAofNReal;
  kPaso: integer;
begin
  for i := 0 to high(mats) do
  begin
    if iPaso < length(mats[i]) then
      kPaso := iPaso
    else
      kPaso := high(mats[i]);

    filaPaso := copy(mats[i][kPaso], 0, length(mats[i][kPaso]));

    if preOrdenar then
      QuickSort_Decreciente(filaPaso);
    iProbExcedencia := round(length(filaPaso) * probExcedencia) - 1;
    iProbExcedencia := max(0, min(high(filaPaso), iProbExcedencia));
    resultado[i] := filaPaso[iProbExcedencia];
    setlength( filaPaso, 0 );
  end;
end;



procedure calcValoresEnRiesgo(const mats: array of TMatOfNReal;
  preOrdenar: boolean; iPaso: integer; probExcedencia1, probExcedencia2: NReal;
  var resultado: TDAofNReal);
var
  i, j, iProbExcedencia1, iProbExcedencia2: integer;
  filaPaso: TDAofNReal;
  aval: NReal;
  kPaso: integer;

begin

  for i := 0 to high(mats) do
  begin

    if iPaso < length(mats[i]) then
      kPaso := iPaso
    else
      kPaso := high(mats[i]);

    filaPaso := copy(mats[i][kPaso], 0, length(mats[i][kPaso]));
    if preOrdenar then
      QuickSort_Decreciente(filaPaso);
    iProbExcedencia1 := trunc(high(filaPaso) * probExcedencia1);
    iProbExcedencia2 := trunc(high(filaPaso) * probExcedencia2);
    aval := 0;
    for j := iProbExcedencia1 to iProbExcedencia2 do
      aval := aval + filaPaso[j];
    resultado[i] := aval / (iProbExcedencia2 - iProbExcedencia1 + 1);
    setlength( filaPaso, 0 );
  end;
end;



{$IFNDEF SIMRES3SOLOTEXTO}
procedure WriteValoresToXLS(
  xls: TExcelFile;
  tipoValores: TTipoValoresAComparar;
  probExcedencia: NReal;
  Pre_Ordenar: boolean;
  ProbExcedencia_Sup: NReal;
  nombresVars: TDAofString;

  mats: array of TMatOfNReal;

  nombreHoja: string;

  titulo: string;

  dtFechaPrimerPaso: TDateTime; dtPaso: double;

  graficar: boolean; tiposGraficos: TDAOfTTipoGrafico;
  ejes: TDAOfTTipoEje; colores: TDAOfTColor;

  // Información del eje Y Primario
  titulo_eje1: string;
  digitos_eje1: integer;
  decimales_eje1: integer;
  minEjeYAuto_eje1: boolean;
  maxEjeYAuto_eje1: boolean;
  minEjeY_eje1: NReal;
  MaxEjeY_eje1: NReal;

  // Información del eje Y Secundario
  titulo_eje2: string = '';
  digitos_eje2: integer = 12;
  decimales_eje2: integer = 2;
  minEjeYAuto_eje2: boolean = true;
  maxEjeYAuto_eje2: boolean = true;
  minEjeY_eje2: NReal = 0.0;
  MaxEjeY_eje2: NReal = 100.0;

  TipoVariableDelEjeX: TTipoVariableDelEje = tiempo;
  titulo_ejeX:string=''
  );
var
  iPaso, iMats: integer;
  iVal: integer;
  valores: TDAofNReal;
  descTipoValor: string;
  colIni, colFin, filaIni, filaFin: integer;
  dtUltimoPaso: TDateTime;
  nFilas, nColumnas, nCronicas, TotCron,iCronVar,iCronica: integer;

begin
  nombreHoja := PurificarNombreHoja(nombreHoja);
  xls.agregoHoja(nombreHoja);
  xls.go(nombreHoja, 1, 1);

  if titulo_eje2  = '' then
    xls.writeln('# ' + titulo + ' ' + titulo_eje1+' '+xls.idstr )
  else
    xls.writeln('# '+titulo + ' ' + titulo_eje1+' '+xls.idstr + ' Eje2:' + titulo_eje2);

  xls.WriteBuffereado('paso');

  nCronicas:=length(mats[1][0]);
  nFilas:= Length( mats[1] );

  nColumnas:= length( mats )-1;  //porq la primera es el ejex

  filaIni := xls.fila;
  filaFin := filaIni + nFilas;
  colIni  := xls.columnaBuffereada;

  colFin  := colIni + length(mats)-1;

  TotCron:= nCronicas * ( nColumnas + 1 );

  if  tipoValores = TodasLasCronicas then
  begin
    SetLength( valores, TotCron );
    case tipoVariableDelEjeX of
      CronVar:
        colFin  := colIni + length(valores)-1;
      PE,tiempo:
        colFin  := colIni + length(valores)-1-(nCronicas - 1);
    end
  end
  else
    SetLength( valores, length( mats ));

  descTipoValor := TTipoValoresACompararToShortStringSingular_(tipoValores, probExcedencia);


  //Escribo los encabezados de las series

  // PRIMER COLUMNA DEL ENCABEZADO
  case tipoVariableDelEjeX of
    tiempo: xls.WriteBuffereado('fecha');
    PE: xls.WriteBuffereado('PE');
    CronVar: xls.WriteBuffereado(nombresVars[0] + '_EjeX' );
   end;

  // DEMAS COLUMNAS DEL ENCABEZADO
  if tipoValores = TodasLasCronicas  then
  begin
    if ( tipoVariableDelEjeX = CronVar ) then
      for iCronica := 1 to nCronicas-1 do
        xls.WriteBuffereado( nombresVars[0] + '_Ejex_' + IntToStr(iCronica+1));

    for iCronVar:= 1 to high( Mats ) do
        for iCronica:= 0 to high( Mats[iCronVar] ) do
          xls.WriteBuffereado(nombresVars[iCronVar] + '_' + IntToStr(iCronica+1));

  end
  else
    for iCronVar := 1 to high( mats) do
       xls.WriteBuffereado(nombresVars[iCronVar] + '_' + descTipoValor);
  xls.writelnBuffer;



  for iPaso := 0 to nFilas -1  do
  begin
    case tipoValores of
      Promedios: calcPromedios( mats, iPaso, valores);

      DesviacionesEstandar: calcDesviacionesEstandar(mats, iPaso, valores);

      ProbabilidadesDeExcedencia: calcProbsExcedencia(mats, pre_Ordenar, iPaso,
          probExcedencia, valores);

      ValoresEnRiesgo: calcValoresEnRiesgo(mats, pre_Ordenar, iPaso,
          probExcedencia, ProbExcedencia_Sup, valores);

      TodasLasCronicas:
          Cronicas(mats, iPaso, valores);   //todas las cronicas de todas las CronVars

    end; // del case

    xls.WriteBuffereado( iPaso + 1 );
    // xls.WriteBuffereado(DateTimeToIsoStr(dtFechaPrimerPaso + iPaso * dtPaso));

    //Escribo el ejex

    // Primer columna del ejeX
    case tipoVariableDelEjeX of
      tiempo: xls.WriteBuffereado( dtFechaPrimerPaso + iPaso * dtPaso);
      PE: xls.WriteBuffereado( iPaso / nfilas );
      CronVar: xls.WriteBuffereado( valores[0] );
    end;

    if tipoValores = TodasLasCronicas  then
    begin
      case tipoVariableDelEjeX of
        CronVar:
          for iVal := 1 to high(valores) do
            xls.WriteBuffereado(valores[iVal]);
        PE, tiempo:
           //las primeras nCronicas se desechan porque es basura
          for iVal := nCronicas to high(valores) do
            xls.WriteBuffereado(valores[iVal]);
      end;
    end
    else
    begin
       for iVal := 1 to high(valores) do
        xls.WriteBuffereado(valores[iVal]);
    end;
    xls.writelnBuffer;

  end;


  // formatedo del área de datos
  xls.SelRango(filaIni + 1, colIni + 1, filaFin, colFin);
  {$IFNDEF SIM_EXCEL}
  if xls.version = 14 then
    xls.CambiarFormato(xf_formatoStr(decimales_eje1))
  else
    xls.CambiarFormato('General');
  {$ENDIF}

  // formatedo de las fechas
  if tipoVariableDelEjeX = tiempo then
  begin
    xls.SelRango(filaIni + 1, colIni, filaFin, colIni);
    if (dtPaso < 1) then
      xls.CambiarFormato(SysUtils.ShortDateFormat + ' hh')
    else
      xls.CambiarFormato(SysUtils.ShortDateFormat );
  end;

  if graficar then
  begin
    case tipoVariableDelEjeX of
      tiempo:
        begin
          dtUltimoPaso:= dtFechaPrimerPaso +  high(mats[1]) * dtPaso ;
    //      titulo_ejeX:='';
        end;
      CronVar:
        begin
          dtUltimoPaso:= valores[0];
          if titulo_ejeX = '' then
            titulo_ejeX:= nombresVars[0];
        end;
      PE:
        begin
          dtUltimoPaso:= 1.0 ;
          dtFechaPrimerPaso:= 0.0;
          if titulo_ejeX = '' then
            titulo_ejeX:='PE'
        end
    end;

    chartMat_MultiEje_Coloreable(xls,
      nombreHoja, titulo, titulo_eje1,
      colIni, colFin, filaIni, filaFin,
      minEjeYAuto_eje1,
      maxEjeYAuto_eje1,
      minEjeY_eje1,
      MaxEjeY_eje1,
      dtFechaPrimerPaso, dtULtimoPaso ,
      tiposGraficos, ejes, colores, dtPaso,nCronicas,
      tipoVariableDelEjeX,
      tipoValores = TodasLasCronicas,
      titulo_ejeX,
      titulo_eje2,
      minEjeYAuto_eje2,
      maxEjeYAuto_eje2,
      minEjeY_eje2,
      MaxEjeY_eje2
      );

  end;

end;



function TTipoGraficoToXLConst(tipoGrafico: TTipoGrafico;
  TipoPrincipal: TTipoGrafico): integer;
begin
  case tipoGrafico of
    linea:
      {$IFDEF SIM_EXCEL}
      result:= xlXYScatterLines;
      {$ELSE}
      Result :=xlLine;
      {$ENDIF}
    dispersion:
      {$IFDEF SIM_EXCEL}
      Result := xlXYScatterLines;
      {$ELSE}
      if tipoPrincipal = dispersion then
        Result := xlXYScatterLines
      else
        Result := xlLineMarkers;
      {$ENDIF}
    areaApilada: Result := xlAreaStacked;
    else
      raise Exception.Create('uPrint.TTipoGraficoToXLConst: TTipoGrafico desconocido ' +
        IntToStr(Ord(tipoGrafico)));
  end;
end;

function TTipoGraficoToString(tipoGrafico: TTipoGrafico): string;
begin
  case tipoGrafico of
    //    linea       : result:= 'Líneas';
    areaApilada: Result := 'are';
    dispersion: Result := 'dis';
    else
      raise Exception.Create('uPrint.TTipoGraficoToString: tipo de grafico desconocido '
        + IntToStr(Ord(tipoGrafico)));
  end;
end;

function StringToTTipoGrafico(tipoGrafico: string): TTipoGrafico;
var
  flg_asignado: boolean;
begin
{  if CompareStr(tipoGrafico, 'Líneas') = 0 then
    result:= linea
  else }
  flg_asignado := False;


  if (pos('Area', tipoGrafico) > 0) or (tipoGrafico = 'are') then
    Result := areaApilada
  else if (pos('Disp', tipoGrafico) > 0) or (tipoGrafico = 'dis') then
    Result := dispersion
  else
    raise Exception.Create('uPrint.StringToTTipoGrafico: tipo de gráfico desconocido ' +
      tipoGrafico);
end;

function TTipoEjeToXLConst(tipoEje: TTipoEje): integer;
begin
  case tipoEje of
    Primario: Result := 1;
    Secundario: Result := 2;
    else
      raise Exception.Create('uPrint.TTipoEjeToXLConst: tipo de eje desconocido ' +
        IntToStr(Ord(tipoEje)));
  end;
end;

function TTipoEjeToString(tipoEje: TTipoEje): string;
begin
  case tipoEje of
    Primario: Result := 'pri';
    Secundario: Result := 'sec';
    else
      raise Exception.Create('uPrint.TTipoEjeToXLConst: tipo de eje desconocido ' +
        IntToStr(Ord(tipoEje)));
  end;
end;

function TEjeToString(Eje: TTipoVariableDelEje): string;
begin
  case Eje of
    tiempo: Result := 'tiempo';
    PE: Result := 'PE';
    CronVar: Result := 'CronVar';
    else
      raise Exception.Create('uPrint.TEjeToXLConst:  eje desconocido ' +
        IntToStr(Ord(Eje)));
  end;
end;

function StringToTTipoEje(tipoEje: string): TTipoEje;
begin
  if (tipoEje = 'Primario') or (tipoEje = 'pri') then
    Result := Primario
  else if (tipoEje = 'Secundario') or (tipoEje = 'sec') then
    Result := Secundario
  else
    raise Exception.Create('StringToTTipoEje: tipo de eje desconocido ' + tipoEje);
end;

function StringToTEje(Eje: string): TTipoVariableDelEje;
begin
  if (Eje = 'tiempo')  then
    Result := tiempo
  else if (Eje = 'PE')  then
    Result := PE
  else if (Eje = 'CronVar')  then
    Result := CronVar
  else
    raise Exception.Create('StringToTEje: tipo de eje desconocido ' + Eje);
end;

function TTipoValoresACompararToString(tipoValoresAComparar:
  TTipoValoresAComparar): string;
begin
  case tipoValoresAComparar of
    Promedios: Result := 'prom';
    DesviacionesEstandar: Result := 'desv';
    ProbabilidadesDeExcedencia: Result := 'pbex';
    ValoresEnRiesgo: Result := 'var';
    TodasLasCronicas: Result:= 'tdlcrs';
    else
      raise Exception.Create(
        'uPrintCronVars.TTipoValoresACompararToString: tipo de grafico desconocido ' +
        IntToStr(Ord(tipoValoresAComparar)));
  end;
end;

function StringToTTipoValoresAComparar(tipoValoresAComparar: string):
TTipoValoresAComparar;
begin
  if (tipoValoresAComparar = 'Promedios') or (tipoValoresAcomparar = 'prom') then
    Result := Promedios
  else if (tipoValoresAComparar = 'Desviaciones Estandar') or
    (tipoValoresAComparar = 'desv') then
    Result := DesviacionesEstandar
  else if (tipoValoresAComparar = 'Probabilidades de Excedencia') or
    (tipoValoresAComparar = 'pbex') then
    Result := ProbabilidadesDeExcedencia
  else if (tipoValoresAComparar = 'Valores en Riesgo') or
    (tipoValoresAComparar = 'var') then
    Result := ValoresEnRiesgo
  else if (tipoValoresAComparar = 'Todas las crónicas') or
      (tipoValoresAComparar = 'tdlcrs') then
      Result := TodasLasCronicas
  else
    raise Exception.Create(
      'uPrintCronVars.StringToTTipoValoresAComparar: tipo de gráfico desconocido ' +
      tipoValoresAComparar);
end;

function TTipoValoresACompararToShortStringSingular_(tipoValoresAComparar:
  TTipoValoresAComparar; probExcedencia: NReal): string;
begin
  case tipoValoresAComparar of
    Promedios: Result := RS_XLS_PROMEDIO;
    DesviacionesEstandar: Result := RS_XLS_DESVIACION_ESTANDAR;
    ProbabilidadesDeExcedencia: Result :=
        RS_XLS_PROBABILIDAD_DE_EXCEDENCIA + ' ' +
        FloatToStrF(probExcedencia * 100, ffFixed, 6, 2) + '%';
    ValoresEnRiesgo: Result :=
        RS_XLS_VALOR_EN_RIESGO + ' ' + FloatToStrF(probExcedencia *
        100, ffFixed, 6, 2) + '%';
    TodasLasCronicas: Result:= RS_XLS_TODAS_LAS_CRONICAS;
    else
      raise Exception.Create(
        'uPrintCronVars.TTipoValoresACompararToShortStringSingular: tipo de grafico desconocido '
        + IntToStr(Ord(tipoValoresAComparar)));
  end;
end;

{$ENDIF}
end.
{$ENDIF}
