¿Por qué necesitamos un sistema de informes?
En 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:

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

Вопрос снимается, в procedure TA7Rep.PasteBand(BandName: string);
вот эти строки были закомменктированны
{ // delete band name from result lines
for i := CurrentLine to CurrentLine + (LastBandLine – FirstBandLine) do begin
TemplateSheet.Cells[i, 1].Value := »;
end;
}
Эти комментарии, были убраны и все заработало
Добрый День!
В Excel 2016 не удаляются Наименование бандов, как сделать, чтобы они удалялись?
Можно ли с помощью Вашего компонента передать в ексель цвет ячейки?
Можно! Если добавить туда процедуру установки цвета ячейки:
procedure TA7Rep.SetColor(VarName: string; Color: Variant); var x, y : Integer; begin ExcelFind(VarName, x, y, xlValues); if Color=null then begin TemplateSheet.Cells[y, x].Interior.Pattern := -4142; //xlNone; end else begin TemplateSheet.Cells[y, x].Interior.Pattern := 1; //xlSolid; TemplateSheet.Cells[y, x].Interior.PatternColorIndex := -4105; // xlAutomatic; TemplateSheet.Cells[y, x].Interior.Color := Color; end; end;Цвет 255 это красный. Все это можно подсмотреть если перейти в режим записи макроса в Excel и выполнив интересующие вас действия посмотреть на код.
I have noticed you don’t monetize your page, don’t waste your traffic, you can earn extra bucks
every month because you’ve got hi quality content.
If you want to know how to make extra bucks, search for: Ercannou’s essential adsense alternative
Немного дописал исходный код:
Процедура смены активного листа (иногда нужно начать заполнение не с первого листа, а потом вернуться к первому).
procedure TA7Rep.ActivateWorkSheet(Name: string); begin if Name='' then TemplateSheet := Excel.Workbooks[1].Sheets[1] else TemplateSheet := Excel.Workbooks[1].Sheets[Name]; CurrentLine := 1; MaxBandColumns := TemplateSheet.UsedRange.Columns.Count; if Assigned(Progress) then Progress.L3.Caption := 'Sheet: ' + Name; end;Процедура для переноса таблицы в любую часть отчета, например, справа от других таблиц. Таблица с фиксированными размерами, строки в нее не вставляются. Таблица шаблона выделяется в именованный диапазон, например totals, а в начальной ячейке, куда вставлять таблицу, пишется идентификатор, например, :totals_to. Эту таблицу в шаблоне не помечаем именами бэндов.
Перед переносом таблицы необходимо заполнить ее значения с помощью этой процедуры (бэндов-то нет).
procedure TA7Rep.SetValueNamed(VarName: string; Value: Variant); var Range: Variant; begin Range := TemplateSheet.Cells.Find(VarName); if Value = null then Range.Replace(VarName, '') else Range.Replace(VarName, VarToStr(Value)); end;Не могу найти Ваш компонент на сайте, по сслыке на скачку – not found
Извиняюсь за битую ссылку. Перезалил более свежую версию.
можно ли вставить рисунок с помощью этого компонента?
a7: К сожалению нет. Но есть возможность вставлять строки с рисунком, если они в таком виде будут в шаблоне. Можно даже заготовить несколько альтернативных бендов, если нужны несколько заранее известных вариантов рисунка, но вставлять произвольный рисунок на этапе генерации отчета все-же нельзя.
Идея очень хорошая, что-то похожее в 1С.
Вот бы хотя бы идею расшифровки данных в ячеке.
Когда данные уже отданы в эксель то уже наврядли это получиться…
a7: Я думаю что теоретически это все-же возможно, например вмонтировав в Excel код VBScript, но это действительно очень нетривиальный и тернистый путь – я таким заниматься пожалуй пока не буду 🙂
Как я понял для Delphi RAD XE он не подойдет ?
a7:Этот отчетный компонент не содержит ничего сложного в себе и его можно без проблем скомпилировать под нужную версию Delphi. Но я все же уже добавил сборку и под Delphi XE2
Отличная вещь!!!!!!!!!!!!!!!!
Вопрос – как добиться того, что бы если наименование товара длинное, то строка изменяла высоту под размер товара, но не для каждого товара одна высота!!!!!
Тоесть один товар – длинный – высоту строки изменили в зависимости от длины второй товар не длинный высоту не меняем т д
Огромное спасибо!!! а компонент то что надо!!!!!!!!!!!!!!
a7:Легко! Поскольку шаблон отчета это обычный эксель то нужно в ячейке шаблона просто установить параметр “переносить по словам” ну и все остальные если надо параметры крутить. Все точно также как делается в экселе при обычной работе. Сам генератор отчета в доработках не нуждается