IPB
ЛогинПароль:

> ВНИМАНИЕ!

Прежде чем задать вопрос, смотрите FAQ.
Рекомендуем загрузить DRKB.

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

3 страниц V  1 2 3 >  
 Ответить  Открыть новую тему 
> Отчет Excel
сообщение
Сообщение #1


Ветеран Броуновского Движения
***

Группа: Пользователи
Сообщений: 281
Пол: Мужской
Реальное имя: Сергей

Репутация: -  0  +


Задача - разложить данные по предприятия в закладки книги файла эксель. Т.е. одна закладка одно предприятие. + имя закладки это имя предприятия из списка. Шапка одна и так же везде должна быть, количество предприятий может меняться. Для вывода отчет использую шаблон и компоненту EXLReport. В один список все прекрасно выходит, а вот как разбить на страницы с именами предприятий и данные разложить вопрос. Не уверен, что верно написал переход по списку предприятий еще...
Вот пример моего вывода:
Код
procedure TForm5.Button1Click(Sender: TObject);
var
  col: integer;
  st: string;
  year, MonthSelected: string;
  oth: string;
  sum_03, sum_04, sum_05, sum_1_04, sum_2_04, sum_1_05, sum_2_05: string;
  provodka: string;
  data: string;
  direct: string;
  IDSOURCE, PR_MEST: string;
  priznak: string;
  NO_FAM: string;
  cods: string;
  KOD:string;
  koll:integer;

  begin

// собираем данные

  year := Form5.Edit1.Text;
  MonthSelected := FloatToStr(Form5.ComboBox1.ItemIndex + 1);
  priznak := IntToStr(Form5.ComboBox3.ItemIndex + 1);

  oth := 'получе5ние отчетного месяца' + MonthSelected + '';
  Form5.ClientDataSet1.close;
  Form5.ClientDataSet1.DataRequest(oth);
  Form5.ClientDataSet1.open;
  oth := Form5.ClientDataSet1.fieldbyname('id_otchm').asstring;


  IDSOURCE := 'выбор источника загрузки '';
  Form5.ClientDataSet1.close;
  Form5.ClientDataSet1.DataRequest(IDSOURCE);
  Form5.ClientDataSet1.open;
  IDSOURCE := Form5.ClientDataSet1.fieldbyname('ID_SOURCE').asstring;
  PR_MEST := Form5.ClientDataSet1.FieldByName('Pr_MEST').AsString;
  NO_FAM := Form5.ClientDataSet1.FieldByName('NO_ONE_FAM').AsString;

    direct := 'reestor_bez_mesta.xls';

    //получаем список кодов организации
  begin

    cods := 'выборка кодов организации  ' +

    ' order by Kodorg asc ';

    Form5.ClientDataSet1.close;
    Form5.ClientDataSet1.DataRequest(cods);
    Form5.ClientDataSet1.open;
    koll:=Form5.ClientDataSet1.RecordCount;

    Kod := Form5.ClientDataSet1.FieldByName('KODORG').AsString;
  while
   Form5.ClientDataSet1.Eof
    do

        begin
      //по одной организации
    

      st := '  запрос данных о предприятии ';

      Form5.ClientDataSet2.close;
      Form5.ClientDataSet2.DataRequest(st);
      Form5.ClientDataSet2.open;

   {   col := Form5.ClientDataSet2.RecordCount;
      begin
        if col = 0 then
        begin
          ShowMessage('Данные отсуствуют')
        end
        else  }


            Form5.ClientDataSet1.Next;
        begin
           Form5.EXLReport1.TemplSheet:='Лист 3';
          exlReport1.Template := 'H:\808.COM\Andreev\Справочники\Forms\' + direct;
          if Assigned(Form5.EXLReport1) then Form5.EXLReport1.Show; // открытие окошка эксель
        end;
      end;
    end;
  end;
//end;



Сообщение отредактировано: Atreides -


--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Сторонние компоненты не использую, идея - такая:
procedure TForm1.Button2Click(Sender: TObject);

var
workBooks, activeBook, curr, Range : Variant;
CellStart, CellFinish : Variant;
sPlace : String;
Ls : TStringList;
i, iRec : Integer;
Data : Variant;
begin
XLApp := CreateOleObject('Excel.Application');
XLApp.Visible := True;

workBooks := XLApp.WorkBooks;
activeBook := workBooks.Add;

try
Ls := TStringList.Create;

ClientDataSet1.First;
while not ClientDataSet1.Eof do
begin
sPlace := ClientDataSet1.FieldByName('Pr_MEST').AsString;
if Ls.IndexOf(sPlace) = -1 then
begin
Ls.Add(sPlace);
end;
ClientDataSet1.Next;
end;

for i := 0 to Pred(Ls.Count) do
begin
ClientDataSet1.Filtered := False;
ClientDataSet1.Filter := 'Pr_MEST = ' + QuotedStr(Ls.Strings[i]);
ClientDataSet1.Filtered := True;

Data := VarArrayCreate([1, ClientDataSet1.RecordCount, 1, 3], varVariant);

ClientDataSet1.First;
iRec := 0;
while not ClientDataSet1.Eof do
begin

Data[iRec + 1, 1] := ClientDataSet1.FieldByName('ID_SOURCE').AsString;
Data[iRec + 1, 2] := ClientDataSet1.FieldByName('Pr_MEST').AsString;
Data[iRec + 1, 3] := ClientDataSet1.FieldByName('NO_ONE_FAM').AsString;
Inc(iRec);

ClientDataSet1.Next;
end;

Curr := ActiveBook.Sheets.Add;
Curr.Name := Ls.Strings[i];
CellStart := Curr.Cells[1, 1];
CellFinish := Curr.Cells[iRec, 3];
Range := Curr.Range[CellStart, CellFinish];
Range.Value := Data;

VarClear(Data);
end;

finally
Ls.Free;
end;
end;
Нужные поля допишешь, если понадобится - поменяешь диапазон на листе, куда будет копироваться информация. Датасет вот такой:
Прикрепленное изображение
, все корректно разбивается на 5 листов.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Ветеран Броуновского Движения
***

Группа: Пользователи
Сообщений: 281
Пол: Мужской
Реальное имя: Сергей

Репутация: -  0  +


XLApp - это ExcelApplication или какой модуль надо подключить? Закладки как имя предприятия принимаются, и в каком месте запрос открывать? Есть возможность использовать шапку и после эту шапку копировать на другие листы? вылетаю по ошибке [DCC Error] Print.pas(360): E2010 Incompatible types: 'TExcelApplication' and 'IDispatch' - несовместимые типы на строке XLApp := CreateOleObject('Excel.Application');


Сообщение отредактировано: Atreides -


--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Цитата
XLApp - это ExcelApplication или какой модуль надо подключить?
Нет. Это

Uses ..., ComObj;

var XLApp : Variant;

Цитата
Закладки как имя предприятия принимаются, и в каком месте запрос открывать?
Еще раз можно этот же вопрос задать, только в более понятной форме? Какой запрос? Запрос - в строке
ClientDataSet1.Filter := 'Pr_MEST = ' + QuotedStr(Ls.Strings[i]);
Если тебе нужно - задай там критерием фильтрации не только поле Pr_MEST, но и любую другую комбинацию условий по правилам SQL.

Цитата
Есть возможность использовать шапку и после эту шапку копировать на другие листы?
Есть возможность новый лист добавлять из шаблона. Прямо с шапкой, в том формате, который тебе нужен:

const
TemplateSheet = 'F:\Programs\Delphi\XLL\Sheet1.XLT';
// В этом шаблоне только один лист, с шапкой которая тебе нужна

var
XLApp : Variant;

procedure TForm1.Button2Click(Sender: TObject);

var
workBooks, activeBook, curr, Range : Variant;
CellStart, CellFinish : Variant;
sPlace : String;
Ls : TStringList;
i, iRec : Integer;
Data : Variant;
begin
XLApp := CreateOleObject('Excel.Application');
XLApp.Visible := True;
XLApp.SheetsInNewWorkbook := 1; // Добавим не 3 (по умолчанию), а 1 лист

workBooks := XLApp.WorkBooks;
ActiveBook := workBooks.Add;
Curr := ActiveBook.Sheets[1]; // Запомним добавленный лист, ниже поймешь зачем

try
Ls := TStringList.Create;

// Ну, дальше все ПОЧТИ без изменений
ClientDataSet1.First;
while not ClientDataSet1.Eof do
begin
sPlace := ClientDataSet1.FieldByName('Pr_MEST').AsString;
if Ls.IndexOf(sPlace) = -1 then
begin
Ls.Add(sPlace);
end;
ClientDataSet1.Next;
end;

for i := 0 to Pred(Ls.Count) do
begin
ClientDataSet1.Filtered := False;
ClientDataSet1.Filter := 'Pr_MEST = ' + QuotedStr(Ls.Strings[i]);
ClientDataSet1.Filtered := True;

Data := VarArrayCreate([1, ClientDataSet1.RecordCount, 1, 3], varVariant);

ClientDataSet1.First;
iRec := 0;
while not ClientDataSet1.Eof do
begin

Data[iRec + 1, 1] := ClientDataSet1.FieldByName('ID_SOURCE').AsString;
Data[iRec + 1, 2] := ClientDataSet1.FieldByName('Pr_MEST').AsString;
Data[iRec + 1, 3] := ClientDataSet1.FieldByName('NO_ONE_FAM').AsString;
Inc(iRec);

ClientDataSet1.Next;
end;

// А вот и изменения: добавляем новый личт из шаблона ПОСЛЕ того, что был текущим
Curr := ActiveBook.Sheets.Add (Type := TemplateSheet, After := Curr);
Curr.Name := Ls.Strings[i];
CellStart := Curr.Cells[2, 1]; // Ну, и корректируем позицию вставки
(*
Я для пробы создал шаблон только с одной строкой, поэтому позицию начала вставки перенес
на 1 строку ниже. Если у тебя в шаблоне 20 строк шапки - то соответственно, сделаешь

CellStart := Curr.Cells[21, 1];

Ну, и сдвинуть столбец тоже можно при желании...
*)
CellFinish := Curr.Cells[iRec + 1, 3];
// Здесь тоже не забывай вносить изменения, одновременно с предыдущей строкой

Range := Curr.Range[CellStart, CellFinish];
Range.Value := Data;

VarClear(Data);
end;

finally
Ls.Free;
end;
ActiveBook.Sheets[1].Delete; // Помнишь первый добавленный лист? Он не нужен...
end;
В комментариях описаны все изменения, которые надо внести... Код тестировался на Дельфи 2009 под Excel XP, но ничего страшного и при более новых версиях Офиса произойти не должно, ничем недокументированным я не пользуюсь, все описано в MSDN -> Microsoft.Office.Interop.Excel Namespace (ссылки пока добавлять не могу, так что ищи сам)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Ветеран Броуновского Движения
***

Группа: Пользователи
Сообщений: 281
Пол: Мужской
Реальное имя: Сергей

Репутация: -  0  +


меня интересует вопрос в каком месте послать запрос и вставлять конструкцию следующего типа или она вообще не нужна?
Код
   st := '  select  ..... ';
      Form5.ClientDataSet1.close;
      Form5.ClientDataSet1.DataRequest(st);
      Form5.ClientDataSet1.open;


Запросом я выдаю весь список данных сгруппированные по предприятиям. Вот мне в закладку надо название организации вкрячить. Т.е. есть организация и на листе все записи с ней, на другом листе все записи по второй и так далее...

Сообщение отредактировано: Atreides -


--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Цитата
меня интересует вопрос в каком месте послать запрос и вставлять конструкцию следующего типа или она вообще не нужна?
Такой запрос не нужен. Его роль на себя берет
      ClientDataSet1.Filtered := False;
ClientDataSet1.Filter := 'Pr_MEST = ' + QuotedStr(Ls.Strings[i]);
ClientDataSet1.Filtered := True;
Заметил? Сначала проходим по всей базе и заносим все разные данные из полей "Pr_MEST" в StringList... А потом просто фильтруем данные из набора: каждый раз подставляя новое значение из List-а в фильтр. Я структуры твоего набора данных не знаю. Предположил, что в поле "Pr_MEST" хранится название организации. Если так - то прекрасно. Не так - замени название поля на нужное в двух местах: в строке 33 и строке 44 исходника из 4-го поста. В 44-ой строке набор будет фильтроваться по нужному критерию, и данные для одной организации запишутся на один лист отчета, для другой - на другой лист. Для тех данных, что я показал - получился вот такой результат:
Прикрепленное изображение

Тебе что, присоединить полный исходник? Сам заполнить ClientDataSet так, как на скриншоте из 2-го поста, и проверить, что происходит при запуске программы - не можешь?

Цитата
Вот мне в закладку надо название организации вкрячить.

Цитата
      Curr := ActiveBook.Sheets.Add (Type := TemplateSheet, After := Curr);
Curr.Name := Ls.Strings[i]; // <--- Эту строчку видел? Что она делает?


Сообщение отредактировано: IUnknown -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Ветеран Броуновского Движения
***

Группа: Пользователи
Сообщений: 281
Пол: Мужской
Реальное имя: Сергей

Репутация: -  0  +


наверное, лучше исходник прикрепить как целостны пример, его по-кусочкам разбирать буду.


--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Ну вот:
Прикрепленный файл  XLL.zip ( 6.41 килобайт ) Кол-во скачиваний: 575


Поменяешь там путь к XLT-файлу на правильный...
Сначала жмешь кнопку "FillDSet", датасет заполнится (я не стал делать соединения с БД, заполнил все в рантайме. Разницы в обработке данных - никакой, а проблем меньше), а потом - "To XL"
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Ветеран Броуновского Движения
***

Группа: Пользователи
Сообщений: 281
Пол: Мужской
Реальное имя: Сергей

Репутация: -  0  +


Почему то в конце столбцов образуются символы (#Н/Д). Чет более трех полей не получается вывести, а мне надо 14

Сообщение отредактировано: Atreides -


--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Цитата
Почему то в конце столбцов образуются символы (#Н/Д).
Значит, размер области
Цитата
Range := Curr.Range[CellStart, CellFinish];
вычислил неправильно. Такое бывает когда ты, скажем, заполняешь массив на 3 столбца и 20 строк, а указываешь Экселю, что перенести его надо в область из трех столбцов и 21 строки. Естественно, Эксель недополучает данные, и все, что недополучил - считает #Н/Д. Где-то у тебя лишняя единица затесалась.

Цитата
Чет более трех полей не получается вывести, а мне надо 14
Хоть 114. Инициализируй Data нужного размера (столбцы - это 3 и 4 индексы)
Data := VarArrayCreate([1, ClientDataSet1.RecordCount, 1, 14], varVariant); // Будет тебе место под 14 столбцов
, и заполняй значениями. А потом переноси, только начальную/конечную ячейки правильно посчитай...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Ветеран Броуновского Движения
***

Группа: Пользователи
Сообщений: 281
Пол: Мужской
Реальное имя: Сергей

Репутация: -  0  +


Код
Data := VarArrayCreate([1, ClientDataSet1.RecordCount, 1, 14], varVariant); // Будет тебе место под 14 столбцов
Значит я верно разобрался. Косякнул в другом месте ((( А еще такой вопрос, при выполнении происходит открытие экселя и его заполнение, а можно заполнить, а поле отобразить?


--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Можно. Перенеси
  ActiveBook.Sheets[1].Delete; // Помнишь первый добавленный лист? Он не нужен...
XLApp.Visible := True; // <--- Вот сюда строку из начала процедуры


Где будет Visible присваиваться True - там и будет появляться окно Excel. Но тогда тебе надо будет добавить какой-нибудь ProgressBar (скажем, по количеству обработанных предприятий), потому что если отчет сложный (много данных), то между нажатием на кнопку и получением результата пройдет какое-то время, пользователь может быть в недоумении.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Ветеран Броуновского Движения
***

Группа: Пользователи
Сообщений: 281
Пол: Мужской
Реальное имя: Сергей

Репутация: -  0  +


Еще вопрос такой возник – можно добавить вставку даты в шапку, в заранее заданную ячейку и итог общий по сумму в конце дописать?


--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Цитата
можно добавить вставку даты в шапку, в заранее заданную ячейку и итог общий по сумму в конце дописать?
Если ячейка известна - то разумеется, можно:

ToCell := 'A3'; // Var ToCell : String;
ActiveBook.Sheets[1].Range[ToCell] := Твои_Данные; // Можешь записать и на другой лист.


Цитата
и итог общий по сумму в конце дописать?
Добавить формулу что-ли в ячейку? И это можно:
ToCell := 'A21';
ActiveBook.Sheets[1].Range[ToCell].Formula := '=Sum(A1:A20)';
- Подставишь свой интервал в формулу, и нужный номер ячейки...

Сообщение отредактировано: IUnknown -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #15


Ветеран Броуновского Движения
***

Группа: Пользователи
Сообщений: 281
Пол: Мужской
Реальное имя: Сергей

Репутация: -  0  +


Из константы можно путь в переменную вывести?


--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #16


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Из константы в переменную - можно, обратно - нельзя.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #17


Ветеран Броуновского Движения
***

Группа: Пользователи
Сообщений: 281
Пол: Мужской
Реальное имя: Сергей

Репутация: -  0  +


Цитата(IUnknown @ 3.05.2011 15:08) *

Из константы в переменную - можно, обратно - нельзя.


Код

var
TemplateSheet:string;
begin
TemplateSheet := 'H:\M6301.XLs';
end;


Чет не прокатывает мне. Чет не так делаю (((


--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #18


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Что значит "не прокатывает"? Все прекрасно скомпилировалось и отработало.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #19


Ветеран Броуновского Движения
***

Группа: Пользователи
Сообщений: 281
Пол: Мужской
Реальное имя: Сергей

Репутация: -  0  +


Цитата(IUnknown @ 3.05.2011 15:51) *

Что значит "не прокатывает"? Все прекрасно скомпилировалось и отработало.

[DCC Error] Print.pas(452): E2029 ':=' expected but '=' found - посылает по этому в этой строке((
Код

    begin
      TemplateSheet  = 'H:\808.COM\Andreev\Справочники\Формы\M6301.XLs';
    end;



--------------------
Отрадно спать, отрадней камнем быть, О, этот век, преступный и постыдный, Не жить, не чувствовать - удел завидный. Прошу, молчи, не смей меня будить!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #20


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Сторонник
Free Pascal: Разработчик

Репутация: -  627  +


Ну, а какого ты сверху написал ":=", а здесь, ниже, уже пишешь "="? Требуется-то именно присваивание, переменная же...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

3 страниц V  1 2 3 >
 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 2.05.2024 20:03
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name