Cree un generador de informes para Delphi y Microsoft Excel

¿Por qué necesitamos un sistema de informes?

Отчеты Excel из DelphiEn un momento, cuando el sistema de contabilidad requerido para hacer el sistema para mostrar información impresa pasó por muchos sistemas diferentes de informes, algunos como FastReport, formaron parte de los editores y placas de forma notable, pero a la mayoría de los usuarios les gusta, cuando Puede recibir información de forma rápida y hermosa ihnem Excel favorito, sin necesidad de convertidores, etc.

Internet ha sido durante mucho tiempo un mar de información sobre la interacción de Delphi y Microsoft Excel, y no voy a escribir otra guía. En su lugar, propongo ver cómo se puede desarrollar un sistema de salida de informes en Excel bastante simple y suficiente para abordar, si no todos, pero sí la mayoría de los problemas.

Cuando cada informe está completamente formado en el código Delphi, el inconveniente de este método era que el código de Delphi no podía ver la lógica del proceso de creación del informe y, lo que es más importante, para cambiar cada detalle en el diseño, tenía que modificar el código y volver a compilar el proyecto. Luego, la idea de escribir un pequeño generador de informes, la plantilla de informe: este es el archivo ekselevsky habitual en el que cualquiera podrá corregir lo que necesita y determinar de antemano el formato de impresión.

La estructura del generador de informes para Excel

La base de la plantilla hasta «bandas». Bend es una o más líneas, dispuestas en fila y con una misma etiqueta: el nombre de la banda. Se pone en la primera columna de cada fila. Eso se verá como una plantilla lista para usar del informe:

Пример шаблона отчета Excel для генератора отчетов

Nuestro componente podrá abrir la plantilla, insertar la banda especificada, insertar el valor de las variables en el último Bend insertado para mostrar el progreso en una serie de líneas derivadas (para simplificar, no jugaremos con el error de cálculo del total), como así como adecuado para abrir el resultado en sí.

La clase del informe será muy sencilla:

 TA7xReport = class(TComponent)
  private
    Excel, TemplateSheet: Variant;
    Progress: TWcProgress;
    CurrentLine: integer; // текущая строка построения отчета
    FirstBandLine, LastBandLine: integer; // положение последнего добавленного бэнда
  protected
  public
    procedure OpenTemplate(FileName: string);
    procedure PasteBand(BandName: string);
    procedure SetValue(VarName: string; Value: Variant);
    procedure Show;
    destructor Destroy; override;
  published
  end;

Comenzar la construcción de cualquier informe sería llamar al procedimiento OpenTemplate, que iniciará Excel, lo abrirá en el patrón deseado e iniciará las variables adicionales necesarias:

  Excel := CreateOleObject('Excel.Application');
  Excel.Workbooks.Open(FileName, True, True);
  TemplateSheet := Excel.Workbooks[1].Sheets[1];
  Excel.DisplayAlerts := False; // Чтобы подавить сообщение об ошибке при замене ненайденного значения в операции SetValue
  CurrentLine := 1;
  Progress := TA7xProgress.Create(Self);
  Application.ProcessMessages;

Se menciona el objeto TA7xProgress, que es un formulario simple con un par de etiquetas para mostrarle al usuario el progreso de construcción del informe que no cree que el programa cuelgue.

Una vez abierta la plantilla, el código de creación de informes llamará al método PasteBand cada vez que necesite agregar a la hoja en blanco original otra parte de la plantilla de informe.

La tecnología consiste en la adición de bandas que colocamos bandas justo antes de la plantilla, dejando así un patrón siempre al final del documento. Para ello, buscamos el nombre correcto para nuestra banda, comenzando a buscarnos a partir de la última banda insertada y más allá, y también definimos la duración y la banda encontrada. Es decir, el siguiente fragmento de código en las variables FirstBandLine y conserva LastBandLine al principio y al final de la banda:

  FirstBandLine := 0; LastBandLine := 0;
  i := CurrentLine;
  while ((LastBandLine = 0) and (i < CurrentLine + MaxBandLines)) do begin
    v := Variant(TemplateSheet.Cells[i, 1].Value);
    if (varType(v) = varOleStr) and (FirstBandLine = 0) then begin
      if v = BandName then begin // нашли начало бенда
        FirstBandLine := i;
      end;
    end;
    if (FirstBandLine <> 0) then begin
      if not ((varType(v) = varOleStr) and (v = BandName)) then LastBandLine := i - 1;
    end;
    inc(i);
  end;

Además, este patrón se encuentra kopipastim insertado inmediatamente después de la última banda de contacto, si ya lo ha sido:

  Range := TemplateSheet.Rows[IntToStr(FirstBandLine) + ':' + IntToStr(LastBandLine)];
  Range.Copy;
  Range := TemplateSheet.Rows[IntToStr(CurrentLine) + ':' + IntToStr(CurrentLine)];
  Range.Insert;

Bueno, cambie las variables indicando la posición de la última línea del informe y lo que ahora se copia de nuestra banda. Esto último es necesario para saber el rango en el que buscar el período deseado de nuestro nombre de variable para reemplazar sus valores:

  CurrentLine := CurrentLine + (LastBandLine - FirstBandLine) + 1;
  // вычисляем позицию куда был скопирован бэнд
  FirstBandLine := CurrentLine - (LastBandLine - FirstBandLine) - 1;
  LastBandLine := CurrentLine - 1;

El siguiente método que se utilizará para mostrar valores en una plantilla ya copiada: SetValue. El código de este método es muy sencillo, al igual que buscar un reemplazo, los valores en el rango dado por medio de Excel:

  Range := TemplateSheet.Rows[IntToStr(FirstBandLine) + ':' + IntToStr(LastBandLine)];
  Range.Replace(VarName, s);

El método SetValue debe ser llamado tantas veces como estemos en los valores correctos, agrupamos. Finalmente, después de que se retiren todas las bandas, el último método se llama – Show, que finalmente eliminó la plantilla, lo que desplaza el final del documento y Excel Trnsfer del estado invisible al visible.

Vale la pena mencionar que si decimos que interrumpa el informe de depuración para llamar a Excel.Visible: = true; entonces Excel quedará colgado en la memoria de los invisibles, y para el próximo informe se creará una nueva instancia de Excel.

¿Cuál es el uso de la herramienta de informes en Delphi-code?

Ahora lo más interesante: un ejemplo de este generador de informes:

Aquí está el procedimiento completo que se muestra arriba usando la salida de la plantilla en formato Excel dado el envío:

procedure TdrashodForm.Print(Template: string);
var i: integer;
  summa_: double;
  h : string;
begin
  Rep.OpenTemplate(Template);
  Rep.PasteBand('TITLE');
  Rep.SetValue('#ID_RASHOD#', ID_RASHOD);
  Rep.SetValue('#PB_NAME#', PbFrame.PbEdit.Text);
  Rep.SetValue('#D#', DateToStr(NaklDTP.Date));
  Rep.SetValue('#POSTNAME#', PostEdit.Text);
  i := 1; summa_ := 0;
  NaklQuery.First;
  while not NaklQuery.Eof do begin
      Rep.PasteBand('STR');
      Rep.SetValue('#N#', i);
      h := NaklQuery['KH_NAME'];
      if h<>'' then h := '['+h+']';
      Rep.SetValue('#NM_NAME#', NaklQuery['NM_NAME']+' '+h);
      Rep.SetValue('#QUANT#', NaklQuery['RSD_QUANT']);
      Rep.SetValue('#SUMMA#', coalesce(NaklQuery['RSD_OSUMMA'],0));
      Rep.SetValue('#NM_UNIT#', coalesce(NaklQuery['NM_UNIT'],''));
      Rep.SetValue('#ZK_NUMBER#', coalesce(NaklQuery['ZK_NUMBER'],''));
      Rep.SetValue('#TW_NAME#', coalesce(NaklQuery['TW_NAME'],''));
      summa_ := summa_ + coalesce(NaklQuery['RSD_OSUMMA'],0);
      inc(i);
    NaklQuery.Next;
  end;
  Rep.PasteBand('FOOT');
  Rep.SetValue('#SUMMA_#', summa_);
  Rep.Show;
end;

Como puede ver, la lógica de la formación de la placa de impresión es completamente transparente y no está cargada con los valores de salida del código técnico en la celda deseada de Microsoft Excel; todo esto se ocupa de nuestro componente del informe y, además, A diferencia de muchos de los informes, tenemos todo el poder de Delphi para calcular y obtener los valores que necesitamos en diferentes partes del procedimiento para construir el informe.

Y ahora lo más importante…

Donde puedo conseguir este maravilloso sistema y hasta gratis

El proyecto de inicio está en a7in.com

Deja un comentario

Tu dirección de correo electrónico no será publicada.